import { expect, test } from "bun:test"; import { renderHintsHtml, renderLessonHtml, resolveHref, sanitizeHtml } from "../src/web/markdown"; const tracks = [{ id: "js", label: "JavaScript" }, { id: "scala", label: "Scala 3" }, { id: "fsharp", label: "F#" }]; const opts = { courseId: "pure-snake", baseFile: "course/01-purity.md", tracks, lessonFiles: { "course/02-data.md": "m02-text" } }; const variants = `Intro **JavaScript** \`\`\`js export const range = (n) => ... \`\`\` **Scala** \`\`\`scala def range(n: Int): List[Int] \`\`\` **F#** \`\`\`fsharp let range (n: int) : int list \`\`\` Tests: after. `; test("track switcher keeps only the chosen variant and its label", () => { const scala = renderLessonHtml(variants, { ...opts, track: "scala" }); expect(scala).toContain("def range"); expect(scala).not.toContain("export const range"); expect(scala).not.toContain("let range"); expect(scala).toContain("Scala"); expect(scala).not.toContain("JavaScript"); expect(scala).toContain("Tests: after."); const fs = renderLessonHtml(variants, { ...opts, track: "fsharp" }); expect(fs).toContain("let range"); expect(fs).not.toContain("def range"); }); test("a lone code block in one track stays visible for other tracks", () => { const md = "Text\n\n```js\nexport const pipe = 1\n```\n\nMore"; expect(renderLessonHtml(md, { ...opts, track: "scala" })).toContain("export const pipe"); }); test("a variant group without the chosen track keeps every variant", () => { const md = "```js\nA\n```\n\n```scala\nB\n```\n"; const html = renderLessonHtml(md, { ...opts, track: "fsharp" }); expect(html).toContain("A"); expect(html).toContain("B"); }); test("headings get GitHub ids and the first heading can be dropped", () => { const html = renderLessonHtml("# Module 1\n\n## Why this module\n\n### Exercise 1.1 — `range`\n\n## Why this module\n", { ...opts, stripFirstHeading: true }); expect(html).not.toContain("Module 1"); expect(html).toContain('
');
expect(html).toContain('target="_blank" rel="noopener noreferrer"');
});
test("exercise hints render as one tier group", () => {
const html = renderHintsHtml([{ label: "nudge", body: "Which **operator**?" }, { label: "near-solution", body: "`a + b`" }], { courseId: "sample", baseFile: null });
expect(html).toContain("Nudge");
expect(html).toContain('data-tier="2" data-tiers="2"');
expect(html).toContain("operator");
});