Skip to content

Commit

Permalink
[Test] [Issue- 221] : Add unit test for ChatBot (#291)
Browse files Browse the repository at this point in the history
  • Loading branch information
kallel-anobom authored Feb 11, 2025
1 parent 6d161d7 commit 2747c08
Show file tree
Hide file tree
Showing 2 changed files with 205 additions and 115 deletions.
90 changes: 90 additions & 0 deletions __tests__/components/ChatBot.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import React from "react";

import { render, screen } from "@testing-library/react";
import { expect } from "@jest/globals";
import "@testing-library/jest-dom/jest-globals";

import ChatBot from "../../src/components/ChatBot";

import { WelcomeFlow } from "../../src/constants/internal/WelcomeFlow";

import { useChatBotContext } from "../../src/context/ChatBotContext";

import { Settings } from "../../src/types/Settings";
import { Styles } from "../../src/types/Styles";
import { Theme } from "../../src/types/Theme";

// Mock dependencies
jest.mock("../../src/utils/idGenerator", () => ({
generateSecureUUID: jest.fn(() => "mocked-uuid"),
}));

jest.mock("../../src/context/ChatBotContext", () => ({
useChatBotContext: jest.fn(),
ChatBotProvider: ({ children }: { children: React.ReactNode }) => (
<div>{children}</div>
),
}));

jest.mock("../../src/components/ChatBotLoader", () => () => (
<div data-testid="chatbot-loader" />
));

jest.mock("../../src/components/ChatBotContainer", () => () => (
<div data-testid="chatbot-container" />
));

describe("ChatBot Component", () => {
it("renders ChatBot with default settings when no props are provided", () => {
render(<ChatBot />);

// Check if ChatBotLoader is rendered with default settings
expect(screen.getByTestId("chatbot-loader")).toBeInTheDocument();
expect(screen.queryByTestId("chatbot-container")).not.toBeInTheDocument();
});

it("renders ChatBot with provided settings", () => {
const customFlow = { ...WelcomeFlow };
const customSettings: Settings = {
/* provide valid properties for Settings type */
};
const customStyles: Styles = {
/* provide valid properties for Styles type */
};
const customThemes: Theme[] = [
/* provide valid properties for Theme type */
];
const customPlugins: [] = [];

render(
<ChatBot
id="custom-id"
flow={customFlow}
settings={customSettings}
styles={customStyles}
themes={customThemes}
plugins={customPlugins}
/>
);

// Check if ChatBotLoader is rendered with provided settings
expect(screen.getByTestId("chatbot-loader")).toBeInTheDocument();
expect(screen.queryByTestId("chatbot-container")).not.toBeInTheDocument();
});
it("renders ChatBot with ChatBotProvider when context is not provided", () => {
render(<ChatBot />);

// Check if ChatBotProvider is rendered
expect(screen.getByTestId("chatbot-loader")).toBeInTheDocument();
});

// useChatBotContext is already imported at the top
(useChatBotContext as jest.Mock).mockReturnValue({});

it("renders ChatBot without ChatBotProvider when context is provided", () => {
render(<ChatBot />);

// Check if ChatBotProvider is not rendered
expect(screen.getByTestId("chatbot-loader")).toBeInTheDocument();
});
});
230 changes: 115 additions & 115 deletions __tests__/components/ChatBotBody/ChatMessagePrompt.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,131 +6,131 @@ import { useBotStatesContext } from "../../../src/context/BotStatesContext";

// Mock contexts
jest.mock("../../../src/context/BotRefsContext", () => ({
useBotRefsContext: jest.fn(() => ({
chatBodyRef: {
current: {
scrollTop: 0,
scrollHeight: 1000,
clientHeight: 400,
},
},
})),
useBotRefsContext: jest.fn(() => ({
chatBodyRef: {
current: {
scrollTop: 0,
scrollHeight: 1000,
clientHeight: 400,
},
},
})),
}));

jest.mock("../../../src/context/BotStatesContext", () => ({
useBotStatesContext: jest.fn(),
useBotStatesContext: jest.fn(),
}));

jest.mock("../../../src/context/SettingsContext", () => ({
useSettingsContext: jest.fn(() => ({
settings: {
general: { primaryColor: "#000" },
chatWindow: {
showMessagePrompt: true,
messagePromptText: "Scroll to new messages",
},
},
})),
useSettingsContext: jest.fn(() => ({
settings: {
general: { primaryColor: "#000" },
chatWindow: {
showMessagePrompt: true,
messagePromptText: "Scroll to new messages",
},
},
})),
}));

jest.mock("../../../src/context/StylesContext", () => ({
useStylesContext: jest.fn(() => ({
styles: {
chatMessagePromptStyle: { color: "#fff", borderColor: "#ccc" },
chatMessagePromptHoveredStyle: { color: "#000", borderColor: "#000" },
},
})),
useStylesContext: jest.fn(() => ({
styles: {
chatMessagePromptStyle: { color: "#fff", borderColor: "#ccc" },
chatMessagePromptHoveredStyle: { color: "#000", borderColor: "#000" },
},
})),
}));

describe("ChatMessagePrompt Component", () => {
const mockSetIsScrolling = jest.fn();

beforeEach(() => {
jest.clearAllMocks();
jest.useFakeTimers();
});

afterEach(() => {
jest.runOnlyPendingTimers();
jest.useRealTimers();
});

const renderComponent = () => render(<ChatMessagePrompt />);

it("renders with the correct message prompt text", () => {
(useBotStatesContext as jest.Mock).mockReturnValue({
unreadCount: 0,
isScrolling: false,
setIsScrolling: mockSetIsScrolling,
});

renderComponent();
const messagePrompt = screen.getByText("Scroll to new messages");
expect(messagePrompt).toBeInTheDocument();
});

it("applies visible class when conditions are met", () => {
(useBotStatesContext as jest.Mock).mockReturnValue({
unreadCount: 2,
isScrolling: true,
setIsScrolling: mockSetIsScrolling,
});

renderComponent();
const messagePrompt = screen.getByText("Scroll to new messages");
expect(messagePrompt.parentElement).toHaveClass("rcb-message-prompt-container visible");
});

it("applies hidden class when conditions are not met", () => {
(useBotStatesContext as jest.Mock).mockReturnValue({
unreadCount: 0,
isScrolling: false,
setIsScrolling: mockSetIsScrolling,
});

renderComponent();
const messagePromptContainer = screen.queryByText("Scroll to new messages")?.parentElement;
expect(messagePromptContainer).toHaveClass("rcb-message-prompt-container hidden");
});

it("applies hover styles when hovered", () => {
(useBotStatesContext as jest.Mock).mockReturnValue({
unreadCount: 2,
isScrolling: true,
setIsScrolling: mockSetIsScrolling,
});

renderComponent();
const messagePrompt = screen.getByText("Scroll to new messages");

// Before hover
expect(messagePrompt).toHaveStyle({ color: "#fff", borderColor: "#ccc" });

// Hover
fireEvent.mouseEnter(messagePrompt);
expect(messagePrompt).toHaveStyle({ color: "#000", borderColor: "#000" });

// Leave hover
fireEvent.mouseLeave(messagePrompt);
expect(messagePrompt).toHaveStyle({ color: "#fff", borderColor: "#ccc" });
});

it("scrolls to the bottom when clicked", () => {
(useBotStatesContext as jest.Mock).mockReturnValue({
unreadCount: 2,
isScrolling: true,
setIsScrolling: mockSetIsScrolling,
});

renderComponent();
const messagePrompt = screen.getByText("Scroll to new messages");

fireEvent.mouseDown(messagePrompt);

// Simulate scrolling completion
jest.advanceTimersByTime(600);

// Verify that setIsScrolling was called
expect(mockSetIsScrolling).toHaveBeenCalledWith(false);
});
const mockSetIsScrolling = jest.fn();

beforeEach(() => {
jest.clearAllMocks();
jest.useFakeTimers();
});

afterEach(() => {
jest.runOnlyPendingTimers();
jest.useRealTimers();
});

const renderComponent = () => render(<ChatMessagePrompt />);

it("renders with the correct message prompt text", () => {
(useBotStatesContext as jest.Mock).mockReturnValue({
unreadCount: 0,
isScrolling: false,
setIsScrolling: mockSetIsScrolling,
});

renderComponent();
const messagePrompt = screen.getByText("Scroll to new messages");
expect(messagePrompt).toBeInTheDocument();
});

it("applies visible class when conditions are met", () => {
(useBotStatesContext as jest.Mock).mockReturnValue({
unreadCount: 2,
isScrolling: true,
setIsScrolling: mockSetIsScrolling,
});

renderComponent();
const messagePrompt = screen.getByText("Scroll to new messages");
expect(messagePrompt.parentElement).toHaveClass("rcb-message-prompt-container visible");
});

it("applies hidden class when conditions are not met", () => {
(useBotStatesContext as jest.Mock).mockReturnValue({
unreadCount: 0,
isScrolling: false,
setIsScrolling: mockSetIsScrolling,
});

renderComponent();
const messagePromptContainer = screen.queryByText("Scroll to new messages")?.parentElement;
expect(messagePromptContainer).toHaveClass("rcb-message-prompt-container hidden");
});

it("applies hover styles when hovered", () => {
(useBotStatesContext as jest.Mock).mockReturnValue({
unreadCount: 2,
isScrolling: true,
setIsScrolling: mockSetIsScrolling,
});

renderComponent();
const messagePrompt = screen.getByText("Scroll to new messages");

// Before hover
expect(messagePrompt).toHaveStyle({ color: "#fff", borderColor: "#ccc" });

// Hover
fireEvent.mouseEnter(messagePrompt);
expect(messagePrompt).toHaveStyle({ color: "#000", borderColor: "#000" });

// Leave hover
fireEvent.mouseLeave(messagePrompt);
expect(messagePrompt).toHaveStyle({ color: "#fff", borderColor: "#ccc" });
});

it("scrolls to the bottom when clicked", () => {
(useBotStatesContext as jest.Mock).mockReturnValue({
unreadCount: 2,
isScrolling: true,
setIsScrolling: mockSetIsScrolling,
});

renderComponent();
const messagePrompt = screen.getByText("Scroll to new messages");

fireEvent.mouseDown(messagePrompt);

// Simulate scrolling completion
jest.advanceTimersByTime(600);

// Verify that setIsScrolling was called
expect(mockSetIsScrolling).toHaveBeenCalledWith(false);
});
});

0 comments on commit 2747c08

Please sign in to comment.