mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-26 05:04:05 -08:00
dff8456382
Ensure all errors in `core` and `workflow` inherit from `ApplicationError` so that we start normalizing all the errors we report to Sentry Follow-up to: https://github.com/n8n-io/n8n/pull/7757#discussion_r1404338844 ### `core` package `ApplicationError` - `FileSystemError` (abstract) - `FileNotFoundError` - `DisallowedFilepathError` - `BinaryDataError` (abstract) - `InvalidModeError` - `InvalidManagerError` - `InvalidExecutionMetadataError` ### `workflow` package `ApplicationError` - `ExecutionBaseError` (abstract) - `WorkflowActivationError` - `WorkflowDeactivationError` - `WebhookTakenError` - `WorkflowOperationError` - `SubworkflowOperationError` - `CliWorkflowOperationError` - `ExpressionError` - `ExpressionExtensionError` - `NodeError` (abstract) - `NodeOperationError` - `NodeApiError` - `NodeSSLError` Up next: - Reorganize errors in `cli` - Flatten the hierarchy in `workflow` (do we really need `ExecutionBaseError`?) - Remove `ExecutionError` type - Stop throwing plain `Error`s - Replace `severity` with `level` - Add node and credential types as `tags` - Add workflow IDs and execution IDs as `extras`
349 lines
7.6 KiB
TypeScript
349 lines
7.6 KiB
TypeScript
import type { IConnections, IExecuteData, INode, IRunExecutionData } from '@/Interfaces';
|
|
import { Workflow } from '@/Workflow';
|
|
import { WorkflowDataProxy } from '@/WorkflowDataProxy';
|
|
import * as Helpers from './Helpers';
|
|
import { ExpressionError } from '@/errors/expression.error';
|
|
|
|
describe('WorkflowDataProxy', () => {
|
|
describe('test data proxy', () => {
|
|
const nodes: INode[] = [
|
|
{
|
|
name: 'Start',
|
|
type: 'test.set',
|
|
parameters: {},
|
|
typeVersion: 1,
|
|
id: 'uuid-1',
|
|
position: [100, 200],
|
|
},
|
|
{
|
|
name: 'Function',
|
|
type: 'test.set',
|
|
parameters: {
|
|
functionCode:
|
|
'// Code here will run only once, no matter how many input items there are.\n// More info and help: https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.function/\nconst { DateTime, Duration, Interval } = require("luxon");\n\nconst data = [\n {\n "length": 105\n },\n {\n "length": 160\n },\n {\n "length": 121\n },\n {\n "length": 275\n },\n {\n "length": 950\n },\n];\n\nreturn data.map(fact => ({json: fact}));',
|
|
},
|
|
typeVersion: 1,
|
|
id: 'uuid-2',
|
|
position: [280, 200],
|
|
},
|
|
{
|
|
name: 'Rename',
|
|
type: 'test.set',
|
|
parameters: {
|
|
value1: 'data',
|
|
value2: 'initialName',
|
|
},
|
|
typeVersion: 1,
|
|
id: 'uuid-3',
|
|
position: [460, 200],
|
|
},
|
|
{
|
|
name: 'Set',
|
|
type: 'test.set',
|
|
parameters: {},
|
|
typeVersion: 1,
|
|
id: 'uuid-4',
|
|
position: [640, 200],
|
|
},
|
|
{
|
|
name: 'End',
|
|
type: 'test.set',
|
|
parameters: {},
|
|
typeVersion: 1,
|
|
id: 'uuid-5',
|
|
position: [640, 200],
|
|
},
|
|
];
|
|
|
|
const connections: IConnections = {
|
|
Start: {
|
|
main: [
|
|
[
|
|
{
|
|
node: 'Function',
|
|
type: 'main',
|
|
index: 0,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
Function: {
|
|
main: [
|
|
[
|
|
{
|
|
node: 'Rename',
|
|
type: 'main',
|
|
index: 0,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
Rename: {
|
|
main: [
|
|
[
|
|
{
|
|
node: 'End',
|
|
type: 'main',
|
|
index: 0,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
};
|
|
|
|
const runExecutionData: IRunExecutionData = {
|
|
resultData: {
|
|
runData: {
|
|
Start: [
|
|
{
|
|
startTime: 1,
|
|
executionTime: 1,
|
|
data: {
|
|
main: [
|
|
[
|
|
{
|
|
json: {},
|
|
},
|
|
],
|
|
],
|
|
},
|
|
source: [],
|
|
},
|
|
],
|
|
Function: [
|
|
{
|
|
startTime: 1,
|
|
executionTime: 1,
|
|
data: {
|
|
main: [
|
|
[
|
|
{
|
|
json: { initialName: 105 },
|
|
pairedItem: { item: 0 },
|
|
},
|
|
{
|
|
json: { initialName: 160 },
|
|
pairedItem: { item: 0 },
|
|
},
|
|
{
|
|
json: { initialName: 121 },
|
|
pairedItem: { item: 0 },
|
|
},
|
|
{
|
|
json: { initialName: 275 },
|
|
pairedItem: { item: 0 },
|
|
},
|
|
{
|
|
json: { initialName: 950 },
|
|
pairedItem: { item: 0 },
|
|
},
|
|
],
|
|
],
|
|
},
|
|
source: [
|
|
{
|
|
previousNode: 'Start',
|
|
},
|
|
],
|
|
},
|
|
],
|
|
Rename: [
|
|
{
|
|
startTime: 1,
|
|
executionTime: 1,
|
|
data: {
|
|
main: [
|
|
[
|
|
{
|
|
json: { data: 105 },
|
|
pairedItem: { item: 0 },
|
|
},
|
|
{
|
|
json: { data: 160 },
|
|
pairedItem: { item: 1 },
|
|
},
|
|
{
|
|
json: { data: 121 },
|
|
pairedItem: { item: 2 },
|
|
},
|
|
{
|
|
json: { data: 275 },
|
|
pairedItem: { item: 3 },
|
|
},
|
|
{
|
|
json: { data: 950 },
|
|
pairedItem: { item: 4 },
|
|
},
|
|
],
|
|
],
|
|
},
|
|
source: [
|
|
{
|
|
previousNode: 'Function',
|
|
},
|
|
],
|
|
},
|
|
],
|
|
End: [
|
|
{
|
|
startTime: 1,
|
|
executionTime: 1,
|
|
data: {
|
|
main: [
|
|
[
|
|
{
|
|
json: { data: 105 },
|
|
pairedItem: { item: 0 },
|
|
},
|
|
{
|
|
json: { data: 160 },
|
|
pairedItem: { item: 1 },
|
|
},
|
|
{
|
|
json: { data: 121 },
|
|
pairedItem: { item: 2 },
|
|
},
|
|
{
|
|
json: { data: 275 },
|
|
pairedItem: { item: 3 },
|
|
},
|
|
{
|
|
json: { data: 950 },
|
|
pairedItem: { item: 4 },
|
|
},
|
|
],
|
|
],
|
|
},
|
|
source: [
|
|
{
|
|
previousNode: 'Rename',
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
},
|
|
};
|
|
|
|
const nodeTypes = Helpers.NodeTypes();
|
|
const workflow = new Workflow({
|
|
id: '123',
|
|
name: 'test workflow',
|
|
nodes,
|
|
connections,
|
|
active: false,
|
|
nodeTypes,
|
|
});
|
|
const nameLastNode = 'End';
|
|
|
|
const lastNodeConnectionInputData =
|
|
runExecutionData.resultData.runData[nameLastNode][0].data!.main[0];
|
|
|
|
const executeData: IExecuteData = {
|
|
data: runExecutionData.resultData.runData[nameLastNode][0].data!,
|
|
node: nodes.find((node) => node.name === nameLastNode) as INode,
|
|
source: {
|
|
main: runExecutionData.resultData.runData[nameLastNode][0].source,
|
|
},
|
|
};
|
|
|
|
const dataProxy = new WorkflowDataProxy(
|
|
workflow,
|
|
runExecutionData,
|
|
0,
|
|
0,
|
|
nameLastNode,
|
|
lastNodeConnectionInputData ?? [],
|
|
{},
|
|
'manual',
|
|
{},
|
|
executeData,
|
|
);
|
|
const proxy = dataProxy.getDataProxy();
|
|
|
|
test('test $("NodeName").all()', () => {
|
|
expect(proxy.$('Rename').all()[1].json.data).toEqual(160);
|
|
});
|
|
test('test $("NodeName").all() length', () => {
|
|
expect(proxy.$('Rename').all().length).toEqual(5);
|
|
});
|
|
test('test $("NodeName").item', () => {
|
|
expect(proxy.$('Rename').item).toEqual({ json: { data: 105 }, pairedItem: { item: 0 } });
|
|
});
|
|
test('test $("NodeNameEarlier").item', () => {
|
|
expect(proxy.$('Function').item).toEqual({
|
|
json: { initialName: 105 },
|
|
pairedItem: { item: 0 },
|
|
});
|
|
});
|
|
test('test $("NodeName").itemMatching(2)', () => {
|
|
expect(proxy.$('Rename').itemMatching(2).json.data).toEqual(121);
|
|
});
|
|
test('test $("NodeName").first()', () => {
|
|
expect(proxy.$('Rename').first().json.data).toEqual(105);
|
|
});
|
|
test('test $("NodeName").last()', () => {
|
|
expect(proxy.$('Rename').last().json.data).toEqual(950);
|
|
});
|
|
|
|
test('test $("NodeName").params', () => {
|
|
expect(proxy.$('Rename').params).toEqual({ value1: 'data', value2: 'initialName' });
|
|
});
|
|
|
|
test('$("NodeName")', () => {
|
|
expect(() => proxy.$('doNotExist')).toThrowError(ExpressionError);
|
|
});
|
|
|
|
test('$("NodeName")', () => {
|
|
expect(() => proxy.$('Set')).toThrowError(ExpressionError);
|
|
});
|
|
|
|
test('test $input.all()', () => {
|
|
expect(proxy.$input.all()[1].json.data).toEqual(160);
|
|
});
|
|
test('test $input.all() length', () => {
|
|
expect(proxy.$input.all().length).toEqual(5);
|
|
});
|
|
test('test $input.first()', () => {
|
|
expect(proxy.$input.first().json.data).toEqual(105);
|
|
});
|
|
test('test $input.last()', () => {
|
|
expect(proxy.$input.last().json.data).toEqual(950);
|
|
});
|
|
test('test $input.item', () => {
|
|
expect(proxy.$input.item.json.data).toEqual(105);
|
|
});
|
|
test('test $thisItem', () => {
|
|
expect(proxy.$thisItem.json.data).toEqual(105);
|
|
});
|
|
|
|
test('test $binary', () => {
|
|
expect(proxy.$binary).toEqual({});
|
|
});
|
|
|
|
test('test $json', () => {
|
|
expect(proxy.$json).toEqual({ data: 105 });
|
|
});
|
|
|
|
test('test $itemIndex', () => {
|
|
expect(proxy.$itemIndex).toEqual(0);
|
|
});
|
|
|
|
test('test $prevNode', () => {
|
|
expect(proxy.$prevNode).toEqual({ name: 'Rename', outputIndex: 0, runIndex: 0 });
|
|
});
|
|
|
|
test('test $runIndex', () => {
|
|
expect(proxy.$runIndex).toEqual(0);
|
|
});
|
|
|
|
test('test $workflow', () => {
|
|
expect(proxy.$workflow).toEqual({
|
|
active: false,
|
|
id: '123',
|
|
name: 'test workflow',
|
|
});
|
|
});
|
|
});
|
|
});
|