From aaf5c15ca78fd55b674f9f210db55db1a03318e4 Mon Sep 17 00:00:00 2001 From: baokimho Date: Sun, 13 Sep 2026 03:04:21 +0300 Subject: [PATCH 1/2] fix(webchat): keep embedding origin stable across rerenders --- .../webchat-message-input-origin.test.tsx | 176 ++++++++++++++++++ .../webchat-message-input.tsx | 23 ++- 2 files changed, 195 insertions(+), 4 deletions(-) create mode 100644 apps/builder/__tests__/webchat-message-input-origin.test.tsx diff --git a/apps/builder/__tests__/webchat-message-input-origin.test.tsx b/apps/builder/__tests__/webchat-message-input-origin.test.tsx new file mode 100644 index 0000000000..ebb50e9961 --- /dev/null +++ b/apps/builder/__tests__/webchat-message-input-origin.test.tsx @@ -0,0 +1,176 @@ +// @vitest-environment jsdom + +import { act, type ReactNode } from "react" +import { createRoot, type Root } from "react-dom/client" +import { afterEach, beforeEach, describe, expect, test, vi } from "vitest" + +const mocks = vi.hoisted(() => ({ + submittedInputs: [] as Array>, + actionOptions: null as { + onExecute: (args: { input: Record }) => void + onSuccess: (args: { data: null }) => void + } | null, + defaultValues: null as Record | null, + submit: null as (() => Promise) | null, + clientEmbeddingOrigin: "https://www.example.com" as string | null, +})) + +vi.mock("@/features/messages/actions/create-webchat-message.action", () => ({ + createWebchatMessageAction: {}, +})) + +vi.mock("@next-safe-action/adapter-react-hook-form/hooks", () => ({ + useHookFormAction: vi.fn((_action, _resolver, options) => { + mocks.actionOptions = options.actionProps + mocks.defaultValues = options.formProps.defaultValues + + const form = { + control: {}, + formState: { isValid: true, isSubmitting: false }, + setValue: vi.fn(), + reset: vi.fn(), + } + + const submit = async () => { + const input = { + ...mocks.defaultValues, + text: "hello", + } + mocks.submittedInputs.push(input) + mocks.actionOptions?.onExecute({ input }) + mocks.actionOptions?.onSuccess({ data: null }) + } + mocks.submit = submit + + return { + form, + handleSubmitWithAction: submit, + resetFormAndAction: vi.fn(), + } + }), +})) + +vi.mock("@/features/integration-webchat/lib/authorized-domain", () => ({ + getClientEmbeddingOrigin: () => mocks.clientEmbeddingOrigin, +})) + +vi.mock( + "@/features/integration-webchat/providers/store/guest-session-provider", + () => ({ + useGuestSessionStore: ( + selector: (state: Record) => unknown, + ) => + selector({ + appendMessage: vi.fn(), + guestConversationId: "guest-1", + sendMessage: vi.fn(), + }), + }), +) + +vi.mock("@chatbotx.io/ui/components/ui/form", () => ({ + Form: ({ children }: { children: ReactNode }) => children, +})) + +vi.mock("@chatbotx.io/ui/components/ui/textarea", () => ({ + Textarea: (props: Record) =>