diff --git a/packages/core/src/execution-engine/node-execution-context/node-execution-context.ts b/packages/core/src/execution-engine/node-execution-context/node-execution-context.ts index f5f3730244e19..79225554d6c85 100644 --- a/packages/core/src/execution-engine/node-execution-context/node-execution-context.ts +++ b/packages/core/src/execution-engine/node-execution-context/node-execution-context.ts @@ -79,18 +79,24 @@ export abstract class NodeExecutionContext implements Omit { beforeEach(() => { @@ -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({ + 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({ + 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({ + type: 'n8n-nodes-base.form', + }), + ]); + expect(result).toBe(true); + }); +}); diff --git a/packages/nodes-base/nodes/Form/utils.ts b/packages/nodes-base/nodes/Form/utils.ts index 87dda98f8862d..6fc414f622072 100644 --- a/packages/nodes-base/nodes/Form/utils.ts +++ b/packages/nodes-base/nodes/Form/utils.ts @@ -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, @@ -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; diff --git a/packages/workflow/src/Interfaces.ts b/packages/workflow/src/Interfaces.ts index 2161569b7d35e..10fc8e9b11897 100644 --- a/packages/workflow/src/Interfaces.ts +++ b/packages/workflow/src/Interfaces.ts @@ -852,6 +852,7 @@ export type NodeTypeAndVersion = { type: string; typeVersion: number; disabled: boolean; + parameters?: INodeParameters; }; export interface FunctionsBase { @@ -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;