mirror of
https://github.com/n8n-io/n8n.git
synced 2026-06-02 17:57:06 +02:00
Co-authored-by: Charlie Kolb <charlie@n8n.io> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
130 lines
5.1 KiB
TypeScript
130 lines
5.1 KiB
TypeScript
import { workflowBuilderEnabledRequirements } from '../../../config/ai-builder-fixtures';
|
|
import { test, expect } from '../../../fixtures/base';
|
|
import type { n8nPage } from '../../../pages/n8nPage';
|
|
|
|
// Helper to open workflow builder and click a specific suggestion pill
|
|
async function openBuilderAndClickSuggestion(n8n: n8nPage, suggestionText: string) {
|
|
await n8n.canvas.waitForBlankCanvasReady();
|
|
await n8n.aiBuilder.waitForCanvasBuildEntry();
|
|
await n8n.aiBuilder.getCanvasBuildWithAIButton().click();
|
|
await expect(n8n.aiAssistant.getAskAssistantChat()).toBeVisible();
|
|
await expect(n8n.aiBuilder.getWorkflowSuggestions()).toBeVisible();
|
|
|
|
// Wait for suggestions to load
|
|
await n8n.aiBuilder.getSuggestionPills().first().waitFor({ state: 'visible' });
|
|
|
|
// Find and click the specific suggestion pill by text
|
|
const targetPill = n8n.aiBuilder.getSuggestionPills().filter({ hasText: suggestionText });
|
|
await expect(targetPill).toBeVisible();
|
|
await targetPill.click();
|
|
|
|
// Suggestion pill already populated the input, just submit with Enter
|
|
await n8n.aiAssistant.sendMessage('', 'enter-key');
|
|
}
|
|
|
|
// Enable proxy server for recording/replaying Anthropic API calls
|
|
test.use({
|
|
capability: {
|
|
services: ['proxy'],
|
|
env: {
|
|
N8N_AI_ANTHROPIC_KEY: 'sk-ant-test-key-for-mocked-tests',
|
|
},
|
|
},
|
|
});
|
|
|
|
test.describe(
|
|
'Workflow Builder @auth:owner @ai @capability:proxy',
|
|
{
|
|
annotation: [{ type: 'owner', description: 'AI' }],
|
|
},
|
|
() => {
|
|
test.beforeEach(async ({ setupRequirements, services }) => {
|
|
await setupRequirements(workflowBuilderEnabledRequirements);
|
|
await services.proxy.clearAllExpectations();
|
|
await services.proxy.loadExpectations('workflow-builder');
|
|
});
|
|
|
|
test('should show Build with AI button on empty canvas', async ({ n8n }) => {
|
|
await n8n.page.goto('/workflow/new');
|
|
|
|
await n8n.canvas.waitForBlankCanvasReady();
|
|
await n8n.aiBuilder.waitForCanvasBuildEntry();
|
|
await expect(n8n.aiBuilder.getCanvasBuildWithAIButton()).toBeVisible();
|
|
});
|
|
|
|
test('should open workflow builder and show suggestions', async ({ n8n }) => {
|
|
await n8n.page.goto('/workflow/new');
|
|
|
|
await n8n.canvas.waitForBlankCanvasReady();
|
|
await n8n.aiBuilder.waitForCanvasBuildEntry();
|
|
await n8n.aiBuilder.getCanvasBuildWithAIButton().click();
|
|
|
|
await expect(n8n.aiAssistant.getAskAssistantSidebar()).toBeVisible();
|
|
await expect(n8n.aiAssistant.getAskAssistantChat()).toBeVisible();
|
|
await expect(n8n.aiBuilder.getWorkflowSuggestions()).toBeVisible();
|
|
|
|
await n8n.aiBuilder.getSuggestionPills().first().waitFor({ state: 'visible' });
|
|
const suggestions = n8n.aiBuilder.getSuggestionPills();
|
|
await expect(suggestions).toHaveCount(8);
|
|
});
|
|
|
|
// @AI team - investigated issues with this test, the replay of recorded events not working as expected
|
|
// doesn't appear to be matching in the correct order/some requests make it past the proxy leading to 401 error
|
|
test.fixme('should build workflow from suggested prompt', async ({ n8n }) => {
|
|
await n8n.page.goto('/workflow/new');
|
|
await openBuilderAndClickSuggestion(n8n, 'YouTube video chapters');
|
|
|
|
await expect(n8n.aiAssistant.getChatMessagesUser().first()).toBeVisible();
|
|
|
|
// Wait for workflow to be built
|
|
await n8n.aiBuilder.waitForWorkflowBuildComplete();
|
|
|
|
await expect(n8n.canvas.getCanvasNodes().first()).toBeVisible();
|
|
|
|
const nodeCount = await n8n.canvas.getCanvasNodes().count();
|
|
expect(nodeCount).toBeGreaterThan(0);
|
|
|
|
// Verify "Execute and refine" button appears after workflow is built
|
|
await expect(n8n.page.getByRole('button', { name: 'Execute and refine' })).toBeVisible();
|
|
});
|
|
|
|
// suffers from the same issue as test above
|
|
test.fixme('should display assistant messages during workflow generation', async ({ n8n }) => {
|
|
await n8n.page.goto('/workflow/new');
|
|
await openBuilderAndClickSuggestion(n8n, 'YouTube video chapters');
|
|
|
|
await expect(n8n.aiAssistant.getChatMessagesUser().first()).toBeVisible();
|
|
await n8n.aiAssistant.waitForStreamingComplete();
|
|
|
|
const assistantMessages = n8n.aiAssistant.getChatMessagesAssistant();
|
|
await expect(assistantMessages.first()).toBeVisible();
|
|
|
|
const messageCount = await assistantMessages.count();
|
|
expect(messageCount).toBeGreaterThan(0);
|
|
});
|
|
|
|
test('should stop workflow generation and show task aborted message', async ({ n8n }) => {
|
|
await n8n.page.goto('/workflow/new');
|
|
await openBuilderAndClickSuggestion(n8n, 'Daily weather report');
|
|
|
|
await expect(n8n.aiAssistant.getChatMessagesUser().first()).toBeVisible();
|
|
|
|
// Wait for stop button to be enabled (streaming has started)
|
|
const stopButton = n8n.aiAssistant.getSendMessageButton();
|
|
await expect(stopButton).toBeEnabled({ timeout: 30000 });
|
|
|
|
await stopButton.click();
|
|
|
|
// Verify "Task aborted" message appears (search by text, not test-id)
|
|
await expect(n8n.page.getByText('Task aborted')).toBeVisible();
|
|
|
|
// Verify canvas returns to default state (no nodes added)
|
|
const nodeCount = await n8n.canvas.getCanvasNodes().count();
|
|
expect(nodeCount).toBe(0);
|
|
|
|
// Verify the Build with AI button is still visible (canvas is back to default)
|
|
await expect(n8n.aiBuilder.getCanvasBuildWithAIButton()).toBeVisible();
|
|
});
|
|
},
|
|
);
|