feat: Add testcontainers and Playwright (no-changelog) (#16662)

Co-authored-by: Tomi Turtiainen <10324676+tomi@users.noreply.github.com>
This commit is contained in:
shortstacked
2025-07-01 14:15:31 +01:00
committed by GitHub
parent 422aa82524
commit 852657c17e
52 changed files with 5686 additions and 1111 deletions

View File

@@ -0,0 +1,113 @@
import { test, expect } from '../fixtures/base';
// Example of using helper functions inside a test
test.describe('Debug mode', () => {
// Constants to avoid magic strings
const URLS = {
FAILING: 'https://foo.bar',
SUCCESS: 'https://postman-echo.com/get?foo1=bar1&foo2=bar2',
};
const NOTIFICATIONS = {
WORKFLOW_CREATED: 'Workflow successfully created',
EXECUTION_IMPORTED: 'Execution data imported',
PROBLEM_IN_NODE: 'Problem in node',
SUCCESSFUL: 'Successful',
DATA_NOT_IMPORTED: "Some execution data wasn't imported",
};
test.beforeEach(async ({ api, n8n }) => {
await api.enableFeature('debugInEditor');
await n8n.goHome();
});
// Helper function to create basic workflow
async function createBasicWorkflow(n8n, url = URLS.FAILING) {
await n8n.workflows.clickAddWorklowButton();
await n8n.canvas.addNode('Manual Trigger');
await n8n.canvas.addNode('HTTP Request');
await n8n.ndv.fillParameterInput('URL', url);
await n8n.ndv.close();
await n8n.canvas.clickSaveWorkflowButton();
await n8n.notifications.waitForNotificationAndClose(NOTIFICATIONS.WORKFLOW_CREATED);
}
// Helper function to import execution for debugging
async function importExecutionForDebugging(n8n) {
await n8n.canvas.clickExecutionsTab();
await n8n.executions.clickDebugInEditorButton();
await n8n.notifications.waitForNotificationAndClose(NOTIFICATIONS.EXECUTION_IMPORTED);
}
test('should enter debug mode for failed executions', async ({ n8n }) => {
await createBasicWorkflow(n8n, URLS.FAILING);
await n8n.workflowComposer.executeWorkflowAndWaitForNotification(NOTIFICATIONS.PROBLEM_IN_NODE);
await importExecutionForDebugging(n8n);
expect(n8n.page.url()).toContain('/debug');
});
test('should exit debug mode after successful execution', async ({ n8n }) => {
await createBasicWorkflow(n8n, URLS.FAILING);
await n8n.workflowComposer.executeWorkflowAndWaitForNotification(NOTIFICATIONS.PROBLEM_IN_NODE);
await importExecutionForDebugging(n8n);
await n8n.canvas.openNode('HTTP Request');
await n8n.ndv.fillParameterInput('URL', URLS.SUCCESS);
await n8n.ndv.close();
await n8n.canvas.clickSaveWorkflowButton();
await n8n.workflowComposer.executeWorkflowAndWaitForNotification(NOTIFICATIONS.SUCCESSFUL);
expect(n8n.page.url()).not.toContain('/debug');
});
test('should handle pinned data conflicts during execution import', async ({ n8n }) => {
await createBasicWorkflow(n8n, URLS.SUCCESS);
await n8n.workflowComposer.executeWorkflowAndWaitForNotification(NOTIFICATIONS.SUCCESSFUL);
await n8n.canvasComposer.pinNodeData('HTTP Request');
await n8n.workflowComposer.executeWorkflowAndWaitForNotification('Successful');
// Go to executions and try to copy execution to editor
await n8n.canvas.clickExecutionsTab();
await n8n.executions.clickLastExecutionItem();
await n8n.executions.clickCopyToEditorButton();
// Test CANCEL dialog
await n8n.executions.handlePinnedNodesConfirmation('Cancel');
// Try again and CONFIRM
await n8n.executions.clickLastExecutionItem();
await n8n.executions.clickCopyToEditorButton();
await n8n.executions.handlePinnedNodesConfirmation('Unpin');
expect(n8n.page.url()).toContain('/debug');
// Verify pinned status
const pinnedNodeNames = await n8n.canvas.getPinnedNodeNames();
expect(pinnedNodeNames).not.toContain('HTTP Request');
expect(pinnedNodeNames).toContain('When clicking Execute workflow');
});
test('should show error for pinned data mismatch', async ({ n8n }) => {
// Create workflow, execute, and pin data
await createBasicWorkflow(n8n, URLS.SUCCESS);
await n8n.workflowComposer.executeWorkflowAndWaitForNotification(NOTIFICATIONS.SUCCESSFUL);
await n8n.canvasComposer.pinNodeData('HTTP Request');
await n8n.workflowComposer.executeWorkflowAndWaitForNotification(NOTIFICATIONS.SUCCESSFUL);
// Delete node to create mismatch
await n8n.canvas.deleteNodeByName('HTTP Request');
// Try to copy execution and verify error
await attemptCopyToEditor(n8n);
await n8n.notifications.waitForNotificationAndClose(NOTIFICATIONS.DATA_NOT_IMPORTED);
expect(n8n.page.url()).toContain('/debug');
});
async function attemptCopyToEditor(n8n) {
await n8n.canvas.clickExecutionsTab();
await n8n.executions.clickLastExecutionItem();
await n8n.executions.clickCopyToEditorButton();
}
});