mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
fix(editor): Prevent excess runs in manual execution with run data (#9259)
This commit is contained in:
parent
9f6f8eae6d
commit
426a12ac0e
28
cypress/e2e/40-manual-partial-execution.cy.ts
Normal file
28
cypress/e2e/40-manual-partial-execution.cy.ts
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import { NDV, WorkflowPage } from '../pages';
|
||||||
|
|
||||||
|
const canvas = new WorkflowPage();
|
||||||
|
const ndv = new NDV();
|
||||||
|
|
||||||
|
describe('Manual partial execution', () => {
|
||||||
|
it('should execute parent nodes with no run data only once', () => {
|
||||||
|
canvas.actions.visit();
|
||||||
|
|
||||||
|
cy.fixture('manual-partial-execution.json').then((data) => {
|
||||||
|
cy.get('body').paste(JSON.stringify(data));
|
||||||
|
});
|
||||||
|
|
||||||
|
canvas.actions.zoomToFit();
|
||||||
|
|
||||||
|
canvas.actions.openNode('Edit Fields');
|
||||||
|
|
||||||
|
cy.get('button').contains('Test step').click(); // create run data
|
||||||
|
cy.get('button').contains('Test step').click(); // use run data
|
||||||
|
|
||||||
|
ndv.actions.close();
|
||||||
|
|
||||||
|
canvas.actions.openNode('Webhook1');
|
||||||
|
|
||||||
|
ndv.getters.nodeRunSuccessIndicator().should('exist');
|
||||||
|
ndv.getters.outputRunSelector().should('not.exist'); // single run
|
||||||
|
});
|
||||||
|
});
|
107
cypress/fixtures/manual-partial-execution.json
Normal file
107
cypress/fixtures/manual-partial-execution.json
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"templateCredsSetupCompleted": true
|
||||||
|
},
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"id": "f4467143-fdb9-46fa-8020-6417cc5eea7d",
|
||||||
|
"name": "Edit Fields",
|
||||||
|
"type": "n8n-nodes-base.set",
|
||||||
|
"typeVersion": 3.3,
|
||||||
|
"position": [
|
||||||
|
1140,
|
||||||
|
260
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"path": "30ff316d-405f-4288-a0ac-e713546c9d4e",
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"id": "4760aafb-5d56-4633-99d3-7a97c576a216",
|
||||||
|
"name": "Webhook1",
|
||||||
|
"type": "n8n-nodes-base.webhook",
|
||||||
|
"typeVersion": 2,
|
||||||
|
"position": [
|
||||||
|
680,
|
||||||
|
340
|
||||||
|
],
|
||||||
|
"webhookId": "30ff316d-405f-4288-a0ac-e713546c9d4e"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"articleId": "123",
|
||||||
|
"additionalFields": {}
|
||||||
|
},
|
||||||
|
"id": "8c811eca-8978-44d9-b8f7-ef2c7725784c",
|
||||||
|
"name": "Hacker News",
|
||||||
|
"type": "n8n-nodes-base.hackerNews",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [
|
||||||
|
920,
|
||||||
|
260
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"path": "4a3398e4-1388-4e10-9d21-add90b804955",
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"id": "1c2c2d06-45c9-4712-9fa0-c655bef8d0e5",
|
||||||
|
"name": "Webhook",
|
||||||
|
"type": "n8n-nodes-base.webhook",
|
||||||
|
"typeVersion": 2,
|
||||||
|
"position": [
|
||||||
|
680,
|
||||||
|
180
|
||||||
|
],
|
||||||
|
"webhookId": "4a3398e4-1388-4e10-9d21-add90b804955"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": {
|
||||||
|
"Webhook1": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Hacker News",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Hacker News": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Edit Fields",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Webhook": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Hacker News",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pinData": {
|
||||||
|
"Webhook": [
|
||||||
|
{
|
||||||
|
"name": "First item",
|
||||||
|
"code": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -334,7 +334,7 @@ export function useRunWorkflow(useRunWorkflowOpts: { router: ReturnType<typeof u
|
||||||
pinData: IPinData | undefined,
|
pinData: IPinData | undefined,
|
||||||
workflow: Workflow,
|
workflow: Workflow,
|
||||||
): { runData: IRunData | undefined; startNodeNames: string[] } {
|
): { runData: IRunData | undefined; startNodeNames: string[] } {
|
||||||
const startNodeNames: string[] = [];
|
const startNodeNames = new Set<string>();
|
||||||
let newRunData: IRunData | undefined;
|
let newRunData: IRunData | undefined;
|
||||||
|
|
||||||
if (runData !== null && Object.keys(runData).length !== 0) {
|
if (runData !== null && Object.keys(runData).length !== 0) {
|
||||||
|
@ -360,7 +360,7 @@ export function useRunWorkflow(useRunWorkflowOpts: { router: ReturnType<typeof u
|
||||||
// When we hit a node which has no data we stop and set it
|
// When we hit a node which has no data we stop and set it
|
||||||
// as a start node the execution from and then go on with other
|
// as a start node the execution from and then go on with other
|
||||||
// direct input nodes
|
// direct input nodes
|
||||||
startNodeNames.push(parentNode);
|
startNodeNames.add(parentNode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (runData[parentNode] && !runData[parentNode]?.[0]?.error) {
|
if (runData[parentNode] && !runData[parentNode]?.[0]?.error) {
|
||||||
|
@ -376,7 +376,7 @@ export function useRunWorkflow(useRunWorkflowOpts: { router: ReturnType<typeof u
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { runData: newRunData, startNodeNames };
|
return { runData: newRunData, startNodeNames: [...startNodeNames] };
|
||||||
}
|
}
|
||||||
|
|
||||||
async function stopCurrentExecution() {
|
async function stopCurrentExecution() {
|
||||||
|
|
Loading…
Reference in a new issue