mirror of
https://github.com/n8n-io/n8n.git
synced 2025-02-21 02:56:40 -08:00
test: Update e2e tests for canvas specific actions (no-changelog) (#12614)
This commit is contained in:
parent
ac2f6476c1
commit
2d3b643f6e
|
@ -1,6 +1,7 @@
|
|||
import { getManualChatModal } from './modals/chat-modal';
|
||||
import { clickGetBackToCanvas, getParameterInputByName } from './ndv';
|
||||
import { ROUTES } from '../constants';
|
||||
import type { OpenContextMenuOptions } from '../types';
|
||||
|
||||
/**
|
||||
* Types
|
||||
|
@ -24,7 +25,36 @@ export type EndpointType =
|
|||
* Getters
|
||||
*/
|
||||
|
||||
export function getAddInputEndpointByType(nodeName: string, endpointType: EndpointType) {
|
||||
export function getCanvas() {
|
||||
return cy.getByTestId('canvas');
|
||||
}
|
||||
|
||||
export function getCanvasPane() {
|
||||
return cy.ifCanvasVersion(
|
||||
() => cy.getByTestId('node-view-background'),
|
||||
() => getCanvas().find('.vue-flow__pane'),
|
||||
);
|
||||
}
|
||||
|
||||
export function getContextMenu() {
|
||||
return cy.getByTestId('context-menu').find('.el-dropdown-menu');
|
||||
}
|
||||
|
||||
export function getContextMenuAction(action: string) {
|
||||
return cy.getByTestId(`context-menu-item-${action}`);
|
||||
}
|
||||
|
||||
export function getInputPlusHandle(nodeName: string) {
|
||||
return cy.ifCanvasVersion(
|
||||
() => cy.get(`.add-input-endpoint[data-endpoint-name="${nodeName}"]`),
|
||||
() =>
|
||||
cy.get(
|
||||
`[data-test-id="canvas-node-input-handle"][data-node-name="${nodeName}"] [data-test-id="canvas-handle-plus"]`,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
export function getInputPlusHandleByType(nodeName: string, endpointType: EndpointType) {
|
||||
return cy.ifCanvasVersion(
|
||||
() =>
|
||||
cy.get(
|
||||
|
@ -37,6 +67,29 @@ export function getAddInputEndpointByType(nodeName: string, endpointType: Endpoi
|
|||
);
|
||||
}
|
||||
|
||||
export function getOutputPlusHandle(nodeName: string) {
|
||||
return cy.ifCanvasVersion(
|
||||
() => cy.get(`.add-output-endpoint[data-endpoint-name="${nodeName}"]`),
|
||||
() =>
|
||||
cy.get(
|
||||
`[data-test-id="canvas-node-output-handle"][data-node-name="${nodeName}"] [data-test-id="canvas-handle-plus"]`,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
export function getOutputPlusHandleByType(nodeName: string, endpointType: EndpointType) {
|
||||
return cy.ifCanvasVersion(
|
||||
() =>
|
||||
cy.get(
|
||||
`.add-output-endpoint[data-jtk-scope-${endpointType}][data-endpoint-name="${nodeName}"]`,
|
||||
),
|
||||
() =>
|
||||
cy.get(
|
||||
`[data-test-id="canvas-node-output-handle"][data-connection-type="${endpointType}"][data-node-name="${nodeName}"] [data-test-id="canvas-handle-plus"]`,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
export function getNodeCreatorItems() {
|
||||
return cy.getByTestId('item-iterator-item');
|
||||
}
|
||||
|
@ -60,6 +113,13 @@ export function getNodeByName(name: string) {
|
|||
);
|
||||
}
|
||||
|
||||
export function getNodeRenderedTypeByName(name: string) {
|
||||
return cy.ifCanvasVersion(
|
||||
() => getNodeByName(name),
|
||||
() => getNodeByName(name).find('[data-canvas-node-render-type]'),
|
||||
);
|
||||
}
|
||||
|
||||
export function getWorkflowHistoryCloseButton() {
|
||||
return cy.getByTestId('workflow-history-close-button');
|
||||
}
|
||||
|
@ -85,6 +145,12 @@ export function getConnectionBySourceAndTarget(source: string, target: string) {
|
|||
);
|
||||
}
|
||||
|
||||
export function getConnectionLabelBySourceAndTarget(source: string, target: string) {
|
||||
return cy
|
||||
.getByTestId('edge-label')
|
||||
.filter(`[data-source-node-name="${source}"][data-target-node-name="${target}"]`);
|
||||
}
|
||||
|
||||
export function getNodeCreatorSearchBar() {
|
||||
return cy.getByTestId('node-creator-search-bar');
|
||||
}
|
||||
|
@ -94,10 +160,7 @@ export function getNodeCreatorPlusButton() {
|
|||
}
|
||||
|
||||
export function getCanvasNodes() {
|
||||
return cy.ifCanvasVersion(
|
||||
() => cy.getByTestId('canvas-node'),
|
||||
() => cy.getByTestId('canvas-node').not('[data-node-type="n8n-nodes-internal.addNodes"]'),
|
||||
);
|
||||
return cy.getByTestId('canvas-node');
|
||||
}
|
||||
|
||||
export function getCanvasNodeByName(nodeName: string) {
|
||||
|
@ -157,7 +220,7 @@ function connectNodeToParent(
|
|||
parentNodeName: string,
|
||||
exactMatch = false,
|
||||
) {
|
||||
getAddInputEndpointByType(parentNodeName, endpointType).click({ force: true });
|
||||
getInputPlusHandleByType(parentNodeName, endpointType).click({ force: true });
|
||||
if (exactMatch) {
|
||||
getNodeCreatorItems()
|
||||
.contains(new RegExp('^' + nodeName + '$', 'g'))
|
||||
|
@ -257,3 +320,34 @@ export function deleteNode(name: string) {
|
|||
getCanvasNodeByName(name).first().click();
|
||||
cy.get('body').type('{del}');
|
||||
}
|
||||
|
||||
export function openContextMenu(
|
||||
nodeName?: string,
|
||||
{ method = 'right-click', anchor = 'center' }: OpenContextMenuOptions = {},
|
||||
) {
|
||||
let target;
|
||||
if (nodeName) {
|
||||
target =
|
||||
method === 'right-click' ? getNodeRenderedTypeByName(nodeName) : getNodeByName(nodeName);
|
||||
} else {
|
||||
target = getCanvasPane();
|
||||
}
|
||||
|
||||
if (method === 'right-click') {
|
||||
target.rightclick(nodeName ? anchor : 'topLeft', { force: true });
|
||||
} else {
|
||||
target.realHover();
|
||||
target.find('[data-test-id="overflow-node-button"]').click({ force: true });
|
||||
}
|
||||
|
||||
cy.ifCanvasVersion(
|
||||
() => {},
|
||||
() => {
|
||||
getContextMenu().should('be.visible');
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function clickContextMenuAction(action: string) {
|
||||
getContextMenuAction(action).click();
|
||||
}
|
||||
|
|
|
@ -184,7 +184,11 @@ describe('Canvas Actions', () => {
|
|||
.last()
|
||||
.findChildByTestId('execute-node-button')
|
||||
.click({ force: true });
|
||||
|
||||
successToast().should('have.length', 1);
|
||||
|
||||
WorkflowPage.actions.executeNode(CODE_NODE_NAME);
|
||||
|
||||
successToast().should('have.length', 2);
|
||||
successToast().should('contain.text', 'Node executed successfully');
|
||||
});
|
||||
|
|
|
@ -7,9 +7,17 @@ import {
|
|||
SWITCH_NODE_NAME,
|
||||
MERGE_NODE_NAME,
|
||||
} from './../constants';
|
||||
import {
|
||||
clickContextMenuAction,
|
||||
getCanvasNodeByName,
|
||||
getCanvasNodes,
|
||||
getConnectionBySourceAndTarget,
|
||||
getConnectionLabelBySourceAndTarget,
|
||||
getOutputPlusHandle,
|
||||
openContextMenu,
|
||||
} from '../composables/workflow';
|
||||
import { NDV, WorkflowExecutionsTab } from '../pages';
|
||||
import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
|
||||
import { isCanvasV2 } from '../utils/workflowUtils';
|
||||
|
||||
const WorkflowPage = new WorkflowPageClass();
|
||||
const ExecutionsTab = new WorkflowExecutionsTab();
|
||||
|
@ -41,27 +49,52 @@ describe('Canvas Node Manipulation and Navigation', () => {
|
|||
|
||||
NDVDialog.actions.close();
|
||||
for (let i = 0; i < desiredOutputs; i++) {
|
||||
WorkflowPage.getters.canvasNodePlusEndpointByName(SWITCH_NODE_NAME, i).click({ force: true });
|
||||
cy.ifCanvasVersion(
|
||||
() => {
|
||||
WorkflowPage.getters
|
||||
.canvasNodePlusEndpointByName(SWITCH_NODE_NAME, i)
|
||||
.click({ force: true });
|
||||
},
|
||||
() => {
|
||||
getOutputPlusHandle(SWITCH_NODE_NAME).eq(0).click();
|
||||
},
|
||||
);
|
||||
WorkflowPage.getters.nodeCreatorSearchBar().should('be.visible');
|
||||
WorkflowPage.actions.addNodeToCanvas(EDIT_FIELDS_SET_NODE_NAME, false);
|
||||
WorkflowPage.actions.zoomToFit();
|
||||
}
|
||||
WorkflowPage.getters.nodeViewBackground().click({ force: true });
|
||||
WorkflowPage.getters.canvasNodePlusEndpointByName(`${EDIT_FIELDS_SET_NODE_NAME}3`).click();
|
||||
cy.ifCanvasVersion(
|
||||
() => {
|
||||
WorkflowPage.getters.canvasNodePlusEndpointByName(`${EDIT_FIELDS_SET_NODE_NAME}3`).click();
|
||||
},
|
||||
() => {
|
||||
getOutputPlusHandle(`${EDIT_FIELDS_SET_NODE_NAME}3`).click();
|
||||
},
|
||||
);
|
||||
WorkflowPage.actions.addNodeToCanvas(SWITCH_NODE_NAME, false);
|
||||
WorkflowPage.actions.saveWorkflowOnButtonClick();
|
||||
cy.reload();
|
||||
cy.waitForLoad();
|
||||
// Make sure outputless switch was connected correctly
|
||||
WorkflowPage.getters
|
||||
.getConnectionBetweenNodes(`${EDIT_FIELDS_SET_NODE_NAME}3`, `${SWITCH_NODE_NAME}1`)
|
||||
.should('exist');
|
||||
cy.ifCanvasVersion(
|
||||
() => {
|
||||
WorkflowPage.getters
|
||||
.getConnectionBetweenNodes(`${EDIT_FIELDS_SET_NODE_NAME}3`, `${SWITCH_NODE_NAME}1`)
|
||||
.should('exist');
|
||||
},
|
||||
() => {
|
||||
getConnectionBySourceAndTarget(
|
||||
`${EDIT_FIELDS_SET_NODE_NAME}3`,
|
||||
`${SWITCH_NODE_NAME}1`,
|
||||
).should('exist');
|
||||
},
|
||||
);
|
||||
// Make sure all connections are there after reload
|
||||
for (let i = 0; i < desiredOutputs; i++) {
|
||||
const setName = `${EDIT_FIELDS_SET_NODE_NAME}${i > 0 ? i : ''}`;
|
||||
WorkflowPage.getters
|
||||
.getConnectionBetweenNodes(`${SWITCH_NODE_NAME}`, setName)
|
||||
.should('exist');
|
||||
|
||||
getConnectionBySourceAndTarget(`${SWITCH_NODE_NAME}`, setName).should('exist');
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -84,14 +117,29 @@ describe('Canvas Node Manipulation and Navigation', () => {
|
|||
);
|
||||
|
||||
// Connect Set1 and Set2 to merge
|
||||
cy.draganddrop(
|
||||
WorkflowPage.getters.getEndpointSelector('plus', EDIT_FIELDS_SET_NODE_NAME),
|
||||
WorkflowPage.getters.getEndpointSelector('input', MERGE_NODE_NAME, 0),
|
||||
);
|
||||
cy.draganddrop(
|
||||
WorkflowPage.getters.getEndpointSelector('plus', `${EDIT_FIELDS_SET_NODE_NAME}1`),
|
||||
WorkflowPage.getters.getEndpointSelector('input', MERGE_NODE_NAME, 1),
|
||||
cy.ifCanvasVersion(
|
||||
() => {
|
||||
cy.draganddrop(
|
||||
WorkflowPage.getters.getEndpointSelector('plus', EDIT_FIELDS_SET_NODE_NAME),
|
||||
WorkflowPage.getters.getEndpointSelector('input', MERGE_NODE_NAME, 0),
|
||||
);
|
||||
cy.draganddrop(
|
||||
WorkflowPage.getters.getEndpointSelector('plus', `${EDIT_FIELDS_SET_NODE_NAME}1`),
|
||||
WorkflowPage.getters.getEndpointSelector('input', MERGE_NODE_NAME, 1),
|
||||
);
|
||||
},
|
||||
() => {
|
||||
cy.draganddrop(
|
||||
WorkflowPage.getters.getEndpointSelector('output', EDIT_FIELDS_SET_NODE_NAME),
|
||||
WorkflowPage.getters.getEndpointSelector('input', MERGE_NODE_NAME, 0),
|
||||
);
|
||||
cy.draganddrop(
|
||||
WorkflowPage.getters.getEndpointSelector('output', `${EDIT_FIELDS_SET_NODE_NAME}1`),
|
||||
WorkflowPage.getters.getEndpointSelector('input', MERGE_NODE_NAME, 1),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
const checkConnections = () => {
|
||||
WorkflowPage.getters
|
||||
.getConnectionBetweenNodes(
|
||||
|
@ -117,10 +165,22 @@ describe('Canvas Node Manipulation and Navigation', () => {
|
|||
WorkflowPage.actions.executeWorkflow();
|
||||
WorkflowPage.getters.stopExecutionButton().should('not.exist');
|
||||
|
||||
// Make sure all connections are there after save & reload
|
||||
WorkflowPage.actions.saveWorkflowOnButtonClick();
|
||||
cy.reload();
|
||||
cy.waitForLoad();
|
||||
checkConnections();
|
||||
|
||||
WorkflowPage.actions.executeWorkflow();
|
||||
WorkflowPage.getters.stopExecutionButton().should('not.exist');
|
||||
|
||||
// If the merged set nodes are connected and executed correctly, there should be 2 items in the output of merge node
|
||||
cy.ifCanvasVersion(
|
||||
() => cy.get('[data-label="2 items"]').should('be.visible'),
|
||||
() => cy.getByTestId('canvas-node-output-handle').contains('2 items').should('be.visible'),
|
||||
() =>
|
||||
getConnectionLabelBySourceAndTarget(`${EDIT_FIELDS_SET_NODE_NAME}1`, MERGE_NODE_NAME)
|
||||
.contains('2 items')
|
||||
.should('be.visible'),
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -144,7 +204,10 @@ describe('Canvas Node Manipulation and Navigation', () => {
|
|||
|
||||
cy.ifCanvasVersion(
|
||||
() => cy.get('.plus-draggable-endpoint').should('have.class', 'ep-success'),
|
||||
() => cy.getByTestId('canvas-handle-plus').should('have.attr', 'data-plus-type', 'success'),
|
||||
() =>
|
||||
cy
|
||||
.getByTestId('canvas-handle-plus-wrapper')
|
||||
.should('have.attr', 'data-plus-type', 'success'),
|
||||
);
|
||||
|
||||
WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME);
|
||||
|
@ -212,8 +275,8 @@ describe('Canvas Node Manipulation and Navigation', () => {
|
|||
WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME);
|
||||
cy.wait(500);
|
||||
WorkflowPage.actions.selectAllFromContextMenu();
|
||||
WorkflowPage.actions.openContextMenu();
|
||||
WorkflowPage.actions.contextMenuAction('delete');
|
||||
openContextMenu();
|
||||
clickContextMenuAction('delete');
|
||||
WorkflowPage.getters.canvasNodes().should('have.length', 0);
|
||||
});
|
||||
|
||||
|
@ -228,41 +291,43 @@ describe('Canvas Node Manipulation and Navigation', () => {
|
|||
WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME);
|
||||
cy.wait(500);
|
||||
WorkflowPage.actions.selectAllFromContextMenu();
|
||||
WorkflowPage.actions.openContextMenu();
|
||||
WorkflowPage.actions.contextMenuAction('delete');
|
||||
openContextMenu();
|
||||
clickContextMenuAction('delete');
|
||||
WorkflowPage.getters.canvasNodes().should('have.length', 0);
|
||||
});
|
||||
|
||||
// FIXME: Canvas V2: Figure out how to test moving of the node
|
||||
it('should move node', () => {
|
||||
WorkflowPage.actions.addNodeToCanvas(MANUAL_TRIGGER_NODE_NAME);
|
||||
WorkflowPage.getters.canvasNodeByName(MANUAL_TRIGGER_NODE_DISPLAY_NAME).click();
|
||||
WorkflowPage.actions.addNodeToCanvas(CODE_NODE_NAME);
|
||||
|
||||
WorkflowPage.actions.zoomToFit();
|
||||
WorkflowPage.getters
|
||||
.canvasNodes()
|
||||
|
||||
getCanvasNodes()
|
||||
.last()
|
||||
.then(($node) => {
|
||||
const { left, top } = $node.position();
|
||||
const { x: x1, y: y1 } = $node[0].getBoundingClientRect();
|
||||
|
||||
if (isCanvasV2()) {
|
||||
cy.drag('.vue-flow__node', [300, 300], {
|
||||
realMouse: true,
|
||||
});
|
||||
} else {
|
||||
cy.drag('[data-test-id="canvas-node"].jtk-drag-selected', [50, 150], {
|
||||
clickToFinish: true,
|
||||
});
|
||||
}
|
||||
cy.ifCanvasVersion(
|
||||
() => {
|
||||
cy.drag('[data-test-id="canvas-node"].jtk-drag-selected', [50, 150], {
|
||||
clickToFinish: true,
|
||||
});
|
||||
},
|
||||
() => {
|
||||
cy.drag(getCanvasNodes().last(), [50, 150], {
|
||||
realMouse: true,
|
||||
abs: true,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
WorkflowPage.getters
|
||||
.canvasNodes()
|
||||
getCanvasNodes()
|
||||
.last()
|
||||
.then(($node) => {
|
||||
const { left: newLeft, top: newTop } = $node.position();
|
||||
expect(newLeft).to.be.greaterThan(left);
|
||||
expect(newTop).to.be.greaterThan(top);
|
||||
const { x: x2, y: y2 } = $node[0].getBoundingClientRect();
|
||||
expect(x2).to.be.greaterThan(x1);
|
||||
expect(y2).to.be.greaterThan(y1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -369,7 +434,7 @@ describe('Canvas Node Manipulation and Navigation', () => {
|
|||
WorkflowPage.actions.hitDisableNodeShortcut();
|
||||
WorkflowPage.getters.disabledNodes().should('have.length', 0);
|
||||
WorkflowPage.actions.deselectAll();
|
||||
WorkflowPage.getters.canvasNodeByName(MANUAL_TRIGGER_NODE_DISPLAY_NAME).click();
|
||||
getCanvasNodeByName(MANUAL_TRIGGER_NODE_DISPLAY_NAME).click();
|
||||
WorkflowPage.actions.hitDisableNodeShortcut();
|
||||
WorkflowPage.getters.disabledNodes().should('have.length', 1);
|
||||
WorkflowPage.actions.hitSelectAll();
|
||||
|
@ -378,19 +443,19 @@ describe('Canvas Node Manipulation and Navigation', () => {
|
|||
|
||||
// Context menu
|
||||
WorkflowPage.actions.hitSelectAll();
|
||||
WorkflowPage.actions.openContextMenu();
|
||||
openContextMenu();
|
||||
WorkflowPage.actions.contextMenuAction('toggle_activation');
|
||||
WorkflowPage.getters.disabledNodes().should('have.length', 0);
|
||||
WorkflowPage.actions.openContextMenu();
|
||||
openContextMenu();
|
||||
WorkflowPage.actions.contextMenuAction('toggle_activation');
|
||||
WorkflowPage.getters.disabledNodes().should('have.length', 2);
|
||||
WorkflowPage.actions.deselectAll();
|
||||
WorkflowPage.getters.canvasNodeByName(MANUAL_TRIGGER_NODE_DISPLAY_NAME).click();
|
||||
WorkflowPage.actions.openContextMenu();
|
||||
openContextMenu();
|
||||
WorkflowPage.actions.contextMenuAction('toggle_activation');
|
||||
WorkflowPage.getters.disabledNodes().should('have.length', 1);
|
||||
WorkflowPage.actions.hitSelectAll();
|
||||
WorkflowPage.actions.openContextMenu();
|
||||
openContextMenu();
|
||||
WorkflowPage.actions.contextMenuAction('toggle_activation');
|
||||
WorkflowPage.getters.disabledNodes().should('have.length', 2);
|
||||
});
|
||||
|
@ -466,7 +531,7 @@ describe('Canvas Node Manipulation and Navigation', () => {
|
|||
WorkflowPage.getters.canvasNodes().should('have.length', 2);
|
||||
WorkflowPage.getters.nodeConnections().should('have.length', 1);
|
||||
});
|
||||
// FIXME: Canvas V2: Credentials should show issue on the first open
|
||||
|
||||
it('should remove unknown credentials on pasting workflow', () => {
|
||||
cy.fixture('workflow-with-unknown-credentials.json').then((data) => {
|
||||
cy.get('body').paste(JSON.stringify(data));
|
||||
|
|
|
@ -57,7 +57,7 @@ const editWorkflowMoreAndActivate = () => {
|
|||
position.left = $element.position().left;
|
||||
});
|
||||
|
||||
cy.drag('[data-test-id="canvas-node"].jtk-drag-selected', [50, 200], { clickToFinish: true });
|
||||
cy.drag('[data-test-id="canvas-node"].jtk-drag-selected', [50, 200]);
|
||||
workflowPage.getters
|
||||
.canvasNodes()
|
||||
.last()
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { BasePage } from './base';
|
||||
import { NodeCreator } from './features/node-creator';
|
||||
import { clickContextMenuAction, getCanvasPane, openContextMenu } from '../composables/workflow';
|
||||
import { META_KEY } from '../constants';
|
||||
import type { OpenContextMenuOptions } from '../types';
|
||||
import { getVisibleSelect } from '../utils';
|
||||
|
@ -38,15 +39,7 @@ export class WorkflowPage extends BasePage {
|
|||
nodeCreatorSearchBar: () => cy.getByTestId('node-creator-search-bar'),
|
||||
nodeCreatorPlusButton: () => cy.getByTestId('node-creator-plus-button'),
|
||||
canvasPlusButton: () => cy.getByTestId('canvas-plus-button'),
|
||||
canvasNodes: () =>
|
||||
cy.ifCanvasVersion(
|
||||
() => cy.getByTestId('canvas-node'),
|
||||
() =>
|
||||
cy
|
||||
.getByTestId('canvas-node')
|
||||
.not('[data-node-type="n8n-nodes-internal.addNodes"]')
|
||||
.not('[data-node-type="n8n-nodes-base.stickyNote"]'),
|
||||
),
|
||||
canvasNodes: () => cy.getByTestId('canvas-node'),
|
||||
canvasNodeByName: (nodeName: string) =>
|
||||
this.getters.canvasNodes().filter(`:contains(${nodeName})`),
|
||||
nodeIssuesByName: (nodeName: string) =>
|
||||
|
@ -110,7 +103,7 @@ export class WorkflowPage extends BasePage {
|
|||
disabledNodes: () =>
|
||||
cy.ifCanvasVersion(
|
||||
() => cy.get('.node-box.disabled'),
|
||||
() => cy.get('[data-test-id*="node"][class*="disabled"]'),
|
||||
() => cy.get('[data-canvas-node-render-type][class*="disabled"]'),
|
||||
),
|
||||
selectedNodes: () =>
|
||||
cy.ifCanvasVersion(
|
||||
|
@ -288,71 +281,77 @@ export class WorkflowPage extends BasePage {
|
|||
nodeTypeName?: string,
|
||||
{ method = 'right-click', anchor = 'center' }: OpenContextMenuOptions = {},
|
||||
) => {
|
||||
const target = nodeTypeName
|
||||
? this.getters.canvasNodeByName(nodeTypeName)
|
||||
: this.getters.nodeViewBackground();
|
||||
cy.ifCanvasVersion(
|
||||
() => {
|
||||
const target = nodeTypeName
|
||||
? this.getters.canvasNodeByName(nodeTypeName)
|
||||
: this.getters.nodeViewBackground();
|
||||
|
||||
if (method === 'right-click') {
|
||||
target.rightclick(nodeTypeName ? anchor : 'topLeft', { force: true });
|
||||
} else {
|
||||
target.realHover();
|
||||
target.find('[data-test-id="overflow-node-button"]').click({ force: true });
|
||||
}
|
||||
if (method === 'right-click') {
|
||||
target.rightclick(nodeTypeName ? anchor : 'topLeft', { force: true });
|
||||
} else {
|
||||
target.realHover();
|
||||
target.find('[data-test-id="overflow-node-button"]').click({ force: true });
|
||||
}
|
||||
},
|
||||
() => {
|
||||
openContextMenu(nodeTypeName, { method, anchor });
|
||||
},
|
||||
);
|
||||
},
|
||||
openNode: (nodeTypeName: string) => {
|
||||
this.getters.canvasNodeByName(nodeTypeName).first().dblclick();
|
||||
},
|
||||
duplicateNode: (nodeTypeName: string) => {
|
||||
this.actions.openContextMenu(nodeTypeName);
|
||||
this.actions.contextMenuAction('duplicate');
|
||||
clickContextMenuAction('duplicate');
|
||||
},
|
||||
deleteNodeFromContextMenu: (nodeTypeName: string) => {
|
||||
this.actions.openContextMenu(nodeTypeName);
|
||||
this.actions.contextMenuAction('delete');
|
||||
clickContextMenuAction('delete');
|
||||
},
|
||||
executeNode: (nodeTypeName: string, options?: OpenContextMenuOptions) => {
|
||||
this.actions.openContextMenu(nodeTypeName, options);
|
||||
this.actions.contextMenuAction('execute');
|
||||
clickContextMenuAction('execute');
|
||||
},
|
||||
addStickyFromContextMenu: () => {
|
||||
this.actions.openContextMenu();
|
||||
this.actions.contextMenuAction('add_sticky');
|
||||
clickContextMenuAction('add_sticky');
|
||||
},
|
||||
renameNode: (nodeTypeName: string) => {
|
||||
this.actions.openContextMenu(nodeTypeName);
|
||||
this.actions.contextMenuAction('rename');
|
||||
clickContextMenuAction('rename');
|
||||
},
|
||||
copyNode: (nodeTypeName: string) => {
|
||||
this.actions.openContextMenu(nodeTypeName);
|
||||
this.actions.contextMenuAction('copy');
|
||||
clickContextMenuAction('copy');
|
||||
},
|
||||
contextMenuAction: (action: string) => {
|
||||
this.getters.contextMenuAction(action).click();
|
||||
},
|
||||
disableNode: (nodeTypeName: string) => {
|
||||
this.actions.openContextMenu(nodeTypeName);
|
||||
this.actions.contextMenuAction('toggle_activation');
|
||||
clickContextMenuAction('toggle_activation');
|
||||
},
|
||||
pinNode: (nodeTypeName: string) => {
|
||||
this.actions.openContextMenu(nodeTypeName);
|
||||
this.actions.contextMenuAction('toggle_pin');
|
||||
clickContextMenuAction('toggle_pin');
|
||||
},
|
||||
openNodeFromContextMenu: (nodeTypeName: string) => {
|
||||
this.actions.openContextMenu(nodeTypeName, { method: 'overflow-button' });
|
||||
this.actions.contextMenuAction('open');
|
||||
clickContextMenuAction('open');
|
||||
},
|
||||
selectAllFromContextMenu: () => {
|
||||
this.actions.openContextMenu();
|
||||
this.actions.contextMenuAction('select_all');
|
||||
clickContextMenuAction('select_all');
|
||||
},
|
||||
deselectAll: () => {
|
||||
cy.ifCanvasVersion(
|
||||
() => {
|
||||
this.actions.openContextMenu();
|
||||
this.actions.contextMenuAction('deselect_all');
|
||||
clickContextMenuAction('deselect_all');
|
||||
},
|
||||
// rightclick doesn't work with vueFlow canvas
|
||||
() => this.getters.nodeViewBackground().click('topLeft'),
|
||||
() => getCanvasPane().click('topLeft'),
|
||||
);
|
||||
},
|
||||
openExpressionEditorModal: () => {
|
||||
|
@ -431,7 +430,7 @@ export class WorkflowPage extends BasePage {
|
|||
pinchToZoom: (steps: number, mode: 'zoomIn' | 'zoomOut' = 'zoomIn') => {
|
||||
cy.window().then((win) => {
|
||||
// Pinch-to-zoom simulates a 'wheel' event with ctrlKey: true (same as zooming by scrolling)
|
||||
this.getters.nodeView().trigger('wheel', {
|
||||
this.getters.canvasViewport().trigger('wheel', {
|
||||
force: true,
|
||||
bubbles: true,
|
||||
ctrlKey: true,
|
||||
|
|
|
@ -172,6 +172,7 @@ Cypress.Commands.add('drag', (selector, pos, options) => {
|
|||
};
|
||||
if (options?.realMouse) {
|
||||
element.realMouseDown();
|
||||
element.realMouseMove(0, 0);
|
||||
element.realMouseMove(newPosition.x, newPosition.y);
|
||||
element.realMouseUp();
|
||||
} else {
|
||||
|
@ -218,8 +219,15 @@ Cypress.Commands.add('draganddrop', (draggableSelector, droppableSelector, optio
|
|||
const pageY = coords.top + coords.height / 2;
|
||||
|
||||
if (draggableSelector) {
|
||||
// We can't use realMouseDown here because it hangs headless run
|
||||
cy.get(draggableSelector).trigger('mousedown');
|
||||
cy.ifCanvasVersion(
|
||||
() => {
|
||||
// We can't use realMouseDown here because it hangs headless run
|
||||
cy.get(draggableSelector).trigger('mousedown');
|
||||
},
|
||||
() => {
|
||||
cy.get(draggableSelector).realMouseDown();
|
||||
},
|
||||
);
|
||||
}
|
||||
// We don't chain these commands to make sure cy.get is re-trying correctly
|
||||
cy.get(droppableSelector).realMouseMove(0, 0);
|
||||
|
|
|
@ -29,7 +29,9 @@ function onActionSelect(item: string) {
|
|||
}
|
||||
|
||||
function closeMenu(event: MouseEvent) {
|
||||
event.preventDefault();
|
||||
if (event.cancelable) {
|
||||
event.preventDefault();
|
||||
}
|
||||
event.stopPropagation();
|
||||
contextMenu.close();
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import type {
|
|||
CanvasNodeEventBusEvents,
|
||||
CanvasEventBusEvents,
|
||||
} from '@/types';
|
||||
import { CanvasConnectionMode } from '@/types';
|
||||
import { CanvasNodeRenderType, CanvasConnectionMode } from '@/types';
|
||||
import NodeIcon from '@/components/NodeIcon.vue';
|
||||
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
|
||||
import CanvasNodeToolbar from '@/components/canvas/elements/nodes/CanvasNodeToolbar.vue';
|
||||
|
@ -107,6 +107,14 @@ const classes = computed(() => ({
|
|||
...Object.fromEntries([...nodeClasses.value].map((c) => [c, true])),
|
||||
}));
|
||||
|
||||
const renderType = computed<CanvasNodeRenderType>(() => props.data.render.type);
|
||||
|
||||
const dataTestId = computed(() =>
|
||||
[CanvasNodeRenderType.StickyNote, CanvasNodeRenderType.AddNodes].includes(renderType.value)
|
||||
? undefined
|
||||
: 'canvas-node',
|
||||
);
|
||||
|
||||
/**
|
||||
* Event bus
|
||||
*/
|
||||
|
@ -330,7 +338,7 @@ onBeforeUnmount(() => {
|
|||
<template>
|
||||
<div
|
||||
:class="classes"
|
||||
data-test-id="canvas-node"
|
||||
:data-test-id="dataTestId"
|
||||
:data-node-name="data.name"
|
||||
:data-node-type="data.type"
|
||||
>
|
||||
|
|
|
@ -13,8 +13,10 @@ const slots = defineSlots<{
|
|||
}>();
|
||||
|
||||
const Render = () => {
|
||||
const renderType = node?.data.value.render.type ?? CanvasNodeRenderType.Default;
|
||||
let Component;
|
||||
switch (node?.data.value.render.type) {
|
||||
|
||||
switch (renderType) {
|
||||
case CanvasNodeRenderType.StickyNote:
|
||||
Component = CanvasNodeStickyNote;
|
||||
break;
|
||||
|
@ -25,7 +27,13 @@ const Render = () => {
|
|||
Component = CanvasNodeDefault;
|
||||
}
|
||||
|
||||
return h(Component, slots.default);
|
||||
return h(
|
||||
Component,
|
||||
{
|
||||
'data-canvas-node-render-type': renderType,
|
||||
},
|
||||
slots.default,
|
||||
);
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
Loading…
Reference in a new issue