Skip to content

Commit

Permalink
fix(Wait Node): Fix for hasNextPage in waiting forms (#12636)
Browse files Browse the repository at this point in the history
  • Loading branch information
michael-radency authored Jan 20, 2025
1 parent 847aa12 commit 652b8d1
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -79,18 +79,24 @@ export abstract class NodeExecutionContext implements Omit<FunctionsBase, 'getCr
return this.workflow.getStaticData(type, this.node);
}

getChildNodes(nodeName: string) {
getChildNodes(nodeName: string, options?: { includeNodeParameters?: boolean }) {
const output: NodeTypeAndVersion[] = [];
const nodeNames = this.workflow.getChildNodes(nodeName);

for (const n of nodeNames) {
const node = this.workflow.nodes[n];
output.push({
const entry: NodeTypeAndVersion = {
name: node.name,
type: node.type,
typeVersion: node.typeVersion,
disabled: node.disabled ?? false,
});
};

if (options?.includeNodeParameters) {
entry.parameters = node.parameters;
}

output.push(entry);
}
return output;
}
Expand Down
42 changes: 41 additions & 1 deletion packages/nodes-base/nodes/Form/test/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,16 @@ import type {
INode,
IWebhookFunctions,
MultiPartFormData,
NodeTypeAndVersion,
} from 'n8n-workflow';

import { formWebhook, prepareFormData, prepareFormReturnItem, resolveRawData } from '../utils';
import {
formWebhook,
prepareFormData,
prepareFormReturnItem,
resolveRawData,
isFormConnected,
} from '../utils';

describe('FormTrigger, formWebhook', () => {
beforeEach(() => {
Expand Down Expand Up @@ -721,3 +728,36 @@ describe('resolveRawData', () => {
);
});
});

describe('FormTrigger, isFormConnected', () => {
it('should return false if Wait node is connected but resume parameter is not form', async () => {
const result = isFormConnected([
mock<NodeTypeAndVersion>({
type: 'n8n-nodes-base.wait',
parameters: {
resume: 'timeInterval',
},
}),
]);
expect(result).toBe(false);
});
it('should return true if Wait node is connected and resume parameter is form', async () => {
const result = isFormConnected([
mock<NodeTypeAndVersion>({
type: 'n8n-nodes-base.wait',
parameters: {
resume: 'form',
},
}),
]);
expect(result).toBe(true);
});
it('should return true if Form node is connected', async () => {
const result = isFormConnected([
mock<NodeTypeAndVersion>({
type: 'n8n-nodes-base.form',
}),
]);
expect(result).toBe(true);
});
});
15 changes: 11 additions & 4 deletions packages/nodes-base/nodes/Form/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,13 @@ export function renderForm({
res.render('form-trigger', data);
}

export const isFormConnected = (nodes: NodeTypeAndVersion[]) => {
return nodes.some(
(n) =>
n.type === FORM_NODE_TYPE || (n.type === WAIT_NODE_TYPE && n.parameters?.resume === 'form'),
);
};

export async function formWebhook(
context: IWebhookFunctions,
authProperty = FORM_TRIGGER_AUTHENTICATION_PROPERTY,
Expand Down Expand Up @@ -403,10 +410,10 @@ export async function formWebhook(
}

if (!redirectUrl && node.type !== FORM_TRIGGER_NODE_TYPE) {
const connectedNodes = context.getChildNodes(context.getNode().name);
const hasNextPage = connectedNodes.some(
(n) => n.type === FORM_NODE_TYPE || n.type === WAIT_NODE_TYPE,
);
const connectedNodes = context.getChildNodes(context.getNode().name, {
includeNodeParameters: true,
});
const hasNextPage = isFormConnected(connectedNodes);

if (hasNextPage) {
redirectUrl = context.evaluateExpression('{{ $execution.resumeFormUrl }}') as string;
Expand Down
6 changes: 5 additions & 1 deletion packages/workflow/src/Interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -852,6 +852,7 @@ export type NodeTypeAndVersion = {
type: string;
typeVersion: number;
disabled: boolean;
parameters?: INodeParameters;
};

export interface FunctionsBase {
Expand All @@ -869,7 +870,10 @@ export interface FunctionsBase {
getRestApiUrl(): string;
getInstanceBaseUrl(): string;
getInstanceId(): string;
getChildNodes(nodeName: string): NodeTypeAndVersion[];
getChildNodes(
nodeName: string,
options?: { includeNodeParameters?: boolean },
): NodeTypeAndVersion[];
getParentNodes(nodeName: string): NodeTypeAndVersion[];
getKnownNodeTypes(): IDataObject;
getMode?: () => WorkflowExecuteMode;
Expand Down

0 comments on commit 652b8d1

Please sign in to comment.