This commit is contained in:
Raj shakya 2025-11-20 17:04:39 +00:00 committed by GitHub
commit 90e580d788
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 237 additions and 3 deletions

View File

@ -0,0 +1,236 @@
import get from 'lodash/get';
import { constructExecutionMetaData } from 'n8n-core';
import {
// NodeOperationError,
type IDataObject,
type IExecuteFunctions,
type IGetNodeParameterOptions,
type INode,
type INodeExecutionData,
} from 'n8n-workflow';
import { type SetNodeOptions } from '../../v2/helpers/interfaces';
import { execute } from '../../v2/manual.mode';
const node: INode = {
id: '11',
name: 'Set Node',
type: 'n8n-nodes-base.set',
notes: 'text ',
typeVersion: 3.4,
position: [42, 42],
onError: 'continueErrorOutput',
parameters: {
assignments: {
assignments: [
{
id: 'b5633e0b-221c-480e-b050-7f34bad8869d',
name: 'Name',
type: 'object',
value: '=invalid object ,{;[',
},
],
},
mode: 'manual',
options: {},
duplicateItem: false,
includeOtherFields: false,
},
};
const createMockExecuteFunction = (
nodeParameters: IDataObject,
continueOnFail: boolean = false,
) => {
const fakeExecuteFunction = {
getNodeParameter(
parameterName: string,
_itemIndex: number,
fallbackValue?: IDataObject,
options?: IGetNodeParameterOptions,
) {
const parameter = options?.extractValue ? `${parameterName}.value` : parameterName;
return get(nodeParameters, parameter, fallbackValue);
},
getNode() {
return node;
},
helpers: { constructExecutionMetaData },
continueOnFail: () => continueOnFail,
} as unknown as IExecuteFunctions;
return fakeExecuteFunction;
};
describe('test Set2, manual mode - error handling with continueOnFail', () => {
const item: INodeExecutionData = {
json: {
input1: 'value1',
input2: 2,
},
pairedItem: {
item: 0,
input: undefined,
},
};
const options: SetNodeOptions = {
include: 'none',
};
afterEach(() => jest.resetAllMocks());
describe('error handling with malformed Object field', () => {
it('should return error object with pairedItem when continueOnFail is true and Object parsing fails', async () => {
// Simulate a malformed Object value that will cause parsing to fail
const malformedObjectValue = '{ invalid json syntax }';
const nodeParameters = {
assignments: {
assignments: [
{
id: 'b5633e0b-221c-480e-b050-7f34bad8869d',
name: 'testField',
type: 'object',
value: malformedObjectValue,
},
],
},
mode: 'manual',
options: {},
};
const fakeExecuteFunction = createMockExecuteFunction(nodeParameters, true);
const rawDataWithMalformed = {
testField: malformedObjectValue,
};
const output = await execute.call(
fakeExecuteFunction,
item,
0,
options,
rawDataWithMalformed,
node,
);
// Verify that the error is returned in the correct format
expect(output).toHaveProperty('json');
expect(output.json).toHaveProperty('error');
expect(output).toHaveProperty('pairedItem');
expect(output.pairedItem).toEqual({ item: 0 });
expect(typeof output.json.error).toBe('string');
expect(output.json.error).toContain('invalid JSON');
});
it('should return error object when continueOnFail is true and Object value is completely invalid', async () => {
// Test with a value that cannot be parsed as JSON at all
const invalidObjectValue = 'not a json object at all';
const nodeParameters = {
assignments: {
assignments: [
{
id: 'b5633e0b-221c-480e-b050-7f34bad8869d',
name: 'testField',
type: 'object',
value: 'invalid-object',
},
],
},
mode: 'manual',
options: {},
};
const fakeExecuteFunction = createMockExecuteFunction(nodeParameters, true);
const rawDataWithInvalid = {
testField: invalidObjectValue,
};
const output = await execute.call(
fakeExecuteFunction,
item,
0,
options,
rawDataWithInvalid,
node,
);
expect(output).toHaveProperty('json');
expect(output.json).toHaveProperty('error');
expect(output.json.error).toContain('invalid JSON');
expect(output.pairedItem).toEqual({ item: 0 });
});
it('should return error object with correct pairedItem index when processing multiple items', async () => {
const malformedObjectValue = '{ invalid }';
const nodeParameters = {
assignments: {
assignments: [
{
id: 'b5633e0b-221c-480e-b050-7f34bad8869d',
name: 'testField',
type: 'object',
value: malformedObjectValue,
},
],
},
mode: 'manual',
options: {},
};
const fakeExecuteFunction = createMockExecuteFunction(nodeParameters, true);
const rawDataWithMalformed = {
testField: malformedObjectValue,
};
// Test with item index 3
const output = await execute.call(
fakeExecuteFunction,
item,
3,
options,
rawDataWithMalformed,
node,
);
expect(output.pairedItem).toEqual({ item: 3 });
expect(output.json.error).toBeDefined();
});
it('should route error item to error output branch (output index 1)', async () => {
const malformedObjectValue = 'invalid{json}';
const nodeParameters = {
assignments: {
assignments: [
{
id: 'b5633e0b-221c-480e-b050-7f34bad8869d',
name: 'testField',
type: 'object',
value: malformedObjectValue,
},
],
},
mode: 'manual',
options: {},
};
const fakeExecuteFunction = createMockExecuteFunction(nodeParameters, true);
const rawDataWithMalformed = {
testField: malformedObjectValue,
};
const output = await execute.call(
fakeExecuteFunction,
item,
0,
options,
rawDataWithMalformed,
node,
);
// The output should have error property which signals error output routing
expect(output).toHaveProperty('json');
expect(output.json).toHaveProperty('error');
expect(typeof output.json.error).toBe('string');
expect(output.pairedItem).toEqual({ item: 0 });
});
});
});

View File

@ -329,7 +329,6 @@ export class SetV2 implements INodeType {
const workflowFieldsJson = this.getNodeParameter('fields.values', 0, [], {
rawExpressions: true,
}) as SetField[];
for (const entry of workflowFieldsJson) {
if (entry.type === 'objectValue' && (entry.objectValue as string).startsWith('=')) {
rawData[entry.name] = (entry.objectValue as string).replace(/^=+/, '');
@ -367,7 +366,6 @@ export class SetV2 implements INodeType {
returnData.push(newItem);
}
}
return [returnData];
}
}

View File

@ -238,7 +238,7 @@ export async function execute(
return prepareReturnItem(this, assignmentCollection, i, item, node, options);
} catch (error) {
if (this.continueOnFail()) {
return { json: { error: (error as Error).message, pairedItem: { item: i } } };
return { json: { error: (error as Error).message }, pairedItem: { item: i } };
}
throw new NodeOperationError(this.getNode(), error as Error, {
itemIndex: i,