mirror of
https://github.com/n8n-io/n8n.git
synced 2026-05-27 23:07:12 +02:00
331 lines
11 KiB
TypeScript
331 lines
11 KiB
TypeScript
import type { IWorkflowBase } from 'n8n-workflow';
|
|
|
|
import { test, expect } from '../../../fixtures/base';
|
|
|
|
test.describe(
|
|
'Form Trigger',
|
|
{
|
|
annotation: [{ type: 'owner', description: 'NODES' }],
|
|
},
|
|
() => {
|
|
test.beforeEach(async ({ n8n }) => {
|
|
await n8n.start.fromBlankCanvas();
|
|
});
|
|
|
|
test("add node by clicking on 'On form submission'", async ({ n8n }) => {
|
|
await n8n.canvas.clickNodeCreatorPlusButton();
|
|
await n8n.canvas.nodeCreatorItemByName('On form submission').click();
|
|
|
|
await n8n.ndv.fillParameterInput('Form Title', 'Test Form');
|
|
await n8n.ndv.fillParameterInput('Form Description', 'Test Form Description');
|
|
await n8n.ndv.clickBackToCanvasButton();
|
|
|
|
await expect(n8n.canvas.nodeByName('On form submission')).toBeVisible();
|
|
await expect(n8n.canvas.nodeIssuesBadge('On form submission')).toBeHidden();
|
|
});
|
|
|
|
test('should fill up form fields', async ({ n8n }) => {
|
|
await n8n.canvas.clickNodeCreatorPlusButton();
|
|
await n8n.canvas.nodeCreatorItemByName('On form submission').click();
|
|
|
|
await n8n.ndv.fillParameterInput('Form Title', 'Test Form');
|
|
await n8n.ndv.fillParameterInput('Form Description', 'Test Form Description');
|
|
|
|
// Add first field - Number type with required flag
|
|
await n8n.ndv.addFixedCollectionItem();
|
|
await n8n.ndv.fillParameterInputByName('fieldLabel', 'Test Field 1');
|
|
await n8n.ndv.selectOptionInParameterDropdown('fieldType', 'Number');
|
|
await n8n.ndv.addFixedCollectionProperty('Custom Field Name', 0);
|
|
await n8n.ndv.fillParameterInputByName('fieldName', 'testField1');
|
|
await n8n.ndv.addFixedCollectionProperty('Required Field', 0);
|
|
await n8n.ndv.setParameterSwitch('requiredField', true);
|
|
|
|
// Add second field - Text type
|
|
await n8n.ndv.addFixedCollectionItem();
|
|
await n8n.ndv.fillParameterInputByName('fieldLabel', 'Test Field 2', 1);
|
|
await n8n.ndv.addFixedCollectionProperty('Custom Field Name', 1);
|
|
await n8n.ndv.fillParameterInputByName('fieldName', 'testField2', 1);
|
|
|
|
// Add third field - Date type
|
|
await n8n.ndv.addFixedCollectionItem();
|
|
await n8n.ndv.fillParameterInputByName('fieldLabel', 'Test Field 3', 2);
|
|
await n8n.ndv.selectOptionInParameterDropdown('fieldType', 'Date', 2);
|
|
await n8n.ndv.addFixedCollectionProperty('Custom Field Name', 2);
|
|
await n8n.ndv.fillParameterInputByName('fieldName', 'testField3', 2);
|
|
|
|
// Add fourth field - Dropdown type with options
|
|
await n8n.ndv.addFixedCollectionItem();
|
|
await n8n.ndv.fillParameterInputByName('fieldLabel', 'Test Field 4', 3);
|
|
await n8n.ndv.selectOptionInParameterDropdown('fieldType', 'Dropdown', 3);
|
|
await n8n.ndv.addFixedCollectionProperty('Custom Field Name', 3);
|
|
await n8n.ndv.fillParameterInputByName('fieldName', 'testField4', 3);
|
|
|
|
// Configure dropdown field options
|
|
await n8n.page.getByRole('button', { name: 'Add Field Option' }).click();
|
|
await n8n.ndv.fillParameterInputByName('option', 'Option 1');
|
|
await n8n.ndv.fillParameterInputByName('option', 'Option 2', 1);
|
|
|
|
// Add optional submitted message
|
|
await n8n.ndv.addParameterOptionByName('Form Response');
|
|
await n8n.ndv.fillParameterInput('Text to Show', 'Your test form was successfully submitted');
|
|
|
|
await n8n.ndv.clickBackToCanvasButton();
|
|
await expect(n8n.canvas.nodeByName('On form submission')).toBeVisible();
|
|
await expect(n8n.canvas.nodeIssuesBadge('On form submission')).toBeHidden();
|
|
});
|
|
|
|
test('should create and submit a multi-page form', async ({ n8n }) => {
|
|
// Add Form Trigger node with first name field
|
|
await n8n.canvas.clickNodeCreatorPlusButton();
|
|
await n8n.canvas.nodeCreatorItemByName('On form submission').click();
|
|
|
|
await n8n.ndv.fillParameterInput('Form Title', 'Multi-Page Form');
|
|
await n8n.ndv.fillParameterInput('Form Description', 'A form with multiple pages');
|
|
|
|
// Add a single field to the Form Trigger node
|
|
await n8n.ndv.addFixedCollectionItem();
|
|
await n8n.ndv.fillParameterInputByName('fieldLabel', 'What is your first name?');
|
|
|
|
await n8n.ndv.clickBackToCanvasButton();
|
|
|
|
// Add Form node (next page) by selecting the "Next Form Page" action
|
|
await n8n.canvas.addNode('n8n Form', { closeNDV: false, action: 'Next Form Page' });
|
|
|
|
// Add a single field to the Form node
|
|
await n8n.ndv.addFixedCollectionItem();
|
|
await n8n.ndv.fillParameterInputByName('fieldLabel', 'What is your last name?');
|
|
|
|
await n8n.ndv.clickBackToCanvasButton();
|
|
|
|
// Start the workflow execution so it's waiting for form submissions
|
|
// This allows the multi-page form flow to work (continuing to Form node after trigger)
|
|
await n8n.canvas.clickExecuteWorkflowButton();
|
|
await expect(n8n.canvas.getExecuteWorkflowButton()).toHaveText('Waiting for trigger event');
|
|
|
|
// Get the form test URL from the NDV
|
|
await n8n.canvas.openNode('On form submission');
|
|
const formUrlLocator = n8n.page.locator('text=/form-test\\/[a-f0-9-]+/');
|
|
const formUrl = await formUrlLocator.textContent();
|
|
|
|
// Open form URL in a new browser tab
|
|
const formPage = await n8n.page.context().newPage();
|
|
await formPage.goto(formUrl!);
|
|
|
|
// Fill first page with a random first name
|
|
const firstName = `John${Date.now()}`;
|
|
await formPage.getByLabel('What is your first name?').fill(firstName);
|
|
await formPage.getByRole('button', { name: 'Submit' }).click();
|
|
|
|
// Fill second page with a random last name
|
|
const lastName = `Doe${Date.now()}`;
|
|
await formPage.getByLabel('What is your last name?').fill(lastName);
|
|
await formPage.getByRole('button', { name: 'Submit' }).click();
|
|
|
|
// Verify the form was submitted successfully
|
|
await expect(formPage.getByText('Your response has been recorded')).toBeVisible();
|
|
|
|
// Close the form page
|
|
await formPage.close();
|
|
});
|
|
|
|
test.describe('form execution with basic auth', () => {
|
|
const password = new Date().toDateString();
|
|
|
|
test.use({
|
|
httpCredentials: {
|
|
username: 'test',
|
|
password,
|
|
},
|
|
});
|
|
|
|
test('form submission works with basic auth', async ({ api, n8n }) => {
|
|
const { id, name } = await api.credentials.createCredential({
|
|
name: 'Basic Auth test:test',
|
|
type: 'httpBasicAuth',
|
|
data: {
|
|
user: 'test',
|
|
password,
|
|
},
|
|
});
|
|
|
|
const workflow: Partial<IWorkflowBase> = {
|
|
nodes: [
|
|
{
|
|
parameters: {
|
|
authentication: 'basicAuth',
|
|
formTitle: 'Test',
|
|
options: {
|
|
respondWithOptions: {
|
|
values: {
|
|
formSubmittedText: 'This worked',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
type: 'n8n-nodes-base.formTrigger',
|
|
typeVersion: 2.5,
|
|
position: [0, 0],
|
|
id: '49b31a69-3fc9-43d0-944e-990783330e7a',
|
|
name: 'On form submission',
|
|
webhookId: '17eae80c-039e-4779-be68-08cd5afc5f65',
|
|
credentials: {
|
|
httpBasicAuth: {
|
|
id,
|
|
name,
|
|
},
|
|
},
|
|
},
|
|
],
|
|
connections: {},
|
|
pinData: {},
|
|
meta: {
|
|
instanceId: 'acd7615bcc3af421bbd7517e305cc16505176a6a47045dbe39e25d904c940573',
|
|
},
|
|
};
|
|
|
|
const { workflowId } = await api.workflows.createWorkflowFromDefinition(workflow, {
|
|
makeUnique: true,
|
|
});
|
|
|
|
await n8n.page.goto(`/workflow/${workflowId}`);
|
|
|
|
// Start the workflow execution so it's waiting for form submissions
|
|
await n8n.canvas.clickExecuteWorkflowButton();
|
|
await expect(n8n.canvas.getExecuteWorkflowButton()).toHaveText('Waiting for trigger event');
|
|
|
|
// Get the form test URL from the NDV
|
|
await n8n.canvas.openNode('On form submission');
|
|
const formUrlLocator = n8n.page.locator('text=/form-test\\/[a-f0-9-]+/');
|
|
const formUrl = await formUrlLocator.textContent();
|
|
|
|
// Open form URL in a new browser tab
|
|
|
|
const formPage = await n8n.page.context().newPage();
|
|
await formPage.goto(formUrl!);
|
|
|
|
// Submit the form
|
|
await formPage.getByRole('button', { name: 'Submit' }).click();
|
|
await expect(formPage.getByText('This worked')).toBeVisible();
|
|
});
|
|
|
|
test('multi-step form submission works with basic auth', async ({ api, n8n }) => {
|
|
const { id, name } = await api.credentials.createCredential({
|
|
name: 'Basic Auth test:test',
|
|
type: 'httpBasicAuth',
|
|
data: {
|
|
user: 'test',
|
|
password,
|
|
},
|
|
});
|
|
|
|
const workflow: Partial<IWorkflowBase> = {
|
|
nodes: [
|
|
{
|
|
parameters: {
|
|
authentication: 'basicAuth',
|
|
formTitle: 'Test',
|
|
},
|
|
type: 'n8n-nodes-base.formTrigger',
|
|
typeVersion: 2.5,
|
|
position: [0, 0],
|
|
id: '49b31a69-3fc9-43d0-944e-990783330e7a',
|
|
name: 'On form submission',
|
|
webhookId: '17eae80c-039e-4779-be68-08cd5afc5f64',
|
|
credentials: {
|
|
httpBasicAuth: {
|
|
id,
|
|
name,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
parameters: {
|
|
options: {
|
|
formDescription: 'Step 2',
|
|
},
|
|
},
|
|
type: 'n8n-nodes-base.form',
|
|
typeVersion: 2.5,
|
|
position: [208, 0],
|
|
id: 'e748b959-faeb-4476-aa30-1c7a6434843a',
|
|
name: 'Form',
|
|
webhookId: '1e1a6d32-d3a4-4150-886b-2119cc4072bc',
|
|
},
|
|
{
|
|
parameters: {
|
|
operation: 'completion',
|
|
completionTitle: 'Success',
|
|
completionMessage: 'This worked',
|
|
options: {},
|
|
},
|
|
type: 'n8n-nodes-base.form',
|
|
typeVersion: 2.5,
|
|
position: [416, 0],
|
|
id: '2e52c834-e08a-4848-bd86-be1f7909a956',
|
|
name: 'Form1',
|
|
webhookId: '1839391a-f07d-4bee-858f-678c1b45252b',
|
|
},
|
|
],
|
|
connections: {
|
|
'On form submission': {
|
|
main: [
|
|
[
|
|
{
|
|
node: 'Form',
|
|
type: 'main',
|
|
index: 0,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
Form: {
|
|
main: [
|
|
[
|
|
{
|
|
node: 'Form1',
|
|
type: 'main',
|
|
index: 0,
|
|
},
|
|
],
|
|
],
|
|
},
|
|
},
|
|
pinData: {},
|
|
meta: {
|
|
templateCredsSetupCompleted: true,
|
|
instanceId: 'acd7615bcc3af421bbd7517e305cc16505176a6a47045dbe39e25d904c940573',
|
|
},
|
|
};
|
|
|
|
const { workflowId } = await api.workflows.createWorkflowFromDefinition(workflow, {
|
|
makeUnique: true,
|
|
});
|
|
|
|
await n8n.page.goto(`/workflow/${workflowId}`);
|
|
|
|
// Start the workflow execution so it's waiting for form submissions
|
|
await n8n.canvas.clickExecuteWorkflowButton();
|
|
await expect(n8n.canvas.getExecuteWorkflowButton()).toHaveText('Waiting for trigger event');
|
|
|
|
// Get the form test URL from the NDV
|
|
await n8n.canvas.openNode('On form submission');
|
|
const formUrlLocator = n8n.page.locator('text=/form-test\\/[a-f0-9-]+/');
|
|
const formUrl = await formUrlLocator.textContent();
|
|
|
|
// Open form URL in a new browser tab
|
|
|
|
const formPage = await n8n.page.context().newPage();
|
|
await formPage.goto(formUrl!);
|
|
|
|
// Submit first page
|
|
await formPage.getByRole('button', { name: 'Submit' }).click();
|
|
await expect(formPage.getByText('Step 2')).toBeVisible();
|
|
|
|
// submit second page
|
|
await formPage.getByRole('button', { name: 'Submit' }).click();
|
|
await expect(formPage.getByText('This worked')).toBeVisible();
|
|
});
|
|
});
|
|
},
|
|
);
|