rea/tests/readmeConsistency.test.ts

93 lines
3.8 KiB
TypeScript

import { readFile } from "node:fs/promises";
import { resolve } from "node:path";
import { describe, expect, it } from "vitest";
import {
ENHANCED_TOOL_CONTRACTS,
OFFICIAL_TOOL_CONTRACTS,
SESSION_TOOL_CONTRACTS,
} from "../src/contracts/toolContracts.js";
import { NATIVE_TOOL_CONTRACTS } from "../src/contracts/nativeToolContracts.js";
import { ARTIFACT_TOOL_CONTRACTS } from "../src/contracts/artifactToolContracts.js";
import { MANAGED_TOOL_CONTRACTS } from "../src/contracts/managedToolContracts.js";
import { MANAGED_WORKFLOW_TOOL_CONTRACTS } from "../src/contracts/managedWorkflowToolContracts.js";
import { BROWSER_TOOL_CONTRACTS } from "../src/contracts/browserToolContracts.js";
import { ELECTRON_TOOL_CONTRACTS } from "../src/contracts/electronToolContracts.js";
import { APPLICATION_TOOL_CONTRACTS } from "../src/contracts/applicationToolContracts.js";
import { SUPPORTED_CLIENT_DEFINITIONS } from "../src/application/SupportedClients.js";
const readmes = [
"README.md",
"README_zh.md",
"README_ja.md",
"README_ko.md",
"README_ar.md",
] as const;
const expectedToolCounts = [
OFFICIAL_TOOL_CONTRACTS.length,
ENHANCED_TOOL_CONTRACTS.length,
NATIVE_TOOL_CONTRACTS.length,
ARTIFACT_TOOL_CONTRACTS.length,
MANAGED_TOOL_CONTRACTS.length + MANAGED_WORKFLOW_TOOL_CONTRACTS.length,
BROWSER_TOOL_CONTRACTS.length,
ELECTRON_TOOL_CONTRACTS.length,
APPLICATION_TOOL_CONTRACTS.length,
SESSION_TOOL_CONTRACTS.length,
] as const;
const toolCountsFromReadme = (content: string, path: string): number[] => {
const lines = content.split(/\r?\n/u);
for (const [index, line] of lines.entries()) {
if (!/^\|\s*-/u.test(line)) continue;
const counts: number[] = [];
for (const row of lines.slice(index + 1)) {
if (!row.trim().startsWith("|")) break;
const count = Number(row.split("|")[2]?.trim());
if (!Number.isInteger(count)) break;
counts.push(count);
}
if (counts.length === expectedToolCounts.length) return counts;
}
throw new Error(`Missing tool-family inventory table in ${path}`);
};
describe("localized README product facts", () => {
it.each(readmes)(
"keeps commands and requirements aligned in %s",
async (path) => {
const content = await readFile(resolve(path), "utf8");
expect(content).toContain("npx skills add morluto/rea");
expect(content).toContain(
"curl -fsSL https://raw.githubusercontent.com/morluto/rea/main/install.sh | bash",
);
expect(content).toContain("npx rea-agents setup");
expect(content).toContain("npx -y rea-agents@latest doctor");
expect(content).toContain("rea uninstall");
expect(content).toContain('"args": ["-y", "rea-agents@latest", "mcp"]');
expect(content).toContain("Node.js 22");
expect(content).toContain("macOS 12");
expect(content).toContain("Ubuntu 24.04");
expect(content).toContain("Fedora 41");
expect(content).toContain("Arch Linux");
for (const client of SUPPORTED_CLIENT_DEFINITIONS)
expect(content).toContain(client.displayName);
if (path === "README_ar.md")
expect(content).toContain("Windows غير مدعوم حاليًا");
expect(content).toContain("MCP-tool_catalog");
expect(toolCountsFromReadme(content, path)).toEqual(expectedToolCounts);
},
);
it("keeps both English CLI onboarding paths discoverable", async () => {
const content = await readFile(resolve("README.md"), "utf8");
expect(content).toContain("npx -y rea-agents@latest analyze");
expect(content).toContain("npm install rea-agents` without `--global`");
expect(content).toContain("npm install --global rea-agents");
expect(content).toContain("rea setup");
expect(content).toContain("--install-hopper");
expect(content).toContain("docs/installation.md");
expect(content).toContain("You do not need both");
});
});