UNPKG

@forgeflowai/chat

Version:

This is an embeddable Chat widget for n8n. It allows the execution of AI-Powered Workflows through a Chat window.

173 lines (172 loc) 6.94 kB
import { fireEvent, waitFor } from "@testing-library/vue"; import { createFetchResponse, createGetLatestMessagesResponse, createSendMessageResponse, getChatInputSendButton, getChatInputTextarea, getChatMessage, getChatMessageByText, getChatMessages, getChatMessageTyping, getChatWindowToggle, getChatWindowWrapper, getChatWrapper, getGetStartedButton, getMountingTarget } from "@forgeflowai/chat/__tests__/utils"; import { createChat } from "@forgeflowai/chat/index"; describe("createChat()", () => { let app; afterEach(() => { vi.clearAllMocks(); app.unmount(); }); describe("mode", () => { it("should create fullscreen chat app with default options", () => { const fetchSpy = vi.spyOn(window, "fetch"); fetchSpy.mockImplementationOnce(createFetchResponse(createGetLatestMessagesResponse())); app = createChat({ mode: "fullscreen" }); expect(getMountingTarget()).toBeVisible(); expect(getChatWrapper()).toBeVisible(); expect(getChatWindowWrapper()).not.toBeInTheDocument(); }); it("should create window chat app with default options", () => { const fetchSpy = vi.spyOn(window, "fetch"); fetchSpy.mockImplementationOnce(createFetchResponse(createGetLatestMessagesResponse())); app = createChat({ mode: "window" }); expect(getMountingTarget()).toBeDefined(); expect(getChatWindowWrapper()).toBeVisible(); expect(getChatWrapper()).not.toBeVisible(); }); it("should open window chat app using toggle button", async () => { const fetchSpy = vi.spyOn(window, "fetch"); fetchSpy.mockImplementationOnce(createFetchResponse(createGetLatestMessagesResponse())); app = createChat(); expect(getMountingTarget()).toBeVisible(); expect(getChatWindowWrapper()).toBeVisible(); const trigger = getChatWindowToggle(); await fireEvent.click(trigger); expect(getChatWrapper()).toBeVisible(); }); }); describe("loadPreviousMessages", () => { it("should load previous messages on mount", async () => { const fetchSpy = vi.spyOn(global, "fetch"); fetchSpy.mockImplementation(createFetchResponse(createGetLatestMessagesResponse())); app = createChat({ mode: "fullscreen", showWelcomeScreen: true }); const getStartedButton = getGetStartedButton(); await fireEvent.click(getStartedButton); expect(fetchSpy.mock.calls[0][1]).toEqual( expect.objectContaining({ method: "POST", headers: { "Content-Type": "application/json" }, body: expect.stringContaining('"action":"loadPreviousSession"'), mode: "cors", cache: "no-cache" }) ); }); }); describe("initialMessages", () => { it.each(["fullscreen", "window"])( "should show initial default messages in %s mode", async (mode) => { const fetchSpy = vi.spyOn(window, "fetch"); fetchSpy.mockImplementationOnce(createFetchResponse(createGetLatestMessagesResponse())); const initialMessages = ["Hello tester!", "How are you?"]; app = createChat({ mode, initialMessages }); if (mode === "window") { const trigger = getChatWindowToggle(); await fireEvent.click(trigger); } expect(getChatMessages().length).toBe(initialMessages.length); expect(getChatMessageByText(initialMessages[0])).toBeInTheDocument(); expect(getChatMessageByText(initialMessages[1])).toBeInTheDocument(); } ); }); describe("sendMessage", () => { it.each(["window", "fullscreen"])( "should send a message and render a text message in %s mode", async (mode) => { const input = "Hello User World!"; const output = "Hello Bot World!"; const fetchSpy = vi.spyOn(window, "fetch"); fetchSpy.mockImplementationOnce(createFetchResponse(createGetLatestMessagesResponse)).mockImplementationOnce(createFetchResponse(createSendMessageResponse(output))); app = createChat({ mode }); if (mode === "window") { const trigger = getChatWindowToggle(); await fireEvent.click(trigger); } expect(getChatMessageTyping()).not.toBeInTheDocument(); expect(getChatMessages().length).toBe(2); await waitFor(() => expect(getChatInputTextarea()).toBeInTheDocument()); const textarea = getChatInputTextarea(); const sendButton = getChatInputSendButton(); await fireEvent.update(textarea, input); expect(sendButton).not.toBeDisabled(); await fireEvent.click(sendButton); expect(fetchSpy.mock.calls[1][1]).toEqual( expect.objectContaining({ method: "POST", headers: { "Content-Type": "application/json" }, body: expect.stringMatching(/"action":"sendMessage"/), mode: "cors", cache: "no-cache" }) ); expect(fetchSpy.mock.calls[1][1]?.body).toContain(`"${input}"`); expect(getChatMessages().length).toBe(3); expect(getChatMessageByText(input)).toBeInTheDocument(); expect(getChatMessageTyping()).toBeVisible(); await waitFor(() => expect(getChatMessageTyping()).not.toBeInTheDocument()); expect(getChatMessageByText(output)).toBeInTheDocument(); } ); it.each(["fullscreen", "window"])( "should send a message and render a code markdown message in %s mode", async (mode) => { const input = "Teach me javascript!"; const output = '# Code\n```js\nconsole.log("Hello World!");\n```'; const fetchSpy = vi.spyOn(window, "fetch"); fetchSpy.mockImplementationOnce(createFetchResponse(createGetLatestMessagesResponse)).mockImplementationOnce(createFetchResponse(createSendMessageResponse(output))); app = createChat({ mode }); if (mode === "window") { const trigger = getChatWindowToggle(); await fireEvent.click(trigger); } await waitFor(() => expect(getChatInputTextarea()).toBeInTheDocument()); const textarea = getChatInputTextarea(); const sendButton = getChatInputSendButton(); await fireEvent.update(textarea, input); await fireEvent.click(sendButton); expect(getChatMessageByText(input)).toBeInTheDocument(); expect(getChatMessages().length).toBe(3); await waitFor(() => expect(getChatMessageTyping()).not.toBeInTheDocument()); const lastMessage = getChatMessage(-1); expect(lastMessage).toBeInTheDocument(); expect(lastMessage.querySelector("h1")).toHaveTextContent("Code"); expect(lastMessage.querySelector("code")).toHaveTextContent('console.log("Hello World!");'); } ); }); });