mirror of
https://github.com/n8n-io/n8n.git
synced 2024-11-14 00:24:07 -08:00
c972f3dd50
* Added logging to n8n This commit adds logging to n8n using the Winston library. For now, this commit only allows logging to console (default behavior) or file (need to pass in config via environment variables). Other logging methods can be further implemented using hooks. These were skipped for now as it would require adding more dependencies. Logging level is notice by default, meaning no additional messages would be displayed at the moment. Logging level can be set to info or debug as well to enrich the generated logs. The ILogger interface was added to the workflow project as it would make it available for all other projects but the implementation was done on the cli project. * Lint fixes and logging level naming. Also fixed the way we use the logger as it was not working previously * Improvements to logging framework Using appropriate single quotes Improving the way the logger is declared * Improved naming for Log Types * Removed logger global variable, replacing it by a proxy * Add logging to CLI commands * Remove unused GenericHelpers * Changed back some messages to console instead of logger and added npm shortcuts for worker and webhook * Fix typos * Adding basic file rotation to logs as suggested by @mutdmour * Fixed linting issues * Correcting comment to correctly reflect space usage * Added settings for log files rotation * Correcting config type from String to Number * Changed default file settings to number To reflect previous changes to the type * Changed the way log messages are added to be called statically. Also minor naming improvements * Applying latest corrections sent by @ivov * ⚡ Some logging improvements * Saving logs to a folder inside n8n home instead of root * Fixed broken tests and linting * Changed some log messages to improve formatting * Adding quotes to names on log messages * Added execution and session IDs to logs. Also removed unnecessary line breaks * ⚡ Added file caller to log messages (#1657) This is done using callsites library which already existed in the project as another library's dependency. So in fact it does not add any new dependency. * Adding logs to help debug Salesforce node * ⚡ Add function name to logs and add more logs * ⚡ Improve some error messages * ⚡ Improve some more log messages * ⚡ Rename logging env variables to match others Co-authored-by: dali <servfrdali@yahoo.fr> Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
1223 lines
22 KiB
TypeScript
1223 lines
22 KiB
TypeScript
|
|
import {
|
|
IConnections,
|
|
ILogger,
|
|
INode,
|
|
IRun,
|
|
LoggerProxy,
|
|
Workflow,
|
|
} from 'n8n-workflow';
|
|
|
|
import {
|
|
createDeferredPromise,
|
|
WorkflowExecute,
|
|
} from '../src';
|
|
|
|
import * as Helpers from './Helpers';
|
|
|
|
|
|
describe('WorkflowExecute', () => {
|
|
|
|
describe('run', () => {
|
|
|
|
const tests: Array<{
|
|
description: string;
|
|
input: {
|
|
workflowData: {
|
|
nodes: INode[],
|
|
connections: IConnections,
|
|
}
|
|
},
|
|
output: {
|
|
nodeExecutionOrder: string[];
|
|
nodeData: {
|
|
[key: string]: any[][]; // tslint:disable-line:no-any
|
|
};
|
|
},
|
|
}> = [
|
|
{
|
|
description: 'should run basic two node workflow',
|
|
input: {
|
|
// Leave the workflowData in regular JSON to be able to easily
|
|
// copy it from/in the UI
|
|
workflowData: {
|
|
"nodes": [
|
|
{
|
|
"parameters": {},
|
|
"name": "Start",
|
|
"type": "n8n-nodes-base.start",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
100,
|
|
300,
|
|
],
|
|
},
|
|
{
|
|
"parameters": {
|
|
"values": {
|
|
"number": [
|
|
{
|
|
"name": "value1",
|
|
"value": 1,
|
|
},
|
|
],
|
|
},
|
|
},
|
|
"name": "Set",
|
|
"type": "n8n-nodes-base.set",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
280,
|
|
300,
|
|
],
|
|
},
|
|
],
|
|
"connections": {
|
|
"Start": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Set",
|
|
"type": "main",
|
|
"index": 0,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
},
|
|
},
|
|
},
|
|
output: {
|
|
nodeExecutionOrder: [
|
|
'Start',
|
|
'Set',
|
|
],
|
|
nodeData: {
|
|
Set: [
|
|
[
|
|
{
|
|
value1: 1,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
},
|
|
},
|
|
{
|
|
description: 'should run node twice when it has two input connections',
|
|
input: {
|
|
// Leave the workflowData in regular JSON to be able to easily
|
|
// copy it from/in the UI
|
|
workflowData: {
|
|
"nodes": [
|
|
{
|
|
"parameters": {},
|
|
"name": "Start",
|
|
"type": "n8n-nodes-base.start",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
100,
|
|
300,
|
|
],
|
|
},
|
|
{
|
|
"parameters": {
|
|
"values": {
|
|
"number": [
|
|
{
|
|
"name": "value1",
|
|
"value": 1,
|
|
},
|
|
],
|
|
},
|
|
},
|
|
"name": "Set1",
|
|
"type": "n8n-nodes-base.set",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
300,
|
|
250,
|
|
],
|
|
},
|
|
{
|
|
"parameters": {
|
|
"values": {
|
|
"number": [
|
|
{
|
|
"name": "value2",
|
|
"value": 2,
|
|
},
|
|
],
|
|
},
|
|
},
|
|
"name": "Set2",
|
|
"type": "n8n-nodes-base.set",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
500,
|
|
400,
|
|
],
|
|
},
|
|
],
|
|
"connections": {
|
|
"Start": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Set1",
|
|
"type": "main",
|
|
"index": 0,
|
|
},
|
|
{
|
|
"node": "Set2",
|
|
"type": "main",
|
|
"index": 0,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
"Set1": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Set2",
|
|
"type": "main",
|
|
"index": 0,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
},
|
|
},
|
|
},
|
|
output: {
|
|
nodeExecutionOrder: [
|
|
'Start',
|
|
'Set1',
|
|
'Set2',
|
|
'Set2',
|
|
],
|
|
nodeData: {
|
|
Set1: [
|
|
[
|
|
{
|
|
value1: 1,
|
|
},
|
|
],
|
|
],
|
|
Set2: [
|
|
[
|
|
{
|
|
value2: 2,
|
|
},
|
|
],
|
|
[
|
|
{
|
|
value1: 1,
|
|
value2: 2,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
},
|
|
},
|
|
{
|
|
description: 'should run complicated multi node workflow',
|
|
input: {
|
|
// Leave the workflowData in regular JSON to be able to easily
|
|
// copy it from/in the UI
|
|
workflowData: {
|
|
"nodes": [
|
|
{
|
|
"parameters": {
|
|
"mode": "passThrough",
|
|
},
|
|
"name": "Merge4",
|
|
"type": "n8n-nodes-base.merge",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
1150,
|
|
500,
|
|
],
|
|
},
|
|
{
|
|
"parameters": {
|
|
"values": {
|
|
"number": [
|
|
{
|
|
"name": "value2",
|
|
"value": 2,
|
|
},
|
|
],
|
|
},
|
|
},
|
|
"name": "Set2",
|
|
"type": "n8n-nodes-base.set",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
290,
|
|
400,
|
|
],
|
|
},
|
|
{
|
|
"parameters": {
|
|
"values": {
|
|
"number": [
|
|
{
|
|
"name": "value4",
|
|
"value": 4,
|
|
},
|
|
],
|
|
},
|
|
},
|
|
"name": "Set4",
|
|
"type": "n8n-nodes-base.set",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
850,
|
|
200,
|
|
],
|
|
},
|
|
{
|
|
"parameters": {
|
|
"values": {
|
|
"number": [
|
|
{
|
|
"name": "value3",
|
|
"value": 3,
|
|
},
|
|
],
|
|
},
|
|
},
|
|
"name": "Set3",
|
|
"type": "n8n-nodes-base.set",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
650,
|
|
200,
|
|
],
|
|
},
|
|
{
|
|
"parameters": {
|
|
"mode": "passThrough",
|
|
},
|
|
"name": "Merge4",
|
|
"type": "n8n-nodes-base.merge",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
1150,
|
|
500,
|
|
],
|
|
},
|
|
{
|
|
"parameters": {},
|
|
"name": "Merge3",
|
|
"type": "n8n-nodes-base.merge",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
1000,
|
|
400,
|
|
],
|
|
},
|
|
{
|
|
"parameters": {
|
|
"mode": "passThrough",
|
|
"output": "input2",
|
|
},
|
|
"name": "Merge2",
|
|
"type": "n8n-nodes-base.merge",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
700,
|
|
400,
|
|
],
|
|
},
|
|
{
|
|
"parameters": {},
|
|
"name": "Merge1",
|
|
"type": "n8n-nodes-base.merge",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
500,
|
|
300,
|
|
],
|
|
},
|
|
{
|
|
"parameters": {
|
|
"values": {
|
|
"number": [
|
|
{
|
|
"name": "value1",
|
|
"value": 1,
|
|
},
|
|
],
|
|
},
|
|
},
|
|
"name": "Set1",
|
|
"type": "n8n-nodes-base.set",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
300,
|
|
200,
|
|
],
|
|
},
|
|
{
|
|
"parameters": {},
|
|
"name": "Start",
|
|
"type": "n8n-nodes-base.start",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
100,
|
|
300,
|
|
],
|
|
},
|
|
],
|
|
"connections": {
|
|
"Set2": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Merge1",
|
|
"type": "main",
|
|
"index": 1,
|
|
},
|
|
{
|
|
"node": "Merge2",
|
|
"type": "main",
|
|
"index": 1,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
"Set4": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Merge3",
|
|
"type": "main",
|
|
"index": 0,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
"Set3": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Set4",
|
|
"type": "main",
|
|
"index": 0,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
"Merge3": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Merge4",
|
|
"type": "main",
|
|
"index": 0,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
"Merge2": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Merge3",
|
|
"type": "main",
|
|
"index": 1,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
"Merge1": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Merge2",
|
|
"type": "main",
|
|
"index": 0,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
"Set1": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Merge1",
|
|
"type": "main",
|
|
"index": 0,
|
|
},
|
|
{
|
|
"node": "Set3",
|
|
"type": "main",
|
|
"index": 0,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
"Start": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Set1",
|
|
"type": "main",
|
|
"index": 0,
|
|
},
|
|
{
|
|
"node": "Set2",
|
|
"type": "main",
|
|
"index": 0,
|
|
},
|
|
{
|
|
"node": "Merge4",
|
|
"type": "main",
|
|
"index": 1,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
},
|
|
},
|
|
},
|
|
output: {
|
|
nodeExecutionOrder: [
|
|
'Start',
|
|
'Set1',
|
|
'Set2',
|
|
'Set3',
|
|
'Merge1',
|
|
'Set4',
|
|
'Merge2',
|
|
'Merge3',
|
|
'Merge4',
|
|
],
|
|
nodeData: {
|
|
Set1: [
|
|
[
|
|
{
|
|
value1: 1,
|
|
},
|
|
],
|
|
],
|
|
Set2: [
|
|
[
|
|
{
|
|
value2: 2,
|
|
},
|
|
],
|
|
],
|
|
Set3: [
|
|
[
|
|
{
|
|
value1: 1,
|
|
value3: 3,
|
|
},
|
|
],
|
|
],
|
|
Set4: [
|
|
[
|
|
{
|
|
value1: 1,
|
|
value3: 3,
|
|
value4: 4,
|
|
},
|
|
],
|
|
],
|
|
Merge1: [
|
|
[
|
|
{
|
|
value1: 1,
|
|
},
|
|
{
|
|
value2: 2,
|
|
},
|
|
],
|
|
],
|
|
Merge2: [
|
|
[
|
|
{
|
|
value2: 2,
|
|
},
|
|
],
|
|
],
|
|
Merge3: [
|
|
[
|
|
{
|
|
value1: 1,
|
|
value3: 3,
|
|
value4: 4,
|
|
},
|
|
{
|
|
value2: 2,
|
|
},
|
|
],
|
|
],
|
|
Merge4: [
|
|
[
|
|
{
|
|
value1: 1,
|
|
value3: 3,
|
|
value4: 4,
|
|
},
|
|
{
|
|
value2: 2,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
},
|
|
},
|
|
{
|
|
description: 'should run workflow also if node has multiple input connections and one is empty',
|
|
input: {
|
|
// Leave the workflowData in regular JSON to be able to easily
|
|
// copy it from/in the UI
|
|
workflowData: {
|
|
"nodes": [
|
|
{
|
|
"parameters": {},
|
|
"name": "Start",
|
|
"type": "n8n-nodes-base.start",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
250,
|
|
450,
|
|
],
|
|
},
|
|
{
|
|
"parameters": {
|
|
"conditions": {
|
|
"boolean": [],
|
|
"number": [
|
|
{
|
|
"value1": "={{Object.keys($json).length}}",
|
|
"operation": "notEqual",
|
|
},
|
|
],
|
|
},
|
|
},
|
|
"name": "IF",
|
|
"type": "n8n-nodes-base.if",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
650,
|
|
350,
|
|
],
|
|
},
|
|
{
|
|
"parameters": {},
|
|
"name": "Merge1",
|
|
"type": "n8n-nodes-base.merge",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
1150,
|
|
450,
|
|
],
|
|
},
|
|
{
|
|
"parameters": {
|
|
"values": {
|
|
"string": [
|
|
{
|
|
"name": "test1",
|
|
"value": "a",
|
|
},
|
|
],
|
|
},
|
|
"options": {},
|
|
},
|
|
"name": "Set1",
|
|
"type": "n8n-nodes-base.set",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
450,
|
|
450,
|
|
],
|
|
},
|
|
{
|
|
"parameters": {
|
|
"values": {
|
|
"string": [
|
|
{
|
|
"name": "test2",
|
|
"value": "b",
|
|
},
|
|
],
|
|
},
|
|
"options": {},
|
|
},
|
|
"name": "Set2",
|
|
"type": "n8n-nodes-base.set",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
800,
|
|
250,
|
|
],
|
|
},
|
|
],
|
|
"connections": {
|
|
"Start": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Set1",
|
|
"type": "main",
|
|
"index": 0,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
"IF": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Set2",
|
|
"type": "main",
|
|
"index": 0,
|
|
},
|
|
],
|
|
[
|
|
{
|
|
"node": "Merge1",
|
|
"type": "main",
|
|
"index": 0,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
"Set1": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "IF",
|
|
"type": "main",
|
|
"index": 0,
|
|
},
|
|
{
|
|
"node": "Merge1",
|
|
"type": "main",
|
|
"index": 1,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
"Set2": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Merge1",
|
|
"type": "main",
|
|
"index": 0,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
},
|
|
},
|
|
},
|
|
output: {
|
|
nodeExecutionOrder: [
|
|
'Start',
|
|
'Set1',
|
|
'IF',
|
|
'Set2',
|
|
'Merge1',
|
|
],
|
|
nodeData: {
|
|
Merge1: [
|
|
[
|
|
{
|
|
test1: 'a',
|
|
test2: 'b',
|
|
},
|
|
{
|
|
test1: 'a',
|
|
},
|
|
],
|
|
],
|
|
},
|
|
},
|
|
},
|
|
{
|
|
description: 'should use empty data if second input does not have any data',
|
|
input: {
|
|
// Leave the workflowData in regular JSON to be able to easily
|
|
// copy it from/in the UI
|
|
workflowData: {
|
|
"nodes": [
|
|
{
|
|
"parameters": {},
|
|
"name": "Start",
|
|
"type": "n8n-nodes-base.start",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
250,
|
|
300,
|
|
],
|
|
},
|
|
{
|
|
"parameters": {},
|
|
"name": "Merge",
|
|
"type": "n8n-nodes-base.merge",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
800,
|
|
450,
|
|
],
|
|
},
|
|
{
|
|
"parameters": {},
|
|
"name": "Merge1",
|
|
"type": "n8n-nodes-base.merge",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
1000,
|
|
300,
|
|
],
|
|
},
|
|
{
|
|
"parameters": {
|
|
"conditions": {
|
|
"boolean": [
|
|
{
|
|
"value2": true,
|
|
},
|
|
],
|
|
"string": [
|
|
{
|
|
"value1": "={{$json[\"key\"]}}",
|
|
"value2": "a",
|
|
},
|
|
],
|
|
},
|
|
"combineOperation": "any",
|
|
},
|
|
"name": "IF",
|
|
"type": "n8n-nodes-base.if",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
600,
|
|
600,
|
|
],
|
|
"alwaysOutputData": false,
|
|
},
|
|
{
|
|
"parameters": {
|
|
"values": {
|
|
"number": [
|
|
{
|
|
"name": "number0",
|
|
},
|
|
],
|
|
"string": [
|
|
{
|
|
"name": "key",
|
|
"value": "a",
|
|
},
|
|
],
|
|
},
|
|
"options": {},
|
|
},
|
|
"name": "Set0",
|
|
"type": "n8n-nodes-base.set",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
450,
|
|
300,
|
|
],
|
|
},
|
|
{
|
|
"parameters": {
|
|
"values": {
|
|
"number": [
|
|
{
|
|
"name": "number1",
|
|
"value": 1,
|
|
},
|
|
],
|
|
"string": [
|
|
{
|
|
"name": "key",
|
|
"value": "b",
|
|
},
|
|
],
|
|
},
|
|
"options": {},
|
|
},
|
|
"name": "Set1",
|
|
"type": "n8n-nodes-base.set",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
450,
|
|
450,
|
|
],
|
|
},
|
|
{
|
|
"parameters": {
|
|
"values": {
|
|
"number": [
|
|
{
|
|
"name": "number2",
|
|
"value": 2,
|
|
},
|
|
],
|
|
"string": [
|
|
{
|
|
"name": "key",
|
|
"value": "c",
|
|
},
|
|
],
|
|
},
|
|
"options": {},
|
|
},
|
|
"name": "Set2",
|
|
"type": "n8n-nodes-base.set",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
450,
|
|
600,
|
|
],
|
|
},
|
|
],
|
|
"connections": {
|
|
"Start": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Set0",
|
|
"type": "main",
|
|
"index": 0,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
"Merge": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Merge1",
|
|
"type": "main",
|
|
"index": 1,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
"IF": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Merge",
|
|
"type": "main",
|
|
"index": 1,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
"Set0": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Merge1",
|
|
"type": "main",
|
|
"index": 0,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
"Set1": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Merge",
|
|
"type": "main",
|
|
"index": 0,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
"Set2": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "IF",
|
|
"type": "main",
|
|
"index": 0,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
},
|
|
},
|
|
},
|
|
output: {
|
|
nodeExecutionOrder: [
|
|
'Start',
|
|
'Set0',
|
|
'Set2',
|
|
'IF',
|
|
'Set1',
|
|
'Merge',
|
|
'Merge1',
|
|
],
|
|
nodeData: {
|
|
Merge: [
|
|
[
|
|
{
|
|
number1: 1,
|
|
key: "b",
|
|
},
|
|
],
|
|
],
|
|
Merge1: [
|
|
[
|
|
{
|
|
number0: 0,
|
|
key: "a",
|
|
},
|
|
{
|
|
number1: 1,
|
|
key: "b",
|
|
},
|
|
],
|
|
],
|
|
},
|
|
},
|
|
},
|
|
{
|
|
description: 'should use empty data if input of sibling does not receive any data from parent',
|
|
input: {
|
|
// Leave the workflowData in regular JSON to be able to easily
|
|
// copy it from/in the UI
|
|
workflowData: {
|
|
"nodes": [
|
|
{
|
|
"parameters": {},
|
|
"name": "Start",
|
|
"type": "n8n-nodes-base.start",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
250,
|
|
300,
|
|
],
|
|
},
|
|
{
|
|
"parameters": {
|
|
"conditions": {
|
|
"number": [
|
|
{
|
|
"value1": "={{$json[\"value1\"]}}",
|
|
"operation": "equal",
|
|
"value2": 1,
|
|
},
|
|
],
|
|
},
|
|
},
|
|
"name": "IF",
|
|
"type": "n8n-nodes-base.if",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
650,
|
|
300,
|
|
],
|
|
},
|
|
{
|
|
"parameters": {
|
|
"values": {
|
|
"string": [],
|
|
"number": [
|
|
{
|
|
"name": "value2",
|
|
"value": 2,
|
|
},
|
|
],
|
|
},
|
|
"options": {},
|
|
},
|
|
"name": "Set2",
|
|
"type": "n8n-nodes-base.set",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
850,
|
|
450,
|
|
],
|
|
},
|
|
{
|
|
"parameters": {
|
|
"values": {
|
|
"number": [
|
|
{
|
|
"name": "value1",
|
|
"value": 1,
|
|
},
|
|
],
|
|
},
|
|
"options": {},
|
|
},
|
|
"name": "Set1",
|
|
"type": "n8n-nodes-base.set",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
450,
|
|
300,
|
|
],
|
|
},
|
|
{
|
|
"parameters": {},
|
|
"name": "Merge",
|
|
"type": "n8n-nodes-base.merge",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
1050,
|
|
300,
|
|
],
|
|
},
|
|
],
|
|
"connections": {
|
|
"Start": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Set1",
|
|
"type": "main",
|
|
"index": 0,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
"IF": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Merge",
|
|
"type": "main",
|
|
"index": 0,
|
|
},
|
|
],
|
|
[
|
|
{
|
|
"node": "Set2",
|
|
"type": "main",
|
|
"index": 0,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
"Set2": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Merge",
|
|
"type": "main",
|
|
"index": 1,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
"Set1": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "IF",
|
|
"type": "main",
|
|
"index": 0,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
},
|
|
},
|
|
},
|
|
output: {
|
|
nodeExecutionOrder: [
|
|
'Start',
|
|
'Set1',
|
|
'IF',
|
|
'Set2',
|
|
'Merge',
|
|
],
|
|
nodeData: {
|
|
Merge: [
|
|
[
|
|
{
|
|
value1: 1,
|
|
},
|
|
{
|
|
value2: 2,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
},
|
|
},
|
|
];
|
|
|
|
const fakeLogger = {
|
|
log: () => {},
|
|
debug: () => {},
|
|
verbose: () => {},
|
|
info: () => {},
|
|
warn: () => {},
|
|
error: () => {},
|
|
} as ILogger;
|
|
|
|
|
|
const executionMode = 'manual';
|
|
const nodeTypes = Helpers.NodeTypes();
|
|
LoggerProxy.init(fakeLogger);
|
|
|
|
for (const testData of tests) {
|
|
test(testData.description, async () => {
|
|
|
|
const workflowInstance = new Workflow({ id: 'test', nodes: testData.input.workflowData.nodes, connections: testData.input.workflowData.connections, active: false, nodeTypes });
|
|
|
|
const waitPromise = await createDeferredPromise<IRun>();
|
|
const nodeExecutionOrder: string[] = [];
|
|
const additionalData = Helpers.WorkflowExecuteAdditionalData(waitPromise, nodeExecutionOrder);
|
|
|
|
const workflowExecute = new WorkflowExecute(additionalData, executionMode);
|
|
|
|
const executionData = await workflowExecute.run(workflowInstance, undefined);
|
|
|
|
const result = await waitPromise.promise();
|
|
|
|
// Check if the data from WorkflowExecute is identical to data received
|
|
// by the webhooks
|
|
expect(executionData).toEqual(result);
|
|
|
|
// Check if the output data of the nodes is correct
|
|
for (const nodeName of Object.keys(testData.output.nodeData)) {
|
|
if (result.data.resultData.runData[nodeName] === undefined) {
|
|
throw new Error(`Data for node "${nodeName}" is missing!`);
|
|
}
|
|
|
|
const resultData = result.data.resultData.runData[nodeName].map((nodeData) => {
|
|
if (nodeData.data === undefined) {
|
|
return null;
|
|
}
|
|
return nodeData.data.main[0]!.map((entry) => entry.json );
|
|
});
|
|
|
|
// expect(resultData).toEqual(testData.output.nodeData[nodeName]);
|
|
expect(resultData).toEqual(testData.output.nodeData[nodeName]);
|
|
}
|
|
|
|
// Check if the nodes did execute in the correct order
|
|
expect(nodeExecutionOrder).toEqual(testData.output.nodeExecutionOrder);
|
|
|
|
// Check if other data has correct value
|
|
expect(result.finished).toEqual(true);
|
|
expect(result.data.executionData!.contextData).toEqual({});
|
|
expect(result.data.executionData!.nodeExecutionStack).toEqual([]);
|
|
expect(result.data.executionData!.waitingExecution).toEqual({});
|
|
});
|
|
}
|
|
|
|
});
|
|
|
|
});
|