fix: address Copilot review round 21 — seed a nested object's own union branch

collectSchemaDefaults recursed only when a nested object declared `properties`
directly, so one keeping its fields on a composition branch was skipped — while
SchemaForm rendered that branch and displayed its read-only discriminator. The
constant was shown and never submitted, and the server rejected the call. The
recursion now gates on declaresAnyFields.

Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
cliffhall 2026-08-26 07:41:22 -04:00
commit 92e485ab82

View file

@ -457,6 +457,37 @@ describe("root composition (#2123)", () => {
expect(Object.hasOwn(seeded, "__proto__")).toBe(true);
});
it("seeds defaults from a nested object's own union branch", () => {
// The nested form renders that branch, so its read-only discriminator has
// to reach the submitted values too.
expect(
collectSchemaDefaults({
type: "object",
properties: {
config: {
type: "object",
anyOf: [
{
type: "object",
properties: {
kind: { type: "string", const: "email" },
address: { type: "string" },
},
},
{
type: "object",
properties: {
kind: { type: "string", const: "sms" },
phone: { type: "string" },
},
},
],
},
},
}),
).toEqual({ config: { kind: "email" } });
});
it("re-applies a nested object's constants", () => {
// The overlay replaces the whole nested object rather than merging into it,
// so a link naming `{ config: { kind: "sms" } }` would otherwise slip past