126 lines
7.7 KiB
JavaScript
126 lines
7.7 KiB
JavaScript
import { mkdir, writeFile } from "node:fs/promises";
|
|
import { join } from "node:path";
|
|
import { tmpdir } from "node:os";
|
|
import { mkdtemp } from "node:fs/promises";
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
import {
|
|
failureCount,
|
|
gates,
|
|
importInventoryPatterns,
|
|
importInventoryScanRoots,
|
|
renderReport,
|
|
reportPath,
|
|
runImportInventory,
|
|
} from "./verify-import-boundary-baseline.mjs";
|
|
|
|
describe("Import Boundary baseline gate contract", () => {
|
|
it("writes the baseline report to the Import Boundary health artifact path", () => {
|
|
expect(reportPath.replaceAll("\\", "/")).toMatch(/\.tc\/baselines\/import-boundary\/baseline-health\.md$/);
|
|
});
|
|
|
|
it("keeps the expected non-E2E gate IDs in order", () => {
|
|
expect(gates.map((gate) => gate.id)).toEqual(["typecheck", "lint", "vitest-export-formats", "vitest-import-infrastructure", "import-inventory"]);
|
|
expect(gates.some((gate) => gate.args?.some((arg) => /playwright|cypress|browser|e2e|test:e2e|--watch|watch/i.test(arg)))).toBe(false);
|
|
});
|
|
|
|
it("pins export format and import infrastructure Vitest gates to explicit unit tests", () => {
|
|
expect(gates.find((gate) => gate.id === "vitest-export-formats")?.args).toEqual([
|
|
"exec",
|
|
"vitest",
|
|
"run",
|
|
"packages/exports/src/index.test.ts",
|
|
"packages/exports/src/csv/index.test.ts",
|
|
"packages/exports/src/json/index.test.ts",
|
|
"packages/exports/src/xlsx/index.test.ts",
|
|
]);
|
|
expect(gates.find((gate) => gate.id === "vitest-import-infrastructure")?.args).toEqual([
|
|
"exec",
|
|
"vitest",
|
|
"run",
|
|
"packages/storage/src/scan/index.test.ts",
|
|
"packages/queue/src/producers.test.ts",
|
|
"apps/worker/src/handlers.test.ts",
|
|
]);
|
|
});
|
|
|
|
it("covers import inventory roots and fingerprint pattern metadata", () => {
|
|
expect(importInventoryScanRoots).toEqual(["apps/web/app/routes", "apps/api/src", "apps/worker/src", "packages/db/src", "packages/exports/src", "packages/queue/src", "packages/storage/src", "prisma/schema"]);
|
|
expect(importInventoryPatterns.map(({ id }) => id)).toEqual([
|
|
"import-format-term",
|
|
"import-job-model-reference",
|
|
"parser-mapping-reference",
|
|
"dry-run-validation-reference",
|
|
"queue-worker-import-wiring",
|
|
"scan-quarantine-reference",
|
|
"tenant-permission-audit-marker",
|
|
"generated-client-reference",
|
|
]);
|
|
const patternSources = Object.fromEntries(importInventoryPatterns.map(({ id, pattern }) => [id, pattern.source]));
|
|
expect(patternSources["import-format-term"]).toMatch(/csv|json|xlsx/);
|
|
expect(patternSources["import-job-model-reference"]).toMatch(/importJob|ImportJob|model/);
|
|
expect(patternSources["parser-mapping-reference"]).toMatch(/parser|mapping|fieldMap/);
|
|
expect(patternSources["dry-run-validation-reference"]).toMatch(/dryRun|validation|duplicate|errorReport/);
|
|
expect(patternSources["queue-worker-import-wiring"]).toMatch(/queue|worker|importJob/);
|
|
expect(patternSources["scan-quarantine-reference"]).toMatch(/clamav|scan|quarantine/);
|
|
expect(patternSources["tenant-permission-audit-marker"]).toMatch(/permission|audit|tenantId/);
|
|
expect(patternSources["generated-client-reference"]).toContain("packages\\/db\\/generated");
|
|
expect(patternSources["generated-client-reference"]).toContain("client\\/models\\/(?:ImportJob|ImportError|FileObject)");
|
|
});
|
|
|
|
it("counts command failures while treating read-only inventory findings as non-failing", () => {
|
|
expect(failureCount("typecheck", "src/a.ts(1,1): error TS2322: wrong\nerror TS7006", "", 2)).toBe(2);
|
|
expect(failureCount("lint", "✖ 5 problems (3 errors, 2 warnings)", "", 1)).toBe(3);
|
|
expect(failureCount("vitest-export-formats", "Tests 2 failed | 4 passed", "", 1)).toBe(2);
|
|
expect(failureCount("vitest-import-infrastructure", "Test Files 1 failed | 2 passed", "", 1)).toBe(1);
|
|
expect(failureCount("import-inventory", "generated-client-reference: 4", "", 1)).toBe(0);
|
|
});
|
|
|
|
it("renders baseline report diagnostics without snapshots", () => {
|
|
const report = renderReport([
|
|
{ id: "import-inventory", command: "read-only import inventory", exitCode: 0, durationMs: 42, failureCount: 0, fingerprint: { hash: "abc123def456", excerpt: "import-format-term: 7" } },
|
|
{ id: "typecheck", command: "pnpm run typecheck", exitCode: 2, durationMs: 99, failureCount: 3, fingerprint: { hash: "badc0ffee123", excerpt: "error TS2322" } },
|
|
]);
|
|
|
|
expect(report).toContain("# Import Boundary Baseline Health");
|
|
expect(report).toContain("non-E2E baseline gates for Import Boundary baseline");
|
|
expect(report).toContain("import job/model/parser/mapping/dry-run/validation/duplicate/error-report markers");
|
|
expect(report).toContain("## import-inventory");
|
|
expect(report).toContain("- Exitcode: 2");
|
|
expect(report).toContain("- Failure Count: 3");
|
|
expect(report).toContain("- Output Fingerprint: badc0ffee123");
|
|
});
|
|
|
|
it("scans import roots while excluding generated Prisma client noise", async () => {
|
|
const root = await mkdtemp(join(tmpdir(), "importBoundary-import-inventory-"));
|
|
await mkdir(join(root, "apps", "web", "app", "routes"), { recursive: true });
|
|
await mkdir(join(root, "apps", "worker", "src"), { recursive: true });
|
|
await mkdir(join(root, "packages", "db", "src"), { recursive: true });
|
|
await mkdir(join(root, "packages", "exports", "src", "csv"), { recursive: true });
|
|
await mkdir(join(root, "packages", "storage", "src", "scan"), { recursive: true });
|
|
await mkdir(join(root, "packages", "db", "generated", "prisma", "client", "models"), { recursive: true });
|
|
await mkdir(join(root, "prisma", "schema"), { recursive: true });
|
|
|
|
await writeFile(join(root, "apps", "web", "app", "routes", "imports.ts"), "export async function action() { return json({ csv: true, dryRun: true, errorReport: true }); }\n", "utf8");
|
|
await writeFile(join(root, "apps", "worker", "src", "import-worker.ts"), "const importJob = queue.add('import', { validation: true, duplicate: false, audit: true });\n", "utf8");
|
|
await writeFile(join(root, "packages", "exports", "src", "csv", "parser.ts"), "const fieldMap = parser.parse('xlsx json mapping row header');\n", "utf8");
|
|
await writeFile(join(root, "packages", "storage", "src", "scan", "clamav.ts"), "const scanResult = 'clamav scan quarantine clean tenantId permission';\n", "utf8");
|
|
await writeFile(join(root, "packages", "db", "src", "import-job.ts"), "const key = 'ImportJob PrismaClient client/models/ImportJob actorId';\n", "utf8");
|
|
await writeFile(join(root, "packages", "db", "generated", "prisma", "client", "models", "ImportJob.ts"), "PrismaClient ImportJob generated/prisma client/models/ImportJob should be ignored\n", "utf8");
|
|
await writeFile(join(root, "prisma", "schema", "schema.prisma"), "model ImportJob { id String @id }\n", "utf8");
|
|
|
|
const inventory = await runImportInventory(root);
|
|
|
|
expect(inventory.roots).toEqual(expect.arrayContaining(["apps/web/app/routes", "apps/worker/src", "packages/db/src", "packages/exports/src", "packages/storage/src", "prisma/schema"]));
|
|
expect(inventory.counts["import-format-term"]).toBeGreaterThan(0);
|
|
expect(inventory.counts["import-job-model-reference"]).toBeGreaterThan(0);
|
|
expect(inventory.counts["parser-mapping-reference"]).toBeGreaterThan(0);
|
|
expect(inventory.counts["dry-run-validation-reference"]).toBeGreaterThan(0);
|
|
expect(inventory.counts["queue-worker-import-wiring"]).toBeGreaterThan(0);
|
|
expect(inventory.counts["scan-quarantine-reference"]).toBeGreaterThan(0);
|
|
expect(inventory.counts["tenant-permission-audit-marker"]).toBeGreaterThan(0);
|
|
expect(inventory.counts["generated-client-reference"]).toBeGreaterThan(0);
|
|
expect(inventory.matches.join("\n")).not.toContain("packages/db/generated/prisma/client/models/ImportJob.ts");
|
|
});
|
|
});
|