diff --git a/packages/@n8n/task-runner/src/js-task-runner/__tests__/result-validation.test.ts b/packages/@n8n/task-runner/src/js-task-runner/__tests__/result-validation.test.ts new file mode 100644 index 0000000000000..7112468863829 --- /dev/null +++ b/packages/@n8n/task-runner/src/js-task-runner/__tests__/result-validation.test.ts @@ -0,0 +1,110 @@ +import { ValidationError } from '@/js-task-runner/errors/validation-error'; +import { + validateRunForAllItemsOutput, + validateRunForEachItemOutput, +} from '@/js-task-runner/result-validation'; + +describe('result validation', () => { + describe('validateRunForAllItemsOutput', () => { + it('should throw an error if the output is not an object', () => { + expect(() => { + validateRunForAllItemsOutput(undefined); + }).toThrowError(ValidationError); + }); + + it('should throw an error if the output is an array and at least one item has a non-n8n key', () => { + expect(() => { + validateRunForAllItemsOutput([{ json: {} }, { json: {}, unknownKey: {} }]); + }).toThrowError(ValidationError); + }); + + it('should not throw an error if the output is an array and all items are json wrapped', () => { + expect(() => { + validateRunForAllItemsOutput([{ json: {} }, { json: {} }, { json: {} }]); + }).not.toThrow(); + }); + + test.each([ + ['binary', {}], + ['pairedItem', {}], + ['error', {}], + ])( + 'should not throw an error if the output item has %s key in addition to json', + (key, value) => { + expect(() => { + validateRunForAllItemsOutput([{ json: {} }, { json: {}, [key]: value }]); + }).not.toThrow(); + }, + ); + + it('should not throw an error if the output is an array and all items are not json wrapped', () => { + expect(() => { + validateRunForAllItemsOutput([ + { + id: 1, + name: 'test3', + }, + { + id: 2, + name: 'test4', + }, + { + id: 3, + name: 'test5', + }, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ] as any); + }).not.toThrow(); + }); + + it('should throw if json is not an object', () => { + expect(() => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + validateRunForAllItemsOutput([{ json: 1 } as any]); + }).toThrowError(ValidationError); + }); + }); + + describe('validateRunForEachItemOutput', () => { + const index = 0; + + it('should throw an error if the output is not an object', () => { + expect(() => { + validateRunForEachItemOutput(undefined, index); + }).toThrowError(ValidationError); + }); + + it('should throw an error if the output is an array', () => { + expect(() => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + validateRunForEachItemOutput([] as any, index); + }).toThrowError(ValidationError); + }); + + it('should throw if json is not an object', () => { + expect(() => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + validateRunForEachItemOutput({ json: 1 } as any, index); + }).toThrowError(ValidationError); + }); + + it('should throw an error if the output is an array and at least one item has a non-n8n key', () => { + expect(() => { + validateRunForEachItemOutput({ json: {}, unknownKey: {} }, index); + }).toThrowError(ValidationError); + }); + + test.each([ + ['binary', {}], + ['pairedItem', {}], + ['error', {}], + ])( + 'should not throw an error if the output item has %s key in addition to json', + (key, value) => { + expect(() => { + validateRunForEachItemOutput({ json: {}, [key]: value }, index); + }).not.toThrow(); + }, + ); + }); +}); diff --git a/packages/@n8n/task-runner/src/js-task-runner/result-validation.ts b/packages/@n8n/task-runner/src/js-task-runner/result-validation.ts index b7d0ffc5fc7ff..4453521bf7fbc 100644 --- a/packages/@n8n/task-runner/src/js-task-runner/result-validation.ts +++ b/packages/@n8n/task-runner/src/js-task-runner/result-validation.ts @@ -9,7 +9,7 @@ export const REQUIRED_N8N_ITEM_KEYS = new Set(['json', 'binary', 'pairedItem', ' function validateTopLevelKeys(item: INodeExecutionData, itemIndex: number) { for (const key in item) { if (Object.prototype.hasOwnProperty.call(item, key)) { - if (REQUIRED_N8N_ITEM_KEYS.has(key)) return; + if (REQUIRED_N8N_ITEM_KEYS.has(key)) continue; throw new ValidationError({ message: `Unknown top-level item key: ${key}`,