Files
n8n/packages/testing/playwright/tests/e2e/ai/assistant-support-chat.spec.ts
alighasami 3d5eaf9445
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
first commit
2026-03-17 16:22:57 +03:30

119 lines
4.3 KiB
TypeScript

import {
simpleAssistantResponse,
aiEnabledWithCodeSnippetRequirements,
aiEnabledWithHttpWorkflowRequirements,
} from '../../../config/ai-assistant-fixtures';
import { HTTP_REQUEST_NODE_NAME } from '../../../config/constants';
import { test, expect } from '../../../fixtures/base';
type ChatRequestBody = {
payload?: {
type?: string;
text?: string;
question?: string;
context?: Record<string, unknown>;
};
};
test.describe('AI Assistant::enabled', {
annotation: [
{ type: 'owner', description: 'AI' },
],
}, () => {
test.describe('Support Chat', () => {
test('assistant returns code snippet', async ({ n8n, setupRequirements }) => {
await setupRequirements(aiEnabledWithCodeSnippetRequirements);
await n8n.page.goto('/workflow/new');
await expect(n8n.aiAssistant.getAskAssistantCanvasActionButton()).toBeVisible();
await n8n.aiAssistant.getAskAssistantCanvasActionButton().click();
await expect(n8n.aiAssistant.getAskAssistantChat()).toBeVisible();
await n8n.aiAssistant.sendMessage('Show me an expression');
await expect(n8n.aiAssistant.getChatMessagesAll()).toHaveCount(3);
await expect(n8n.aiAssistant.getChatMessagesUser().first()).toContainText(
'Show me an expression',
);
await expect(n8n.aiAssistant.getChatMessagesAssistant().first()).toContainText(
'To use expressions in n8n, follow these steps:',
);
await expect(n8n.aiAssistant.getChatMessagesAssistant().first()).toContainText('New York');
await expect(n8n.aiAssistant.getCodeSnippet()).toHaveText('{{$json.body.city}}');
});
test('should send current context to support chat', async ({ n8n, setupRequirements }) => {
await setupRequirements(aiEnabledWithHttpWorkflowRequirements);
const chatRequests: ChatRequestBody[] = [];
await n8n.page.route('**/rest/ai/chat', async (route) => {
const body = route.request().postDataJSON() as ChatRequestBody;
chatRequests.push(body);
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(simpleAssistantResponse),
});
});
await n8n.aiAssistant.getAskAssistantCanvasActionButton().click();
await n8n.aiAssistant.sendMessage('What is wrong with this workflow?');
const supportRequest = chatRequests.find(
(request) => request.payload?.question === 'What is wrong with this workflow?',
);
expect(supportRequest).toBeDefined();
const supportContext = supportRequest?.payload?.context;
expect(supportContext).toBeDefined();
expect(supportContext?.currentView).toBeDefined();
expect(supportContext?.currentWorkflow).toBeDefined();
});
test('should not send workflow context if nothing changed', async ({
n8n,
setupRequirements,
}) => {
await setupRequirements(aiEnabledWithHttpWorkflowRequirements);
const chatRequests: ChatRequestBody[] = [];
await n8n.page.route('**/rest/ai/chat', async (route) => {
const body = route.request().postDataJSON() as ChatRequestBody;
chatRequests.push(body);
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(simpleAssistantResponse),
});
});
await n8n.aiAssistant.getAskAssistantCanvasActionButton().click();
await n8n.aiAssistant.sendMessage('What is wrong with this workflow?', 'enter-key');
// Wait for message to be processed
await expect(n8n.aiAssistant.getChatMessagesAssistant()).toHaveCount(1);
await n8n.aiAssistant.sendMessage('And now?', 'enter-key');
await expect(n8n.aiAssistant.getChatMessagesAssistant()).toHaveCount(2);
const secondRequest = chatRequests.find((request) => request.payload?.text === 'And now?');
const secondContext = secondRequest?.payload?.context;
expect(secondContext?.currentWorkflow).toBeUndefined();
await n8n.canvas.openNode(HTTP_REQUEST_NODE_NAME);
await n8n.ndv.setParameterInputValue('url', 'https://example.com');
await n8n.ndv.close();
await n8n.canvas.clickExecuteWorkflowButton();
await n8n.aiAssistant.sendMessage('What about now?', 'enter-key');
await expect(n8n.aiAssistant.getChatMessagesAssistant()).toHaveCount(3);
const thirdRequest = chatRequests.find(
(request) => request.payload?.text === 'What about now?',
);
const thirdContext = thirdRequest?.payload?.context;
expect(thirdContext?.currentWorkflow).toBeTruthy();
expect(thirdContext?.executionData).toBeTruthy();
});
});
});