83 lines
2.9 KiB
TypeScript
83 lines
2.9 KiB
TypeScript
import { readFile } from "node:fs/promises";
|
|
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
import {
|
|
bundleOutputInventoryArtifactSchema,
|
|
bundlePerformanceArtifactSchema,
|
|
} from "../../scripts/contracts/release-artifacts.ts";
|
|
|
|
const sha256 = "a".repeat(64);
|
|
|
|
const inventory = {
|
|
schemaVersion: 1,
|
|
generatedAt: "2026-08-02T00:00:00.000Z",
|
|
context: {
|
|
nodeVersion: "v24.14.0",
|
|
packageManager: "pnpm@11.17.0",
|
|
runnerImage: "fixture@sha256:abc",
|
|
},
|
|
outputs: [
|
|
{ path: "dist/assets/entry.js", bytes: 100, gzipBytes: 50, sha256 },
|
|
{ path: "dist/assets/lazy.js", bytes: 80, gzipBytes: 40, sha256 },
|
|
{ path: "dist/index.html", bytes: 20, gzipBytes: 15, sha256 },
|
|
],
|
|
} as const;
|
|
|
|
const completed = {
|
|
...inventory,
|
|
measurements: {
|
|
initialJsGzipBytes: 50,
|
|
lazyChunks: [{ path: "assets/lazy.js", gzipBytes: 40 }],
|
|
},
|
|
classification: {
|
|
initialFiles: ["assets/entry.js"],
|
|
lazyFiles: ["assets/lazy.js"],
|
|
missingImports: [],
|
|
},
|
|
missingOutputs: [],
|
|
thresholds: { initialJsGzipBytes: 60, lazyChunkGzipBytes: 45 },
|
|
results: {
|
|
initialPassed: true,
|
|
lazyResults: [
|
|
{ path: "assets/lazy.js", gzipBytes: 40, threshold: 45, passed: true },
|
|
],
|
|
passed: true,
|
|
},
|
|
fixtures: [
|
|
{ name: "initial-js-over-budget", passed: true },
|
|
{ name: "lazy-chunk-over-budget", passed: true },
|
|
],
|
|
passed: true,
|
|
} as const;
|
|
|
|
describe("bundle artifact contracts", () => {
|
|
it("separates the raw output inventory from final budget evidence", () => {
|
|
expect(bundleOutputInventoryArtifactSchema.parse(inventory)).toEqual(inventory);
|
|
expect(() => bundleOutputInventoryArtifactSchema.parse(completed)).toThrow();
|
|
expect(bundlePerformanceArtifactSchema.parse(completed)).toEqual(completed);
|
|
expect(() => bundlePerformanceArtifactSchema.parse(inventory)).toThrow();
|
|
});
|
|
|
|
it.each([
|
|
["initial total", { measurements: { ...completed.measurements, initialJsGzipBytes: 49 } }],
|
|
["lazy classification", { classification: { ...completed.classification, lazyFiles: [] } }],
|
|
["missing output", { missingOutputs: ["assets/missing.js"], passed: true }],
|
|
["threshold result", { results: { ...completed.results, initialPassed: false } }],
|
|
["lazy result", { results: { ...completed.results, lazyResults: [] } }],
|
|
["fixture identity", { fixtures: [{ name: "other", passed: true }, completed.fixtures[1]] }],
|
|
["overall result", { passed: false }],
|
|
] as const)("rejects inconsistent %s evidence", (_name, mutation) => {
|
|
expect(() =>
|
|
bundlePerformanceArtifactSchema.parse({ ...completed, ...mutation })
|
|
).toThrow();
|
|
});
|
|
|
|
it("publishes final evidence only through the validated atomic writer", async () => {
|
|
const source = await readFile("scripts/check-bundle.ts", "utf8");
|
|
expect(source).toContain("bundleOutputInventoryArtifactSchema.parse");
|
|
expect(source).toContain("writeValidatedJsonArtifact");
|
|
expect(source).not.toMatch(/\bwriteFile\s*\(/u);
|
|
});
|
|
});
|