test(props): add tests for node and edge event handlers

This commit is contained in:
moklick
2022-08-30 15:58:08 +02:00
parent ba9df1035b
commit e59307bbc1
9 changed files with 200 additions and 29 deletions

View File

@@ -17,7 +17,7 @@ describe('<ReactFlow />: Basic Props', () => {
it('drags a node', () => {
const styleBeforeDrag = Cypress.$('.react-flow__node:first').css('transform');
cy.drag('.react-flow__node:first', { x: 200, y: 25 }).then(($el: any) => {
cy.drag('.react-flow__node:first', { x: 200, y: 25 }).then(($el: JQuery<HTMLElement>) => {
const styleAfterDrag = $el.css('transform');
expect(styleBeforeDrag).to.not.equal(styleAfterDrag);
});
@@ -43,7 +43,7 @@ describe('<ReactFlow />: Basic Props', () => {
it('can not drag a node', () => {
const styleBeforeDrag = Cypress.$('.react-flow__node:first').css('transform');
cy.drag('.react-flow__node:first', { x: 200, y: 25 }).then(($el: any) => {
cy.drag('.react-flow__node:first', { x: 200, y: 25 }).then(($el: JQuery<HTMLElement>) => {
const styleAfterDrag = $el.css('transform');
expect(styleBeforeDrag).to.equal(styleAfterDrag);
});
@@ -63,7 +63,7 @@ describe('<ReactFlow />: Basic Props', () => {
it('drags a node', () => {
const styleBeforeDrag = Cypress.$('.react-flow__node:first').css('transform');
cy.drag('.react-flow__node:first', { x: 200, y: 25 }).then(($el: any) => {
cy.drag('.react-flow__node:first', { x: 200, y: 25 }).then(($el: JQuery<HTMLElement>) => {
const styleAfterDrag = $el.css('transform');
expect(styleBeforeDrag).to.not.equal(styleAfterDrag);
});
@@ -195,5 +195,3 @@ describe('<ReactFlow />: Basic Props', () => {
cy.get('.react-flow').should('have.class', 'custom');
});
});
// test specific helper component

View File

@@ -0,0 +1,168 @@
import { skipOn } from '@cypress/skip-test';
import { nodes, edges } from '../../fixtures/simpleflow';
import ControlledFlow from '../../support/ControlledFlow';
describe('<ReactFlow />: Event handlers', () => {
describe('Node event handlers', () => {
it('handles onInit', () => {
const onInitSpy = cy.spy().as('onInitSpy');
cy.mount(<ControlledFlow initialNodes={nodes} initialEdges={edges} onInit={onInitSpy} />)
.wait(100)
.then(() => {
expect(onInitSpy.callCount).to.be.eq(1);
});
});
it('handles onNodeClick', () => {
const onNodeClickSpy = cy.spy().as('onNodeClickSpy');
cy.mount(<ControlledFlow initialNodes={nodes} initialEdges={edges} onNodeClick={onNodeClickSpy} />).then(() => {
expect(onNodeClickSpy.callCount).to.be.eq(0);
cy.get('.react-flow__node:first')
.click()
.then(() => {
expect(onNodeClickSpy.callCount).to.be.eq(1);
});
});
});
it('handles onNodeDrag handlers', () => {
const onNodeDragStart = cy.spy().as('onNodeDragStart');
const onNodeDrag = cy.spy().as('onNodeDrag');
const onNodeDragStop = cy.spy().as('onNodeDragStop');
cy.mount(
<ControlledFlow
initialNodes={nodes}
initialEdges={edges}
onNodeDragStart={onNodeDragStart}
onNodeDrag={onNodeDrag}
onNodeDragStop={onNodeDragStop}
/>
).then(() => {
expect(onNodeDragStart.callCount).to.be.eq(0);
expect(onNodeDrag.callCount).to.be.eq(0);
expect(onNodeDragStop.callCount).to.be.eq(0);
cy.drag('.react-flow__node:first', { x: 200, y: 0 }).then(() => {
expect(onNodeDragStart.callCount).to.be.eq(1);
expect(onNodeDrag.callCount).to.be.eq(1);
expect(onNodeDragStop.callCount).to.be.eq(1);
});
});
});
it('handles onNodeMouse handlers', () => {
const onNodeMouseEnter = cy.spy().as('onNodeMouseEnter');
const onNodeMouseMove = cy.spy().as('onNodeMouseMove');
const onNodeMouseLeave = cy.spy().as('onNodeMouseLeave');
const onNodeContextMenu = cy.spy().as('onNodeContextMenu');
const onNodeDoubleClick = cy.spy().as('onNodeDoubleClick');
cy.mount(
<ControlledFlow
initialNodes={nodes}
initialEdges={edges}
onNodeMouseEnter={onNodeMouseEnter}
onNodeMouseMove={onNodeMouseMove}
onNodeMouseLeave={onNodeMouseLeave}
onNodeContextMenu={onNodeContextMenu}
onNodeDoubleClick={onNodeDoubleClick}
/>
)
.wait(200)
.then(() => {
expect(onNodeMouseEnter.callCount).to.be.eq(0);
expect(onNodeMouseMove.callCount).to.be.eq(0);
expect(onNodeMouseLeave.callCount).to.be.eq(0);
expect(onNodeContextMenu.callCount).to.be.eq(0);
expect(onNodeDoubleClick.callCount).to.be.eq(0);
const node = cy.get('.react-flow__node').contains('Node 1');
node
.rightclick()
.dblclick()
.then(() => {
expect(onNodeContextMenu.callCount).to.be.eq(1);
expect(onNodeDoubleClick.callCount).to.be.eq(1);
});
skipOn('firefox');
node
.realHover()
.realMouseMove(100, 100)
.then(() => {
expect(onNodeMouseEnter.callCount).to.be.gt(0);
expect(onNodeMouseMove.callCount).to.be.gt(0);
expect(onNodeMouseLeave.callCount).to.be.gt(0);
});
});
});
});
describe('Edge event handlers', () => {
it('handles onEdgeClick', () => {
const onEdgeClick = cy.spy().as('onEdgeClick');
cy.mount(<ControlledFlow initialNodes={nodes} initialEdges={edges} onEdgeClick={onEdgeClick} />).then(() => {
expect(onEdgeClick.callCount).to.be.eq(0);
cy.get('.react-flow__edge:first')
.click()
.then(() => {
expect(onEdgeClick.callCount).to.be.eq(1);
});
});
});
it('handles onEdgeMouse handlers', () => {
const onEdgeMouseEnter = cy.spy().as('onEdgeMouseEnter');
const onEdgeMouseMove = cy.spy().as('onEdgeMouseMove');
const onEdgeMouseLeave = cy.spy().as('onEdgeMouseLeave');
const onEdgeContextMenu = cy.spy().as('onEdgeContextMenu');
const onEdgeDoubleClick = cy.spy().as('onEdgedoubleClick');
cy.mount(
<ControlledFlow
initialNodes={nodes}
initialEdges={edges}
onEdgeMouseEnter={onEdgeMouseEnter}
onEdgeMouseMove={onEdgeMouseMove}
onEdgeMouseLeave={onEdgeMouseLeave}
onEdgeContextMenu={onEdgeContextMenu}
onEdgeDoubleClick={onEdgeDoubleClick}
/>
)
.wait(200)
.then(() => {
expect(onEdgeMouseEnter.callCount).to.be.eq(0);
expect(onEdgeMouseMove.callCount).to.be.eq(0);
expect(onEdgeMouseLeave.callCount).to.be.eq(0);
expect(onEdgeContextMenu.callCount).to.be.eq(0);
expect(onEdgeDoubleClick.callCount).to.be.eq(0);
const edge = cy.get('.react-flow__edge:first');
edge
.rightclick()
.dblclick()
.then(() => {
expect(onEdgeContextMenu.callCount).to.be.eq(1);
});
skipOn('firefox');
edge
.realHover()
.realMouseMove(100, 100)
.then(() => {
expect(onEdgeMouseEnter.callCount).to.be.gt(0);
expect(onEdgeMouseMove.callCount).to.be.gt(0);
expect(onEdgeMouseLeave.callCount).to.be.gt(0);
});
});
});
});
});

View File

@@ -21,7 +21,7 @@ describe('<ReactFlow />: Uncontrolled Flow', () => {
it('drags a node', () => {
const styleBeforeDrag = Cypress.$('.react-flow__node:first').css('transform');
cy.drag('.react-flow__node:first', { x: 200, y: 25 }).then(($el: any) => {
cy.drag('.react-flow__node:first', { x: 200, y: 25 }).then(($el: JQuery<HTMLElement>) => {
const styleAfterDrag = $el.css('transform');
expect(styleBeforeDrag).to.not.equal(styleAfterDrag);
});

View File

@@ -1,5 +1,3 @@
/// <reference types="cypress" />
Cypress.Commands.add('drag', (selector, { x, y }) =>
cy.window().then((window) => {
const elementToDrag = cy.get(selector as string);
@@ -11,7 +9,7 @@ Cypress.Commands.add('drag', (selector, { x, y }) =>
const nextY: number = centerY + y;
return elementToDrag
.trigger('mousedown', { which: 1, view: window })
.trigger('mousedown', { view: window })
.trigger('mousemove', nextX, nextY, { force: true })
.wait(50)
.trigger('mouseup', { view: window, force: true });

View File

@@ -1,23 +1,9 @@
// ***********************************************************
// This example support/component.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
///<reference types="cypress" />
///<reference types="@cypress/skip-test" />
///<reference types="cypress-real-events" />
// Import commands.js using ES2015 syntax:
import './commands';
// Alternatively you can use CommonJS syntax:
// require('./commands')
import 'cypress-real-events/support';
import { mount } from 'cypress/react18';
import { XYPosition } from 'reactflow';
@@ -26,6 +12,7 @@ import '../../styles/globals.css';
import '../../styles/rf-style.css';
declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace Cypress {
interface Chainable {
mount: typeof mount;

View File

@@ -21,8 +21,10 @@
"reactflow": "workspace:*"
},
"devDependencies": {
"@cypress/skip-test": "^2.6.1",
"@types/dagre": "^0.7.47",
"cypress": "^10.6.0",
"cypress-real-events": "^1.7.1",
"eslint": "^8.22.0",
"eslint-config-next": "12.2.2",
"next-global-css": "^1.3.1",

View File

@@ -15,7 +15,7 @@
"jsx": "preserve",
"incremental": true,
"baseUrl": "./",
"types": ["cypress"]
"types": ["cypress", "cypress-real-events"]
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]

View File

@@ -153,7 +153,7 @@ function useDrag({
.filter((event: MouseEvent) => {
const target = event.target as HTMLDivElement;
const isDraggable =
event.button === 0 &&
!event.button &&
(!noDragClassName || !hasSelector(target, `.${noDragClassName}`, nodeRef)) &&
(!handleSelector || hasSelector(target, handleSelector, nodeRef));

View File

@@ -1908,6 +1908,13 @@ __metadata:
languageName: node
linkType: hard
"@cypress/skip-test@npm:^2.6.1":
version: 2.6.1
resolution: "@cypress/skip-test@npm:2.6.1"
checksum: 48ec912f162563ca8657b6f023b701f66ddc29083ed36ae96cd861087c828046c2abb36c6fa0b316bb74941a17b046ac3b143532218e4cdc6d78d7838a64a141
languageName: node
linkType: hard
"@cypress/xvfb@npm:^1.2.4":
version: 1.2.4
resolution: "@cypress/xvfb@npm:1.2.4"
@@ -4330,6 +4337,15 @@ __metadata:
languageName: node
linkType: hard
"cypress-real-events@npm:^1.7.1":
version: 1.7.1
resolution: "cypress-real-events@npm:1.7.1"
peerDependencies:
cypress: ^4.x || ^5.x || ^6.x || ^7.x || ^8.x || ^9.x || ^10.x
checksum: b31c2facfa03e01e298926cd0925260b12474770fc1a3ce8998da21818db7e6d9fc2f9eb60d1771aa4ce3c29aca63d04da21e1a63e3bb117b1506a72ab0c3eb1
languageName: node
linkType: hard
"cypress@npm:^10.6.0":
version: 10.6.0
resolution: "cypress@npm:10.6.0"
@@ -8462,9 +8478,11 @@ __metadata:
version: 0.0.0-use.local
resolution: "reactflow-examples@workspace:examples/nextjs"
dependencies:
"@cypress/skip-test": ^2.6.1
"@preconstruct/next": ^4.0.0
"@types/dagre": ^0.7.47
cypress: ^10.6.0
cypress-real-events: ^1.7.1
dagre: ^0.8.5
eslint: ^8.22.0
eslint-config-next: 12.2.2