chore: Add e2e tests for Subworkflow Conversion (no-changelog) (#16220)

This commit is contained in:
Charlie Kolb
2025-06-11 14:30:35 +02:00
committed by GitHub
parent 3946e5c244
commit 21b84ef4e7
4 changed files with 373 additions and 1 deletions

View File

@@ -1,6 +1,6 @@
import { getManualChatModal } from './modals/chat-modal';
import { clickGetBackToCanvas, getParameterInputByName } from './ndv';
import { ROUTES } from '../constants';
import { META_KEY, ROUTES } from '../constants';
import type { OpenContextMenuOptions } from '../types';
/**
@@ -364,3 +364,48 @@ export function openExecutions() {
export function clickClearExecutionDataButton() {
cy.getByTestId('clear-execution-data-button').click();
}
/**
* Undo/Redo
*/
export function hitComboShortcut(modifier: string, key: string) {
cy.get('body').wait(100).type(modifier, { delay: 100, release: false }).type(key);
}
export function hitUndo() {
hitComboShortcut(`{${META_KEY}}`, 'z');
}
export function hitRedo() {
cy.get('body').type(`{${META_KEY}+shift+z}`);
}
export function hitSelectAll() {
hitComboShortcut(`{${META_KEY}}`, 'a');
}
export function hitDeleteAllNodes() {
hitSelectAll();
cy.get('body').type('{backspace}');
}
export function hitDisableNodeShortcut() {
cy.get('body').type('d');
}
export function hitCopy() {
hitComboShortcut(`{${META_KEY}}`, 'c');
}
export function hitPinNodeShortcut() {
cy.get('body').type('p');
}
export function hitSaveWorkflow() {
cy.get('body').type(`{${META_KEY}+s}`);
}
export function hitExecuteWorkflow() {
cy.get('body').type(`{${META_KEY}+enter}`);
}
export function hitDuplicateNode() {
cy.get('body').type(`{${META_KEY}+d}`);
}
export function hitAddSticky() {
cy.get('body').type('{shift+S}');
}
export function selectRight() {
cy.get('body').type('{shift+rightArrow}');
}

View File

@@ -0,0 +1,80 @@
import {
clickContextMenuAction,
clickZoomToFit,
executeWorkflow,
getCanvasNodeByName,
getCanvasNodes,
hitUndo,
navigateToNewWorkflowPage,
openContextMenu,
pasteWorkflow,
saveWorkflowOnButtonClick,
selectRight,
} from '../composables/workflow';
import SubworkflowExtractionFixture from '../fixtures/Subworkflow-extraction-workflow.json';
import { clearAnyNotifications, successToast } from '../pages/notifications';
const EDIT_FIELDS_NAMES = [
'Edit Fields0',
'Edit Fields1',
'Edit Fields2',
'Edit Fields3',
'Edit Fields4',
'Edit Fields5',
] as const;
function selectNode(nodeName: string) {
getCanvasNodeByName(nodeName).click();
}
function executeAndConfirmSuccess() {
executeWorkflow();
successToast().should('contain.text', 'Workflow executed successfully');
clearAnyNotifications();
}
describe('Subworkflow Extraction', () => {
beforeEach(() => {
navigateToNewWorkflowPage();
// this selects all nodes
pasteWorkflow(SubworkflowExtractionFixture);
saveWorkflowOnButtonClick();
getCanvasNodes().should('have.length', 7);
clickZoomToFit();
executeAndConfirmSuccess();
openContextMenu();
clickContextMenuAction('deselect_all');
});
describe('can extract a valid selection and still execute the workflow', () => {
it('should extract a node and succeed execution, and then undo and succeed executions', () => {
for (const name of EDIT_FIELDS_NAMES) {
selectNode(name);
openContextMenu(name);
clickContextMenuAction('extract_sub_workflow');
cy.getByTestId('submit-button').click();
executeAndConfirmSuccess();
}
for (const _ of EDIT_FIELDS_NAMES) {
hitUndo();
executeAndConfirmSuccess();
}
});
it('should extract all nodes besides trigger and succeed execution', () => {
selectNode(EDIT_FIELDS_NAMES[0]);
selectRight();
openContextMenu();
clickContextMenuAction('extract_sub_workflow');
cy.getByTestId('submit-button').click();
executeAndConfirmSuccess();
});
});
});

View File

@@ -0,0 +1,231 @@
{
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [0, -5],
"id": "41b93a1d-ca68-49c1-b252-323e57f58ba9",
"name": "When clicking Execute workflow"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "624c7310-e17a-4075-922f-3b57952e3dfa",
"name": "x",
"value": "={{ $json.x + 'a' }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [220, -5],
"id": "afd95339-62f5-4efd-bcaa-637cec90ab0f",
"name": "Edit Fields0"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "624c7310-e17a-4075-922f-3b57952e3dfa",
"name": "x",
"value": "={{ $json.x + 'a' + $('When clicking Execute workflow').item.json.x}}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [440, 120],
"id": "c279107f-08c2-4be6-9016-d19215cfeb9e",
"name": "Edit Fields1"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "624c7310-e17a-4075-922f-3b57952e3dfa",
"name": "x",
"value": "={{ $json.x + 'a' + $('When clicking Execute workflow').first().json.x }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [440, -120],
"id": "1d4eb1a0-ad87-4d8b-87e6-c853f27aa8ad",
"name": "Edit Fields2"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "624c7310-e17a-4075-922f-3b57952e3dfa",
"name": "x",
"value": "={{ $json.x + 'a' + $('When clicking Execute workflow').last().json.x}}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [440, -320],
"id": "b99d763e-cb4c-487f-8718-8b9a5f02c167",
"name": "Edit Fields3"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "624c7310-e17a-4075-922f-3b57952e3dfa",
"name": "x",
"value": "={{ $json.x + 'a' + $('When clicking Execute workflow').item.json.x}}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [720, 0],
"id": "4244c039-51c3-415b-8b3d-06be5a90dc7a",
"name": "Edit Fields4"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "624c7310-e17a-4075-922f-3b57952e3dfa",
"name": "x",
"value": "={{ $json.x + 'a' + $('When clicking Execute workflow').item.json.x + $('Edit Fields0').item.json.x }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [960, 0],
"id": "2653bbfe-8f06-4029-9071-8faacfb73cd0",
"name": "Edit Fields5"
}
],
"connections": {
"When clicking Execute workflow": {
"main": [
[
{
"node": "Edit Fields0",
"type": "main",
"index": 0
}
]
]
},
"Edit Fields0": {
"main": [
[
{
"node": "Edit Fields1",
"type": "main",
"index": 0
},
{
"node": "Edit Fields2",
"type": "main",
"index": 0
},
{
"node": "Edit Fields3",
"type": "main",
"index": 0
},
{
"node": "Edit Fields4",
"type": "main",
"index": 0
}
]
]
},
"Edit Fields1": {
"main": [
[
{
"node": "Edit Fields4",
"type": "main",
"index": 0
}
]
]
},
"Edit Fields2": {
"main": [
[
{
"node": "Edit Fields4",
"type": "main",
"index": 0
}
]
]
},
"Edit Fields3": {
"main": [
[
{
"node": "Edit Fields4",
"type": "main",
"index": 0
}
]
]
},
"Edit Fields4": {
"main": [
[
{
"node": "Edit Fields5",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {
"When clicking Execute workflow": [
{
"x": "l"
},
{
"x": "m"
},
{
"x": "o"
}
]
},
"meta": {
"instanceId": "d30ee1956588565f63beb4b8b589790a4701843b47fcd9e8d6d5527fe47872c3"
}
}

View File

@@ -24,3 +24,19 @@ export const clearNotifications = () => {
}
});
};
// Clears notifications without asserting their existence
export const clearAnyNotifications = () => {
const notificationSelector = '.el-notification:has(.el-notification--success)';
cy.get('body')
.should('have.length.gte', 0)
.then(($body) => {
if ($body.find(notificationSelector).length) {
cy.get(notificationSelector).each(($el) => {
if ($el.find('.el-notification__closeBtn').length) {
cy.wrap($el).find('.el-notification__closeBtn').click({ force: true });
}
});
}
});
};