chore: Replace repeated response-mode child scans with one predicate (#39076)

Co-authored-by: n8n-cat-bot[bot] <n8n-cat-bot[bot]@users.noreply.github.com>
This commit is contained in:
n8n-cat-bot[bot] 2026-09-28 07:18:38 +00:00 committed by GitHub
parent ee9dfd1a37
commit 7ed93eadae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 29 additions and 32 deletions

View File

@ -146,6 +146,23 @@ describe('autoDetectResponseMode', () => {
expect(result).toBe('responseNode');
});
test('should return responseNode when a matching child follows a non-matching child', () => {
const workflowStartNode = mock<INode>({
type: FORM_NODE_TYPE,
name: 'startNode',
parameters: {},
});
workflow.getChildNodes.mockReturnValue(['disabledChild', 'enabledChild']);
workflow.nodes.disabledChild = mock<INode>({ type: WAIT_NODE_TYPE, disabled: true });
workflow.nodes.enabledChild = mock<INode>({
type: WAIT_NODE_TYPE,
parameters: { resume: 'form' },
disabled: false,
});
const result = autoDetectResponseMode(workflowStartNode, workflow, 'POST');
expect(result).toBe('responseNode');
});
test('should return formPage when start node is FORM_NODE_TYPE and method is POST and there is a following FORM_NODE_TYPE node', () => {
const workflowStartNode = mock<INode>({
type: FORM_NODE_TYPE,

View File

@ -330,17 +330,13 @@ export function autoDetectResponseMode(
workflow: Workflow,
method: string,
): WebhookResponseMode | undefined {
if (workflowStartNode.type === FORM_TRIGGER_NODE_TYPE && method === 'POST') {
const connectedNodes = workflow.getChildNodes(workflowStartNode.name);
const hasChildMatching = (predicate: (node: INode) => boolean) =>
workflow
.getChildNodes(workflowStartNode.name)
.some((nodeName) => predicate(workflow.nodes[nodeName]));
for (const nodeName of connectedNodes) {
const node = workflow.nodes[nodeName];
if (isEnabledFormPageNode(node)) {
return 'formPage';
}
}
}
const isFormTriggerPost = workflowStartNode.type === FORM_TRIGGER_NODE_TYPE && method === 'POST';
if (isFormTriggerPost && hasChildMatching(isEnabledFormPageNode)) return 'formPage';
const chatResponseMode = getChatResponseMode(workflowStartNode, method);
if (chatResponseMode) return chatResponseMode;
@ -348,17 +344,9 @@ export function autoDetectResponseMode(
// If there are form nodes connected to a current form node we're dealing with a multipage form
// and we need to return the formPage response mode when a second page of the form gets submitted
// to be able to show potential form errors correctly.
if (workflowStartNode.type === FORM_NODE_TYPE && method === 'POST') {
const connectedNodes = workflow.getChildNodes(workflowStartNode.name);
for (const nodeName of connectedNodes) {
const node = workflow.nodes[nodeName];
if (node.type === FORM_NODE_TYPE && !node.disabled) {
return 'formPage';
}
}
}
const isFormPost = workflowStartNode.type === FORM_NODE_TYPE && method === 'POST';
if (isFormPost && hasChildMatching((node) => node.type === FORM_NODE_TYPE && !node.disabled))
return 'formPage';
if (workflowStartNode.type === WAIT_NODE_TYPE && workflowStartNode.parameters.resume !== 'form') {
return undefined;
@ -370,17 +358,9 @@ export function autoDetectResponseMode(
) {
return 'onReceived';
}
if ([FORM_NODE_TYPE, WAIT_NODE_TYPE].includes(workflowStartNode.type) && method === 'POST') {
const connectedNodes = workflow.getChildNodes(workflowStartNode.name);
for (const nodeName of connectedNodes) {
const node = workflow.nodes[nodeName];
if (isEnabledFormPageNode(node)) {
return 'responseNode';
}
}
}
const isFormOrWaitPost =
[FORM_NODE_TYPE, WAIT_NODE_TYPE].includes(workflowStartNode.type) && method === 'POST';
if (isFormOrWaitPost && hasChildMatching(isEnabledFormPageNode)) return 'responseNode';
return undefined;
}