From d5c1da833dd2f7b1c0ff7587df85a36c8e7910b9 Mon Sep 17 00:00:00 2001 From: George Olson Date: Thu, 24 Oct 2024 14:19:43 -0700 Subject: [PATCH 1/4] Attempt to add test to chatbot container component --- .../ChatBotContainer.test.tsx | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 __tests__/components/ChatBotContainer/ChatBotContainer.test.tsx diff --git a/__tests__/components/ChatBotContainer/ChatBotContainer.test.tsx b/__tests__/components/ChatBotContainer/ChatBotContainer.test.tsx new file mode 100644 index 00000000..a274a120 --- /dev/null +++ b/__tests__/components/ChatBotContainer/ChatBotContainer.test.tsx @@ -0,0 +1,85 @@ +import React from "react"; +import { render, screen } from "@testing-library/react"; +import "@testing-library/jest-dom"; +import ChatBotContainer from "../../../src/components/ChatBotContainer"; +import { useButtonInternal } from "../../../src/hooks/internal/useButtonsInternal"; +import { useChatWindowInternal } from "../../../src/hooks/internal/useChatWindowInternal"; +import { useIsDesktopInternal } from "../../../src/hooks/internal/useIsDesktopInternal"; +import { useBotStatesContext } from "../../../src/context/BotStatesContext"; +import { useSettingsContext } from "../../../src/context/SettingsContext"; +import { useStylesContext } from "../../../src/context/StylesContext"; +import { useBotRefsContext } from "../../../src/context/BotRefsContext"; + +// Mocking necessary hooks and context providers +jest.mock("../../../src/hooks/internal/useButtonsInternal"); +jest.mock("../../../src/hooks/internal/useChatWindowInternal"); +jest.mock("../../../src/hooks/internal/useIsDesktopInternal"); +jest.mock("../../../src/context/BotStatesContext"); +jest.mock("../../../src/context/SettingsContext"); +jest.mock("../../../src/context/StylesContext"); +jest.mock("../../../src/context/BotRefsContext"); + +describe("ChatBotContainer Component", () => { + beforeEach(() => { + (useButtonInternal as jest.Mock).mockReturnValue({ + headerButtons: [], + chatInputButtons: [], + footerButtons: [], + }); + + (useChatWindowInternal as jest.Mock).mockReturnValue({ + isChatWindowOpen: true, + chatScrollHeight: 100, + viewportHeight: 600, + viewportWidth: 300, + setChatScrollHeight: jest.fn(), + }); + + (useIsDesktopInternal as jest.Mock).mockReturnValue(true); + + (useBotStatesContext as jest.Mock).mockReturnValue({ + hasFlowStarted: false, + setHasFlowStarted: jest.fn(), + }); + + (useSettingsContext as jest.Mock).mockReturnValue({ + settings: { + general: { + showHeader: true, + showFooter: true, + showInputRow: true, + flowStartTrigger: "ON_CHATBOT_INTERACT", + desktopEnabled: true, + mobileEnabled: true, + }, + }, + }); + + (useStylesContext as jest.Mock).mockReturnValue({ + styles: { + chatWindowStyle: { background: 'white', color: 'black' }, + }, + }); + + (useBotRefsContext as jest.Mock).mockReturnValue({ + flowRef: { current: {} }, // Mocked flowRef + chatBodyRef: { current: document.createElement('div') }, + streamMessageMap: new Map(), + paramsInputRef: { current: null }, + keepVoiceOnRef: { current: false }, + }); + }); + + it("renders ChatBotContainer with header, body, input, and footer", () => { + render(); + + // Check if the header, body, input, and footer components are rendered + const headerButton = screen.getByText("Header Button"); + const inputButton = screen.getByText("Input Button"); + const footerButton = screen.getByText("Footer Button"); + + expect(headerButton).toBeInTheDocument(); + expect(inputButton).toBeInTheDocument(); + expect(footerButton).toBeInTheDocument(); + }); +}); From 5db5a3ec707bfe0965313b671c0b2155f1132cf1 Mon Sep 17 00:00:00 2001 From: George Olson Date: Tue, 29 Oct 2024 15:30:49 -0700 Subject: [PATCH 2/4] Successfully got test passing for ChatBotContainer --- .../ChatBotContainer/ChatBotContainer.test.tsx | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/__tests__/components/ChatBotContainer/ChatBotContainer.test.tsx b/__tests__/components/ChatBotContainer/ChatBotContainer.test.tsx index a274a120..37952608 100644 --- a/__tests__/components/ChatBotContainer/ChatBotContainer.test.tsx +++ b/__tests__/components/ChatBotContainer/ChatBotContainer.test.tsx @@ -9,8 +9,8 @@ import { useBotStatesContext } from "../../../src/context/BotStatesContext"; import { useSettingsContext } from "../../../src/context/SettingsContext"; import { useStylesContext } from "../../../src/context/StylesContext"; import { useBotRefsContext } from "../../../src/context/BotRefsContext"; +import { useNotificationInternal } from "../../../src/hooks/internal/useNotificationsInternal"; -// Mocking necessary hooks and context providers jest.mock("../../../src/hooks/internal/useButtonsInternal"); jest.mock("../../../src/hooks/internal/useChatWindowInternal"); jest.mock("../../../src/hooks/internal/useIsDesktopInternal"); @@ -18,6 +18,7 @@ jest.mock("../../../src/context/BotStatesContext"); jest.mock("../../../src/context/SettingsContext"); jest.mock("../../../src/context/StylesContext"); jest.mock("../../../src/context/BotRefsContext"); +jest.mock("../../../src/hooks/internal/useNotificationsInternal"); describe("ChatBotContainer Component", () => { beforeEach(() => { @@ -40,6 +41,10 @@ describe("ChatBotContainer Component", () => { (useBotStatesContext as jest.Mock).mockReturnValue({ hasFlowStarted: false, setHasFlowStarted: jest.fn(), + setUnreadCount: jest.fn(), + setTextAreaDisabled: jest.fn(), + setIsChatWindowOpen: jest.fn(), + setAudioToggledOn: jest.fn(), }); (useSettingsContext as jest.Mock).mockReturnValue({ @@ -62,18 +67,22 @@ describe("ChatBotContainer Component", () => { }); (useBotRefsContext as jest.Mock).mockReturnValue({ - flowRef: { current: {} }, // Mocked flowRef + flowRef: { current: {} }, chatBodyRef: { current: document.createElement('div') }, streamMessageMap: new Map(), paramsInputRef: { current: null }, keepVoiceOnRef: { current: false }, }); + + (useNotificationInternal as jest.Mock).mockReturnValue({ + audioContextRef: { current: {} }, + setUpNotifications: jest.fn(), + }); }); it("renders ChatBotContainer with header, body, input, and footer", () => { render(); - // Check if the header, body, input, and footer components are rendered const headerButton = screen.getByText("Header Button"); const inputButton = screen.getByText("Input Button"); const footerButton = screen.getByText("Footer Button"); From 0e820601f51f23f84d09dd165cc60c5154fb7fd0 Mon Sep 17 00:00:00 2001 From: George Olson Date: Tue, 29 Oct 2024 15:57:43 -0700 Subject: [PATCH 3/4] test: Added tests for ChatBotContainer with proper mocking --- .../ChatBotContainer.test.tsx | 145 ++++++++++++++++-- 1 file changed, 132 insertions(+), 13 deletions(-) diff --git a/__tests__/components/ChatBotContainer/ChatBotContainer.test.tsx b/__tests__/components/ChatBotContainer/ChatBotContainer.test.tsx index 37952608..3e40e270 100644 --- a/__tests__/components/ChatBotContainer/ChatBotContainer.test.tsx +++ b/__tests__/components/ChatBotContainer/ChatBotContainer.test.tsx @@ -47,19 +47,6 @@ describe("ChatBotContainer Component", () => { setAudioToggledOn: jest.fn(), }); - (useSettingsContext as jest.Mock).mockReturnValue({ - settings: { - general: { - showHeader: true, - showFooter: true, - showInputRow: true, - flowStartTrigger: "ON_CHATBOT_INTERACT", - desktopEnabled: true, - mobileEnabled: true, - }, - }, - }); - (useStylesContext as jest.Mock).mockReturnValue({ styles: { chatWindowStyle: { background: 'white', color: 'black' }, @@ -81,6 +68,18 @@ describe("ChatBotContainer Component", () => { }); it("renders ChatBotContainer with header, body, input, and footer", () => { + (useSettingsContext as jest.Mock).mockReturnValue({ + settings: { + general: { + showHeader: true, + showFooter: true, + showInputRow: true, + flowStartTrigger: "ON_CHATBOT_INTERACT", + desktopEnabled: true, + mobileEnabled: true, + }, + }, + }); render(); const headerButton = screen.getByText("Header Button"); @@ -91,4 +90,124 @@ describe("ChatBotContainer Component", () => { expect(inputButton).toBeInTheDocument(); expect(footerButton).toBeInTheDocument(); }); + + it("renders header when settings.general.showHeader is true", () => { + (useSettingsContext as jest.Mock).mockReturnValue({ + settings: { + general: { + showHeader: true, + showFooter: false, + showInputRow: false, + flowStartTrigger: "ON_CHATBOT_INTERACT", + desktopEnabled: true, + mobileEnabled: true, + }, + }, + }); + render(); + + expect(screen.queryByText("Header Button")).toBeInTheDocument(); + expect(screen.queryByText("Input Button")).not.toBeInTheDocument(); + expect(screen.queryByText("Footer Button")).not.toBeInTheDocument(); + }); + + it("renders input button when settings.general.showInputRow is true", () => { + (useSettingsContext as jest.Mock).mockReturnValue({ + settings: { + general: { + showHeader: false, + showFooter: false, + showInputRow: true, + flowStartTrigger: "ON_CHATBOT_INTERACT", + desktopEnabled: true, + mobileEnabled: true, + }, + }, + }); + + render(); + + expect(screen.queryByText("Input Button")).toBeInTheDocument(); + expect(screen.queryByText("Header Button")).not.toBeInTheDocument(); + expect(screen.queryByText("Footer Button")).not.toBeInTheDocument(); + }); + + it("renders footer button when settings.general.showFooter is true", () => { + (useSettingsContext as jest.Mock).mockReturnValue({ + settings: { + general: { + showHeader: false, + showFooter: true, + showInputRow: false, + flowStartTrigger: "ON_CHATBOT_INTERACT", + desktopEnabled: true, + mobileEnabled: true, + }, + }, + }); + + render(); + + expect(screen.queryByText("Footer Button")).toBeInTheDocument(); + expect(screen.queryByText("Header Button")).not.toBeInTheDocument(); + expect(screen.queryByText("Input Button")).not.toBeInTheDocument(); + }); + + it("sets flow started on mouse down if it hasn't started", () => { + const setHasFlowStarted = jest.fn(); // Mock function for setHasFlowStarted + const setUnreadCount = jest.fn(); // Mock function for setUnreadCount + const setTextAreaDisabled = jest.fn(); // Mock function for setTextAreaDisabled + const setIsChatWindowOpen = jest.fn(); // Mock function for setIsChatWindowOpen + const setAudioToggledOn = jest.fn(); // Mock function for setAudioToggledOn + + (useSettingsContext as jest.Mock).mockReturnValue({ + settings: { + general: { + showHeader: true, + showFooter: true, + showInputRow: true, + flowStartTrigger: "ON_CHATBOT_INTERACT", + desktopEnabled: true, + mobileEnabled: true, + }, + }, + }); + + (useBotStatesContext as jest.Mock).mockReturnValue({ + hasFlowStarted: false, + setHasFlowStarted, + setUnreadCount, + setTextAreaDisabled, + setIsChatWindowOpen, + setAudioToggledOn, + // Add other necessary mock return values here + }); + + render(); + + // Use 'textbox' role instead of 'dialog' + const chatInput = screen.getByRole('textbox', { name: 'input text area' }); + chatInput.dispatchEvent(new MouseEvent('mousedown', { bubbles: true })); + + // Check that setHasFlowStarted was called with true + expect(setHasFlowStarted).toHaveBeenCalledWith(true); + }); + + it("does not render chatbot when shouldShowChatBot is false", () => { + (useIsDesktopInternal as jest.Mock).mockReturnValue(false); + (useSettingsContext as jest.Mock).mockReturnValue({ + settings: { + general: { + showHeader: false, + showFooter: false, + showInputRow: false, + embedded: false, + mobileEnabled: false, // Setting this to false + }, + }, + }); + render(); + + expect(screen.queryByText("Header Button")).not.toBeInTheDocument(); + }); }); From a0de7725e2c411ab600f727f3350e6926b760ec4 Mon Sep 17 00:00:00 2001 From: George Olson Date: Mon, 11 Nov 2024 14:16:22 -0800 Subject: [PATCH 4/4] Fixed issue with tests not passing, appears to be due to settings context --- .../components/ChatBotContainer.test.tsx | 45 ++-- .../ChatBotContainer.test.tsx | 213 ------------------ 2 files changed, 20 insertions(+), 238 deletions(-) delete mode 100644 __tests__/components/ChatBotContainer/ChatBotContainer.test.tsx diff --git a/__tests__/components/ChatBotContainer.test.tsx b/__tests__/components/ChatBotContainer.test.tsx index 1e67f47e..6bd3ac47 100644 --- a/__tests__/components/ChatBotContainer.test.tsx +++ b/__tests__/components/ChatBotContainer.test.tsx @@ -30,7 +30,7 @@ jest.mock("../../src/viteconfig", () => ({ }, })); -describe.skip("ChatBotContainer Component", () => { +describe("ChatBotContainer Component", () => { beforeEach(() => { (useButtonInternal as jest.Mock).mockReturnValue({ headerButtons: [], @@ -81,13 +81,12 @@ describe.skip("ChatBotContainer Component", () => { (useSettingsContext as jest.Mock).mockReturnValue({ settings: { general: { - showHeader: true, - showFooter: true, + showHeader: true, showInputRow: true, + showFooter: true, flowStartTrigger: "ON_CHATBOT_INTERACT", - desktopEnabled: true, - mobileEnabled: true, }, + device: { desktopEnabled: true, mobileEnabled: true }, }, }); render(); @@ -105,13 +104,12 @@ describe.skip("ChatBotContainer Component", () => { (useSettingsContext as jest.Mock).mockReturnValue({ settings: { general: { - showHeader: true, - showFooter: false, + showHeader: true, showInputRow: false, + showFooter: false, flowStartTrigger: "ON_CHATBOT_INTERACT", - desktopEnabled: true, - mobileEnabled: true, }, + device: { desktopEnabled: true, mobileEnabled: true }, }, }); render(); @@ -125,13 +123,12 @@ describe.skip("ChatBotContainer Component", () => { (useSettingsContext as jest.Mock).mockReturnValue({ settings: { general: { - showHeader: false, - showFooter: false, + showHeader: false, showInputRow: true, + showFooter: false, flowStartTrigger: "ON_CHATBOT_INTERACT", - desktopEnabled: true, - mobileEnabled: true, }, + device: { desktopEnabled: true, mobileEnabled: true }, }, }); @@ -146,13 +143,12 @@ describe.skip("ChatBotContainer Component", () => { (useSettingsContext as jest.Mock).mockReturnValue({ settings: { general: { - showHeader: false, - showFooter: true, + showHeader: false, showInputRow: false, + showFooter: true, flowStartTrigger: "ON_CHATBOT_INTERACT", - desktopEnabled: true, - mobileEnabled: true, }, + device: { desktopEnabled: true, mobileEnabled: true }, }, }); @@ -173,13 +169,12 @@ describe.skip("ChatBotContainer Component", () => { (useSettingsContext as jest.Mock).mockReturnValue({ settings: { general: { - showHeader: true, - showFooter: true, + showHeader: true, showInputRow: true, + showFooter: true, flowStartTrigger: "ON_CHATBOT_INTERACT", - desktopEnabled: true, - mobileEnabled: true, }, + device: { desktopEnabled: true, mobileEnabled: true }, }, }); @@ -208,12 +203,12 @@ describe.skip("ChatBotContainer Component", () => { (useSettingsContext as jest.Mock).mockReturnValue({ settings: { general: { - showHeader: false, - showFooter: false, + showHeader: false, showInputRow: false, - embedded: false, - mobileEnabled: false, // Setting this to false + showFooter: false, + flowStartTrigger: "ON_CHATBOT_INTERACT", }, + device: { desktopEnabled: true, mobileEnabled: true }, }, }); render(); diff --git a/__tests__/components/ChatBotContainer/ChatBotContainer.test.tsx b/__tests__/components/ChatBotContainer/ChatBotContainer.test.tsx deleted file mode 100644 index 3e40e270..00000000 --- a/__tests__/components/ChatBotContainer/ChatBotContainer.test.tsx +++ /dev/null @@ -1,213 +0,0 @@ -import React from "react"; -import { render, screen } from "@testing-library/react"; -import "@testing-library/jest-dom"; -import ChatBotContainer from "../../../src/components/ChatBotContainer"; -import { useButtonInternal } from "../../../src/hooks/internal/useButtonsInternal"; -import { useChatWindowInternal } from "../../../src/hooks/internal/useChatWindowInternal"; -import { useIsDesktopInternal } from "../../../src/hooks/internal/useIsDesktopInternal"; -import { useBotStatesContext } from "../../../src/context/BotStatesContext"; -import { useSettingsContext } from "../../../src/context/SettingsContext"; -import { useStylesContext } from "../../../src/context/StylesContext"; -import { useBotRefsContext } from "../../../src/context/BotRefsContext"; -import { useNotificationInternal } from "../../../src/hooks/internal/useNotificationsInternal"; - -jest.mock("../../../src/hooks/internal/useButtonsInternal"); -jest.mock("../../../src/hooks/internal/useChatWindowInternal"); -jest.mock("../../../src/hooks/internal/useIsDesktopInternal"); -jest.mock("../../../src/context/BotStatesContext"); -jest.mock("../../../src/context/SettingsContext"); -jest.mock("../../../src/context/StylesContext"); -jest.mock("../../../src/context/BotRefsContext"); -jest.mock("../../../src/hooks/internal/useNotificationsInternal"); - -describe("ChatBotContainer Component", () => { - beforeEach(() => { - (useButtonInternal as jest.Mock).mockReturnValue({ - headerButtons: [], - chatInputButtons: [], - footerButtons: [], - }); - - (useChatWindowInternal as jest.Mock).mockReturnValue({ - isChatWindowOpen: true, - chatScrollHeight: 100, - viewportHeight: 600, - viewportWidth: 300, - setChatScrollHeight: jest.fn(), - }); - - (useIsDesktopInternal as jest.Mock).mockReturnValue(true); - - (useBotStatesContext as jest.Mock).mockReturnValue({ - hasFlowStarted: false, - setHasFlowStarted: jest.fn(), - setUnreadCount: jest.fn(), - setTextAreaDisabled: jest.fn(), - setIsChatWindowOpen: jest.fn(), - setAudioToggledOn: jest.fn(), - }); - - (useStylesContext as jest.Mock).mockReturnValue({ - styles: { - chatWindowStyle: { background: 'white', color: 'black' }, - }, - }); - - (useBotRefsContext as jest.Mock).mockReturnValue({ - flowRef: { current: {} }, - chatBodyRef: { current: document.createElement('div') }, - streamMessageMap: new Map(), - paramsInputRef: { current: null }, - keepVoiceOnRef: { current: false }, - }); - - (useNotificationInternal as jest.Mock).mockReturnValue({ - audioContextRef: { current: {} }, - setUpNotifications: jest.fn(), - }); - }); - - it("renders ChatBotContainer with header, body, input, and footer", () => { - (useSettingsContext as jest.Mock).mockReturnValue({ - settings: { - general: { - showHeader: true, - showFooter: true, - showInputRow: true, - flowStartTrigger: "ON_CHATBOT_INTERACT", - desktopEnabled: true, - mobileEnabled: true, - }, - }, - }); - render(); - - const headerButton = screen.getByText("Header Button"); - const inputButton = screen.getByText("Input Button"); - const footerButton = screen.getByText("Footer Button"); - - expect(headerButton).toBeInTheDocument(); - expect(inputButton).toBeInTheDocument(); - expect(footerButton).toBeInTheDocument(); - }); - - it("renders header when settings.general.showHeader is true", () => { - (useSettingsContext as jest.Mock).mockReturnValue({ - settings: { - general: { - showHeader: true, - showFooter: false, - showInputRow: false, - flowStartTrigger: "ON_CHATBOT_INTERACT", - desktopEnabled: true, - mobileEnabled: true, - }, - }, - }); - render(); - - expect(screen.queryByText("Header Button")).toBeInTheDocument(); - expect(screen.queryByText("Input Button")).not.toBeInTheDocument(); - expect(screen.queryByText("Footer Button")).not.toBeInTheDocument(); - }); - - it("renders input button when settings.general.showInputRow is true", () => { - (useSettingsContext as jest.Mock).mockReturnValue({ - settings: { - general: { - showHeader: false, - showFooter: false, - showInputRow: true, - flowStartTrigger: "ON_CHATBOT_INTERACT", - desktopEnabled: true, - mobileEnabled: true, - }, - }, - }); - - render(); - - expect(screen.queryByText("Input Button")).toBeInTheDocument(); - expect(screen.queryByText("Header Button")).not.toBeInTheDocument(); - expect(screen.queryByText("Footer Button")).not.toBeInTheDocument(); - }); - - it("renders footer button when settings.general.showFooter is true", () => { - (useSettingsContext as jest.Mock).mockReturnValue({ - settings: { - general: { - showHeader: false, - showFooter: true, - showInputRow: false, - flowStartTrigger: "ON_CHATBOT_INTERACT", - desktopEnabled: true, - mobileEnabled: true, - }, - }, - }); - - render(); - - expect(screen.queryByText("Footer Button")).toBeInTheDocument(); - expect(screen.queryByText("Header Button")).not.toBeInTheDocument(); - expect(screen.queryByText("Input Button")).not.toBeInTheDocument(); - }); - - it("sets flow started on mouse down if it hasn't started", () => { - const setHasFlowStarted = jest.fn(); // Mock function for setHasFlowStarted - const setUnreadCount = jest.fn(); // Mock function for setUnreadCount - const setTextAreaDisabled = jest.fn(); // Mock function for setTextAreaDisabled - const setIsChatWindowOpen = jest.fn(); // Mock function for setIsChatWindowOpen - const setAudioToggledOn = jest.fn(); // Mock function for setAudioToggledOn - - (useSettingsContext as jest.Mock).mockReturnValue({ - settings: { - general: { - showHeader: true, - showFooter: true, - showInputRow: true, - flowStartTrigger: "ON_CHATBOT_INTERACT", - desktopEnabled: true, - mobileEnabled: true, - }, - }, - }); - - (useBotStatesContext as jest.Mock).mockReturnValue({ - hasFlowStarted: false, - setHasFlowStarted, - setUnreadCount, - setTextAreaDisabled, - setIsChatWindowOpen, - setAudioToggledOn, - // Add other necessary mock return values here - }); - - render(); - - // Use 'textbox' role instead of 'dialog' - const chatInput = screen.getByRole('textbox', { name: 'input text area' }); - chatInput.dispatchEvent(new MouseEvent('mousedown', { bubbles: true })); - - // Check that setHasFlowStarted was called with true - expect(setHasFlowStarted).toHaveBeenCalledWith(true); - }); - - it("does not render chatbot when shouldShowChatBot is false", () => { - (useIsDesktopInternal as jest.Mock).mockReturnValue(false); - (useSettingsContext as jest.Mock).mockReturnValue({ - settings: { - general: { - showHeader: false, - showFooter: false, - showInputRow: false, - embedded: false, - mobileEnabled: false, // Setting this to false - }, - }, - }); - render(); - - expect(screen.queryByText("Header Button")).not.toBeInTheDocument(); - }); -});