feat(course-format): stcourse.yaml schema
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
3b15d87a5f
commit
7e7ce30535
4 files changed
+171
-1
No files matched your search
@@ -0,0 +1,51 @@
|
||||
import { describe, expect, test } from "bun:test";
|
||||
import { parseManifest } from "../src/schema";
|
||||
|
||||
const base = (extra = "", lessons = " - { id: l1, title: One, type: text, file: a.md }") =>
|
||||
`schema: 1\nid: x\ntitle: X\n${extra}modules:\n - id: m1\n title: M\n lessons:\n${lessons}\n`;
|
||||
|
||||
describe("parseManifest", () => {
|
||||
test("parses a minimal manifest", () => {
|
||||
const r = parseManifest(base());
|
||||
expect(r.ok).toBe(true);
|
||||
if (r.ok) {
|
||||
expect(r.manifest.visibility).toBe("restricted");
|
||||
expect(r.manifest.gating).toBe("none");
|
||||
}
|
||||
});
|
||||
|
||||
test("rejects a bad accent", () => {
|
||||
const r = parseManifest(base('accent: "orange"\n'));
|
||||
expect(r.ok).toBe(false);
|
||||
if (!r.ok) expect(r.errors.some((e) => e.includes("accent"))).toBe(true);
|
||||
});
|
||||
|
||||
test("rejects duplicate lesson ids across modules", () => {
|
||||
const text = base() + " - id: m2\n title: M2\n lessons:\n - { id: l1, title: Dup, type: text, file: b.md }\n";
|
||||
const r = parseManifest(text);
|
||||
expect(r.ok).toBe(false);
|
||||
if (!r.ok) expect(r.errors.some((e) => e.includes("l1"))).toBe(true);
|
||||
});
|
||||
|
||||
test("requires file for text and video lessons", () => {
|
||||
for (const type of ["text", "video"]) {
|
||||
const r = parseManifest(base("", ` - { id: l1, title: One, type: ${type} }`));
|
||||
expect(r.ok).toBe(false);
|
||||
if (!r.ok) expect(r.errors.some((e) => e.includes("file"))).toBe(true);
|
||||
}
|
||||
expect(parseManifest(base("", " - { id: l1, title: One, type: exercise }")).ok).toBe(true);
|
||||
});
|
||||
|
||||
test("rejects a deck whose attachTo is not a lesson or module id", () => {
|
||||
const r = parseManifest(base("decks:\n - { id: d1, file: d.pdf, attachTo: nope }\n"));
|
||||
expect(r.ok).toBe(false);
|
||||
if (!r.ok) expect(r.errors.some((e) => e.includes("nope"))).toBe(true);
|
||||
expect(parseManifest(base("decks:\n - { id: d1, file: d.pdf, attachTo: m1 }\n")).ok).toBe(true);
|
||||
});
|
||||
|
||||
test("rejects schema: 2", () => {
|
||||
const r = parseManifest(base().replace("schema: 1", "schema: 2"));
|
||||
expect(r.ok).toBe(false);
|
||||
if (!r.ok) expect(r.errors.some((e) => e.startsWith("schema"))).toBe(true);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user