Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
iampearlep committed Oct 13, 2024
2 parents fb04476 + 3c1ac0c commit cc230ee
Show file tree
Hide file tree
Showing 71 changed files with 1,952 additions and 516 deletions.
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# CHANGELOG.md

## v2.0.0-beta.17 (13-10-2024)

**Fixed:**
- Fixed improper parsing of css files in themes
- Fixed toast animation not working

**Added:**
- Updated button with svgs from: https://fonts.google.com/
- Added disabled icon support for all buttons (now possible to have different icons for enabled/disabled state)
- Added svg component support for button icons (conveniently use the `fill` attribute to recolor icons!)
- Added a new `sendIconDisabledStyle`
- Loading of chat history no longer locks the text area
- Standardized keyframe naming conventions

## v2.0.0-beta.16 (08-10-2024)

**Fixed:**
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ If there are any questions pertaining to the application itself (usage or implem
Credits are to be given for the following images:
- [Logo](https://www.craiyon.com/)
- [Bot Avatar (v1)](https://www.craiyon.com/)
- [Buttons](https://fonts.google.com/)

Note: Some buttons are hand-drawn.

#### Sound
Credits are to be given for the notification sound:
Expand All @@ -119,6 +122,4 @@ Credits are to be given for the notification sound:
#### Inspirations
As I have used similar alternatives at some point in my developer journey, some inspirations have been taken from them and they ought to be credited here:
- [Tidio](https://www.tidio.com/)
- [React Simple Chatbot](https://github.com/LucasBassetti/react-simple-chatbot)

Note: All other media content are hand-drawn unless otherwise stated, feel free to use them!
- [React Simple Chatbot](https://github.com/LucasBassetti/react-simple-chatbot)
10 changes: 9 additions & 1 deletion __tests__/__mocks__/fileMock.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,10 @@
// __mocks__/fileMock.ts
export const botAvatar = "../../assets/bot_avatar.svg";
export const botAvatar = "../../assets/bot_avatar.svg";
export const actionDisabledIcon = "../../assets/action_disabled_icon.svg";
export const emojiIcon = "../../assets/emoji_icon.svg";
export const closeChatIcon = "../../assets/close_chat_icon.svg";
export const notificationIcon = "../../assets/notification_icon.svg";
export const notificationIconDisabled = "../../assets/notification_icon_disabled.svg";
export const audioIcon = "../../assets/audio_icon.svg";
export const audioIconDisabled = "../../assets/audio_icon_disabled.svg";
export const sendIcon = "../../assets/send_icon.svg";
121 changes: 121 additions & 0 deletions __tests__/components/ChatBotTooltip/ChatBotTooltip.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import React from "react";
import "@testing-library/jest-dom";
import { render, screen, fireEvent } from "@testing-library/react";
import ChatBotTooltip from "../../../src/components/ChatBotTooltip/ChatBotTooltip";
import { useIsDesktopInternal } from "../../../src/hooks/internal/useIsDesktopInternal";
import { useChatWindowInternal } from "../../../src/hooks/internal/useChatWindowInternal";
import { useSettingsContext } from "../../../src/context/SettingsContext";
import { useStylesContext } from "../../../src/context/StylesContext";

// Mock the contexts and hooks
jest.mock("../../../src/hooks/internal/useIsDesktopInternal");
jest.mock("../../../src/hooks/internal/useChatWindowInternal");
jest.mock("../../../src/context/SettingsContext");
jest.mock("../../../src/context/StylesContext");

describe("ChatBotTooltip Component", () => {
// Set up default mock return values before each test
beforeEach(() => {
(useIsDesktopInternal as jest.Mock).mockReturnValue(true);
(useChatWindowInternal as jest.Mock).mockReturnValue({
isChatWindowOpen: false,
openChat: jest.fn(),
});
(useSettingsContext as jest.Mock).mockReturnValue({
settings: {
general: { primaryColor: "blue", secondaryColor: "#000", embedded: false },
tooltip: { text: "Chatbot Tooltip" },
},
});
(useStylesContext as jest.Mock).mockReturnValue({
styles: {
chatButtonStyle: { width: 75 },
chatWindowStyle: { width: 375 },
tooltipStyle: {},
},
});
});

// Clear all mocks after each test case to avoid test interference
afterEach(() => {
jest.clearAllMocks();
});

// Test: Render the tooltip when mode is "ALWAYS" and on desktop
it('renders tooltip when mode is "ALWAYS" and isDesktop is true', () => {
// Mock the context to return settings with mode "ALWAYS"
(useSettingsContext as jest.Mock).mockReturnValueOnce({
settings: {
tooltip: { mode: "ALWAYS", text: "Chatbot Tooltip" },
},
});

// Render the component and ensure the tooltip is shown
render(<ChatBotTooltip />);
const tooltip = screen.getByTestId("chat-tooltip");
expect(tooltip).toBeInTheDocument();
expect(tooltip).toHaveClass("rcb-tooltip-show");
});

// Test: Ensure the tooltip is hidden when mode is "NEVER"
it('hides tooltip when mode is "NEVER"', () => {
// Mock the context to return settings with mode "NEVER"
(useSettingsContext as jest.Mock).mockReturnValueOnce({
settings: {
tooltip: { mode: "NEVER", text: "Chatbot Tooltip" },
},
});

// Render the component and ensure the tooltip is rendered but hidden
render(<ChatBotTooltip />);
const tooltip = screen.getByTestId("chat-tooltip");
expect(tooltip).toBeInTheDocument();
expect(tooltip).toHaveClass("rcb-tooltip-hide");
});

// Test: Show the tooltip when mode is "START" (when component is rendered for the first time)
it('shows tooltip when mode is "START" and shownTooltipOnStart is false', () => {
// Mock the context to return settings with mode "START"
(useSettingsContext as jest.Mock).mockReturnValueOnce({
settings: {
tooltip: { mode: "START", text: "Chatbot Tooltip" },
},
});

// Render the component and ensure the tooltip is shown
render(<ChatBotTooltip />);
const tooltip = screen.getByText("Chatbot Tooltip");
expect(tooltip).toBeInTheDocument();
});

// Test: Ensure the tooltip shows when mode is "CLOSE"
it('shows tooltip when mode is "CLOSE"', () => {
// Mock the context to return settings with mode "CLOSE"
(useSettingsContext as jest.Mock).mockReturnValueOnce({
settings: {
tooltip: { mode: "CLOSE", text: "Chatbot Tooltip" },
},
});

// Render the component and ensure the tooltip is shown
render(<ChatBotTooltip />);
const tooltip = screen.getByText("Chatbot Tooltip");
expect(tooltip).toBeInTheDocument();
});

// Test: Ensure clicking the tooltip calls the openChat function
it("calls openChat function when tooltip is clicked", () => {
// Mock the function that opens the chat
const mockOpenChat = jest.fn();
(useChatWindowInternal as jest.Mock).mockReturnValue({
isChatWindowOpen: false,
openChat: mockOpenChat,
});

// Render the component, simulate click event and verify that openChat is called
render(<ChatBotTooltip />);
const tooltip = screen.getByText("Chatbot Tooltip");
fireEvent.click(tooltip);
expect(mockOpenChat).toHaveBeenCalledWith(true);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ describe("ChatHistoryButton", () => {
};

const mockStyles = {
chatHistoryButtonStyle: { backgroundColor: "#ffffff", border: "1px solid #ccc" },
chatHistoryButtonStyle: { backgroundColor: "#ffffff", border: "1px solid", borderColor: "#ccc" },
chatHistoryButtonHoveredStyle: { backgroundColor: "#f0f0f0" },
};

Expand All @@ -49,7 +49,7 @@ describe("ChatHistoryButton", () => {
// Verify the button's initial styles
const button = screen.getByRole("button");
expect(button).toHaveStyle("background-color: #ffffff");
expect(button).toHaveStyle("border: 1px solid #ccc");
expect(button).toHaveStyle("border: 1px solid; border-color: #ccc");
});

it("changes styles when hovered", () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import React from "react";

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

import ChatHistoryLineBreak from "../../../src/components/ChatHistoryLineBreak/ChatHistoryLineBreak";
import { useSettingsContext } from "../../../src/context/SettingsContext";
import { useStylesContext } from "../../../src/context/StylesContext";
import { DefaultStyles } from "../../../src/constants/internal/DefaultStyles";
import { DefaultSettings } from "../../../src/constants/internal/DefaultSettings";

jest.mock("../../../src/context/SettingsContext");
jest.mock("../../../src/context/StylesContext");

/**
* Test for ChatHistoryLineBreak component.
*/
describe("ChatHistoryLineBreak Component", () => {
const mockText = DefaultSettings.chatHistory?.chatHistoryLineBreakText ?? "test break line";
const mockColor = DefaultStyles.chatHistoryLineBreakStyle?.color ?? "blue";

// Mock default settings and styles before each test
beforeEach(() => {
(useSettingsContext as jest.Mock).mockReturnValue({
settings: {
chatHistory: {
chatHistoryLineBreakText: mockText
}
}
});

(useStylesContext as jest.Mock).mockReturnValue({
styles: {
chatHistoryLineBreakStyle: {
color: mockColor
}
}
});
});

it("renders mock line break text and style", () => {
render(<ChatHistoryLineBreak />);

// check if the default text is rendered
const lineBreak = screen.getByText(mockText);
expect(lineBreak).toBeInTheDocument();

// check if line break color is correct
expect(lineBreak).toHaveStyle(`color: ${mockColor}`);
});

it("renders empty div when chatHistoryLineBreakText is not provided", () => {
// Mock settings without chatHistoryLineBreakText
(useSettingsContext as jest.Mock).mockReturnValue({
settings: {
chatHistory: {} // Simulate missing chatHistoryLineBreakText
}
});

render(<ChatHistoryLineBreak />);

// check that line break div exists but text is empty
const lineBreak = screen.getByTestId("chat-history-line-break-text");
expect(lineBreak).toBeInTheDocument();
expect(lineBreak).toBeEmptyDOMElement();

// check if line break color is applied even when chatHistoryLineBreakText is empty
expect(lineBreak).toHaveStyle(`color: ${DefaultStyles.chatHistoryLineBreakStyle?.color ?? mockColor}`);
});

it("renders empty when chatHistory is not provided", () => {
(useSettingsContext as jest.Mock).mockReturnValue({
settings: {}
});

render(<ChatHistoryLineBreak />);

// check that line break div exists but text is empty
const lineBreak = screen.getByTestId("chat-history-line-break-text");
expect(lineBreak).toBeInTheDocument();
expect(lineBreak).toBeEmptyDOMElement();

// check line break color is applied even when chatHistory is empty
expect(lineBreak).toHaveStyle(`color: ${DefaultStyles.chatHistoryLineBreakStyle?.color ?? mockColor}`);
});
});
Loading

0 comments on commit cc230ee

Please sign in to comment.