diff --git a/cypress/e2e/5-ndv.cy.ts b/cypress/e2e/5-ndv.cy.ts index d255e80bc119c..aaa16681ead02 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'); + cy.get('.has-issues').should('have.length', 0); + cy.get('[class*=hasIssues]').should('have.length', 0); + 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 only after blur or re-opening of NDV', () => { + 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..5f8651677b7df 100644 --- a/packages/editor-ui/src/Interface.ts +++ b/packages/editor-ui/src/Interface.ts @@ -960,6 +960,7 @@ export interface ITemplatesNode extends IVersionNode { export interface INodeMetadata { parametersLastUpdatedAt?: number; + pristine: boolean; } export interface IUsedCredential { 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" /> -