mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-16 17:46:45 +00:00
test: Migrate form trigger test from cypress -> playwright (#19453)
This commit is contained in:
@@ -1,101 +0,0 @@
|
||||
import { WorkflowPage, NDV } from '../pages';
|
||||
import { getVisibleSelect } from '../utils';
|
||||
|
||||
const workflowPage = new WorkflowPage();
|
||||
const ndv = new NDV();
|
||||
|
||||
describe('n8n Form Trigger', () => {
|
||||
beforeEach(() => {
|
||||
workflowPage.actions.visit();
|
||||
});
|
||||
|
||||
it("add node by clicking on 'On form submission'", () => {
|
||||
workflowPage.getters.canvasPlusButton().click();
|
||||
workflowPage.getters.nodeCreatorNodeItems().contains('On form submission').click();
|
||||
ndv.getters.parameterInput('formTitle').type('Test Form');
|
||||
ndv.getters.parameterInput('formDescription').type('Test Form Description');
|
||||
ndv.getters.backToCanvas().click();
|
||||
workflowPage.getters.nodeIssuesByName('On form submission').should('not.exist');
|
||||
});
|
||||
|
||||
it('should fill up form fields', () => {
|
||||
workflowPage.actions.addInitialNodeToCanvas('n8n Form Trigger', {
|
||||
isTrigger: true,
|
||||
action: 'On new n8n Form event',
|
||||
});
|
||||
ndv.getters.parameterInput('formTitle').type('Test Form');
|
||||
ndv.getters.parameterInput('formDescription').type('Test Form Description');
|
||||
cy.get('[data-test-id="fixed-collection-add"]').click();
|
||||
ndv.getters.parameterInput('fieldLabel').type('Test Field 1');
|
||||
ndv.getters.parameterInput('fieldType').click();
|
||||
//fill up first field of type number
|
||||
getVisibleSelect().contains('Number').click();
|
||||
cy.get(
|
||||
'[data-test-id="parameter-input-requiredField"] > .parameter-input > .el-switch > .el-switch__core',
|
||||
).click();
|
||||
//fill up second field of type text
|
||||
cy.get('.fixed-collection-parameter > :nth-child(2) > .button > span').click();
|
||||
cy.get('.border-top-dashed > .parameter-input-list-wrapper > :nth-child(1) > .parameter-item')
|
||||
.find('input[placeholder*="e.g. What is your name?"]')
|
||||
.type('Test Field 2');
|
||||
//fill up second field of type date
|
||||
cy.get('.fixed-collection-parameter > :nth-child(2) > .button > span').click();
|
||||
cy.get(
|
||||
':nth-child(3) > .border-top-dashed > .parameter-input-list-wrapper > :nth-child(1) > .parameter-item',
|
||||
)
|
||||
.find('input[placeholder*="e.g. What is your name?"]')
|
||||
.type('Test Field 3');
|
||||
cy.get(
|
||||
':nth-child(3) > .border-top-dashed > .parameter-input-list-wrapper > :nth-child(2) > .parameter-item',
|
||||
).click();
|
||||
getVisibleSelect().contains('Date').click();
|
||||
// fill up second field of type dropdown
|
||||
cy.get('.fixed-collection-parameter > :nth-child(2) > .button').click();
|
||||
cy.get(
|
||||
':nth-child(4) > .border-top-dashed > .parameter-input-list-wrapper > :nth-child(1) > .parameter-item',
|
||||
)
|
||||
.find('input[placeholder*="e.g. What is your name?"]')
|
||||
.type('Test Field 4');
|
||||
cy.get(
|
||||
':nth-child(4) > .border-top-dashed > .parameter-input-list-wrapper > :nth-child(2) > .parameter-item',
|
||||
).click();
|
||||
getVisibleSelect().contains('Dropdown').click();
|
||||
cy.contains('button', 'Add Field Option').click();
|
||||
cy.contains('label', 'Field Options')
|
||||
.parent()
|
||||
.parent()
|
||||
.nextAll()
|
||||
.find('[data-test-id="parameter-input-field"]')
|
||||
.eq(0)
|
||||
.type('Option 1');
|
||||
cy.contains('label', 'Field Options')
|
||||
.parent()
|
||||
.parent()
|
||||
.nextAll()
|
||||
.find('[data-test-id="parameter-input-field"]')
|
||||
.eq(1)
|
||||
.type('Option 2');
|
||||
|
||||
//add optional submitted message
|
||||
cy.get('.param-options').click();
|
||||
// wait for selector debounce
|
||||
getVisibleSelect().find('span').contains('Form Response').click().wait(300);
|
||||
cy.contains('span', 'Text to Show')
|
||||
.should('exist')
|
||||
.parent()
|
||||
.parent()
|
||||
.next()
|
||||
.children()
|
||||
.children()
|
||||
.children()
|
||||
.children()
|
||||
.children()
|
||||
.children()
|
||||
.children()
|
||||
.first()
|
||||
.type('Your test form was successfully submitted');
|
||||
|
||||
ndv.getters.backToCanvas().click();
|
||||
workflowPage.getters.nodeIssuesByName('On form submission').should('not.exist');
|
||||
});
|
||||
});
|
||||
@@ -44,6 +44,10 @@ export class CanvasPage extends BasePage {
|
||||
return this.page.locator(`[data-test-id="canvas-node"][data-node-name="${nodeName}"]`);
|
||||
}
|
||||
|
||||
nodeIssuesBadge(nodeName: string) {
|
||||
return this.nodeByName(nodeName).getByTestId('node-issues');
|
||||
}
|
||||
|
||||
nodeToolbar(nodeName: string): Locator {
|
||||
return this.nodeByName(nodeName).getByTestId('canvas-node-toolbar');
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { BasePage } from './BasePage';
|
||||
import { RunDataPanel } from './components/RunDataPanel';
|
||||
import { NodeParameterHelper } from '../helpers/NodeParameterHelper';
|
||||
import { EditFieldsNode } from './nodes/EditFieldsNode';
|
||||
import { locatorByIndex } from '../utils/index-helper';
|
||||
|
||||
export class NodeDetailsViewPage extends BasePage {
|
||||
readonly setupHelper: NodeParameterHelper;
|
||||
@@ -46,8 +47,10 @@ export class NodeDetailsViewPage extends BasePage {
|
||||
return this.getContainer().locator('.parameter-item').filter({ hasText: labelName });
|
||||
}
|
||||
|
||||
async fillParameterInput(labelName: string, value: string) {
|
||||
await this.getParameterByLabel(labelName).getByTestId('parameter-input-field').fill(value);
|
||||
async fillParameterInput(labelName: string, value: string, index?: number) {
|
||||
await locatorByIndex(this.getParameterByLabel(labelName), index)
|
||||
.getByTestId('parameter-input-field')
|
||||
.fill(value);
|
||||
}
|
||||
|
||||
async selectWorkflowResource(createItemText: string, searchText: string = '') {
|
||||
@@ -68,6 +71,10 @@ export class NodeDetailsViewPage extends BasePage {
|
||||
await this.clickBackToCanvasButton();
|
||||
}
|
||||
|
||||
async addFixedCollectionItem() {
|
||||
await this.clickByTestId('fixed-collection-add');
|
||||
}
|
||||
|
||||
async execute() {
|
||||
await this.clickByTestId('node-execute-button');
|
||||
}
|
||||
@@ -211,31 +218,29 @@ export class NodeDetailsViewPage extends BasePage {
|
||||
await editor.type(text);
|
||||
}
|
||||
|
||||
getParameterInput(parameterName: string) {
|
||||
return this.page.getByTestId(`parameter-input-${parameterName}`);
|
||||
getParameterInput(parameterName: string, index?: number) {
|
||||
return locatorByIndex(this.page.getByTestId(`parameter-input-${parameterName}`), index);
|
||||
}
|
||||
|
||||
getParameterInputField(parameterName: string) {
|
||||
return this.getParameterInput(parameterName).locator('input');
|
||||
getParameterInputField(parameterName: string, index?: number) {
|
||||
return this.getParameterInput(parameterName, index).locator('input');
|
||||
}
|
||||
|
||||
async selectOptionInParameterDropdown(parameterName: string, optionText: string) {
|
||||
const dropdown = this.getParameterInput(parameterName);
|
||||
await dropdown.click();
|
||||
|
||||
await this.page.getByRole('option', { name: optionText }).click();
|
||||
async selectOptionInParameterDropdown(parameterName: string, optionText: string, index = 0) {
|
||||
await this.clickParameterDropdown(parameterName, index);
|
||||
await this.selectFromVisibleDropdown(optionText);
|
||||
}
|
||||
|
||||
async clickParameterDropdown(parameterName: string): Promise<void> {
|
||||
await this.clickByTestId(`parameter-input-${parameterName}`);
|
||||
async clickParameterDropdown(parameterName: string, index = 0): Promise<void> {
|
||||
await locatorByIndex(this.page.getByTestId(`parameter-input-${parameterName}`), index).click();
|
||||
}
|
||||
|
||||
async selectFromVisibleDropdown(optionText: string): Promise<void> {
|
||||
await this.page.getByRole('option', { name: optionText }).click();
|
||||
}
|
||||
|
||||
async fillParameterInputByName(parameterName: string, value: string): Promise<void> {
|
||||
const input = this.getParameterInputField(parameterName);
|
||||
async fillParameterInputByName(parameterName: string, value: string, index = 0): Promise<void> {
|
||||
const input = this.getParameterInputField(parameterName, index);
|
||||
await input.click();
|
||||
await input.fill(value);
|
||||
}
|
||||
@@ -244,6 +249,11 @@ export class NodeDetailsViewPage extends BasePage {
|
||||
await this.page.locator('.param-options').click();
|
||||
}
|
||||
|
||||
async addParameterOptionByName(optionName: string): Promise<void> {
|
||||
await this.clickParameterOptions();
|
||||
await this.selectFromVisibleDropdown(optionName);
|
||||
}
|
||||
|
||||
getVisiblePopper() {
|
||||
return this.page.locator('.el-popper:visible');
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import { test, expect } from '../../fixtures/base';
|
||||
|
||||
test.describe('Form Trigger', () => {
|
||||
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.setParameterSwitch('requiredField', true);
|
||||
|
||||
// Add second field - Text type
|
||||
await n8n.ndv.addFixedCollectionItem();
|
||||
await n8n.ndv.fillParameterInputByName('fieldLabel', 'Test Field 2', 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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();
|
||||
});
|
||||
});
|
||||
10
packages/testing/playwright/utils/index-helper.ts
Normal file
10
packages/testing/playwright/utils/index-helper.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import type { Locator } from '@playwright/test';
|
||||
|
||||
/**
|
||||
* Returns a locator for a specific element by index, or the original locator if no index is provided.
|
||||
* Without an index, Playwright throws an error when multiple matching elements are found.
|
||||
* @see https://playwright.dev/docs/locators#strictness
|
||||
*/
|
||||
export function locatorByIndex(locator: Locator, index?: number) {
|
||||
return typeof index === 'number' ? locator.nth(index) : locator;
|
||||
}
|
||||
Reference in New Issue
Block a user