From a11ee998184e6a9579fb6b43baea1c4427eb86fb Mon Sep 17 00:00:00 2001 From: olaservo Date: Sat, 27 Sep 2025 21:17:17 -0700 Subject: [PATCH] Update ToolsTab tests to require JSON fields and adjust default value generation for optional types --- .../components/__tests__/ToolsTab.test.tsx | 25 ++++++++----- .../src/utils/__tests__/schemaUtils.test.ts | 36 ++++++++++++++----- client/src/utils/schemaUtils.ts | 6 ++-- 3 files changed, 48 insertions(+), 19 deletions(-) diff --git a/client/src/components/__tests__/ToolsTab.test.tsx b/client/src/components/__tests__/ToolsTab.test.tsx index 290605dd..a50f62df 100644 --- a/client/src/components/__tests__/ToolsTab.test.tsx +++ b/client/src/components/__tests__/ToolsTab.test.tsx @@ -644,6 +644,7 @@ describe("ToolsTab", () => { description: "Tool with JSON parameters", inputSchema: { type: "object" as const, + required: ["config", "data"], // Make them required so they render as form fields properties: { config: { type: "object" as const, @@ -693,15 +694,16 @@ describe("ToolsTab", () => { callTool: mockCallTool, }); - // Find JSON editor textareas + // Find JSON editor textareas (should have one for each required field: config and data) const textareas = screen.getAllByRole("textbox"); + expect(textareas.length).toBe(2); - // Enter valid JSON in the first textarea + // Enter valid JSON in each textarea fireEvent.change(textareas[0], { - target: { - value: - '{ "config": { "setting": "value" }, "data": ["item1", "item2"] }', - }, + target: { value: '{ "setting": "value" }' }, + }); + fireEvent.change(textareas[1], { + target: { value: '["item1", "item2"]' }, }); // Wait for debounced updates @@ -799,9 +801,16 @@ describe("ToolsTab", () => { }); const textareas = screen.getAllByRole("textbox"); + expect(textareas.length).toBe(2); - // Clear the textarea (empty JSON should be valid) - fireEvent.change(textareas[0], { target: { value: "" } }); + // Clear both textareas (empty JSON should be valid) + fireEvent.change(textareas[0], { target: { value: "{}" } }); + fireEvent.change(textareas[1], { target: { value: "[]" } }); + + // Wait for debounced updates + await act(async () => { + await new Promise((resolve) => setTimeout(resolve, 350)); + }); // Try to run the tool const runButton = screen.getByRole("button", { name: /run tool/i }); diff --git a/client/src/utils/__tests__/schemaUtils.test.ts b/client/src/utils/__tests__/schemaUtils.test.ts index 0ecd8075..0e832b09 100644 --- a/client/src/utils/__tests__/schemaUtils.test.ts +++ b/client/src/utils/__tests__/schemaUtils.test.ts @@ -39,12 +39,12 @@ describe("generateDefaultValue", () => { ).toBe(false); }); - test("generates default array", () => { - expect(generateDefaultValue({ type: "array" })).toEqual([]); + test("generates undefined for optional array", () => { + expect(generateDefaultValue({ type: "array" })).toBe(undefined); }); - test("generates default empty object", () => { - expect(generateDefaultValue({ type: "object" })).toEqual({}); + test("generates undefined for optional object", () => { + expect(generateDefaultValue({ type: "object" })).toBe(undefined); }); test("generates default null for unknown types", () => { @@ -52,12 +52,32 @@ describe("generateDefaultValue", () => { expect(generateDefaultValue({ type: "unknown" })).toBe(undefined); }); - test("generates empty array for non-required array", () => { - expect(generateDefaultValue({ type: "array" })).toEqual([]); + test("generates empty array for required array", () => { + const parentSchema = { required: ["testArray"] }; + expect( + generateDefaultValue({ type: "array" }, "testArray", parentSchema), + ).toEqual([]); }); - test("generates empty object for non-required object", () => { - expect(generateDefaultValue({ type: "object" })).toEqual({}); + test("generates undefined for non-required array", () => { + const parentSchema = { required: ["otherField"] }; + expect( + generateDefaultValue({ type: "array" }, "testArray", parentSchema), + ).toBe(undefined); + }); + + test("generates empty object for required object", () => { + const parentSchema = { required: ["testObject"] }; + expect( + generateDefaultValue({ type: "object" }, "testObject", parentSchema), + ).toEqual({}); + }); + + test("generates undefined for non-required object", () => { + const parentSchema = { required: ["otherField"] }; + expect( + generateDefaultValue({ type: "object" }, "testObject", parentSchema), + ).toBe(undefined); }); test("generates undefined for non-required primitive types", () => { diff --git a/client/src/utils/schemaUtils.ts b/client/src/utils/schemaUtils.ts index 7a175142..4ad8e8ca 100644 --- a/client/src/utils/schemaUtils.ts +++ b/client/src/utils/schemaUtils.ts @@ -109,9 +109,9 @@ export function generateDefaultValue( case "boolean": return isRequired ? false : undefined; case "array": - return []; + return isRequired ? [] : undefined; case "object": { - if (!schema.properties) return {}; + if (!schema.properties) return isRequired ? {} : undefined; const obj: JsonObject = {}; // Only include properties that are required according to the schema's required array @@ -123,7 +123,7 @@ export function generateDefaultValue( } } }); - return obj; + return isRequired ? obj : Object.keys(obj).length > 0 ? obj : undefined; } case "null": return null;