diff --git a/packages/mui-base/src/MenuButton/MenuButton.test.tsx b/packages/mui-base/src/MenuButton/MenuButton.test.tsx index 4a4624f034..a95219f24b 100644 --- a/packages/mui-base/src/MenuButton/MenuButton.test.tsx +++ b/packages/mui-base/src/MenuButton/MenuButton.test.tsx @@ -11,10 +11,6 @@ import { } from '@base_ui/react/useDropdown'; import { describeConformanceUnstyled } from '../../test/describeConformanceUnstyled'; -// TODO v6: initialize @testing-library/user-event using userEvent.setup() instead of directly calling methods e.g. userEvent.click() for all related tests in this file -// currently the setup() method uses the ClipboardEvent constructor which is incompatible with our lowest supported version of iOS Safari (12.2) https://github.com/mui/material-ui/blob/master/.browserslistrc#L44 -// userEvent.setup() requires Safari 14 or up to work - const testContext: DropdownContextValue = { dispatch: () => {}, popupId: 'menu-popup', @@ -146,6 +142,8 @@ describe('', () => { dispatch: dispatchSpy, }; + const user = userEvent.setup(); + const { getByRole } = render( {buttonComponent}, ); @@ -155,7 +153,7 @@ describe('', () => { button.focus(); }); - await userEvent.keyboard(`{${key}}`); + await user.keyboard(`{${key}}`); expect(dispatchSpy.calledOnce).to.equal(true); expect(dispatchSpy.args[0][0]).to.contain({ type: DropdownActionTypes.open }); @@ -171,6 +169,8 @@ describe('', () => { dispatch: dispatchSpy, }; + const user = userEvent.setup(); + const { getByRole } = render( {buttonComponent}, ); @@ -180,7 +180,7 @@ describe('', () => { button.focus(); }); - await userEvent.keyboard(`{${key}}`); + await user.keyboard(`{${key}}`); expect(dispatchSpy.calledOnce).to.equal(true); expect(dispatchSpy.args[0][0]).to.contain({ type: DropdownActionTypes.toggle }); diff --git a/packages/mui-base/src/Select/Select.test.tsx b/packages/mui-base/src/Select/Select.test.tsx index 57895a72eb..cf7a79fe5a 100644 --- a/packages/mui-base/src/Select/Select.test.tsx +++ b/packages/mui-base/src/Select/Select.test.tsx @@ -18,10 +18,6 @@ import { Option, OptionProps, OptionRootSlotProps, optionClasses } from '@base_u import { OptionGroup } from '@base_ui/react/OptionGroup'; import { describeConformanceUnstyled } from '../../test/describeConformanceUnstyled'; -// TODO v6: initialize @testing-library/user-event using userEvent.setup() instead of directly calling methods e.g. userEvent.click() for all related tests in this file -// currently the setup() method uses the ClipboardEvent constructor which is incompatible with our lowest supported version of iOS Safari (12.2) https://github.com/mui/material-ui/blob/master/.browserslistrc#L44 -// userEvent.setup() requires Safari 14 or up to work - describe('', () => { const mount = createMount(); const { render: internalRender } = createRenderer(); @@ -115,13 +111,16 @@ describe('', () => { const triggerType = selectComponent.props.slots?.root ? 'non-native' : 'native'; ['Enter', 'ArrowDown', 'ArrowUp', ' '].forEach((key) => { it(`opens the dropdown when the "${key}" key is pressed on a ${triggerType} button trigger`, async () => { + const user = userEvent.setup(); + const { getByRole } = await render(selectComponent); + const select = getByRole('combobox'); act(() => { select.focus(); }); - await userEvent.keyboard(`{${key}}`); + await user.keyboard(`{${key}}`); expect(select).to.have.attribute('aria-expanded', 'true'); expect(getByRole('listbox')).not.to.equal(null); @@ -131,6 +130,8 @@ describe('', () => { ['Enter', ' ', 'Escape'].forEach((key) => { it(`closes the dropdown when the "${key}" key is pressed`, async () => { + const user = userEvent.setup(); + const { getByRole } = await render( 1 @@ -142,7 +143,8 @@ describe('', () => { }); const listbox = getByRole('listbox'); - await userEvent.keyboard(`{${key}}`); + + await user.keyboard(`{${key}}`); expect(select).to.have.attribute('aria-expanded', 'false'); expect(listbox).toBeHidden(); @@ -151,6 +153,8 @@ describe('', () => { ['Enter', ' '].forEach((key) => { it(`does not close the multiselect dropdown when the "${key}" key is pressed`, async () => { + const user = userEvent.setup(); + const { getByRole, queryByRole } = await render( 1 @@ -161,7 +165,7 @@ describe('', () => { select.click(); }); - await userEvent.keyboard(`{${key}}`); + await user.keyboard(`{${key}}`); expect(select).to.have.attribute('aria-expanded', 'true'); expect(queryByRole('listbox')).not.to.equal(null); @@ -171,6 +175,8 @@ describe('', () => { describe('item selection', () => { ['Enter', ' '].forEach((key) => it(`selects a highlighted item using the "${key}" key in single mode`, async () => { + const user = userEvent.setup(); + const { getByRole } = await render( 1 @@ -180,9 +186,9 @@ describe('', () => { const select = getByRole('combobox'); - await userEvent.pointer({ target: select, keys: '[MouseLeft]' }); - await userEvent.keyboard('{ArrowDown}'); - await userEvent.keyboard(`{${key}}`); + await user.pointer({ target: select, keys: '[MouseLeft]' }); + await user.keyboard('{ArrowDown}'); + await user.keyboard(`{${key}}`); expect(select).to.have.text('2'); }), @@ -190,6 +196,8 @@ describe('', () => { ['Enter', ' '].forEach((key) => it(`selects a highlighted item using the "${key}" key in multiple mode`, async () => { + const user = userEvent.setup(); + const { getByRole } = await render( 1 @@ -199,10 +207,10 @@ describe('', () => { const select = getByRole('combobox'); - await userEvent.pointer({ target: select, keys: '[MouseLeft]' }); - await userEvent.keyboard(`{${key}}`); - await userEvent.keyboard('{ArrowDown}'); - await userEvent.keyboard(`{${key}}`); + await user.pointer({ target: select, keys: '[MouseLeft]' }); + await user.keyboard(`{${key}}`); + await user.keyboard('{ArrowDown}'); + await user.keyboard(`{${key}}`); expect(select).to.have.text('1, 2'); }), @@ -211,6 +219,8 @@ describe('', () => { describe('text navigation', () => { it('navigate to matched key', async () => { + const user = userEvent.setup(); + const { getByRole, getByText } = await render( Apple @@ -227,15 +237,17 @@ describe('', () => { select.click(); }); - await userEvent.keyboard('d'); + await user.keyboard('d'); expect(getByText('Dragon Fruit')).to.have.class(optionClasses.highlighted); - await userEvent.keyboard('r'); + await user.keyboard('r'); expect(getByText('Dragon Fruit')).to.have.class(optionClasses.highlighted); - await userEvent.keyboard('z'); + await user.keyboard('z'); expect(getByText('Dragon Fruit')).to.have.class(optionClasses.highlighted); }); it('navigate to next element with same starting character on repeated keys', async () => { + const user = userEvent.setup(); + const { getByRole, getByText } = await render( Apple @@ -252,11 +264,11 @@ describe('', () => { select.click(); }); - await userEvent.keyboard('c'); + await user.keyboard('c'); expect(getByText('Cherry')).to.have.class(optionClasses.highlighted); - await userEvent.keyboard('c'); + await user.keyboard('c'); expect(getByText('Calamondin')).to.have.class(optionClasses.highlighted); - await userEvent.keyboard('c'); + await user.keyboard('c'); expect(getByText('Cherry')).to.have.class(optionClasses.highlighted); }); @@ -275,6 +287,8 @@ describe('', () => { ); } + const user = userEvent.setup(); + const { getByRole, getByTestId } = await render( @@ -291,15 +305,17 @@ describe('', () => { select.click(); }); - await userEvent.keyboard('d'); + await user.keyboard('d'); expect(getByTestId('5')).to.have.class(optionClasses.highlighted); - await userEvent.keyboard('r'); + await user.keyboard('r'); expect(getByTestId('5')).to.have.class(optionClasses.highlighted); - await userEvent.keyboard('z'); + await user.keyboard('z'); expect(getByTestId('5')).to.have.class(optionClasses.highlighted); }); it('skips the non-stringifiable options', async () => { + const user = userEvent.setup(); + const { getByRole, getByText } = await render( Apple @@ -319,15 +335,17 @@ describe('', () => { select.click(); }); - await userEvent.keyboard('c'); + await user.keyboard('c'); expect(getByText('Cherry')).to.have.class(optionClasses.highlighted); - await userEvent.keyboard('c'); + await user.keyboard('c'); expect(getByText('Calamondin')).to.have.class(optionClasses.highlighted); - await userEvent.keyboard('c'); + await user.keyboard('c'); expect(getByText('Cherry')).to.have.class(optionClasses.highlighted); }); it('navigate to options with diacritic characters', async () => { + const user = userEvent.setup(); + const { getByRole, getByText } = await render( Aa @@ -343,14 +361,16 @@ describe('', () => { select.click(); }); - await userEvent.keyboard('b'); + await user.keyboard('b'); expect(getByText('Ba')).to.have.class(optionClasses.highlighted); - await userEvent.keyboard('{Control>}{Alt>}ą{/Alt}{/Control}'); + await user.keyboard('{Control>}{Alt>}ą{/Alt}{/Control}'); expect(getByText('Bą')).to.have.class(optionClasses.highlighted); }); it('navigate to next options with beginning diacritic characters', async () => { + const user = userEvent.setup(); + const { getByRole, getByText } = await render( Aa @@ -365,18 +385,20 @@ describe('', () => { select.click(); }); - await userEvent.keyboard('{Control>}{Alt>}ą{/Alt}{/Control}'); + await user.keyboard('{Control>}{Alt>}ą{/Alt}{/Control}'); expect(getByText('ąa')).to.have.class(optionClasses.highlighted); - await userEvent.keyboard('{Alt>}{Control>}ą{/Control}{/Alt}'); + await user.keyboard('{Alt>}{Control>}ą{/Control}{/Alt}'); expect(getByText('ąb')).to.have.class(optionClasses.highlighted); - await userEvent.keyboard('{Control>}{AltGraph>}ą{/AltGraph}{/Control}'); + await user.keyboard('{Control>}{AltGraph>}ą{/AltGraph}{/Control}'); expect(getByText('ąc')).to.have.class(optionClasses.highlighted); }); }); it('closes the listbox without selecting an option when "Escape" is pressed', async () => { + const user = userEvent.setup(); + const { getByRole, queryByRole } = await render( 1 @@ -390,8 +412,8 @@ describe('', () => { select.click(); }); - await userEvent.keyboard('{ArrowDown}'); // highlights '2' - await userEvent.keyboard('{Escape}'); + await user.keyboard('{ArrowDown}'); // highlights '2' + await user.keyboard('{Escape}'); expect(select).to.have.attribute('aria-expanded', 'false'); expect(select).to.have.text('1'); @@ -399,6 +421,8 @@ describe('', () => { }); it('closes the listbox after selecting with keyboard', async () => { + const user = userEvent.setup(); + const { getByRole, queryByRole } = await render( 1 @@ -408,9 +432,9 @@ describe('', () => { const select = getByRole('combobox'); - await userEvent.pointer({ target: select, keys: '[MouseLeft]' }); - await userEvent.keyboard('{ArrowDown}'); // highlights '2' - await userEvent.keyboard('{Enter}'); + await user.pointer({ target: select, keys: '[MouseLeft]' }); + await user.keyboard('{ArrowDown}'); // highlights '2' + await user.keyboard('{Enter}'); expect(select).to.have.attribute('aria-expanded', 'false'); expect(select).to.have.text('2'); @@ -438,6 +462,8 @@ describe('', () => { return ; }); + const user = userEvent.setup(); + const { getByRole } = await render( 1 @@ -455,23 +481,23 @@ describe('', () => { select.focus(); }); - await userEvent.keyboard('{ArrowDown}'); // opens the listbox and highlights 1 + await user.keyboard('{ArrowDown}'); // opens the listbox and highlights 1 const listbox = getByRole('listbox'); - await userEvent.keyboard('{ArrowDown}'); // highlights 2 + await user.keyboard('{ArrowDown}'); // highlights 2 expect(listbox.scrollTop).to.equal(0); - await userEvent.keyboard('{ArrowDown}'); // highlights 3 + await user.keyboard('{ArrowDown}'); // highlights 3 expect(listbox.scrollTop).to.equal(50); - await userEvent.keyboard('{ArrowDown}'); // highlights 4 + await user.keyboard('{ArrowDown}'); // highlights 4 expect(listbox.scrollTop).to.equal(100); - await userEvent.keyboard('{ArrowUp}'); // highlights 3 + await user.keyboard('{ArrowUp}'); // highlights 3 expect(listbox.scrollTop).to.equal(100); - await userEvent.keyboard('{ArrowUp}'); // highlights 2 + await user.keyboard('{ArrowUp}'); // highlights 2 expect(listbox.scrollTop).to.equal(50); }); }); @@ -1074,6 +1100,8 @@ describe('', () => { }); it('closes the listbox when the select is clicked again', async () => { + const user = userEvent.setup(); + const { getByRole } = await render( One @@ -1082,16 +1110,18 @@ describe('', () => { const select = getByRole('combobox'); - await userEvent.pointer({ keys: '[MouseLeft]', target: select }); + await user.pointer({ keys: '[MouseLeft]', target: select }); expect(select).to.have.attribute('aria-expanded', 'true'); - await userEvent.pointer({ keys: '[MouseLeft]', target: select }); + await user.pointer({ keys: '[MouseLeft]', target: select }); expect(select).to.have.attribute('aria-expanded', 'false'); }); it('closes the listbox without selecting an option when focus is lost', async () => { + const user = userEvent.setup(); + const { getByRole, getByTestId } = await render( @@ -1111,7 +1141,8 @@ describe('', () => { }); const listbox = getByRole('listbox'); - await userEvent.keyboard('{ArrowDown}'); // highlights '2' + + await user.keyboard('{ArrowDown}'); // highlights '2' const focusTarget = getByTestId('focus-target'); act(() => { @@ -1285,6 +1316,8 @@ describe('', () => { return ; }); + const user = userEvent.setup(); + const { getByRole } = await render( ', () => { // React renders twice in strict mode, so we expect twice the number of spy calls expect(renderOption1Spy.callCount).to.equal(2); // '1' as focusVisible becomes true - await userEvent.keyboard('{ArrowDown}'); // highlights '2' + await user.keyboard('{ArrowDown}'); // highlights '2' expect(renderOption1Spy.callCount).to.equal(6); // '1' rerenders as it loses highlight expect(renderOption2Spy.callCount).to.equal(4); // '2' rerenders as it receives highlight - await userEvent.keyboard('{Enter}'); // selects '2' + await user.keyboard('{Enter}'); // selects '2' expect(renderOption1Spy.callCount).to.equal(6); expect(renderOption2Spy.callCount).to.equal(8); diff --git a/test/karma.conf.profile.js b/test/karma.conf.profile.js index 5bf1104dc9..4482e12b79 100644 --- a/test/karma.conf.profile.js +++ b/test/karma.conf.profile.js @@ -153,7 +153,8 @@ module.exports = function setKarmaConfig(config) { os: 'Windows', os_version: '10', browser: 'firefox', - browser_version: '15.0', + // We support Firefox 115.x per .browserslistrc + browser_version: '115.0', }, // No accurate performance timings (integer precision instead of double). safari: {