import assert from "node:assert/strict"; import { describe, it } from "node:test"; import { scanCards, writeSchedule } from "../shared/cards.ts"; import { formatSrComment, isDue, parseSrComment, review } from "../shared/srs.ts"; describe("SM-2", () => { it("walks 1, 6, then interval × ease on good; resets on again", () => { const a = review(null, "good", "2026-09-14"); assert.deepEqual(a, { due: "2026-09-15", interval: 1, ease: 2500 }); const b = review(a, "good", "2026-09-15"); assert.equal(b.interval, 6); const c = review(b, "good", "2026-09-21"); assert.equal(c.interval, 15); const d = review(c, "again", "2026-10-06"); assert.deepEqual(d, { due: "2026-10-07", interval: 1, ease: 2300 }); assert.equal(review(c, "easy", "2026-10-06").ease, 2650); assert.ok(review({ due: "x", interval: 10, ease: 1300 }, "hard", "2026-10-06").ease >= 1300); }); it("round-trips the plugin's comment and knows what is due", () => { const s = parseSrComment("")!; assert.deepEqual(s, { due: "2026-09-27", interval: 4, ease: 250 }); assert.equal(formatSrComment(s), ""); assert.equal(isDue(s, "2026-09-27"), true); assert.equal(isDue(s, "2026-09-26"), false); assert.equal(isDue(null, "2026-01-01"), true); }); }); const NOTE = `--- title: x --- # Cards What is the rule of three? ? Never keep fewer than three copies. Capital of Egypt::Cairo The ==mitochondria== is the powerhouse of the ==cell==. > [!quote] Ibn Khaldun, p. 12 > History is the record of human society. > It has many aspects. - [ ] not a card::really `; describe("cards in a note", () => { it("finds the block Q/A, the inline Q/A, the cloze paragraph and the quote", () => { const cards = scanCards(NOTE); assert.deepEqual(cards.map((c) => [c.kind, c.line, c.end]), [["qa", 6, 8], ["qa", 11, 11], ["cloze", 13, 13], ["quote", 15, 17]]); assert.equal(cards[0].front, "What is the rule of three?"); assert.equal(cards[0].schedule?.interval, 6); assert.equal(cards[1].back, "Cairo"); assert.equal(cards[2].front, "The **[…]** is the powerhouse of the **[…]**."); assert.equal(cards[2].back, "mitochondria · cell"); assert.ok(cards[3].front.startsWith("**Ibn Khaldun, p. 12**")); assert.equal(cards[3].back, "History is the record of human society.\nIt has many aspects."); assert.equal(cards[3].schedule, null); }); it("writes a schedule after a block, on an inline line, and replaces one already there", () => { const s = { due: "2026-10-01", interval: 3, ease: 2500 }; const next = writeSchedule(NOTE, 6, s); assert.ok(next.includes("Never keep fewer than three copies.\n\n\nCapital")); assert.equal(scanCards(next).filter((c) => c.kind === "qa").length, 2); const inline = writeSchedule(NOTE, 11, s); assert.ok(inline.includes("Capital of Egypt::Cairo ")); // The reviewed inline card is still a card, with its schedule read back. const reviewed = scanCards(inline).find((c) => c.line === 11); assert.deepEqual(reviewed && [reviewed.front, reviewed.back, reviewed.schedule], ["Capital of Egypt", "Cairo", s]); const quote = writeSchedule(NOTE, 15, s); assert.ok(quote.includes("> It has many aspects.\n\n")); const again = writeSchedule(quote, 15, { ...s, interval: 9 }); assert.equal((again.match(/SR:!2026-10-01,9,2500/g) ?? []).length, 1); assert.equal((again.match(/