Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/n8n-io/n8n into node-2485-…
Browse files Browse the repository at this point in the history
…google-chat-send-and-wait
  • Loading branch information
michael-radency committed Mar 11, 2025
2 parents 6bbce46 + de23ae5 commit 286883e
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 38 deletions.
4 changes: 2 additions & 2 deletions packages/cli/src/scaling/__tests__/scaling.service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ describe('ScalingService', () => {
});

describe('if worker', () => {
it('should wait for running jobs to finish', async () => {
it('should pause queue and wait for running jobs to finish', async () => {
// @ts-expect-error readonly property
instanceSettings.instanceType = 'worker';
await scalingService.setupQueue();
Expand All @@ -211,7 +211,7 @@ describe('ScalingService', () => {
await scalingService.stop();

expect(getRunningJobsCountSpy).toHaveBeenCalled();
expect(queue.pause).not.toHaveBeenCalled();
expect(queue.pause).toHaveBeenCalled();
expect(stopQueueRecoverySpy).not.toHaveBeenCalled();
});
});
Expand Down
12 changes: 8 additions & 4 deletions packages/cli/src/scaling/scaling.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,17 +139,21 @@ export class ScalingService {
else if (instanceType === 'worker') await this.stopWorker();
}

private async pauseQueue() {
await this.queue.pause(true, true); // no more jobs will be enqueued or picked up
this.logger.debug('Paused queue');
}

private async stopMain() {
if (this.instanceSettings.isSingleMain) {
await this.queue.pause(true, true); // no more jobs will be picked up
this.logger.debug('Queue paused');
}
if (this.instanceSettings.isSingleMain) await this.pauseQueue();

if (this.queueRecoveryContext.timeout) this.stopQueueRecovery();
if (this.isQueueMetricsEnabled) this.stopQueueMetrics();
}

private async stopWorker() {
await this.pauseQueue();

let count = 0;

while (this.getRunningJobsCount() !== 0) {
Expand Down
10 changes: 1 addition & 9 deletions packages/nodes-base/nodes/Form/Form.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -336,15 +336,7 @@ export class Form extends Node {
});
}
} else {
fields = (context.getNodeParameter('formFields.values', []) as FormFieldsParameter).map(
(field) => {
if (field.fieldType === 'hiddenField') {
field.fieldLabel = field.fieldName as string;
}

return field;
},
);
fields = context.getNodeParameter('formFields.values', []) as FormFieldsParameter;
}

const method = context.getRequestObject().method;
Expand Down
8 changes: 1 addition & 7 deletions packages/nodes-base/nodes/Form/formNodeUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
type IWebhookResponseData,
} from 'n8n-workflow';

import { renderForm, sanitizeHtml } from './utils';
import { renderForm } from './utils';

export const renderFormNode = async (
context: IWebhookFunctions,
Expand Down Expand Up @@ -42,12 +42,6 @@ export const renderFormNode = async (
) as string) || 'Submit';
}

for (const field of fields) {
if (field.fieldType === 'html') {
field.html = sanitizeHtml(field.html as string);
}
}

const appendAttribution = context.evaluateExpression(
`{{ $('${trigger?.name}').params.options?.appendAttribution === false ? false : true }}`,
) as boolean;
Expand Down
20 changes: 15 additions & 5 deletions packages/nodes-base/nodes/Form/test/formNodeUtils.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { type Response } from 'express';
import type { MockProxy } from 'jest-mock-extended';
import { mock } from 'jest-mock-extended';
import {
type FormFieldsParameter,
Expand All @@ -9,10 +10,19 @@ import {
import { renderFormNode } from '../formNodeUtils';

describe('formNodeUtils', () => {
let webhookFunctions: MockProxy<IWebhookFunctions>;

beforeEach(() => {
webhookFunctions = mock<IWebhookFunctions>();
});

afterEach(() => {
jest.clearAllMocks();
});

it('should sanitize custom html', async () => {
const executeFunctions = mock<IWebhookFunctions>();
executeFunctions.getNode.mockReturnValue({ typeVersion: 2.1 } as any);
executeFunctions.getNodeParameter.calledWith('options').mockReturnValue({
webhookFunctions.getNode.mockReturnValue({ typeVersion: 2.1 } as any);
webhookFunctions.getNodeParameter.calledWith('options').mockReturnValue({
formTitle: 'Test Title',
formDescription: 'Test Description',
buttonLabel: 'Test Button Label',
Expand Down Expand Up @@ -47,12 +57,12 @@ describe('formNodeUtils', () => {
},
];

executeFunctions.getNodeParameter.calledWith('formFields.values').mockReturnValue(formFields);
webhookFunctions.getNodeParameter.calledWith('formFields.values').mockReturnValue(formFields);

const responseMock = mock<Response>({ render: mockRender } as any);
const triggerMock = mock<NodeTypeAndVersion>({ name: 'triggerName' } as any);

await renderFormNode(executeFunctions, responseMock, triggerMock, formFields, 'test');
await renderFormNode(webhookFunctions, responseMock, triggerMock, formFields, 'test');

expect(mockRender).toHaveBeenCalledWith('form-trigger', {
appendAttribution: true,
Expand Down
37 changes: 37 additions & 0 deletions packages/nodes-base/nodes/Form/test/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
isFormConnected,
sanitizeHtml,
validateResponseModeConfiguration,
prepareFormFields,
} from '../utils';

describe('FormTrigger, parseFormDescription', () => {
Expand Down Expand Up @@ -994,4 +995,40 @@ describe('validateResponseModeConfiguration', () => {

expect(() => validateResponseModeConfiguration(webhookFunctions)).not.toThrow();
});

describe('prepareFormFields', () => {
it('should resolve expressions in html fields', async () => {
webhookFunctions.evaluateExpression.mockImplementation((expression) => {
if (expression === '{{ $json.formMode }}') {
return 'Title';
}
});

const result = prepareFormFields(webhookFunctions, [
{
fieldLabel: 'Custom HTML',
fieldType: 'html',
elementName: 'test',
html: '<h1>{{ $json.formMode }}</h1>',
},
]);

expect(result[0].html).toBe('<h1>Title</h1>');
});
it('should prepare hiddenField', async () => {
const result = prepareFormFields(webhookFunctions, [
{
fieldLabel: '',
fieldName: 'test',
fieldType: 'hiddenField',
},
]);

expect(result[0]).toEqual({
fieldLabel: 'test',
fieldName: 'test',
fieldType: 'hiddenField',
});
});
});
});
37 changes: 26 additions & 11 deletions packages/nodes-base/nodes/Form/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,28 @@ export function sanitizeHtml(text: string) {
});
}

export const prepareFormFields = (context: IWebhookFunctions, fields: FormFieldsParameter) => {
return fields.map((field) => {
if (field.fieldType === 'html') {
let { html } = field;

if (!html) return field;

for (const resolvable of getResolvables(html)) {
html = html.replace(resolvable, context.evaluateExpression(resolvable) as string);
}

field.html = sanitizeHtml(html as string);
}

if (field.fieldType === 'hiddenField') {
field.fieldLabel = field.fieldName as string;
}

return field;
});
};

export function sanitizeCustomCss(css: string | undefined): string | undefined {
if (!css) return undefined;

Expand Down Expand Up @@ -411,6 +433,8 @@ export function renderForm({
} catch (error) {}
}

formFields = prepareFormFields(context, formFields);

const data = prepareFormData({
formTitle,
formDescription,
Expand Down Expand Up @@ -476,17 +500,8 @@ export async function formWebhook(
}

const mode = context.getMode() === 'manual' ? 'test' : 'production';
const formFields = (context.getNodeParameter('formFields.values', []) as FormFieldsParameter).map(
(field) => {
if (field.fieldType === 'html') {
field.html = sanitizeHtml(field.html as string);
}
if (field.fieldType === 'hiddenField') {
field.fieldLabel = field.fieldName as string;
}
return field;
},
);
const formFields = context.getNodeParameter('formFields.values', []) as FormFieldsParameter;

const method = context.getRequestObject().method;

validateResponseModeConfiguration(context);
Expand Down

0 comments on commit 286883e

Please sign in to comment.