import { spawnSync } from "node:child_process"; import { readFileSync } from "node:fs"; import { describe, expect, it } from "vitest"; import { createPluginContractTestShards } from "../../scripts/lib/plugin-contract-test-plan.mjs"; import { expectNoNodeFsScans } from "../../src/test-utils/fs-scan-assertions.js"; function listContractTests(rootDir = "src/plugins/contracts"): string[] { const result = spawnSync("git", ["ls-files", "--", rootDir], { cwd: process.cwd(), encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], }); expect(result.status).toBe(0); return result.stdout .split("\n") .map((line) => line.trim().replaceAll("\\", "/")) .filter((line) => line.endsWith(".test.ts")) .toSorted((a, b) => a.localeCompare(b)); } describe("scripts/lib/plugin-contract-test-plan.mjs", () => { it("keeps manual CI compatible with legacy target refs", () => { const workflow = readFileSync(".github/workflows/ci.yml", "utf8"); expect(workflow).toContain( 'await import(\n "./scripts/lib/plugin-contract-test-plan.mjs"', ); expect(workflow).toContain("checks-fast-contracts-plugins-legacy"); expect(workflow).not.toContain( "createPluginContractTestShards: () => [\n createPluginContractTestShards", ); }); it("splits plugin contracts into focused shards", () => { const suffixes = ["a", "b", "c", "d"]; expect( createPluginContractTestShards().map((shard) => ({ checkName: shard.checkName, runtime: shard.runtime, task: shard.task, })), ).toEqual( suffixes.map((suffix) => ({ checkName: `checks-fast-contracts-plugins-${suffix}`, runtime: "node", task: "contracts-plugins", })), ); }); it("covers every plugin contract test exactly once", () => { const actual = createPluginContractTestShards() .flatMap((shard) => shard.includePatterns) .toSorted((a, b) => a.localeCompare(b)); expect(actual).toEqual(listContractTests()); expect(new Set(actual).size).toBe(actual.length); }); it("uses git-tracked files without walking contract directories", () => { const payload = expectNoNodeFsScans<{ files: number; shards: number; }>(` const { createPluginContractTestShards } = await import("./scripts/lib/plugin-contract-test-plan.mjs"); const shards = createPluginContractTestShards(); return { files: shards.reduce((total, shard) => total + shard.includePatterns.length, 0), shards: shards.length, }; `); expect(payload.shards).toBe(4); expect(payload.files).toBeGreaterThan(0); }); it("keeps plugin registration contract files spread across checks", () => { for (const shard of createPluginContractTestShards()) { const registrationFiles = shard.includePatterns.filter((pattern) => pattern.includes("/plugin-registration."), ); expect(registrationFiles.length).toBeLessThanOrEqual(7); } }); });