57 lines
1.6 KiB
JavaScript
57 lines
1.6 KiB
JavaScript
import { describe, expect, it } from "vitest";
|
|
|
|
import {
|
|
evaluatePromotionReadiness,
|
|
PROMOTION_FORMULA,
|
|
} from "../../src/application/policies/promotion-readiness.js";
|
|
|
|
const allGateIds = Object.values(PROMOTION_FORMULA).flat();
|
|
const passing =
|
|
/** @type {Record<string, "PASS" | "FAIL" | "UNVERIFIED">} */ (
|
|
Object.fromEntries(allGateIds.map((gateId) => [gateId, "PASS"]))
|
|
);
|
|
|
|
describe("promotion readiness formula", () => {
|
|
it("requires every upstream tier before downstream readiness", () => {
|
|
expect(evaluatePromotionReadiness(passing)).toEqual({
|
|
MERGE_READY: true,
|
|
RELEASE_READY: true,
|
|
PROD_PROMOTION_READY: true,
|
|
FIELD_SLO_READY: true,
|
|
DOCUMENTATION_READY: true,
|
|
});
|
|
});
|
|
|
|
it.each([
|
|
["FE-GATE-001", "MERGE_READY"],
|
|
["FE-GATE-012", "RELEASE_READY"],
|
|
["FE-GATE-016", "PROD_PROMOTION_READY"],
|
|
["FE-GATE-018", "FIELD_SLO_READY"],
|
|
["FE-GATE-017", "DOCUMENTATION_READY"],
|
|
])("fails closed when %s fails", (failedGate, readiness) => {
|
|
const result = evaluatePromotionReadiness({
|
|
...passing,
|
|
[failedGate]: "FAIL",
|
|
});
|
|
const readinessKey =
|
|
/** @type {keyof ReturnType<typeof evaluatePromotionReadiness>} */ (
|
|
readiness
|
|
);
|
|
expect(result[readinessKey]).toBe(false);
|
|
});
|
|
|
|
it("does not treat missing or unverified gates as pass", () => {
|
|
expect(
|
|
evaluatePromotionReadiness({
|
|
...passing,
|
|
"FE-GATE-009": "UNVERIFIED",
|
|
}),
|
|
).toMatchObject({
|
|
MERGE_READY: false,
|
|
RELEASE_READY: false,
|
|
PROD_PROMOTION_READY: false,
|
|
FIELD_SLO_READY: false,
|
|
});
|
|
});
|
|
});
|