-
Notifications
You must be signed in to change notification settings - Fork 13k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(Summarize Node): Turns error when field not found in items into …
…warning (#11889) Co-authored-by: Dana Lee <[email protected]> Co-authored-by: Elias Meire <[email protected]>
- Loading branch information
1 parent
69a97bd
commit d7dda3f
Showing
5 changed files
with
237 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
53 changes: 53 additions & 0 deletions
53
packages/nodes-base/nodes/Transform/Summarize/test/unitTests/checkIfFieldExists.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import { NodeOperationError, type IExecuteFunctions, type IDataObject } from 'n8n-workflow'; | ||
|
||
import { checkIfFieldExists, type Aggregations } from '../../utils'; | ||
|
||
describe('Test Summarize Node, checkIfFieldExists', () => { | ||
let mockExecuteFunctions: IExecuteFunctions; | ||
|
||
beforeEach(() => { | ||
mockExecuteFunctions = { | ||
getNode: jest.fn().mockReturnValue({ name: 'test-node' }), | ||
} as unknown as IExecuteFunctions; | ||
}); | ||
|
||
const items = [{ a: 1 }, { b: 2 }, { c: 3 }]; | ||
|
||
it('should not throw error if all fields exist', () => { | ||
const aggregations: Aggregations = [ | ||
{ aggregation: 'sum', field: 'a' }, | ||
{ aggregation: 'count', field: 'c' }, | ||
]; | ||
const getValue = (item: IDataObject, field: string) => item[field]; | ||
expect(() => { | ||
checkIfFieldExists.call(mockExecuteFunctions, items, aggregations, getValue); | ||
}).not.toThrow(); | ||
}); | ||
|
||
it('should throw NodeOperationError if any field does not exist', () => { | ||
const aggregations: Aggregations = [ | ||
{ aggregation: 'sum', field: 'b' }, | ||
{ aggregation: 'count', field: 'd' }, | ||
]; | ||
const getValue = (item: IDataObject, field: string) => item[field]; | ||
expect(() => { | ||
checkIfFieldExists.call(mockExecuteFunctions, items, aggregations, getValue); | ||
}).toThrow(NodeOperationError); | ||
}); | ||
|
||
it("should throw NodeOperationError with error message containing the field name that doesn't exist", () => { | ||
const aggregations: Aggregations = [{ aggregation: 'count', field: 'D' }]; | ||
const getValue = (item: IDataObject, field: string) => item[field]; | ||
expect(() => { | ||
checkIfFieldExists.call(mockExecuteFunctions, items, aggregations, getValue); | ||
}).toThrow("The field 'D' does not exist in any items"); | ||
}); | ||
|
||
it('should not throw error if field is empty string', () => { | ||
const aggregations: Aggregations = [{ aggregation: 'count', field: '' }]; | ||
const getValue = (item: IDataObject, field: string) => item[field]; | ||
expect(() => { | ||
checkIfFieldExists.call(mockExecuteFunctions, items, aggregations, getValue); | ||
}).not.toThrow(); | ||
}); | ||
}); |
80 changes: 80 additions & 0 deletions
80
packages/nodes-base/nodes/Transform/Summarize/test/unitTests/execute.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import type { MockProxy } from 'jest-mock-extended'; | ||
import { mock } from 'jest-mock-extended'; | ||
import type { IExecuteFunctions } from 'n8n-workflow'; | ||
import { NodeExecutionOutput, NodeOperationError } from 'n8n-workflow'; | ||
|
||
import { Summarize } from '../../Summarize.node'; | ||
import type { Aggregations } from '../../utils'; | ||
|
||
let summarizeNode: Summarize; | ||
let mockExecuteFunctions: MockProxy<IExecuteFunctions>; | ||
|
||
describe('Test Summarize Node, execute', () => { | ||
beforeEach(() => { | ||
summarizeNode = new Summarize(); | ||
mockExecuteFunctions = mock<IExecuteFunctions>({ | ||
getNode: jest.fn().mockReturnValue({ name: 'test-node' }), | ||
getNodeParameter: jest.fn(), | ||
getInputData: jest.fn(), | ||
helpers: { | ||
constructExecutionMetaData: jest.fn().mockReturnValue([]), | ||
}, | ||
}); | ||
}); | ||
|
||
afterEach(() => { | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
it('should handle field not found with hints if version > 1', async () => { | ||
mockExecuteFunctions.getInputData.mockReturnValue([{ json: { someField: 1 } }]); | ||
mockExecuteFunctions.getNode.mockReturnValue({ | ||
id: '1', | ||
name: 'test-node', | ||
type: 'test-type', | ||
position: [0, 0], | ||
parameters: {}, | ||
typeVersion: 1.1, | ||
}); | ||
mockExecuteFunctions.getNodeParameter | ||
.mockReturnValueOnce({}) // options | ||
.mockReturnValueOnce('') // fieldsToSplitBy | ||
.mockReturnValueOnce([{ field: 'nonexistentField', aggregation: 'sum' }]); // fieldsToSummarize | ||
|
||
const result = await summarizeNode.execute.call(mockExecuteFunctions); | ||
|
||
expect(result).toBeInstanceOf(NodeExecutionOutput); | ||
expect(result).toEqual([[{ json: { sum_nonexistentField: 0 }, pairedItem: [{ item: 0 }] }]]); | ||
expect((result as NodeExecutionOutput).getHints()).toEqual([ | ||
{ | ||
location: 'outputPane', | ||
message: "The field 'nonexistentField' does not exist in any items", | ||
}, | ||
]); | ||
}); | ||
|
||
it('should throw error if node version is < 1.1 and fields not found', async () => { | ||
const items = [{ json: { a: 1, b: 2, c: 3 } }]; | ||
const aggregations: Aggregations = [ | ||
{ aggregation: 'sum', field: 'b' }, | ||
{ aggregation: 'count', field: 'd' }, | ||
]; | ||
|
||
mockExecuteFunctions.getNode.mockReturnValue({ | ||
id: '1', | ||
name: 'test-node', | ||
type: 'test-type', | ||
position: [0, 0], | ||
parameters: {}, | ||
typeVersion: 1, | ||
}); | ||
mockExecuteFunctions.getInputData.mockReturnValue(items); | ||
mockExecuteFunctions.getNodeParameter | ||
.mockReturnValueOnce({}) // options | ||
.mockReturnValueOnce('') // fieldsToSplitBy | ||
.mockReturnValueOnce(aggregations); // fieldsToSummarize | ||
await expect(async () => { | ||
await summarizeNode.execute.bind(mockExecuteFunctions)(); | ||
}).rejects.toThrow(NodeOperationError); | ||
}); | ||
}); |
70 changes: 70 additions & 0 deletions
70
packages/nodes-base/nodes/Transform/Summarize/test/workflow.summarize_hint.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
{ | ||
"nodes": [ | ||
{ | ||
"parameters": {}, | ||
"type": "n8n-nodes-base.manualTrigger", | ||
"typeVersion": 1, | ||
"position": [520, -80], | ||
"id": "9ff1d8e0-ebe8-4c52-931a-e482e14ac911", | ||
"name": "When clicking ‘Test workflow’" | ||
}, | ||
{ | ||
"parameters": { | ||
"category": "randomData", | ||
"randomDataSeed": "ria", | ||
"randomDataCount": 5 | ||
}, | ||
"type": "n8n-nodes-base.debugHelper", | ||
"typeVersion": 1, | ||
"position": [700, -80], | ||
"id": "50cea846-f8ed-4b5a-a14a-c11bf4ba0f5d", | ||
"name": "DebugHelper2" | ||
}, | ||
{ | ||
"parameters": { | ||
"fieldsToSummarize": { | ||
"values": [ | ||
{ | ||
"field": "passwor" | ||
} | ||
] | ||
}, | ||
"options": {} | ||
}, | ||
"type": "n8n-nodes-base.summarize", | ||
"typeVersion": 1.1, | ||
"position": [900, -80], | ||
"id": "d39fedc9-62e1-45bc-8c9a-d20f2b63b543", | ||
"name": "Summarize1" | ||
} | ||
], | ||
"connections": { | ||
"When clicking ‘Test workflow’": { | ||
"main": [ | ||
[ | ||
{ | ||
"node": "DebugHelper2", | ||
"type": "main", | ||
"index": 0 | ||
} | ||
] | ||
] | ||
}, | ||
"DebugHelper2": { | ||
"main": [ | ||
[ | ||
{ | ||
"node": "Summarize1", | ||
"type": "main", | ||
"index": 0 | ||
} | ||
] | ||
] | ||
} | ||
}, | ||
"pinData": {}, | ||
"meta": { | ||
"templateCredsSetupCompleted": true, | ||
"instanceId": "ee90fdf8d57662f949e6c691dc07fa0fd2f66e1eee28ed82ef06658223e67255" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters