ci(editor): Run e2e tests in parallel and improve build caching (#5445)

* WIP: Cypress parallel CI run test

* Trigger action on branch push

* Change build artifacts path

* Make sure to checkout the repo for testing job

* Use Cypress action for installing

* Lock cypress action userd version

* Skip node install step since we're using cypress node16 container

* Let Cypress handle pnpm install

* Use setup-node action for caching pnpm

* Set CYPRESS_CACHE_FOLDER

* Set CYPRESS_CACHE_FOLDER

* Manually cache pnpm store

* Dont fix pnpm version

* Use caching action also in testing job

* Zip packages dist before uploading the artifacts and change caching key

* Use absolute build paths for zipping job

* Use zip command in action

* Use tar for zipping packages

* Debuggin directory ls

* Debugging caching of modules

* Attempt to fix permissions issue

* Porivde Cypress executable via `CYPRESS_RUN_BINARY`

* Cache /github/home

* Adjust caching keys

* Debug: search for cypress exec

* Debugging: List dirs

* Use pnpm install action to install node_modules

* Do not log /home/runner

* Use node_modules/.bin Cypress binary

* Use absolute path to nodue modules

* Run Cypress via custom command

* Try with patched cypress action

* Revert logging

* Manually specify cypress config file

* Use absolute paths

* Fix cypress config name

* Debug print cypress config

* Remove debugging, increase to 4 containers

* Increase amount of containers

* Add env-version matrix

* Replace node14 with node18 in testing matrix

* Remove debugging and add node 14

* Use just node14

* Use cypress:base and remove browser req

* Give more general timeouts

* Try with node16

* Change cache directive position

* Replace zip artifact upload with cache

* Cache full packages not just dist

* Test with variable inputs

* Add commit info message

* Remove wrongly commited code

* Allow WF API dispatch

* Try Chrome browser again for comparison

* Include Monaco in the build

* Make e2e workflow re-usable

* Comment out invalid reusable workflow args

* Use electron and add node 14 run

* Fix env arg

* Provide custom ci-build-id

* Refactor remaining e2e workflow to use reusable action

* Remove single matrix directive

* Refactor ci-pull-req

* Make lint job dependant on test jobs

* Disable debugging job

* Make containers dynamic

* Cleanup & install git for linting action

* Use regular buntu image for PR linting

* Debugging failing tests

* Remove fixed spec name

* Debug e2e env var

* Do not use realkeypress which crashes electron runner

* Debugging

* chore: remove console

* chore: remove console

* test: remove node 14 tests

* test: replace test branch with master

* test: use tests in current branch

* test: use relative path

* chore: clean up

* test: only trigger on approval

* ci: update test PR

* ci: use curr branch

* ci: only run 14 on schedule, not for slack command

* ci: only run test on approval

* ci: clean up branch, rename step

* ci: rename steps

* ci: clean up cancel

* ci: clean up env var

* ci: set var

* ci: use chromef

* ci: use electron

* chore: add console log

* chore: add console log

* ci: update to string

* ci: set all env options

* test: build

* ci: fix step issue

* Fix failing tests & upgrade to Cypress 12

* Allow WF dispatch of e2e reusable

* Fix wrong naming in e2e-tests workflow

* Redeploy

* Fix tests

* Fix NDV tests and remove skipping of webhooks execution tests

* Fix clipboard read command

* Fix execution failing tests

* Reset before each 15 and 3

* Fix flaky tests

* Cleanup and log envs

* Test fixes

* Default owner spec fixes

* Get rid of CYPRESS_RUN_ENV

* Increase amount of containers, cleanup and add mock for credentials test call

* Cleanup & fix PR tests unit tests

* Wait for WF to loade in sharing spec

* Do linting and unit tests first

* Use frozen lockfile

* Revert back ci pull request jobs order

* Refine credential input selector and move cy.waitForLoad to correct position in 15-scheduler spec

* test: build

* Wait for WF execution instead of arbitraty timeout in WF execution spec, change order of jobs for ci pull request

* Fix flaky 3-default owner spec and wait for execution list to load in 20-workflow-executions

* Use setup node action

* Remove caching for lint/unit tests

* Experiment with parallel test & lint on ci

* Provide cache key dynamically

* Run e2e in parallel on pr

* Only run node14 e2e on daily schedule

* Make sure to generate generate new ci-build-id on re-runs

* Remove debugging prints

* Address PR comments

* Rename custom onBeforeUnload handler

* Make sure 19-execution spec waits for wf to load properly before import fixtures

---------

Co-authored-by: Mutasem <mutdmour@gmail.com>
This commit is contained in:
OlegIvaniv
2023-03-02 16:50:21 +01:00
committed by GitHub
parent 5040fea93e
commit 0004dc7ee8
31 changed files with 528 additions and 356 deletions

View File

@@ -63,11 +63,9 @@ describe('Log Streaming Settings', () => {
settingsLogStreamingPage.getters.getSelectDestinationType().click();
settingsLogStreamingPage.getters.getSelectDestinationTypeItems().eq(0).click();
settingsLogStreamingPage.getters.getSelectDestinationButton().click();
settingsLogStreamingPage.getters
.getDestinationNameInput()
.click()
.clear()
.type('Destination 0');
settingsLogStreamingPage.getters.getDestinationNameInput().click()
settingsLogStreamingPage.getters.getDestinationNameInput().find('input').clear().type('Destination 0');
settingsLogStreamingPage.getters.getDestinationSaveButton().click();
cy.wait(100);
settingsLogStreamingPage.getters.getDestinationModal().click(1, 1);
@@ -88,11 +86,8 @@ describe('Log Streaming Settings', () => {
settingsLogStreamingPage.getters.getSelectDestinationType().click();
settingsLogStreamingPage.getters.getSelectDestinationTypeItems().eq(0).click();
settingsLogStreamingPage.getters.getSelectDestinationButton().click();
settingsLogStreamingPage.getters
.getDestinationNameInput()
.click()
.clear()
.type('Destination 1');
settingsLogStreamingPage.getters.getDestinationNameInput().click()
settingsLogStreamingPage.getters.getDestinationNameInput().find('input').clear().type('Destination 1');
settingsLogStreamingPage.getters.getDestinationSaveButton().should('not.have.attr', 'disabled');
settingsLogStreamingPage.getters.getDestinationSaveButton().click();
cy.wait(100);

View File

@@ -17,6 +17,7 @@ describe('Inline expression editor', () => {
});
it('should resolve primitive resolvables', () => {
WorkflowPage.getters.inlineExpressionEditorInput().clear();
WorkflowPage.getters.inlineExpressionEditorInput().type('{{');
WorkflowPage.getters.inlineExpressionEditorInput().type('1 + 2');
WorkflowPage.getters.inlineExpressionEditorOutput().contains(/^3$/);
@@ -35,6 +36,7 @@ describe('Inline expression editor', () => {
});
it('should resolve object resolvables', () => {
WorkflowPage.getters.inlineExpressionEditorInput().clear();
WorkflowPage.getters.inlineExpressionEditorInput().type('{{');
WorkflowPage.getters
.inlineExpressionEditorInput()

View File

@@ -16,7 +16,7 @@ describe('Data transformation expressions', () => {
cy.window()
// @ts-ignore
.then(
(win) => win.onBeforeUnload && win.removeEventListener('beforeunload', win.onBeforeUnload),
(win) => win.onBeforeUnloadNodeView && win.removeEventListener('beforeunload', win.onBeforeUnloadNodeView),
);
});
@@ -80,19 +80,18 @@ describe('Data transformation expressions', () => {
ndv.getters.outputDataContainer().contains(output);
});
it('$json + native array methods', () => {
it('$json + native array access', () => {
wf.actions.addInitialNodeToCanvas('Schedule Trigger', { keepNdvOpen: true });
ndv.actions.setPinnedData([{ myArr: [1, 2, 3] }]);
ndv.actions.close();
addSet();
const input = '{{$json.myArr.includes(1) + " " + $json.myArr.at(2)';
const input = '{{$json.myArr.includes(1) + " " + $json.myArr[2]';
const output = 'true 3';
ndv.getters.inlineExpressionEditorInput().clear().type(input);
ndv.actions.execute();
ndv.getters.outputDataContainer().should('be.visible');
ndv.getters.outputDataContainer().contains(output);
ndv.getters.outputDataContainer().find('[class*=value_]').should('exist')
ndv.getters.outputDataContainer().find('[class*=value_]').should('contain', output);
});
it('$json + n8n array methods', () => {
@@ -106,7 +105,8 @@ describe('Data transformation expressions', () => {
ndv.getters.inlineExpressionEditorInput().clear().type(input);
ndv.actions.execute();
ndv.getters.outputDataContainer().should('be.visible').contains(output);
ndv.getters.outputDataContainer().find('[class*=value_]').should('exist')
ndv.getters.outputDataContainer().find('[class*=value_]').should('contain', output);
});
});

View File

@@ -21,7 +21,7 @@ describe('Data mapping', () => {
cy.window()
// @ts-ignore
.then(
(win) => win.onBeforeUnload && win.removeEventListener('beforeunload', win.onBeforeUnload),
(win) => win.onBeforeUnloadNodeView && win.removeEventListener('beforeunload', win.onBeforeUnloadNodeView),
);
});

View File

@@ -5,15 +5,15 @@ const workflowPage = new WorkflowPage();
const ndv = new NDV();
describe('Schedule Trigger node', async () => {
before(() => {
beforeEach(() => {
cy.resetAll();
cy.skipSetup();
cy.visit(workflowsPage.url);
});
it('should execute and return the execution timestamp', () => {
cy.visit(workflowsPage.url);
workflowsPage.actions.createWorkflowFromCard();
cy.waitForLoad();
workflowPage.actions.addInitialNodeToCanvas('Schedule Trigger');
workflowPage.actions.openNode('Schedule Trigger');
ndv.actions.execute();
@@ -22,9 +22,8 @@ describe('Schedule Trigger node', async () => {
});
it('should execute once per second when activated', () => {
cy.visit(workflowsPage.url);
workflowsPage.actions.createWorkflowFromCard();
cy.waitForLoad();
workflowPage.actions.renameWorkflow('Schedule Trigger Workflow');
workflowPage.actions.addInitialNodeToCanvas('Schedule Trigger');
workflowPage.actions.openNode('Schedule Trigger');

View File

@@ -103,7 +103,7 @@ describe('Webhook Trigger node', async () => {
cy.window()
// @ts-ignore
.then(
(win) => win.onBeforeUnload && win.removeEventListener('beforeunload', win.onBeforeUnload),
(win) => win.onBeforeUnloadNodeView && win.removeEventListener('beforeunload', win.onBeforeUnloadNodeView),
);
});

View File

@@ -82,6 +82,7 @@ describe('Sharing', () => {
cy.visit(workflowsPage.url);
workflowsPage.getters.newWorkflowButtonCard().click();
cy.waitForLoad();
workflowPage.actions.setWorkflowName('Workflow W1');
workflowPage.actions.addInitialNodeToCanvas('Manual Trigger');
workflowPage.actions.addNodeToCanvas('Notion', true, true);

View File

@@ -5,12 +5,9 @@ const wf = new WorkflowPage();
const TEST_TAGS = ['Tag 1', 'Tag 2', 'Tag 3'];
describe('Workflow tags', () => {
before(() => {
beforeEach(() => {
cy.resetAll();
cy.skipSetup();
});
beforeEach(() => {
wf.actions.visit();
cy.waitForLoad();
});

View File

@@ -6,18 +6,15 @@ const workflowPage = new WorkflowPageClass();
const ndv = new NDV();
describe('Execution', () => {
before(() => {
beforeEach(() => {
cy.resetAll();
cy.skipSetup();
});
beforeEach(() => {
cy.visit('/');
// Import workflow
workflowsPage.getters.newWorkflowButtonCard().click();
cy.waitForLoad();
});
it('should test manual workflow', () => {
// Import workflow
workflowsPage.getters.newWorkflowButtonCard().click();
cy.createFixtureWorkflow('Manual_wait_set.json', `Manual wait set ${uuid()}`);
// Check workflow buttons
@@ -40,14 +37,14 @@ describe('Execution', () => {
workflowPage.getters
.canvasNodeByName('Manual')
.within(() => cy.get('.fa-check'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Wait')
.within(() => cy.get('.fa-check').should('not.exist'));
workflowPage.getters
.canvasNodeByName('Wait')
.within(() => cy.get('.fa-sync-alt'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Set')
.within(() => cy.get('.fa-check').should('not.exist'));
@@ -58,15 +55,15 @@ describe('Execution', () => {
workflowPage.getters
.canvasNodeByName('Manual')
.within(() => cy.get('.fa-check'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Wait')
.within(() => cy.get('.fa-check'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Set')
.within(() => cy.get('.fa-check'))
.should('be.visible');
.should('exist');
// Clear execution data
workflowPage.getters.clearExecutionDataButton().should('be.visible');
@@ -78,8 +75,6 @@ describe('Execution', () => {
});
it('should test manual workflow stop', () => {
// Import workflow
workflowsPage.getters.newWorkflowButtonCard().click();
cy.createFixtureWorkflow('Manual_wait_set.json', `Manual wait set ${uuid()}`);
// Check workflow buttons
@@ -102,14 +97,14 @@ describe('Execution', () => {
workflowPage.getters
.canvasNodeByName('Manual')
.within(() => cy.get('.fa-check'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Wait')
.within(() => cy.get('.fa-check').should('not.exist'));
workflowPage.getters
.canvasNodeByName('Wait')
.within(() => cy.get('.fa-sync-alt'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Set')
.within(() => cy.get('.fa-check').should('not.exist'));
@@ -121,11 +116,11 @@ describe('Execution', () => {
workflowPage.getters
.canvasNodeByName('Manual')
.within(() => cy.get('.fa-check'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Wait')
.within(() => cy.get('.fa-check'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Wait')
.within(() => cy.get('.fa-sync-alt').should('not.visible'));
@@ -143,8 +138,6 @@ describe('Execution', () => {
});
it('should test webhook workflow', () => {
// Import workflow
workflowsPage.getters.newWorkflowButtonCard().click();
cy.createFixtureWorkflow('Webhook_wait_set.json', `Webhook wait set ${uuid()}`);
// Check workflow buttons
@@ -184,14 +177,14 @@ describe('Execution', () => {
workflowPage.getters
.canvasNodeByName('Webhook')
.within(() => cy.get('.fa-check'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Wait')
.within(() => cy.get('.fa-check').should('not.exist'));
workflowPage.getters
.canvasNodeByName('Wait')
.within(() => cy.get('.fa-sync-alt'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Set')
.within(() => cy.get('.fa-check').should('not.exist'));
@@ -202,15 +195,15 @@ describe('Execution', () => {
workflowPage.getters
.canvasNodeByName('Webhook')
.within(() => cy.get('.fa-check'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Wait')
.within(() => cy.get('.fa-check'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Set')
.within(() => cy.get('.fa-check'))
.should('be.visible');
.should('exist');
// Clear execution data
workflowPage.getters.clearExecutionDataButton().should('be.visible');
@@ -222,8 +215,6 @@ describe('Execution', () => {
});
it('should test webhook workflow stop', () => {
// Import workflow
workflowsPage.getters.newWorkflowButtonCard().click();
cy.createFixtureWorkflow('Webhook_wait_set.json', `Webhook wait set ${uuid()}`);
// Check workflow buttons
@@ -259,34 +250,33 @@ describe('Execution', () => {
});
});
workflowPage.getters.stopExecutionButton().click();
// Check canvas nodes after 1st step (workflow passed the manual trigger node
workflowPage.getters
.canvasNodeByName('Webhook')
.within(() => cy.get('.fa-check'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Wait')
.within(() => cy.get('.fa-check').should('not.exist'));
workflowPage.getters
.canvasNodeByName('Wait')
.within(() => cy.get('.fa-sync-alt'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Set')
.within(() => cy.get('.fa-check').should('not.exist'));
cy.wait(1000);
workflowPage.getters.stopExecutionWaitingForWebhookButton().click();
// Check canvas nodes after workflow stopped
workflowPage.getters
.canvasNodeByName('Webhook')
.within(() => cy.get('.fa-check'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Wait')
.within(() => cy.get('.fa-check'))
.should('be.visible');
.should('exist');
workflowPage.getters
.canvasNodeByName('Wait')
.within(() => cy.get('.fa-sync-alt').should('not.visible'));

View File

@@ -32,6 +32,14 @@ describe('Credentials', () => {
before(() => {
cy.resetAll();
cy.setup({ email, firstName, lastName, password });
// Always intercept the request to test credentials and return a success
cy.intercept('POST', '/rest/credentials/test', {
statusCode: 200,
body: {
data: { status: 'success', message: 'Tested successfully' },
}
});
});
beforeEach(() => {
@@ -53,7 +61,6 @@ describe('Credentials', () => {
credentialsModal.getters.newCredentialTypeOption('Notion API').click();
credentialsModal.getters.newCredentialTypeButton().click();
credentialsModal.getters.connectionParameter('API Key').type('1234567890');
credentialsModal.actions.setName('My awesome Notion account');
@@ -71,7 +78,7 @@ describe('Credentials', () => {
credentialsModal.getters.newCredentialTypeOption('Airtable API').click();
credentialsModal.getters.newCredentialTypeButton().click();
credentialsModal.getters.editCredentialModal().should('be.visible');
credentialsModal.getters.connectionParameter('API Key').type('1234567890');
credentialsModal.actions.setName('Airtable Account');

View File

@@ -19,7 +19,13 @@ describe('Current Workflow Executions', () => {
});
it('should render executions tab correctly', () => {
cy.waitForLoad();
cy.intercept('GET', '/rest/executions?filter=*').as('getExecutions');
cy.intercept('GET', '/rest/executions-current?filter=*').as('getCurrentExecutions');
executionsTab.actions.switchToExecutionsTab();
cy.wait(['@getExecutions', '@getCurrentExecutions']);
executionsTab.getters.executionListItems().should('have.length', 11);
executionsTab.getters.successfulExecutionListItems().should('have.length', 9);
executionsTab.getters.failedExecutionListItems().should('have.length', 2);
@@ -40,6 +46,4 @@ const createMockExecutions = () => {
// Then add some more successful ones
executionsTab.actions.toggleNodeEnabled('Error');
executionsTab.actions.createManualExecutions(4);
executionsTab.actions.switchToExecutionsTab();
cy.waitForLoad();
};

View File

@@ -34,26 +34,19 @@ const firstName = randFirstName();
const lastName = randLastName();
describe('Default owner', () => {
before(() => {
cy.resetAll();
});
beforeEach(() => {
cy.visit('/');
});
it('should skip owner setup', () => {
cy.skipSetup();
});
it('should be able to create workflows', () => {
cy.resetAll();
cy.skipSetup();
cy.visit('/');
workflowsPage.getters.newWorkflowButtonCard().should('be.visible');
workflowsPage.getters.newWorkflowButtonCard().click();
cy.waitForLoad();
cy.createFixtureWorkflow('Test_workflow_1.json', `Test workflow`);
// reload page, ensure owner still has access
cy.reload();
cy.waitForLoad();
workflowPage.getters.workflowNameInput().should('contain.value', 'Test workflow');
});
@@ -82,6 +75,7 @@ describe('Default owner', () => {
});
it('should be able to setup UM from settings', () => {
cy.visit('/');
mainSidebar.getters.settings().should('be.visible');
mainSidebar.actions.goToSettings();
cy.url().should('include', settingsUsagePage.url);

View File

@@ -1,13 +1,7 @@
import { NodeCreator } from '../pages/features/node-creator';
import { DEFAULT_USER_EMAIL, DEFAULT_USER_PASSWORD } from '../constants';
import { randFirstName, randLastName } from '@ngneat/falso';
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
import { NDV } from '../pages/ndv';
const email = DEFAULT_USER_EMAIL;
const password = DEFAULT_USER_PASSWORD;
const firstName = randFirstName();
const lastName = randLastName();
const nodeCreatorFeature = new NodeCreator();
const WorkflowPage = new WorkflowPageClass();
const NDVModal = new NDV();
@@ -15,12 +9,10 @@ const NDVModal = new NDV();
describe('Node Creator', () => {
before(() => {
cy.resetAll();
cy.setup({ email, firstName, lastName, password });
cy.skipSetup();
});
beforeEach(() => {
cy.signin({ email, password });
cy.visit(nodeCreatorFeature.url);
cy.waitForLoad();
});
@@ -105,58 +97,52 @@ describe('Node Creator', () => {
it('should search through actions and confirm added action', () => {
nodeCreatorFeature.actions.openNodeCreator();
nodeCreatorFeature.getters.searchBar().find('input').clear().type('ftp');
nodeCreatorFeature.getters.searchBar().find('input').realPress('{rightarrow}');
nodeCreatorFeature.getters.searchBar().find('input').type('{rightarrow}');
nodeCreatorFeature.getters.activeSubcategory().should('have.text', 'FTP');
nodeCreatorFeature.getters.searchBar().find('input').clear().type('file');
// Navigate to rename action which should be the 4th item
nodeCreatorFeature.getters.searchBar().find('input').realPress('{downarrow}');
nodeCreatorFeature.getters.searchBar().find('input').realPress('{downarrow}');
nodeCreatorFeature.getters.searchBar().find('input').realPress('{downarrow}');
nodeCreatorFeature.getters.searchBar().find('input').realPress('{rightarrow}');
nodeCreatorFeature.getters.searchBar().find('input').type('{downarrow} {downarrow} {downarrow} {rightarrow}');
NDVModal.getters.parameterInput('operation').should('contain.text', 'Rename');
})
it('should render and select community node', () => {
cy.intercept('GET', '/types/nodes.json').as('nodesIntercept');
cy.wait('@nodesIntercept').then(() => {
const customNode = 'E2E Node';
const customNode = 'E2E Node';
nodeCreatorFeature.actions.openNodeCreator();
nodeCreatorFeature.getters.searchBar().find('input').clear().type(customNode);
nodeCreatorFeature.actions.openNodeCreator();
nodeCreatorFeature.getters.searchBar().find('input').clear().type(customNode);
nodeCreatorFeature.getters
.getCreatorItem(customNode)
.findChildByTestId('node-creator-item-tooltip')
.should('exist');
nodeCreatorFeature.actions.selectNode(customNode);
nodeCreatorFeature.getters
.getCreatorItem(customNode)
.findChildByTestId('node-creator-item-tooltip')
.should('exist');
nodeCreatorFeature.actions.selectNode(customNode);
// TODO: Replace once we have canvas feature utils
cy.get('.data-display .node-name').contains(customNode).should('exist');
// TODO: Replace once we have canvas feature utils
cy.get('.data-display .node-name').contains(customNode).should('exist');
const nodeParameters = () => cy.getByTestId('node-parameters');
const firstParameter = () => nodeParameters().find('.parameter-item').eq(0);
const secondParameter = () => nodeParameters().find('.parameter-item').eq(1);
const nodeParameters = () => cy.getByTestId('node-parameters');
const firstParameter = () => nodeParameters().find('.parameter-item').eq(0);
const secondParameter = () => nodeParameters().find('.parameter-item').eq(1);
// Check correct fields are rendered
nodeParameters().should('exist');
// Test property text input
firstParameter().contains('Test property').should('exist');
firstParameter().find('input.el-input__inner').should('have.value', 'Some default');
// Resource select input
secondParameter().find('label').contains('Resource').should('exist');
secondParameter().find('input.el-input__inner').should('have.value', 'option2');
secondParameter().find('.el-select').click();
secondParameter().find('.el-select-dropdown__list').should('exist');
// Check if all options are rendered and select the fourth one
secondParameter().find('.el-select-dropdown__list').children().should('have.length', 4);
secondParameter()
.find('.el-select-dropdown__list')
.children()
.eq(3)
.contains('option4')
.should('exist')
.click();
secondParameter().find('input.el-input__inner').should('have.value', 'option4');
});
// Check correct fields are rendered
nodeParameters().should('exist');
// Test property text input
firstParameter().contains('Test property').should('exist');
firstParameter().find('input.el-input__inner').should('have.value', 'Some default');
// Resource select input
secondParameter().find('label').contains('Resource').should('exist');
secondParameter().find('input.el-input__inner').should('have.value', 'option2');
secondParameter().find('.el-select').click();
secondParameter().find('.el-select-dropdown__list').should('exist');
// Check if all options are rendered and select the fourth one
secondParameter().find('.el-select-dropdown__list').children().should('have.length', 4);
secondParameter()
.find('.el-select-dropdown__list')
.children()
.eq(3)
.contains('option4')
.should('exist')
.click();
secondParameter().find('input.el-input__inner').should('have.value', 'option4');
});
});

View File

@@ -1,22 +1,19 @@
import { WorkflowsPage, WorkflowPage, NDV } from '../pages';
import { WorkflowPage, NDV } from '../pages';
import { v4 as uuid } from 'uuid';
const workflowsPage = new WorkflowsPage();
const workflowPage = new WorkflowPage();
const ndv = new NDV();
describe('NDV', () => {
before(() => {
cy.resetAll();
cy.skipSetup();
});
beforeEach(() => {
workflowsPage.actions.createWorkflowFromCard();
cy.resetAll();
cy.skipSetup();
cy.visit(workflowPage.url)
cy.waitForLoad();
workflowPage.actions.renameWorkflow(uuid());
workflowPage.actions.saveWorkflowOnButtonClick();
});
it('should show up when double clicked on a node and close when Back to canvas clicked', () => {
workflowPage.actions.addInitialNodeToCanvas('Manual');
workflowPage.getters.canvasNodes().first().dblclick();
@@ -52,11 +49,12 @@ describe('NDV', () => {
workflowPage.getters.canvasNodes().last().dblclick();
ndv.getters.inputSelect().click();
ndv.getters.inputOption().last().click();
ndv.getters.inputDataContainer().find('[class*=schema_]').should('exist')
ndv.getters.inputDataContainer().should('contain', 'start');
});
it('should show correct validation state for resource locator params', () => {
workflowPage.actions.addNodeToCanvas('Typeform', true, false);
workflowPage.actions.addNodeToCanvas('Typeform', true, true);
ndv.getters.container().should('be.visible');
cy.get('.has-issues').should('have.length', 0);
cy.get('[class*=hasIssues]').should('have.length', 0);

View File

@@ -112,6 +112,9 @@ describe('Workflow Actions', () => {
});
it('should update workflow settings', () => {
cy.resetAll();
cy.skipSetup();
WorkflowPage.actions.visit();
// Open settings dialog
WorkflowPage.actions.saveWorkflowOnButtonClick();
WorkflowPage.getters.workflowMenu().should('be.visible');