mirror of
https://github.com/n8n-io/n8n.git
synced 2025-01-12 21:37:32 -08:00
feat(core): Expose item index being processed (#3590)
* 🧑💻 Expose item index being processed * ✅ Fix tests for getCurrentItemIndex * ✅ Fix tests for getCurrentItemIndex * ⚡ Rename method Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
This commit is contained in:
parent
23eba33613
commit
1e4fd9e4df
|
@ -2320,6 +2320,9 @@ export function getExecuteSingleFunctions(
|
||||||
|
|
||||||
return allItems[itemIndex];
|
return allItems[itemIndex];
|
||||||
},
|
},
|
||||||
|
getItemIndex() {
|
||||||
|
return itemIndex;
|
||||||
|
},
|
||||||
getMode: (): WorkflowExecuteMode => {
|
getMode: (): WorkflowExecuteMode => {
|
||||||
return mode;
|
return mode;
|
||||||
},
|
},
|
||||||
|
|
|
@ -566,6 +566,7 @@ export interface IExecuteSingleFunctions {
|
||||||
getContext(type: string): IContextObject;
|
getContext(type: string): IContextObject;
|
||||||
getCredentials(type: string): Promise<ICredentialDataDecryptedObject>;
|
getCredentials(type: string): Promise<ICredentialDataDecryptedObject>;
|
||||||
getInputData(inputIndex?: number, inputName?: string): INodeExecutionData;
|
getInputData(inputIndex?: number, inputName?: string): INodeExecutionData;
|
||||||
|
getItemIndex(): number;
|
||||||
getMode(): WorkflowExecuteMode;
|
getMode(): WorkflowExecuteMode;
|
||||||
getNode(): INode;
|
getNode(): INode;
|
||||||
getNodeParameter(
|
getNodeParameter(
|
||||||
|
|
|
@ -427,6 +427,9 @@ export function getExecuteSingleFunctions(
|
||||||
|
|
||||||
return allItems[itemIndex];
|
return allItems[itemIndex];
|
||||||
},
|
},
|
||||||
|
getItemIndex: () => {
|
||||||
|
return itemIndex;
|
||||||
|
},
|
||||||
getMode: (): WorkflowExecuteMode => {
|
getMode: (): WorkflowExecuteMode => {
|
||||||
return mode;
|
return mode;
|
||||||
},
|
},
|
||||||
|
|
|
@ -1748,4 +1748,194 @@ describe('RoutingNode', () => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('itemIndex', () => {
|
||||||
|
const tests: Array<{
|
||||||
|
description: string;
|
||||||
|
input: {
|
||||||
|
nodeType: {
|
||||||
|
properties?: INodeProperties[];
|
||||||
|
credentials?: INodeCredentialDescription[];
|
||||||
|
requestDefaults?: IHttpRequestOptions;
|
||||||
|
requestOperations?: IN8nRequestOperations;
|
||||||
|
};
|
||||||
|
node: {
|
||||||
|
parameters: INodeParameters;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
output: INodeExecutionData[][] | undefined;
|
||||||
|
}> = [
|
||||||
|
{
|
||||||
|
description: 'single parameter, only send defined, fixed value, using requestDefaults',
|
||||||
|
input: {
|
||||||
|
nodeType: {
|
||||||
|
requestDefaults: {
|
||||||
|
baseURL: 'http://127.0.0.1:5678',
|
||||||
|
url: '/test-url',
|
||||||
|
},
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
displayName: 'Email',
|
||||||
|
name: 'email',
|
||||||
|
type: 'string',
|
||||||
|
routing: {
|
||||||
|
send: {
|
||||||
|
property: 'toEmail',
|
||||||
|
type: 'body',
|
||||||
|
value: 'fixedValue',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
node: {
|
||||||
|
parameters: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
output: [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
json: {
|
||||||
|
headers: {},
|
||||||
|
statusCode: 200,
|
||||||
|
requestOptions: {
|
||||||
|
url: '/test-url',
|
||||||
|
qs: {},
|
||||||
|
body: {
|
||||||
|
toEmail: 'fixedValue',
|
||||||
|
},
|
||||||
|
baseURL: 'http://127.0.0.1:5678',
|
||||||
|
returnFullResponse: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const nodeTypes = Helpers.NodeTypes();
|
||||||
|
const baseNode: INode = {
|
||||||
|
parameters: {},
|
||||||
|
name: 'test',
|
||||||
|
type: 'test.set',
|
||||||
|
typeVersion: 1,
|
||||||
|
position: [0, 0],
|
||||||
|
};
|
||||||
|
|
||||||
|
const mode = 'internal';
|
||||||
|
const runIndex = 0;
|
||||||
|
const itemIndex = 0;
|
||||||
|
const connectionInputData: INodeExecutionData[] = [];
|
||||||
|
const runExecutionData: IRunExecutionData = { resultData: { runData: {} } };
|
||||||
|
const additionalData = Helpers.WorkflowExecuteAdditionalData();
|
||||||
|
const nodeType = nodeTypes.getByNameAndVersion(baseNode.type);
|
||||||
|
|
||||||
|
const inputData: ITaskDataConnections = {
|
||||||
|
main: [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
json: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
json: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
json: {},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const testData of tests) {
|
||||||
|
test(testData.description, async () => {
|
||||||
|
const node: INode = { ...baseNode, ...testData.input.node };
|
||||||
|
|
||||||
|
const workflowData = {
|
||||||
|
nodes: [node],
|
||||||
|
connections: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
nodeType.description = { ...testData.input.nodeType };
|
||||||
|
|
||||||
|
const workflow = new Workflow({
|
||||||
|
nodes: workflowData.nodes,
|
||||||
|
connections: workflowData.connections,
|
||||||
|
active: false,
|
||||||
|
nodeTypes,
|
||||||
|
});
|
||||||
|
|
||||||
|
const routingNode = new RoutingNode(
|
||||||
|
workflow,
|
||||||
|
node,
|
||||||
|
connectionInputData,
|
||||||
|
runExecutionData ?? null,
|
||||||
|
additionalData,
|
||||||
|
mode,
|
||||||
|
);
|
||||||
|
|
||||||
|
const executeData = {
|
||||||
|
data: {},
|
||||||
|
node,
|
||||||
|
source: null,
|
||||||
|
} as IExecuteData;
|
||||||
|
|
||||||
|
let currentItemIndex = 0;
|
||||||
|
for (let iteration = 0; iteration < inputData.main[0]!.length; iteration++) {
|
||||||
|
// @ts-ignore
|
||||||
|
const nodeExecuteFunctions: INodeExecuteFunctions = {
|
||||||
|
getExecuteFunctions: () => {
|
||||||
|
return Helpers.getExecuteFunctions(
|
||||||
|
workflow,
|
||||||
|
runExecutionData,
|
||||||
|
runIndex,
|
||||||
|
connectionInputData,
|
||||||
|
{},
|
||||||
|
node,
|
||||||
|
itemIndex + iteration,
|
||||||
|
additionalData,
|
||||||
|
executeData,
|
||||||
|
mode,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
getExecuteSingleFunctions: () => {
|
||||||
|
return Helpers.getExecuteSingleFunctions(
|
||||||
|
workflow,
|
||||||
|
runExecutionData,
|
||||||
|
runIndex,
|
||||||
|
connectionInputData,
|
||||||
|
{},
|
||||||
|
node,
|
||||||
|
itemIndex + iteration,
|
||||||
|
additionalData,
|
||||||
|
executeData,
|
||||||
|
mode,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const routingNodeExecutionContext = nodeExecuteFunctions.getExecuteSingleFunctions(
|
||||||
|
routingNode.workflow,
|
||||||
|
routingNode.runExecutionData,
|
||||||
|
runIndex,
|
||||||
|
routingNode.connectionInputData,
|
||||||
|
inputData,
|
||||||
|
routingNode.node,
|
||||||
|
iteration,
|
||||||
|
routingNode.additionalData,
|
||||||
|
executeData,
|
||||||
|
routingNode.mode,
|
||||||
|
);
|
||||||
|
|
||||||
|
currentItemIndex = routingNodeExecutionContext.getItemIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
const expectedItemIndex = inputData.main[0]!.length - 1;
|
||||||
|
|
||||||
|
expect(currentItemIndex).toEqual(expectedItemIndex);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue