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
@@ -17,7 +17,7 @@ describe('<ReactFlow />: Basic Props', () => {
it('drags a node', () => { it('drags a node', () => {
const styleBeforeDrag = Cypress.$('.react-flow__node:first').css('transform'); 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'); const styleAfterDrag = $el.css('transform');
expect(styleBeforeDrag).to.not.equal(styleAfterDrag); expect(styleBeforeDrag).to.not.equal(styleAfterDrag);
}); });
@@ -43,7 +43,7 @@ describe('<ReactFlow />: Basic Props', () => {
it('can not drag a node', () => { it('can not drag a node', () => {
const styleBeforeDrag = Cypress.$('.react-flow__node:first').css('transform'); 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'); const styleAfterDrag = $el.css('transform');
expect(styleBeforeDrag).to.equal(styleAfterDrag); expect(styleBeforeDrag).to.equal(styleAfterDrag);
}); });
@@ -63,7 +63,7 @@ describe('<ReactFlow />: Basic Props', () => {
it('drags a node', () => { it('drags a node', () => {
const styleBeforeDrag = Cypress.$('.react-flow__node:first').css('transform'); 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'); const styleAfterDrag = $el.css('transform');
expect(styleBeforeDrag).to.not.equal(styleAfterDrag); expect(styleBeforeDrag).to.not.equal(styleAfterDrag);
}); });
@@ -195,5 +195,3 @@ describe('<ReactFlow />: Basic Props', () => {
cy.get('.react-flow').should('have.class', 'custom'); cy.get('.react-flow').should('have.class', 'custom');
}); });
}); });
// test specific helper component
@@ -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);
});
});
});
});
});
@@ -21,7 +21,7 @@ describe('<ReactFlow />: Uncontrolled Flow', () => {
it('drags a node', () => { it('drags a node', () => {
const styleBeforeDrag = Cypress.$('.react-flow__node:first').css('transform'); 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'); const styleAfterDrag = $el.css('transform');
expect(styleBeforeDrag).to.not.equal(styleAfterDrag); expect(styleBeforeDrag).to.not.equal(styleAfterDrag);
}); });
+1 -3
View File
@@ -1,5 +1,3 @@
/// <reference types="cypress" />
Cypress.Commands.add('drag', (selector, { x, y }) => Cypress.Commands.add('drag', (selector, { x, y }) =>
cy.window().then((window) => { cy.window().then((window) => {
const elementToDrag = cy.get(selector as string); const elementToDrag = cy.get(selector as string);
@@ -11,7 +9,7 @@ Cypress.Commands.add('drag', (selector, { x, y }) =>
const nextY: number = centerY + y; const nextY: number = centerY + y;
return elementToDrag return elementToDrag
.trigger('mousedown', { which: 1, view: window }) .trigger('mousedown', { view: window })
.trigger('mousemove', nextX, nextY, { force: true }) .trigger('mousemove', nextX, nextY, { force: true })
.wait(50) .wait(50)
.trigger('mouseup', { view: window, force: true }); .trigger('mouseup', { view: window, force: true });
+5 -18
View File
@@ -1,23 +1,9 @@
// *********************************************************** ///<reference types="cypress" />
// This example support/component.js is processed and ///<reference types="@cypress/skip-test" />
// loaded automatically before your test files. ///<reference types="cypress-real-events" />
//
// 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
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands'; import './commands';
import 'cypress-real-events/support';
// Alternatively you can use CommonJS syntax:
// require('./commands')
import { mount } from 'cypress/react18'; import { mount } from 'cypress/react18';
import { XYPosition } from 'reactflow'; import { XYPosition } from 'reactflow';
@@ -26,6 +12,7 @@ import '../../styles/globals.css';
import '../../styles/rf-style.css'; import '../../styles/rf-style.css';
declare global { declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace Cypress { namespace Cypress {
interface Chainable { interface Chainable {
mount: typeof mount; mount: typeof mount;
+2
View File
@@ -21,8 +21,10 @@
"reactflow": "workspace:*" "reactflow": "workspace:*"
}, },
"devDependencies": { "devDependencies": {
"@cypress/skip-test": "^2.6.1",
"@types/dagre": "^0.7.47", "@types/dagre": "^0.7.47",
"cypress": "^10.6.0", "cypress": "^10.6.0",
"cypress-real-events": "^1.7.1",
"eslint": "^8.22.0", "eslint": "^8.22.0",
"eslint-config-next": "12.2.2", "eslint-config-next": "12.2.2",
"next-global-css": "^1.3.1", "next-global-css": "^1.3.1",
+1 -1
View File
@@ -15,7 +15,7 @@
"jsx": "preserve", "jsx": "preserve",
"incremental": true, "incremental": true,
"baseUrl": "./", "baseUrl": "./",
"types": ["cypress"] "types": ["cypress", "cypress-real-events"]
}, },
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"] "exclude": ["node_modules"]
+1 -1
View File
@@ -153,7 +153,7 @@ function useDrag({
.filter((event: MouseEvent) => { .filter((event: MouseEvent) => {
const target = event.target as HTMLDivElement; const target = event.target as HTMLDivElement;
const isDraggable = const isDraggable =
event.button === 0 && !event.button &&
(!noDragClassName || !hasSelector(target, `.${noDragClassName}`, nodeRef)) && (!noDragClassName || !hasSelector(target, `.${noDragClassName}`, nodeRef)) &&
(!handleSelector || hasSelector(target, handleSelector, nodeRef)); (!handleSelector || hasSelector(target, handleSelector, nodeRef));
+18
View File
@@ -1908,6 +1908,13 @@ __metadata:
languageName: node languageName: node
linkType: hard 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": "@cypress/xvfb@npm:^1.2.4":
version: 1.2.4 version: 1.2.4
resolution: "@cypress/xvfb@npm:1.2.4" resolution: "@cypress/xvfb@npm:1.2.4"
@@ -4330,6 +4337,15 @@ __metadata:
languageName: node languageName: node
linkType: hard 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": "cypress@npm:^10.6.0":
version: 10.6.0 version: 10.6.0
resolution: "cypress@npm:10.6.0" resolution: "cypress@npm:10.6.0"
@@ -8462,9 +8478,11 @@ __metadata:
version: 0.0.0-use.local version: 0.0.0-use.local
resolution: "reactflow-examples@workspace:examples/nextjs" resolution: "reactflow-examples@workspace:examples/nextjs"
dependencies: dependencies:
"@cypress/skip-test": ^2.6.1
"@preconstruct/next": ^4.0.0 "@preconstruct/next": ^4.0.0
"@types/dagre": ^0.7.47 "@types/dagre": ^0.7.47
cypress: ^10.6.0 cypress: ^10.6.0
cypress-real-events: ^1.7.1
dagre: ^0.8.5 dagre: ^0.8.5
eslint: ^8.22.0 eslint: ^8.22.0
eslint-config-next: 12.2.2 eslint-config-next: 12.2.2