90 lines
2.0 KiB
TypeScript
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([]);
|
|
});
|
|
});
|