From 1e8e21c90a205d2bf539b8ecfc87f0fc86f1147d Mon Sep 17 00:00:00 2001 From: Oleg Ivaniv Date: Thu, 12 Jan 2023 17:54:00 +0100 Subject: [PATCH 1/5] feat(editor): Supress validation errors when node is added from node creator --- cypress/e2e/5-ndv.cy.ts | 37 +++++++++++++ .../fixtures/Test_workflow_ndv_errors.json | 32 +++++++++++ cypress/pages/workflow.ts | 5 +- packages/editor-ui/src/Interface.ts | 1 + .../src/components/NodeCredentials.vue | 28 +++++++--- .../editor-ui/src/components/NodeSettings.vue | 35 +++++++++++- .../src/components/ParameterInputFull.vue | 6 ++ .../src/components/ParameterInputList.vue | 55 +++++++++++++------ .../ResourceLocator/ResourceLocator.vue | 1 + packages/editor-ui/src/stores/workflows.ts | 6 ++ packages/editor-ui/src/views/NodeView.vue | 1 + 11 files changed, 180 insertions(+), 27 deletions(-) create mode 100644 cypress/fixtures/Test_workflow_ndv_errors.json diff --git a/cypress/e2e/5-ndv.cy.ts b/cypress/e2e/5-ndv.cy.ts index d255e80bc119c..101ab14f12372 100644 --- a/cypress/e2e/5-ndv.cy.ts +++ b/cypress/e2e/5-ndv.cy.ts @@ -53,4 +53,41 @@ describe('NDV', () => { ndv.getters.dataContainer().should('contain', 'start'); }); }); + + it('should show correct validation state for resource locator params', () => { + workflowPage.actions.addNodeToCanvas('Typeform', true); + ndv.getters.container().should('be.visible'); + // The resource locator error should be visible initially + cy.get('.has-issues').should('have.length', 1); + ndv.getters.backToCanvas().click(); + // Both credentials and resource locator errors should be visible + workflowPage.actions.openNodeNdv('Typeform'); + cy.get('.has-issues').should('have.length', 1); + cy.get('[class*=hasIssues]').should('have.length', 1); + }); + + it('should show validation errors after blur', () => { + workflowPage.actions.addNodeToCanvas('Manual Trigger'); + workflowPage.actions.addNodeToCanvas('Airtable', true); + ndv.getters.container().should('be.visible'); + cy.get('.has-issues').should('have.length', 0); + workflowPage.getters.ndvParameterInput('table').find('input').eq(1).focus().blur() + workflowPage.getters.ndvParameterInput('application').find('input').eq(1).focus().blur() + cy.get('.has-issues').should('have.length', 2); + ndv.getters.backToCanvas().click(); + workflowPage.actions.openNodeNdv('Airtable'); + cy.get('.has-issues').should('have.length', 3); + cy.get('[class*=hasIssues]').should('have.length', 1); + }); + + it('should show all validation errors when opening pasted node', () => { + cy.fixture('Test_workflow_ndv_errors.json').then((data) => { + cy.get('body').paste(JSON.stringify(data)); + workflowPage.getters.canvasNodes().should('have.have.length', 1); + workflowPage.actions.openNodeNdv('Airtable'); + cy.get('.has-issues').should('have.length', 3); + cy.get('[class*=hasIssues]').should('have.length', 1); + }); + }); + }); diff --git a/cypress/fixtures/Test_workflow_ndv_errors.json b/cypress/fixtures/Test_workflow_ndv_errors.json new file mode 100644 index 0000000000000..aea6fc1190f7e --- /dev/null +++ b/cypress/fixtures/Test_workflow_ndv_errors.json @@ -0,0 +1,32 @@ +{ + "meta": { + "instanceId": "3204fc455f5cbeb4e71fdbd3b1dfaf0b088088dea3e639de49e61462b80ffc1d" + }, + "nodes": [ + { + "parameters": { + "application": { + "__rl": true, + "mode": "url", + "value": "", + "__regex": "https://airtable.com/([a-zA-Z0-9]{2,})" + }, + "table": { + "__rl": true, + "mode": "url", + "value": "", + "__regex": "https://airtable.com/[a-zA-Z0-9]{2,}/([a-zA-Z0-9]{2,})" + } + }, + "id": "e0c0cf7e-aa98-4b72-9645-6e64e2902bd1", + "name": "Airtable", + "type": "n8n-nodes-base.airtable", + "typeVersion": 1, + "position": [ + 380, + 180 + ] + } + ], + "connections": {} +} diff --git a/cypress/pages/workflow.ts b/cypress/pages/workflow.ts index ac055c6bc8797..c5a959303e056 100644 --- a/cypress/pages/workflow.ts +++ b/cypress/pages/workflow.ts @@ -93,11 +93,12 @@ export class WorkflowPage extends BasePage { this.getters.nodeCreatorSearchBar().type('{enter}'); cy.get('body').type('{esc}'); }, - addNodeToCanvas: (nodeDisplayName: string) => { + addNodeToCanvas: (nodeDisplayName: string, preventNdvClose?: boolean) => { this.getters.nodeCreatorPlusButton().click(); this.getters.nodeCreatorSearchBar().type(nodeDisplayName); this.getters.nodeCreatorSearchBar().type('{enter}'); - cy.get('body').type('{esc}'); + + if (!preventNdvClose) cy.get('body').type('{esc}'); }, openNodeNdv: (nodeTypeName: string) => { this.getters.canvasNodeByName(nodeTypeName).dblclick(); diff --git a/packages/editor-ui/src/Interface.ts b/packages/editor-ui/src/Interface.ts index f8828dd670fc7..7be1a8731d940 100644 --- a/packages/editor-ui/src/Interface.ts +++ b/packages/editor-ui/src/Interface.ts @@ -193,6 +193,7 @@ export interface INodeUi extends INode { issues?: INodeIssues; name: string; pinData?: IDataObject; + pristine: boolean; } export interface INodeTypesMaxCount { diff --git a/packages/editor-ui/src/components/NodeCredentials.vue b/packages/editor-ui/src/components/NodeCredentials.vue index 8af8d36fc2dc9..58e34d5b85ccf 100644 --- a/packages/editor-ui/src/components/NodeCredentials.vue +++ b/packages/editor-ui/src/components/NodeCredentials.vue @@ -27,10 +27,11 @@ size="small" /> -
+
@@ -49,7 +50,7 @@ -
+