Docs nav tests
The docs linked in the bar. A nav list in docs/README.md sets their order, and without one
every doc is linked in alphabetical order. Names that aren't docs are skipped, with a warning.
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { afterEach, describe, expect, it } from "vite-plus/test";
import { docsNav, renderNav } from "../src/nav.js";
let root: string;
afterEach(() => rmSync(root, { recursive: true, force: true }));
function repo(readme: string | null): string[] {
root = mkdtempSync(join(tmpdir(), "prose-nav-"));
mkdirSync(join(root, "docs"));
if (readme !== null) writeFileSync(join(root, "docs/README.md"), readme);
const files = ["docs/usage.md", "docs/design.md", "docs/getting-started.md", "docs/deep/x.md"];
return readme === null ? files : ["docs/README.md", ...files];
}
describe("docsNav", () => {
it("warns when docs/README.md's metadata can't be read, and lists every doc", () => {
const files = repo("---\nnav:\n - usage.md\n---\n# Docs\n");
const warnings: string[] = [];
expect(docsNav(root, files, warnings).map((item) => item.label)).toEqual([
"Design",
"Getting started",
"Usage",
]);
expect(warnings).toHaveLength(1);
expect(warnings[0]).toMatch(
/^docs\/README\.md line 3: .*, so the bar lists every doc in alphabetical order$/,
);
});
it("follows the nav list in docs/README.md, skipping and warning about a name that isn't a doc", () => {
const files = repo("---\nnav: [usage.md, missing.md, design.md, /quality]\n---\n# Docs\n");
const warnings: string[] = [];
expect(docsNav(root, files, warnings)).toEqual([
{ path: "docs/usage.md", label: "Usage" },
{ path: "docs/design.md", label: "Design" },
]);
expect(warnings).toEqual([
"docs/README.md's nav lists missing.md, which isn't a doc in docs/, so the bar skips it",
"docs/README.md's nav lists /quality, which isn't a doc in docs/, so the bar skips it",
]);
});
it("pins every doc in docs/, alphabetically, with no README or no list in it", () => {
const labels = (files: string[]) => docsNav(root, files).map((item) => item.label);
expect(labels(repo(null))).toEqual(["Design", "Getting started", "Usage"]);
rmSync(root, { recursive: true, force: true });
expect(labels(repo("# Docs\n\nNo metadata.\n"))).toEqual([
"Design",
"Getting started",
"Usage",
]);
});
it("links the docs in the bar, the current one marked, and nothing without docs", () => {
const html = renderNav([{ path: "docs/design.md", label: "Design" }], "docs/design.md");
expect(html).toContain(
'<nav class="docs" id="docs" popover aria-label="Docs"><a href="/docs/design.md" aria-current="page">Design</a></nav>',
);
expect(html).toContain('popovertarget="docs"');
expect(renderNav([], "")).toBe("");
});
});