From 19d7bf94631882a53a015d97cd127cfafb06e297 Mon Sep 17 00:00:00 2001 From: eps1lon Date: Wed, 23 Jun 2021 20:04:56 +0200 Subject: [PATCH 1/4] [test] Convert SwipeableDrawer tests to testing-library --- .../SwipeableDrawer/SwipeableDrawer.test.js | 105 +++++------------- 1 file changed, 28 insertions(+), 77 deletions(-) diff --git a/packages/material-ui/src/SwipeableDrawer/SwipeableDrawer.test.js b/packages/material-ui/src/SwipeableDrawer/SwipeableDrawer.test.js index 4b6aca08d1f58c..fc6c9e9fe34ecf 100644 --- a/packages/material-ui/src/SwipeableDrawer/SwipeableDrawer.test.js +++ b/packages/material-ui/src/SwipeableDrawer/SwipeableDrawer.test.js @@ -2,7 +2,6 @@ import * as React from 'react'; import { expect } from 'chai'; import { spy } from 'sinon'; import { - act, createMount, fireEvent, createClientRender, @@ -13,45 +12,8 @@ import PropTypes, { checkPropTypes } from 'prop-types'; import SwipeableDrawer from '@material-ui/core/SwipeableDrawer'; import Drawer, { drawerClasses } from '@material-ui/core/Drawer'; import { backdropClasses } from '@material-ui/core/Backdrop'; -import SwipeArea from './SwipeArea'; import useForkRef from '../utils/useForkRef'; -function fireMouseEvent(name, element, properties = {}) { - act(() => { - const event = document.createEvent('MouseEvents'); - event.initEvent(name, true, true); - Object.keys(properties).forEach((key) => { - event[key] = properties[key]; - }); - if (element.dispatchEvent) { - element.dispatchEvent(event); - } else { - element.getDOMNode().dispatchEvent(event); - } - }); -} - -function fireBodyMouseEvent(name, properties = {}) { - fireMouseEvent(name, document.body, properties); -} - -function fireSwipeAreaMouseEvent(wrapper, name, properties = {}) { - let event; - act(() => { - event = document.createEvent('MouseEvents'); - event.initEvent(name, true, true); - Object.keys(properties).forEach((key) => { - event[key] = properties[key]; - }); - const swipeArea = wrapper.find(SwipeArea); - if (swipeArea.length >= 1) { - // if no SwipeArea is mounted, the body event wouldn't propagate to it anyway - swipeArea.getDOMNode().dispatchEvent(event); - } - }); - return event; -} - const FakePaper = React.forwardRef(function FakeWidthPaper(props, ref) { const { style, ...other } = props; const paperRef = React.useRef(null); @@ -474,8 +436,9 @@ describe('', () => { describe('disableSwipeToOpen', () => { it('should not support swipe to open if disableSwipeToOpen is set', () => { const handleOpen = spy(); - const wrapper = mount( + render( {}} open={false} @@ -485,53 +448,48 @@ describe('', () => { , ); - // simulate open swipe - wrapper.setProps({ disableSwipeToOpen: true }); - expect(wrapper.find('[role="presentation"]').exists()).to.equal(false); - fireBodyMouseEvent('touchstart', { touches: [{ pageX: 10, clientY: 0 }] }); - fireBodyMouseEvent('touchmove', { touches: [{ pageX: 150, clientY: 0 }] }); - fireBodyMouseEvent('touchend', { changedTouches: [{ pageX: 250, clientY: 0 }] }); + fireEvent.touchStart(document.body, { touches: [{ pageX: 10, clientY: 0 }] }); + fireEvent.touchMove(document.body, { touches: [{ pageX: 150, clientY: 0 }] }); + fireEvent.touchEnd(document.body, { changedTouches: [{ pageX: 250, clientY: 0 }] }); + expect(handleOpen.callCount).to.equal(0); - expect(wrapper.find('[role="presentation"]').exists()).to.equal(false); - wrapper.unmount(); }); it('should support swipe to close if disableSwipeToOpen is set', () => { const handleClose = spy(); - const wrapper = mount( + render( {}} onClose={handleClose} open - PaperProps={{ component: FakePaper }} + PaperProps={{ component: FakePaper, 'data-testid': 'paper' }} >
SwipeableDrawer
, ); - // simulate close swipe - wrapper.setProps({ disableSwipeToOpen: true }); - expect(wrapper.find('[role="presentation"]').exists()).to.equal(true); - fireMouseEvent('touchstart', wrapper.find(FakePaper), { + fireEvent.touchStart(screen.getByTestId('paper'), { touches: [{ pageX: 250, clientY: 0 }], }); - fireBodyMouseEvent('touchmove', { touches: [{ pageX: 150, clientY: 0 }] }); - fireBodyMouseEvent('touchend', { changedTouches: [{ pageX: 10, clientY: 0 }] }); + fireEvent.touchMove(document.body, { touches: [{ pageX: 150, clientY: 0 }] }); + fireEvent.touchEnd(document.body, { changedTouches: [{ pageX: 10, clientY: 0 }] }); + expect(handleClose.callCount).to.equal(1); - wrapper.unmount(); }); }); describe('lock', () => { it('should handle a single swipe at the time', () => { const handleOpen = spy(); - const wrapper = mount( + render(
{}} open={false} PaperProps={{ component: FakePaper }} + SwipeAreaProps={{ 'data-testid': 'swipearea' }} >
Drawer1
@@ -540,47 +498,40 @@ describe('', () => { onClose={() => {}} open={false} PaperProps={{ component: FakePaper }} + SwipeAreaProps={{ 'data-testid': 'swipearea' }} >
Drawer2
, ); - // use the same event object for both touch start events, one would propagate to the other swipe area in the browser - const touchStartEvent = fireSwipeAreaMouseEvent( - wrapper.find(SwipeableDrawer).at(0), - 'touchstart', - { - touches: [{ pageX: 0, clientY: 0 }], - }, - ); - wrapper - .find(SwipeableDrawer) - .at(1) - .find(SwipeArea) - .getDOMNode() - .dispatchEvent(touchStartEvent); - fireBodyMouseEvent('touchmove', { touches: [{ pageX: 20, clientY: 0 }] }); - fireBodyMouseEvent('touchmove', { touches: [{ pageX: 180, clientY: 0 }] }); - fireBodyMouseEvent('touchend', { changedTouches: [{ pageX: 180, clientY: 0 }] }); + fireEvent.touchStart(screen.getAllByTestId('swipearea')[0], { + touches: [{ pageX: 0, clientY: 0 }], + }); + fireEvent.touchMove(document.body, { touches: [{ pageX: 20, clientY: 0 }] }); + fireEvent.touchMove(document.body, { touches: [{ pageX: 180, clientY: 0 }] }); + fireEvent.touchEnd(document.body, { changedTouches: [{ pageX: 180, clientY: 0 }] }); + expect(handleOpen.callCount).to.equal(1); }); }); it('does not crash when updating the parent component while swiping', () => { - const wrapper = mount( + render( {}} onClose={() => {}} open={false} PaperProps={{ component: NullPaper }} + SwipeAreaProps={{ 'data-testid': 'swipearea' }} >
SwipeableDrawer
, ); - fireSwipeAreaMouseEvent(wrapper, 'touchstart', { touches: [{ pageX: 0, clientY: 0 }] }); + + fireEvent.touchStart(screen.getByTestId('swipearea'), { touches: [{ pageX: 0, clientY: 0 }] }); // simulate paper ref being null because of the drawer being updated - fireBodyMouseEvent('touchmove', { touches: [{ pageX: 20, clientY: 0 }] }); + fireEvent.touchMove(document.body, { touches: [{ pageX: 20, clientY: 0 }] }); }); describe('no backdrop', () => { From 3d5b0f5ff3ac91c73ffa2daa814bd9657790f36c Mon Sep 17 00:00:00 2001 From: eps1lon Date: Wed, 23 Jun 2021 20:06:12 +0200 Subject: [PATCH 2/4] StrictMode comaptible --- .../SwipeableDrawer/SwipeableDrawer.test.js | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/packages/material-ui/src/SwipeableDrawer/SwipeableDrawer.test.js b/packages/material-ui/src/SwipeableDrawer/SwipeableDrawer.test.js index fc6c9e9fe34ecf..aa3cfd6f86aa51 100644 --- a/packages/material-ui/src/SwipeableDrawer/SwipeableDrawer.test.js +++ b/packages/material-ui/src/SwipeableDrawer/SwipeableDrawer.test.js @@ -1,6 +1,6 @@ import * as React from 'react'; import { expect } from 'chai'; -import { spy } from 'sinon'; +import { spy, useFakeTimers } from 'sinon'; import { createMount, fireEvent, @@ -64,9 +64,19 @@ const NullPaper = React.forwardRef(function NullPaper(props, ref) { }); describe('', () => { - // test are mostly asserting on implementation details - const mount = createMount({ strict: null }); - const render = createClientRender({ strict: false }); + /** + * @type {ReturnType} + */ + let clock; + beforeEach(() => { + clock = useFakeTimers(); + }); + afterEach(() => { + clock.restore(); + }); + + const mount = createMount(); + const render = createClientRender(); describeConformance( {}} onClose={() => {}} open />, () => ({ classes: {}, From 08c989b9c945fa2fe68056f2e2a4f174779706a4 Mon Sep 17 00:00:00 2001 From: eps1lon Date: Thu, 24 Jun 2021 09:15:18 +0200 Subject: [PATCH 3/4] Create actual Touch objects --- .../SwipeableDrawer/SwipeableDrawer.test.js | 57 ++++++++++++++----- 1 file changed, 43 insertions(+), 14 deletions(-) diff --git a/packages/material-ui/src/SwipeableDrawer/SwipeableDrawer.test.js b/packages/material-ui/src/SwipeableDrawer/SwipeableDrawer.test.js index aa3cfd6f86aa51..56f0869874d1c1 100644 --- a/packages/material-ui/src/SwipeableDrawer/SwipeableDrawer.test.js +++ b/packages/material-ui/src/SwipeableDrawer/SwipeableDrawer.test.js @@ -458,9 +458,17 @@ describe('', () => { , ); - fireEvent.touchStart(document.body, { touches: [{ pageX: 10, clientY: 0 }] }); - fireEvent.touchMove(document.body, { touches: [{ pageX: 150, clientY: 0 }] }); - fireEvent.touchEnd(document.body, { changedTouches: [{ pageX: 250, clientY: 0 }] }); + fireEvent.touchStart(document.body, { + touches: [new Touch({ identifier: 0, target: document.body, pageX: 10, clientY: 0 })], + }); + fireEvent.touchMove(document.body, { + touches: [new Touch({ identifier: 0, target: document.body, pageX: 150, clientY: 0 })], + }); + fireEvent.touchEnd(document.body, { + changedTouches: [ + new Touch({ identifier: 0, target: document.body, pageX: 250, clientY: 0 }), + ], + }); expect(handleOpen.callCount).to.equal(0); }); @@ -479,11 +487,18 @@ describe('', () => { , ); - fireEvent.touchStart(screen.getByTestId('paper'), { - touches: [{ pageX: 250, clientY: 0 }], + const paper = screen.getByTestId('paper'); + fireEvent.touchStart(paper, { + touches: [new Touch({ identifier: 0, target: paper, pageX: 250, clientY: 0 })], + }); + fireEvent.touchMove(document.body, { + touches: [new Touch({ identifier: 0, target: document.body, pageX: 150, clientY: 0 })], + }); + fireEvent.touchEnd(document.body, { + changedTouches: [ + new Touch({ identifier: 0, target: document.body, pageX: 10, clientY: 0 }), + ], }); - fireEvent.touchMove(document.body, { touches: [{ pageX: 150, clientY: 0 }] }); - fireEvent.touchEnd(document.body, { changedTouches: [{ pageX: 10, clientY: 0 }] }); expect(handleClose.callCount).to.equal(1); }); @@ -515,12 +530,21 @@ describe('', () => { , ); - fireEvent.touchStart(screen.getAllByTestId('swipearea')[0], { - touches: [{ pageX: 0, clientY: 0 }], + const [firstSwipeArea] = screen.getAllByTestId('swipearea'); + fireEvent.touchStart(firstSwipeArea, { + touches: [new Touch({ identifier: 0, target: firstSwipeArea, pageX: 0, clientY: 0 })], + }); + fireEvent.touchMove(document.body, { + touches: [new Touch({ identifier: 0, target: document.body, pageX: 20, clientY: 0 })], + }); + fireEvent.touchMove(document.body, { + touches: [new Touch({ identifier: 0, target: document.body, pageX: 180, clientY: 0 })], + }); + fireEvent.touchEnd(document.body, { + changedTouches: [ + new Touch({ identifier: 0, target: document.body, pageX: 180, clientY: 0 }), + ], }); - fireEvent.touchMove(document.body, { touches: [{ pageX: 20, clientY: 0 }] }); - fireEvent.touchMove(document.body, { touches: [{ pageX: 180, clientY: 0 }] }); - fireEvent.touchEnd(document.body, { changedTouches: [{ pageX: 180, clientY: 0 }] }); expect(handleOpen.callCount).to.equal(1); }); @@ -539,9 +563,14 @@ describe('', () => { , ); - fireEvent.touchStart(screen.getByTestId('swipearea'), { touches: [{ pageX: 0, clientY: 0 }] }); + const swipeArea = screen.getByTestId('swipearea'); + fireEvent.touchStart(swipeArea, { + touches: [new Touch({ identifier: 0, target: swipeArea, pageX: 0, clientY: 0 })], + }); // simulate paper ref being null because of the drawer being updated - fireEvent.touchMove(document.body, { touches: [{ pageX: 20, clientY: 0 }] }); + fireEvent.touchMove(document.body, { + touches: [new Touch({ identifier: 0, target: document.body, pageX: 20, clientY: 0 })], + }); }); describe('no backdrop', () => { From 0e4b072f71ebb36bce4aecdc60c46147f6fb7ef1 Mon Sep 17 00:00:00 2001 From: eps1lon Date: Thu, 24 Jun 2021 09:55:12 +0200 Subject: [PATCH 4/4] Match browser event order --- .../SwipeableDrawer/SwipeableDrawer.test.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/material-ui/src/SwipeableDrawer/SwipeableDrawer.test.js b/packages/material-ui/src/SwipeableDrawer/SwipeableDrawer.test.js index 56f0869874d1c1..4a3461bf03b3ec 100644 --- a/packages/material-ui/src/SwipeableDrawer/SwipeableDrawer.test.js +++ b/packages/material-ui/src/SwipeableDrawer/SwipeableDrawer.test.js @@ -530,19 +530,20 @@ describe('', () => { , ); - const [firstSwipeArea] = screen.getAllByTestId('swipearea'); - fireEvent.touchStart(firstSwipeArea, { - touches: [new Touch({ identifier: 0, target: firstSwipeArea, pageX: 0, clientY: 0 })], + // Event order recorded with https://codesandbox.io/s/single-swipearea-lock-ksyss + const topMostSwipeArea = screen.getAllByTestId('swipearea').slice(-1)[0]; + fireEvent.touchStart(topMostSwipeArea, { + touches: [new Touch({ identifier: 0, target: topMostSwipeArea, pageX: 0, clientY: 0 })], }); - fireEvent.touchMove(document.body, { - touches: [new Touch({ identifier: 0, target: document.body, pageX: 20, clientY: 0 })], + fireEvent.touchMove(topMostSwipeArea, { + touches: [new Touch({ identifier: 0, target: topMostSwipeArea, pageX: 20, clientY: 0 })], }); - fireEvent.touchMove(document.body, { - touches: [new Touch({ identifier: 0, target: document.body, pageX: 180, clientY: 0 })], + fireEvent.touchMove(topMostSwipeArea, { + touches: [new Touch({ identifier: 0, target: topMostSwipeArea, pageX: 180, clientY: 0 })], }); - fireEvent.touchEnd(document.body, { + fireEvent.touchEnd(topMostSwipeArea, { changedTouches: [ - new Touch({ identifier: 0, target: document.body, pageX: 180, clientY: 0 }), + new Touch({ identifier: 0, target: topMostSwipeArea, pageX: 180, clientY: 0 }), ], });