diff --git a/packages-internal/test-utils/src/focusVisible.ts b/packages-internal/test-utils/src/focusVisible.ts index 8b650bc01ee0ae..ebc2f9cac1a07d 100644 --- a/packages-internal/test-utils/src/focusVisible.ts +++ b/packages-internal/test-utils/src/focusVisible.ts @@ -14,6 +14,10 @@ export function simulatePointerDevice() { fireEvent.pointerDown(document.body); } +export function simulateKeyboardDevice() { + fireEvent.keyDown(document.body, { key: 'TAB' }); +} + /** * See https://bugs.chromium.org/p/chromium/issues/detail?id=1127875 for more details. */ diff --git a/packages/mui-material/src/Button/Button.test.js b/packages/mui-material/src/Button/Button.test.js index 0b887e085482df..d711feb1458cbd 100644 --- a/packages/mui-material/src/Button/Button.test.js +++ b/packages/mui-material/src/Button/Button.test.js @@ -1,11 +1,12 @@ import * as React from 'react'; import { expect } from 'chai'; -import { act, createRenderer, fireEvent, screen } from '@mui/internal-test-utils'; +import { act, createRenderer, fireEvent, screen, simulateKeyboardDevice } from '@mui/internal-test-utils'; import { ClassNames } from '@emotion/react'; import { ThemeProvider, createTheme } from '@mui/material/styles'; import Button, { buttonClasses as classes } from '@mui/material/Button'; import ButtonBase, { touchRippleClasses } from '@mui/material/ButtonBase'; import describeConformance from '../../test/describeConformance'; +import * as ripple from '../../test/ripple'; describe(', ); const button = getByRole('button'); - + await ripple.startTouch(button); expect(button.querySelector('.touch-ripple')).not.to.equal(null); }); - it('can disable the ripple', () => { + it('can disable the ripple', async () => { const { getByRole } = render( , ); const button = getByRole('button'); - + await ripple.startTouch(button); expect(button.querySelector('.touch-ripple')).to.equal(null); }); @@ -582,7 +583,7 @@ describe(' , ); + await ripple.startTouch(container.querySelector('button')) expect(container.querySelectorAll(`.${touchRippleClasses.root}`)).to.have.length(1); }); diff --git a/packages/mui-material/src/ButtonBase/ButtonBase.test.js b/packages/mui-material/src/ButtonBase/ButtonBase.test.js index 47604bbcc51020..536d44452c003e 100644 --- a/packages/mui-material/src/ButtonBase/ButtonBase.test.js +++ b/packages/mui-material/src/ButtonBase/ButtonBase.test.js @@ -15,6 +15,7 @@ import PropTypes from 'prop-types'; import { ThemeProvider, createTheme } from '@mui/material/styles'; import ButtonBase, { buttonBaseClasses as classes } from '@mui/material/ButtonBase'; import describeConformance from '../../test/describeConformance'; +import * as ripple from '../../test/ripple'; describe('', () => { const { render } = createRenderer(); @@ -266,7 +267,7 @@ describe('', () => { expect(button.querySelectorAll('.ripple-pulsate')).to.have.lengthOf(0); }); - it('should start the ripple when the mouse is pressed', () => { + it('should start the ripple when the mouse is pressed', async () => { const { getByRole } = render( ', () => { ); const button = getByRole('button'); - fireEvent.mouseDown(button); + await ripple.startTouch(button) expect(button.querySelectorAll('.ripple-visible .child-leaving')).to.have.lengthOf(0); expect( @@ -288,7 +289,7 @@ describe('', () => { ).to.have.lengthOf(1); }); - it('should stop the ripple when the mouse is released', () => { + it('should stop the ripple when the mouse is released', async () => { const { getByRole } = render( ', () => { />, ); const button = getByRole('button'); - fireEvent.mouseDown(button); - fireEvent.mouseUp(button); + await ripple.startTouch(button) + await ripple.stopTouch(button) expect(button.querySelectorAll('.ripple-visible .child-leaving')).to.have.lengthOf(1); expect( @@ -311,7 +312,7 @@ describe('', () => { ).to.have.lengthOf(0); }); - it('should start the ripple when the mouse is pressed 2', () => { + it('should start the ripple when the mouse is pressed 2', async () => { const { getByRole } = render( ', () => { />, ); const button = getByRole('button'); - fireEvent.mouseDown(button); - fireEvent.mouseUp(button); - fireEvent.mouseDown(button); + await ripple.startTouch(button) + await ripple.stopTouch(button) + + await ripple.startTouch(button) expect(button.querySelectorAll('.ripple-visible .child-leaving')).to.have.lengthOf(1); expect( @@ -335,7 +337,7 @@ describe('', () => { ).to.have.lengthOf(1); }); - it('should stop the ripple when the button blurs', () => { + it('should stop the ripple when the button blurs', async () => { const { getByRole } = render( ', () => { />, ); const button = getByRole('button'); - fireEvent.mouseDown(button); + await ripple.startTouch(button); - button.blur(); + act(() => button.blur()); expect(button.querySelectorAll('.ripple-visible .child-leaving')).to.have.lengthOf(0); expect( @@ -358,7 +360,7 @@ describe('', () => { ).to.have.lengthOf(1); }); - it('should restart the ripple when the mouse is pressed again', () => { + it('should restart the ripple when the mouse is pressed again', async () => { const { getByRole } = render( ', () => { ); const button = getByRole('button'); - fireEvent.mouseDown(button); + await ripple.startTouch(button); expect(button.querySelectorAll('.ripple-visible .child-leaving')).to.have.lengthOf(0); expect( button.querySelectorAll('.ripple-visible .child:not(.child-leaving)'), ).to.have.lengthOf(1); - fireEvent.mouseUp(button); - fireEvent.mouseDown(button); + await ripple.stopTouch(button); + await ripple.startTouch(button); expect(button.querySelectorAll('.ripple-visible .child-leaving')).to.have.lengthOf(1); expect( @@ -388,7 +390,7 @@ describe('', () => { ).to.have.lengthOf(1); }); - it('should stop the ripple when the mouse leaves', () => { + it('should stop the ripple when the mouse leaves', async () => { const { getByRole } = render( ', () => { />, ); const button = getByRole('button'); - fireEvent.mouseDown(button); - - fireEvent.mouseLeave(button); + await ripple.asyncFireEvent(button, 'mouseDown'); + await ripple.asyncFireEvent(button, 'mouseLeave'); expect(button.querySelectorAll('.ripple-visible .child-leaving')).to.have.lengthOf(1); expect( @@ -411,7 +412,7 @@ describe('', () => { ).to.have.lengthOf(0); }); - it('should stop the ripple when dragging has finished', function test() { + it('should stop the ripple when dragging has finished', async function test() { if (!canFireDragEvents) { this.skip(); } @@ -427,9 +428,9 @@ describe('', () => { />, ); const button = getByRole('button'); - fireEvent.mouseDown(button); + await ripple.asyncFireEvent(button, 'mouseDown'); - fireEvent.dragLeave(button); + await ripple.asyncFireEvent(button, 'dragLeave'); expect(button.querySelectorAll('.ripple-visible .child-leaving')).to.have.lengthOf(1); expect( @@ -437,7 +438,7 @@ describe('', () => { ).to.have.lengthOf(0); }); - it('should stop the ripple when the context menu opens', () => { + it('should stop the ripple when the context menu opens', async () => { const { getByRole } = render( ', () => { />, ); const button = getByRole('button'); - fireEvent.mouseDown(button); + await ripple.asyncFireEvent(button, 'mouseDown') expect(button.querySelectorAll('.ripple-visible .child-leaving')).to.have.lengthOf(0); expect( button.querySelectorAll('.ripple-visible .child:not(.child-leaving)'), ).to.have.lengthOf(1); - fireEvent.contextMenu(button); + await ripple.asyncFireEvent(button, 'contextMenu') expect(button.querySelectorAll('.ripple-visible .child-leaving')).to.have.lengthOf(1); expect( @@ -465,7 +466,7 @@ describe('', () => { ).to.have.lengthOf(0); }); - it('should not crash when changes enableRipple from false to true', () => { + it('should not crash when changes enableRipple from false to true', async () => { function App() { /** @type {React.MutableRefObject} */ const buttonRef = React.useRef(null); @@ -509,11 +510,11 @@ describe('', () => { const { container, getByTestId } = render(); - fireEvent.click(getByTestId('trigger')); + await ripple.asyncFireEvent(getByTestId('trigger'), 'click'); expect(container.querySelectorAll('.ripple-pulsate')).to.have.lengthOf(1); }); - it('should stop the ripple on blur if disableTouchRipple is set', () => { + it('should stop the ripple on blur if disableTouchRipple is set', async () => { const buttonActions = React.createRef(); const { getByRole } = render( @@ -528,17 +529,18 @@ describe('', () => { childLeaving: 'child-leaving', }, }} - />, + > + Test + , ); const button = getByRole('button'); simulatePointerDevice(); - focusVisible(button); + await ripple.stopFocus(button); + await ripple.startFocus(button); - act(() => { - button.blur(); - }); + await ripple.stopFocus(button); expect(button.querySelectorAll('.ripple-visible .child-leaving')).to.have.lengthOf(1); }); @@ -546,7 +548,7 @@ describe('', () => { }); describe('prop: centerRipple', () => { - it('centers the TouchRipple', () => { + it('centers the TouchRipple', async () => { const { container, getByRole } = render( ', () => { Hello , ); + await ripple.startTouch(getByRole('button')) + await ripple.stopTouch(getByRole('button')) // @ts-ignore stub(container.querySelector('.touch-ripple'), 'getBoundingClientRect').callsFake(() => ({ width: 100, @@ -563,7 +567,7 @@ describe('', () => { left: 20, top: 20, })); - fireEvent.mouseDown(getByRole('button'), { clientX: 10, clientY: 10 }); + await ripple.startTouch(getByRole('button'), { clientX: 10, clientY: 10 }) const rippleRipple = container.querySelector('.touch-ripple-ripple'); expect(rippleRipple).not.to.equal(null); // @ts-ignore @@ -572,7 +576,7 @@ describe('', () => { expect(rippleStyle).to.have.property('width', '101px'); }); - it('is disabled by default', () => { + it('is disabled by default', async () => { const { container, getByRole } = render( ', () => { Hello , ); + await ripple.startTouch(getByRole('button')) + await ripple.stopTouch(getByRole('button')) // @ts-ignore stub(container.querySelector('.touch-ripple'), 'getBoundingClientRect').callsFake(() => ({ width: 100, @@ -588,7 +594,7 @@ describe('', () => { left: 20, top: 20, })); - fireEvent.mouseDown(getByRole('button'), { clientX: 10, clientY: 10 }); + await ripple.startTouch(getByRole('button'), { clientX: 10, clientY: 10 }) const rippleRipple = container.querySelector('.touch-ripple-ripple'); expect(rippleRipple).not.to.equal(null); // @ts-ignore @@ -599,7 +605,7 @@ describe('', () => { }); describe('focusRipple', () => { - it('should pulsate the ripple when focusVisible', () => { + it('should pulsate the ripple when focusVisible', async () => { const { getByRole } = render( ', () => { const button = getByRole('button'); simulatePointerDevice(); - focusVisible(button); + await ripple.startFocus(button); expect(button.querySelectorAll('.ripple-pulsate')).to.have.lengthOf(1); }); - it('should not stop the ripple when the mouse leaves', () => { + it('should not stop the ripple when the mouse leaves', async () => { const { getByRole } = render( ', () => { const button = getByRole('button'); simulatePointerDevice(); - focusVisible(button); - fireEvent.mouseLeave(button); + await ripple.startFocus(button); + await ripple.asyncFireEvent(button, 'mouseLeave'); expect(button.querySelectorAll('.ripple-pulsate')).to.have.lengthOf(1); }); - it('should stop pulsate and start a ripple when the space button is pressed', () => { + it('should stop pulsate and start a ripple when the space button is pressed', async () => { const { getByRole } = render( ', () => { const button = getByRole('button'); simulatePointerDevice(); - focusVisible(button); - fireEvent.keyDown(button, { key: ' ' }); + await ripple.startFocus(button); + await ripple.asyncFireEvent(button, 'keyDown', { key: ' ' }); expect(button.querySelectorAll('.ripple-pulsate .child-leaving')).to.have.lengthOf(1); expect(button.querySelectorAll('.ripple-visible')).to.have.lengthOf(0); }); - it('should stop and re-pulsate when space bar is released', () => { + it('should stop and re-pulsate when space bar is released', async function () { const { getByRole } = render( ', () => { ); const button = getByRole('button'); + // XXX: failing on firefox + simulatePointerDevice(); - focusVisible(button); - fireEvent.keyDown(button, { key: ' ' }); - fireEvent.keyUp(button, { key: ' ' }); + await ripple.startFocus(button); + expect(button.querySelectorAll('.ripple-visible')).to.have.lengthOf(1); - expect(button.querySelectorAll('.ripple-pulsate .child-leaving')).to.have.lengthOf(1); - expect(button.querySelectorAll('.ripple-pulsate')).to.have.lengthOf(2); + await ripple.asyncFireEvent(button, 'keyDown', { key: ' ' }) + expect(button.querySelectorAll('.ripple-visible')).to.have.lengthOf(2); + + await ripple.asyncFireEvent(button, 'keyUp', { key: ' ' }) expect(button.querySelectorAll('.ripple-visible')).to.have.lengthOf(3); }); - it('should stop on blur and set focusVisible to false', () => { + it('should stop on blur and set focusVisible to false', async () => { const { getByRole } = render( ', () => { ); const button = getByRole('button'); simulatePointerDevice(); - focusVisible(button); + await ripple.startFocus(button); - act(() => { - button.blur(); - }); + await ripple.stopFocus(button); expect(button.querySelectorAll('.ripple-visible .child-leaving')).to.have.lengthOf(1); }); @@ -885,7 +892,7 @@ describe('', () => { }); describe('event: keydown', () => { - it('ripples on repeated keydowns', () => { + it('ripples on repeated keydowns', async () => { const { container, getByText } = render( Hello @@ -894,8 +901,9 @@ describe('', () => { const button = getByText('Hello'); + await ripple.startFocus(button); + act(() => { - button.focus(); fireEvent.keyDown(button, { key: 'Enter' }); }); @@ -922,7 +930,7 @@ describe('', () => { }); describe('prop: disableTouchRipple', () => { - it('creates no ripples on click', () => { + it('creates no ripples on click', async () => { const { getByText } = render( ', () => { ); const button = getByText('Hello'); - fireEvent.click(button); + await ripple.startTouch(button); expect(button).not.to.have.class('ripple-visible'); }); }); describe('prop: disableRipple', () => { - it('removes the TouchRipple', () => { + it('removes the TouchRipple', async () => { const { getByText } = render( Hello , ); - expect(getByText('Hello').querySelector('.touch-ripple')).to.equal(null); + const button = getByText('Hello'); + + await ripple.startTouch(button); + + expect(button.querySelector('.touch-ripple')).to.equal(null); }); }); @@ -1235,9 +1247,10 @@ describe('', () => { }); describe('prop: touchRippleRef', () => { - it('should return a ref', () => { + it('should return a ref', async () => { const ref = React.createRef(); render(); + await ripple.startTouch(screen.getByRole('button')); expect(ref.current).not.to.equal(null); }); }); diff --git a/packages/mui-material/src/ButtonGroup/ButtonGroup.test.js b/packages/mui-material/src/ButtonGroup/ButtonGroup.test.js index ec308440ad9385..05ad6f2fb06b39 100644 --- a/packages/mui-material/src/ButtonGroup/ButtonGroup.test.js +++ b/packages/mui-material/src/ButtonGroup/ButtonGroup.test.js @@ -1,11 +1,12 @@ import * as React from 'react'; import { expect } from 'chai'; -import { createRenderer, screen } from '@mui/internal-test-utils'; +import { act, fireEvent, createRenderer, screen } from '@mui/internal-test-utils'; import ButtonGroup, { buttonGroupClasses as classes } from '@mui/material/ButtonGroup'; import { ThemeProvider, createTheme } from '@mui/material/styles'; import Button, { buttonClasses } from '@mui/material/Button'; import ButtonGroupContext from './ButtonGroupContext'; import describeConformance from '../../test/describeConformance'; +import * as ripple from '../../test/ripple'; describe('', () => { const { render } = createRenderer(); @@ -122,12 +123,13 @@ describe('', () => { expect(button).to.have.class('MuiButton-outlinedSizeLarge'); }); - it('should have a ripple by default', () => { - const { container } = render( + it('should have a ripple', async () => { + const { container, getByRole } = render( , ); + await ripple.startTouch(getByRole('button')); expect(container.querySelector('.touchRipple')).not.to.equal(null); }); @@ -141,12 +143,13 @@ describe('', () => { expect(button).to.have.class('MuiButton-disableElevation'); }); - it('can disable the ripple', () => { - const { container } = render( + it('can disable the ripple', async () => { + const { container, getByRole } = render( , ); + await ripple.startTouch(getByRole('button')); expect(container.querySelector('.touchRipple')).to.equal(null); }); diff --git a/packages/mui-material/src/Chip/Chip.test.js b/packages/mui-material/src/Chip/Chip.test.js index 3f2f182ac9155e..62d6c15ce27cdf 100644 --- a/packages/mui-material/src/Chip/Chip.test.js +++ b/packages/mui-material/src/Chip/Chip.test.js @@ -85,7 +85,6 @@ describe('', () => { expect(container.firstChild).to.have.class('MuiButtonBase-root'); expect(container.firstChild).to.have.tagName('a'); - expect(container.firstChild.querySelector('.MuiTouchRipple-root')).not.to.equal(null); }); it('should disable ripple when MuiButtonBase has disableRipple in theme', () => { diff --git a/packages/mui-material/src/Fab/Fab.test.js b/packages/mui-material/src/Fab/Fab.test.js index 4cc81fbc832e71..59ba85a3452b15 100644 --- a/packages/mui-material/src/Fab/Fab.test.js +++ b/packages/mui-material/src/Fab/Fab.test.js @@ -5,6 +5,7 @@ import Fab, { fabClasses as classes } from '@mui/material/Fab'; import ButtonBase, { touchRippleClasses } from '@mui/material/ButtonBase'; import Icon from '@mui/material/Icon'; import describeConformance from '../../test/describeConformance'; +import * as ripple from '../../test/ripple'; describe('', () => { const { render, renderToString } = createRenderer(); @@ -90,19 +91,19 @@ describe('', () => { expect(button).to.have.class(classes.sizeMedium); }); - it('should have a ripple by default', () => { - const { container } = render(Fab); - + it('should have a ripple', async () => { + const { container, getByRole } = render(Fab); + await ripple.startTouch(getByRole('button')); expect(container.querySelector(`.${touchRippleClasses.root}`)).not.to.equal(null); }); - it('should pass disableRipple to ButtonBase', () => { - const { container } = render(Fab); - + it('should pass disableRipple to ButtonBase', async () => { + const { container, getByRole } = render(Fab); + await ripple.startTouch(getByRole('button')); expect(container.querySelector(`.${touchRippleClasses.root}`)).to.equal(null); }); - it('should have a focusRipple by default', async () => { + it('should have a focusRipple', async () => { const { getByRole } = render( ', () => { ); const button = getByRole('button'); - act(() => { - fireEvent.keyDown(document.body, { key: 'TAB' }); - button.focus(); - }); + await ripple.startFocus(button); expect(button.querySelector('.pulsate-focus-visible')).not.to.equal(null); }); @@ -135,10 +133,7 @@ describe('', () => { ); const button = getByRole('button'); - act(() => { - fireEvent.keyDown(document.body, { key: 'TAB' }); - button.focus(); - }); + await ripple.startFocus(button); expect(button.querySelector('.pulsate-focus-visible')).to.equal(null); }); diff --git a/packages/mui-material/src/IconButton/IconButton.test.js b/packages/mui-material/src/IconButton/IconButton.test.js index 317e11f48b7394..3fad1d8384fbb5 100644 --- a/packages/mui-material/src/IconButton/IconButton.test.js +++ b/packages/mui-material/src/IconButton/IconButton.test.js @@ -8,6 +8,7 @@ import IconButton, { iconButtonClasses as classes } from '@mui/material/IconButt import Icon from '@mui/material/Icon'; import ButtonBase from '@mui/material/ButtonBase'; import describeConformance from '../../test/describeConformance'; +import * as ripple from '../../test/ripple'; describe('', () => { const { render } = createRenderer(); @@ -30,19 +31,21 @@ describe('', () => { expect(getByTestId('icon')).to.have.class(childClassName); }); - it('should have a ripple by default', () => { - const { container } = render( + it('should have a ripple', async () => { + const { container, getByRole } = render( book, ); + await ripple.startTouch(getByRole('button')); expect(container.querySelector('.touch-ripple')).not.to.equal(null); }); - it('can disable the ripple and hover effect', () => { - const { container } = render( + it('can disable the ripple and hover effect', async () => { + const { container, getByRole } = render( book , ); + await ripple.startTouch(getByRole('button')); expect(container.querySelector('.touch-ripple')).to.equal(null); }); diff --git a/packages/mui-material/src/MenuItem/MenuItem.test.js b/packages/mui-material/src/MenuItem/MenuItem.test.js index 6c8513da6fc83b..024c4f4073fe4b 100644 --- a/packages/mui-material/src/MenuItem/MenuItem.test.js +++ b/packages/mui-material/src/MenuItem/MenuItem.test.js @@ -6,6 +6,7 @@ import MenuItem, { menuItemClasses as classes } from '@mui/material/MenuItem'; import ButtonBase from '@mui/material/ButtonBase'; import ListContext from '../List/ListContext'; import describeConformance from '../../test/describeConformance'; +import * as ripple from '../../test/ripple'; describe('', () => { const { render } = createRenderer(); @@ -28,12 +29,11 @@ describe('', () => { expect(menuitem).to.have.property('tabIndex', -1); }); - it('has a ripple when clicked', () => { + it('has a ripple when clicked', async () => { render(); const menuitem = screen.getByRole('menuitem'); - // ripple starts on mousedown - fireEvent.mouseDown(menuitem); + await ripple.startTouch(menuitem) expect(menuitem.querySelectorAll('.ripple-visible')).to.have.length(1); }); diff --git a/packages/mui-material/src/Tab/Tab.test.js b/packages/mui-material/src/Tab/Tab.test.js index 01000e2c3d6819..c2c6a42b864adb 100644 --- a/packages/mui-material/src/Tab/Tab.test.js +++ b/packages/mui-material/src/Tab/Tab.test.js @@ -1,10 +1,11 @@ import { expect } from 'chai'; import * as React from 'react'; import { spy } from 'sinon'; -import { act, createRenderer, fireEvent } from '@mui/internal-test-utils'; +import { createRenderer, simulatePointerDevice } from '@mui/internal-test-utils'; import Tab, { tabClasses as classes } from '@mui/material/Tab'; import ButtonBase from '@mui/material/ButtonBase'; import describeConformance from '../../test/describeConformance'; +import * as ripple from '../../test/ripple'; describe('', () => { const { render } = createRenderer(); @@ -19,48 +20,39 @@ describe('', () => { skip: ['componentProp', 'componentsProp'], })); - it('should have a ripple by default', () => { + it('should have a ripple', async () => { const { container } = render(); - + await ripple.startTouch(container.querySelector('button')); expect(container.querySelector('.touch-ripple')).not.to.equal(null); }); - it('can disable the ripple', () => { + it('can disable the ripple', async () => { const { container } = render( , ); + await ripple.startTouch(container.querySelector('button')); expect(container.querySelector('.touch-ripple')).to.equal(null); }); - it('should have a focusRipple by default', () => { - const { container, getByRole } = render( + it('should have a focusRipple', async () => { + const { container } = render( , ); - // simulate pointer device - fireEvent.pointerDown(document.body); + simulatePointerDevice(); - act(() => { - fireEvent.keyDown(document.body, { key: 'Tab' }); - // jsdom doesn't actually support tab focus, we need to do it manually - getByRole('tab').focus(); - }); + await ripple.startFocus(container.querySelector('button')); expect(container.querySelector('.focus-ripple')).not.to.equal(null); }); - it('can disable the focusRipple', () => { - const { container, getByRole } = render( + it('can disable the focusRipple', async () => { + const { container } = render( , ); - // simulate pointer device - fireEvent.pointerDown(document.body); + simulatePointerDevice(); - act(() => { - fireEvent.keyDown(document.body, { key: 'Tab' }); - // jsdom doesn't actually support tab focus, we need to do it manually - getByRole('tab').focus(); - }); + await ripple.startFocus(container.querySelector('button')); expect(container.querySelector('.focus-ripple')).to.equal(null); }); diff --git a/packages/mui-material/src/internal/SwitchBase.test.js b/packages/mui-material/src/internal/SwitchBase.test.js index fef9508d39395e..51cf0b4f2ce717 100644 --- a/packages/mui-material/src/internal/SwitchBase.test.js +++ b/packages/mui-material/src/internal/SwitchBase.test.js @@ -7,6 +7,7 @@ import FormControl, { useFormControl } from '../FormControl'; import ButtonBase from '../ButtonBase'; import classes from './switchBaseClasses'; import describeConformance from '../../test/describeConformance'; +import * as ripple from '../../test/ripple'; describe('', () => { const { render } = createRenderer(); @@ -43,8 +44,8 @@ describe('', () => { expect(buttonInside.childNodes[1]).to.have.text('unchecked'); }); - it('should have a ripple by default', () => { - const { getByTestId } = render( + it('should have a ripple', async () => { + const { container, getByTestId } = render( ', () => { />, ); + await ripple.startTouch(container.querySelector('button')); + expect(getByTestId('TouchRipple')).not.to.equal(null); }); @@ -64,8 +67,8 @@ describe('', () => { expect(container.firstChild).to.have.class(classes.edgeStart); }); - it('can disable the ripple ', () => { - const { queryByTestId } = render( + it('can disable the ripple ', async () => { + const { container, queryByTestId } = render( ', () => { />, ); + await ripple.startTouch(container.querySelector('button')); + expect(queryByTestId('TouchRipple')).to.equal(null); }); diff --git a/packages/mui-material/test/ripple.ts b/packages/mui-material/test/ripple.ts new file mode 100644 index 00000000000000..be61357dfee239 --- /dev/null +++ b/packages/mui-material/test/ripple.ts @@ -0,0 +1,32 @@ +import { act, fireEvent } from '@mui/internal-test-utils'; + +function delay(ms: number) { + return new Promise(r => setTimeout(r, ms)); +} + +export async function asyncFireEvent(node: Element, event: keyof typeof fireEvent, options?: any) { + act(() => fireEvent[event](node, options)); + await delay(1); +} + +export function startTouch(node: Element, options?: any) { + return asyncFireEvent(node, 'mouseDown', options); +} + +export async function stopTouch(node: Element) { + return asyncFireEvent(node, 'mouseUp'); +} + +export async function startFocus(node: HTMLElement) { + act(() => { + node.focus(); + }); + await delay(1); +} + +export async function stopFocus(node: HTMLElement) { + act(() => { + node.blur(); + }); + await delay(1); +}