mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-18 02:21:13 +00:00
feat(editor): Migrate Design System and Editor UI to Vue 3 (#6476)
* feat: remove vue-fragment (no-changelog) * feat: partial design-system migration * feat: migrate info-accordion and info-tip components * feat: migrate several components to vue 3 * feat: migrated several components * feat: migrate several components * feat: migrate several components * feat: migrate several components * feat: re-exported all design system components * fix: fix design for popper components * fix: editor kind of working, lots of issues to fix * fix: fix several vue 3 migration issues * fix: replace @change with @update:modelValue in several places * fix: fix translation linking * fix: fix inline-edit input * fix: fix ndv and dialog design * fix: update parameter input event bindings * fix: rename deprecated lifecycle methods * fix: fix json view mapping * build: update lock file * fix(editor): revisit last conflict with master and fix issues * fix(editor): revisit last conflict with master and fix issues * fix: fix expression editor bug causing code mirror to no longer be reactive * fix: fix resource locator bug * fix: fix vue-agile integration * fix: remove global import for vue-agile * fix: replace element-plus buttons with n8n-buttons everywhere * fix(editor): Fix various element-plus styles (#6571) * fix(editor): Fix various element-plus styles Signed-off-by: Oleg Ivaniv <me@olegivaniv.com> * Remove debugging code Signed-off-by: Oleg Ivaniv <me@olegivaniv.com> * Address PR comments Signed-off-by: Oleg Ivaniv <me@olegivaniv.com> --------- Signed-off-by: Oleg Ivaniv <me@olegivaniv.com> * fix(editor): Fix loading in production mode [Vue 3] (#6578) Signed-off-by: Oleg Ivaniv <me@olegivaniv.com> * fix(editor): First round of e2e tests fixes with Vue 3 (#6579) * fix(editor): Fix broken smoke and workflow list e2e tests * ✔️ Fix failing canvas action tests. Updating some selectors used in credentials and workflow tests * feat: add vue 3 eslint rules and fix issues * fix: fix tags-dropdown * fix: fix white-space issues caused by i18n-t * fix: rename non-generic click events * fix: fix search in resources list layout * fix: fix datatable paginator * fix: fix popper select caret and dropdown size * fix: add width to action-dropdown * fix: fix workflow settings icon not being hidden * fix: refactor newly added code * fix: fix merge issue * fix: fix ndv credentials watcher * fix: fix workflow saving and grabber notch * fix: fix nodes list panel transition * fix: fix node title visibility * fix: fix data unpinning * fix: fix value access * fix: show input panel only if trigger panel enabled or not trigger node * fix: fix tags dropdown and executions status spcing * fix(editor): Prevent execution list to load back when leaving the route (#6697) fix(editor): prevent execution list to load back when leaving the route * fix: fix drawer visibility * fix: fix expression toggle padding * fix: fix expressions editor styling * chore: prepare for testing * fix: fix styling for el-button without patching * test: fix unit tests in design-system * test: fix most unit tests * fix: remove import cycle. * fix: fix personalization modal tests * fix further resource mapper test adjustments * fix: fix multiple tests and n8n-route attr duplication * fix: fix source control tets * fix: fixed remaining unit tests * fix: fix workflows and credentials e2e tests * fix: fix localizeNodeNames * fix: update ndv e2e tests * fix: fix popper left placement arrow * fix: fix 5-ndv e2e tests * fix: fix 6-code-node e2e tests * fix(editor): Drop click outside directive from NodeCreator (#6716) * fix(editor): Drop click outside directive from NodeCreator * fix(editor): make sure mouseup outside is unbound at least before the component is unmounted * fix: fix 10-settings-log-streaming e2e tests * fix: fix node redrawing * fix: fix tooltip buttons styling * fix: fix varous e2e suites * fix: fix 15-scheduler-node e2e suite * fix: fix route watcher * fix: fixed param name update and credential edit * feat: update event names * refactor: Remove deprecated `$data` (#6576) Co-authored-by: Alex Grozav <alex@grozav.com> * fix: fix 17-sharing e2e suite * fix: fix tags dropdown * fix: fix tags manager * fix(editor): move :deep selectors to a separate scoped style block * fix: fix sticky component and inline text edit * fix: update e2e tests * fix: remove button override references * fix(editor): Adjust spacing in templates for Vue 3 (#6744) * fix(editor): Adjust spacing in templates * fix: Undo unneeded change * fix: Undo unneeded change * fix(editor): Adjust NDV height for Vue 3 (#6742) fix(editor): Adjust NDV height * fix(editor): Restore collapsed sidebar items for Vue 3 (#6743) fix(editor): Restore collapsed sidebar items * fix: fix linting issues * fix: fix design-system deps * fix: post-merge fixes * fix: update tests * fix: increase timeout for executionslist tets * chore: fix linting issue * fix: fix 14-mapping e2e tests in ci * fix: re-enable tests * fix: fix workflow duplication e2e tests after tags update * fix(editor): Change component prop to be typed * fix: fix tags dropdown in duplicate wf modal * fix: fix focus behaviour in tags selector * fix: fix tag creation * fix: fix log streaming e2e race condition * fix(editor): Fix Vue 3 linting issues (#6748) * fix(editor): Fix Vue 3 linting issues Signed-off-by: Oleg Ivaniv <me@olegivaniv.com> * fix MainSidebar linter issues * revert pnpm lock * update pnpm lock file --------- Signed-off-by: Oleg Ivaniv <me@olegivaniv.com> Co-authored-by: Alex Grozav <alex@grozav.com> * fix(editor): Some css fixes for vue3 branch (#6749) * ✨ Fixing filter button height * ✨ Update input modal button position * ✨ Updating tags styling * ✨ Fix event logging settings spacing * 👕 Fixing lint errors * fix: fix linting issues * Revert to `// eslint-disable-next-line @typescript-eslint/no-misused-promises` disabling of mixins init Signed-off-by: Oleg Ivaniv <me@olegivaniv.com> * fix: fix css issue * fix(editor): Lint fix * fix(editor): Fix settings initialisation (#6750) Signed-off-by: Oleg Ivaniv <me@olegivaniv.com> * fix: fix initial settings loading * fix: replace realClick with click force * fix: fix randomly failing mapping e2e tests * fix(editor): Fix menu item event handling * fix: fix resource filters dropdown events (#6752) * fix: fix resource filters dropdown events * fix: remove teleported:false * fix: fix event selection event naming (#6753) * fix: removed console.log (#6754) * fix: rever await nextTick changes * fix: redo linting changes * fix(editor): Redraw node connections if adding more than one node to canvas (#6755) * fix(editor): Redraw node connections if adding more than one node to canvas Signed-off-by: Oleg Ivaniv <me@olegivaniv.com> * Update position before connection two nodes * Lint fix --------- Signed-off-by: Oleg Ivaniv <me@olegivaniv.com> Co-authored-by: Alex Grozav <alex@grozav.com> * fix(editor): Fix `ResourceMapper` unit tests (#6758) * ✔️ Fix matching columns test * ✔️ Fix multiple matching columns test * ✔️ Removing `skip` from the last test * fix: Allow pasting a big workflow (#6760) * fix: pasting a big workflow * chore: update comment * refactor: move try/catch to function * refactor: move try/catch to function * fix(editor): Fix modal layer width * fix: fix position changes * fix: undo it.only * fix: make undo/redo multiple steps more verbose * fix: Fix value survey styles (#6764) * fix: fix value survey styles * fix: lint * Revert "fix: lint" 72869c431f1448861df021be041b61c62f1e3118 * fix: lint * fix(editor): Fix collapsed sub menu * fix: Fix drawer animation (#6767) fix: drawer animation * fix(editor): Fix source control buttons (#6769) * fix(editor): Fix App loading & auth (#6768) * fix(editor): Fix App loading & auth Signed-off-by: Oleg Ivaniv <me@olegivaniv.com> * Await promises Signed-off-by: Oleg Ivaniv <me@olegivaniv.com> * Fix eslint error Signed-off-by: Oleg Ivaniv <me@olegivaniv.com> --------- Signed-off-by: Oleg Ivaniv <me@olegivaniv.com> --------- Signed-off-by: Oleg Ivaniv <me@olegivaniv.com> Co-authored-by: Csaba Tuncsik <csaba@n8n.io> Co-authored-by: OlegIvaniv <me@olegivaniv.com> Co-authored-by: Milorad FIlipović <milorad@n8n.io> Co-authored-by: Iván Ovejero <ivov.src@gmail.com> Co-authored-by: Mutasem Aldmour <4711238+mutdmour@users.noreply.github.com>
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
import { SettingsLogStreamingPage } from '../pages';
|
||||
import { getVisibleModalOverlay } from '../utils/modal';
|
||||
import { getVisibleDropdown } from '../utils';
|
||||
|
||||
const settingsLogStreamingPage = new SettingsLogStreamingPage();
|
||||
|
||||
@@ -19,6 +21,7 @@ describe('Log Streaming Settings', () => {
|
||||
});
|
||||
|
||||
it('should show the add destination modal', () => {
|
||||
cy.enableFeature('logStreaming');
|
||||
cy.visit('/settings/log-streaming');
|
||||
settingsLogStreamingPage.actions.clickAddFirstDestination();
|
||||
cy.wait(100);
|
||||
@@ -27,7 +30,7 @@ describe('Log Streaming Settings', () => {
|
||||
settingsLogStreamingPage.getters.getSelectDestinationButton().should('be.visible');
|
||||
settingsLogStreamingPage.getters.getSelectDestinationButton().should('have.attr', 'disabled');
|
||||
settingsLogStreamingPage.getters
|
||||
.getDestinationModalDialog()
|
||||
.getDestinationModal()
|
||||
.invoke('css', 'width')
|
||||
.then((widthStr) => parseInt((widthStr as unknown as string).replace('px', '')))
|
||||
.should('be.lessThan', 500);
|
||||
@@ -36,65 +39,67 @@ describe('Log Streaming Settings', () => {
|
||||
settingsLogStreamingPage.getters
|
||||
.getSelectDestinationButton()
|
||||
.should('not.have.attr', 'disabled');
|
||||
settingsLogStreamingPage.getters.getDestinationModal().click(1, 1);
|
||||
getVisibleModalOverlay().click(1, 1);
|
||||
settingsLogStreamingPage.getters.getDestinationModal().should('not.exist');
|
||||
});
|
||||
|
||||
it('should create a destination and delete it', () => {
|
||||
cy.enableFeature('logStreaming');
|
||||
cy.visit('/settings/log-streaming');
|
||||
cy.wait(1000); // Race condition with getDestinationDataFromBackend()
|
||||
settingsLogStreamingPage.actions.clickAddFirstDestination();
|
||||
cy.wait(100);
|
||||
settingsLogStreamingPage.getters.getDestinationModal().should('be.visible');
|
||||
settingsLogStreamingPage.getters.getSelectDestinationType().click();
|
||||
settingsLogStreamingPage.getters.getSelectDestinationTypeItems().eq(0).click();
|
||||
settingsLogStreamingPage.getters.getSelectDestinationButton().click();
|
||||
settingsLogStreamingPage.getters.getDestinationNameInput().click()
|
||||
settingsLogStreamingPage.getters.getDestinationNameInput().click();
|
||||
|
||||
settingsLogStreamingPage.getters.getDestinationNameInput().find('input').clear().type('Destination 0');
|
||||
settingsLogStreamingPage.getters
|
||||
.getDestinationNameInput()
|
||||
.find('input')
|
||||
.clear()
|
||||
.type('Destination 0');
|
||||
settingsLogStreamingPage.getters.getDestinationSaveButton().click();
|
||||
cy.wait(100);
|
||||
settingsLogStreamingPage.getters.getDestinationModal().click(1, 1);
|
||||
getVisibleModalOverlay().click(1, 1);
|
||||
cy.reload();
|
||||
settingsLogStreamingPage.getters.getDestinationCards().eq(0).click();
|
||||
settingsLogStreamingPage.getters.getDestinationDeleteButton().should('be.visible').click();
|
||||
cy.get('.el-message-box').should('be.visible').find('.btn--cancel').click();
|
||||
settingsLogStreamingPage.getters.getDestinationDeleteButton().click();
|
||||
cy.get('.el-message-box').should('be.visible').find('.btn--confirm').click();
|
||||
cy.reload();
|
||||
});
|
||||
|
||||
it('should create a destination and delete it via card actions', () => {
|
||||
cy.enableFeature('logStreaming');
|
||||
cy.visit('/settings/log-streaming');
|
||||
cy.wait(1000); // Race condition with getDestinationDataFromBackend()
|
||||
settingsLogStreamingPage.actions.clickAddFirstDestination();
|
||||
cy.wait(100);
|
||||
settingsLogStreamingPage.getters.getDestinationModal().should('be.visible');
|
||||
settingsLogStreamingPage.getters.getSelectDestinationType().click();
|
||||
settingsLogStreamingPage.getters.getSelectDestinationTypeItems().eq(0).click();
|
||||
settingsLogStreamingPage.getters.getSelectDestinationButton().click();
|
||||
settingsLogStreamingPage.getters.getDestinationNameInput().click()
|
||||
settingsLogStreamingPage.getters.getDestinationNameInput().find('input').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);
|
||||
settingsLogStreamingPage.getters.getDestinationModal().click(1, 1);
|
||||
getVisibleModalOverlay().click(1, 1);
|
||||
cy.reload();
|
||||
|
||||
settingsLogStreamingPage.getters
|
||||
.getDestinationCards()
|
||||
.eq(0)
|
||||
.find('.el-dropdown-selfdefine')
|
||||
.click();
|
||||
cy.get('.el-dropdown-menu').find('.el-dropdown-menu__item').eq(0).click();
|
||||
settingsLogStreamingPage.getters.getDestinationCards().eq(0).find('.el-dropdown').click();
|
||||
getVisibleDropdown().find('.el-dropdown-menu__item').eq(0).click();
|
||||
settingsLogStreamingPage.getters.getDestinationSaveButton().should('not.exist');
|
||||
settingsLogStreamingPage.getters.getDestinationModal().click(1, 1);
|
||||
getVisibleModalOverlay().click(1, 1);
|
||||
|
||||
settingsLogStreamingPage.getters
|
||||
.getDestinationCards()
|
||||
.eq(0)
|
||||
.find('.el-dropdown-selfdefine')
|
||||
.click();
|
||||
cy.get('.el-dropdown-menu').find('.el-dropdown-menu__item').eq(1).click();
|
||||
settingsLogStreamingPage.getters.getDestinationCards().eq(0).find('.el-dropdown').click();
|
||||
getVisibleDropdown().find('.el-dropdown-menu__item').eq(1).click();
|
||||
cy.get('.el-message-box').should('be.visible').find('.btn--confirm').click();
|
||||
cy.reload();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -119,18 +119,15 @@ describe('Undo/Redo', () => {
|
||||
WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME);
|
||||
cy.drag('[data-test-id="canvas-node"].jtk-drag-selected', [50, 150]);
|
||||
WorkflowPage.getters
|
||||
.canvasNodes()
|
||||
.last()
|
||||
.canvasNodeByName('Code')
|
||||
.should('have.attr', 'style', 'left: 740px; top: 320px;');
|
||||
WorkflowPage.actions.hitUndo();
|
||||
WorkflowPage.getters
|
||||
.canvasNodes()
|
||||
.last()
|
||||
.canvasNodeByName('Code')
|
||||
.should('have.attr', 'style', 'left: 640px; top: 220px;');
|
||||
WorkflowPage.actions.hitRedo();
|
||||
WorkflowPage.getters
|
||||
.canvasNodes()
|
||||
.last()
|
||||
.canvasNodeByName('Code')
|
||||
.should('have.attr', 'style', 'left: 740px; top: 320px;');
|
||||
});
|
||||
|
||||
@@ -138,7 +135,10 @@ describe('Undo/Redo', () => {
|
||||
WorkflowPage.actions.addNodeToCanvas(SCHEDULE_TRIGGER_NODE_NAME);
|
||||
WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME);
|
||||
WorkflowPage.getters.nodeConnections().realHover();
|
||||
cy.get('.connection-actions .delete').filter(':visible').should('be.visible').click();
|
||||
cy.get('.connection-actions .delete')
|
||||
.filter(':visible')
|
||||
.should('be.visible')
|
||||
.click({ force: true });
|
||||
WorkflowPage.getters.nodeConnections().should('have.length', 0);
|
||||
WorkflowPage.actions.hitUndo();
|
||||
WorkflowPage.getters.nodeConnections().should('have.length', 1);
|
||||
@@ -256,6 +256,9 @@ describe('Undo/Redo', () => {
|
||||
});
|
||||
|
||||
it('should undo/redo multiple steps', () => {
|
||||
const initialPosition = 'left: 420px; top: 220px;';
|
||||
const movedPosition = 'left: 540px; top: 360px;';
|
||||
|
||||
WorkflowPage.actions.addNodeToCanvas(SCHEDULE_TRIGGER_NODE_NAME);
|
||||
WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME);
|
||||
WorkflowPage.actions.addNodeToCanvas(SET_NODE_NAME);
|
||||
@@ -266,8 +269,10 @@ describe('Undo/Redo', () => {
|
||||
WorkflowPage.getters.canvasNodes().last().click();
|
||||
WorkflowPage.actions.hitDisableNodeShortcut();
|
||||
// Move first one
|
||||
WorkflowPage.getters.canvasNodes().first().should('have.attr', 'style', initialPosition);
|
||||
WorkflowPage.getters.canvasNodes().first().click();
|
||||
cy.drag('[data-test-id="canvas-node"].jtk-drag-selected', [50, 150]);
|
||||
WorkflowPage.getters.canvasNodes().first().should('have.attr', 'style', movedPosition);
|
||||
// Delete the set node
|
||||
WorkflowPage.getters.canvasNodeByName(SET_NODE_NAME).click().click();
|
||||
cy.get('body').type('{backspace}');
|
||||
@@ -278,10 +283,7 @@ describe('Undo/Redo', () => {
|
||||
WorkflowPage.getters.nodeConnections().should('have.length', 3);
|
||||
// Second undo: Should move first node to it's original position
|
||||
WorkflowPage.actions.hitUndo();
|
||||
WorkflowPage.getters
|
||||
.canvasNodes()
|
||||
.first()
|
||||
.should('have.attr', 'style', 'left: 420px; top: 220px;');
|
||||
WorkflowPage.getters.canvasNodes().first().should('have.attr', 'style', initialPosition);
|
||||
// Third undo: Should enable last node
|
||||
WorkflowPage.actions.hitUndo();
|
||||
WorkflowPage.getters.disabledNodes().should('have.length', 0);
|
||||
@@ -291,10 +293,7 @@ describe('Undo/Redo', () => {
|
||||
WorkflowPage.getters.disabledNodes().should('have.length', 1);
|
||||
// Second redo: Should move the first node
|
||||
WorkflowPage.actions.hitRedo();
|
||||
WorkflowPage.getters
|
||||
.canvasNodes()
|
||||
.first()
|
||||
.should('have.attr', 'style', 'left: 540px; top: 360px;');
|
||||
WorkflowPage.getters.canvasNodes().first().should('have.attr', 'style', movedPosition);
|
||||
// Third redo: Should delete the Set node
|
||||
WorkflowPage.actions.hitRedo();
|
||||
WorkflowPage.getters.canvasNodes().should('have.length', 3);
|
||||
|
||||
@@ -66,7 +66,6 @@ describe('Canvas Actions', () => {
|
||||
WorkflowPage.getters.nodeViewBackground().click({ force: true });
|
||||
});
|
||||
|
||||
|
||||
it('should add a connected node using plus endpoint', () => {
|
||||
WorkflowPage.actions.addNodeToCanvas(MANUAL_TRIGGER_NODE_NAME);
|
||||
cy.get('.plus-endpoint').should('be.visible').click();
|
||||
|
||||
@@ -107,7 +107,7 @@ describe('Canvas Node Manipulation and Navigation', () => {
|
||||
WorkflowPage.actions.zoomToFit();
|
||||
|
||||
cy.get('.plus-draggable-endpoint').filter(':visible').should('not.have.class', 'ep-success');
|
||||
cy.get('.jtk-connector.success').should('have.length', 4);
|
||||
cy.get('.jtk-connector.success').should('have.length', 3);
|
||||
cy.get('.jtk-connector').should('have.length', 4);
|
||||
});
|
||||
|
||||
|
||||
@@ -7,12 +7,10 @@ describe('Data transformation expressions', () => {
|
||||
beforeEach(() => {
|
||||
wf.actions.visit();
|
||||
|
||||
cy.window().then(
|
||||
(win) => {
|
||||
// @ts-ignore
|
||||
win.preventNodeViewBeforeUnload = true;
|
||||
},
|
||||
);
|
||||
cy.window().then((win) => {
|
||||
// @ts-ignore
|
||||
win.preventNodeViewBeforeUnload = true;
|
||||
});
|
||||
});
|
||||
|
||||
it('$json + native string methods', () => {
|
||||
@@ -85,7 +83,7 @@ describe('Data transformation expressions', () => {
|
||||
|
||||
ndv.getters.inlineExpressionEditorInput().clear().type(input);
|
||||
ndv.actions.execute();
|
||||
ndv.getters.outputDataContainer().find('[class*=value_]').should('exist')
|
||||
ndv.getters.outputDataContainer().find('[class*=value_]').should('exist');
|
||||
ndv.getters.outputDataContainer().find('[class*=value_]').should('contain', output);
|
||||
});
|
||||
|
||||
@@ -100,7 +98,7 @@ describe('Data transformation expressions', () => {
|
||||
|
||||
ndv.getters.inlineExpressionEditorInput().clear().type(input);
|
||||
ndv.actions.execute();
|
||||
ndv.getters.outputDataContainer().find('[class*=value_]').should('exist')
|
||||
ndv.getters.outputDataContainer().find('[class*=value_]').should('exist');
|
||||
ndv.getters.outputDataContainer().find('[class*=value_]').should('contain', output);
|
||||
});
|
||||
});
|
||||
@@ -111,7 +109,7 @@ describe('Data transformation expressions', () => {
|
||||
|
||||
const addSet = () => {
|
||||
wf.actions.addNodeToCanvas('Set', true, true);
|
||||
ndv.getters.parameterInput('keepOnlySet').find('div[role=switch]').click(); // shorten output
|
||||
ndv.getters.parameterInput('keepOnlySet').find('.el-switch').click(); // shorten output
|
||||
cy.get('input[placeholder="Add Value"]').click();
|
||||
cy.get('span').contains('String').click();
|
||||
ndv.getters.nthParam(3).contains('Expression').invoke('show').click(); // Values to Set > String > Value
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
SCHEDULE_TRIGGER_NODE_NAME,
|
||||
} from './../constants';
|
||||
import { WorkflowPage, NDV } from '../pages';
|
||||
import { getVisibleSelect } from '../utils';
|
||||
|
||||
const workflowPage = new WorkflowPage();
|
||||
const ndv = new NDV();
|
||||
@@ -28,11 +29,7 @@ describe('Data mapping', () => {
|
||||
ndv.getters.inputDataContainer().get('table', { timeout: 10000 }).should('exist');
|
||||
|
||||
ndv.getters.nodeParameters().find('input[placeholder*="Add Value"]').click();
|
||||
ndv.getters
|
||||
.nodeParameters()
|
||||
.find('.el-select-dropdown__list li:nth-child(3)')
|
||||
.should('have.text', 'String')
|
||||
.click();
|
||||
getVisibleSelect().find('li:nth-child(3)').should('have.text', 'String').click();
|
||||
ndv.getters
|
||||
.parameterInput('name')
|
||||
.should('have.length', 1)
|
||||
@@ -128,7 +125,7 @@ describe('Data mapping', () => {
|
||||
.find('.json-data')
|
||||
.should(
|
||||
'have.text',
|
||||
'[{"input":[{"count":0,"with space":"!!","with.dot":"!!","with"quotes":"!!"}]},{"input":[{"count":1}]}]',
|
||||
'[{"input": [{"count": 0,"with space": "!!","with.dot": "!!","with"quotes": "!!"}]},{"input": [{"count": 1}]}]',
|
||||
)
|
||||
.find('span')
|
||||
.contains('"count"')
|
||||
@@ -178,6 +175,7 @@ describe('Data mapping', () => {
|
||||
|
||||
it('maps expressions from previous nodes', () => {
|
||||
cy.createFixtureWorkflow('Test_workflow_3.json', `My test workflow`);
|
||||
workflowPage.actions.zoomToFit();
|
||||
workflowPage.actions.openNode('Set1');
|
||||
|
||||
ndv.actions.selectInputNode(SCHEDULE_TRIGGER_NODE_NAME);
|
||||
@@ -245,7 +243,8 @@ describe('Data mapping', () => {
|
||||
workflowPage.actions.addNodeToCanvas('Item Lists');
|
||||
workflowPage.actions.openNode('Item Lists');
|
||||
|
||||
ndv.getters.parameterInput('operation').click().find('li').contains('Sort').click();
|
||||
ndv.getters.parameterInput('operation').click();
|
||||
getVisibleSelect().find('li').contains('Sort').click();
|
||||
|
||||
ndv.getters.nodeParameters().find('button').contains('Add Field To Sort By').click();
|
||||
|
||||
@@ -274,6 +273,8 @@ describe('Data mapping', () => {
|
||||
|
||||
ndv.actions.typeIntoParameterInput('value', 'fun');
|
||||
ndv.actions.clearParameterInput('value'); // keep focus on param
|
||||
ndv.actions.dismissMappingTooltip();
|
||||
cy.wait(300);
|
||||
|
||||
ndv.getters.inputDataContainer().should('exist').find('span').contains('count').realMouseDown();
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { WorkflowPage, WorkflowsPage, NDV } from '../pages';
|
||||
import { BACKEND_BASE_URL } from '../constants';
|
||||
import { getVisibleSelect } from '../utils';
|
||||
|
||||
const workflowsPage = new WorkflowsPage();
|
||||
const workflowPage = new WorkflowPage();
|
||||
@@ -24,11 +25,7 @@ describe('Schedule Trigger node', async () => {
|
||||
workflowPage.actions.openNode('Schedule Trigger');
|
||||
|
||||
cy.getByTestId('parameter-input-field').click();
|
||||
cy.getByTestId('parameter-input-field')
|
||||
.find('.el-select-dropdown')
|
||||
.find('.option-headline')
|
||||
.contains('Seconds')
|
||||
.click();
|
||||
getVisibleSelect().find('.option-headline').contains('Seconds').click();
|
||||
cy.getByTestId('parameter-input-secondsInterval').clear().type('1');
|
||||
|
||||
ndv.getters.backToCanvas().click();
|
||||
|
||||
@@ -2,6 +2,7 @@ import { WorkflowPage, NDV, CredentialsModal } from '../pages';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { cowBase64 } from '../support/binaryTestFiles';
|
||||
import { BACKEND_BASE_URL } from '../constants';
|
||||
import { getVisibleSelect } from '../utils';
|
||||
|
||||
const workflowPage = new WorkflowPage();
|
||||
const ndv = new NDV();
|
||||
@@ -34,11 +35,7 @@ const simpleWebhookCall = (options: SimpleWebhookCallOptions) => {
|
||||
workflowPage.actions.openNode('Webhook');
|
||||
|
||||
cy.getByTestId('parameter-input-httpMethod').click();
|
||||
cy.getByTestId('parameter-input-httpMethod')
|
||||
.find('.el-select-dropdown')
|
||||
.find('.option-headline')
|
||||
.contains(method)
|
||||
.click();
|
||||
getVisibleSelect().find('.option-headline').contains(method).click();
|
||||
cy.getByTestId('parameter-input-path')
|
||||
.find('.parameter-input')
|
||||
.find('input')
|
||||
@@ -47,11 +44,7 @@ const simpleWebhookCall = (options: SimpleWebhookCallOptions) => {
|
||||
|
||||
if (authentication) {
|
||||
cy.getByTestId('parameter-input-authentication').click();
|
||||
cy.getByTestId('parameter-input-authentication')
|
||||
.find('.el-select-dropdown')
|
||||
.find('.option-headline')
|
||||
.contains(authentication)
|
||||
.click();
|
||||
getVisibleSelect().find('.option-headline').contains(authentication).click();
|
||||
}
|
||||
|
||||
if (responseCode) {
|
||||
@@ -64,20 +57,12 @@ const simpleWebhookCall = (options: SimpleWebhookCallOptions) => {
|
||||
|
||||
if (respondWith) {
|
||||
cy.getByTestId('parameter-input-responseMode').click();
|
||||
cy.getByTestId('parameter-input-responseMode')
|
||||
.find('.el-select-dropdown')
|
||||
.find('.option-headline')
|
||||
.contains(respondWith)
|
||||
.click();
|
||||
getVisibleSelect().find('.option-headline').contains(respondWith).click();
|
||||
}
|
||||
|
||||
if (responseData) {
|
||||
cy.getByTestId('parameter-input-responseData').click();
|
||||
cy.getByTestId('parameter-input-responseData')
|
||||
.find('.el-select-dropdown')
|
||||
.find('.option-headline')
|
||||
.contains(responseData)
|
||||
.click();
|
||||
getVisibleSelect().find('.option-headline').contains(responseData).click();
|
||||
}
|
||||
|
||||
if (executeNow) {
|
||||
@@ -136,13 +121,13 @@ describe('Webhook Trigger node', async () => {
|
||||
workflowPage.actions.addNodeToCanvas('Set');
|
||||
workflowPage.actions.openNode('Set');
|
||||
cy.get('.add-option').click();
|
||||
cy.get('.add-option').find('.el-select-dropdown__item').contains('Number').click();
|
||||
getVisibleSelect().find('.el-select-dropdown__item').contains('Number').click();
|
||||
cy.get('.fixed-collection-parameter')
|
||||
.getByTestId('parameter-input-name')
|
||||
.clear()
|
||||
.type('MyValue');
|
||||
cy.get('.fixed-collection-parameter').getByTestId('parameter-input-value').clear().type('1234');
|
||||
ndv.getters.backToCanvas().click();
|
||||
ndv.getters.backToCanvas().click({ force: true });
|
||||
|
||||
workflowPage.actions.addNodeToCanvas('Respond to Webhook');
|
||||
|
||||
@@ -185,13 +170,18 @@ describe('Webhook Trigger node', async () => {
|
||||
workflowPage.actions.addNodeToCanvas('Set');
|
||||
workflowPage.actions.openNode('Set');
|
||||
cy.get('.add-option').click();
|
||||
cy.get('.add-option').find('.el-select-dropdown__item').contains('Number').click();
|
||||
getVisibleSelect().find('.el-select-dropdown__item').contains('Number').click();
|
||||
cy.get('.fixed-collection-parameter')
|
||||
.getByTestId('parameter-input-name')
|
||||
.find('input')
|
||||
.clear()
|
||||
.type('MyValue');
|
||||
cy.get('.fixed-collection-parameter').getByTestId('parameter-input-value').clear().type('1234');
|
||||
ndv.getters.backToCanvas().click();
|
||||
cy.get('.fixed-collection-parameter')
|
||||
.getByTestId('parameter-input-value')
|
||||
.find('input')
|
||||
.clear()
|
||||
.type('1234');
|
||||
ndv.getters.backToCanvas().click({ force: true });
|
||||
|
||||
workflowPage.actions.executeWorkflow();
|
||||
cy.wait(waitForWebhook);
|
||||
@@ -216,7 +206,7 @@ describe('Webhook Trigger node', async () => {
|
||||
workflowPage.actions.addNodeToCanvas('Set');
|
||||
workflowPage.actions.openNode('Set');
|
||||
cy.get('.add-option').click();
|
||||
cy.get('.add-option').find('.el-select-dropdown__item').contains('String').click();
|
||||
getVisibleSelect().find('.el-select-dropdown__item').contains('String').click();
|
||||
cy.get('.fixed-collection-parameter').getByTestId('parameter-input-name').clear().type('data');
|
||||
cy.get('.fixed-collection-parameter')
|
||||
.getByTestId('parameter-input-value')
|
||||
@@ -231,11 +221,7 @@ describe('Webhook Trigger node', async () => {
|
||||
|
||||
workflowPage.actions.openNode('Move Binary Data');
|
||||
cy.getByTestId('parameter-input-mode').click();
|
||||
cy.getByTestId('parameter-input-mode')
|
||||
.find('.el-select-dropdown')
|
||||
.find('.option-headline')
|
||||
.contains('JSON to Binary')
|
||||
.click();
|
||||
getVisibleSelect().find('.option-headline').contains('JSON to Binary').click();
|
||||
ndv.getters.backToCanvas().click();
|
||||
|
||||
workflowPage.actions.executeWorkflow();
|
||||
@@ -274,7 +260,7 @@ describe('Webhook Trigger node', async () => {
|
||||
});
|
||||
// add credentials
|
||||
workflowPage.getters.nodeCredentialsSelect().click();
|
||||
workflowPage.getters.nodeCredentialsSelect().find('li').last().click();
|
||||
getVisibleSelect().find('li').last().click();
|
||||
credentialsModal.getters.credentialsEditModal().should('be.visible');
|
||||
credentialsModal.actions.fillCredentialsForm();
|
||||
|
||||
@@ -317,7 +303,7 @@ describe('Webhook Trigger node', async () => {
|
||||
});
|
||||
// add credentials
|
||||
workflowPage.getters.nodeCredentialsSelect().click();
|
||||
workflowPage.getters.nodeCredentialsSelect().find('li').last().click();
|
||||
getVisibleSelect().find('li').last().click();
|
||||
credentialsModal.getters.credentialsEditModal().should('be.visible');
|
||||
credentialsModal.actions.fillCredentialsForm();
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ describe('Sharing', { disableAutoLogin: true }, () => {
|
||||
workflowPage.actions.setWorkflowName('Workflow W1');
|
||||
workflowPage.actions.addInitialNodeToCanvas('Manual Trigger');
|
||||
workflowPage.actions.addNodeToCanvas('Notion', true, true);
|
||||
ndv.getters.credentialInput().should('contain', 'Credential C1');
|
||||
ndv.getters.credentialInput().find('input').should('have.value', 'Credential C1');
|
||||
ndv.actions.close();
|
||||
|
||||
workflowPage.actions.openShareModal();
|
||||
@@ -87,16 +87,12 @@ describe('Sharing', { disableAutoLogin: true }, () => {
|
||||
workflowsPage.getters.workflowCards().should('have.length', 1);
|
||||
workflowsPage.getters.workflowCard('Workflow W1').click();
|
||||
workflowPage.actions.addNodeToCanvas('Airtable', true, true);
|
||||
ndv.getters.credentialInput().should('contain', 'Credential C2');
|
||||
ndv.getters.credentialInput().find('input').should('have.value', 'Credential C2');
|
||||
ndv.actions.close();
|
||||
workflowPage.actions.saveWorkflowOnButtonClick();
|
||||
|
||||
workflowPage.actions.openNode('Notion');
|
||||
ndv.getters
|
||||
.credentialInput()
|
||||
.find('input')
|
||||
.should('have.value', 'Credential C1')
|
||||
.should('be.disabled');
|
||||
ndv.getters.credentialInput().should('have.value', 'Credential C1').should('be.disabled');
|
||||
ndv.actions.close();
|
||||
});
|
||||
|
||||
@@ -116,11 +112,7 @@ describe('Sharing', { disableAutoLogin: true }, () => {
|
||||
workflowsPage.getters.workflowCards().should('have.length', 2);
|
||||
workflowsPage.getters.workflowCard('Workflow W1').click();
|
||||
workflowPage.actions.openNode('Notion');
|
||||
ndv.getters
|
||||
.credentialInput()
|
||||
.find('input')
|
||||
.should('have.value', 'Credential C1')
|
||||
.should('be.disabled');
|
||||
ndv.getters.credentialInput().should('have.value', 'Credential C1').should('be.disabled');
|
||||
ndv.actions.close();
|
||||
|
||||
cy.waitForLoad();
|
||||
|
||||
@@ -30,7 +30,7 @@ describe('Workflow tags', () => {
|
||||
}
|
||||
cy.contains('Done').click();
|
||||
|
||||
wf.getters.createTagButton().click();
|
||||
wf.getters.tagsDropdown().click();
|
||||
wf.getters.tagsInDropdown().should('have.length', 5);
|
||||
wf.getters.tagPills().should('have.length', 0); // none attached
|
||||
});
|
||||
@@ -45,7 +45,7 @@ describe('Workflow tags', () => {
|
||||
});
|
||||
|
||||
cy.contains('Done').click();
|
||||
wf.getters.createTagButton().click();
|
||||
wf.getters.tagsDropdown().click();
|
||||
wf.getters.tagsInDropdown().should('have.length', 0); // none stored
|
||||
wf.getters.tagPills().should('have.length', 0); // none attached
|
||||
});
|
||||
@@ -57,7 +57,8 @@ describe('Workflow tags', () => {
|
||||
|
||||
cy.contains('Create a tag').click();
|
||||
cy.getByTestId('tags-table').find('input').type(first).type('{enter}');
|
||||
cy.getByTestId('edit-tag-button').click({ force: true });
|
||||
cy.getByTestId('tags-table').should('contain.text', first);
|
||||
cy.getByTestId('edit-tag-button').eq(-1).click({ force: true });
|
||||
cy.wait(300);
|
||||
cy.getByTestId('tags-table')
|
||||
.find('.el-input--large')
|
||||
@@ -65,7 +66,7 @@ describe('Workflow tags', () => {
|
||||
.type(' Updated')
|
||||
.type('{enter}');
|
||||
cy.contains('Done').click();
|
||||
wf.getters.createTagButton().click();
|
||||
wf.getters.tagsDropdown().click();
|
||||
wf.getters.tagsInDropdown().should('have.length', 1); // one stored
|
||||
wf.getters.tagsInDropdown().contains('Updated').should('exist');
|
||||
wf.getters.tagPills().should('have.length', 0); // none attached
|
||||
@@ -76,7 +77,7 @@ describe('Workflow tags', () => {
|
||||
wf.actions.addTags(TEST_TAGS);
|
||||
wf.getters.nthTagPill(1).click();
|
||||
wf.getters.tagsDropdown().find('.el-tag__close').first().click();
|
||||
cy.get('body').type('{enter}');
|
||||
cy.get('body').click(0, 0);
|
||||
wf.getters.tagPills().should('have.length', TEST_TAGS.length - 1);
|
||||
});
|
||||
|
||||
@@ -84,8 +85,8 @@ describe('Workflow tags', () => {
|
||||
wf.getters.createTagButton().click();
|
||||
wf.actions.addTags(TEST_TAGS);
|
||||
wf.getters.nthTagPill(1).click();
|
||||
wf.getters.tagsDropdown().find('li.selected').first().click();
|
||||
cy.get('body').type('{enter}');
|
||||
wf.getters.tagsInDropdown().filter('.selected').first().click();
|
||||
cy.get('body').click(0, 0);
|
||||
wf.getters.tagPills().should('have.length', TEST_TAGS.length - 1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -58,19 +58,19 @@ describe('User Management', { disableAutoLogin: true }, () => {
|
||||
it('should delete user and their data', () => {
|
||||
usersSettingsPage.actions.loginAndVisit(INSTANCE_OWNER.email, INSTANCE_OWNER.password, true);
|
||||
usersSettingsPage.actions.opedDeleteDialog(INSTANCE_MEMBERS[0].email);
|
||||
usersSettingsPage.getters.deleteDataRadioButton().realClick();
|
||||
usersSettingsPage.getters.deleteDataRadioButton().click();
|
||||
usersSettingsPage.getters.deleteDataInput().type('delete all data');
|
||||
usersSettingsPage.getters.deleteUserButton().realClick();
|
||||
usersSettingsPage.getters.deleteUserButton().click();
|
||||
workflowPage.getters.successToast().should('contain', 'User deleted');
|
||||
});
|
||||
|
||||
it('should delete user and transfer their data', () => {
|
||||
usersSettingsPage.actions.loginAndVisit(INSTANCE_OWNER.email, INSTANCE_OWNER.password, true);
|
||||
usersSettingsPage.actions.opedDeleteDialog(INSTANCE_MEMBERS[1].email);
|
||||
usersSettingsPage.getters.transferDataRadioButton().realClick();
|
||||
usersSettingsPage.getters.userSelectDropDown().realClick();
|
||||
usersSettingsPage.getters.userSelectOptions().first().realClick();
|
||||
usersSettingsPage.getters.deleteUserButton().realClick();
|
||||
usersSettingsPage.getters.transferDataRadioButton().click();
|
||||
usersSettingsPage.getters.userSelectDropDown().click();
|
||||
usersSettingsPage.getters.userSelectOptions().first().click();
|
||||
usersSettingsPage.getters.deleteUserButton().click();
|
||||
workflowPage.getters.successToast().should('contain', 'User deleted');
|
||||
});
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@ import {
|
||||
PIPEDRIVE_NODE_NAME,
|
||||
HTTP_REQUEST_NODE_NAME,
|
||||
NEW_QUERY_AUTH_ACCOUNT_NAME,
|
||||
} from './../constants';
|
||||
import {
|
||||
GMAIL_NODE_NAME,
|
||||
NEW_GOOGLE_ACCOUNT_NAME,
|
||||
NEW_TRELLO_ACCOUNT_NAME,
|
||||
@@ -13,6 +11,7 @@ import {
|
||||
TRELLO_NODE_NAME,
|
||||
} from '../constants';
|
||||
import { CredentialsPage, CredentialsModal, WorkflowPage, NDV } from '../pages';
|
||||
import { getVisibleSelect } from '../utils';
|
||||
|
||||
const credentialsPage = new CredentialsPage();
|
||||
const credentialsModal = new CredentialsModal();
|
||||
@@ -90,13 +89,16 @@ describe('Credentials', () => {
|
||||
workflowPage.getters.canvasNodes().last().click();
|
||||
cy.get('body').type('{enter}');
|
||||
workflowPage.getters.nodeCredentialsSelect().click();
|
||||
workflowPage.getters.nodeCredentialsSelect().find('li').last().click();
|
||||
getVisibleSelect().find('li').last().click();
|
||||
credentialsModal.getters.credentialsEditModal().should('be.visible');
|
||||
credentialsModal.getters.credentialAuthTypeRadioButtons().should('have.length', 2);
|
||||
credentialsModal.getters.credentialAuthTypeRadioButtons().first().click();
|
||||
credentialsModal.actions.fillCredentialsForm();
|
||||
cy.get('.el-message-box').find('button').contains('Close').click();
|
||||
workflowPage.getters.nodeCredentialsSelect().should('contain', NEW_GOOGLE_ACCOUNT_NAME);
|
||||
workflowPage.getters
|
||||
.nodeCredentialsSelect()
|
||||
.find('input')
|
||||
.should('have.value', NEW_GOOGLE_ACCOUNT_NAME);
|
||||
});
|
||||
|
||||
it('should show multiple credential types in the same dropdown', () => {
|
||||
@@ -107,7 +109,7 @@ describe('Credentials', () => {
|
||||
cy.get('body').type('{enter}');
|
||||
workflowPage.getters.nodeCredentialsSelect().click();
|
||||
// Add oAuth credentials
|
||||
workflowPage.getters.nodeCredentialsSelect().find('li').last().click();
|
||||
getVisibleSelect().find('li').last().click();
|
||||
credentialsModal.getters.credentialsEditModal().should('be.visible');
|
||||
credentialsModal.getters.credentialAuthTypeRadioButtons().should('have.length', 2);
|
||||
credentialsModal.getters.credentialAuthTypeRadioButtons().first().click();
|
||||
@@ -115,13 +117,14 @@ describe('Credentials', () => {
|
||||
cy.get('.el-message-box').find('button').contains('Close').click();
|
||||
workflowPage.getters.nodeCredentialsSelect().click();
|
||||
// Add Service account credentials
|
||||
workflowPage.getters.nodeCredentialsSelect().find('li').last().click();
|
||||
getVisibleSelect().find('li').last().click();
|
||||
credentialsModal.getters.credentialsEditModal().should('be.visible');
|
||||
credentialsModal.getters.credentialAuthTypeRadioButtons().should('have.length', 2);
|
||||
credentialsModal.getters.credentialAuthTypeRadioButtons().last().click();
|
||||
credentialsModal.actions.fillCredentialsForm();
|
||||
// Both (+ the 'Create new' option) should be in the dropdown
|
||||
workflowPage.getters.nodeCredentialsSelect().find('li').should('have.length.greaterThan', 3);
|
||||
workflowPage.getters.nodeCredentialsSelect().click();
|
||||
getVisibleSelect().find('li').should('have.length.greaterThan', 2);
|
||||
});
|
||||
|
||||
it('should correctly render required and optional credentials', () => {
|
||||
@@ -132,18 +135,18 @@ describe('Credentials', () => {
|
||||
// Select incoming authentication
|
||||
nodeDetailsView.getters.parameterInput('incomingAuthentication').should('exist');
|
||||
nodeDetailsView.getters.parameterInput('incomingAuthentication').click();
|
||||
nodeDetailsView.getters.parameterInput('incomingAuthentication').find('li').first().click();
|
||||
getVisibleSelect().find('li').first().click();
|
||||
// There should be two credential fields
|
||||
workflowPage.getters.nodeCredentialsSelect().should('have.length', 2);
|
||||
|
||||
workflowPage.getters.nodeCredentialsSelect().first().click();
|
||||
workflowPage.getters.nodeCredentialsSelect().first().find('li').last().click();
|
||||
getVisibleSelect().find('li').last().click();
|
||||
// This one should show auth type selector
|
||||
credentialsModal.getters.credentialAuthTypeRadioButtons().should('have.length', 2);
|
||||
cy.get('body').type('{esc}');
|
||||
|
||||
workflowPage.getters.nodeCredentialsSelect().last().click();
|
||||
workflowPage.getters.nodeCredentialsSelect().last().find('li').last().click();
|
||||
getVisibleSelect().find('li').last().click();
|
||||
// This one should not show auth type selector
|
||||
credentialsModal.getters.credentialsAuthTypeSelector().should('not.exist');
|
||||
});
|
||||
@@ -155,10 +158,13 @@ describe('Credentials', () => {
|
||||
workflowPage.getters.canvasNodes().last().click();
|
||||
cy.get('body').type('{enter}');
|
||||
workflowPage.getters.nodeCredentialsSelect().click();
|
||||
workflowPage.getters.nodeCredentialsSelect().find('li').last().click();
|
||||
getVisibleSelect().find('li').last().click();
|
||||
credentialsModal.getters.credentialsAuthTypeSelector().should('not.exist');
|
||||
credentialsModal.actions.fillCredentialsForm();
|
||||
workflowPage.getters.nodeCredentialsSelect().should('contain', NEW_TRELLO_ACCOUNT_NAME);
|
||||
workflowPage.getters
|
||||
.nodeCredentialsSelect()
|
||||
.find('input')
|
||||
.should('have.value', NEW_TRELLO_ACCOUNT_NAME);
|
||||
});
|
||||
|
||||
it('should delete credentials from NDV', () => {
|
||||
@@ -168,16 +174,22 @@ describe('Credentials', () => {
|
||||
workflowPage.getters.canvasNodes().last().click();
|
||||
cy.get('body').type('{enter}');
|
||||
workflowPage.getters.nodeCredentialsSelect().click();
|
||||
workflowPage.getters.nodeCredentialsSelect().find('li').last().click();
|
||||
getVisibleSelect().find('li').last().click();
|
||||
credentialsModal.actions.fillCredentialsForm();
|
||||
workflowPage.getters.nodeCredentialsSelect().should('contain', NEW_NOTION_ACCOUNT_NAME);
|
||||
workflowPage.getters
|
||||
.nodeCredentialsSelect()
|
||||
.find('input')
|
||||
.should('have.value', NEW_NOTION_ACCOUNT_NAME);
|
||||
|
||||
workflowPage.getters.nodeCredentialsEditButton().click();
|
||||
credentialsModal.getters.credentialsEditModal().should('be.visible');
|
||||
credentialsModal.getters.deleteButton().click();
|
||||
cy.get('.el-message-box').find('button').contains('Yes').click();
|
||||
workflowPage.getters.successToast().contains('Credential deleted');
|
||||
workflowPage.getters.nodeCredentialsSelect().should('not.contain', NEW_TRELLO_ACCOUNT_NAME);
|
||||
workflowPage.getters
|
||||
.nodeCredentialsSelect()
|
||||
.find('input')
|
||||
.should('not.have.value', NEW_TRELLO_ACCOUNT_NAME);
|
||||
});
|
||||
|
||||
it('should rename credentials from NDV', () => {
|
||||
@@ -187,17 +199,18 @@ describe('Credentials', () => {
|
||||
workflowPage.getters.canvasNodes().last().click();
|
||||
cy.get('body').type('{enter}');
|
||||
workflowPage.getters.nodeCredentialsSelect().click();
|
||||
workflowPage.getters.nodeCredentialsSelect().find('li').last().click();
|
||||
getVisibleSelect().find('li').last().click();
|
||||
credentialsModal.actions.fillCredentialsForm();
|
||||
workflowPage.getters.nodeCredentialsSelect().should('contain', NEW_TRELLO_ACCOUNT_NAME);
|
||||
|
||||
workflowPage.getters.nodeCredentialsEditButton().click();
|
||||
credentialsModal.getters.credentialsEditModal().should('be.visible');
|
||||
credentialsModal.getters.name().click();
|
||||
credentialsModal.actions.renameCredential(NEW_CREDENTIAL_NAME);
|
||||
credentialsModal.getters.saveButton().click();
|
||||
credentialsModal.getters.closeButton().click();
|
||||
workflowPage.getters.nodeCredentialsSelect().should('contain', NEW_CREDENTIAL_NAME);
|
||||
workflowPage.getters
|
||||
.nodeCredentialsSelect()
|
||||
.find('input')
|
||||
.should('have.value', NEW_CREDENTIAL_NAME);
|
||||
});
|
||||
|
||||
it('should setup generic authentication for HTTP node', () => {
|
||||
@@ -207,20 +220,20 @@ describe('Credentials', () => {
|
||||
workflowPage.getters.canvasNodes().last().click();
|
||||
cy.get('body').type('{enter}');
|
||||
nodeDetailsView.getters.parameterInput('authentication').click();
|
||||
nodeDetailsView.getters.parameterInput('authentication').find('li').should('have.length', 3);
|
||||
nodeDetailsView.getters.parameterInput('authentication').find('li').last().click();
|
||||
getVisibleSelect().find('li').should('have.length', 3);
|
||||
getVisibleSelect().find('li').last().click();
|
||||
nodeDetailsView.getters.parameterInput('genericAuthType').should('exist');
|
||||
nodeDetailsView.getters.parameterInput('genericAuthType').click();
|
||||
nodeDetailsView.getters
|
||||
.parameterInput('genericAuthType')
|
||||
.find('li')
|
||||
.should('have.length.greaterThan', 0);
|
||||
nodeDetailsView.getters.parameterInput('genericAuthType').find('li').last().click();
|
||||
getVisibleSelect().find('li').should('have.length.greaterThan', 0);
|
||||
getVisibleSelect().find('li').last().click();
|
||||
|
||||
workflowPage.getters.nodeCredentialsSelect().should('exist');
|
||||
workflowPage.getters.nodeCredentialsSelect().click();
|
||||
workflowPage.getters.nodeCredentialsSelect().find('li').last().click();
|
||||
getVisibleSelect().find('li').last().click();
|
||||
credentialsModal.actions.fillCredentialsForm();
|
||||
workflowPage.getters.nodeCredentialsSelect().should('contain', NEW_QUERY_AUTH_ACCOUNT_NAME);
|
||||
workflowPage.getters
|
||||
.nodeCredentialsSelect()
|
||||
.find('input')
|
||||
.should('have.value', NEW_QUERY_AUTH_ACCOUNT_NAME);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,6 +4,7 @@ import { CredentialsModal, WorkflowPage } from '../pages';
|
||||
import CustomNodeWithN8nCredentialFixture from '../fixtures/Custom_node_n8n_credential.json';
|
||||
import CustomNodeWithCustomCredentialFixture from '../fixtures/Custom_node_custom_credential.json';
|
||||
import CustomCredential from '../fixtures/Custom_credential.json';
|
||||
import { getVisibleSelect } from '../utils';
|
||||
|
||||
const credentialsModal = new CredentialsModal();
|
||||
const nodeCreatorFeature = new NodeCreator();
|
||||
@@ -20,9 +21,13 @@ describe('Community Nodes', () => {
|
||||
req.on('response', (res) => {
|
||||
const nodes = res.body || [];
|
||||
|
||||
nodes.push(CustomNodeFixture, CustomNodeWithN8nCredentialFixture, CustomNodeWithCustomCredentialFixture);
|
||||
nodes.push(
|
||||
CustomNodeFixture,
|
||||
CustomNodeWithN8nCredentialFixture,
|
||||
CustomNodeWithCustomCredentialFixture,
|
||||
);
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
cy.intercept('/types/credentials.json', { middleware: true }, (req) => {
|
||||
req.headers['cache-control'] = 'no-cache, no-store';
|
||||
@@ -31,8 +36,8 @@ describe('Community Nodes', () => {
|
||||
const credentials = res.body || [];
|
||||
|
||||
credentials.push(CustomCredential);
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
workflowPage.actions.visit();
|
||||
});
|
||||
@@ -45,7 +50,7 @@ describe('Community Nodes', () => {
|
||||
|
||||
nodeCreatorFeature.getters
|
||||
.getCreatorItem(customNode)
|
||||
.findChildByTestId('node-creator-item-tooltip')
|
||||
.find('.el-tooltip__trigger')
|
||||
.should('exist');
|
||||
nodeCreatorFeature.actions.selectNode(customNode);
|
||||
|
||||
@@ -65,16 +70,9 @@ describe('Community Nodes', () => {
|
||||
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();
|
||||
getVisibleSelect().find('li').should('have.length', 4);
|
||||
getVisibleSelect().find('li').eq(3).contains('option4').should('exist').click();
|
||||
secondParameter().find('input.el-input__inner').should('have.value', 'option4');
|
||||
});
|
||||
|
||||
|
||||
@@ -28,59 +28,36 @@ describe('NDV', () => {
|
||||
ndv.actions.switchOutputMode('Table');
|
||||
|
||||
// input to output
|
||||
ndv.getters.inputTableRow(1)
|
||||
ndv.getters
|
||||
.inputTableRow(1)
|
||||
.should('exist')
|
||||
.invoke('attr', 'data-test-id')
|
||||
.should('equal', 'hovering-item');
|
||||
|
||||
ndv.getters.inputTableRow(1)
|
||||
.realHover();
|
||||
ndv.getters.outputTableRow(4)
|
||||
.invoke('attr', 'data-test-id')
|
||||
.should('equal', 'hovering-item');
|
||||
ndv.getters.inputTableRow(1).realHover();
|
||||
ndv.getters.outputTableRow(4).invoke('attr', 'data-test-id').should('equal', 'hovering-item');
|
||||
|
||||
ndv.getters.inputTableRow(2)
|
||||
.realHover();
|
||||
ndv.getters.outputTableRow(2)
|
||||
.invoke('attr', 'data-test-id')
|
||||
.should('equal', 'hovering-item');
|
||||
|
||||
ndv.getters.inputTableRow(3)
|
||||
.realHover();
|
||||
ndv.getters.outputTableRow(6)
|
||||
.invoke('attr', 'data-test-id')
|
||||
.should('equal', 'hovering-item');
|
||||
ndv.getters.inputTableRow(2).realHover();
|
||||
ndv.getters.outputTableRow(2).invoke('attr', 'data-test-id').should('equal', 'hovering-item');
|
||||
|
||||
ndv.getters.inputTableRow(3).realHover();
|
||||
ndv.getters.outputTableRow(6).invoke('attr', 'data-test-id').should('equal', 'hovering-item');
|
||||
|
||||
// output to input
|
||||
ndv.getters.outputTableRow(1)
|
||||
.realHover();
|
||||
ndv.getters.inputTableRow(4)
|
||||
.invoke('attr', 'data-test-id')
|
||||
.should('equal', 'hovering-item');
|
||||
ndv.getters.outputTableRow(1).realHover();
|
||||
ndv.getters.inputTableRow(4).invoke('attr', 'data-test-id').should('equal', 'hovering-item');
|
||||
|
||||
ndv.getters.outputTableRow(4)
|
||||
.realHover();
|
||||
ndv.getters.inputTableRow(1)
|
||||
.invoke('attr', 'data-test-id')
|
||||
.should('equal', 'hovering-item');
|
||||
ndv.getters.outputTableRow(4).realHover();
|
||||
ndv.getters.inputTableRow(1).invoke('attr', 'data-test-id').should('equal', 'hovering-item');
|
||||
|
||||
ndv.getters.outputTableRow(2)
|
||||
.realHover();
|
||||
ndv.getters.inputTableRow(2)
|
||||
.invoke('attr', 'data-test-id')
|
||||
.should('equal', 'hovering-item');
|
||||
|
||||
ndv.getters.outputTableRow(6)
|
||||
.realHover();
|
||||
ndv.getters.inputTableRow(3)
|
||||
.invoke('attr', 'data-test-id')
|
||||
.should('equal', 'hovering-item');
|
||||
ndv.getters.outputTableRow(2).realHover();
|
||||
ndv.getters.inputTableRow(2).invoke('attr', 'data-test-id').should('equal', 'hovering-item');
|
||||
|
||||
ndv.getters.outputTableRow(1)
|
||||
.realHover();
|
||||
ndv.getters.inputTableRow(4)
|
||||
.invoke('attr', 'data-test-id')
|
||||
.should('equal', 'hovering-item');
|
||||
ndv.getters.outputTableRow(6).realHover();
|
||||
ndv.getters.inputTableRow(3).invoke('attr', 'data-test-id').should('equal', 'hovering-item');
|
||||
|
||||
ndv.getters.outputTableRow(1).realHover();
|
||||
ndv.getters.inputTableRow(4).invoke('attr', 'data-test-id').should('equal', 'hovering-item');
|
||||
});
|
||||
|
||||
it('maps paired input and output items based on selected input node', () => {
|
||||
@@ -92,9 +69,11 @@ describe('NDV', () => {
|
||||
workflowPage.actions.openNode('Set2');
|
||||
|
||||
ndv.getters.inputPanel().contains('6 items').should('exist');
|
||||
ndv.getters.outputRunSelector()
|
||||
ndv.getters
|
||||
.outputRunSelector()
|
||||
.find('input')
|
||||
.should('exist')
|
||||
.should('include.text', '2 of 2 (6 items)');
|
||||
.should('have.value', '2 of 2 (6 items)');
|
||||
|
||||
ndv.actions.switchInputMode('Table');
|
||||
ndv.actions.switchOutputMode('Table');
|
||||
@@ -106,7 +85,8 @@ describe('NDV', () => {
|
||||
ndv.actions.selectInputNode('Set1');
|
||||
ndv.getters.backToCanvas().realHover(); // reset to default hover
|
||||
|
||||
ndv.getters.inputTableRow(1)
|
||||
ndv.getters
|
||||
.inputTableRow(1)
|
||||
.should('have.text', '1000')
|
||||
.invoke('attr', 'data-test-id')
|
||||
.should('equal', 'hovering-item');
|
||||
@@ -119,7 +99,8 @@ describe('NDV', () => {
|
||||
ndv.actions.changeOutputRunSelector('1 of 2 (6 items)');
|
||||
ndv.getters.backToCanvas().realHover(); // reset to default hover
|
||||
|
||||
ndv.getters.inputTableRow(1)
|
||||
ndv.getters
|
||||
.inputTableRow(1)
|
||||
.should('have.text', '1111')
|
||||
.invoke('attr', 'data-test-id')
|
||||
.should('equal', 'hovering-item');
|
||||
@@ -137,11 +118,13 @@ describe('NDV', () => {
|
||||
workflowPage.actions.executeWorkflow();
|
||||
workflowPage.actions.openNode('Set3');
|
||||
|
||||
ndv.getters.inputRunSelector()
|
||||
ndv.getters
|
||||
.inputRunSelector()
|
||||
.should('exist')
|
||||
.find('input')
|
||||
.should('include.value', '2 of 2 (6 items)');
|
||||
ndv.getters.outputRunSelector()
|
||||
ndv.getters
|
||||
.outputRunSelector()
|
||||
.should('exist')
|
||||
.find('input')
|
||||
.should('include.value', '2 of 2 (6 items)');
|
||||
@@ -150,23 +133,19 @@ describe('NDV', () => {
|
||||
ndv.actions.switchOutputMode('Table');
|
||||
|
||||
ndv.actions.changeOutputRunSelector('1 of 2 (6 items)');
|
||||
ndv.getters.inputRunSelector().find('input')
|
||||
.should('include.value', '1 of 2 (6 items)');
|
||||
ndv.getters.outputRunSelector().find('input')
|
||||
.should('include.value', '1 of 2 (6 items)');
|
||||
ndv.getters.inputRunSelector().find('input').should('include.value', '1 of 2 (6 items)');
|
||||
ndv.getters.outputRunSelector().find('input').should('include.value', '1 of 2 (6 items)');
|
||||
|
||||
ndv.getters.inputTableRow(1)
|
||||
ndv.getters
|
||||
.inputTableRow(1)
|
||||
.should('have.text', '1111')
|
||||
.invoke('attr', 'data-test-id')
|
||||
.should('equal', 'hovering-item');
|
||||
ndv.getters.outputTableRow(1)
|
||||
.should('have.text', '1111')
|
||||
.realHover();
|
||||
ndv.getters.outputTableRow(1).should('have.text', '1111').realHover();
|
||||
|
||||
ndv.getters.outputTableRow(3)
|
||||
.should('have.text', '4444')
|
||||
.realHover();
|
||||
ndv.getters.inputTableRow(3)
|
||||
ndv.getters.outputTableRow(3).should('have.text', '4444').realHover();
|
||||
ndv.getters
|
||||
.inputTableRow(3)
|
||||
.should('have.text', '4444')
|
||||
.invoke('attr', 'data-test-id')
|
||||
.should('equal', 'hovering-item');
|
||||
@@ -174,18 +153,16 @@ describe('NDV', () => {
|
||||
ndv.actions.changeOutputRunSelector('2 of 2 (6 items)');
|
||||
cy.wait(50);
|
||||
|
||||
ndv.getters.inputTableRow(1)
|
||||
.should('have.text', '1000')
|
||||
.realHover();
|
||||
ndv.getters.outputTableRow(1)
|
||||
ndv.getters.inputTableRow(1).should('have.text', '1000').realHover();
|
||||
ndv.getters
|
||||
.outputTableRow(1)
|
||||
.should('have.text', '1000')
|
||||
.invoke('attr', 'data-test-id')
|
||||
.should('equal', 'hovering-item');
|
||||
|
||||
ndv.getters.outputTableRow(3)
|
||||
.should('have.text', '2000')
|
||||
.realHover();
|
||||
ndv.getters.inputTableRow(3)
|
||||
ndv.getters.outputTableRow(3).should('have.text', '2000').realHover();
|
||||
ndv.getters
|
||||
.inputTableRow(3)
|
||||
.should('have.text', '2000')
|
||||
.invoke('attr', 'data-test-id')
|
||||
.should('equal', 'hovering-item');
|
||||
@@ -200,15 +177,18 @@ describe('NDV', () => {
|
||||
workflowPage.actions.openNode('Set2');
|
||||
|
||||
ndv.getters.inputPanel().contains('6 items').should('exist');
|
||||
ndv.getters.outputRunSelector()
|
||||
ndv.getters
|
||||
.outputRunSelector()
|
||||
.find('input')
|
||||
.should('exist')
|
||||
.should('include.text', '2 of 2 (6 items)');
|
||||
.should('have.value', '2 of 2 (6 items)');
|
||||
|
||||
ndv.actions.switchInputMode('Table');
|
||||
ndv.actions.switchOutputMode('Table');
|
||||
|
||||
ndv.getters.backToCanvas().realHover(); // reset to default hover
|
||||
ndv.getters.inputTableRow(1)
|
||||
ndv.getters
|
||||
.inputTableRow(1)
|
||||
.should('have.text', '1111')
|
||||
.invoke('attr', 'data-test-id')
|
||||
.should('equal', 'hovering-item');
|
||||
@@ -218,28 +198,32 @@ describe('NDV', () => {
|
||||
|
||||
ndv.actions.selectInputNode('Code1');
|
||||
ndv.getters.inputTableRow(1).realHover();
|
||||
ndv.getters.inputTableRow(1)
|
||||
ndv.getters
|
||||
.inputTableRow(1)
|
||||
.should('have.text', '1000')
|
||||
.invoke('attr', 'data-test-id')
|
||||
.should('equal', 'hovering-item');
|
||||
ndv.getters.outputTableRow(1)
|
||||
.should('have.text', '1000');
|
||||
ndv.getters.outputTableRow(1).should('have.text', '1000');
|
||||
ndv.getters.parameterExpressionPreview('value').should('include.text', '1000');
|
||||
|
||||
ndv.actions.selectInputNode('Code');
|
||||
|
||||
ndv.getters.inputTableRow(1).realHover();
|
||||
ndv.getters.inputTableRow(1)
|
||||
.should('have.text', '6666')
|
||||
.invoke('attr', 'data-test-id')
|
||||
.should('equal', 'hovering-item');
|
||||
ndv.getters
|
||||
.inputTableRow(1)
|
||||
.should('have.text', '6666')
|
||||
.invoke('attr', 'data-test-id')
|
||||
.should('equal', 'hovering-item');
|
||||
ndv.getters.outputHoveringItem().should('not.exist');
|
||||
ndv.getters.parameterExpressionPreview('value').should('include.text', '1000');
|
||||
|
||||
ndv.actions.selectInputNode('When clicking');
|
||||
|
||||
ndv.getters.inputTableRow(1).realHover();
|
||||
ndv.getters.inputTableRow(1).should('have.text', "This is an item, but it's empty.").realHover();
|
||||
ndv.getters
|
||||
.inputTableRow(1)
|
||||
.should('have.text', "This is an item, but it's empty.")
|
||||
.realHover();
|
||||
ndv.getters.outputHoveringItem().should('have.length', 6);
|
||||
ndv.getters.parameterExpressionPreview('value').should('include.text', '1000');
|
||||
});
|
||||
@@ -256,18 +240,16 @@ describe('NDV', () => {
|
||||
ndv.actions.switchOutputMode('Table');
|
||||
|
||||
ndv.actions.switchOutputBranch('False Branch (2 items)');
|
||||
ndv.getters.outputTableRow(1)
|
||||
.should('have.text', '8888')
|
||||
.realHover();
|
||||
ndv.getters.inputTableRow(5)
|
||||
ndv.getters.outputTableRow(1).should('have.text', '8888').realHover();
|
||||
ndv.getters
|
||||
.inputTableRow(5)
|
||||
.should('have.text', '8888')
|
||||
.invoke('attr', 'data-test-id')
|
||||
.should('equal', 'hovering-item');
|
||||
|
||||
ndv.getters.outputTableRow(2)
|
||||
.should('have.text', '9999')
|
||||
.realHover();
|
||||
ndv.getters.inputTableRow(6)
|
||||
ndv.getters.outputTableRow(2).should('have.text', '9999').realHover();
|
||||
ndv.getters
|
||||
.inputTableRow(6)
|
||||
.should('have.text', '9999')
|
||||
.invoke('attr', 'data-test-id')
|
||||
.should('equal', 'hovering-item');
|
||||
@@ -277,31 +259,21 @@ describe('NDV', () => {
|
||||
workflowPage.actions.openNode('Set5');
|
||||
|
||||
ndv.actions.switchInputBranch('True Branch');
|
||||
ndv.actions.changeOutputRunSelector('1 of 2 (2 items)')
|
||||
ndv.getters.outputTableRow(1)
|
||||
.should('have.text', '8888')
|
||||
.realHover();
|
||||
ndv.actions.changeOutputRunSelector('1 of 2 (2 items)');
|
||||
ndv.getters.outputTableRow(1).should('have.text', '8888').realHover();
|
||||
ndv.getters.inputHoveringItem().should('not.exist');
|
||||
|
||||
ndv.getters.inputTableRow(1)
|
||||
.should('have.text', '1111')
|
||||
.realHover();
|
||||
ndv.getters.inputTableRow(1).should('have.text', '1111').realHover();
|
||||
ndv.getters.outputHoveringItem().should('not.exist');
|
||||
|
||||
ndv.actions.switchInputBranch('False Branch');
|
||||
ndv.getters.inputTableRow(1)
|
||||
.should('have.text', '8888')
|
||||
.realHover();
|
||||
ndv.getters.inputTableRow(1).should('have.text', '8888').realHover();
|
||||
|
||||
ndv.actions.changeOutputRunSelector('2 of 2 (4 items)')
|
||||
ndv.getters.outputTableRow(1)
|
||||
.should('have.text', '1111')
|
||||
.realHover();
|
||||
ndv.actions.changeOutputRunSelector('2 of 2 (4 items)');
|
||||
ndv.getters.outputTableRow(1).should('have.text', '1111').realHover();
|
||||
|
||||
ndv.actions.changeOutputRunSelector('1 of 2 (2 items)')
|
||||
ndv.getters.inputTableRow(1)
|
||||
.should('have.text', '8888')
|
||||
.realHover();
|
||||
ndv.actions.changeOutputRunSelector('1 of 2 (2 items)');
|
||||
ndv.getters.inputTableRow(1).should('have.text', '8888').realHover();
|
||||
ndv.getters.outputHoveringItem().should('have.text', '8888');
|
||||
// todo there's a bug here need to fix ADO-534
|
||||
// ndv.getters.outputHoveringItem().should('not.exist');
|
||||
|
||||
@@ -2,7 +2,13 @@ import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
|
||||
|
||||
const workflowPage = new WorkflowPageClass();
|
||||
|
||||
function checkStickiesStyle( top: number, left: number, height: number, width: number, zIndex?: number) {
|
||||
function checkStickiesStyle(
|
||||
top: number,
|
||||
left: number,
|
||||
height: number,
|
||||
width: number,
|
||||
zIndex?: number,
|
||||
) {
|
||||
workflowPage.getters.stickies().should(($el) => {
|
||||
expect($el).to.have.css('top', `${top}px`);
|
||||
expect($el).to.have.css('left', `${left}px`);
|
||||
@@ -18,22 +24,23 @@ describe('Canvas Actions', () => {
|
||||
beforeEach(() => {
|
||||
workflowPage.actions.visit();
|
||||
|
||||
cy.window().then(
|
||||
(win) => {
|
||||
// @ts-ignore
|
||||
win.preventNodeViewBeforeUnload = true;
|
||||
},
|
||||
);
|
||||
cy.window().then((win) => {
|
||||
// @ts-ignore
|
||||
win.preventNodeViewBeforeUnload = true;
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('adds sticky to canvas with default text and position', () => {
|
||||
workflowPage.getters.addStickyButton().should('not.be.visible');
|
||||
|
||||
addDefaultSticky()
|
||||
workflowPage.getters.stickies().eq(0)
|
||||
addDefaultSticky();
|
||||
workflowPage.getters
|
||||
.stickies()
|
||||
.eq(0)
|
||||
.should('have.text', 'I’m a note\nDouble click to edit me. Guide\n')
|
||||
.find('a').contains('Guide').should('have.attr', 'href');
|
||||
.find('a')
|
||||
.contains('Guide')
|
||||
.should('have.attr', 'href');
|
||||
});
|
||||
|
||||
it('drags sticky around to top left corner', () => {
|
||||
@@ -57,18 +64,19 @@ describe('Canvas Actions', () => {
|
||||
|
||||
it('deletes sticky', () => {
|
||||
workflowPage.actions.addSticky();
|
||||
workflowPage.getters.stickies().should('have.length', 1)
|
||||
workflowPage.getters.stickies().should('have.length', 1);
|
||||
|
||||
workflowPage.actions.deleteSticky();
|
||||
|
||||
workflowPage.getters.stickies().should('have.length', 0)
|
||||
workflowPage.getters.stickies().should('have.length', 0);
|
||||
});
|
||||
|
||||
it('edits sticky and updates content as markdown', () => {
|
||||
workflowPage.actions.addSticky();
|
||||
|
||||
workflowPage.getters.stickies()
|
||||
.should('have.text', 'I’m a note\nDouble click to edit me. Guide\n')
|
||||
workflowPage.getters
|
||||
.stickies()
|
||||
.should('have.text', 'I’m a note\nDouble click to edit me. Guide\n');
|
||||
|
||||
workflowPage.getters.stickies().dblclick();
|
||||
workflowPage.actions.editSticky('# hello world \n ## text text');
|
||||
@@ -159,32 +167,41 @@ describe('Canvas Actions', () => {
|
||||
cy.drag('[data-test-id="sticky"] [data-dir="topLeft"]', [-150, -150]);
|
||||
checkStickiesStyle(124, 256, 316, 384, -121);
|
||||
|
||||
workflowPage.getters.canvasNodes().eq(0)
|
||||
workflowPage.getters
|
||||
.canvasNodes()
|
||||
.eq(0)
|
||||
.should(($el) => {
|
||||
expect($el).to.have.css('z-index', 'auto');
|
||||
});
|
||||
|
||||
workflowPage.actions.addSticky();
|
||||
workflowPage.getters.stickies().eq(0)
|
||||
workflowPage.getters
|
||||
.stickies()
|
||||
.eq(0)
|
||||
.should(($el) => {
|
||||
expect($el).to.have.css('z-index', '-121');
|
||||
});
|
||||
workflowPage.getters.stickies().eq(1)
|
||||
workflowPage.getters
|
||||
.stickies()
|
||||
.eq(1)
|
||||
.should(($el) => {
|
||||
expect($el).to.have.css('z-index', '-38');
|
||||
});
|
||||
|
||||
cy.drag('[data-test-id="sticky"] [data-dir="topLeft"]', [-200, -200], { index: 1 });
|
||||
workflowPage.getters.stickies().eq(0)
|
||||
workflowPage.getters
|
||||
.stickies()
|
||||
.eq(0)
|
||||
.should(($el) => {
|
||||
expect($el).to.have.css('z-index', '-121');
|
||||
});
|
||||
|
||||
workflowPage.getters.stickies().eq(1)
|
||||
workflowPage.getters
|
||||
.stickies()
|
||||
.eq(1)
|
||||
.should(($el) => {
|
||||
expect($el).to.have.css('z-index', '-158');
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -198,15 +215,20 @@ type BoundingBox = {
|
||||
width: number;
|
||||
top: number;
|
||||
left: number;
|
||||
}
|
||||
};
|
||||
|
||||
function dragRightEdge(curr: BoundingBox, move: number) {
|
||||
workflowPage.getters.stickies().first().then(($el) => {
|
||||
const { left, top, height, width } = curr;
|
||||
cy.drag(`[data-test-id="sticky"] [data-dir="right"]`, [left + width + move, 0], { abs: true });
|
||||
stickyShouldBePositionedCorrectly({ top, left });
|
||||
stickyShouldHaveCorrectSize([height, width * 1.5 + move]);
|
||||
});
|
||||
workflowPage.getters
|
||||
.stickies()
|
||||
.first()
|
||||
.then(($el) => {
|
||||
const { left, top, height, width } = curr;
|
||||
cy.drag(`[data-test-id="sticky"] [data-dir="right"]`, [left + width + move, 0], {
|
||||
abs: true,
|
||||
});
|
||||
stickyShouldBePositionedCorrectly({ top, left });
|
||||
stickyShouldHaveCorrectSize([height, width * 1.5 + move]);
|
||||
});
|
||||
}
|
||||
|
||||
function shouldHaveOneSticky() {
|
||||
@@ -214,17 +236,20 @@ function shouldHaveOneSticky() {
|
||||
}
|
||||
|
||||
function shouldBeInDefaultLocation() {
|
||||
workflowPage.getters.stickies().eq(0).should(($el) => {
|
||||
expect($el).to.have.css('height', '160px');
|
||||
expect($el).to.have.css('width', '240px');
|
||||
})
|
||||
workflowPage.getters
|
||||
.stickies()
|
||||
.eq(0)
|
||||
.should(($el) => {
|
||||
expect($el).to.have.css('height', '160px');
|
||||
expect($el).to.have.css('width', '240px');
|
||||
});
|
||||
}
|
||||
|
||||
function shouldHaveDefaultSize() {
|
||||
workflowPage.getters.stickies().should(($el) => {
|
||||
expect($el).to.have.css('height', '160px');
|
||||
expect($el).to.have.css('width', '240px');
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
function addDefaultSticky() {
|
||||
@@ -237,21 +262,19 @@ function addDefaultSticky() {
|
||||
function stickyShouldBePositionedCorrectly(position: Position) {
|
||||
const yOffset = -100;
|
||||
const xOffset = -180;
|
||||
workflowPage.getters.stickies()
|
||||
.should(($el) => {
|
||||
expect($el).to.have.css('top', `${yOffset + position.top}px`);
|
||||
expect($el).to.have.css('left', `${xOffset + position.left}px`);
|
||||
});
|
||||
workflowPage.getters.stickies().should(($el) => {
|
||||
expect($el).to.have.css('top', `${yOffset + position.top}px`);
|
||||
expect($el).to.have.css('left', `${xOffset + position.left}px`);
|
||||
});
|
||||
}
|
||||
|
||||
function stickyShouldHaveCorrectSize(size: [number, number]) {
|
||||
const yOffset = 0;
|
||||
const xOffset = 0;
|
||||
workflowPage.getters.stickies()
|
||||
.should(($el) => {
|
||||
expect($el).to.have.css('height', `${yOffset + size[0]}px`);
|
||||
expect($el).to.have.css('width', `${xOffset + size[1]}px`);
|
||||
});
|
||||
workflowPage.getters.stickies().should(($el) => {
|
||||
expect($el).to.have.css('height', `${yOffset + size[0]}px`);
|
||||
expect($el).to.have.css('width', `${xOffset + size[1]}px`);
|
||||
});
|
||||
}
|
||||
|
||||
function moveSticky(target: Position) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { WorkflowPage, NDV, CredentialsModal } from '../pages';
|
||||
import { getVisibleSelect } from '../utils';
|
||||
|
||||
const workflowPage = new WorkflowPage();
|
||||
const ndv = new NDV();
|
||||
@@ -32,7 +33,7 @@ describe('Resource Locator', () => {
|
||||
workflowPage.actions.addNodeToCanvas('Google Sheets', true, true);
|
||||
workflowPage.getters.nodeCredentialsSelect().click();
|
||||
// Add oAuth credentials
|
||||
workflowPage.getters.nodeCredentialsSelect().find('li').last().click();
|
||||
getVisibleSelect().find('li').last().click();
|
||||
credentialsModal.getters.credentialsEditModal().should('be.visible');
|
||||
credentialsModal.getters.credentialAuthTypeRadioButtons().should('have.length', 2);
|
||||
credentialsModal.getters.credentialAuthTypeRadioButtons().first().click();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { NodeCreator } from '../pages/features/node-creator';
|
||||
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
|
||||
import { NDV } from '../pages/ndv';
|
||||
import { getVisibleSelect } from '../utils';
|
||||
|
||||
const nodeCreatorFeature = new NodeCreator();
|
||||
const WorkflowPage = new WorkflowPageClass();
|
||||
@@ -85,7 +86,7 @@ describe('Node Creator', () => {
|
||||
nodeCreatorFeature.getters.getCreatorItem(editImageNode).click();
|
||||
nodeCreatorFeature.getters.activeSubcategory().should('have.text', editImageNode);
|
||||
nodeCreatorFeature.getters.getCreatorItem('Crop Image').click();
|
||||
NDVModal.getters.parameterInput('operation').should('contain.text', 'Crop');
|
||||
NDVModal.getters.parameterInput('operation').find('input').should('have.value', 'Crop');
|
||||
});
|
||||
|
||||
it('should search through actions and confirm added action', () => {
|
||||
@@ -95,9 +96,9 @@ describe('Node Creator', () => {
|
||||
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').type('{uparrow}{uparrow}{rightarrow}');
|
||||
NDVModal.getters.parameterInput('operation').should('contain.text', 'Rename');
|
||||
})
|
||||
nodeCreatorFeature.getters.searchBar().find('input').type('{uparrow}{rightarrow}');
|
||||
NDVModal.getters.parameterInput('operation').find('input').should('have.value', 'Rename');
|
||||
});
|
||||
|
||||
it('should not show actions for single action nodes', () => {
|
||||
const singleActionNodes = [
|
||||
@@ -110,19 +111,22 @@ describe('Node Creator', () => {
|
||||
'Spontit',
|
||||
'Vonage',
|
||||
'Send Email',
|
||||
'Toggl Trigger'
|
||||
]
|
||||
const doubleActionNode = 'OpenWeatherMap'
|
||||
'Toggl Trigger',
|
||||
];
|
||||
const doubleActionNode = 'OpenWeatherMap';
|
||||
|
||||
nodeCreatorFeature.actions.openNodeCreator();
|
||||
singleActionNodes.forEach((node) => {
|
||||
nodeCreatorFeature.getters.searchBar().find('input').clear().type(node);
|
||||
nodeCreatorFeature.getters.getCreatorItem(node).find('button[class*="panelIcon"]').should('not.exist');
|
||||
})
|
||||
nodeCreatorFeature.getters
|
||||
.getCreatorItem(node)
|
||||
.find('button[class*="panelIcon"]')
|
||||
.should('not.exist');
|
||||
});
|
||||
nodeCreatorFeature.getters.searchBar().find('input').clear().type(doubleActionNode);
|
||||
nodeCreatorFeature.getters.getCreatorItem(doubleActionNode).click();
|
||||
nodeCreatorFeature.getters.creatorItem().should('have.length', 4);
|
||||
})
|
||||
});
|
||||
|
||||
it('should have "Actions" section collapsed when opening actions view from Trigger root view', () => {
|
||||
nodeCreatorFeature.actions.openNodeCreator();
|
||||
@@ -131,10 +135,19 @@ describe('Node Creator', () => {
|
||||
nodeCreatorFeature.getters.getCategoryItem('Actions').should('exist');
|
||||
nodeCreatorFeature.getters.getCategoryItem('Triggers').should('exist');
|
||||
|
||||
nodeCreatorFeature.getters.getCategoryItem('Triggers').parent().should('not.have.attr', 'data-category-collapsed');
|
||||
nodeCreatorFeature.getters.getCategoryItem('Actions').parent().should('have.attr', 'data-category-collapsed', 'true');
|
||||
nodeCreatorFeature.getters.getCategoryItem('Actions').click()
|
||||
nodeCreatorFeature.getters.getCategoryItem('Actions').parent().should('not.have.attr', 'data-category-collapsed');
|
||||
nodeCreatorFeature.getters
|
||||
.getCategoryItem('Triggers')
|
||||
.parent()
|
||||
.should('have.attr', 'data-category-collapsed', 'false');
|
||||
nodeCreatorFeature.getters
|
||||
.getCategoryItem('Actions')
|
||||
.parent()
|
||||
.should('have.attr', 'data-category-collapsed', 'true');
|
||||
nodeCreatorFeature.getters.getCategoryItem('Actions').click();
|
||||
nodeCreatorFeature.getters
|
||||
.getCategoryItem('Actions')
|
||||
.parent()
|
||||
.should('have.attr', 'data-category-collapsed', 'false');
|
||||
});
|
||||
|
||||
it('should have "Triggers" section collapsed when opening actions view from Regular root view', () => {
|
||||
@@ -145,17 +158,33 @@ describe('Node Creator', () => {
|
||||
nodeCreatorFeature.getters.searchBar().find('input').clear().type('n8n');
|
||||
nodeCreatorFeature.getters.getCreatorItem('n8n').click();
|
||||
|
||||
nodeCreatorFeature.getters.getCategoryItem('Actions').parent().should('not.have.attr', 'data-category-collapsed');
|
||||
nodeCreatorFeature.getters.getCategoryItem('Actions').click()
|
||||
nodeCreatorFeature.getters.getCategoryItem('Actions').parent().should('have.attr', 'data-category-collapsed');
|
||||
nodeCreatorFeature.getters.getCategoryItem('Triggers').parent().should('have.attr', 'data-category-collapsed');
|
||||
nodeCreatorFeature.getters.getCategoryItem('Triggers').click()
|
||||
nodeCreatorFeature.getters.getCategoryItem('Triggers').parent().should('not.have.attr', 'data-category-collapsed');
|
||||
nodeCreatorFeature.getters
|
||||
.getCategoryItem('Actions')
|
||||
.parent()
|
||||
.should('have.attr', 'data-category-collapsed', 'false');
|
||||
nodeCreatorFeature.getters.getCategoryItem('Actions').click();
|
||||
nodeCreatorFeature.getters
|
||||
.getCategoryItem('Actions')
|
||||
.parent()
|
||||
.should('have.attr', 'data-category-collapsed', 'true');
|
||||
nodeCreatorFeature.getters
|
||||
.getCategoryItem('Triggers')
|
||||
.parent()
|
||||
.should('have.attr', 'data-category-collapsed', 'true');
|
||||
nodeCreatorFeature.getters.getCategoryItem('Triggers').click();
|
||||
nodeCreatorFeature.getters
|
||||
.getCategoryItem('Triggers')
|
||||
.parent()
|
||||
.should('have.attr', 'data-category-collapsed', 'false');
|
||||
});
|
||||
|
||||
it('should show callout and two suggested nodes if node has no trigger actions', () => {
|
||||
nodeCreatorFeature.actions.openNodeCreator();
|
||||
nodeCreatorFeature.getters.searchBar().find('input').clear().type('Customer Datastore (n8n training)');
|
||||
nodeCreatorFeature.getters
|
||||
.searchBar()
|
||||
.find('input')
|
||||
.clear()
|
||||
.type('Customer Datastore (n8n training)');
|
||||
nodeCreatorFeature.getters.getCreatorItem('Customer Datastore (n8n training)').click();
|
||||
|
||||
cy.getByTestId('actions-panel-no-triggers-callout').should('be.visible');
|
||||
@@ -165,28 +194,32 @@ describe('Node Creator', () => {
|
||||
|
||||
it('should show intro callout if user has not made a production execution', () => {
|
||||
nodeCreatorFeature.actions.openNodeCreator();
|
||||
nodeCreatorFeature.getters.searchBar().find('input').clear().type('Customer Datastore (n8n training)');
|
||||
nodeCreatorFeature.getters
|
||||
.searchBar()
|
||||
.find('input')
|
||||
.clear()
|
||||
.type('Customer Datastore (n8n training)');
|
||||
nodeCreatorFeature.getters.getCreatorItem('Customer Datastore (n8n training)').click();
|
||||
|
||||
cy.getByTestId('actions-panel-activation-callout').should('be.visible');
|
||||
nodeCreatorFeature.getters.activeSubcategory().find('button').click();
|
||||
nodeCreatorFeature.getters.searchBar().find('input').clear()
|
||||
nodeCreatorFeature.getters.searchBar().find('input').clear();
|
||||
|
||||
nodeCreatorFeature.getters.getCreatorItem('On a schedule').click();
|
||||
|
||||
// Setup 1s interval execution
|
||||
cy.getByTestId('parameter-input-field').click();
|
||||
cy.getByTestId('parameter-input-field')
|
||||
.find('.el-select-dropdown')
|
||||
.find('.option-headline')
|
||||
.contains('Seconds')
|
||||
.click();
|
||||
getVisibleSelect().find('.option-headline').contains('Seconds').click();
|
||||
cy.getByTestId('parameter-input-secondsInterval').clear().type('1');
|
||||
|
||||
NDVModal.actions.close();
|
||||
|
||||
nodeCreatorFeature.actions.openNodeCreator();
|
||||
nodeCreatorFeature.getters.searchBar().find('input').clear().type('Customer Datastore (n8n training)');
|
||||
nodeCreatorFeature.getters
|
||||
.searchBar()
|
||||
.find('input')
|
||||
.clear()
|
||||
.type('Customer Datastore (n8n training)');
|
||||
nodeCreatorFeature.getters.getCreatorItem('Customer Datastore (n8n training)').click();
|
||||
nodeCreatorFeature.getters.getCreatorItem('Get All People').click();
|
||||
NDVModal.actions.close();
|
||||
@@ -197,11 +230,15 @@ describe('Node Creator', () => {
|
||||
|
||||
// Wait for schedule 1s execution to mark user as having made a production execution
|
||||
cy.wait(1500);
|
||||
cy.reload()
|
||||
cy.reload();
|
||||
|
||||
// Action callout should not be visible after user has made a production execution
|
||||
nodeCreatorFeature.actions.openNodeCreator();
|
||||
nodeCreatorFeature.getters.searchBar().find('input').clear().type('Customer Datastore (n8n training)');
|
||||
nodeCreatorFeature.getters
|
||||
.searchBar()
|
||||
.find('input')
|
||||
.clear()
|
||||
.type('Customer Datastore (n8n training)');
|
||||
nodeCreatorFeature.getters.getCreatorItem('Customer Datastore (n8n training)').click();
|
||||
|
||||
cy.getByTestId('actions-panel-activation-callout').should('not.exist');
|
||||
@@ -210,7 +247,11 @@ describe('Node Creator', () => {
|
||||
it('should show Trigger and Actions sections during search', () => {
|
||||
nodeCreatorFeature.actions.openNodeCreator();
|
||||
|
||||
nodeCreatorFeature.getters.searchBar().find('input').clear().type('Customer Datastore (n8n training)');
|
||||
nodeCreatorFeature.getters
|
||||
.searchBar()
|
||||
.find('input')
|
||||
.clear()
|
||||
.type('Customer Datastore (n8n training)');
|
||||
nodeCreatorFeature.getters.getCreatorItem('Customer Datastore (n8n training)').click();
|
||||
|
||||
nodeCreatorFeature.getters.searchBar().find('input').clear().type('Non existent action name');
|
||||
@@ -228,7 +269,8 @@ describe('Node Creator', () => {
|
||||
{
|
||||
name: 'canvas add button',
|
||||
handler: () => nodeCreatorFeature.getters.canvasAddButton().click(),
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: 'plus button',
|
||||
handler: () => nodeCreatorFeature.getters.plusButton().click(),
|
||||
},
|
||||
@@ -238,10 +280,10 @@ describe('Node Creator', () => {
|
||||
// name: 'tab key',
|
||||
// handler: () => cy.realPress('Tab'),
|
||||
// },
|
||||
]
|
||||
];
|
||||
sourcesWithAppend.forEach((source) => {
|
||||
it(`should append manual trigger when source is ${source.name}`, () => {
|
||||
source.handler()
|
||||
source.handler();
|
||||
nodeCreatorFeature.getters.searchBar().find('input').clear().type('n8n');
|
||||
nodeCreatorFeature.getters.getCreatorItem('n8n').click();
|
||||
nodeCreatorFeature.getters.getCategoryItem('Actions').click();
|
||||
@@ -251,6 +293,7 @@ describe('Node Creator', () => {
|
||||
});
|
||||
});
|
||||
|
||||
// @TODO FIX ADDING 2 NODES IN ONE GO
|
||||
it('should not append manual trigger when source is canvas related', () => {
|
||||
nodeCreatorFeature.getters.canvasAddButton().click();
|
||||
nodeCreatorFeature.getters.searchBar().find('input').clear().type('n8n');
|
||||
@@ -258,8 +301,8 @@ describe('Node Creator', () => {
|
||||
nodeCreatorFeature.getters.getCategoryItem('Actions').click();
|
||||
nodeCreatorFeature.getters.getCreatorItem('Create a credential').click();
|
||||
NDVModal.actions.close();
|
||||
WorkflowPage.actions.deleteNode('When clicking "Execute Workflow"')
|
||||
WorkflowPage.getters.canvasNodePlusEndpointByName('n8n').click()
|
||||
WorkflowPage.actions.deleteNode('When clicking "Execute Workflow"');
|
||||
WorkflowPage.getters.canvasNodePlusEndpointByName('n8n').click();
|
||||
nodeCreatorFeature.getters.searchBar().find('input').clear().type('n8n');
|
||||
nodeCreatorFeature.getters.getCreatorItem('n8n').click();
|
||||
nodeCreatorFeature.getters.getCategoryItem('Actions').click();
|
||||
@@ -267,8 +310,8 @@ describe('Node Creator', () => {
|
||||
NDVModal.actions.close();
|
||||
WorkflowPage.getters.canvasNodes().should('have.length', 2);
|
||||
WorkflowPage.actions.zoomToFit();
|
||||
WorkflowPage.actions.addNodeBetweenNodes('n8n', 'n8n1', 'Item Lists', 'Summarize')
|
||||
WorkflowPage.actions.addNodeBetweenNodes('n8n', 'n8n1', 'Item Lists', 'Summarize');
|
||||
WorkflowPage.getters.canvasNodes().should('have.length', 3);
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -117,7 +117,7 @@ describe('NDV', () => {
|
||||
setupSchemaWorkflow();
|
||||
ndv.getters.outputDisplayMode().children().should('have.length', 3);
|
||||
ndv.getters.outputDisplayMode().find('[class*=active]').should('contain', 'Table');
|
||||
ndv.getters.outputDisplayMode().contains('Schema').click();
|
||||
ndv.actions.switchOutputMode('Schema');
|
||||
ndv.getters.outputDisplayMode().find('[class*=active]').should('contain', 'Schema');
|
||||
|
||||
schemaKeys.forEach((key) => {
|
||||
@@ -130,7 +130,7 @@ describe('NDV', () => {
|
||||
});
|
||||
it('should preserve schema view after execution', () => {
|
||||
setupSchemaWorkflow();
|
||||
ndv.getters.outputDisplayMode().contains('Schema').click();
|
||||
ndv.actions.switchOutputMode('Schema');
|
||||
ndv.actions.execute();
|
||||
ndv.getters.outputDisplayMode().find('[class*=active]').should('contain', 'Schema');
|
||||
});
|
||||
@@ -142,7 +142,7 @@ describe('NDV', () => {
|
||||
.outputPanel()
|
||||
.find('[data-test-id=run-data-schema-item]')
|
||||
.filter(':contains("objectValue")');
|
||||
ndv.getters.outputDisplayMode().contains('Schema').click();
|
||||
ndv.actions.switchOutputMode('Schema');
|
||||
|
||||
expandedObjectProps.forEach((key) => {
|
||||
ndv.getters
|
||||
@@ -173,9 +173,9 @@ describe('NDV', () => {
|
||||
ndv.actions.execute();
|
||||
ndv.getters.outputPanel().contains('25 items').should('exist');
|
||||
ndv.getters.outputPanel().find('[class*=_pagination]').should('exist');
|
||||
ndv.getters.outputDisplayMode().contains('Schema').click();
|
||||
ndv.actions.switchOutputMode('Schema');
|
||||
ndv.getters.outputPanel().find('[class*=_pagination]').should('not.exist');
|
||||
ndv.getters.outputDisplayMode().contains('JSON').click();
|
||||
ndv.actions.switchOutputMode('JSON');
|
||||
ndv.getters.outputPanel().find('[class*=_pagination]').should('exist');
|
||||
});
|
||||
it('should display large schema', () => {
|
||||
@@ -188,7 +188,7 @@ describe('NDV', () => {
|
||||
|
||||
ndv.getters.outputPanel().contains('20 items').should('exist');
|
||||
ndv.getters.outputPanel().find('[class*=_pagination]').should('exist');
|
||||
ndv.getters.outputDisplayMode().contains('Schema').click();
|
||||
ndv.actions.switchOutputMode('Schema');
|
||||
ndv.getters.outputPanel().find('[class*=_pagination]').should('not.exist');
|
||||
ndv.getters
|
||||
.outputPanel()
|
||||
|
||||
@@ -6,9 +6,11 @@ import {
|
||||
} from '../constants';
|
||||
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
|
||||
import { WorkflowsPage as WorkflowsPageClass } from '../pages/workflows';
|
||||
import { getVisibleDropdown, getVisibleSelect } from '../utils';
|
||||
|
||||
const NEW_WORKFLOW_NAME = 'Something else';
|
||||
const IMPORT_WORKFLOW_URL = 'https://gist.githubusercontent.com/OlegIvaniv/010bd3f45c8a94f8eb7012e663a8b671/raw/3afea1aec15573cc168d9af7e79395bd76082906/test-workflow.json';
|
||||
const IMPORT_WORKFLOW_URL =
|
||||
'https://gist.githubusercontent.com/OlegIvaniv/010bd3f45c8a94f8eb7012e663a8b671/raw/3afea1aec15573cc168d9af7e79395bd76082906/test-workflow.json';
|
||||
const DUPLICATE_WORKFLOW_NAME = 'Duplicated workflow';
|
||||
const DUPLICATE_WORKFLOW_TAG = 'Duplicate';
|
||||
|
||||
@@ -67,11 +69,11 @@ describe('Workflow Actions', () => {
|
||||
it('should not save workflow if canvas is loading', () => {
|
||||
let interceptCalledCount = 0;
|
||||
|
||||
// There's no way in Cypress to check if intercept was not called
|
||||
// There's no way in Cypress to check if intercept was not called
|
||||
// so we'll count the number of times it was called
|
||||
cy.intercept('PATCH', '/rest/workflows/*', () => {
|
||||
interceptCalledCount++;
|
||||
}).as('saveWorkflow');
|
||||
cy.intercept('PATCH', '/rest/workflows/*', () => {
|
||||
interceptCalledCount++;
|
||||
}).as('saveWorkflow');
|
||||
|
||||
WorkflowPage.actions.addNodeToCanvas(MANUAL_TRIGGER_NODE_NAME);
|
||||
WorkflowPage.actions.saveWorkflowOnButtonClick();
|
||||
@@ -84,11 +86,11 @@ describe('Workflow Actions', () => {
|
||||
(req) => {
|
||||
// Delay the response to give time for the save to be triggered
|
||||
req.on('response', async (res) => {
|
||||
await new Promise((resolve) => setTimeout(resolve, 2000))
|
||||
await new Promise((resolve) => setTimeout(resolve, 2000));
|
||||
res.send();
|
||||
})
|
||||
}
|
||||
)
|
||||
});
|
||||
},
|
||||
);
|
||||
cy.reload();
|
||||
cy.get('.el-loading-mask').should('exist');
|
||||
cy.get('body').type(META_KEY, { release: false }).type('s');
|
||||
@@ -99,7 +101,7 @@ describe('Workflow Actions', () => {
|
||||
cy.get('body').type(META_KEY, { release: false }).type('s');
|
||||
cy.wait('@saveWorkflow');
|
||||
cy.wrap(null).then(() => expect(interceptCalledCount).to.eq(1));
|
||||
})
|
||||
});
|
||||
it('should copy nodes', () => {
|
||||
WorkflowPage.actions.addNodeToCanvas(SCHEDULE_TRIGGER_NODE_NAME);
|
||||
WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME);
|
||||
@@ -127,7 +129,7 @@ describe('Workflow Actions', () => {
|
||||
cy.get('.el-message-box').should('be.visible');
|
||||
cy.get('.el-message-box').find('input').type(IMPORT_WORKFLOW_URL);
|
||||
cy.get('body').type('{enter}');
|
||||
cy.waitForLoad(false)
|
||||
cy.waitForLoad(false);
|
||||
WorkflowPage.actions.zoomToFit();
|
||||
WorkflowPage.getters.canvasNodes().should('have.length', 2);
|
||||
WorkflowPage.getters.nodeConnections().should('have.length', 1);
|
||||
@@ -137,7 +139,7 @@ describe('Workflow Actions', () => {
|
||||
WorkflowPage.getters
|
||||
.workflowImportInput()
|
||||
.selectFile('cypress/fixtures/Test_workflow-actions_paste-data.json', { force: true });
|
||||
cy.waitForLoad(false)
|
||||
cy.waitForLoad(false);
|
||||
WorkflowPage.actions.zoomToFit();
|
||||
WorkflowPage.getters.canvasNodes().should('have.length', 2);
|
||||
WorkflowPage.getters.nodeConnections().should('have.length', 1);
|
||||
@@ -157,57 +159,33 @@ describe('Workflow Actions', () => {
|
||||
WorkflowPage.getters.workflowMenuItemSettings().click();
|
||||
// Change all settings
|
||||
// totalWorkflows + 1 (current workflow) + 1 (no workflow option)
|
||||
WorkflowPage.getters.workflowSettingsErrorWorkflowSelect().find('li').should('have.length', totalWorkflows + 2);
|
||||
WorkflowPage.getters
|
||||
.workflowSettingsErrorWorkflowSelect()
|
||||
WorkflowPage.getters.workflowSettingsErrorWorkflowSelect().click();
|
||||
getVisibleSelect()
|
||||
.find('li')
|
||||
.last()
|
||||
.click({ force: true });
|
||||
WorkflowPage.getters.workflowSettingsTimezoneSelect().find('li').should('exist');
|
||||
WorkflowPage.getters.workflowSettingsTimezoneSelect().find('li').eq(1).click({ force: true });
|
||||
WorkflowPage.getters
|
||||
.workflowSettingsSaveFiledExecutionsSelect()
|
||||
.find('li')
|
||||
.should('have.length', 3);
|
||||
WorkflowPage.getters
|
||||
.workflowSettingsSaveFiledExecutionsSelect()
|
||||
.find('li')
|
||||
.last()
|
||||
.click({ force: true });
|
||||
WorkflowPage.getters
|
||||
.workflowSettingsSaveSuccessExecutionsSelect()
|
||||
.find('li')
|
||||
.should('have.length', 3);
|
||||
WorkflowPage.getters
|
||||
.workflowSettingsSaveSuccessExecutionsSelect()
|
||||
.find('li')
|
||||
.last()
|
||||
.click({ force: true });
|
||||
WorkflowPage.getters
|
||||
.workflowSettingsSaveManualExecutionsSelect()
|
||||
.find('li')
|
||||
.should('have.length', 3);
|
||||
WorkflowPage.getters
|
||||
.workflowSettingsSaveManualExecutionsSelect()
|
||||
.find('li')
|
||||
.last()
|
||||
.click({ force: true });
|
||||
WorkflowPage.getters
|
||||
.workflowSettingsSaveExecutionProgressSelect()
|
||||
.find('li')
|
||||
.should('have.length', 3);
|
||||
WorkflowPage.getters
|
||||
.workflowSettingsSaveExecutionProgressSelect()
|
||||
.find('li')
|
||||
.last()
|
||||
.click({ force: true });
|
||||
.should('have.length', totalWorkflows + 2);
|
||||
getVisibleSelect().find('li').last().click({ force: true });
|
||||
WorkflowPage.getters.workflowSettingsTimezoneSelect().click();
|
||||
getVisibleSelect().find('li').should('exist');
|
||||
getVisibleSelect().find('li').eq(1).click({ force: true });
|
||||
WorkflowPage.getters.workflowSettingsSaveFiledExecutionsSelect().click();
|
||||
getVisibleSelect().find('li').should('have.length', 3);
|
||||
getVisibleSelect().find('li').last().click({ force: true });
|
||||
WorkflowPage.getters.workflowSettingsSaveSuccessExecutionsSelect().click();
|
||||
getVisibleSelect().find('li').should('have.length', 3);
|
||||
getVisibleSelect().find('li').last().click({ force: true });
|
||||
WorkflowPage.getters.workflowSettingsSaveManualExecutionsSelect().click();
|
||||
getVisibleSelect().find('li').should('have.length', 3);
|
||||
getVisibleSelect().find('li').last().click({ force: true });
|
||||
WorkflowPage.getters.workflowSettingsSaveExecutionProgressSelect().click();
|
||||
getVisibleSelect().find('li').should('have.length', 3);
|
||||
getVisibleSelect().find('li').last().click({ force: true });
|
||||
WorkflowPage.getters.workflowSettingsTimeoutWorkflowSwitch().click();
|
||||
WorkflowPage.getters.workflowSettingsTimeoutForm().find('input').first().type('1');
|
||||
// Save settings
|
||||
WorkflowPage.getters.workflowSettingsSaveButton().click();
|
||||
WorkflowPage.getters.workflowSettingsModal().should('not.exist');
|
||||
WorkflowPage.getters.successToast().should('exist');
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
it('should not be able to delete unsaved workflow', () => {
|
||||
@@ -245,7 +223,7 @@ describe('Workflow Actions', () => {
|
||||
.find('.el-select__tags input')
|
||||
.type(DUPLICATE_WORKFLOW_TAG);
|
||||
WorkflowPage.getters.duplicateWorkflowModal().find('.el-select__tags input').type('{enter}');
|
||||
WorkflowPage.getters.duplicateWorkflowModal().find('.el-select__tags input').type('{enter}');
|
||||
WorkflowPage.getters.duplicateWorkflowModal().find('.el-select__tags input').type('{esc}');
|
||||
WorkflowPage.getters
|
||||
.duplicateWorkflowModal()
|
||||
.find('button')
|
||||
|
||||
@@ -5,7 +5,7 @@ export class CredentialsPage extends BasePage {
|
||||
getters = {
|
||||
emptyListCreateCredentialButton: () => cy.getByTestId('empty-resources-list').find('button'),
|
||||
createCredentialButton: () => cy.getByTestId('resources-list-add'),
|
||||
searchInput: () => cy.getByTestId('resources-list-search').find('input'),
|
||||
searchInput: () => cy.getByTestId('resources-list-search'),
|
||||
emptyList: () => cy.getByTestId('resources-list-empty'),
|
||||
credentialCards: () => cy.getByTestId('resources-list-item'),
|
||||
credentialCard: (credentialName: string) =>
|
||||
@@ -17,8 +17,8 @@ export class CredentialsPage extends BasePage {
|
||||
this.getters.credentialCard(credentialName).findChildByTestId('credential-card-actions'),
|
||||
credentialDeleteButton: () =>
|
||||
cy.getByTestId('action-toggle-dropdown').filter(':visible').contains('Delete'),
|
||||
sort: () => cy.getByTestId('resources-list-sort'),
|
||||
sortOption: (label: string) => this.getters.sort().contains(label).first(),
|
||||
sort: () => cy.getByTestId('resources-list-sort').first(),
|
||||
sortOption: (label: string) => cy.getByTestId('resources-list-sort-item').contains(label).first(),
|
||||
filtersTrigger: () => cy.getByTestId('resources-list-filters-trigger'),
|
||||
filtersDropdown: () => cy.getByTestId('resources-list-filters-dropdown'),
|
||||
};
|
||||
|
||||
@@ -20,7 +20,7 @@ export class CredentialsModal extends BasePage {
|
||||
credentialsEditModal: () => cy.getByTestId('credential-edit-dialog'),
|
||||
credentialsAuthTypeSelector: () => cy.getByTestId('node-auth-type-selector'),
|
||||
credentialAuthTypeRadioButtons: () =>
|
||||
this.getters.credentialsAuthTypeSelector().find('label[role=radio]'),
|
||||
this.getters.credentialsAuthTypeSelector().find('label.el-radio'),
|
||||
credentialInputs: () => cy.getByTestId('credential-connection-parameter'),
|
||||
menu: () => this.getters.editCredentialModal().get('.menu-container'),
|
||||
menuItem: (name: string) => this.getters.menu().get('.n8n-menu-item').contains(name),
|
||||
@@ -42,7 +42,7 @@ export class CredentialsModal extends BasePage {
|
||||
},
|
||||
save: (test = false) => {
|
||||
cy.intercept('POST', '/rest/credentials').as('saveCredential');
|
||||
this.getters.saveButton().click();
|
||||
this.getters.saveButton().click({ force: true });
|
||||
|
||||
cy.wait('@saveCredential');
|
||||
if (test) cy.wait('@testCredential');
|
||||
|
||||
@@ -5,15 +5,15 @@ export class MessageBox extends BasePage {
|
||||
modal: () => cy.get('.el-message-box', { withinSubject: null }),
|
||||
header: () => this.getters.modal().find('.el-message-box__title'),
|
||||
content: () => this.getters.modal().find('.el-message-box__content'),
|
||||
confirm: () => this.getters.modal().find('.btn--confirm'),
|
||||
cancel: () => this.getters.modal().find('.btn--cancel'),
|
||||
confirm: () => this.getters.modal().find('.btn--confirm').first(),
|
||||
cancel: () => this.getters.modal().find('.btn--cancel').first(),
|
||||
};
|
||||
actions = {
|
||||
confirm: () => {
|
||||
this.getters.confirm().click();
|
||||
this.getters.confirm().click({ force: true});
|
||||
},
|
||||
cancel: () => {
|
||||
this.getters.cancel().click();
|
||||
this.getters.cancel().click({ force: true});
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { BasePage } from './base';
|
||||
import { getVisibleSelect } from '../utils';
|
||||
|
||||
export class NDV extends BasePage {
|
||||
getters = {
|
||||
@@ -101,10 +102,11 @@ export class NDV extends BasePage {
|
||||
this.getters.parameterInput(parameterName).type(content);
|
||||
},
|
||||
selectOptionInParameterDropdown: (parameterName: string, content: string) => {
|
||||
this.getters.parameterInput(parameterName).find('.option-headline').contains(content).click();
|
||||
getVisibleSelect().find('.option-headline').contains(content).click();
|
||||
},
|
||||
dismissMappingTooltip: () => {
|
||||
cy.getByTestId('dismiss-mapping-tooltip').click();
|
||||
cy.getByTestId('dismiss-mapping-tooltip').should('not.be.visible');
|
||||
},
|
||||
rename: (newName: string) => {
|
||||
this.getters.nodeNameContainer().click();
|
||||
@@ -139,11 +141,11 @@ export class NDV extends BasePage {
|
||||
},
|
||||
changeInputRunSelector: (runName: string) => {
|
||||
this.getters.inputRunSelector().click();
|
||||
cy.get('.el-select-dropdown:visible .el-select-dropdown__item').contains(runName).click();
|
||||
getVisibleSelect().find('.el-select-dropdown__item').contains(runName).click();
|
||||
},
|
||||
changeOutputRunSelector: (runName: string) => {
|
||||
this.getters.outputRunSelector().click();
|
||||
cy.get('.el-select-dropdown:visible .el-select-dropdown__item').contains(runName).click();
|
||||
getVisibleSelect().find('.el-select-dropdown__item').contains(runName).click();
|
||||
},
|
||||
toggleOutputRunLinking: () => {
|
||||
this.getters.outputRunSelector().find('button').click();
|
||||
@@ -159,7 +161,7 @@ export class NDV extends BasePage {
|
||||
},
|
||||
setRLCValue: (paramName: string, value: string) => {
|
||||
this.getters.resourceLocatorModeSelector(paramName).click();
|
||||
this.getters.resourceLocatorModeSelector(paramName).find('li').last().click();
|
||||
getVisibleSelect().find('li').last().click();
|
||||
this.getters.resourceLocatorInput(paramName).type(value);
|
||||
},
|
||||
validateExpressionPreview: (paramName: string, value: string) => {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { BasePage } from './base';
|
||||
import { getVisibleSelect } from '../utils';
|
||||
|
||||
export class SettingsLogStreamingPage extends BasePage {
|
||||
url = '/settings/log-streaming';
|
||||
@@ -6,11 +7,9 @@ export class SettingsLogStreamingPage extends BasePage {
|
||||
getActionBoxUnlicensed: () => cy.getByTestId('action-box-unlicensed'),
|
||||
getActionBoxLicensed: () => cy.getByTestId('action-box-licensed'),
|
||||
getDestinationModal: () => cy.getByTestId('destination-modal'),
|
||||
getDestinationModalDialog: () => this.getters.getDestinationModal().find('.el-dialog'),
|
||||
getSelectDestinationType: () => cy.getByTestId('select-destination-type'),
|
||||
getDestinationNameInput: () => cy.getByTestId('subtitle-showing-type'),
|
||||
getSelectDestinationTypeItems: () =>
|
||||
this.getters.getSelectDestinationType().find('.el-select-dropdown__item'),
|
||||
getSelectDestinationTypeItems: () => getVisibleSelect().find('.el-select-dropdown__item'),
|
||||
getSelectDestinationButton: () => cy.getByTestId('select-destination-button'),
|
||||
getContactUsButton: () => this.getters.getActionBoxUnlicensed().find('button'),
|
||||
getAddFirstDestinationButton: () => this.getters.getActionBoxLicensed().find('button'),
|
||||
|
||||
@@ -11,7 +11,7 @@ export class PersonalSettingsPage extends BasePage {
|
||||
lastNameInput: () => cy.getByTestId('lastName').find('input').first(),
|
||||
emailInputContainer: () => cy.getByTestId('email'),
|
||||
emailInput: () => cy.getByTestId('email').find('input').first(),
|
||||
changePasswordLink: () => cy.getByTestId('change-password-link').find('a').first(),
|
||||
changePasswordLink: () => cy.getByTestId('change-password-link').first(),
|
||||
saveSettingsButton: () => cy.getByTestId('save-settings-button'),
|
||||
};
|
||||
actions = {
|
||||
@@ -34,7 +34,10 @@ export class PersonalSettingsPage extends BasePage {
|
||||
},
|
||||
tryToSetWeakPassword: (oldPassword: string, newPassword: string) => {
|
||||
this.actions.updatePassword(oldPassword, newPassword);
|
||||
changePasswordModal.getters.newPasswordInputContainer().find('div[class^="_errorInput"]').should('exist');
|
||||
changePasswordModal.getters
|
||||
.newPasswordInputContainer()
|
||||
.find('div[class^="_errorInput"]')
|
||||
.should('exist');
|
||||
},
|
||||
updateEmail: (newEmail: string) => {
|
||||
this.getters.emailInput().type('{selectall}').type(newEmail).type('{enter}');
|
||||
|
||||
@@ -4,8 +4,8 @@ import { WorkflowPage } from './workflow';
|
||||
import { WorkflowsPage } from './workflows';
|
||||
import { BasePage } from './base';
|
||||
|
||||
const workflowPage = new WorkflowPage();
|
||||
const workflowsPage = new WorkflowsPage();
|
||||
const workflowPage = new WorkflowPage();
|
||||
const workflowsPage = new WorkflowsPage();
|
||||
const mainSidebar = new MainSidebar();
|
||||
const settingsSidebar = new SettingsSidebar();
|
||||
|
||||
@@ -18,11 +18,15 @@ export class SettingsUsersPage extends BasePage {
|
||||
inviteUsersModalEmailsInput: () => cy.getByTestId('emails').find('input').first(),
|
||||
userListItems: () => cy.get('[data-test-id^="user-list-item"]'),
|
||||
userItem: (email: string) => cy.getByTestId(`user-list-item-${email.toLowerCase()}`),
|
||||
userActionsToggle: (email: string) => this.getters.userItem(email).find('[data-test-id="action-toggle"]'),
|
||||
deleteUserAction: () => cy.getByTestId('action-toggle-dropdown').find('li:contains("Delete"):visible'),
|
||||
userActionsToggle: (email: string) =>
|
||||
this.getters.userItem(email).find('[data-test-id="action-toggle"]'),
|
||||
deleteUserAction: () =>
|
||||
cy.getByTestId('action-toggle-dropdown').find('li:contains("Delete"):visible'),
|
||||
confirmDeleteModal: () => cy.getByTestId('deleteUser-modal').last(),
|
||||
transferDataRadioButton: () => this.getters.confirmDeleteModal().find('[role="radio"]').first(),
|
||||
deleteDataRadioButton: () => this.getters.confirmDeleteModal().find('[role="radio"]').last(),
|
||||
transferDataRadioButton: () =>
|
||||
this.getters.confirmDeleteModal().find('.el-radio .el-radio__input').first(),
|
||||
deleteDataRadioButton: () =>
|
||||
this.getters.confirmDeleteModal().find('.el-radio .el-radio__input').last(),
|
||||
userSelectDropDown: () => this.getters.confirmDeleteModal().find('.n8n-select'),
|
||||
userSelectOptions: () => cy.get('.el-select-dropdown:visible .el-select-dropdown__item'),
|
||||
deleteUserButton: () => this.getters.confirmDeleteModal().find('button:contains("Delete")'),
|
||||
|
||||
@@ -10,7 +10,7 @@ export class VariablesPage extends BasePage {
|
||||
goToUpgrade: () => cy.getByTestId('go-to-upgrade'),
|
||||
actionBox: () => cy.getByTestId('action-box'),
|
||||
emptyResourcesListNewVariableButton: () => this.getters.emptyResourcesList().find('button'),
|
||||
searchBar: () => cy.getByTestId('resources-list-search').find('input'),
|
||||
searchBar: () => cy.getByTestId('resources-list-search'),
|
||||
createVariableButton: () => cy.getByTestId('resources-list-add'),
|
||||
variablesRows: () => cy.getByTestId('variables-row'),
|
||||
variablesEditableRows: () =>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { META_KEY } from '../constants';
|
||||
import { BasePage } from './base';
|
||||
import { getVisibleSelect } from '../utils';
|
||||
|
||||
export class WorkflowPage extends BasePage {
|
||||
url = '/workflow/new';
|
||||
@@ -16,7 +17,7 @@ export class WorkflowPage extends BasePage {
|
||||
nthTagPill: (n: number) =>
|
||||
cy.get(`[data-test-id="workflow-tags-container"] span.tags > span:nth-child(${n})`),
|
||||
tagsDropdown: () => cy.getByTestId('workflow-tags-dropdown'),
|
||||
tagsInDropdown: () => cy.getByTestId('workflow-tags-dropdown').find('li').filter('.tag'),
|
||||
tagsInDropdown: () => getVisibleSelect().find('li').filter('.tag'),
|
||||
createTagButton: () => cy.getByTestId('new-tag-link'),
|
||||
saveButton: () => cy.getByTestId('workflow-save-button'),
|
||||
nodeCreatorSearchBar: () => cy.getByTestId('node-creator-search-bar'),
|
||||
@@ -37,8 +38,8 @@ export class WorkflowPage extends BasePage {
|
||||
canvasNodePlusEndpointByName: (nodeName: string, index = 0) => {
|
||||
return cy.get(this.getters.getEndpointSelector('plus', nodeName, index));
|
||||
},
|
||||
successToast: () => cy.get('.el-notification .el-icon-success').parent(),
|
||||
errorToast: () => cy.get('.el-notification .el-icon-error'),
|
||||
successToast: () => cy.get('.el-notification .el-notification--success').parent(),
|
||||
errorToast: () => cy.get('.el-notification .el-notification--error'),
|
||||
activatorSwitch: () => cy.getByTestId('workflow-activate-switch'),
|
||||
workflowMenu: () => cy.getByTestId('workflow-menu'),
|
||||
firstStepButton: () => cy.getByTestId('canvas-add-button'),
|
||||
@@ -84,7 +85,8 @@ export class WorkflowPage extends BasePage {
|
||||
duplicateWorkflowModal: () => cy.getByTestId('duplicate-modal'),
|
||||
nodeViewBackground: () => cy.getByTestId('node-view-background'),
|
||||
nodeView: () => cy.getByTestId('node-view'),
|
||||
inlineExpressionEditorInput: () => cy.getByTestId('inline-expression-editor-input').find('[role=textbox]'),
|
||||
inlineExpressionEditorInput: () =>
|
||||
cy.getByTestId('inline-expression-editor-input').find('[role=textbox]'),
|
||||
inlineExpressionEditorOutput: () => cy.getByTestId('inline-expression-editor-output'),
|
||||
zoomInButton: () => cy.getByTestId('zoom-in-button'),
|
||||
zoomOutButton: () => cy.getByTestId('zoom-out-button'),
|
||||
@@ -92,8 +94,10 @@ export class WorkflowPage extends BasePage {
|
||||
executeWorkflowButton: () => cy.getByTestId('execute-workflow-button'),
|
||||
clearExecutionDataButton: () => cy.getByTestId('clear-execution-data-button'),
|
||||
stopExecutionButton: () => cy.getByTestId('stop-execution-button'),
|
||||
stopExecutionWaitingForWebhookButton: () => cy.getByTestId('stop-execution-waiting-for-webhook-button'),
|
||||
stopExecutionWaitingForWebhookButton: () =>
|
||||
cy.getByTestId('stop-execution-waiting-for-webhook-button'),
|
||||
nodeCredentialsSelect: () => cy.getByTestId('node-credentials-select'),
|
||||
nodeCredentialsCreateOption: () => cy.getByTestId('node-credentials-select-item-new'),
|
||||
nodeCredentialsEditButton: () => cy.getByTestId('credential-edit-button'),
|
||||
nodeCreatorItems: () => cy.getByTestId('item-iterator-item'),
|
||||
ndvParameters: () => cy.getByTestId('parameter-item'),
|
||||
@@ -134,17 +138,17 @@ export class WorkflowPage extends BasePage {
|
||||
|
||||
this.getters.nodeCreatorSearchBar().type(nodeDisplayName);
|
||||
this.getters.nodeCreatorSearchBar().type('{enter}');
|
||||
cy.wait(500)
|
||||
cy.wait(500);
|
||||
cy.get('body').then((body) => {
|
||||
if(body.find('[data-test-id=node-creator]').length > 0) {
|
||||
if(action) {
|
||||
cy.contains(action).click()
|
||||
if (body.find('[data-test-id=node-creator]').length > 0) {
|
||||
if (action) {
|
||||
cy.contains(action).click();
|
||||
} else {
|
||||
// Select the first action
|
||||
cy.get('[data-keyboard-nav-type="action"]').eq(0).click()
|
||||
cy.get('[data-keyboard-nav-type="action"]').eq(0).click();
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
if (!preventNdvClose) cy.get('body').type('{esc}');
|
||||
},
|
||||
@@ -157,7 +161,8 @@ export class WorkflowPage extends BasePage {
|
||||
},
|
||||
openTagManagerModal: () => {
|
||||
this.getters.createTagButton().click();
|
||||
this.getters.tagsDropdown().find('li.manage-tags').first().click();
|
||||
this.getters.tagsDropdown().click();
|
||||
getVisibleSelect().find('li.manage-tags').first().click();
|
||||
},
|
||||
openInlineExpressionEditor: () => {
|
||||
cy.contains('Expression').invoke('show').click();
|
||||
@@ -209,7 +214,7 @@ export class WorkflowPage extends BasePage {
|
||||
this.getters.workflowTagsInput().type(tag);
|
||||
this.getters.workflowTagsInput().type('{enter}');
|
||||
});
|
||||
cy.get('body').type('{enter}');
|
||||
cy.get('body').click(0, 0);
|
||||
// For a brief moment the Element UI tag component shows the tags as(+X) string
|
||||
// so we need to wait for it to disappear
|
||||
this.getters.workflowTagsContainer().should('not.contain', `+${tags.length}`);
|
||||
@@ -241,7 +246,12 @@ export class WorkflowPage extends BasePage {
|
||||
executeWorkflow: () => {
|
||||
this.getters.executeWorkflowButton().click();
|
||||
},
|
||||
addNodeBetweenNodes: (sourceNodeName: string, targetNodeName: string, newNodeName: string, action?: string) => {
|
||||
addNodeBetweenNodes: (
|
||||
sourceNodeName: string,
|
||||
targetNodeName: string,
|
||||
newNodeName: string,
|
||||
action?: string,
|
||||
) => {
|
||||
this.getters.getConnectionBetweenNodes(sourceNodeName, targetNodeName).first().realHover();
|
||||
this.getters
|
||||
.getConnectionActionsBetweenNodes(sourceNodeName, targetNodeName)
|
||||
@@ -268,18 +278,10 @@ export class WorkflowPage extends BasePage {
|
||||
this.getters.addStickyButton().click();
|
||||
},
|
||||
deleteSticky: () => {
|
||||
this.getters.stickies().eq(0)
|
||||
.realHover()
|
||||
.find('[data-test-id="delete-sticky"]')
|
||||
.click();
|
||||
this.getters.stickies().eq(0).realHover().find('[data-test-id="delete-sticky"]').click();
|
||||
},
|
||||
editSticky: (content: string) => {
|
||||
this.getters.stickies()
|
||||
.dblclick()
|
||||
.find('textarea')
|
||||
.clear()
|
||||
.type(content)
|
||||
.type('{esc}');
|
||||
this.getters.stickies().dblclick().find('textarea').clear().type(content).type('{esc}');
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ export class WorkflowsPage extends BasePage {
|
||||
getters = {
|
||||
newWorkflowButtonCard: () => cy.getByTestId('new-workflow-card'),
|
||||
newWorkflowTemplateCard: () => cy.getByTestId('new-workflow-template-card'),
|
||||
searchBar: () => cy.getByTestId('resources-list-search').find('input'),
|
||||
searchBar: () => cy.getByTestId('resources-list-search'),
|
||||
createWorkflowButton: () => cy.getByTestId('resources-list-add'),
|
||||
workflowCards: () => cy.getByTestId('resources-list-item'),
|
||||
workflowCard: (workflowName: string) =>
|
||||
|
||||
@@ -53,12 +53,12 @@ Cypress.Commands.add('signin', ({ email, password }) => {
|
||||
});
|
||||
|
||||
Cypress.Commands.add('signout', () => {
|
||||
cy.request('POST', '/rest/logout');
|
||||
cy.request('POST', `${BACKEND_BASE_URL}/rest/logout`);
|
||||
cy.getCookie(N8N_AUTH_COOKIE).should('not.exist');
|
||||
});
|
||||
|
||||
Cypress.Commands.add('interceptREST', (method, url) => {
|
||||
cy.intercept(method, `http://localhost:5678/rest${url}`);
|
||||
cy.intercept(method, `${BACKEND_BASE_URL}/rest${url}`);
|
||||
});
|
||||
|
||||
const setFeature = (feature: string, enabled: boolean) =>
|
||||
|
||||
@@ -6,6 +6,10 @@ before(() => {
|
||||
owner: INSTANCE_OWNER,
|
||||
members: INSTANCE_MEMBERS,
|
||||
});
|
||||
|
||||
Cypress.on('uncaught:exception', (err) => {
|
||||
return !err.message.includes('ResizeObserver');
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
1
cypress/utils/index.ts
Normal file
1
cypress/utils/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './popper';
|
||||
3
cypress/utils/modal.ts
Normal file
3
cypress/utils/modal.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export function getVisibleModalOverlay() {
|
||||
return cy.get('.el-overlay .el-overlay-dialog').filter(':visible');
|
||||
}
|
||||
11
cypress/utils/popper.ts
Normal file
11
cypress/utils/popper.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
export function getVisiblePopper() {
|
||||
return cy.get('.el-popper').filter(':visible');
|
||||
}
|
||||
|
||||
export function getVisibleSelect() {
|
||||
return getVisiblePopper().filter('.el-select__popper');
|
||||
}
|
||||
|
||||
export function getVisibleDropdown() {
|
||||
return getVisiblePopper().filter('.el-dropdown__popper');
|
||||
}
|
||||
Reference in New Issue
Block a user