From 60fbed8c15010923d46b11349bad7a8a8fb392f8 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 28 Oct 2026 10:14:03 +0000 Subject: [PATCH 1/2] feat(field-toolbar): show the Edit button for Boolean fields Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01YU96SVM9VXkfjSbSeoFdZ4 --- .../components/__test__/fieldToolbar.test.tsx | 136 ++++++++++++++++++ .../components/icons/fields/index.ts | 1 + src/visualBuilder/utils/constants.ts | 1 + 3 files changed, 138 insertions(+) diff --git a/src/visualBuilder/components/__test__/fieldToolbar.test.tsx b/src/visualBuilder/components/__test__/fieldToolbar.test.tsx index 8105623d..a8a91ea4 100644 --- a/src/visualBuilder/components/__test__/fieldToolbar.test.tsx +++ b/src/visualBuilder/components/__test__/fieldToolbar.test.tsx @@ -797,6 +797,142 @@ describe("FieldToolbarComponent", () => { }); }); + describe("Boolean field toolbar", () => { + const booleanSchema = { + data_type: "boolean", + display_name: "Featured", + uid: "featured", + field_metadata: { description: "", default_value: false }, + multiple: false, + mandatory: false, + unique: false, + non_localizable: false, + } as unknown as ISchemaFieldMap; + + const fileSchema = { + data_type: "file", + display_name: "Cover", + uid: "cover", + field_metadata: { description: "", rich_text_type: "" }, + multiple: false, + mandatory: false, + unique: false, + non_localizable: false, + } as unknown as ISchemaFieldMap; + + const EDIT_ID = + "visual-builder__focused-toolbar__multiple-field-toolbar__edit-button"; + const TOOLBAR_ID = + "visual-builder__focused-toolbar__multiple-field-toolbar"; + + const booleanMetadata: CslpData = { + ...mockMultipleFieldMetadata, + fieldPath: "featured", + fieldPathWithIndex: "featured", + multipleFieldMetadata: { index: -1, parentDetails: null }, + instance: { fieldPathWithIndex: "featured" }, + }; + + const renderField = async ( + schema: ISchemaFieldMap, + fieldMetadata: CslpData + ) => { + vi.mocked(FieldSchemaMap.getFieldSchema).mockImplementation(() => + Promise.resolve(schema) + ); + const utils = render( + + ); + await act(async () => { + await new Promise((r) => setTimeout(r, 0)); + }); + return utils; + }; + + test("boolean field shows the edit button", async () => { + const { container } = await renderField( + booleanSchema, + booleanMetadata + ); + + expect( + await findByTestId(container, EDIT_ID, {}, { timeout: 1000 }) + ).toBeInTheDocument(); + }); + + test("clicking the edit button opens the edit modal with the field metadata", async () => { + const { container } = await renderField( + booleanSchema, + booleanMetadata + ); + + fireEvent.click( + await findByTestId(container, EDIT_ID, {}, { timeout: 1000 }) + ); + + expect(visualBuilderPostMessage?.send).toHaveBeenCalledWith( + VisualBuilderPostMessageEvents.OPEN_FIELD_EDIT_MODAL, + { fieldMetadata: booleanMetadata } + ); + }); + + test("edit button is disabled when the boolean field is disabled", async () => { + vi.mocked(isFieldDisabled).mockReturnValue({ + isDisabled: true, + reason: "", + } as ReturnType); + const { container } = await renderField( + booleanSchema, + booleanMetadata + ); + + expect( + await findByTestId(container, EDIT_ID, {}, { timeout: 1000 }) + ).toBeDisabled(); + }); + + test("boolean field has no replace button", async () => { + const { container } = await renderField( + booleanSchema, + booleanMetadata + ); + + await findByTestId(container, EDIT_ID, {}, { timeout: 1000 }); + expect( + container.querySelector( + '[data-testid="visual-builder-replace-boolean"]' + ) + ).not.toBeInTheDocument(); + }); + + test("a field type that is not editable in the modal keeps its toolbar without an edit button", async () => { + const { container } = await renderField(fileSchema, { + ...booleanMetadata, + fieldPath: "cover", + fieldPathWithIndex: "cover", + instance: { fieldPathWithIndex: "cover" }, + }); + + expect( + await findByTestId( + container, + "visual-builder-replace-file", + {}, + { timeout: 1000 } + ) + ).toBeInTheDocument(); + expect( + container.querySelector(`[data-testid="${TOOLBAR_ID}"]`) + ).toBeInTheDocument(); + expect( + container.querySelector(`[data-testid="${EDIT_ID}"]`) + ).not.toBeInTheDocument(); + }); + }); + describe("Taxonomy field toolbar", () => { const taxonomySchema = { data_type: "taxonomy", diff --git a/src/visualBuilder/components/icons/fields/index.ts b/src/visualBuilder/components/icons/fields/index.ts index a7ed0328..f655fead 100644 --- a/src/visualBuilder/components/icons/fields/index.ts +++ b/src/visualBuilder/components/icons/fields/index.ts @@ -13,4 +13,5 @@ export const fieldIcons: Partial> = { select: EditIcon, taxonomy: EditIcon, tags: EditIcon, + boolean: EditIcon, }; diff --git a/src/visualBuilder/utils/constants.ts b/src/visualBuilder/utils/constants.ts index 130b579a..3825c50e 100644 --- a/src/visualBuilder/utils/constants.ts +++ b/src/visualBuilder/utils/constants.ts @@ -48,6 +48,7 @@ export const ALLOWED_MODAL_EDITABLE_FIELD: FieldDataType[] = [ FieldDataType.SELECT, FieldDataType.TAXONOMY, FieldDataType.TAGS, + FieldDataType.BOOLEAN, ]; export const ALLOWED_REPLACE_FIELDS: FieldDataType[] = [ From 88b0ee256c36b4d75d162238d228eb7f3586680d Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 28 Oct 2026 10:50:23 +0000 Subject: [PATCH 2/2] test(field-toolbar): drop Boolean tests that other toolbar tests already cover Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01YU96SUpGdU5NuSX7N5UsA5 --- .../components/__test__/fieldToolbar.test.tsx | 53 ------------------- 1 file changed, 53 deletions(-) diff --git a/src/visualBuilder/components/__test__/fieldToolbar.test.tsx b/src/visualBuilder/components/__test__/fieldToolbar.test.tsx index a8a91ea4..44fc1791 100644 --- a/src/visualBuilder/components/__test__/fieldToolbar.test.tsx +++ b/src/visualBuilder/components/__test__/fieldToolbar.test.tsx @@ -809,21 +809,8 @@ describe("FieldToolbarComponent", () => { non_localizable: false, } as unknown as ISchemaFieldMap; - const fileSchema = { - data_type: "file", - display_name: "Cover", - uid: "cover", - field_metadata: { description: "", rich_text_type: "" }, - multiple: false, - mandatory: false, - unique: false, - non_localizable: false, - } as unknown as ISchemaFieldMap; - const EDIT_ID = "visual-builder__focused-toolbar__multiple-field-toolbar__edit-button"; - const TOOLBAR_ID = - "visual-builder__focused-toolbar__multiple-field-toolbar"; const booleanMetadata: CslpData = { ...mockMultipleFieldMetadata, @@ -863,22 +850,6 @@ describe("FieldToolbarComponent", () => { ).toBeInTheDocument(); }); - test("clicking the edit button opens the edit modal with the field metadata", async () => { - const { container } = await renderField( - booleanSchema, - booleanMetadata - ); - - fireEvent.click( - await findByTestId(container, EDIT_ID, {}, { timeout: 1000 }) - ); - - expect(visualBuilderPostMessage?.send).toHaveBeenCalledWith( - VisualBuilderPostMessageEvents.OPEN_FIELD_EDIT_MODAL, - { fieldMetadata: booleanMetadata } - ); - }); - test("edit button is disabled when the boolean field is disabled", async () => { vi.mocked(isFieldDisabled).mockReturnValue({ isDisabled: true, @@ -907,30 +878,6 @@ describe("FieldToolbarComponent", () => { ) ).not.toBeInTheDocument(); }); - - test("a field type that is not editable in the modal keeps its toolbar without an edit button", async () => { - const { container } = await renderField(fileSchema, { - ...booleanMetadata, - fieldPath: "cover", - fieldPathWithIndex: "cover", - instance: { fieldPathWithIndex: "cover" }, - }); - - expect( - await findByTestId( - container, - "visual-builder-replace-file", - {}, - { timeout: 1000 } - ) - ).toBeInTheDocument(); - expect( - container.querySelector(`[data-testid="${TOOLBAR_ID}"]`) - ).toBeInTheDocument(); - expect( - container.querySelector(`[data-testid="${EDIT_ID}"]`) - ).not.toBeInTheDocument(); - }); }); describe("Taxonomy field toolbar", () => {