mirror of
https://github.com/n8n-io/n8n.git
synced 2024-11-09 22:24:05 -08:00
test: E2E NDV (#4712)
* test: start testing node details view * test: deleting workflow after test * test: rename deleteWorkflow command * test: webhook node * test: roll back deleting workflow in workflow test * test: check output display modes after webhook node invoked * test: simplifying test * test: simplifying test * test: adding more tests related to NDV * test: adding more tests related to NDV * test: update after merge * Merge remote-tracking branch 'origin/master' into n8n-5494-e2e-ndv # Conflicts: # cypress/pages/workflow.ts * test: improving test blocks * test: NDV change node input * test: NDV change node input * test: NDV fix missing command * test(editor): Add NDV page object
This commit is contained in:
parent
00bed61b39
commit
430cc65a4e
66
cypress/e2e/5-ndv.cy.ts
Normal file
66
cypress/e2e/5-ndv.cy.ts
Normal file
|
@ -0,0 +1,66 @@
|
|||
import { WorkflowsPage, WorkflowPage, NDV } from '../pages';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
const workflowsPage = new WorkflowsPage();
|
||||
const workflowPage = new WorkflowPage();
|
||||
const ndv = new NDV();
|
||||
|
||||
describe('NDV', () => {
|
||||
beforeEach(() => {
|
||||
cy.resetAll();
|
||||
cy.skipSetup();
|
||||
workflowsPage.actions.createWorkflowFromCard();
|
||||
workflowPage.actions.renameWorkflow(uuid());
|
||||
workflowPage.actions.saveWorkflowOnButtonClick();
|
||||
});
|
||||
|
||||
it('should show up when double clicked on a node and close when Back to canvas clicked', () => {
|
||||
workflowPage.actions.addInitialNodeToCanvas('Manual Trigger');
|
||||
workflowPage.getters.canvasNodes().first().dblclick();
|
||||
ndv.getters.container().should('be.visible');
|
||||
ndv.getters.backToCanvas().click()
|
||||
ndv.getters.container().should('not.be.visible');
|
||||
});
|
||||
|
||||
it('should test webhook node', () => {
|
||||
workflowPage.actions.addInitialNodeToCanvas('Webhook');
|
||||
workflowPage.getters.canvasNodes().first().dblclick();
|
||||
|
||||
ndv.getters.nodeExecuteButton().first().click();
|
||||
ndv.getters.copyInput().click();
|
||||
|
||||
cy.wrap(Cypress.automation('remote:debugger:protocol', {
|
||||
command: 'Browser.grantPermissions',
|
||||
params: {
|
||||
permissions: ['clipboardReadWrite', 'clipboardSanitizedWrite'],
|
||||
origin: window.location.origin,
|
||||
},
|
||||
}));
|
||||
|
||||
cy.window().its('navigator.permissions')
|
||||
.invoke('query', {name: 'clipboard-read'})
|
||||
.its('state').should('equal', 'granted');
|
||||
|
||||
cy.window().its('navigator.clipboard').invoke('readText').then(url => {
|
||||
cy.request({
|
||||
method: 'GET',
|
||||
url,
|
||||
}).then((resp) => {
|
||||
expect(resp.status).to.eq(200)
|
||||
})
|
||||
});
|
||||
|
||||
ndv.getters.runDataDisplayMode().should('have.length.at.least', 1).and('be.visible');
|
||||
});
|
||||
|
||||
it('should change input', () => {
|
||||
cy.createFixtureWorkflow('NDV-test-select-input.json', `NDV test select input ${uuid()}`);
|
||||
workflowPage.actions.zoomToFit();
|
||||
workflowPage.getters.canvasNodes().last().dblclick();
|
||||
ndv.getters.inputSelect().click();
|
||||
ndv.getters.inputOption().last().click();
|
||||
ndv.getters.inputPanel().within(() => {
|
||||
ndv.getters.dataContainer().should('contain', 'start');
|
||||
});
|
||||
});
|
||||
});
|
83
cypress/fixtures/NDV-test-select-input.json
Normal file
83
cypress/fixtures/NDV-test-select-input.json
Normal file
|
@ -0,0 +1,83 @@
|
|||
{
|
||||
"name": "ff739753-9d6e-46a7-94d3-25bd03dd4973",
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "c30d1114-d7f7-44dc-b55a-15312ef2d76d",
|
||||
"name": "On clicking 'execute'",
|
||||
"type": "n8n-nodes-base.manualTrigger",
|
||||
"typeVersion": 1,
|
||||
"position": [
|
||||
600,
|
||||
580
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"options": {}
|
||||
},
|
||||
"id": "5bf514bd-65ae-4a1c-8b69-a01bfeaad411",
|
||||
"name": "Set",
|
||||
"type": "n8n-nodes-base.set",
|
||||
"typeVersion": 1,
|
||||
"position": [
|
||||
820,
|
||||
580
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"options": {}
|
||||
},
|
||||
"id": "02bf49e9-44b2-4f4e-8cb2-8c02399208af",
|
||||
"name": "Set1",
|
||||
"type": "n8n-nodes-base.set",
|
||||
"typeVersion": 1,
|
||||
"position": [
|
||||
1040,
|
||||
580
|
||||
]
|
||||
}
|
||||
],
|
||||
"pinData": {
|
||||
"On clicking 'execute'": [
|
||||
{
|
||||
"json": {
|
||||
"start": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"connections": {
|
||||
"On clicking 'execute'": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Set",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Set": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Set1",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"active": false,
|
||||
"settings": {},
|
||||
"hash": "abd7b28aa2605c96ba24474d72cbe610",
|
||||
"id": 3,
|
||||
"meta": {
|
||||
"instanceId": "08a83d394781701f5c18052cde68e8d92c88b26f5cc8809eb10ad545f14015cb"
|
||||
},
|
||||
"tags": []
|
||||
}
|
|
@ -6,3 +6,4 @@ export * from './workflows';
|
|||
export * from './workflow';
|
||||
export * from './modals';
|
||||
export * from './settings-users';
|
||||
export * from './ndv';
|
||||
|
|
16
cypress/pages/ndv.ts
Normal file
16
cypress/pages/ndv.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
import { BasePage } from "./base";
|
||||
|
||||
export class NDV extends BasePage {
|
||||
getters = {
|
||||
container: () => cy.getByTestId('ndv'),
|
||||
backToCanvas: () => cy.getByTestId('back-to-canvas'),
|
||||
copyInput: () => cy.getByTestId('copy-input'),
|
||||
nodeExecuteButton: () => cy.getByTestId('node-execute-button'),
|
||||
inputSelect: () => cy.getByTestId('ndv-input-select'),
|
||||
inputOption: () => cy.getByTestId('ndv-input-option'),
|
||||
inputPanel: () => cy.getByTestId('ndv-input-panel'),
|
||||
dataContainer: () => cy.getByTestId('ndv-data-container'),
|
||||
runDataDisplayMode: () => cy.getByTestId('ndv-run-data-display-mode'),
|
||||
digital: () => cy.getByTestId('ndv-run-data-display-mode'),
|
||||
}
|
||||
}
|
|
@ -11,17 +11,11 @@ export class WorkflowPage extends BasePage {
|
|||
workflowTagsContainer: () => cy.getByTestId('workflow-tags-container'),
|
||||
newTagLink: () => cy.getByTestId('new-tag-link'),
|
||||
saveButton: () => cy.getByTestId('workflow-save-button'),
|
||||
|
||||
nodeCreatorSearchBar: () => cy.getByTestId('node-creator-search-bar'),
|
||||
nodeCreatorPlusButton: () => cy.getByTestId('node-creator-plus-button'),
|
||||
canvasPlusButton: () => cy.getByTestId('canvas-plus-button'),
|
||||
canvasNodeBox: (nodeDisplayName: string) => {
|
||||
return cy
|
||||
.getByTestId('canvas-node-box-title')
|
||||
.contains(nodeDisplayName)
|
||||
.parents('[data-test-id="canvas-node-box"]');
|
||||
},
|
||||
|
||||
canvasNodes: () => cy.getByTestId('canvas-node'),
|
||||
canvasNodeByName: (nodeName: string) => this.getters.canvasNodes().filter(`:contains("${nodeName}")`),
|
||||
ndvParameterInput: (parameterName: string) =>
|
||||
cy.getByTestId(`parameter-input-${parameterName}`),
|
||||
ndvOutputPanel: () => cy.getByTestId('output-panel'),
|
||||
|
@ -51,7 +45,7 @@ export class WorkflowPage extends BasePage {
|
|||
this.getters.nodeCreatorSearchBar().type('{enter}{esc}');
|
||||
},
|
||||
openNodeNdv: (nodeTypeName: string) => {
|
||||
this.getters.canvasNodeBox(nodeTypeName).dblclick();
|
||||
this.getters.canvasNodeByName(nodeTypeName).dblclick();
|
||||
},
|
||||
typeIntoParameterInput: (parameterName: string, content: string) => {
|
||||
this.getters.ndvParameterInput(parameterName).type(content);
|
||||
|
@ -94,5 +88,8 @@ export class WorkflowPage extends BasePage {
|
|||
});
|
||||
cy.get('body').type('{enter}');
|
||||
},
|
||||
zoomToFit: () => {
|
||||
cy.getByTestId('zoom-to-fit').click();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -29,5 +29,12 @@ export class WorkflowsPage extends BasePage {
|
|||
createWorkflowFromCard: () => {
|
||||
this.getters.newWorkflowButtonCard().click();
|
||||
},
|
||||
deleteWorkFlow: (name: string) => {
|
||||
cy.visit(this.url);
|
||||
this.getters.workflowCardActions(name).click();
|
||||
this.getters.workflowDeleteButton().click();
|
||||
|
||||
cy.get('button').contains('delete').click();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
<template>
|
||||
<div
|
||||
:class="{ [$style.zoomMenu]: true, [$style.regularZoomMenu]: !isDemo, [$style.demoZoomMenu]: isDemo }">
|
||||
<div :class="{ [$style.zoomMenu]: true, [$style.regularZoomMenu]: !isDemo, [$style.demoZoomMenu]: isDemo }">
|
||||
<n8n-icon-button @click="zoomToFit" type="tertiary" size="large" :title="$locale.baseText('nodeView.zoomToFit')"
|
||||
icon="expand" />
|
||||
icon="expand"
|
||||
data-test-id="zoom-to-fit" />
|
||||
/>
|
||||
<n8n-icon-button @click="zoomIn" type="tertiary" size="large" :title="$locale.baseText('nodeView.zoomIn')"
|
||||
icon="search-plus" />
|
||||
<n8n-icon-button @click="zoomOut" type="tertiary" size="large" :title="$locale.baseText('nodeView.zoomOut')"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div>
|
||||
<n8n-input-label :label="label">
|
||||
<div :class="{[$style.copyText]: true, [$style[size]]: true, [$style.collapsed]: collapse}" @click="copy">
|
||||
<div :class="{[$style.copyText]: true, [$style[size]]: true, [$style.collapsed]: collapse}" @click="copy" data-test-id="copy-input">
|
||||
<span ref="copyInputValue">{{ value }}</span>
|
||||
<div :class="$style.copyButton"><span>{{ copyButtonText }}</span></div>
|
||||
</div>
|
||||
|
|
|
@ -20,14 +20,15 @@
|
|||
@unlinkRun="onUnlinkRun"
|
||||
@runChange="onRunIndexChange"
|
||||
@tableMounted="$emit('tableMounted', $event)"
|
||||
data-test-id="ndv-input-panel"
|
||||
>
|
||||
<template #header>
|
||||
<div :class="$style.titleSection">
|
||||
<n8n-select v-if="parentNodes.length" :popper-append-to-body="true" size="small" :value="currentNodeName" @input="onSelect" :no-data-text="$locale.baseText('ndv.input.noNodesFound')" :placeholder="$locale.baseText('ndv.input.parentNodes')" filterable>
|
||||
<n8n-select v-if="parentNodes.length" :popper-append-to-body="true" size="small" :value="currentNodeName" @input="onSelect" :no-data-text="$locale.baseText('ndv.input.noNodesFound')" :placeholder="$locale.baseText('ndv.input.parentNodes')" filterable data-test-id="ndv-input-select">
|
||||
<template #prepend>
|
||||
<span :class="$style.title">{{ $locale.baseText('ndv.input') }}</span>
|
||||
</template>
|
||||
<n8n-option v-for="node of parentNodes" :value="node.name" :key="node.name" class="node-option" :label="`${truncate(node.name)} ${getMultipleNodesText(node.name)}`">
|
||||
<n8n-option v-for="node of parentNodes" :value="node.name" :key="node.name" class="node-option" :label="`${truncate(node.name)} ${getMultipleNodesText(node.name)}`" data-test-id="ndv-input-option">
|
||||
{{ truncate(node.name) }}
|
||||
<span v-if="getMultipleNodesText(node.name)">{{ getMultipleNodesText(node.name) }}</span>
|
||||
<span v-else>{{ $locale.baseText('ndv.input.nodeDistance', {adjustToNumber: node.depth}) }}</span>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="node-wrapper" :style="nodePosition" :id="nodeId" data-test-id="canvas-node-box">
|
||||
<div class="node-wrapper" :style="nodePosition" :id="nodeId" data-test-id="canvas-node">
|
||||
<div class="select-background" v-show="isSelected"></div>
|
||||
<div :class="{'node-default': true, 'touch-active': isTouchActive, 'is-touch-device': isTouchDevice}" :data-name="data.name" :ref="data.name">
|
||||
<div :class="nodeClass" :style="nodeStyle" @click.left="onClick" v-touch:start="touchStart" v-touch:end="touchEnd">
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
class="ndv-wrapper"
|
||||
width="auto"
|
||||
append-to-body
|
||||
data-test-id="ndv"
|
||||
>
|
||||
<n8n-tooltip
|
||||
placement="bottom-start"
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
</template>
|
||||
<div>
|
||||
<n8n-button
|
||||
data-test-id="node-execute-button"
|
||||
:loading="nodeRunning && !isListeningForEvents && !isListeningForWorkflowEvents"
|
||||
:disabled="disabled || !!disabledHint"
|
||||
:label="buttonLabel"
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
@tableMounted="$emit('tableMounted', $event)"
|
||||
@itemHover="$emit('itemHover', $event)"
|
||||
ref="runData"
|
||||
data-test-id="ndv-output-panel"
|
||||
>
|
||||
<template #header>
|
||||
<div :class="$style.titleSection">
|
||||
|
@ -47,8 +48,8 @@
|
|||
</template>
|
||||
|
||||
<template #node-not-run>
|
||||
<n8n-text v-if="workflowRunning && !isTriggerNode">{{ $locale.baseText('ndv.output.waitingToRun') }}</n8n-text>
|
||||
<n8n-text v-if="!workflowRunning">
|
||||
<n8n-text v-if="workflowRunning && !isTriggerNode" data-test-id="ndv-output-waiting">{{ $locale.baseText('ndv.output.waitingToRun') }}</n8n-text>
|
||||
<n8n-text v-if="!workflowRunning" data-test-id="ndv-output-run-node-hint">
|
||||
{{ $locale.baseText('ndv.output.runNodeHint') }}
|
||||
<span @click="insertTestData" v-if="canPinData">
|
||||
<br>
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
:value="displayMode"
|
||||
:options="buttons"
|
||||
@input="onDisplayModeChange"
|
||||
data-test-id="ndv-run-data-display-mode"
|
||||
/>
|
||||
<n8n-icon-button
|
||||
v-if="canPinData && !isReadOnly"
|
||||
|
@ -133,6 +134,7 @@
|
|||
<div
|
||||
:class="$style['data-container']"
|
||||
ref="dataContainer"
|
||||
data-test-id="ndv-data-container"
|
||||
>
|
||||
<div v-if="isExecuting" :class="$style.center">
|
||||
<div :class="$style.spinner"><n8n-spinner type="ring" /></div>
|
||||
|
|
Loading…
Reference in a new issue