chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
const MEMORY_ITEMS = [
|
||||
{
|
||||
id: "mem_001",
|
||||
type: "user",
|
||||
content: "User prefers dark mode",
|
||||
score: 0.95,
|
||||
createdAt: "2026-05-10T10:00:00Z",
|
||||
},
|
||||
{
|
||||
id: "mem_002",
|
||||
type: "project",
|
||||
content: "Project uses Next.js 16",
|
||||
score: 0.88,
|
||||
createdAt: "2026-05-09T12:00:00Z",
|
||||
},
|
||||
];
|
||||
|
||||
function makeResp(data: unknown, status = 200) {
|
||||
const obj = {
|
||||
ok: status < 400,
|
||||
status,
|
||||
exitCode: status < 400 ? 0 : 1,
|
||||
json: () => Promise.resolve(data),
|
||||
text: () => Promise.resolve(JSON.stringify(data)),
|
||||
headers: new Headers(),
|
||||
};
|
||||
obj.json = obj.json.bind(obj);
|
||||
obj.text = obj.text.bind(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
async function captureStdout(fn: () => Promise<void>): Promise<string> {
|
||||
const chunks: string[] = [];
|
||||
const orig = process.stdout.write.bind(process.stdout);
|
||||
process.stdout.write = (c: string | Uint8Array) => {
|
||||
if (typeof c === "string") chunks.push(c);
|
||||
return true;
|
||||
};
|
||||
try {
|
||||
await fn();
|
||||
} finally {
|
||||
process.stdout.write = orig;
|
||||
}
|
||||
return chunks.join("");
|
||||
}
|
||||
|
||||
function makeCmd(output = "json") {
|
||||
return { optsWithGlobals: () => ({ output, quiet: output !== "table" }) };
|
||||
}
|
||||
|
||||
test("runMemorySearch retorna items como array JSON", async () => {
|
||||
const origFetch = globalThis.fetch;
|
||||
globalThis.fetch = (() => Promise.resolve(makeResp({ items: MEMORY_ITEMS }))) as any;
|
||||
|
||||
const { runMemorySearch } = await import("../../bin/cli/commands/memory.mjs");
|
||||
const out = await captureStdout(() =>
|
||||
runMemorySearch("dark mode", { limit: 20 }, makeCmd() as any)
|
||||
);
|
||||
|
||||
globalThis.fetch = origFetch;
|
||||
const parsed = JSON.parse(out);
|
||||
assert.ok(Array.isArray(parsed));
|
||||
assert.equal(parsed[0].id, "mem_001");
|
||||
assert.equal(parsed[0].type, "user");
|
||||
});
|
||||
|
||||
test("runMemorySearch envia q e type na query", async () => {
|
||||
let capturedUrl = "";
|
||||
const origFetch = globalThis.fetch;
|
||||
globalThis.fetch = ((url: string) => {
|
||||
capturedUrl = url;
|
||||
return Promise.resolve(makeResp({ items: MEMORY_ITEMS }));
|
||||
}) as any;
|
||||
|
||||
const { runMemorySearch } = await import("../../bin/cli/commands/memory.mjs");
|
||||
await captureStdout(() =>
|
||||
runMemorySearch("react hooks", { limit: 10, type: "project" }, makeCmd() as any)
|
||||
);
|
||||
|
||||
globalThis.fetch = origFetch;
|
||||
assert.ok(capturedUrl.includes("q=react") && capturedUrl.includes("hooks"));
|
||||
// Plan 21 / D17: legacy 'project' is remapped to canonical 'factual' by
|
||||
// applyLegacyTypeMap in the CLI before reaching the backend.
|
||||
assert.ok(capturedUrl.includes("type=factual"));
|
||||
assert.ok(!capturedUrl.includes("type=project"));
|
||||
assert.ok(capturedUrl.includes("limit=10"));
|
||||
});
|
||||
|
||||
test("runMemoryAdd envia POST com content e type", async () => {
|
||||
// Plan 21 / D17: legacy 'user' type is mapped to canonical 'factual'.
|
||||
let capturedUrl = "";
|
||||
let capturedInit: any = null;
|
||||
const origFetch = globalThis.fetch;
|
||||
globalThis.fetch = ((url: string, init: any) => {
|
||||
capturedUrl = url;
|
||||
capturedInit = init;
|
||||
return Promise.resolve(
|
||||
makeResp({ id: "mem_new", type: "factual", content: "test content" })
|
||||
);
|
||||
}) as any;
|
||||
|
||||
const { runMemoryAdd } = await import("../../bin/cli/commands/memory.mjs");
|
||||
await captureStdout(() =>
|
||||
runMemoryAdd({ content: "test content", type: "user" }, makeCmd() as any)
|
||||
);
|
||||
|
||||
globalThis.fetch = origFetch;
|
||||
assert.ok(capturedUrl.includes("/api/memory"));
|
||||
assert.equal(capturedInit?.method, "POST");
|
||||
const body = JSON.parse(capturedInit?.body);
|
||||
assert.equal(body.content, "test content");
|
||||
// Legacy 'user' is remapped to canonical 'factual' by CLI (plan 21 / D17).
|
||||
assert.equal(body.type, "factual");
|
||||
});
|
||||
|
||||
test("runMemoryList retorna items sem q", async () => {
|
||||
let capturedUrl = "";
|
||||
const origFetch = globalThis.fetch;
|
||||
globalThis.fetch = ((url: string) => {
|
||||
capturedUrl = url;
|
||||
return Promise.resolve(makeResp({ items: MEMORY_ITEMS }));
|
||||
}) as any;
|
||||
|
||||
const { runMemoryList } = await import("../../bin/cli/commands/memory.mjs");
|
||||
const out = await captureStdout(() => runMemoryList({ limit: 100 }, makeCmd() as any));
|
||||
|
||||
globalThis.fetch = origFetch;
|
||||
assert.ok(!capturedUrl.includes("q="));
|
||||
const parsed = JSON.parse(out);
|
||||
assert.ok(Array.isArray(parsed));
|
||||
assert.equal(parsed.length, 2);
|
||||
});
|
||||
|
||||
test("runMemoryGet busca /api/memory/:id", async () => {
|
||||
let capturedUrl = "";
|
||||
const origFetch = globalThis.fetch;
|
||||
globalThis.fetch = ((url: string) => {
|
||||
capturedUrl = url;
|
||||
return Promise.resolve(makeResp(MEMORY_ITEMS[0]));
|
||||
}) as any;
|
||||
|
||||
const { runMemoryGet } = await import("../../bin/cli/commands/memory.mjs");
|
||||
const out = await captureStdout(() => runMemoryGet("mem_001", {}, makeCmd() as any));
|
||||
|
||||
globalThis.fetch = origFetch;
|
||||
assert.ok(capturedUrl.includes("/api/memory/mem_001"));
|
||||
const parsed = JSON.parse(out);
|
||||
assert.equal(parsed.id, "mem_001");
|
||||
});
|
||||
|
||||
test("runMemoryHealth retorna status do subsistema", async () => {
|
||||
const origFetch = globalThis.fetch;
|
||||
globalThis.fetch = (() =>
|
||||
Promise.resolve(makeResp({ status: "healthy", fts5: true, qdrant: true }))) as any;
|
||||
|
||||
const { runMemoryHealth } = await import("../../bin/cli/commands/memory.mjs");
|
||||
const out = await captureStdout(() => runMemoryHealth({}, makeCmd() as any));
|
||||
|
||||
globalThis.fetch = origFetch;
|
||||
const parsed = JSON.parse(out);
|
||||
assert.equal(parsed.status, "healthy");
|
||||
});
|
||||
|
||||
test("runMemoryClear --yes envia DELETE com filtro de type", async () => {
|
||||
let capturedUrl = "";
|
||||
let capturedInit: any = null;
|
||||
const origFetch = globalThis.fetch;
|
||||
globalThis.fetch = ((url: string, init: any) => {
|
||||
capturedUrl = url;
|
||||
capturedInit = init;
|
||||
return Promise.resolve(makeResp({ deleted: 5 }));
|
||||
}) as any;
|
||||
|
||||
const { runMemoryClear } = await import("../../bin/cli/commands/memory.mjs");
|
||||
await captureStdout(() => runMemoryClear({ yes: true, type: "project" }, makeCmd() as any));
|
||||
|
||||
globalThis.fetch = origFetch;
|
||||
assert.ok(capturedUrl.includes("/api/memory"));
|
||||
assert.equal(capturedInit?.method, "DELETE");
|
||||
// Plan 21 / D17: legacy 'project' is remapped to canonical 'factual' by
|
||||
// applyLegacyTypeMap in the CLI before reaching the backend.
|
||||
assert.ok(capturedUrl.includes("type=factual"));
|
||||
assert.ok(!capturedUrl.includes("type=project"));
|
||||
});
|
||||
Reference in New Issue
Block a user