Files
openclaw/test/scripts/docs-sync-publish.test.ts
2026-07-28 23:45:40 +08:00

135 lines
4.3 KiB
TypeScript

import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { describe, expect, it } from "vitest";
import {
composeDocsConfig,
parseArgs,
reportOrphanLocaleDocs,
} from "../../scripts/docs-sync-publish.mjs";
function collectPages(entry: unknown, pages: string[] = []): string[] {
if (typeof entry === "string") {
pages.push(entry);
return pages;
}
if (Array.isArray(entry)) {
for (const item of entry) {
collectPages(item, pages);
}
return pages;
}
if (!entry || typeof entry !== "object") {
return pages;
}
const record = entry as Record<string, unknown>;
if (typeof record.page === "string") {
pages.push(record.page);
}
collectPages(record.pages, pages);
collectPages(record.groups, pages);
collectPages(record.tabs, pages);
return pages;
}
describe("docs-sync-publish", () => {
it("parses docs sync provenance args", () => {
expect(
parseArgs([
"--target",
"generated-docs",
"--source-repo",
"openclaw/openclaw",
"--source-sha",
"abc123",
"--clawhub-repo",
"../clawhub",
"--clawhub-source-repo",
"openclaw/clawhub",
"--clawhub-source-sha",
"def456",
]),
).toMatchObject({
clawhubRepo: "../clawhub",
clawhubSourceRepo: "openclaw/clawhub",
clawhubSourceSha: "def456",
sourceRepo: "openclaw/openclaw",
sourceSha: "abc123",
target: "generated-docs",
});
});
it("rejects missing docs sync option values", () => {
for (const flag of [
"--target",
"--source-repo",
"--source-sha",
"--clawhub-repo",
"--clawhub-source-repo",
"--clawhub-source-sha",
]) {
expect(() => parseArgs([flag])).toThrow(`${flag} requires a value`);
expect(() => parseArgs([flag, "--target", "generated-docs"])).toThrow(
`${flag} requires a value`,
);
expect(() => parseArgs([flag, "-h"])).toThrow(`${flag} requires a value`);
}
});
it("defers orphan locale deletion to translation finalization", () => {
const docsDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-docs-sync-"));
const mirroredEnglish = path.join(docsDir, "clawhub", "api.md");
const localizedMirror = path.join(docsDir, "de", "clawhub", "api.md");
const orphan = path.join(docsDir, "de", "removed.md");
fs.mkdirSync(path.dirname(mirroredEnglish), { recursive: true });
fs.mkdirSync(path.dirname(localizedMirror), { recursive: true });
fs.writeFileSync(mirroredEnglish, "# ClawHub API\n");
fs.writeFileSync(localizedMirror, "# ClawHub-API\n");
fs.writeFileSync(orphan, "# Removed\n");
try {
expect(reportOrphanLocaleDocs(docsDir)).toBe(1);
expect(fs.existsSync(localizedMirror)).toBe(true);
expect(fs.existsSync(orphan)).toBe(true);
} finally {
fs.rmSync(docsDir, { recursive: true, force: true });
}
});
it("keeps generated locale navigation aligned with English routes", () => {
const config = composeDocsConfig() as {
navigation: {
languages: Array<{
language: string;
tabs: Array<{ tab: string; groups?: Array<{ group: string }> }>;
}>;
};
};
const english = config.navigation.languages.find((entry) => entry.language === "en");
const simplifiedChinese = config.navigation.languages.find(
(entry) => entry.language === "zh-Hans",
);
const german = config.navigation.languages.find((entry) => entry.language === "de");
expect(english).toBeDefined();
expect(simplifiedChinese).toBeDefined();
expect(german).toBeDefined();
const englishWithoutClawHub = {
...english,
tabs: english!.tabs.filter((tab) => tab.tab !== "ClawHub"),
};
const expectedZhPages = collectPages(englishWithoutClawHub)
.map((page) => `zh-CN/${page}`)
.toSorted();
expect(collectPages(simplifiedChinese).toSorted()).toEqual(expectedZhPages);
expect(simplifiedChinese!.tabs[0]?.tab).toBe("快速开始");
expect(simplifiedChinese!.tabs[0]?.groups?.[0]?.group).toBe("首页");
expect(collectPages(german)).toHaveLength(collectPages(englishWithoutClawHub).length);
expect(german!.tabs[0]?.tab).toBe("Loslegen");
expect(german!.tabs[0]?.groups?.[0]?.group).toBe("Überblick");
});
});