test/research-pages.test.js
Rama main · réplica de lectura del repositorio original.
import { test } from "node:test";
import assert from "node:assert/strict";
import { mkdtemp, mkdir, writeFile, readFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import path from "node:path";
const scratch = await mkdtemp(path.join(tmpdir(), "forge-pages-"));
process.env.FORGE_DECKS_DIR = scratch;
process.env.FORGE_CONFIG_DIR = process.env.FORGE_CONFIG_DIR ?? path.join(scratch, "config");
const { writeResearch } = await import("../src/ai/pipeline.js");
const { readResearchPages } = await import("../src/ai/research.js");
/**
* The per-source page store.
*
* `notes.md` is the merged text the writer draws from, but the merge forgets
* which source each passage came from — so a references slide cannot say which
* slide drew on which source. `research/pages.json` keeps the per-page texts
* beside the merge; `notes.md` itself is byte-identical either way.
*/
async function dir(name) {
const d = path.join(scratch, name);
await mkdir(d, { recursive: true });
return d;
}
test("writeResearch stores per-page texts beside the merged notes", async () => {
const d = await dir("deck-a");
await writeResearch(d, {
text: "## Alpha\n\n180 GW by 2030.",
sources: [{ url: "https://a.example/x", title: "Alpha", words: 5 }],
pages: [{ url: "https://a.example/x", title: "Alpha", words: 5, text: "180 GW by 2030." }],
});
assert.equal(await readFile(path.join(d, "research", "notes.md"), "utf8"), "## Alpha\n\n180 GW by 2030.");
const pages = await readResearchPages(d);
assert.equal(pages.length, 1);
assert.equal(pages[0].url, "https://a.example/x");
assert.equal(pages[0].text, "180 GW by 2030.");
});
test("writeResearch without pages writes no pages.json and reads back null", async () => {
const d = await dir("deck-b");
await writeResearch(d, { text: "nothing much", sources: [] });
assert.equal(await readResearchPages(d), null);
});
test("empty-text pages are dropped and upload pseudo-pages survive", async () => {
const d = await dir("deck-c");
await writeResearch(d, {
text: "hello",
sources: [],
pages: [
{ url: null, title: "brief.pdf", words: 1, kind: "user-provided", text: "hello" },
{ url: "https://b.example/y", title: "Blank", words: 0, text: " " },
],
});
const pages = await readResearchPages(d);
assert.equal(pages.length, 1);
assert.equal(pages[0].kind, "user-provided");
assert.equal(pages[0].url, null);
});
test("readResearchPages is null-safe on corrupt or missing files", async () => {
const d = await dir("deck-d");
await mkdir(path.join(d, "research"), { recursive: true });
await writeFile(path.join(d, "research", "pages.json"), "not json", "utf8");
assert.equal(await readResearchPages(d), null);
assert.equal(await readResearchPages(path.join(scratch, "no-such-deck")), null);
});