76 lines
2.7 KiB
JavaScript
76 lines
2.7 KiB
JavaScript
// Standalone test for the pure project/recents logic.
|
|
// Builds src/main/project.ts with esbuild (no Electron needed) and asserts behavior.
|
|
// Run with: node tests/run-project-test.mjs
|
|
import fs from "fs";
|
|
import os from "os";
|
|
import path from "path";
|
|
import { bundleForTest } from "./helpers/bundle.mjs";
|
|
|
|
const { mod, cleanupBundle } = await bundleForTest({
|
|
name: "folio-project",
|
|
entryPoints: ["src/main/project.ts"],
|
|
});
|
|
const {
|
|
APP_ID,
|
|
META_FILE,
|
|
CHAPTERS_DIR,
|
|
createBook,
|
|
loadBook,
|
|
saveMeta,
|
|
hasBook,
|
|
listRecents,
|
|
addRecent,
|
|
makeChapterId,
|
|
chapterFileName,
|
|
} = mod;
|
|
|
|
let failures = 0;
|
|
function ok(cond, msg) {
|
|
if (cond) console.log(" ok -", msg);
|
|
else { failures++; console.error("FAIL -", msg); }
|
|
}
|
|
|
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "folio-test-"));
|
|
|
|
const meta = createBook(dir, "My Novel");
|
|
ok(meta.app === APP_ID, "book app id is folio");
|
|
ok(meta.title === "My Novel", "book title set");
|
|
ok(meta.chapterOrder.length === 0, "new book has empty chapter order");
|
|
ok(fs.existsSync(path.join(dir, CHAPTERS_DIR)), "chapters/ dir created");
|
|
ok(fs.existsSync(path.join(dir, META_FILE)), "folio.json created");
|
|
|
|
const loaded = loadBook(dir);
|
|
ok(loaded.title === "My Novel", "load returns title");
|
|
ok(hasBook(dir) === true, "hasBook true for created book");
|
|
ok(hasBook("/tmp") === false, "hasBook false for non-book dir");
|
|
|
|
let threw = false;
|
|
try { loadBook("/tmp"); } catch { threw = true; }
|
|
ok(threw, "loadBook throws on non-book");
|
|
|
|
const m = loadBook(dir);
|
|
m.chapterOrder.push("x");
|
|
m.chapters["x"] = { id: "x", title: "Intro", file: "chapters/x.md" };
|
|
saveMeta(dir, m);
|
|
const m2 = loadBook(dir);
|
|
ok(m2.chapterOrder[0] === "x", "chapter order persisted");
|
|
ok(m2.chapters["x"].title === "Intro", "chapter entry persisted");
|
|
|
|
const rf = path.join(dir, "recents.json");
|
|
const r1 = addRecent(rf, { path: dir, title: "My Novel", lastOpened: "2026-01-01T00:00:00Z" });
|
|
ok(r1.length === 1, "first recent added");
|
|
ok(listRecents(rf).length === 1, "recent read back");
|
|
const r2 = addRecent(rf, { path: "/other", title: "Other", lastOpened: "2026-02-02T00:00:00Z" });
|
|
ok(r2.length === 2 && r2[0].path === "/other", "second recent added to top");
|
|
const r3 = addRecent(rf, { path: dir, title: "My Novel", lastOpened: "2026-03-03T00:00:00Z" });
|
|
ok(r3.length === 2 && r3[0].path === dir, "duplicate path deduped + moved to top");
|
|
|
|
const id = makeChapterId("Chapter One");
|
|
ok(id.startsWith("chapter-one-"), "chapter id slugified: " + id);
|
|
ok(chapterFileName(id) === `${id}.md`, "filename is <id>.md");
|
|
|
|
cleanupBundle();
|
|
fs.rmSync(dir, { recursive: true, force: true });
|
|
|
|
console.log("\nProject tests: " + (failures === 0 ? "ALL PASSED" : failures + " FAILED"));
|
|
process.exit(failures === 0 ? 0 : 1);
|