Track HiveGrid Cloud planning reference
This commit is contained in:
1 parent
b3d5ea6764
commit
e341c5938a
5784 files changed
+1104929
-3
No files matched your search
@@ -0,0 +1,127 @@
|
||||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import assert from "node:assert/strict";
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { afterEach, describe, it } from "vitest";
|
||||
|
||||
import { checkDocsLinks, formatDocsLinkCheckResult } from "./docs-link-check";
|
||||
|
||||
const fixtures: string[] = [];
|
||||
|
||||
function createFixture(files: Record<string, string>): string {
|
||||
const rootDir = fs.mkdtempSync(path.join(os.tmpdir(), "docs-link-check-"));
|
||||
fixtures.push(rootDir);
|
||||
|
||||
for (const [relativePath, content] of Object.entries(files)) {
|
||||
const absolutePath = path.join(rootDir, relativePath);
|
||||
fs.mkdirSync(path.dirname(absolutePath), { recursive: true });
|
||||
fs.writeFileSync(absolutePath, content);
|
||||
}
|
||||
|
||||
return rootDir;
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
while (fixtures.length > 0) {
|
||||
fs.rmSync(fixtures.pop() as string, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
describe("docs-link-check", () => {
|
||||
it("passes for valid local Markdown links and anchors", () => {
|
||||
const rootDir = createFixture({
|
||||
"README.md": "# Root\nSee [plugins](docs/plugins.md#plugin-boundaries).",
|
||||
"docs/plugins.md": "# Plugin Boundaries\nSee [feature inventory](feature-inventory.md).",
|
||||
"docs/feature-inventory.md": "# Feature Inventory\n",
|
||||
});
|
||||
|
||||
const result = checkDocsLinks(rootDir, ["README.md", "docs"]);
|
||||
const output = formatDocsLinkCheckResult(result);
|
||||
|
||||
assert.deepEqual(result.failures, []);
|
||||
assert.match(output, /^PASS docs link check/);
|
||||
});
|
||||
|
||||
it("fails with file context for missing local paths", () => {
|
||||
const rootDir = createFixture({
|
||||
"README.md": "# Root\nSee [missing](docs/missing.md).",
|
||||
});
|
||||
|
||||
const result = checkDocsLinks(rootDir, ["README.md", "docs"]);
|
||||
|
||||
assert.match(result.failures.join("\n"), /README\.md:\d+:\d+: broken local link "docs\/missing\.md"/);
|
||||
});
|
||||
|
||||
it("fails with file context for missing local anchors", () => {
|
||||
const rootDir = createFixture({
|
||||
"README.md": "# Root\nSee [plugins](docs/plugins.md#missing-anchor).",
|
||||
"docs/plugins.md": "# Plugin Boundaries\n",
|
||||
});
|
||||
|
||||
const result = checkDocsLinks(rootDir, ["README.md", "docs"]);
|
||||
|
||||
assert.match(result.failures.join("\n"), /README\.md:\d+:\d+: broken local anchor "#missing-anchor"/);
|
||||
});
|
||||
|
||||
it("ignores external URLs and special link schemes", () => {
|
||||
const rootDir = createFixture({
|
||||
"README.md": [
|
||||
"# Root",
|
||||
"See [external](https://example.com/missing#anchor).",
|
||||
"Send [mail](mailto:help@example.com) or [call](tel:+15555550100).",
|
||||
"Jump to [local](#root).",
|
||||
].join("\n"),
|
||||
});
|
||||
|
||||
const result = checkDocsLinks(rootDir, ["README.md"]);
|
||||
|
||||
assert.deepEqual(result.failures, []);
|
||||
});
|
||||
|
||||
it("fails closed when a configured docs root is missing", () => {
|
||||
const rootDir = createFixture({
|
||||
"README.md": "# Root\n",
|
||||
});
|
||||
|
||||
const result = checkDocsLinks(rootDir, ["README.md", "docs"]);
|
||||
|
||||
assert.match(result.failures.join("\n"), /docs-roots: missing configured docs root docs/);
|
||||
});
|
||||
|
||||
it("fails closed when no Markdown files are checked", () => {
|
||||
const rootDir = createFixture({
|
||||
"src/index.ts": "export {};",
|
||||
});
|
||||
|
||||
const result = checkDocsLinks(rootDir, ["docs"]);
|
||||
|
||||
assert.match(result.failures.join("\n"), /docs-roots: checked 0 Markdown files/);
|
||||
});
|
||||
|
||||
it("exits non-zero from the CLI when local links are broken", () => {
|
||||
const rootDir = createFixture({
|
||||
"README.md": "# Root\nSee [missing](docs/missing.md).",
|
||||
"AGENTS.md": "# Agents\n",
|
||||
"SECURITY.md": "# Security\n",
|
||||
"CHANGELOG.md": "# Changelog\n",
|
||||
"docs/index.md": "# Docs\n",
|
||||
"guides/index.md": "# Guides\n",
|
||||
"llm-docs/index.md": "# LLM Docs\n",
|
||||
});
|
||||
|
||||
let output = "";
|
||||
assert.throws(() => {
|
||||
try {
|
||||
execFileSync("pnpm", ["exec", "tsx", path.resolve("scripts/docs-link-check.ts"), rootDir], { encoding: "utf8", stdio: "pipe" });
|
||||
} catch (error) {
|
||||
if (error && typeof error === "object") {
|
||||
const failure = error as { stderr?: Buffer | string; stdout?: Buffer | string };
|
||||
output = `${String(failure.stderr ?? "")}\n${String(failure.stdout ?? "")}`;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
assert.match(output, /broken local link "docs\/missing\.md"/);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user