feat(editor): Add ‘execute workflow’ buttons below triggers on the canvas (#12769)

Co-authored-by: Danny Martini <danny@n8n.io>
Co-authored-by: Mutasem Aldmour <mutasem@n8n.io>
This commit is contained in:
autologie
2025-02-10 09:14:39 +01:00
committed by GitHub
parent e92556260f
commit b17cbec3af
28 changed files with 957 additions and 168 deletions

View File

@@ -4,6 +4,10 @@
import { getVisiblePopper, getVisibleSelect } from '../utils/popper';
export function getNdvContainer() {
return cy.getByTestId('ndv');
}
export function getCredentialSelect(eq = 0) {
return cy.getByTestId('node-credentials-select').eq(eq);
}

View File

@@ -101,8 +101,8 @@ export function getNodeCreatorItems() {
return cy.getByTestId('item-iterator-item');
}
export function getExecuteWorkflowButton() {
return cy.getByTestId('execute-workflow-button');
export function getExecuteWorkflowButton(triggerNodeName?: string) {
return cy.getByTestId(`execute-workflow-button${triggerNodeName ? `-${triggerNodeName}` : ''}`);
}
export function getManualChatButton() {
@@ -294,8 +294,8 @@ export function addRetrieverNodeToParent(nodeName: string, parentNodeName: strin
addSupplementalNodeToParent(nodeName, 'ai_retriever', parentNodeName);
}
export function clickExecuteWorkflowButton() {
getExecuteWorkflowButton().click();
export function clickExecuteWorkflowButton(triggerNodeName?: string) {
getExecuteWorkflowButton(triggerNodeName).click();
}
export function clickManualChatButton() {

View File

@@ -1,3 +1,11 @@
import { clickGetBackToCanvas, getNdvContainer, getOutputTableRow } from '../composables/ndv';
import {
clickExecuteWorkflowButton,
getExecuteWorkflowButton,
getNodeByName,
getZoomToFitButton,
openNode,
} from '../composables/workflow';
import { SCHEDULE_TRIGGER_NODE_NAME, EDIT_FIELDS_SET_NODE_NAME } from '../constants';
import { NDV, WorkflowExecutionsTab, WorkflowPage as WorkflowPageClass } from '../pages';
import { clearNotifications, errorToast, successToast } from '../pages/notifications';
@@ -214,6 +222,39 @@ describe('Execution', () => {
workflowPage.getters.clearExecutionDataButton().should('not.exist');
});
it('should test workflow with specific trigger node', () => {
cy.createFixtureWorkflow('Two_schedule_triggers.json');
getZoomToFitButton().click();
getExecuteWorkflowButton('Trigger A').should('not.be.visible');
getExecuteWorkflowButton('Trigger B').should('not.be.visible');
// Execute the workflow from trigger A
getNodeByName('Trigger A').realHover();
getExecuteWorkflowButton('Trigger A').should('be.visible');
getExecuteWorkflowButton('Trigger B').should('not.be.visible');
clickExecuteWorkflowButton('Trigger A');
// Check the output
successToast().contains('Workflow executed successfully');
openNode('Edit Fields');
getOutputTableRow(1).should('include.text', 'Trigger A');
clickGetBackToCanvas();
getNdvContainer().should('not.be.visible');
// Execute the workflow from trigger B
getNodeByName('Trigger B').realHover();
getExecuteWorkflowButton('Trigger A').should('not.be.visible');
getExecuteWorkflowButton('Trigger B').should('be.visible');
clickExecuteWorkflowButton('Trigger B');
// Check the output
successToast().contains('Workflow executed successfully');
openNode('Edit Fields');
getOutputTableRow(1).should('include.text', 'Trigger B');
});
describe('execution preview', () => {
it('when deleting the last execution, it should show empty state', () => {
workflowPage.actions.addInitialNodeToCanvas('Manual Trigger');

View File

@@ -0,0 +1,76 @@
{
"nodes": [
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "6a8c3d85-26f8-4f28-ace9-55a196a23d37",
"name": "prevNode",
"value": "={{ $prevNode.name }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [200, -100],
"id": "351ce967-0399-4a78-848a-9cc69b831796",
"name": "Edit Fields"
},
{
"parameters": {
"rule": {
"interval": [{}]
}
},
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.2,
"position": [0, -100],
"id": "cf2f58a8-1fbb-4c70-b2b1-9e06bee7ec47",
"name": "Trigger A"
},
{
"parameters": {
"rule": {
"interval": [{}]
}
},
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.2,
"position": [0, 100],
"id": "4fade34e-2bfc-4a2e-a8ed-03ab2ed9c690",
"name": "Trigger B"
}
],
"connections": {
"Trigger A": {
"main": [
[
{
"node": "Edit Fields",
"type": "main",
"index": 0
}
]
]
},
"Trigger B": {
"main": [
[
{
"node": "Edit Fields",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {},
"meta": {
"instanceId": "0dd4627b77a5a795ab9bf073e5812be94dd8d1a5f012248ef2a4acac09be12cb"
}
}