96 lines
3.3 KiB
TypeScript
96 lines
3.3 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
|
|
import { isCliOperationFailure } from "./cliLogging.js";
|
|
import {
|
|
analysisCliErrorEnvelopeSchema,
|
|
analysisErrorProjectionSchema,
|
|
} from "./contracts/errorSchemas.js";
|
|
import { AnalysisInputError } from "./domain/analysisErrorCore.js";
|
|
import { projectAnalysisError } from "./domain/analysisErrorProjection.js";
|
|
|
|
const projection = projectAnalysisError(new AnalysisInputError("test-input"));
|
|
const envelope = { error: "Application workflow failed", ...projection };
|
|
|
|
describe("CLI JSON input failure recognition", () => {
|
|
it.each([
|
|
{},
|
|
{ input_path: "input.json" },
|
|
{ input_reason: "invalid-json" },
|
|
{ input_path: "input.json", input_reason: "invalid-json" },
|
|
{ input_path: "missing.json", input_reason: "read-failed" },
|
|
{ input_path: "large.json", input_reason: "too-large" },
|
|
{ input_path: "", input_reason: "read-failed" },
|
|
])("recognizes a complete envelope with metadata %j", (metadata) => {
|
|
const value = { ...envelope, ...metadata };
|
|
expect(analysisCliErrorEnvelopeSchema.parse(value)).toEqual(value);
|
|
expect(isCliOperationFailure(value)).toBe(true);
|
|
});
|
|
|
|
it.each([
|
|
{ input_path: null },
|
|
{ input_path: 1 },
|
|
{ input_path: ["input.json"] },
|
|
{ input_reason: null },
|
|
{ input_reason: 1 },
|
|
{ input_reason: "" },
|
|
{ input_reason: "unknown" },
|
|
{ input_reason: ["invalid-json"] },
|
|
{ unknown_field: "extra" },
|
|
{ input_path: "input.json", input_reason: "invalid-json", extra: true },
|
|
{ error: "" },
|
|
{ error: 1 },
|
|
{ retryable: "false" },
|
|
{ remediation: { action: "retry", extra: true } },
|
|
])("rejects malformed or unknown envelope fields %j", (changes) => {
|
|
const value = { ...envelope, ...changes };
|
|
expect(analysisCliErrorEnvelopeSchema.safeParse(value).success).toBe(false);
|
|
expect(isCliOperationFailure(value)).toBe(false);
|
|
});
|
|
|
|
it.each(["code", "category", "message", "retryable", "remediation"])(
|
|
"requires the complete canonical projection, including %s",
|
|
(field) => {
|
|
const value = Object.fromEntries(
|
|
Object.entries({ ...envelope, input_reason: "invalid-json" }).filter(
|
|
([key]) => key !== field,
|
|
),
|
|
);
|
|
expect(analysisCliErrorEnvelopeSchema.safeParse(value).success).toBe(
|
|
false,
|
|
);
|
|
expect(isCliOperationFailure(value)).toBe(false);
|
|
},
|
|
);
|
|
|
|
it.each([
|
|
{ error: "ordinary data" },
|
|
{ code: "invalid_request", message: "ordinary data" },
|
|
{
|
|
error: "ordinary data",
|
|
code: "invalid_request",
|
|
input_path: "input.json",
|
|
},
|
|
{ error: { code: "invalid_request" } },
|
|
{ result: envelope },
|
|
{ input_path: "input.json", input_reason: "invalid-json" },
|
|
null,
|
|
[],
|
|
])("keeps ordinary or incomplete error-like data successful: %j", (value) => {
|
|
expect(isCliOperationFailure(value)).toBe(false);
|
|
});
|
|
|
|
it("keeps CLI metadata out of the strict canonical error schema", () => {
|
|
expect(analysisErrorProjectionSchema.parse(projection)).toEqual(projection);
|
|
for (const metadata of [
|
|
{ error: "Application workflow failed" },
|
|
{ input_path: "input.json" },
|
|
{ input_reason: "invalid-json" },
|
|
{ extra: true },
|
|
])
|
|
expect(
|
|
analysisErrorProjectionSchema.safeParse({ ...projection, ...metadata })
|
|
.success,
|
|
).toBe(false);
|
|
});
|
|
});
|