Files

90 lines
2.0 KiB
TypeScript

import { describe, expect, test } from "bun:test";
import { extractHints, extractSection, slugify } from "../src/markdown";
describe("slugify", () => {
test("follows GitHub's algorithm", () => {
expect(slugify("Exercise 3.1 — `move`")).toBe("exercise-31--move");
expect(slugify("Why this module")).toBe("why-this-module");
expect(slugify("Rules as functions `State → State`")).toBe("rules-as-functions-state--state");
expect(slugify("**Bold** and [a link](http://x.y)")).toBe("bold-and-a-link");
});
});
const sample = `# Top
intro
## First
one
### Middle
middle body
\`\`\`sh
# not a heading
\`\`\`
#### Deeper
deep body
### Sibling
sibling body
## Last
end
`;
describe("extractSection", () => {
test("returns only the middle section, including deeper headings", () => {
const s = extractSection(sample, "middle");
expect(s).not.toBeNull();
expect(s!.startsWith("### Middle")).toBe(true);
expect(s).toContain("# not a heading");
expect(s).toContain("deep body");
expect(s).not.toContain("sibling body");
expect(s).not.toContain("one");
});
test("returns null for an unknown anchor", () => {
expect(extractSection(sample, "nope")).toBeNull();
});
test("a section runs to the end of file when nothing follows", () => {
expect(extractSection(sample, "last")).toBe("## Last\n\nend");
});
});
describe("extractHints", () => {
const md = `## Hints
<details><summary>Exercise 3.1 (move) — nudge</summary>
Think about direction.
</details>
<details><summary>Exercise 3.1 (move) — stronger hint</summary>
Add the delta.
</details>
<details><summary>Exercise 3.2 (inBounds) — nudge</summary>
Other.
</details>
`;
test("returns matching blocks in order with trimmed labels", () => {
const h = extractHints(md, "Exercise 3.1 (move)");
expect(h.map((x) => x.label)).toEqual(["nudge", "stronger hint"]);
expect(h[0]!.body).toBe("Think about direction.");
});
test("returns [] when nothing matches", () => {
expect(extractHints(md, "Exercise 9.9")).toEqual([]);
});
});