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
119 lines
4.3 KiB
TypeScript
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();
|
|
});
|
|
});
|
|
});
|