Files
clean-architecture-frontend…/tests/unit/release-artifacts.test.ts
T
2026-08-01 19:39:59 +09:00

130 lines
3.7 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
parseBuildManifestArtifact,
parseReleaseArtifact,
parseRuntimeConfigArtifact,
projectReleaseTokens,
} from "../../scripts/contracts/release-artifacts.ts";
const EMPTY_CONTRACT_SET_DIGEST =
"sha256:ad6aab71fea6a9ff87cbd170b984b339965afc90d85bb57f87801c9e0c020da2";
const releaseV2 = {
schemaVersion: 2,
appVersion: "0.1.0",
buildId: "build-a",
commitSha: "abc1234",
configSchemaVersion: "2.0",
assetManifestHash: "asset-hash",
releaseId: "release-a",
builtAt: "2026-08-01T00:00:00.000Z",
routeChunks: { "route-home": "assets/home.js" },
contractSet: {
setAlgorithm: "CA_CONTRACT_SET_V1",
setDigest: EMPTY_CONTRACT_SET_DIGEST,
packages: [],
},
} as const;
const buildManifest = {
schemaVersion: 1,
buildId: "build-a",
commitSha: "abc1234",
releaseId: "release-a",
moduleInventoryHash: "inventory-hash",
generatedAt: "2026-08-01T00:00:00.000Z",
buildContext: {
nodeVersion: "v24.14.0",
packageManagerVersion: "11.17.0",
runnerImage: "linux-x64",
sourceDateEpoch: null,
},
outputs: {
directory: "dist",
viteManifest: "dist/.vite/manifest.json",
moduleInventory: "artifacts/quality/vite-module-inventory.json",
routeChunks: { "route-home": "assets/home.js" },
runtimeConfigSchema: "dist/runtime-config.schema.json",
},
} as const;
describe("release artifact contracts", () => {
it("projects the nested V2 contract-set digest without a legacy scalar", () => {
const release = parseReleaseArtifact(releaseV2);
expect(projectReleaseTokens(release)).toMatchObject({
schemaVersion: 2,
buildId: "build-a",
contractSetDigest: EMPTY_CONTRACT_SET_DIGEST,
});
expect(projectReleaseTokens(release)).not.toHaveProperty(
"apiContractVersion",
);
});
it("projects the legacy scalar only for V1", () => {
const { contractSet: _contractSet, ...releaseWithoutContractSet } = releaseV2;
void _contractSet;
const release = parseReleaseArtifact({
...releaseWithoutContractSet,
schemaVersion: 1,
configSchemaVersion: "1",
apiContractVersion: "1.4.0",
});
expect(projectReleaseTokens(release)).toMatchObject({
schemaVersion: 1,
apiContractVersion: "1.4.0",
});
expect(projectReleaseTokens(release)).not.toHaveProperty(
"contractSetDigest",
);
});
it("rejects a V2 release carrying the removed scalar", () => {
expect(() =>
parseReleaseArtifact({
...releaseV2,
apiContractVersion: "1",
}),
).toThrow();
});
it("accepts the exact build manifest emitted by the generator", () => {
expect(parseBuildManifestArtifact(buildManifest)).toEqual(buildManifest);
});
it("rejects unknown build manifest output fields", () => {
expect(() =>
parseBuildManifestArtifact({
...buildManifest,
outputs: { ...buildManifest.outputs, unexpected: "value" },
}),
).toThrow();
});
it("accepts Runtime Config V2 without a legacy API scalar", () => {
expect(
parseRuntimeConfigArtifact({
APP_ENV: "local",
API_BASE_URL: "http://localhost:8080/",
REQUEST_TIMEOUT_MS: 10_000,
MAX_RETRY_ATTEMPTS: 2,
TELEMETRY_ENABLED: false,
AUTH_MODE: "demo",
CONFIG_SCHEMA_VERSION: "2.0",
RELEASE_MANIFEST_URL: "/release-manifest.json",
BUILD_ID: "build-a",
RELEASE_ID: "release-a",
CAPABILITY_OVERRIDES: {
REALTIME: "DEFAULT",
WEB_WORKER: "DEFAULT",
SERVICE_WORKER: "DEFAULT",
OFFLINE_COMMANDS: "DEFAULT",
},
}),
).not.toHaveProperty("API_CONTRACT_VERSION");
});
});