Files
Automata/packages/@n8n/chat/src/__tests__/index.spec.ts
Alex Grozav af49e95cc7 feat: Add Chat Trigger node (#7409)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
Co-authored-by: Jesper Bylund <mail@jesperbylund.com>
Co-authored-by: OlegIvaniv <me@olegivaniv.com>
Co-authored-by: Deborah <deborah@starfallprojects.co.uk>
Co-authored-by: Jan Oberhauser <janober@users.noreply.github.com>
Co-authored-by: Jon <jonathan.bennetts@gmail.com>
Co-authored-by: कारतोफ्फेलस्क्रिप्ट™ <aditya@netroy.in>
Co-authored-by: Michael Kret <88898367+michael-radency@users.noreply.github.com>
Co-authored-by: Giulio Andreini <andreini@netseven.it>
Co-authored-by: Mason Geloso <Mason.geloso@gmail.com>
Co-authored-by: Mason Geloso <hone@Masons-Mac-mini.local>
Co-authored-by: Mutasem Aldmour <mutasem@n8n.io>
2024-01-09 13:11:39 +02:00

219 lines
6.6 KiB
TypeScript

import { fireEvent, waitFor } from '@testing-library/vue';
import {
createFetchResponse,
createGetLatestMessagesResponse,
createSendMessageResponse,
getChatInputSendButton,
getChatInputTextarea,
getChatMessage,
getChatMessageByText,
getChatMessages,
getChatMessageTyping,
getChatWindowToggle,
getChatWindowWrapper,
getChatWrapper,
getGetStartedButton,
getMountingTarget,
} from '@n8n/chat/__tests__/utils';
import { createChat } from '@n8n/chat/index';
describe('createChat()', () => {
let app: ReturnType<typeof createChat>;
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 as HTMLElement);
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 as HTMLElement);
expect(fetchSpy.mock.calls[0][1]).toEqual(
expect.objectContaining({
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: expect.stringContaining('"action":"loadPreviousSession"') as unknown,
mode: 'cors',
cache: 'no-cache',
}),
);
});
});
describe('initialMessages', () => {
it.each(['fullscreen', 'window'] as Array<'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 as HTMLElement);
}
expect(getChatMessages().length).toBe(initialMessages.length);
expect(getChatMessageByText(initialMessages[0])).toBeInTheDocument();
expect(getChatMessageByText(initialMessages[1])).toBeInTheDocument();
},
);
});
describe('sendMessage', () => {
it.each(['window', 'fullscreen'] as Array<'fullscreen' | 'window'>)(
'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 as HTMLElement);
}
expect(getChatMessageTyping()).not.toBeInTheDocument();
expect(getChatMessages().length).toBe(2);
await waitFor(() => expect(getChatInputTextarea()).toBeInTheDocument());
const textarea = getChatInputTextarea();
const sendButton = getChatInputSendButton();
await fireEvent.update(textarea as HTMLElement, input);
expect(sendButton).not.toBeDisabled();
await fireEvent.click(sendButton as HTMLElement);
expect(fetchSpy.mock.calls[1][1]).toEqual(
expect.objectContaining({
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: expect.stringMatching(/"action":"sendMessage"/) as unknown,
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'] as Array<'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 as HTMLElement);
}
await waitFor(() => expect(getChatInputTextarea()).toBeInTheDocument());
const textarea = getChatInputTextarea();
const sendButton = getChatInputSendButton();
await fireEvent.update(textarea as HTMLElement, input);
await fireEvent.click(sendButton as HTMLElement);
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!");');
},
);
});
});