diff --git a/cypress/e2e/30-if-node.cy.ts b/cypress/e2e/30-if-node.cy.ts deleted file mode 100644 index 95ed1e9a0d..0000000000 --- a/cypress/e2e/30-if-node.cy.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { IF_NODE_NAME } from '../constants'; -import { WorkflowPage, NDV } from '../pages'; - -const workflowPage = new WorkflowPage(); -const ndv = new NDV(); - -const FILTER_PARAM_NAME = 'conditions'; - -describe('If Node (filter component)', () => { - beforeEach(() => { - workflowPage.actions.visit(); - }); - - it('should be able to create and delete multiple conditions', () => { - workflowPage.actions.addInitialNodeToCanvas(IF_NODE_NAME, { keepNdvOpen: true }); - - // Default state - ndv.getters.filterComponent(FILTER_PARAM_NAME).should('exist'); - ndv.getters.filterConditions(FILTER_PARAM_NAME).should('have.length', 1); - ndv.getters - .filterConditionOperator(FILTER_PARAM_NAME) - .find('input') - .should('have.value', 'is equal to'); - - // Add - ndv.actions.addFilterCondition(FILTER_PARAM_NAME); - ndv.getters.filterConditionLeft(FILTER_PARAM_NAME, 0).find('input').type('first left'); - ndv.getters.filterConditionLeft(FILTER_PARAM_NAME, 1).find('input').type('second left'); - ndv.actions.addFilterCondition(FILTER_PARAM_NAME); - ndv.getters.filterConditions(FILTER_PARAM_NAME).should('have.length', 3); - - // Delete - ndv.actions.removeFilterCondition(FILTER_PARAM_NAME, 0); - ndv.getters.filterConditions(FILTER_PARAM_NAME).should('have.length', 2); - ndv.getters - .filterConditionLeft(FILTER_PARAM_NAME, 0) - .find('input') - .should('have.value', 'second left'); - ndv.actions.removeFilterCondition(FILTER_PARAM_NAME, 1); - ndv.getters.filterConditions(FILTER_PARAM_NAME).should('have.length', 1); - }); - - it('should correctly evaluate conditions', () => { - cy.fixture('Test_workflow_filter.json').then((data) => { - cy.get('body').paste(JSON.stringify(data)); - }); - - workflowPage.actions.zoomToFit(); - workflowPage.actions.executeWorkflow(); - - workflowPage.actions.openNode('Then'); - ndv.getters.outputPanel().contains('3 items').should('exist'); - ndv.actions.close(); - - workflowPage.actions.openNode('Else'); - ndv.getters.outputPanel().contains('1 item').should('exist'); - }); -}); diff --git a/packages/testing/playwright/pages/NodeDetailsViewPage.ts b/packages/testing/playwright/pages/NodeDetailsViewPage.ts index 67ee5f7213..fb215f6855 100644 --- a/packages/testing/playwright/pages/NodeDetailsViewPage.ts +++ b/packages/testing/playwright/pages/NodeDetailsViewPage.ts @@ -885,6 +885,47 @@ export class NodeDetailsViewPage extends BasePage { getCredentialLabel(credentialType: string) { return this.page.getByText(credentialType); } + + getFilterComponent(paramName: string) { + return this.page.getByTestId(`filter-${paramName}`); + } + + getFilterConditions(paramName: string) { + return this.getFilterComponent(paramName).getByTestId('filter-condition'); + } + + getFilterCondition(paramName: string, index: number = 0) { + return this.getFilterComponent(paramName).getByTestId('filter-condition').nth(index); + } + + getFilterConditionLeft(paramName: string, index: number = 0) { + return this.getFilterComponent(paramName).getByTestId('filter-condition-left').nth(index); + } + + getFilterConditionRight(paramName: string, index: number = 0) { + return this.getFilterComponent(paramName).getByTestId('filter-condition-right').nth(index); + } + + getFilterConditionOperator(paramName: string, index: number = 0) { + return this.getFilterComponent(paramName).getByTestId('filter-operator-select').nth(index); + } + + getFilterConditionRemove(paramName: string, index: number = 0) { + return this.getFilterComponent(paramName).getByTestId('filter-remove-condition').nth(index); + } + + getFilterConditionAdd(paramName: string) { + return this.getFilterComponent(paramName).getByTestId('filter-add-condition'); + } + + async addFilterCondition(paramName: string) { + await this.getFilterConditionAdd(paramName).click(); + } + + async removeFilterCondition(paramName: string, index: number) { + await this.getFilterConditionRemove(paramName, index).click(); + } + getWebhookTestEvent() { return this.page.getByText('Listening for test event'); } diff --git a/packages/testing/playwright/tests/ui/30-if-node.spec.ts b/packages/testing/playwright/tests/ui/30-if-node.spec.ts new file mode 100644 index 0000000000..3c03ea9fa8 --- /dev/null +++ b/packages/testing/playwright/tests/ui/30-if-node.spec.ts @@ -0,0 +1,50 @@ +import { IF_NODE_NAME } from '../../config/constants'; +import { test, expect } from '../../fixtures/base'; + +const FILTER_PARAM_NAME = 'conditions'; + +test.describe('If Node (filter component)', () => { + test.beforeEach(async ({ n8n }) => { + await n8n.start.fromBlankCanvas(); + }); + + test('should be able to create and delete multiple conditions', async ({ n8n }) => { + await n8n.canvas.addNode(IF_NODE_NAME, { closeNDV: false }); + + // Default state + await expect(n8n.ndv.getFilterComponent(FILTER_PARAM_NAME)).toBeVisible(); + await expect(n8n.ndv.getFilterConditions(FILTER_PARAM_NAME)).toHaveCount(1); + await expect( + n8n.ndv.getFilterConditionOperator(FILTER_PARAM_NAME).locator('input'), + ).toHaveValue('is equal to'); + + // Add + await n8n.ndv.addFilterCondition(FILTER_PARAM_NAME); + await n8n.ndv.getFilterConditionLeft(FILTER_PARAM_NAME, 0).locator('input').fill('first left'); + await n8n.ndv.getFilterConditionLeft(FILTER_PARAM_NAME, 1).locator('input').fill('second left'); + await n8n.ndv.addFilterCondition(FILTER_PARAM_NAME); + await expect(n8n.ndv.getFilterConditions(FILTER_PARAM_NAME)).toHaveCount(3); + + // Delete + await n8n.ndv.removeFilterCondition(FILTER_PARAM_NAME, 0); + await expect(n8n.ndv.getFilterConditions(FILTER_PARAM_NAME)).toHaveCount(2); + await expect(n8n.ndv.getFilterConditionLeft(FILTER_PARAM_NAME, 0).locator('input')).toHaveValue( + 'second left', + ); + await n8n.ndv.removeFilterCondition(FILTER_PARAM_NAME, 1); + await expect(n8n.ndv.getFilterConditions(FILTER_PARAM_NAME)).toHaveCount(1); + }); + + test('should correctly evaluate conditions', async ({ n8n }) => { + await n8n.start.fromImportedWorkflow('Test_workflow_filter.json'); + + await n8n.canvas.clickExecuteWorkflowButton(); + + await n8n.canvas.openNode('Then'); + await expect(n8n.ndv.outputPanel.get()).toContainText('3 items'); + await n8n.ndv.close(); + + await n8n.canvas.openNode('Else'); + await expect(n8n.ndv.outputPanel.get()).toContainText('1 item'); + }); +}); diff --git a/packages/testing/playwright/workflows/Test_workflow_filter.json b/packages/testing/playwright/workflows/Test_workflow_filter.json new file mode 100644 index 0000000000..843e54c3d6 --- /dev/null +++ b/packages/testing/playwright/workflows/Test_workflow_filter.json @@ -0,0 +1,138 @@ +{ + "name": "Filter test", + "nodes": [ + { + "parameters": {}, + "id": "f332a7d1-31b4-4e78-b31e-9e8db945bf3f", + "name": "When clicking ‘Execute workflow’", + "type": "n8n-nodes-base.manualTrigger", + "typeVersion": 1, + "position": [-60, 480] + }, + { + "parameters": { + "jsCode": "return [\n {\n \"label\": \"Apple\",\n tags: [],\n meta: {foo: 'bar'}\n },\n {\n \"label\": \"Banana\",\n tags: ['exotic'],\n meta: {}\n },\n {\n \"label\": \"Pear\",\n tags: ['other'],\n meta: {}\n },\n {\n \"label\": \"Orange\",\n meta: {}\n }\n]" + }, + "id": "60697c7f-3948-4790-97ba-8aba03d02ac2", + "name": "Code", + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [160, 480] + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "" + }, + "conditions": [ + { + "leftValue": "={{ $json.tags }}", + "rightValue": "exotic", + "operator": { + "type": "array", + "operation": "contains", + "rightType": "any" + } + }, + { + "leftValue": "={{ $json.meta }}", + "rightValue": "", + "operator": { + "type": "object", + "operation": "notEmpty", + "singleValue": true + } + }, + { + "leftValue": "={{ $json.label }}", + "rightValue": "Pea", + "operator": { + "type": "string", + "operation": "startsWith", + "rightType": "string" + } + } + ], + "combinator": "or" + }, + "options": {} + }, + "id": "7531191b-5ac3-45dc-8afb-27ae83d8f33a", + "name": "If", + "type": "n8n-nodes-base.if", + "typeVersion": 2, + "position": [380, 480] + }, + { + "parameters": {}, + "id": "d8c614ea-0bbf-4b12-ad7d-c9ebe09ce583", + "name": "Then", + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [600, 400] + }, + { + "parameters": {}, + "id": "69364770-60d2-4ef4-9f29-9570718a9a10", + "name": "Else", + "type": "n8n-nodes-base.noOp", + "typeVersion": 1, + "position": [600, 580] + } + ], + "pinData": {}, + "connections": { + "When clicking ‘Execute workflow’": { + "main": [ + [ + { + "node": "Code", + "type": "main", + "index": 0 + } + ] + ] + }, + "Code": { + "main": [ + [ + { + "node": "If", + "type": "main", + "index": 0 + } + ] + ] + }, + "If": { + "main": [ + [ + { + "node": "Then", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Else", + "type": "main", + "index": 0 + } + ] + ] + } + }, + "active": false, + "settings": { + "executionOrder": "v1" + }, + "versionId": "a6249f48-d88f-4b80-9ed9-79555e522d48", + "id": "BWUTRs5RHxVgQ4uT", + "meta": { + "instanceId": "78577815012af39cf16dad7a787b0898c42fb7514b8a7f99b2136862c2af502c" + }, + "tags": [] +}