mirror of
https://github.com/morluto/rea
synced 2026-10-26 06:16:17 -04:00
fix(validation): retain unmatched union correction details
Preserve actionable field paths and schema-declared variants for unknown or missing discriminators. Closes #1421. Refs #1065.
This commit is contained in:
@@ -35,7 +35,23 @@ const projectIssue = (
|
||||
typeof part === "string" || typeof part === "number" ? [part] : [],
|
||||
);
|
||||
// Branch issue paths are relative to the union; branches often agree.
|
||||
if (issue.code === "invalid_union")
|
||||
if (issue.code === "invalid_union") {
|
||||
// Unmatched discriminators and ambiguous unions have no branch issues.
|
||||
// Keep their outer failure instead of flattening it into an empty list.
|
||||
if (issue.errors.length === 0) {
|
||||
const expected =
|
||||
"options" in issue ? issue.options?.filter(isSafeExpected) : undefined;
|
||||
return [
|
||||
{
|
||||
path,
|
||||
reason:
|
||||
valueAtPath(input, path) === undefined
|
||||
? "missing_argument"
|
||||
: "invalid_value",
|
||||
...(expected === undefined ? {} : { expected }),
|
||||
},
|
||||
];
|
||||
}
|
||||
return uniqueIssues(
|
||||
issue.errors.flatMap((branch) =>
|
||||
branch.flatMap((branchIssue) =>
|
||||
@@ -46,6 +62,7 @@ const projectIssue = (
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
if (issue.code === "invalid_key")
|
||||
return issue.issues.flatMap((keyIssue) =>
|
||||
projectIssue(
|
||||
|
||||
@@ -80,3 +80,48 @@ cliTest("rejects a request that omits source", async ({ cli }) => {
|
||||
details: { operation: "inspect-analysis-view" },
|
||||
});
|
||||
});
|
||||
|
||||
for (const [view, reason] of [
|
||||
[{ kind: "unknown-view" }, "invalid_value"],
|
||||
[{}, "missing_argument"],
|
||||
] as const) {
|
||||
cliTest(
|
||||
`reports correction details for ${reason} view kind`,
|
||||
async ({ cli }) => {
|
||||
const root = await createTestTempDirectory("rea-view-variant-");
|
||||
const input = join(root, "view.json");
|
||||
await writeFile(
|
||||
input,
|
||||
JSON.stringify({
|
||||
source: {
|
||||
kind: "inline",
|
||||
evidence: analysisViewLayoutEvidence(),
|
||||
},
|
||||
view,
|
||||
}),
|
||||
);
|
||||
const result = await cli.run({
|
||||
arguments: ["inspect-analysis-view", input, "--json"],
|
||||
environment: {
|
||||
HOME: root,
|
||||
XDG_CONFIG_HOME: root,
|
||||
XDG_CACHE_HOME: root,
|
||||
},
|
||||
});
|
||||
expect(result.exitCode).toBe(1);
|
||||
expect(result.json).toMatchObject({
|
||||
code: "invalid_request",
|
||||
details: {
|
||||
issues: [
|
||||
{
|
||||
path: ["view", "kind"],
|
||||
reason,
|
||||
expected: expect.arrayContaining(["summary", "page"]),
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
expect(JSON.stringify(result.json)).not.toContain("unknown-view");
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user