first commit
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
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
This commit is contained in:
@@ -0,0 +1,289 @@
|
||||
import { test, expect } from '../../../fixtures/base';
|
||||
import type { TestRequirements } from '../../../Types';
|
||||
|
||||
const requirements: TestRequirements = {
|
||||
config: {
|
||||
settings: {
|
||||
previewMode: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// Simple workflow structures for testing
|
||||
const oldWorkflow = {
|
||||
id: 'old-workflow-id',
|
||||
name: 'Test Workflow - Before',
|
||||
nodes: [
|
||||
{
|
||||
parameters: {},
|
||||
id: '1',
|
||||
name: 'Manual Trigger',
|
||||
type: 'n8n-nodes-base.manualTrigger',
|
||||
typeVersion: 1,
|
||||
position: [250, 300],
|
||||
},
|
||||
{
|
||||
parameters: {},
|
||||
id: '2',
|
||||
name: 'Set',
|
||||
type: 'n8n-nodes-base.set',
|
||||
typeVersion: 1,
|
||||
position: [450, 300],
|
||||
},
|
||||
],
|
||||
connections: {
|
||||
'Manual Trigger': {
|
||||
main: [
|
||||
[
|
||||
{
|
||||
node: 'Set',
|
||||
type: 'main',
|
||||
index: 0,
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const newWorkflow = {
|
||||
id: 'new-workflow-id',
|
||||
name: 'Test Workflow - After',
|
||||
nodes: [
|
||||
{
|
||||
parameters: {},
|
||||
id: '1',
|
||||
name: 'Manual Trigger',
|
||||
type: 'n8n-nodes-base.manualTrigger',
|
||||
typeVersion: 1,
|
||||
position: [250, 300],
|
||||
},
|
||||
{
|
||||
parameters: {
|
||||
options: {
|
||||
keepOnlySet: true,
|
||||
},
|
||||
},
|
||||
id: '2',
|
||||
name: 'Set',
|
||||
type: 'n8n-nodes-base.set',
|
||||
typeVersion: 1,
|
||||
position: [450, 300],
|
||||
},
|
||||
{
|
||||
parameters: {},
|
||||
id: '3',
|
||||
name: 'Code',
|
||||
type: 'n8n-nodes-base.code',
|
||||
typeVersion: 1,
|
||||
position: [650, 300],
|
||||
},
|
||||
],
|
||||
connections: {
|
||||
'Manual Trigger': {
|
||||
main: [
|
||||
[
|
||||
{
|
||||
node: 'Set',
|
||||
type: 'main',
|
||||
index: 0,
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
Set: {
|
||||
main: [
|
||||
[
|
||||
{
|
||||
node: 'Code',
|
||||
type: 'main',
|
||||
index: 0,
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
test.describe('Workflow Diff Demo', {
|
||||
annotation: [
|
||||
{ type: 'owner', description: 'Adore' },
|
||||
],
|
||||
}, () => {
|
||||
test.beforeEach(async ({ setupRequirements }) => {
|
||||
await setupRequirements(requirements);
|
||||
});
|
||||
|
||||
test('shows waiting state initially', async ({ n8n }) => {
|
||||
await n8n.page.goto('/workflows/demo/diff');
|
||||
// Verify the waiting state message is shown
|
||||
await expect(n8n.page.getByText('Waiting for workflow data...')).toBeVisible();
|
||||
});
|
||||
|
||||
test('renders diff view when receiving workflow data via postMessage', async ({ n8n }) => {
|
||||
await n8n.page.goto('/workflows/demo/diff');
|
||||
|
||||
// Verify the waiting state is initially shown
|
||||
await expect(n8n.page.getByText('Waiting for workflow data...')).toBeVisible();
|
||||
|
||||
// Send postMessage with workflow data
|
||||
await n8n.page.evaluate(
|
||||
({ oldWf, newWf }) => {
|
||||
window.postMessage(
|
||||
JSON.stringify({
|
||||
command: 'openDiff',
|
||||
oldWorkflow: oldWf,
|
||||
newWorkflow: newWf,
|
||||
}),
|
||||
'*',
|
||||
);
|
||||
},
|
||||
{ oldWf: oldWorkflow, newWf: newWorkflow },
|
||||
);
|
||||
|
||||
// Wait for the diff view to appear - the waiting message should disappear
|
||||
await expect(n8n.page.getByText('Waiting for workflow data...')).toBeHidden();
|
||||
|
||||
// The workflow name should appear in the header
|
||||
await expect(
|
||||
n8n.page.getByRole('heading', { name: /Test Workflow/, exact: false }),
|
||||
).toBeVisible();
|
||||
|
||||
// The Changes button should be visible (part of the diff view header)
|
||||
await expect(n8n.page.getByRole('button', { name: /Changes/ })).toBeVisible();
|
||||
});
|
||||
|
||||
test('renders diff view with only new workflow (creation scenario)', async ({ n8n }) => {
|
||||
await n8n.page.goto('/workflows/demo/diff');
|
||||
|
||||
// Wait for the page to be ready (component mounted with event listener active)
|
||||
await expect(n8n.page.getByText('Waiting for workflow data...')).toBeVisible();
|
||||
|
||||
// Send postMessage with only newWorkflow (simulating workflow creation)
|
||||
await n8n.page.evaluate(
|
||||
({ newWf }) => {
|
||||
window.postMessage(
|
||||
JSON.stringify({
|
||||
command: 'openDiff',
|
||||
newWorkflow: newWf,
|
||||
}),
|
||||
'*',
|
||||
);
|
||||
},
|
||||
{ newWf: newWorkflow },
|
||||
);
|
||||
|
||||
// Wait for the diff view to appear
|
||||
await expect(n8n.page.getByText('Waiting for workflow data...')).toBeHidden();
|
||||
|
||||
// The workflow name from newWorkflow should appear
|
||||
await expect(n8n.page.getByRole('heading', { name: 'Test Workflow - After' })).toBeVisible();
|
||||
});
|
||||
|
||||
test('renders diff view with only old workflow (deletion scenario)', async ({ n8n }) => {
|
||||
await n8n.page.goto('/workflows/demo/diff');
|
||||
|
||||
// Wait for the page to be ready (component mounted with event listener active)
|
||||
await expect(n8n.page.getByText('Waiting for workflow data...')).toBeVisible();
|
||||
|
||||
// Send postMessage with only oldWorkflow (simulating workflow deletion)
|
||||
await n8n.page.evaluate(
|
||||
({ oldWf }) => {
|
||||
window.postMessage(
|
||||
JSON.stringify({
|
||||
command: 'openDiff',
|
||||
oldWorkflow: oldWf,
|
||||
}),
|
||||
'*',
|
||||
);
|
||||
},
|
||||
{ oldWf: oldWorkflow },
|
||||
);
|
||||
|
||||
// Wait for the diff view to appear
|
||||
await expect(n8n.page.getByText('Waiting for workflow data...')).toBeHidden();
|
||||
|
||||
// The workflow name from oldWorkflow should appear
|
||||
await expect(n8n.page.getByRole('heading', { name: 'Test Workflow - Before' })).toBeVisible();
|
||||
});
|
||||
|
||||
test('applies tidy up when tidyUp option is true', async ({ n8n }) => {
|
||||
await n8n.page.goto('/workflows/demo/diff');
|
||||
|
||||
// Wait for the page to be ready (component mounted with event listener active)
|
||||
await expect(n8n.page.getByText('Waiting for workflow data...')).toBeVisible();
|
||||
|
||||
// Send postMessage with tidyUp: true
|
||||
await n8n.page.evaluate(
|
||||
({ oldWf, newWf }) => {
|
||||
window.postMessage(
|
||||
JSON.stringify({
|
||||
command: 'openDiff',
|
||||
oldWorkflow: oldWf,
|
||||
newWorkflow: newWf,
|
||||
tidyUp: true,
|
||||
}),
|
||||
'*',
|
||||
);
|
||||
},
|
||||
{ oldWf: oldWorkflow, newWf: newWorkflow },
|
||||
);
|
||||
|
||||
// Wait for the diff view to appear
|
||||
await expect(n8n.page.getByText('Waiting for workflow data...')).toBeHidden();
|
||||
|
||||
// The diff view should render (tidyUp affects node positioning but view should still render)
|
||||
await expect(
|
||||
n8n.page.getByRole('heading', { name: /Test Workflow/, exact: false }),
|
||||
).toBeVisible();
|
||||
|
||||
// The Changes button should be visible (part of the diff view header)
|
||||
await expect(n8n.page.getByRole('button', { name: /Changes/ })).toBeVisible();
|
||||
});
|
||||
|
||||
test('ignores malformed postMessage data', async ({ n8n }) => {
|
||||
await n8n.page.goto('/workflows/demo/diff');
|
||||
|
||||
// Verify initial waiting state
|
||||
await expect(n8n.page.getByText('Waiting for workflow data...')).toBeVisible();
|
||||
|
||||
// Send malformed message
|
||||
await n8n.page.evaluate(() => {
|
||||
window.postMessage('not valid json {{{', '*');
|
||||
});
|
||||
|
||||
// Waiting state should still be shown
|
||||
await expect(n8n.page.getByText('Waiting for workflow data...')).toBeVisible();
|
||||
});
|
||||
|
||||
test('ignores non-openDiff commands', async ({ n8n }) => {
|
||||
await n8n.page.goto('/workflows/demo/diff');
|
||||
|
||||
// Verify initial waiting state
|
||||
await expect(n8n.page.getByText('Waiting for workflow data...')).toBeVisible();
|
||||
|
||||
// Send a different command
|
||||
await n8n.page.evaluate(() => {
|
||||
window.postMessage(
|
||||
JSON.stringify({
|
||||
command: 'someOtherCommand',
|
||||
data: {},
|
||||
}),
|
||||
'*',
|
||||
);
|
||||
});
|
||||
|
||||
// Waiting state should still be shown
|
||||
await expect(n8n.page.getByText('Waiting for workflow data...')).toBeVisible();
|
||||
});
|
||||
|
||||
test('can override theme to dark', async ({ n8n }) => {
|
||||
await n8n.page.goto('/workflows/demo/diff?theme=dark');
|
||||
await expect(n8n.page.locator('body')).toHaveAttribute('data-theme', 'dark');
|
||||
});
|
||||
|
||||
test('can override theme to light', async ({ n8n }) => {
|
||||
await n8n.page.goto('/workflows/demo/diff?theme=light');
|
||||
await expect(n8n.page.locator('body')).toHaveAttribute('data-theme', 'light');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user