diff --git a/packages/core/src/WorkflowExecute.ts b/packages/core/src/WorkflowExecute.ts index ec58e6c5d2381..ce17eafa9bb0d 100644 --- a/packages/core/src/WorkflowExecute.ts +++ b/packages/core/src/WorkflowExecute.ts @@ -1125,7 +1125,6 @@ export class WorkflowExecute { ); const errorItems: INodeExecutionData[] = []; - const successItems: INodeExecutionData[] = []; const closeFunctions: CloseFunction[] = []; // Create a WorkflowDataProxy instance that we can get the data of the // item which did error @@ -1150,8 +1149,10 @@ export class WorkflowExecute { outputIndex < mainOutputTypes.length - 1; outputIndex++ ) { - successItems.length = 0; - const items = nodeSuccessData.length ? nodeSuccessData[0] : []; + const successItems: INodeExecutionData[] = []; + const items = nodeSuccessData[outputIndex]?.length + ? nodeSuccessData[outputIndex] + : []; while (items.length) { const item = items.pop(); diff --git a/packages/core/test/WorkflowExecute.test.ts b/packages/core/test/WorkflowExecute.test.ts index 684aeaee559d5..0d2b6a735c7c2 100644 --- a/packages/core/test/WorkflowExecute.test.ts +++ b/packages/core/test/WorkflowExecute.test.ts @@ -120,7 +120,10 @@ describe('WorkflowExecute', () => { if (nodeData.data === undefined) { return null; } - return nodeData.data.main[0]!.map((entry) => entry.json); + const toMap = testData.output.testAllOutputs + ? nodeData.data.main + : [nodeData.data.main[0]!]; + return toMap.map((data) => data!.map((entry) => entry.json)); }); // expect(resultData).toEqual(testData.output.nodeData[nodeName]); diff --git a/packages/core/test/helpers/constants.ts b/packages/core/test/helpers/constants.ts index c71044cdb38ba..8bbb3f200bd97 100644 --- a/packages/core/test/helpers/constants.ts +++ b/packages/core/test/helpers/constants.ts @@ -2786,22 +2786,28 @@ export const v1WorkflowExecuteTests: WorkflowTestData[] = [ nodeData: { Set1: [ [ - { - value1: 1, - }, + [ + { + value1: 1, + }, + ], ], ], Set2: [ [ - { - value1: 1, - value2: 2, - }, + [ + { + value1: 1, + value2: 2, + }, + ], ], [ - { - value2: 2, - }, + [ + { + value2: 2, + }, + ], ], ], }, @@ -3065,74 +3071,90 @@ export const v1WorkflowExecuteTests: WorkflowTestData[] = [ nodeData: { Set1: [ [ - { - value1: 1, - }, + [ + { + value1: 1, + }, + ], ], ], Set2: [ [ - { - value2: 2, - }, + [ + { + value2: 2, + }, + ], ], ], Set3: [ [ - { - value1: 1, - value3: 3, - }, + [ + { + value1: 1, + value3: 3, + }, + ], ], ], Set4: [ [ - { - value1: 1, - value3: 3, - value4: 4, - }, + [ + { + value1: 1, + value3: 3, + value4: 4, + }, + ], ], ], Merge1: [ [ - { - value1: 1, - }, - { - value2: 2, - }, + [ + { + value1: 1, + }, + { + value2: 2, + }, + ], ], ], Merge2: [ [ - { - value2: 2, - }, + [ + { + value2: 2, + }, + ], ], ], Merge3: [ [ - { - value1: 1, - value3: 3, - value4: 4, - }, - { - value2: 2, - }, + [ + { + value1: 1, + value3: 3, + value4: 4, + }, + { + value2: 2, + }, + ], ], ], Merge4: [ [ - { - value1: 1, - value3: 3, - value4: 4, - }, - { - value2: 2, - }, + [ + { + value1: 1, + value3: 3, + value4: 4, + }, + { + value2: 2, + }, + ], ], ], }, @@ -3903,113 +3925,143 @@ export const v1WorkflowExecuteTests: WorkflowTestData[] = [ 'Merge2', ], nodeData: { - Start: [[{}]], + Start: [[[{}]]], Set1: [ [ - { - counter: 1, - }, + [ + { + counter: 1, + }, + ], ], [ - { - counter: 2, - }, + [ + { + counter: 2, + }, + ], ], [ - { - counter: 3, - }, + [ + { + counter: 3, + }, + ], ], ], Set: [ [ - { - counter: 1, - }, + [ + { + counter: 1, + }, + ], ], [ - { - counter: 2, - }, + [ + { + counter: 2, + }, + ], ], [ - { - counter: 3, - }, + [ + { + counter: 3, + }, + ], ], ], IF1: [ [ - { - counter: 1, - }, + [ + { + counter: 1, + }, + ], ], [ - { - counter: 2, - }, + [ + { + counter: 2, + }, + ], ], - [], + [[]], ], IF: [ [ - { - counter: 1, - }, + [ + { + counter: 1, + }, + ], ], [ - { - counter: 2, - }, + [ + { + counter: 2, + }, + ], ], - [], + [[]], ], Merge1: [ [ - { - counter: 1, - }, - { - counter: 1, - }, + [ + { + counter: 1, + }, + { + counter: 1, + }, + ], ], [ - { - counter: 2, - }, - { - counter: 2, - }, + [ + { + counter: 2, + }, + { + counter: 2, + }, + ], ], ], Merge: [ [ - { - counter: 3, - }, - {}, + [ + { + counter: 3, + }, + {}, + ], ], ], Merge2: [ [ - { - counter: 1, - }, - { - counter: 1, - }, - { - counter: 3, - }, - {}, + [ + { + counter: 1, + }, + { + counter: 1, + }, + { + counter: 3, + }, + {}, + ], ], [ - { - counter: 2, - }, - { - counter: 2, - }, + [ + { + counter: 2, + }, + { + counter: 2, + }, + ], ], ], }, @@ -4159,9 +4211,11 @@ export const v1WorkflowExecuteTests: WorkflowTestData[] = [ nodeData: { Merge: [ [ - { - test: 'a', - }, + [ + { + test: 'a', + }, + ], ], ], }, @@ -4535,62 +4589,390 @@ export const v1WorkflowExecuteTests: WorkflowTestData[] = [ nodeData: { Merge1: [ [ - { - test: 'a', - }, + [ + { + test: 'a', + }, + ], ], ], Merge2: [ [ - { - test: 'a', - }, + [ + { + test: 'a', + }, + ], ], ], Merge4: [ [ - { - test: 'a', - }, - { - test: 'a', - }, + [ + { + test: 'a', + }, + { + test: 'a', + }, + ], ], ], Merge5: [ [ - { - test: 'a', - }, - { - test: 'a', - }, + [ + { + test: 'a', + }, + { + test: 'a', + }, + ], ], ], Merge6: [ [ - { - test: 'a', - }, - { - test: 'a', - }, - { - test: 'a', - }, + [ + { + test: 'a', + }, + { + test: 'a', + }, + { + test: 'a', + }, + ], ], ], Merge7: [ [ - { - test: 'a', + [ + { + test: 'a', + }, + { + test: 'a', + }, + { + test: 'a', + }, + ], + ], + ], + }, + }, + }, + { + description: + 'Should output successful branches on multi-output nodes with continueErrorOutput selected', + input: { + workflowData: { + nodes: [ + { + parameters: {}, + id: '84b789e9-0dfc-4aa3-b0b2-cedf8966f904', + name: 'Start', + type: 'n8n-nodes-base.start', + position: [440, 1100], + typeVersion: 1, + }, + { + parameters: { + assignments: { + assignments: [ + { + id: '1ba24256-5b24-43cb-9638-fc1c2074d210', + name: 'name', + value: 'foo', + type: 'string', + }, + { + id: 'eee5a4fe-923d-46a2-b19e-c18b97a6c535', + name: 'value', + value: 'bar', + type: 'string', + }, + ], + }, + options: {}, }, - { - test: 'a', + id: '01720c87-f4ae-4e0f-89d7-0612a378226b', + name: 'Edit Fields', + type: 'n8n-nodes-base.set', + typeVersion: 3.4, + position: [780, 980], + }, + { + parameters: { + assignments: { + assignments: [ + { + id: '9182c7f5-7262-4366-8c04-cbf2bae338c1', + name: 'name', + value: 'bar', + type: 'string', + }, + { + id: 'cba31e58-23a9-4620-9cfc-ebb433528e6a', + name: 'value', + value: 'baz', + type: 'string', + }, + ], + }, + options: {}, }, - { - test: 'a', + id: '2e7977b0-f74f-46e7-af48-e5cbb41706e4', + name: 'Edit Fields1', + type: 'n8n-nodes-base.set', + typeVersion: 3.4, + position: [780, 1180], + }, + { + parameters: {}, + id: '95f67825-9244-44dc-82b9-7a6d7792e948', + name: 'Merge', + type: 'n8n-nodes-base.merge', + typeVersion: 1, + position: [1080, 1060], + }, + { + parameters: { + assignments: { + assignments: [ + { + id: '14d413c6-5088-4fb9-a895-e2e71557322d', + name: 'name', + value: '={{ $json.name }}', + type: 'string', + }, + { + id: '77f3d6d9-5ae7-4109-9144-9832f3e9f3bc', + name: 'value', + value: '={{ $json.value }}', + type: 'string', + }, + ], + }, + options: {}, }, + id: '89c06371-f539-4574-86a8-6ba9994924b4', + name: 'Edit Fields3', + type: 'n8n-nodes-base.set', + typeVersion: 3.4, + position: [1580, 1180], + }, + { + parameters: { + conditions: { + options: { + caseSensitive: true, + leftValue: '', + typeValidation: 'strict', + }, + conditions: [ + { + id: '96f95963-0edc-4d65-9935-6e141f39fcb1', + leftValue: '={{ $json.name }}', + rightValue: 'foo', + operator: { + type: 'string', + operation: 'equals', + name: 'filter.operator.equals', + }, + }, + ], + combinator: 'and', + }, + options: {}, + }, + id: '6fcdb8ea-9afc-44cb-a125-cef6cbb5765b', + name: 'If1', + type: 'n8n-nodes-base.if', + typeVersion: 2, + position: [1360, 1060], + onError: 'continueErrorOutput', + }, + { + parameters: { + assignments: { + assignments: [ + { + id: 'c8974629-7b62-40f8-8add-08e4dc8698be', + name: 'name', + value: '={{ $json.name }}', + type: 'string', + }, + { + id: '341a502e-3952-4654-b299-822fb2d303fe', + name: 'value', + value: '={{ $json.value }}', + type: 'string', + }, + ], + }, + options: {}, + }, + id: 'b4152f19-d0e6-43cd-8a90-9a7396856367', + name: 'Edit Fields2', + type: 'n8n-nodes-base.set', + typeVersion: 3.4, + position: [1580, 900], + }, + ], + connections: { + Start: { + main: [ + [ + { + node: 'Edit Fields', + type: NodeConnectionType.Main, + index: 0, + }, + { + node: 'Edit Fields1', + type: NodeConnectionType.Main, + index: 0, + }, + ], + ], + }, + 'Edit Fields': { + main: [ + [ + { + node: 'Merge', + type: NodeConnectionType.Main, + index: 0, + }, + ], + ], + }, + 'Edit Fields1': { + main: [ + [ + { + node: 'Merge', + type: NodeConnectionType.Main, + index: 1, + }, + ], + ], + }, + Merge: { + main: [ + [ + { + node: 'If1', + type: NodeConnectionType.Main, + index: 0, + }, + ], + ], + }, + If1: { + main: [ + [ + { + node: 'Edit Fields2', + type: NodeConnectionType.Main, + index: 0, + }, + ], + [ + { + node: 'Edit Fields3', + type: NodeConnectionType.Main, + index: 0, + }, + ], + ], + }, + }, + }, + }, + output: { + nodeExecutionOrder: [ + 'Start', + 'Edit Fields', + 'Edit Fields1', + 'Merge', + 'If1', + 'Edit Fields2', + 'Edit Fields3', + ], + testAllOutputs: true, + nodeData: { + Start: [[[{}]]], + 'Edit Fields': [ + [ + [ + { + name: 'foo', + value: 'bar', + }, + ], + ], + ], + 'Edit Fields1': [ + [ + [ + { + name: 'bar', + value: 'baz', + }, + ], + ], + ], + Merge: [ + [ + [ + { + name: 'foo', + value: 'bar', + }, + { + name: 'bar', + value: 'baz', + }, + ], + ], + ], + If1: [ + [ + [ + { + name: 'foo', + value: 'bar', + }, + ], + [ + { + name: 'bar', + value: 'baz', + }, + ], + [], + ], + ], + 'Edit Fields2': [ + [ + [ + { + name: 'foo', + value: 'bar', + }, + ], + ], + ], + 'Edit Fields3': [ + [ + [ + { + name: 'bar', + value: 'baz', + }, + ], ], ], }, diff --git a/packages/workflow/src/Interfaces.ts b/packages/workflow/src/Interfaces.ts index 057c500b0bbbf..ebe4b59477a35 100644 --- a/packages/workflow/src/Interfaces.ts +++ b/packages/workflow/src/Interfaces.ts @@ -2256,6 +2256,7 @@ export interface WorkflowTestData { }; output: { nodeExecutionOrder?: string[]; + testAllOutputs?: boolean; nodeData: { [key: string]: any[][]; };