mirror of
https://github.com/n8n-io/n8n.git
synced 2026-05-23 04:45:21 +02:00
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Danny Martini <danny@n8n.io>
95 lines
2.7 KiB
TypeScript
95 lines
2.7 KiB
TypeScript
import flatted from 'flatted';
|
|
import type { IWorkflowBase } from 'n8n-workflow';
|
|
import { nanoid } from 'nanoid';
|
|
|
|
import { workflow, trigger, node } from '../../../../../@n8n/workflow-sdk/src';
|
|
import { test, expect } from '../../../fixtures/base';
|
|
|
|
const TRIGGER_NAME = 'Manual Trigger';
|
|
const ALL_ITEMS_NODE_NAME = 'Code All Items';
|
|
const EACH_ITEM_NODE_NAME = 'Code Each Item';
|
|
|
|
function createCodeNodeWorkflow(): IWorkflowBase {
|
|
const manualTrigger = trigger({
|
|
type: 'n8n-nodes-base.manualTrigger',
|
|
version: 1,
|
|
config: {
|
|
name: TRIGGER_NAME,
|
|
parameters: {},
|
|
},
|
|
});
|
|
|
|
const codeAllItems = node({
|
|
type: 'n8n-nodes-base.code',
|
|
version: 1,
|
|
config: {
|
|
name: ALL_ITEMS_NODE_NAME,
|
|
parameters: {
|
|
mode: 'runOnceForAllItems',
|
|
jsCode: 'return [{ json: { value: 1 } }, { json: { value: 2 } }];',
|
|
},
|
|
},
|
|
});
|
|
|
|
const codeEachItem = node({
|
|
type: 'n8n-nodes-base.code',
|
|
version: 1,
|
|
config: {
|
|
name: EACH_ITEM_NODE_NAME,
|
|
parameters: {
|
|
mode: 'runOnceForEachItem',
|
|
jsCode: 'return { json: { processed: $json.value * 2 } };',
|
|
},
|
|
},
|
|
});
|
|
|
|
const wf = workflow(nanoid(), `Code node test ${nanoid()}`)
|
|
.add(manualTrigger.to(codeAllItems))
|
|
.add(codeAllItems.to(codeEachItem));
|
|
|
|
const json = wf.toJSON() as IWorkflowBase;
|
|
json.settings = { executionOrder: 'v1' };
|
|
|
|
return json;
|
|
}
|
|
|
|
test.describe(
|
|
'Code node API execution @capability:task-runner',
|
|
{
|
|
annotation: [{ type: 'owner', description: 'NODES' }],
|
|
},
|
|
() => {
|
|
test('should execute runOnceForAllItems and runOnceForEachItem code nodes successfully', async ({
|
|
api,
|
|
}) => {
|
|
const { workflowId } = await api.workflows.createWorkflowFromDefinition(
|
|
createCodeNodeWorkflow(),
|
|
);
|
|
|
|
await api.workflows.runManually(workflowId, TRIGGER_NAME);
|
|
|
|
const execution = await api.workflows.waitForExecution(workflowId, 15_000, 'manual');
|
|
expect(execution.status).toBe('success');
|
|
|
|
const fullExecution = await api.workflows.getExecution(execution.id);
|
|
const executionData = flatted.parse(fullExecution.data);
|
|
|
|
// Verify runOnceForAllItems node produced correct output
|
|
const allItemsOutput = executionData.resultData.runData[ALL_ITEMS_NODE_NAME];
|
|
expect(allItemsOutput).toBeDefined();
|
|
expect(allItemsOutput[0].data.main[0]).toEqual([
|
|
expect.objectContaining({ json: { value: 1 } }),
|
|
expect.objectContaining({ json: { value: 2 } }),
|
|
]);
|
|
|
|
// Verify runOnceForEachItem node processed each item correctly
|
|
const eachItemOutput = executionData.resultData.runData[EACH_ITEM_NODE_NAME];
|
|
expect(eachItemOutput).toBeDefined();
|
|
expect(eachItemOutput[0].data.main[0]).toEqual([
|
|
expect.objectContaining({ json: { processed: 2 } }),
|
|
expect.objectContaining({ json: { processed: 4 } }),
|
|
]);
|
|
});
|
|
},
|
|
);
|