import { expect, test } from "bun:test"; import { parseManifest } from "@stc/course-format"; import { moduleLocks } from "../src/server/gating"; const m = (gating: string) => { const r = parseManifest(`schema: 1\nid: g\ntitle: G\ngating: ${gating}\nmodules:\n - { id: a, title: A, lessons: [{ id: a1, title: A1, type: exercise }, { id: a2, title: A2, type: exercise }] }\n - { id: b, title: B, lessons: [{ id: b1, title: B1, type: exercise }] }\n - { id: c, title: C, lessons: [{ id: c1, title: C1, type: exercise }] }\n`); if (!r.ok) throw new Error(r.errors.join()); return r.manifest; }; test("no gating unlocks everything", () => { expect(moduleLocks(m("none"), {})).toEqual([false, false, false]); }); test("sequential gating locks until the previous module is done", () => { expect(moduleLocks(m("sequential"), {})).toEqual([false, true, true]); expect(moduleLocks(m("sequential"), { a1: { state: "done" } })).toEqual([false, true, true]); expect(moduleLocks(m("sequential"), { a1: { state: "done" }, a2: { state: "done" } })).toEqual([false, false, true]); // done later modules do not unlock past an unfinished one expect(moduleLocks(m("sequential"), { a1: { state: "done" }, a2: { state: "done" }, c1: { state: "done" } })).toEqual([false, false, true]); expect(moduleLocks(m("sequential"), {}, true)).toEqual([false, false, false]); });