149 lines
3.8 KiB
TypeScript
149 lines
3.8 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
|
|
import { classifyGateStepResult } from "../../scripts/lib/ci-step-result.ts";
|
|
|
|
describe("CI gate step result classification", () => {
|
|
it("accepts a negative fixture only with its exact exit and diagnostic identity", () => {
|
|
expect(
|
|
classifyGateStepResult(
|
|
{
|
|
kind: "fail",
|
|
expectedExitCode: 2,
|
|
expectedDiagnosticId: "error TS2322:",
|
|
},
|
|
{
|
|
status: 2,
|
|
signal: null,
|
|
stdout: "fixture.ts(1,1): error TS2322: incompatible type\n",
|
|
stderr: "",
|
|
},
|
|
),
|
|
).toEqual({ kind: "EXPECTED_FAILURE", expectationMet: true });
|
|
});
|
|
|
|
it("rejects a negative fixture with the wrong non-zero exit code", () => {
|
|
expect(
|
|
classifyGateStepResult(
|
|
{
|
|
kind: "fail",
|
|
expectedExitCode: 2,
|
|
expectedDiagnosticId: "error TS2322:",
|
|
},
|
|
{
|
|
status: 1,
|
|
signal: null,
|
|
stdout: "fixture.ts(1,1): error TS2322: incompatible type\n",
|
|
stderr: "",
|
|
},
|
|
),
|
|
).toEqual({ kind: "UNEXPECTED_EXIT", expectationMet: false });
|
|
});
|
|
|
|
it("rejects a negative fixture without the exact case-sensitive diagnostic identity", () => {
|
|
expect(
|
|
classifyGateStepResult(
|
|
{
|
|
kind: "fail",
|
|
expectedExitCode: 2,
|
|
expectedDiagnosticId: "error TS2322:",
|
|
},
|
|
{
|
|
status: 2,
|
|
signal: null,
|
|
stdout: "fixture.ts(1,1): error ts2322: incompatible type\n",
|
|
stderr: "",
|
|
},
|
|
),
|
|
).toEqual({ kind: "UNEXPECTED_DIAGNOSTIC", expectationMet: false });
|
|
});
|
|
|
|
it("matches an exact diagnostic identity emitted on stderr", () => {
|
|
expect(
|
|
classifyGateStepResult(
|
|
{
|
|
kind: "fail",
|
|
expectedExitCode: 1,
|
|
expectedDiagnosticId: "Risk coverage failed:",
|
|
},
|
|
{
|
|
status: 1,
|
|
signal: null,
|
|
stdout: "",
|
|
stderr: "Risk coverage failed:\n- expected fixture finding\n",
|
|
},
|
|
),
|
|
).toEqual({ kind: "EXPECTED_FAILURE", expectationMet: true });
|
|
});
|
|
|
|
it.each(["ENOENT", "EACCES", "ETIMEDOUT", "ENOBUFS"])(
|
|
"never treats spawn infrastructure error %s as an expected negative fixture",
|
|
(code) => {
|
|
expect(
|
|
classifyGateStepResult(
|
|
{
|
|
kind: "fail",
|
|
expectedExitCode: 1,
|
|
expectedDiagnosticId: "fixture failed:",
|
|
},
|
|
{
|
|
status: null,
|
|
signal: null,
|
|
stdout: "",
|
|
stderr: "",
|
|
error: { code },
|
|
},
|
|
),
|
|
).toEqual({
|
|
kind: "INFRASTRUCTURE_FAILURE",
|
|
expectationMet: false,
|
|
detail: code,
|
|
});
|
|
},
|
|
);
|
|
|
|
it("treats a code-less spawn error as infrastructure failure", () => {
|
|
expect(
|
|
classifyGateStepResult(
|
|
{
|
|
kind: "fail",
|
|
expectedExitCode: 1,
|
|
expectedDiagnosticId: "fixture failed:",
|
|
},
|
|
{
|
|
status: 1,
|
|
signal: null,
|
|
stdout: "",
|
|
stderr: "fixture failed:\n",
|
|
error: {},
|
|
},
|
|
),
|
|
).toEqual({
|
|
kind: "INFRASTRUCTURE_FAILURE",
|
|
expectationMet: false,
|
|
detail: "SPAWN_ERROR",
|
|
});
|
|
});
|
|
|
|
it("treats a signal-terminated or status-less child as infrastructure failure", () => {
|
|
expect(
|
|
classifyGateStepResult(
|
|
{
|
|
kind: "fail",
|
|
expectedExitCode: 1,
|
|
expectedDiagnosticId: "fixture failed:",
|
|
},
|
|
{
|
|
status: null,
|
|
signal: "SIGTERM",
|
|
stdout: "",
|
|
stderr: "",
|
|
},
|
|
),
|
|
).toEqual({
|
|
kind: "INFRASTRUCTURE_FAILURE",
|
|
expectationMet: false,
|
|
detail: "SIGTERM",
|
|
});
|
|
});
|
|
});
|