mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-25 04:34:06 -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];
|
||||
},
|
||||
getItemIndex() {
|
||||
return itemIndex;
|
||||
},
|
||||
getMode: (): WorkflowExecuteMode => {
|
||||
return mode;
|
||||
},
|
||||
|
|
|
@ -566,6 +566,7 @@ export interface IExecuteSingleFunctions {
|
|||
getContext(type: string): IContextObject;
|
||||
getCredentials(type: string): Promise<ICredentialDataDecryptedObject>;
|
||||
getInputData(inputIndex?: number, inputName?: string): INodeExecutionData;
|
||||
getItemIndex(): number;
|
||||
getMode(): WorkflowExecuteMode;
|
||||
getNode(): INode;
|
||||
getNodeParameter(
|
||||
|
|
|
@ -427,6 +427,9 @@ export function getExecuteSingleFunctions(
|
|||
|
||||
return allItems[itemIndex];
|
||||
},
|
||||
getItemIndex: () => {
|
||||
return itemIndex;
|
||||
},
|
||||
getMode: (): WorkflowExecuteMode => {
|
||||
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