first commit
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled

This commit is contained in:
2026-03-17 16:22:57 +03:30
commit 3d5eaf9445
15349 changed files with 2847338 additions and 0 deletions
@@ -0,0 +1,167 @@
{
"name": "My workflow 64",
"nodes": [
{
"parameters": {},
"id": "58cc2d21-a8b1-424d-a8e4-e79d39955fa8",
"name": "When clicking \"Execute Workflow\"",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [0, 620]
},
{
"parameters": {
"data": [
{
"output": "third",
"text": "third output text"
},
{
"output": "fourth",
"text": "fourth output text"
},
{
"output": "first",
"text": "first output text"
},
{
"output": "second",
"text": "second output text"
}
]
},
"id": "85adf7fc-2d33-49aa-b4bb-2000cce07ce0",
"name": "Code",
"type": "n8n-nodes-testing.testData",
"typeVersion": 1,
"position": [220, 620]
},
{
"parameters": {},
"id": "ebab0b65-6feb-416c-828e-ca5e766ea048",
"name": "No Operation, do nothing",
"type": "n8n-nodes-base.noOp",
"typeVersion": 1,
"position": [760, 460]
},
{
"parameters": {},
"id": "2f58a703-b7ae-4279-a60b-a0243af3b563",
"name": "No Operation, do nothing1",
"type": "n8n-nodes-base.noOp",
"typeVersion": 1,
"position": [760, 620]
},
{
"parameters": {},
"id": "b1d0b310-6edf-4a40-a66d-689078ddbf31",
"name": "No Operation, do nothing2",
"type": "n8n-nodes-base.noOp",
"typeVersion": 1,
"position": [760, 780]
},
{
"parameters": {
"mode": "expression",
"numberOutputs": 3,
"output": "={{ Math.max(0, ['first', 'second', 'third'].indexOf( $json.output)) }}"
},
"id": "437e2c46-81d8-4c76-a036-db767576f55d",
"name": "Switch",
"type": "n8n-nodes-base.switch",
"typeVersion": 3,
"position": [460, 620]
}
],
"pinData": {
"No Operation, do nothing2": [
{
"json": {
"output": "third",
"text": "third output text"
}
}
],
"No Operation, do nothing1": [
{
"json": {
"output": "second",
"text": "second output text"
}
}
],
"No Operation, do nothing": [
{
"json": {
"output": "fourth",
"text": "fourth output text"
}
},
{
"json": {
"output": "first",
"text": "first output text"
}
}
]
},
"connections": {
"When clicking \"Execute Workflow\"": {
"main": [
[
{
"node": "Code",
"type": "main",
"index": 0
}
]
]
},
"Code": {
"main": [
[
{
"node": "Switch",
"type": "main",
"index": 0
}
]
]
},
"Switch": {
"main": [
[
{
"node": "No Operation, do nothing",
"type": "main",
"index": 0
}
],
[
{
"node": "No Operation, do nothing1",
"type": "main",
"index": 0
}
],
[
{
"node": "No Operation, do nothing2",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "c72f2f9b-5089-42c2-8939-b70d9467a718",
"id": "1vDZkJN9SpYXu0Ic",
"meta": {
"instanceId": "b888bd11cd1ddbb95450babf3e199556799d999b896f650de768b8370ee50363"
},
"tags": []
}
@@ -0,0 +1,570 @@
import { mockDeep } from 'jest-mock-extended';
import type {
IExecuteFunctions,
ILoadOptionsFunctions,
INodeTypeBaseDescription,
} from 'n8n-workflow';
import { NodeOperationError, ApplicationError } from 'n8n-workflow';
import { SwitchV3 } from '../SwitchV3.node';
describe('SwitchV3 Node', () => {
let switchNode: SwitchV3;
let mockExecuteFunctions: jest.Mocked<IExecuteFunctions>;
let mockLoadOptionsFunctions: jest.Mocked<ILoadOptionsFunctions>;
const baseDescription: INodeTypeBaseDescription = {
displayName: 'Switch',
name: 'n8n-nodes-base.switch',
group: ['transform'],
description: 'Route items to different outputs',
};
beforeEach(() => {
switchNode = new SwitchV3(baseDescription);
mockExecuteFunctions = mockDeep<IExecuteFunctions>();
mockLoadOptionsFunctions = mockDeep<ILoadOptionsFunctions>();
jest.clearAllMocks();
});
describe('Version-specific behavior', () => {
it('should have two numberOutputs parameters with different version conditions', () => {
const switchNode = new SwitchV3(baseDescription);
const numberOutputsParams = switchNode.description.properties.filter(
(prop) => prop.name === 'numberOutputs',
);
expect(numberOutputsParams).toHaveLength(2);
});
it('should have noDataExpression: true for version 3.3+ numberOutputs parameter', () => {
const switchNode = new SwitchV3(baseDescription);
const numberOutputsParamWithNoExpression = switchNode.description.properties.find(
(prop) => prop.name === 'numberOutputs' && prop.noDataExpression === true,
);
expect(numberOutputsParamWithNoExpression).toBeDefined();
expect(numberOutputsParamWithNoExpression?.noDataExpression).toBe(true);
expect(numberOutputsParamWithNoExpression?.displayOptions?.show?.['@version']).toEqual([
{ _cnd: { gte: 3.3 } },
]);
});
it('should have numberOutputs parameter without noDataExpression for older versions', () => {
const switchNode = new SwitchV3(baseDescription);
const numberOutputsParamWithoutNoExpression = switchNode.description.properties.find(
(prop) => prop.name === 'numberOutputs' && !prop.noDataExpression,
);
expect(numberOutputsParamWithoutNoExpression).toBeDefined();
expect(numberOutputsParamWithoutNoExpression?.noDataExpression).toBeUndefined();
expect(numberOutputsParamWithoutNoExpression?.displayOptions?.show?.['@version']).toEqual([
{ _cnd: { lt: 3.3 } },
]);
});
it('should include version 3.3 in supported versions', () => {
const switchNode = new SwitchV3(baseDescription);
expect(switchNode.description.version).toContain(3.3);
});
});
describe('Expression Mode Execution', () => {
beforeEach(() => {
mockExecuteFunctions.getNode.mockReturnValue({
id: 'switch-node',
name: 'Switch',
type: 'n8n-nodes-base.switch',
typeVersion: 3.3,
position: [0, 0],
parameters: {},
});
});
it('should route items to correct output in expression mode', async () => {
const inputData = [{ json: { value: 1 } }, { json: { value: 2 } }, { json: { value: 3 } }];
mockExecuteFunctions.getInputData.mockReturnValue(inputData);
mockExecuteFunctions.getNodeParameter.mockImplementation(
(paramName: string, itemIndex: number) => {
const params: Record<string, any> = {
mode: 'expression',
numberOutputs: 3,
output: itemIndex % 3,
};
return params[paramName];
},
);
const result = await switchNode.execute.call(mockExecuteFunctions);
expect(result).toHaveLength(3);
expect(result[0]).toHaveLength(1);
expect(result[0][0].json).toEqual({ value: 1 });
expect(result[1]).toHaveLength(1);
expect(result[1][0].json).toEqual({ value: 2 });
expect(result[2]).toHaveLength(1);
expect(result[2][0].json).toEqual({ value: 3 });
});
it('should handle multiple items routed to same output', async () => {
const inputData = [{ json: { value: 1 } }, { json: { value: 2 } }, { json: { value: 3 } }];
mockExecuteFunctions.getInputData.mockReturnValue(inputData);
mockExecuteFunctions.getNodeParameter.mockImplementation((paramName: string) => {
const params: Record<string, any> = {
mode: 'expression',
numberOutputs: 2,
output: 0,
};
return params[paramName];
});
const result = await switchNode.execute.call(mockExecuteFunctions);
expect(result).toHaveLength(2);
expect(result[0]).toHaveLength(3);
expect(result[1]).toHaveLength(0);
});
it('should throw error for invalid output index', async () => {
const inputData = [{ json: { value: 1 } }];
mockExecuteFunctions.getInputData.mockReturnValue(inputData);
mockExecuteFunctions.getNodeParameter.mockImplementation((paramName: string) => {
const params: Record<string, any> = {
mode: 'expression',
numberOutputs: 2,
output: 5,
};
return params[paramName];
});
await expect(switchNode.execute.call(mockExecuteFunctions)).rejects.toThrow(
NodeOperationError,
);
});
it('should throw error for negative output index', async () => {
const inputData = [{ json: { value: 1 } }];
mockExecuteFunctions.getInputData.mockReturnValue(inputData);
mockExecuteFunctions.getNodeParameter.mockImplementation((paramName: string) => {
const params: Record<string, any> = {
mode: 'expression',
numberOutputs: 2,
output: -1,
};
return params[paramName];
});
await expect(switchNode.execute.call(mockExecuteFunctions)).rejects.toThrow(
NodeOperationError,
);
});
it('should handle empty input data', async () => {
mockExecuteFunctions.getInputData.mockReturnValue([]);
mockExecuteFunctions.getNodeParameter.mockReturnValue('expression');
const result = await switchNode.execute.call(mockExecuteFunctions);
expect(result).toEqual([[]]);
});
});
describe('Rules Mode Execution', () => {
beforeEach(() => {
mockExecuteFunctions.getNode.mockReturnValue({
id: 'switch-node',
name: 'Switch',
type: 'n8n-nodes-base.switch',
typeVersion: 3.3,
position: [0, 0],
parameters: {},
});
});
it('should route items based on matching rules', async () => {
const inputData = [
{ json: { status: 'active' } },
{ json: { status: 'inactive' } },
{ json: { status: 'pending' } },
];
mockExecuteFunctions.getInputData.mockReturnValue(inputData);
mockExecuteFunctions.getNodeParameter.mockImplementation((paramName: string) => {
if (paramName === 'mode') return 'rules';
if (paramName === 'rules.values') {
return [
{
conditions: {
conditions: [
{
leftValue: '={{$json.status}}',
rightValue: 'active',
operator: { type: 'string', operation: 'equals' },
},
],
combinator: 'and',
},
},
{
conditions: {
conditions: [
{
leftValue: '={{$json.status}}',
rightValue: 'inactive',
operator: { type: 'string', operation: 'equals' },
},
],
combinator: 'and',
},
},
];
}
if (paramName === 'options') return {};
return false;
});
mockExecuteFunctions.getNodeParameter.mockImplementation(
(paramName: string, itemIndex: number, defaultValue: any, options?: any) => {
if (paramName === 'mode') return 'rules';
if (paramName === 'rules.values') {
return [
{ conditions: { conditions: [], combinator: 'and' } },
{ conditions: { conditions: [], combinator: 'and' } },
];
}
if (paramName === 'options') return {};
if (paramName.includes('conditions') && options?.extractValue) {
if (itemIndex === 0) return true; // active matches first rule
if (itemIndex === 1) return false; // inactive doesn't match first rule
return false;
}
return defaultValue;
},
);
const result = await switchNode.execute.call(mockExecuteFunctions);
expect(result).toHaveLength(2);
expect(result[0]).toHaveLength(1);
expect(result[0][0].json).toEqual({ status: 'active' });
expect(result[1]).toHaveLength(0);
});
it('should handle fallback output when no rules match', async () => {
const inputData = [{ json: { status: 'unknown' } }];
mockExecuteFunctions.getInputData.mockReturnValue(inputData);
mockExecuteFunctions.getNodeParameter.mockImplementation(
(paramName: string, _itemIndex: number, defaultValue: any, options?: any) => {
if (paramName === 'mode') return 'rules';
if (paramName === 'rules.values') {
return [{ conditions: { conditions: [], combinator: 'and' } }];
}
if (paramName === 'options') return { fallbackOutput: 'extra' };
if (paramName.includes('conditions') && options?.extractValue) {
return false; // No rule matches
}
return defaultValue;
},
);
const result = await switchNode.execute.call(mockExecuteFunctions);
expect(result).toHaveLength(2); // One rule output + one fallback output
expect(result[0]).toHaveLength(0); // No matches for rule
expect(result[1]).toHaveLength(1); // Item goes to fallback
expect(result[1][0].json).toEqual({ status: 'unknown' });
});
it('should handle allMatchingOutputs option', async () => {
const inputData = [{ json: { value: 10 } }];
mockExecuteFunctions.getInputData.mockReturnValue(inputData);
mockExecuteFunctions.getNodeParameter.mockImplementation(
(paramName: string, _itemIndex: number, defaultValue: any, options?: any) => {
if (paramName === 'mode') return 'rules';
if (paramName === 'rules.values') {
return [
{ conditions: { conditions: [], combinator: 'and' } },
{ conditions: { conditions: [], combinator: 'and' } },
];
}
if (paramName === 'options') return { allMatchingOutputs: true };
if (paramName.includes('conditions') && options?.extractValue) {
return true; // Both rules match
}
return defaultValue;
},
);
const result = await switchNode.execute.call(mockExecuteFunctions);
expect(result).toHaveLength(2);
expect(result[0]).toHaveLength(1);
expect(result[1]).toHaveLength(1);
expect(result[0][0].json).toEqual({ value: 10 });
expect(result[1][0].json).toEqual({ value: 10 });
});
it('should skip items when no rules are defined', async () => {
const inputData = [{ json: { value: 1 } }];
mockExecuteFunctions.getInputData.mockReturnValue(inputData);
mockExecuteFunctions.getNodeParameter.mockImplementation((paramName: string) => {
if (paramName === 'mode') return 'rules';
if (paramName === 'rules.values') return [];
if (paramName === 'options') return {};
return undefined;
});
const result = await switchNode.execute.call(mockExecuteFunctions);
expect(result).toEqual([[]]);
});
});
describe('Error Handling', () => {
beforeEach(() => {
mockExecuteFunctions.getNode.mockReturnValue({
id: 'switch-node',
name: 'Switch',
type: 'n8n-nodes-base.switch',
typeVersion: 3.3,
position: [0, 0],
parameters: {},
});
});
it('should handle errors with continueOnFail', async () => {
const inputData = [{ json: { value: 1 } }];
mockExecuteFunctions.getInputData.mockReturnValue(inputData);
mockExecuteFunctions.getNodeParameter.mockImplementation((paramName: string) => {
if (paramName === 'mode') return 'expression';
if (paramName === 'numberOutputs') return 1;
if (paramName === 'output') {
throw new Error('Parameter error');
}
return undefined;
});
mockExecuteFunctions.continueOnFail.mockReturnValue(true);
const result = await switchNode.execute.call(mockExecuteFunctions);
expect(result[0][0].json).toHaveProperty('error', 'Parameter error');
});
it('should rethrow NodeOperationError', async () => {
const inputData = [{ json: { value: 1 } }];
mockExecuteFunctions.getInputData.mockReturnValue(inputData);
mockExecuteFunctions.getNodeParameter.mockImplementation(() => {
throw new NodeOperationError(mockExecuteFunctions.getNode(), 'Invalid parameter');
});
await expect(switchNode.execute.call(mockExecuteFunctions)).rejects.toThrow(
NodeOperationError,
);
});
it('should handle ApplicationError with context', async () => {
const inputData = [{ json: { value: 1 } }];
mockExecuteFunctions.getInputData.mockReturnValue(inputData);
mockExecuteFunctions.getNodeParameter.mockImplementation(() => {
const error = new ApplicationError('Application error');
throw error;
});
await expect(switchNode.execute.call(mockExecuteFunctions)).rejects.toThrow(ApplicationError);
});
it('should wrap generic errors in NodeOperationError', async () => {
const inputData = [{ json: { value: 1 } }];
mockExecuteFunctions.getInputData.mockReturnValue(inputData);
mockExecuteFunctions.getNodeParameter.mockImplementation((paramName: string) => {
if (paramName === 'mode') return 'expression';
if (paramName === 'numberOutputs') return 1;
if (paramName === 'output') {
throw new Error('Generic error');
}
return undefined;
});
await expect(switchNode.execute.call(mockExecuteFunctions)).rejects.toThrow(
NodeOperationError,
);
});
});
describe('Load Options', () => {
it('should load fallback output options with no rules', async () => {
mockLoadOptionsFunctions.getCurrentNodeParameter.mockReturnValue([]);
const result =
await switchNode.methods.loadOptions.getFallbackOutputOptions.call(
mockLoadOptionsFunctions,
);
expect(result).toEqual([
{
// eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased
name: 'None (default)',
value: 'none',
description: 'Items will be ignored',
},
{
name: 'Extra Output',
value: 'extra',
description: 'Items will be sent to the extra, separate, output',
},
]);
});
it('should load fallback output options with rules', async () => {
const rules = [
{ outputKey: 'Rule 1' },
{ outputKey: 'Rule 2' },
{}, // Rule without outputKey
];
mockLoadOptionsFunctions.getCurrentNodeParameter.mockReturnValue(rules);
const result =
await switchNode.methods.loadOptions.getFallbackOutputOptions.call(
mockLoadOptionsFunctions,
);
expect(result).toEqual([
{
// eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased
name: 'None (default)',
value: 'none',
description: 'Items will be ignored',
},
{
name: 'Extra Output',
value: 'extra',
description: 'Items will be sent to the extra, separate, output',
},
{
name: 'Output Rule 1',
value: 0,
description: 'Items will be sent to the same output as when matched rule 1',
},
{
name: 'Output Rule 2',
value: 1,
description: 'Items will be sent to the same output as when matched rule 2',
},
{
name: 'Output 2',
value: 2,
description: 'Items will be sent to the same output as when matched rule 3',
},
]);
});
it('should handle null rules parameter', async () => {
mockLoadOptionsFunctions.getCurrentNodeParameter.mockReturnValue(null);
const result =
await switchNode.methods.loadOptions.getFallbackOutputOptions.call(
mockLoadOptionsFunctions,
);
expect(result).toEqual([
{
// eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased
name: 'None (default)',
value: 'none',
description: 'Items will be ignored',
},
{
name: 'Extra Output',
value: 'extra',
description: 'Items will be sent to the extra, separate, output',
},
]);
});
});
describe('Edge Cases', () => {
beforeEach(() => {
mockExecuteFunctions.getNode.mockReturnValue({
id: 'switch-node',
name: 'Switch',
type: 'n8n-nodes-base.switch',
typeVersion: 3.3,
position: [0, 0],
parameters: {},
});
});
it('should handle items with pairedItem already set', async () => {
const inputData = [{ json: { value: 1 }, pairedItem: { item: 5 } }];
mockExecuteFunctions.getInputData.mockReturnValue(inputData);
mockExecuteFunctions.getNodeParameter.mockImplementation((paramName: string) => {
const params: Record<string, any> = {
mode: 'expression',
numberOutputs: 1,
output: 0,
};
return params[paramName];
});
const result = await switchNode.execute.call(mockExecuteFunctions);
expect(result[0][0].pairedItem).toEqual({ item: 0 });
});
it('should handle output index equal to returnData length', async () => {
const inputData = [{ json: { value: 1 } }];
mockExecuteFunctions.getInputData.mockReturnValue(inputData);
mockExecuteFunctions.getNodeParameter.mockImplementation((paramName: string) => {
const params: Record<string, any> = {
mode: 'expression',
numberOutputs: 2,
output: 2, // Equal to returnData length
};
return params[paramName];
});
await expect(switchNode.execute.call(mockExecuteFunctions)).rejects.toThrow(
NodeOperationError,
);
});
it('should handle fallback output to existing rule output', async () => {
const inputData = [{ json: { status: 'unknown' } }];
mockExecuteFunctions.getInputData.mockReturnValue(inputData);
mockExecuteFunctions.getNodeParameter.mockImplementation(
(paramName: string, _itemIndex: number, defaultValue: any, options?: any) => {
if (paramName === 'mode') return 'rules';
if (paramName === 'rules.values') {
return [{ conditions: { conditions: [], combinator: 'and' } }];
}
if (paramName === 'options') return { fallbackOutput: 0 };
if (paramName.includes('conditions') && options?.extractValue) {
return false; // No rule matches
}
return defaultValue;
},
);
const result = await switchNode.execute.call(mockExecuteFunctions);
expect(result).toHaveLength(1);
expect(result[0]).toHaveLength(1);
expect(result[0][0].json).toEqual({ status: 'unknown' });
});
});
});
@@ -0,0 +1,341 @@
{
"name": "Switch Regex Test",
"nodes": [
{
"parameters": {},
"id": "1301e15e-7a64-44bf-bc4b-d60e7b8c629a",
"name": "When clicking Execute workflow",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [780, 600]
},
{
"parameters": {},
"id": "be9a3cd8-7c19-493c-aacf-a52aba064324",
"name": "Fallback",
"type": "n8n-nodes-base.noOp",
"typeVersion": 1,
"position": [1680, 900]
},
{
"parameters": {},
"id": "f7de5522-5750-4102-9b3b-0a01f7bbf6cc",
"name": "Output",
"type": "n8n-nodes-base.noOp",
"typeVersion": 1,
"position": [1640, 320]
},
{
"parameters": {
"fields": {
"values": [
{
"name": "test",
"stringValue": "value"
}
]
},
"options": {}
},
"id": "55af4400-ed88-4ee2-b654-3a82bd112875",
"name": "Edit Fields",
"type": "n8n-nodes-base.set",
"typeVersion": 3.2,
"position": [1020, 600]
},
{
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "17eb6574-9578-4915-8365-772e08d2f06b",
"leftValue": "={{ $json.test }}",
"rightValue": "/^value$/g",
"operator": {
"type": "string",
"operation": "notRegex"
}
}
],
"combinator": "and"
}
}
]
},
"options": {
"fallbackOutput": "extra"
}
},
"id": "06657954-6bcb-4d60-a659-5d3e5e3d093d",
"name": "NotMatch",
"type": "n8n-nodes-base.switch",
"typeVersion": 3,
"position": [1320, 720],
"alwaysOutputData": false
},
{
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "17eb6574-9578-4915-8365-772e08d2f06b",
"leftValue": "={{ $json.test }}",
"rightValue": "/^value$/g",
"operator": {
"type": "string",
"operation": "regex"
}
}
],
"combinator": "and"
}
}
]
},
"options": {
"fallbackOutput": "extra"
}
},
"id": "07776b86-1d7c-4435-b7d8-da73a01830cf",
"name": "Match",
"type": "n8n-nodes-base.switch",
"typeVersion": 3,
"position": [1320, 340],
"alwaysOutputData": false
},
{
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "17eb6574-9578-4915-8365-772e08d2f06b",
"leftValue": "={{ $json.test }}",
"rightValue": "^value$",
"operator": {
"type": "string",
"operation": "regex"
}
}
],
"combinator": "and"
}
}
]
},
"options": {
"fallbackOutput": "extra"
}
},
"id": "9fb71a7e-23aa-44f6-ae75-cfc4dc045b81",
"name": "Match1",
"type": "n8n-nodes-base.switch",
"typeVersion": 3,
"position": [1320, 500],
"alwaysOutputData": false
},
{
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "17eb6574-9578-4915-8365-772e08d2f06b",
"leftValue": "={{ $json.test }}",
"rightValue": "^value$",
"operator": {
"type": "string",
"operation": "notRegex"
}
}
],
"combinator": "and"
}
}
]
},
"options": {
"fallbackOutput": "extra"
}
},
"id": "555125fe-6509-4b68-8e3d-bf643f9b4d09",
"name": "NotMatch1",
"type": "n8n-nodes-base.switch",
"typeVersion": 3,
"position": [1320, 880],
"alwaysOutputData": false
},
{
"parameters": {},
"id": "a8d5d282-cff3-4bbf-8293-67b1bbb08e2f",
"name": "Output1",
"type": "n8n-nodes-base.noOp",
"typeVersion": 1,
"position": [1640, 480]
},
{
"parameters": {},
"id": "3b7cf77e-f435-4863-a63d-db716cd27528",
"name": "Fallback1",
"type": "n8n-nodes-base.noOp",
"typeVersion": 1,
"position": [1680, 740]
}
],
"pinData": {
"Output": [
{
"json": {
"test": "value"
}
}
],
"Fallback": [
{
"json": {
"test": "value"
}
}
],
"Output1": [
{
"json": {
"test": "value"
}
}
],
"Fallback1": [
{
"json": {
"test": "value"
}
}
]
},
"connections": {
"When clicking Execute workflow": {
"main": [
[
{
"node": "Edit Fields",
"type": "main",
"index": 0
}
]
]
},
"Edit Fields": {
"main": [
[
{
"node": "Match",
"type": "main",
"index": 0
},
{
"node": "NotMatch",
"type": "main",
"index": 0
},
{
"node": "Match1",
"type": "main",
"index": 0
},
{
"node": "NotMatch1",
"type": "main",
"index": 0
}
]
]
},
"NotMatch": {
"main": [
[],
[
{
"node": "Fallback1",
"type": "main",
"index": 0
}
]
]
},
"Match": {
"main": [
[
{
"node": "Output",
"type": "main",
"index": 0
}
]
]
},
"NotMatch1": {
"main": [
[],
[
{
"node": "Fallback",
"type": "main",
"index": 0
}
]
]
},
"Match1": {
"main": [
[
{
"node": "Output1",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "1fdad78e-d569-48c8-bbb9-640e8889b8e3",
"meta": {
"templateCredsSetupCompleted": true,
"instanceId": "8c8c5237b8e37b006a7adce87f4369350c58e41f3ca9de16196d3197f69eabcd"
},
"id": "EbLiIKvBYzJvLtX3",
"tags": []
}
@@ -0,0 +1,241 @@
{
"name": "My workflow 64",
"nodes": [
{
"parameters": {},
"id": "2c6504d1-9412-4da5-bd51-e5f9d6a84721",
"name": "When clicking \"Execute Workflow\"",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [-560, 620]
},
{
"parameters": {
"data": [
{
"output": "third",
"text": "third output text"
},
{
"output": "fourth",
"text": "fourth output text"
},
{
"output": "first",
"text": "first output text"
},
{
"output": "second",
"text": "second output text"
}
]
},
"id": "73d838de-89f2-476e-9dc8-a4dc59e4bdfb",
"name": "Code",
"type": "n8n-nodes-testing.testData",
"typeVersion": 1,
"position": [-340, 620]
},
{
"parameters": {},
"id": "d19a786e-e9fc-4480-af8a-c1abc9d9ef9a",
"name": "No Operation, do nothing",
"type": "n8n-nodes-base.noOp",
"typeVersion": 1,
"position": [200, 460]
},
{
"parameters": {},
"id": "82d5a7b9-6a29-4df8-823a-bd926f2000a9",
"name": "No Operation, do nothing1",
"type": "n8n-nodes-base.noOp",
"typeVersion": 1,
"position": [200, 620]
},
{
"parameters": {},
"id": "40276b8e-eaad-49bd-9271-cd82c6688f24",
"name": "No Operation, do nothing2",
"type": "n8n-nodes-base.noOp",
"typeVersion": 1,
"position": [200, 780]
},
{
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"leftValue": "={{ $json.output }}",
"rightValue": "first",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "First Output"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "199d4f8c-1c92-48cd-99ad-e1da186ed54f",
"leftValue": "={{ $json.output }}",
"rightValue": "second",
"operator": {
"type": "string",
"operation": "equals",
"name": "filter.operator.equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "Second Output"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "e894662a-7496-4df4-a084-7200c3192485",
"leftValue": "={{ $json.output }}",
"rightValue": "third",
"operator": {
"type": "string",
"operation": "equals",
"name": "filter.operator.equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "Third Output"
}
]
},
"options": {
"fallbackOutput": 2
}
},
"id": "0c34bae5-89c8-4adb-bb38-092d5a0e349e",
"name": "Switch1",
"type": "n8n-nodes-base.switch",
"typeVersion": 3,
"position": [-120, 620]
}
],
"pinData": {
"No Operation, do nothing": [
{
"json": {
"output": "first",
"text": "first output text"
}
}
],
"No Operation, do nothing1": [
{
"json": {
"output": "second",
"text": "second output text"
}
}
],
"No Operation, do nothing2": [
{
"json": {
"output": "third",
"text": "third output text"
}
},
{
"json": {
"output": "fourth",
"text": "fourth output text"
}
}
]
},
"connections": {
"When clicking \"Execute Workflow\"": {
"main": [
[
{
"node": "Code",
"type": "main",
"index": 0
}
]
]
},
"Code": {
"main": [
[
{
"node": "Switch1",
"type": "main",
"index": 0
}
]
]
},
"Switch1": {
"main": [
[
{
"node": "No Operation, do nothing",
"type": "main",
"index": 0
}
],
[
{
"node": "No Operation, do nothing1",
"type": "main",
"index": 0
}
],
[
{
"node": "No Operation, do nothing2",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "c9c4d7fd-b704-4664-8fde-d1c2414e68f0",
"id": "1vDZkJN9SpYXu0Ic",
"meta": {
"instanceId": "b888bd11cd1ddbb95450babf3e199556799d999b896f650de768b8370ee50363"
},
"tags": []
}