fix: address composite input contract review

This commit is contained in:
lda
2026-08-13 21:44:29 +07:00 Verified
parent 1bb684bfcd
commit cca1be891f
18 changed files with 455 additions and 172 deletions
@@ -28,6 +28,38 @@ describe("CapabilityNodeForm", () => {
expect(value.inputBindings[0]).toHaveProperty("expression.kind", "array");
});
it("preserves rehydrated expression bindings when the legacy form is submitted", async () => {
const user = userEvent.setup();
const submissions: CapabilityNodeFormValue[] = [];
const expressionBinding = {
target: "request",
expression: {
kind: "array",
items: [
{ kind: "path", path: "state.foo" },
{ kind: "literal", value: "wowcool" },
],
},
} as const;
render(
<CapabilityNodeForm
capabilityName="wf.std.concat"
initialValue={{ stepId: "concat", inputBindings: [expressionBinding] }}
inputSchema={{ type: "object", properties: {} }}
onSubmit={(value) => { submissions.push(value); }}
submitLabel="Save node"
/>,
);
await user.click(screen.getByRole("button", { name: "Save node" }));
expect(submissions).toHaveLength(1);
expect(
submissions[0]?.inputBindings?.filter((binding) => "expression" in binding),
).toEqual([expressionBinding]);
});
it("submits explicit node metadata and serialized schema bindings", async () => {
const user = userEvent.setup();
const submissions: unknown[] = [];
@@ -105,9 +105,13 @@ export const CapabilityNodeForm = ({
: {}),
...(retry === undefined ? {} : { retry }),
...(timeoutSeconds === undefined ? {} : { timeoutSeconds }),
// The legacy schema editor cannot deserialize expression rows. Keep the
// rehydrated rows alongside its fresh simple bindings until Task 6 owns
// expression editing, rather than silently deleting them on save.
inputBindings: [
...result.bindings,
...result.literalBindings,
...(initialValue?.inputBindings?.filter((binding) => "expression" in binding) ?? []),
],
...(routeOutcomes.length > 0
? {