import { codeDiffSuggestionResponse, applyCodeDiffResponse, nodeExecutionSucceededResponse, aiEnabledWorkflowBaseRequirements, aiEnabledWithCodeDiffRequirements, } from '../../../config/ai-assistant-fixtures'; import { test, expect } from '../../../fixtures/base'; test.describe('AI Assistant::enabled', { annotation: [ { type: 'owner', description: 'AI' }, ], }, () => { test.describe('Code Node Error Help', () => { test('should apply code diff to code node', async ({ n8n, setupRequirements }) => { await setupRequirements(aiEnabledWithCodeDiffRequirements); let applySuggestionCalls = 0; await n8n.page.route('**/rest/ai/chat/apply-suggestion', async (route) => { applySuggestionCalls += 1; await route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(applyCodeDiffResponse), }); }); await n8n.canvas.openNode('Code'); await n8n.ndv.execute(); await n8n.aiAssistant.getNodeErrorViewAssistantButton().click(); await expect(n8n.aiAssistant.getChatMessagesAll()).toHaveCount(2); await expect(n8n.aiAssistant.getCodeDiffs()).toHaveCount(1); await expect(n8n.aiAssistant.getApplyCodeDiffButtons()).toHaveCount(1); await n8n.aiAssistant.getApplyCodeDiffButtons().first().click(); await expect(n8n.aiAssistant.getApplyCodeDiffButtons()).toHaveCount(0); await expect(n8n.aiAssistant.getUndoReplaceCodeButtons()).toHaveCount(1); await expect(n8n.aiAssistant.getCodeReplacedMessage()).toBeVisible(); await expect(n8n.ndv.getCodeEditor()).toContainText('item.json.myNewField = 1'); await n8n.aiAssistant.getUndoReplaceCodeButtons().first().click(); await expect(n8n.aiAssistant.getApplyCodeDiffButtons()).toHaveCount(1); await expect(n8n.aiAssistant.getCodeReplacedMessage()).toHaveCount(0); expect(applySuggestionCalls).toBe(1); await expect(n8n.ndv.getCodeEditor()).toContainText('item.json.myNewField = 1aaa'); await n8n.aiAssistant.getApplyCodeDiffButtons().first().click(); await expect(n8n.ndv.getCodeEditor()).toContainText('item.json.myNewField = 1'); }); test('should ignore node execution success and error messages after the node run successfully once', async ({ n8n, setupRequirements, }) => { await setupRequirements(aiEnabledWorkflowBaseRequirements); let chatRequestCount = 0; await n8n.page.route('**/rest/ai/chat', async (route) => { chatRequestCount += 1; const response = chatRequestCount === 1 ? codeDiffSuggestionResponse : nodeExecutionSucceededResponse; await route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(response), }); }); await n8n.canvas.openNode('Code'); await n8n.ndv.execute(); await n8n.aiAssistant.getNodeErrorViewAssistantButton().click(); await n8n.ndv .getCodeEditor() .fill( "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\nfor (const item of $input.all()) {\n item.json.myNewField = 1;\n}\n\nreturn $input.all();", ); await n8n.ndv.execute(); await n8n.ndv .getCodeEditor() .fill( "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\nfor (const item of $input.all()) {\n item.json.myNewField = 1aaaa!;\n}\n\nreturn $input.all();", ); await n8n.ndv.execute(); await expect(n8n.aiAssistant.getChatMessagesAssistant().nth(2)).toContainText( 'Code node ran successfully, did my solution help resolve your issue?', ); }); }); });