mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-21 11:49:59 +00:00
feat(n8n Form Trigger Node): Form Improvements (#12590)
This commit is contained in:
@@ -10,19 +10,58 @@ import type {
|
||||
|
||||
import {
|
||||
formWebhook,
|
||||
createDescriptionMetadata,
|
||||
prepareFormData,
|
||||
prepareFormReturnItem,
|
||||
resolveRawData,
|
||||
isFormConnected,
|
||||
} from '../utils';
|
||||
|
||||
describe('FormTrigger, parseFormDescription', () => {
|
||||
it('should remove HTML tags and truncate to 150 characters', () => {
|
||||
const descriptions = [
|
||||
{ description: '<p>This is a test description</p>', expected: 'This is a test description' },
|
||||
{ description: 'Test description', expected: 'Test description' },
|
||||
{
|
||||
description:
|
||||
'Beneath the golden hues of a setting sun, waves crashed against the rugged shore, carrying whispers of ancient tales etched in natures timeless and soothing song.',
|
||||
expected:
|
||||
'Beneath the golden hues of a setting sun, waves crashed against the rugged shore, carrying whispers of ancient tales etched in natures timeless and so',
|
||||
},
|
||||
{
|
||||
description:
|
||||
'<p>Beneath the golden hues of a setting sun, waves crashed against the rugged shore, carrying whispers of ancient tales etched in natures timeless and soothing song.</p>',
|
||||
expected:
|
||||
'Beneath the golden hues of a setting sun, waves crashed against the rugged shore, carrying whispers of ancient tales etched in natures timeless and so',
|
||||
},
|
||||
];
|
||||
|
||||
descriptions.forEach(({ description, expected }) => {
|
||||
expect(createDescriptionMetadata(description)).toBe(expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('FormTrigger, formWebhook', () => {
|
||||
const executeFunctions = mock<IWebhookFunctions>();
|
||||
executeFunctions.getNode.mockReturnValue({ typeVersion: 2.1 } as any);
|
||||
executeFunctions.getNodeParameter.calledWith('options').mockReturnValue({});
|
||||
executeFunctions.getNodeParameter.calledWith('formTitle').mockReturnValue('Test Form');
|
||||
executeFunctions.getNodeParameter
|
||||
.calledWith('formDescription')
|
||||
.mockReturnValue('Test Description');
|
||||
executeFunctions.getNodeParameter.calledWith('responseMode').mockReturnValue('onReceived');
|
||||
executeFunctions.getRequestObject.mockReturnValue({ method: 'GET', query: {} } as any);
|
||||
executeFunctions.getMode.mockReturnValue('manual');
|
||||
executeFunctions.getInstanceId.mockReturnValue('instanceId');
|
||||
executeFunctions.getBodyData.mockReturnValue({ data: {}, files: {} });
|
||||
executeFunctions.getChildNodes.mockReturnValue([]);
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should call response render', async () => {
|
||||
const executeFunctions = mock<IWebhookFunctions>();
|
||||
const mockRender = jest.fn();
|
||||
|
||||
const formFields: FormFieldsParameter = [
|
||||
@@ -43,20 +82,8 @@ describe('FormTrigger, formWebhook', () => {
|
||||
},
|
||||
];
|
||||
|
||||
executeFunctions.getNode.mockReturnValue({ typeVersion: 2.1 } as any);
|
||||
executeFunctions.getNodeParameter.calledWith('options').mockReturnValue({});
|
||||
executeFunctions.getNodeParameter.calledWith('formTitle').mockReturnValue('Test Form');
|
||||
executeFunctions.getNodeParameter
|
||||
.calledWith('formDescription')
|
||||
.mockReturnValue('Test Description');
|
||||
executeFunctions.getNodeParameter.calledWith('responseMode').mockReturnValue('onReceived');
|
||||
executeFunctions.getNodeParameter.calledWith('formFields.values').mockReturnValue(formFields);
|
||||
executeFunctions.getResponseObject.mockReturnValue({ render: mockRender } as any);
|
||||
executeFunctions.getRequestObject.mockReturnValue({ method: 'GET', query: {} } as any);
|
||||
executeFunctions.getMode.mockReturnValue('manual');
|
||||
executeFunctions.getInstanceId.mockReturnValue('instanceId');
|
||||
executeFunctions.getBodyData.mockReturnValue({ data: {}, files: {} });
|
||||
executeFunctions.getChildNodes.mockReturnValue([]);
|
||||
|
||||
await formWebhook(executeFunctions);
|
||||
|
||||
@@ -64,6 +91,7 @@ describe('FormTrigger, formWebhook', () => {
|
||||
appendAttribution: true,
|
||||
buttonLabel: 'Submit',
|
||||
formDescription: 'Test Description',
|
||||
formDescriptionMetadata: 'Test Description',
|
||||
formFields: [
|
||||
{
|
||||
defaultValue: '',
|
||||
@@ -117,8 +145,55 @@ describe('FormTrigger, formWebhook', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should sanitize form descriptions', async () => {
|
||||
const mockRender = jest.fn();
|
||||
|
||||
const formDescription = [
|
||||
{ description: 'Test Description', expected: 'Test Description' },
|
||||
{ description: '<i>hello</i>', expected: '<i>hello</i>' },
|
||||
{ description: '<script>alert("hello world")</script>', expected: '' },
|
||||
];
|
||||
const formFields: FormFieldsParameter = [
|
||||
{ fieldLabel: 'Name', fieldType: 'text', requiredField: true },
|
||||
];
|
||||
|
||||
executeFunctions.getNodeParameter.calledWith('formFields.values').mockReturnValue(formFields);
|
||||
executeFunctions.getResponseObject.mockReturnValue({ render: mockRender } as any);
|
||||
|
||||
for (const { description, expected } of formDescription) {
|
||||
executeFunctions.getNodeParameter.calledWith('formDescription').mockReturnValue(description);
|
||||
|
||||
await formWebhook(executeFunctions);
|
||||
|
||||
expect(mockRender).toHaveBeenCalledWith('form-trigger', {
|
||||
appendAttribution: true,
|
||||
buttonLabel: 'Submit',
|
||||
formDescription: expected,
|
||||
formDescriptionMetadata: createDescriptionMetadata(expected),
|
||||
formFields: [
|
||||
{
|
||||
defaultValue: '',
|
||||
errorId: 'error-field-0',
|
||||
id: 'field-0',
|
||||
inputRequired: 'form-required',
|
||||
isInput: true,
|
||||
label: 'Name',
|
||||
placeholder: undefined,
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
formSubmittedText: 'Your response has been recorded',
|
||||
formTitle: 'Test Form',
|
||||
n8nWebsiteLink:
|
||||
'https://n8n.io/?utm_source=n8n-internal&utm_medium=form-trigger&utm_campaign=instanceId',
|
||||
testRun: true,
|
||||
useResponseData: false,
|
||||
validForm: true,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it('should return workflowData on POST request', async () => {
|
||||
const executeFunctions = mock<IWebhookFunctions>();
|
||||
const mockStatus = jest.fn();
|
||||
const mockEnd = jest.fn();
|
||||
|
||||
@@ -132,15 +207,9 @@ describe('FormTrigger, formWebhook', () => {
|
||||
'field-1': '30',
|
||||
};
|
||||
|
||||
executeFunctions.getNode.mockReturnValue({ typeVersion: 2.1 } as any);
|
||||
executeFunctions.getNodeParameter.calledWith('options').mockReturnValue({});
|
||||
executeFunctions.getNodeParameter.calledWith('responseMode').mockReturnValue('onReceived');
|
||||
executeFunctions.getChildNodes.mockReturnValue([]);
|
||||
executeFunctions.getNodeParameter.calledWith('formFields.values').mockReturnValue(formFields);
|
||||
executeFunctions.getResponseObject.mockReturnValue({ status: mockStatus, end: mockEnd } as any);
|
||||
executeFunctions.getRequestObject.mockReturnValue({ method: 'POST' } as any);
|
||||
executeFunctions.getMode.mockReturnValue('manual');
|
||||
executeFunctions.getInstanceId.mockReturnValue('instanceId');
|
||||
executeFunctions.getBodyData.mockReturnValue({ data: bodyData, files: {} });
|
||||
|
||||
const result = await formWebhook(executeFunctions);
|
||||
@@ -213,6 +282,7 @@ describe('FormTrigger, prepareFormData', () => {
|
||||
validForm: true,
|
||||
formTitle: 'Test Form',
|
||||
formDescription: 'This is a test form',
|
||||
formDescriptionMetadata: 'This is a test form',
|
||||
formSubmittedText: 'Thank you for your submission',
|
||||
n8nWebsiteLink:
|
||||
'https://n8n.io/?utm_source=n8n-internal&utm_medium=form-trigger&utm_campaign=test-instance',
|
||||
@@ -292,6 +362,7 @@ describe('FormTrigger, prepareFormData', () => {
|
||||
validForm: true,
|
||||
formTitle: 'Test Form',
|
||||
formDescription: 'This is a test form',
|
||||
formDescriptionMetadata: 'This is a test form',
|
||||
formSubmittedText: 'Your response has been recorded',
|
||||
n8nWebsiteLink: 'https://n8n.io/?utm_source=n8n-internal&utm_medium=form-trigger',
|
||||
formFields: [
|
||||
|
||||
Reference in New Issue
Block a user