From a8b86273bccd89b31ef7b0ad6152dee99dacb63c Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Tue, 28 Nov 2023 16:59:15 -0800 Subject: [PATCH 01/31] progress on updating the testing docs --- .../dev/docs/pages/react-spectrum/testing.mdx | 140 ++++++++++++++++++ 1 file changed, 140 insertions(+) diff --git a/packages/dev/docs/pages/react-spectrum/testing.mdx b/packages/dev/docs/pages/react-spectrum/testing.mdx index e0d3343762f..e70ecb553be 100644 --- a/packages/dev/docs/pages/react-spectrum/testing.mdx +++ b/packages/dev/docs/pages/react-spectrum/testing.mdx @@ -156,3 +156,143 @@ userEvent.type(document.activeElement, 'Pas$w0rd'); userEvent.tab(); userEvent.click(document.activeElement); ``` + +## Test setup + +### Providers + +When testing anything that uses a React Spectrum component, you must provide a wrapping Provider at the top level. Components rely on this wrapping provider +to inform them of the app's theme, locale, breakpoints and more. See the [Provider page](./Provider.html#application-provider) for a list of properties +your Provider can accept. If you see the following errors, you should check to see if you have a wrapping Provider. + +``` +Error: Uncaught [TypeError: Cannot destructure property 'scale' of '(0 , _provider.useProvider)(...)' as it is null.] +``` + +``` +TypeError: Cannot read properties of null (reading 'scale') +``` + +If you are using React Testing Library, you can overwrite the provided `render` function so that it automatically includes a Provider by default. + +// TODO: replace this with our util if we go that direction. Also test this +```tsx +import {Provider, defaultTheme} from '@adobe/react-spectrum'; +import React, {ReactElement} from 'react'; +import {render} from '@testing-library/react'; + +// export everything from React Testing Library +export * from '@testing-library/react'; + +function ProviderWrapper(props) { + return ( + + {props.children} + + ); +} + +export function customRender(ui, options) { + return render(ui, {wrapper: ProviderWrapper, ...options}); +} + +// override render method +export {customRender as render}; +``` + +### Timers + +If you are using fake timers in your test suite, be aware that you may need to advance your timers whenever an animation or load is taking place. +Historically, this most commonly happened when a modals, popovers, or trays is opened or closed as a result of a simulated user action (e.g. opening a Picker's dropdown via click). +In Jest, this can be handled by calling `act(() => jest.runAllTimers());` but you may require more precise control depending on the other time sensitive behavior you +are testing. Please see [Jest's timer docs](https://jestjs.io/docs/timer-mocks) or the equivalent docs of your test frameworks for more information on how to do so. +It is also a good idea to run all timers to completion after each test case to avoid any left over transitions or timeouts that a component may have setup during its lifecycle. + +```tsx +afterEach(() => { + act(() => jest.runAllTimers()); +}); +``` + +Consider adding a `act(() => jest.runAllTimers());` after your simulated user interaction if you run into a test failure that looks like the following: + +```tsx +TestingLibraryElementError: Unable to find an accessible element with the role "listbox" +``` + +If you are using real timers instead, you can await for popovers to appear or for a particular state of your app to be reached. If you are using React Testing Library, you can perform a `waitFor` query +to wait for a dialog to appear: + +```tsx +await waitFor(() => { + expect(getByRole('dialog')).toBeInTheDocument(); +}); +``` + +### Desktop vs Mobile + +Components like ComboBox and Picker render a different experience on mobile versus desktop. If you need to test mobile vs desktop for you app or want to make sure the React Spectrum +components are rendered only against a specific experience, you'll need to mock the window screen width accordingly. We currently use a +[screen width of 700px](https://github.com/adobe/react-spectrum/blob/5e487532e3ca4714513fb6ab64f7a78d9d1ca281/packages/%40react-spectrum/utils/src/useIsMobileDevice.ts#L15-L23) as the breakpoint +between mobile and desktop, so you should mock the `width` getter of `window.screen` to a value greater or less than this value accordingly. This example shows how you set this up in Jest. + +// TODO replace with helper function if we are going with that +```tsx +beforeAll(() => { + // Simulate mobile + jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => 650); +}); +``` + +// TODO: this section assumes that we will turn off virtualization for in test environments, update if aren't going ship with that +### Virtualized components + +Many of our collection components are virtualized out of the box and thus rely on DOM node measurement to know how large a item should be and how many items can be rendered at once. By default, virtualization for these +collection components is turned off by since it is an implementation detail of the component itself and thus doesn't need to be tested by your test suites. However, if you'd like to re-enable virtualization or are running against +an older version of the library that doesn't have this virtualization turned off by default, then you'll have to mock the `clientHeight` and `clientWidth` getters of the `HTMLElement` prototype to get the items of the virtualized collection +to render. `scrollHeight` and `scrollWidth` should also be mocked to set the height and width of each item. See below for an example implementation in Jest. + +```tsx +beforeAll(function () { + // The virtualizer will now think it has a visible area of 1000px x 1000px and that the items within it are 40px x 40px + jest.spyOn(window.HTMLElement.prototype, 'clientWidth', 'get').mockImplementation(() => 1000); + jest.spyOn(window.HTMLElement.prototype, 'clientHeight', 'get').mockImplementation(() => 1000); + jest.spyOn(window.HTMLElement.prototype, 'scrollHeight', 'get').mockImplementation(() => 40); + jest.spyOn(window.HTMLElement.prototype, 'scrollWidth', 'get').mockImplementation(() => 40); +}); +``` + +Please note that this is greatly simplified and still won't accurately reflect the behavior of the virtualizer in browser so we highly recommended that you avoid doing the above or use a browser based automated testing framework to +test virtualizer behavior. If you run into a test error where your collection component doesn't render any items/rows within it, try adding the above mocks. + +// TODO perhaps also note that various component doc pages will have testing sub sections if we deem them applicable + +## Gotchas + +// TODO: revise this if we do/don't decide to offer installPointerEvents and/or triggerLongPress from our utils. +// Also double check with our current version of user event library +### Simulating user long press + +Components like ListView and TableView support long press to perform specific interactions like drag and drop or entering selection mode on mobile devices. Unfortunately, the approach of using the userEvent library to simulate a press event and running timers to hit the +long press internal timer threshold isn't sufficient due to `useLongPress`'s usage of `PointerEvent`. Call our `installPointerEvent` utility to properly simulate these long press events in your tests. If you don't need to control the specific timings around the long press interaction, +use our `triggerLongPress` utility as shown below. + +```tsx +// top level in your test file +installPointerEvent(); + +let button = getByRole('button); + +// With userEvent and specific timing control +await user.pointer({target: button, keys: '[TouchA]'}); +act(() => jest.advanceTimersByTime(800)); +await user.pointer({target: button, keys: '[TouchA]'}); + +// With triggerLongPress +triggerLongPress(button); +... + +### Snapshot tests + +If you are use React 16 or 17, you may run into an issue where the ids generated by the React Spectrum components are changing on every snapshot. To remedy this, simply wrap your component in a [SSRProvider](../react-aria/SSRProvider.html). +Note that you can use this provider even if your component doesn't support server side rendering, it will simply stabilize the ids generated. From 790e8adeff9237590350166fb1c4e907f99d507b Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Wed, 29 Nov 2023 16:36:24 -0800 Subject: [PATCH 02/31] setup and testing of new util packages --- packages/@react-aria/test-utils/README.md | 3 + packages/@react-aria/test-utils/index.ts | 13 ++ packages/@react-aria/test-utils/package.json | 36 ++++++ packages/@react-aria/test-utils/src/events.ts | 113 ++++++++++++++++++ packages/@react-aria/test-utils/src/index.ts | 19 +++ .../test-utils/src/userEventMaps.ts | 11 ++ .../@react-spectrum/table/test/Table.test.js | 6 +- packages/@react-spectrum/test-utils/README.md | 3 + packages/@react-spectrum/test-utils/index.ts | 13 ++ .../@react-spectrum/test-utils/package.json | 48 ++++++++ .../@react-spectrum/test-utils/src/Blah.tsx | 43 +++++++ .../@react-spectrum/test-utils/src/index.ts | 15 +++ .../dev/docs/pages/react-spectrum/testing.mdx | 9 +- packages/dev/test-utils/package.json | 2 + .../dev/test-utils/src/StrictModeWrapper.tsx | 18 ++- .../dev/test-utils/src/mockImplementation.ts | 1 + packages/dev/test-utils/src/renderOverride.js | 7 +- 17 files changed, 347 insertions(+), 13 deletions(-) create mode 100644 packages/@react-aria/test-utils/README.md create mode 100644 packages/@react-aria/test-utils/index.ts create mode 100644 packages/@react-aria/test-utils/package.json create mode 100644 packages/@react-aria/test-utils/src/events.ts create mode 100644 packages/@react-aria/test-utils/src/index.ts create mode 100644 packages/@react-aria/test-utils/src/userEventMaps.ts create mode 100644 packages/@react-spectrum/test-utils/README.md create mode 100644 packages/@react-spectrum/test-utils/index.ts create mode 100644 packages/@react-spectrum/test-utils/package.json create mode 100644 packages/@react-spectrum/test-utils/src/Blah.tsx create mode 100644 packages/@react-spectrum/test-utils/src/index.ts diff --git a/packages/@react-aria/test-utils/README.md b/packages/@react-aria/test-utils/README.md new file mode 100644 index 00000000000..25125080234 --- /dev/null +++ b/packages/@react-aria/test-utils/README.md @@ -0,0 +1,3 @@ +# @react-aria/test-utils + +This package is part of [react-spectrum](https://github.com/adobe/react-spectrum). See the repo for more details. diff --git a/packages/@react-aria/test-utils/index.ts b/packages/@react-aria/test-utils/index.ts new file mode 100644 index 00000000000..7e5b036e91f --- /dev/null +++ b/packages/@react-aria/test-utils/index.ts @@ -0,0 +1,13 @@ +/* + * Copyright 2023 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +export * from './src'; diff --git a/packages/@react-aria/test-utils/package.json b/packages/@react-aria/test-utils/package.json new file mode 100644 index 00000000000..9f98559b106 --- /dev/null +++ b/packages/@react-aria/test-utils/package.json @@ -0,0 +1,36 @@ +{ + "name": "@react-aria/test-utils", + "version": "3.0.0-alpha.1", + "private": true, + "description": "Testing utils for react-aria patterns", + "license": "Apache-2.0", + "main": "dist/main.js", + "module": "dist/module.js", + "types": "dist/types.d.ts", + "exports": { + "types": "./dist/types.d.ts", + "import": "./dist/import.mjs", + "require": "./dist/main.js" + }, + "source": "src/index.ts", + "files": [ + "dist", + "src" + ], + "sideEffects": false, + "repository": { + "type": "git", + "url": "https://github.com/adobe/react-spectrum" + }, + "dependencies": { + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "@testing-library/react": "^14.0.0", + "@testing-library/user-event": "^14.4.3", + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/@react-aria/test-utils/src/events.ts b/packages/@react-aria/test-utils/src/events.ts new file mode 100644 index 00000000000..38b295c1630 --- /dev/null +++ b/packages/@react-aria/test-utils/src/events.ts @@ -0,0 +1,113 @@ +/* + * Copyright 2020 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +import {act, fireEvent} from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +// TODO: delete the dev/test-utils equivalent +// try to get rid of triggerPress and triggerTouch entirely from our code base so I can get rid of the +// file in dev/test-utils + +// Triggers a "longPress" event on an element. +export const DEFAULT_LONG_PRESS_TIME = 500; + +export function triggerLongPress(element, opts = {}) { + fireEvent.pointerDown(element, {pointerType: 'touch', ...opts}); + act(() => { + jest.advanceTimersByTime(DEFAULT_LONG_PRESS_TIME); + }); + fireEvent.pointerUp(element, {pointerType: 'touch', ...opts}); +} + +/** + * Enables reading pageX/pageY from fireEvent.mouse*(..., {pageX: ..., pageY: ...}). + */ +export function installMouseEvent() { + beforeAll(() => { + let oldMouseEvent = MouseEvent; + // @ts-ignore + global.MouseEvent = class FakeMouseEvent extends MouseEvent { + _init: {pageX: number, pageY: number}; + constructor(name, init) { + super(name, init); + this._init = init; + } + get pageX() { + return this._init.pageX; + } + get pageY() { + return this._init.pageY; + } + }; + // @ts-ignore + global.MouseEvent.oldMouseEvent = oldMouseEvent; + }); + afterAll(() => { + // @ts-ignore + global.MouseEvent = global.MouseEvent.oldMouseEvent; + }); +} + +export function installPointerEvent() { + beforeAll(() => { + // @ts-ignore + global.PointerEvent = class FakePointerEvent extends MouseEvent { + _init: {pageX: number, pageY: number, pointerType: string, pointerId: number, width: number, height: number}; + constructor(name, init) { + super(name, init); + this._init = init; + } + get pointerType() { + return this._init.pointerType ?? 'mouse'; + } + get pointerId() { + return this._init.pointerId; + } + get pageX() { + return this._init.pageX; + } + get pageY() { + return this._init.pageY; + } + get width() { + return this._init.width; + } + get height() { + return this._init.height; + } + }; + }); + afterAll(() => { + // @ts-ignore + delete global.PointerEvent; + }); +} + +/** + * Must **not** be called inside an `act` callback! + * + * \@testing-library/user-event's `type` helper doesn't call `act` every keystroke. + * But we want to run all event handles after every character. + * @param el The input element to type into. + * @param value The text. + * @deprecated Use `user.keyboard` instead. + */ +export function typeText(el: HTMLElement, value: string, opts?: any) { + let skipClick = document.activeElement === el; + for (let char of value) { + act(() => { + userEvent.type(el, char, {skipClick, ...opts}); + }); + + skipClick = true; + } +} diff --git a/packages/@react-aria/test-utils/src/index.ts b/packages/@react-aria/test-utils/src/index.ts new file mode 100644 index 00000000000..f30c01d6229 --- /dev/null +++ b/packages/@react-aria/test-utils/src/index.ts @@ -0,0 +1,19 @@ +/* + * Copyright 2023 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +// TODO update +export * from './events'; +export * from './testSSR'; +export * from './renderOverride'; +export * from './StrictModeWrapper'; +export * from './mockImplementation'; +export * from './userEventMaps'; diff --git a/packages/@react-aria/test-utils/src/userEventMaps.ts b/packages/@react-aria/test-utils/src/userEventMaps.ts new file mode 100644 index 00000000000..9a91a9d918d --- /dev/null +++ b/packages/@react-aria/test-utils/src/userEventMaps.ts @@ -0,0 +1,11 @@ +import {pointerKey} from '@testing-library/user-event/system/pointer/shared'; + +// TODO: delete the dev test-utils equivalent +export let pointerMap: pointerKey[] = [ + {name: 'MouseLeft', pointerType: 'mouse', button: 'primary', height: 1, width: 1, pressure: 0.5}, + {name: 'MouseRight', pointerType: 'mouse', button: 'secondary'}, + {name: 'MouseMiddle', pointerType: 'mouse', button: 'auxiliary'}, + {name: 'TouchA', pointerType: 'touch', height: 1, width: 1}, + {name: 'TouchB', pointerType: 'touch'}, + {name: 'TouchC', pointerType: 'touch'} +] as unknown as pointerKey[]; diff --git a/packages/@react-spectrum/table/test/Table.test.js b/packages/@react-spectrum/table/test/Table.test.js index 5f07aede145..9eb4e2497d0 100644 --- a/packages/@react-spectrum/table/test/Table.test.js +++ b/packages/@react-spectrum/table/test/Table.test.js @@ -159,9 +159,9 @@ export let tableTests = () => { let render = (children, scale = 'medium') => { let tree = renderComponent( - + // {children} - + // ); // account for table column resizing to do initial pass due to relayout from useTableColumnResizeState render act(() => {jest.runAllTimers();}); @@ -191,7 +191,7 @@ export let tableTests = () => { let focusCell = (tree, text) => act(() => getCell(tree, text).focus()); let moveFocus = (key, opts = {}) => {fireEvent.keyDown(document.activeElement, {key, ...opts});}; - it('renders a static table', function () { + it.only('renders a static table', function () { let {getByRole} = render( diff --git a/packages/@react-spectrum/test-utils/README.md b/packages/@react-spectrum/test-utils/README.md new file mode 100644 index 00000000000..0030138c3bf --- /dev/null +++ b/packages/@react-spectrum/test-utils/README.md @@ -0,0 +1,3 @@ +# @react-spectrum/test-utils + +This package is part of [react-spectrum](https://github.com/adobe/react-spectrum). See the repo for more details. diff --git a/packages/@react-spectrum/test-utils/index.ts b/packages/@react-spectrum/test-utils/index.ts new file mode 100644 index 00000000000..7e5b036e91f --- /dev/null +++ b/packages/@react-spectrum/test-utils/index.ts @@ -0,0 +1,13 @@ +/* + * Copyright 2023 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +export * from './src'; diff --git a/packages/@react-spectrum/test-utils/package.json b/packages/@react-spectrum/test-utils/package.json new file mode 100644 index 00000000000..9043ad824f6 --- /dev/null +++ b/packages/@react-spectrum/test-utils/package.json @@ -0,0 +1,48 @@ +{ + "name": "@react-spectrum/todotest-utils", + "version": "3.0.0-alpha.1", + "private": true, + "description": "Spectrum UI components in React", + "license": "Apache-2.0", + "main": "dist/main.js", + "module": "dist/module.js", + "types": "dist/types.d.ts", + "exports": { + "types": "./dist/types.d.ts", + "import": "./dist/import.mjs", + "require": "./dist/main.js" + }, + "source": "src/index.ts", + "files": ["dist", "src"], + "sideEffects": [ + "*.css" + ], + "targets": { + "main": { + "includeNodeModules": ["@adobe/spectrum-css-temp"] + }, + "module": { + "includeNodeModules": ["@adobe/spectrum-css-temp"] + } + }, + "repository": { + "type": "git", + "url": "https://github.com/adobe/react-spectrum" + }, + "dependencies": { + "@swc/helpers": "^0.5.0", + "@react-aria/utils": "^3.0.0", + "@react-spectrum/utils": "^3.0.0", + "@react-types/shared": "^3.0.0" + }, + "devDependencies": { + "@adobe/spectrum-css-temp": "3.0.0-alpha.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "@react-spectrum/provider": "^3.0.0" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/@react-spectrum/test-utils/src/Blah.tsx b/packages/@react-spectrum/test-utils/src/Blah.tsx new file mode 100644 index 00000000000..62f7f04b374 --- /dev/null +++ b/packages/@react-spectrum/test-utils/src/Blah.tsx @@ -0,0 +1,43 @@ +/* + * Copyright 2023 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +import {classNames, useDOMRef, useStyleProps} from '@react-spectrum/utils'; +import {DOMProps, DOMRef, StyleProps} from '@react-types/shared'; +import {filterDOMProps} from '@react-aria/utils'; +import React from 'react'; +import {useProviderProps} from '@react-spectrum/provider'; + +export interface SpectrumBlahProps extends DOMProps, StyleProps { + onChange?: any +} + +function Blah(props: SpectrumBlahProps, ref: DOMRef) { + // Grabs specific props from the closest Provider (see https://react-spectrum.adobe.com/react-spectrum/Provider.html#property-groups). Remove if your component doesn't support any of the listed props. + props = useProviderProps(props); + // Handles RSP specific style options, UNSAFE_style, and UNSAFE_className props (see https://react-spectrum.adobe.com/react-spectrum/styling.html#style-props) + let {styleProps} = useStyleProps(props); + let domRef = useDOMRef(ref); + + return ( +
+ ); +} + +/** + * TODO: Add description of component here. + */ +const _Blah = React.forwardRef(Blah); +export {_Blah as Blah}; diff --git a/packages/@react-spectrum/test-utils/src/index.ts b/packages/@react-spectrum/test-utils/src/index.ts new file mode 100644 index 00000000000..0ccdcbabaed --- /dev/null +++ b/packages/@react-spectrum/test-utils/src/index.ts @@ -0,0 +1,15 @@ +/* + * Copyright 2023 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +/// + +export * from './Blah'; diff --git a/packages/dev/docs/pages/react-spectrum/testing.mdx b/packages/dev/docs/pages/react-spectrum/testing.mdx index e70ecb553be..3dc57e6c80d 100644 --- a/packages/dev/docs/pages/react-spectrum/testing.mdx +++ b/packages/dev/docs/pages/react-spectrum/testing.mdx @@ -283,10 +283,11 @@ installPointerEvent(); let button = getByRole('button); -// With userEvent and specific timing control -await user.pointer({target: button, keys: '[TouchA]'}); +// TODO: test with userevent +// With fireEvent and specific timing control +await user.pointer({target: el, keys: '[TouchA>]'}); act(() => jest.advanceTimersByTime(800)); -await user.pointer({target: button, keys: '[TouchA]'}); +await user.pointer({target: el, keys: '[/TouchA]'}); // With triggerLongPress triggerLongPress(button); @@ -295,4 +296,4 @@ triggerLongPress(button); ### Snapshot tests If you are use React 16 or 17, you may run into an issue where the ids generated by the React Spectrum components are changing on every snapshot. To remedy this, simply wrap your component in a [SSRProvider](../react-aria/SSRProvider.html). -Note that you can use this provider even if your component doesn't support server side rendering, it will simply stabilize the ids generated. +Note that you can use the SSRProvider even if your component doesn't support server side rendering, it will simply stabilize the ids generated. diff --git a/packages/dev/test-utils/package.json b/packages/dev/test-utils/package.json index 23cea905a17..521ee2be4ab 100644 --- a/packages/dev/test-utils/package.json +++ b/packages/dev/test-utils/package.json @@ -33,10 +33,12 @@ }, "dependencies": { "@react-aria/ssr": "^3.0.0", + "@react-spectrum/theme-default": "^3.5.7", "@swc/helpers": "^0.5.0", "resolve": "^1.17.0" }, "peerDependencies": { + "@react-spectrum/provider": "^3.9.2", "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.4.3", "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", diff --git a/packages/dev/test-utils/src/StrictModeWrapper.tsx b/packages/dev/test-utils/src/StrictModeWrapper.tsx index 20449cf3c85..70e77d3d442 100644 --- a/packages/dev/test-utils/src/StrictModeWrapper.tsx +++ b/packages/dev/test-utils/src/StrictModeWrapper.tsx @@ -10,16 +10,28 @@ * governing permissions and limitations under the License. */ +import {Provider} from '@react-spectrum/provider'; import React, {StrictMode} from 'react'; +import {theme} from '@react-spectrum/theme-default'; + +// TODO move over and include Provider +// first get Provider working here, then move it over +export function RenderWrapper(props) { + console.log('props', props); + + let providerWrapper = ( + + {props.children} + + ); -export function StrictModeWrapper(props) { if (process.env.STRICT_MODE) { return ( - {props.children} + {providerWrapper} ); } - return props.children; + return providerWrapper; } diff --git a/packages/dev/test-utils/src/mockImplementation.ts b/packages/dev/test-utils/src/mockImplementation.ts index 1b4ed951446..5c54899d64b 100644 --- a/packages/dev/test-utils/src/mockImplementation.ts +++ b/packages/dev/test-utils/src/mockImplementation.ts @@ -15,6 +15,7 @@ type Access = [any, string, 'get' | 'set']; type SpyTarget = Method | Access type MockCalls = Array<() => any> +// TODO: ask if this stuff should also live in the react-spectrum/test-util package? What about the SSR stuff as well? // Util for mockImplementation that automatically handles extra calls needed for strict mode export function mockImplementation(spyTarget: SpyTarget, mockCalls: MockCalls, retainLastMock = true) { if (mockCalls.length === 0) { diff --git a/packages/dev/test-utils/src/renderOverride.js b/packages/dev/test-utils/src/renderOverride.js index a1850600916..e0d6dd856c8 100644 --- a/packages/dev/test-utils/src/renderOverride.js +++ b/packages/dev/test-utils/src/renderOverride.js @@ -11,7 +11,7 @@ */ import {render} from '@testing-library/react'; -import {StrictModeWrapper} from './StrictModeWrapper'; +import {RenderWrapper} from './StrictModeWrapper'; let reactTestingLibrary = require('@testing-library/react'); @@ -28,8 +28,9 @@ if (!renderHook) { actHook = rhtl.act; } -function customRender(ui, options) { - return render(ui, {wrapper: StrictModeWrapper, ...options}); +// TODO update and move to spectrum utils package. Also update so StrictModeWrapper is both strictmode and provider +function customRender(ui, options, providerOptions) { + return render(ui, {wrapper: RenderWrapper, ...options}); } // override render method with From 5c5b8c949a08f5fdafdb9d352912d6afb7c028e8 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Wed, 29 Nov 2023 17:17:05 -0800 Subject: [PATCH 03/31] move test utils to react-spectrum and add provider wrapper --- packages/@react-aria/test-utils/src/index.ts | 5 -- .../@react-spectrum/test-utils/package.json | 26 ++++++--- .../@react-spectrum/test-utils/src/Blah.tsx | 43 --------------- .../test-utils/src/ProviderWrapper.tsx} | 10 ++-- .../test-utils/src/events.ts | 0 .../@react-spectrum/test-utils/src/index.ts | 9 +++- .../test-utils/src/mockImplementation.ts | 0 .../test-utils/src/renderOverride.js | 10 ++-- .../test-utils/src/ssrSetup.js | 0 .../test-utils/src/ssrTeardown.js | 0 .../test-utils/src/ssrUtils.js | 0 .../test-utils/src/ssrWorker.js | 0 .../test-utils/src/testSSR.js | 0 .../test-utils/src/userEventMaps.ts | 0 packages/dev/test-utils/README.md | 3 -- packages/dev/test-utils/index.ts | 13 ----- packages/dev/test-utils/package.json | 53 ------------------- packages/dev/test-utils/src/index.ts | 20 ------- 18 files changed, 36 insertions(+), 156 deletions(-) delete mode 100644 packages/@react-spectrum/test-utils/src/Blah.tsx rename packages/{dev/test-utils/src/StrictModeWrapper.tsx => @react-spectrum/test-utils/src/ProviderWrapper.tsx} (80%) rename packages/{dev => @react-spectrum}/test-utils/src/events.ts (100%) rename packages/{dev => @react-spectrum}/test-utils/src/mockImplementation.ts (100%) rename packages/{dev => @react-spectrum}/test-utils/src/renderOverride.js (85%) rename packages/{dev => @react-spectrum}/test-utils/src/ssrSetup.js (100%) rename packages/{dev => @react-spectrum}/test-utils/src/ssrTeardown.js (100%) rename packages/{dev => @react-spectrum}/test-utils/src/ssrUtils.js (100%) rename packages/{dev => @react-spectrum}/test-utils/src/ssrWorker.js (100%) rename packages/{dev => @react-spectrum}/test-utils/src/testSSR.js (100%) rename packages/{dev => @react-spectrum}/test-utils/src/userEventMaps.ts (100%) delete mode 100644 packages/dev/test-utils/README.md delete mode 100644 packages/dev/test-utils/index.ts delete mode 100644 packages/dev/test-utils/package.json delete mode 100644 packages/dev/test-utils/src/index.ts diff --git a/packages/@react-aria/test-utils/src/index.ts b/packages/@react-aria/test-utils/src/index.ts index f30c01d6229..51b67b7f7af 100644 --- a/packages/@react-aria/test-utils/src/index.ts +++ b/packages/@react-aria/test-utils/src/index.ts @@ -12,8 +12,3 @@ // TODO update export * from './events'; -export * from './testSSR'; -export * from './renderOverride'; -export * from './StrictModeWrapper'; -export * from './mockImplementation'; -export * from './userEventMaps'; diff --git a/packages/@react-spectrum/test-utils/package.json b/packages/@react-spectrum/test-utils/package.json index 9043ad824f6..0d035e2bc3b 100644 --- a/packages/@react-spectrum/test-utils/package.json +++ b/packages/@react-spectrum/test-utils/package.json @@ -1,5 +1,5 @@ { - "name": "@react-spectrum/todotest-utils", + "name": "@react-spectrum/test-utils", "version": "3.0.0-alpha.1", "private": true, "description": "Spectrum UI components in React", @@ -13,16 +13,23 @@ "require": "./dist/main.js" }, "source": "src/index.ts", - "files": ["dist", "src"], + "files": [ + "dist", + "src" + ], "sideEffects": [ "*.css" ], "targets": { "main": { - "includeNodeModules": ["@adobe/spectrum-css-temp"] + "includeNodeModules": [ + "@adobe/spectrum-css-temp" + ] }, "module": { - "includeNodeModules": ["@adobe/spectrum-css-temp"] + "includeNodeModules": [ + "@adobe/spectrum-css-temp" + ] } }, "repository": { @@ -30,17 +37,20 @@ "url": "https://github.com/adobe/react-spectrum" }, "dependencies": { + "@react-aria/ssr": "^3.9.0", + "@react-spectrum/theme-default": "^3.5.7", "@swc/helpers": "^0.5.0", - "@react-aria/utils": "^3.0.0", - "@react-spectrum/utils": "^3.0.0", - "@react-types/shared": "^3.0.0" + "resolve": "^1.17.0" }, "devDependencies": { "@adobe/spectrum-css-temp": "3.0.0-alpha.1" }, "peerDependencies": { + "@react-spectrum/provider": "^3.9.2", + "@testing-library/react": "^14.0.0", + "@testing-library/user-event": "^14.4.3", "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", - "@react-spectrum/provider": "^3.0.0" + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" }, "publishConfig": { "access": "public" diff --git a/packages/@react-spectrum/test-utils/src/Blah.tsx b/packages/@react-spectrum/test-utils/src/Blah.tsx deleted file mode 100644 index 62f7f04b374..00000000000 --- a/packages/@react-spectrum/test-utils/src/Blah.tsx +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2023 Adobe. All rights reserved. - * This file is licensed to you under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. You may obtain a copy - * of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under - * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS - * OF ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. - */ - -import {classNames, useDOMRef, useStyleProps} from '@react-spectrum/utils'; -import {DOMProps, DOMRef, StyleProps} from '@react-types/shared'; -import {filterDOMProps} from '@react-aria/utils'; -import React from 'react'; -import {useProviderProps} from '@react-spectrum/provider'; - -export interface SpectrumBlahProps extends DOMProps, StyleProps { - onChange?: any -} - -function Blah(props: SpectrumBlahProps, ref: DOMRef) { - // Grabs specific props from the closest Provider (see https://react-spectrum.adobe.com/react-spectrum/Provider.html#property-groups). Remove if your component doesn't support any of the listed props. - props = useProviderProps(props); - // Handles RSP specific style options, UNSAFE_style, and UNSAFE_className props (see https://react-spectrum.adobe.com/react-spectrum/styling.html#style-props) - let {styleProps} = useStyleProps(props); - let domRef = useDOMRef(ref); - - return ( -
- ); -} - -/** - * TODO: Add description of component here. - */ -const _Blah = React.forwardRef(Blah); -export {_Blah as Blah}; diff --git a/packages/dev/test-utils/src/StrictModeWrapper.tsx b/packages/@react-spectrum/test-utils/src/ProviderWrapper.tsx similarity index 80% rename from packages/dev/test-utils/src/StrictModeWrapper.tsx rename to packages/@react-spectrum/test-utils/src/ProviderWrapper.tsx index 70e77d3d442..549577654ef 100644 --- a/packages/dev/test-utils/src/StrictModeWrapper.tsx +++ b/packages/@react-spectrum/test-utils/src/ProviderWrapper.tsx @@ -14,14 +14,12 @@ import {Provider} from '@react-spectrum/provider'; import React, {StrictMode} from 'react'; import {theme} from '@react-spectrum/theme-default'; -// TODO move over and include Provider -// first get Provider working here, then move it over -export function RenderWrapper(props) { - console.log('props', props); +export function ProviderWrapper(props) { + let {children, ...providerProps} = props; let providerWrapper = ( - - {props.children} + + {children} ); diff --git a/packages/dev/test-utils/src/events.ts b/packages/@react-spectrum/test-utils/src/events.ts similarity index 100% rename from packages/dev/test-utils/src/events.ts rename to packages/@react-spectrum/test-utils/src/events.ts diff --git a/packages/@react-spectrum/test-utils/src/index.ts b/packages/@react-spectrum/test-utils/src/index.ts index 0ccdcbabaed..7091d9041f0 100644 --- a/packages/@react-spectrum/test-utils/src/index.ts +++ b/packages/@react-spectrum/test-utils/src/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2023 Adobe. All rights reserved. + * Copyright 2020 Adobe. All rights reserved. * This file is licensed to you under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 @@ -12,4 +12,9 @@ /// -export * from './Blah'; +export * from './events'; +export * from './testSSR'; +export * from './renderOverride'; +export * from './ProviderWrapper'; +export * from './mockImplementation'; +export * from './userEventMaps'; diff --git a/packages/dev/test-utils/src/mockImplementation.ts b/packages/@react-spectrum/test-utils/src/mockImplementation.ts similarity index 100% rename from packages/dev/test-utils/src/mockImplementation.ts rename to packages/@react-spectrum/test-utils/src/mockImplementation.ts diff --git a/packages/dev/test-utils/src/renderOverride.js b/packages/@react-spectrum/test-utils/src/renderOverride.js similarity index 85% rename from packages/dev/test-utils/src/renderOverride.js rename to packages/@react-spectrum/test-utils/src/renderOverride.js index e0d6dd856c8..59495cd2ed3 100644 --- a/packages/dev/test-utils/src/renderOverride.js +++ b/packages/@react-spectrum/test-utils/src/renderOverride.js @@ -10,8 +10,9 @@ * governing permissions and limitations under the License. */ +import {ProviderWrapper} from './ProviderWrapper'; +import React from 'react'; import {render} from '@testing-library/react'; -import {RenderWrapper} from './StrictModeWrapper'; let reactTestingLibrary = require('@testing-library/react'); @@ -28,9 +29,12 @@ if (!renderHook) { actHook = rhtl.act; } -// TODO update and move to spectrum utils package. Also update so StrictModeWrapper is both strictmode and provider function customRender(ui, options, providerOptions) { - return render(ui, {wrapper: RenderWrapper, ...options}); + return render(( + + {ui} + + ), options); } // override render method with diff --git a/packages/dev/test-utils/src/ssrSetup.js b/packages/@react-spectrum/test-utils/src/ssrSetup.js similarity index 100% rename from packages/dev/test-utils/src/ssrSetup.js rename to packages/@react-spectrum/test-utils/src/ssrSetup.js diff --git a/packages/dev/test-utils/src/ssrTeardown.js b/packages/@react-spectrum/test-utils/src/ssrTeardown.js similarity index 100% rename from packages/dev/test-utils/src/ssrTeardown.js rename to packages/@react-spectrum/test-utils/src/ssrTeardown.js diff --git a/packages/dev/test-utils/src/ssrUtils.js b/packages/@react-spectrum/test-utils/src/ssrUtils.js similarity index 100% rename from packages/dev/test-utils/src/ssrUtils.js rename to packages/@react-spectrum/test-utils/src/ssrUtils.js diff --git a/packages/dev/test-utils/src/ssrWorker.js b/packages/@react-spectrum/test-utils/src/ssrWorker.js similarity index 100% rename from packages/dev/test-utils/src/ssrWorker.js rename to packages/@react-spectrum/test-utils/src/ssrWorker.js diff --git a/packages/dev/test-utils/src/testSSR.js b/packages/@react-spectrum/test-utils/src/testSSR.js similarity index 100% rename from packages/dev/test-utils/src/testSSR.js rename to packages/@react-spectrum/test-utils/src/testSSR.js diff --git a/packages/dev/test-utils/src/userEventMaps.ts b/packages/@react-spectrum/test-utils/src/userEventMaps.ts similarity index 100% rename from packages/dev/test-utils/src/userEventMaps.ts rename to packages/@react-spectrum/test-utils/src/userEventMaps.ts diff --git a/packages/dev/test-utils/README.md b/packages/dev/test-utils/README.md deleted file mode 100644 index 0030138c3bf..00000000000 --- a/packages/dev/test-utils/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# @react-spectrum/test-utils - -This package is part of [react-spectrum](https://github.com/adobe/react-spectrum). See the repo for more details. diff --git a/packages/dev/test-utils/index.ts b/packages/dev/test-utils/index.ts deleted file mode 100644 index 1210ae1e402..00000000000 --- a/packages/dev/test-utils/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright 2020 Adobe. All rights reserved. - * This file is licensed to you under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. You may obtain a copy - * of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under - * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS - * OF ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. - */ - -export * from './src'; diff --git a/packages/dev/test-utils/package.json b/packages/dev/test-utils/package.json deleted file mode 100644 index 521ee2be4ab..00000000000 --- a/packages/dev/test-utils/package.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "name": "@react-spectrum/test-utils", - "version": "3.0.0-alpha.1", - "private": true, - "description": "Spectrum UI components in React", - "license": "Apache-2.0", - "main": "dist/main.js", - "module": "dist/module.js", - "types": "dist/types.d.ts", - "source": "src/index.ts", - "files": [ - "dist", - "src" - ], - "sideEffects": [ - "*.css" - ], - "targets": { - "main": { - "includeNodeModules": [ - "@adobe/spectrum-css-temp" - ] - }, - "module": { - "includeNodeModules": [ - "@adobe/spectrum-css-temp" - ] - } - }, - "repository": { - "type": "git", - "url": "https://github.com/adobe/react-spectrum" - }, - "dependencies": { - "@react-aria/ssr": "^3.0.0", - "@react-spectrum/theme-default": "^3.5.7", - "@swc/helpers": "^0.5.0", - "resolve": "^1.17.0" - }, - "peerDependencies": { - "@react-spectrum/provider": "^3.9.2", - "@testing-library/react": "^14.0.0", - "@testing-library/user-event": "^14.4.3", - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" - }, - "devDependencies": { - "@adobe/spectrum-css-temp": "3.0.0-alpha.1" - }, - "publishConfig": { - "access": "public" - } -} diff --git a/packages/dev/test-utils/src/index.ts b/packages/dev/test-utils/src/index.ts deleted file mode 100644 index 19010e66919..00000000000 --- a/packages/dev/test-utils/src/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2020 Adobe. All rights reserved. - * This file is licensed to you under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. You may obtain a copy - * of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under - * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS - * OF ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. - */ - -/// - -export * from './events'; -export * from './testSSR'; -export * from './renderOverride'; -export * from './StrictModeWrapper'; -export * from './mockImplementation'; -export * from './userEventMaps'; From 80b67c19511d449739eabc0307aeb5cac8a449da Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Thu, 30 Nov 2023 16:05:14 -0800 Subject: [PATCH 04/31] restoring StrictModeWrapper --- packages/@react-spectrum/test-utils/package.json | 2 -- ...ProviderWrapper.tsx => StrictModeWrapper.tsx} | 16 +++------------- packages/@react-spectrum/test-utils/src/index.ts | 2 +- .../test-utils/src/renderOverride.js | 11 +++-------- 4 files changed, 7 insertions(+), 24 deletions(-) rename packages/@react-spectrum/test-utils/src/{ProviderWrapper.tsx => StrictModeWrapper.tsx} (67%) diff --git a/packages/@react-spectrum/test-utils/package.json b/packages/@react-spectrum/test-utils/package.json index 0d035e2bc3b..e7e141d158f 100644 --- a/packages/@react-spectrum/test-utils/package.json +++ b/packages/@react-spectrum/test-utils/package.json @@ -38,7 +38,6 @@ }, "dependencies": { "@react-aria/ssr": "^3.9.0", - "@react-spectrum/theme-default": "^3.5.7", "@swc/helpers": "^0.5.0", "resolve": "^1.17.0" }, @@ -46,7 +45,6 @@ "@adobe/spectrum-css-temp": "3.0.0-alpha.1" }, "peerDependencies": { - "@react-spectrum/provider": "^3.9.2", "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.4.3", "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", diff --git a/packages/@react-spectrum/test-utils/src/ProviderWrapper.tsx b/packages/@react-spectrum/test-utils/src/StrictModeWrapper.tsx similarity index 67% rename from packages/@react-spectrum/test-utils/src/ProviderWrapper.tsx rename to packages/@react-spectrum/test-utils/src/StrictModeWrapper.tsx index 549577654ef..20449cf3c85 100644 --- a/packages/@react-spectrum/test-utils/src/ProviderWrapper.tsx +++ b/packages/@react-spectrum/test-utils/src/StrictModeWrapper.tsx @@ -10,26 +10,16 @@ * governing permissions and limitations under the License. */ -import {Provider} from '@react-spectrum/provider'; import React, {StrictMode} from 'react'; -import {theme} from '@react-spectrum/theme-default'; - -export function ProviderWrapper(props) { - let {children, ...providerProps} = props; - - let providerWrapper = ( - - {children} - - ); +export function StrictModeWrapper(props) { if (process.env.STRICT_MODE) { return ( - {providerWrapper} + {props.children} ); } - return providerWrapper; + return props.children; } diff --git a/packages/@react-spectrum/test-utils/src/index.ts b/packages/@react-spectrum/test-utils/src/index.ts index 7091d9041f0..19010e66919 100644 --- a/packages/@react-spectrum/test-utils/src/index.ts +++ b/packages/@react-spectrum/test-utils/src/index.ts @@ -15,6 +15,6 @@ export * from './events'; export * from './testSSR'; export * from './renderOverride'; -export * from './ProviderWrapper'; +export * from './StrictModeWrapper'; export * from './mockImplementation'; export * from './userEventMaps'; diff --git a/packages/@react-spectrum/test-utils/src/renderOverride.js b/packages/@react-spectrum/test-utils/src/renderOverride.js index 59495cd2ed3..a1850600916 100644 --- a/packages/@react-spectrum/test-utils/src/renderOverride.js +++ b/packages/@react-spectrum/test-utils/src/renderOverride.js @@ -10,9 +10,8 @@ * governing permissions and limitations under the License. */ -import {ProviderWrapper} from './ProviderWrapper'; -import React from 'react'; import {render} from '@testing-library/react'; +import {StrictModeWrapper} from './StrictModeWrapper'; let reactTestingLibrary = require('@testing-library/react'); @@ -29,12 +28,8 @@ if (!renderHook) { actHook = rhtl.act; } -function customRender(ui, options, providerOptions) { - return render(( - - {ui} - - ), options); +function customRender(ui, options) { + return render(ui, {wrapper: StrictModeWrapper, ...options}); } // override render method with From 9c8ef8f7d5b202da00b2344b778a6d010aaf6747 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Thu, 30 Nov 2023 16:30:31 -0800 Subject: [PATCH 05/31] add desktop and mobile mock util setup --- .../aria-modal-polyfill/test/index.test.tsx | 4 +- .../test/useSelectableCollection.test.js | 6 +- .../test/SearchAutocomplete.test.js | 12 +-- .../combobox/test/ComboBox.test.js | 14 +-- .../test/ContextualHelp.test.js | 4 +- .../datepicker/test/DatePickerBase.test.js | 4 +- .../dialog/test/DialogTrigger.test.js | 11 +-- .../@react-spectrum/form/test/Form.test.js | 4 +- .../menu/test/MenuTrigger.test.js | 3 +- .../picker/test/Picker.test.js | 4 +- .../@react-spectrum/table/test/Table.test.js | 6 +- .../table/test/TableSizing.test.tsx | 14 +-- .../@react-spectrum/test-utils/src/events.ts | 67 +------------- .../@react-spectrum/test-utils/src/index.ts | 1 + .../test-utils/src/testSetup.ts | 92 +++++++++++++++++++ 15 files changed, 140 insertions(+), 106 deletions(-) create mode 100644 packages/@react-spectrum/test-utils/src/testSetup.ts diff --git a/packages/@react-aria/aria-modal-polyfill/test/index.test.tsx b/packages/@react-aria/aria-modal-polyfill/test/index.test.tsx index 009a8d60c64..8aa48d403a9 100644 --- a/packages/@react-aria/aria-modal-polyfill/test/index.test.tsx +++ b/packages/@react-aria/aria-modal-polyfill/test/index.test.tsx @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, render, triggerPress, waitFor} from '@react-spectrum/test-utils'; +import {act, fireEvent, render, simulateMobile, triggerPress, waitFor} from '@react-spectrum/test-utils'; import {ActionButton, Button} from '@react-spectrum/button'; import {Content} from '@react-spectrum/view'; import {Dialog, DialogTrigger} from '@react-spectrum/dialog'; @@ -215,7 +215,7 @@ describe('watchModals', () => { ]} ]; // menu should be a tray - jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => 700); + simulateMobile(); watchModals(); let {getByLabelText, getByRole, queryByRole} = render( <> diff --git a/packages/@react-aria/selection/test/useSelectableCollection.test.js b/packages/@react-aria/selection/test/useSelectableCollection.test.js index 12746652012..fcfaac77e3f 100644 --- a/packages/@react-aria/selection/test/useSelectableCollection.test.js +++ b/packages/@react-aria/selection/test/useSelectableCollection.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {fireEvent, installPointerEvent, pointerMap, render} from '@react-spectrum/test-utils'; +import {fireEvent, installPointerEvent, pointerMap, render, simulateDesktop, simulateMobile} from '@react-spectrum/test-utils'; import {Item} from '@react-stately/collections'; import {List} from '../stories/List'; import React from 'react'; @@ -24,7 +24,7 @@ describe('useSelectableCollection', () => { }); beforeEach(() => { - jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => 750); + simulateDesktop(750); }); it('selects the first item it focuses if selectOnFocus', async () => { @@ -89,7 +89,7 @@ describe('useSelectableCollection', () => { `('always uses toggle for $type', ({prepare, actions: [start, end]}) => { prepare(); it('uses toggle mode when the interaction is touch', () => { - jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => 700); + simulateMobile(700); let {getAllByRole} = render( Paco de Lucia diff --git a/packages/@react-spectrum/autocomplete/test/SearchAutocomplete.test.js b/packages/@react-spectrum/autocomplete/test/SearchAutocomplete.test.js index b7b3ee49ebb..fe4e7578b8e 100644 --- a/packages/@react-spectrum/autocomplete/test/SearchAutocomplete.test.js +++ b/packages/@react-spectrum/autocomplete/test/SearchAutocomplete.test.js @@ -11,7 +11,7 @@ */ jest.mock('@react-aria/live-announcer'); -import {act, fireEvent, pointerMap, render, screen, triggerPress, waitFor, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, screen, simulateDesktop, simulateMobile, triggerPress, waitFor, within} from '@react-spectrum/test-utils'; import {announce} from '@react-aria/live-announcer'; import {Button} from '@react-spectrum/button'; import Filter from '@spectrum-icons/workflow/Filter'; @@ -146,7 +146,7 @@ describe('SearchAutocomplete', function () { jest.spyOn(window.HTMLElement.prototype, 'clientWidth', 'get').mockImplementation(() => 1000); jest.spyOn(window.HTMLElement.prototype, 'clientHeight', 'get').mockImplementation(() => 1000); window.HTMLElement.prototype.scrollIntoView = jest.fn(); - jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => 1024); + simulateDesktop(); jest.useFakeTimers(); }); @@ -1533,7 +1533,7 @@ describe('SearchAutocomplete', function () { describe('mobile searchAutocomplete', function () { beforeEach(() => { - jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => 700); + simulateMobile(); }); afterEach(() => { @@ -2447,7 +2447,7 @@ describe('SearchAutocomplete', function () { describe('forms', () => { describe('desktop', () => { beforeAll(function () { - jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => 1024); + simulateDesktop(); }); afterAll(function () { @@ -2732,7 +2732,7 @@ describe('SearchAutocomplete', function () { describe('mobile', () => { beforeEach(() => { - jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => 700); + simulateMobile(); }); afterEach(() => { @@ -2985,7 +2985,7 @@ describe('SearchAutocomplete', function () { describe('accessibility', function () { beforeAll(function () { - jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => 1024); + simulateDesktop(); }); afterAll(function () { diff --git a/packages/@react-spectrum/combobox/test/ComboBox.test.js b/packages/@react-spectrum/combobox/test/ComboBox.test.js index 139f61d7f40..6f83810d0b6 100644 --- a/packages/@react-spectrum/combobox/test/ComboBox.test.js +++ b/packages/@react-spectrum/combobox/test/ComboBox.test.js @@ -11,7 +11,7 @@ */ jest.mock('@react-aria/live-announcer'); -import {act, fireEvent, pointerMap, render, screen, triggerPress, waitFor, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, screen, simulateDesktop, simulateMobile, triggerPress, waitFor, within} from '@react-spectrum/test-utils'; import {announce} from '@react-aria/live-announcer'; import {Button} from '@react-spectrum/button'; import {chain} from '@react-aria/utils'; @@ -250,7 +250,7 @@ describe('ComboBox', function () { jest.spyOn(window.HTMLElement.prototype, 'clientWidth', 'get').mockImplementation(() => 1000); jest.spyOn(window.HTMLElement.prototype, 'clientHeight', 'get').mockImplementation(() => 1000); window.HTMLElement.prototype.scrollIntoView = jest.fn(); - jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => 1024); + simulateDesktop(); jest.useFakeTimers(); }); @@ -3728,7 +3728,7 @@ describe('ComboBox', function () { describe('mobile combobox', function () { beforeEach(() => { - jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => 700); + simulateMobile(); }); afterEach(() => { @@ -4844,7 +4844,7 @@ describe('ComboBox', function () { describe('accessibility', function () { beforeAll(function () { - jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => 1024); + simulateDesktop(); }); afterAll(function () { @@ -5311,7 +5311,7 @@ describe('ComboBox', function () { describe('forms', () => { describe('desktop', () => { beforeAll(function () { - jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => 1024); + simulateDesktop(); }); afterAll(function () { @@ -5610,7 +5610,7 @@ describe('ComboBox', function () { describe('mobile', () => { beforeEach(() => { - jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => 700); + simulateMobile(); }); afterEach(() => { @@ -5874,7 +5874,7 @@ describe('ComboBox', function () { describe('links', () => { beforeAll(function () { - jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => 1024); + simulateDesktop(); }); afterAll(function () { diff --git a/packages/@react-spectrum/contextualhelp/test/ContextualHelp.test.js b/packages/@react-spectrum/contextualhelp/test/ContextualHelp.test.js index 5bff20fa98c..2a622f3cb73 100644 --- a/packages/@react-spectrum/contextualhelp/test/ContextualHelp.test.js +++ b/packages/@react-spectrum/contextualhelp/test/ContextualHelp.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, render, triggerPress} from '@react-spectrum/test-utils'; +import {act, render, simulateDesktop, triggerPress} from '@react-spectrum/test-utils'; import {Content, Footer, Header} from '@react-spectrum/view'; import {ContextualHelp} from '../'; import {Link} from '@react-spectrum/link'; @@ -21,7 +21,7 @@ import {theme} from '@react-spectrum/theme-default'; describe('ContextualHelp', function () { beforeAll(() => { jest.useFakeTimers(); - jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => 1024); + simulateDesktop(); }); afterAll(() => { jest.clearAllMocks(); diff --git a/packages/@react-spectrum/datepicker/test/DatePickerBase.test.js b/packages/@react-spectrum/datepicker/test/DatePickerBase.test.js index 105a0b85f6e..5543810eb74 100644 --- a/packages/@react-spectrum/datepicker/test/DatePickerBase.test.js +++ b/packages/@react-spectrum/datepicker/test/DatePickerBase.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, installPointerEvent, render as render_, triggerPress, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, installPointerEvent, render as render_, simulateDesktop, triggerPress, within} from '@react-spectrum/test-utils'; import {CalendarDate, parseZonedDateTime} from '@internationalized/date'; import {DatePicker, DateRangePicker} from '../'; import {Provider} from '@react-spectrum/provider'; @@ -41,7 +41,7 @@ function render(el) { describe('DatePickerBase', function () { beforeAll(() => { - jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => 1024); + simulateDesktop(); }); afterAll(() => { diff --git a/packages/@react-spectrum/dialog/test/DialogTrigger.test.js b/packages/@react-spectrum/dialog/test/DialogTrigger.test.js index bf227249eb3..f4025d95ade 100644 --- a/packages/@react-spectrum/dialog/test/DialogTrigger.test.js +++ b/packages/@react-spectrum/dialog/test/DialogTrigger.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, triggerPress, waitFor, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, simulateDesktop, simulateMobile, triggerPress, waitFor, within} from '@react-spectrum/test-utils'; import {ActionButton, Button} from '@react-spectrum/button'; import {ButtonGroup} from '@react-spectrum/buttongroup'; import {Content} from '@react-spectrum/view'; @@ -26,7 +26,6 @@ import userEvent from '@testing-library/user-event'; describe('DialogTrigger', function () { let warnMock; - let windowSpy; let user; beforeAll(() => { @@ -35,7 +34,7 @@ describe('DialogTrigger', function () { }); beforeEach(() => { - windowSpy = jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => 1024); + simulateDesktop(); if (process.env.STRICT_MODE) { warnMock = jest.spyOn(global.console, 'warn').mockImplementation(); } @@ -179,7 +178,7 @@ describe('DialogTrigger', function () { }); it('should trigger a modal instead of a popover on mobile', function () { - windowSpy.mockImplementation(() => 700); + simulateMobile(); let {getByRole, queryByRole, getByTestId} = render( @@ -206,7 +205,7 @@ describe('DialogTrigger', function () { }); it('should trigger a tray instead of a popover on mobile if mobileType="tray"', function () { - windowSpy.mockImplementation(() => 700); + simulateMobile(); let {getByRole, queryByRole, getByTestId} = render( @@ -688,7 +687,7 @@ describe('DialogTrigger', function () { }); it('mobile type modals should be closable by clicking outside the modal', async function () { - windowSpy.mockImplementation(() => 700); + simulateMobile(); function Test({defaultOpen, onOpenChange}) { return ( diff --git a/packages/@react-spectrum/form/test/Form.test.js b/packages/@react-spectrum/form/test/Form.test.js index 6ac50212009..ad21ad4d8a2 100644 --- a/packages/@react-spectrum/form/test/Form.test.js +++ b/packages/@react-spectrum/form/test/Form.test.js @@ -16,7 +16,7 @@ import {Content, Header} from '@react-spectrum/view'; import {ContextualHelp} from '@react-spectrum/contextualhelp'; import {Form} from '../'; import {Item, Picker} from '@react-spectrum/picker'; -import {pointerMap, render, triggerPress} from '@react-spectrum/test-utils'; +import {pointerMap, render, simulateMobile, triggerPress} from '@react-spectrum/test-utils'; import {Provider} from '@react-spectrum/provider'; import React from 'react'; import {TextField} from '@react-spectrum/textfield'; @@ -30,7 +30,7 @@ describe('Form', function () { beforeAll(() => { user = userEvent.setup({delay: null, pointerMap}); jest.useFakeTimers(); - jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => 700); + simulateMobile(); }); afterAll(() => { diff --git a/packages/@react-spectrum/menu/test/MenuTrigger.test.js b/packages/@react-spectrum/menu/test/MenuTrigger.test.js index c88860f81e0..6659d2b17bd 100644 --- a/packages/@react-spectrum/menu/test/MenuTrigger.test.js +++ b/packages/@react-spectrum/menu/test/MenuTrigger.test.js @@ -19,6 +19,7 @@ import { DEFAULT_LONG_PRESS_TIME, installPointerEvent, pointerMap, + simulateDesktop, triggerLongPress, triggerPress, triggerTouch @@ -76,7 +77,7 @@ describe('MenuTrigger', function () { offsetWidth = jest.spyOn(window.HTMLElement.prototype, 'offsetWidth', 'get').mockImplementation(() => 1000); offsetHeight = jest.spyOn(window.HTMLElement.prototype, 'offsetHeight', 'get').mockImplementation(() => 1000); window.HTMLElement.prototype.scrollIntoView = jest.fn(); - jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => 1024); + simulateDesktop(); jest.useFakeTimers(); }); diff --git a/packages/@react-spectrum/picker/test/Picker.test.js b/packages/@react-spectrum/picker/test/Picker.test.js index 8735a20a210..acfe90e4283 100644 --- a/packages/@react-spectrum/picker/test/Picker.test.js +++ b/packages/@react-spectrum/picker/test/Picker.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, triggerPress, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, simulateDesktop, triggerPress, within} from '@react-spectrum/test-utils'; import AlignCenter from '@spectrum-icons/workflow/AlignCenter'; import AlignLeft from '@spectrum-icons/workflow/AlignLeft'; import AlignRight from '@spectrum-icons/workflow/AlignRight'; @@ -38,7 +38,7 @@ describe('Picker', function () { offsetWidth = jest.spyOn(window.HTMLElement.prototype, 'clientWidth', 'get').mockImplementation(() => 1000); offsetHeight = jest.spyOn(window.HTMLElement.prototype, 'clientHeight', 'get').mockImplementation(() => 1000); window.HTMLElement.prototype.scrollIntoView = jest.fn(); - jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => 1024); + simulateDesktop(); jest.useFakeTimers(); }); diff --git a/packages/@react-spectrum/table/test/Table.test.js b/packages/@react-spectrum/table/test/Table.test.js index 9eb4e2497d0..5f07aede145 100644 --- a/packages/@react-spectrum/table/test/Table.test.js +++ b/packages/@react-spectrum/table/test/Table.test.js @@ -159,9 +159,9 @@ export let tableTests = () => { let render = (children, scale = 'medium') => { let tree = renderComponent( - // + {children} - // + ); // account for table column resizing to do initial pass due to relayout from useTableColumnResizeState render act(() => {jest.runAllTimers();}); @@ -191,7 +191,7 @@ export let tableTests = () => { let focusCell = (tree, text) => act(() => getCell(tree, text).focus()); let moveFocus = (key, opts = {}) => {fireEvent.keyDown(document.activeElement, {key, ...opts});}; - it.only('renders a static table', function () { + it('renders a static table', function () { let {getByRole} = render( diff --git a/packages/@react-spectrum/table/test/TableSizing.test.tsx b/packages/@react-spectrum/table/test/TableSizing.test.tsx index 7dadf2f0ee7..e1ec78668de 100644 --- a/packages/@react-spectrum/table/test/TableSizing.test.tsx +++ b/packages/@react-spectrum/table/test/TableSizing.test.tsx @@ -17,7 +17,7 @@ import Add from '@spectrum-icons/workflow/Add'; import {Cell, Column, Row, TableBody, TableHeader, TableView} from '../'; import {ColumnSize} from '@react-types/table'; import {ControllingResize} from '../stories/ControllingResize'; -import {fireEvent, installPointerEvent, pointerMap, triggerTouch} from '@react-spectrum/test-utils'; +import {fireEvent, installPointerEvent, pointerMap, simulateDesktop, triggerTouch} from '@react-spectrum/test-utils'; import {HidingColumns} from '../stories/HidingColumns'; import {Key} from '@react-types/shared'; import {Provider} from '@react-spectrum/provider'; @@ -705,7 +705,7 @@ describe('TableViewSizing', function () { installPointerEvent(); it('dragging the resizer works - desktop', () => { - jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => 1024); + simulateDesktop(); let onResizeEnd = jest.fn(); let tree = render( @@ -859,7 +859,7 @@ describe('TableViewSizing', function () { it('dragging the resizer works - desktop', () => { setInteractionModality('pointer'); - jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => 1024); + simulateDesktop(); let onResizeEnd = jest.fn(); let tree = render( @@ -1030,7 +1030,7 @@ describe('TableViewSizing', function () { describe('keyboard', () => { it('arrow keys the resizer works - desktop', async () => { - jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => 1024); + simulateDesktop(); let onResizeEnd = jest.fn(); let tree = render( @@ -1218,7 +1218,7 @@ describe('TableViewSizing', function () { expect(tree.queryByRole('slider')).toBeNull(); }); it('can exit resize via Enter', async () => { - jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => 1024); + simulateDesktop(); let onResizeEnd = jest.fn(); let tree = render( @@ -1268,7 +1268,7 @@ describe('TableViewSizing', function () { expect(tree.queryByRole('slider')).toBeNull(); }); it('can exit resize via Tab', async () => { - jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => 1024); + simulateDesktop(); let onResizeEnd = jest.fn(); let tree = render( @@ -1318,7 +1318,7 @@ describe('TableViewSizing', function () { expect(tree.queryByRole('slider')).toBeNull(); }); it('can exit resize via shift Tab', async () => { - jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => 1024); + simulateDesktop(); let onResizeEnd = jest.fn(); let tree = render( diff --git a/packages/@react-spectrum/test-utils/src/events.ts b/packages/@react-spectrum/test-utils/src/events.ts index e0d9de3e084..f5c0dc74277 100644 --- a/packages/@react-spectrum/test-utils/src/events.ts +++ b/packages/@react-spectrum/test-utils/src/events.ts @@ -13,6 +13,7 @@ import {act, fireEvent} from '@testing-library/react'; import userEvent from '@testing-library/user-event'; +// TODO: try to get rid of this in favor of user event // Triggers a "press" event on an element. // TODO: move to somewhere more common export function triggerPress(element, opts = {}) { @@ -21,12 +22,14 @@ export function triggerPress(element, opts = {}) { fireEvent.click(element, {detail: 1, ...opts}); } +// TODO: try to get rid of this in favor of user event // Triggers a "touch" event on an element. export function triggerTouch(element, opts = {}) { fireEvent.pointerDown(element, {pointerType: 'touch', ...opts}); fireEvent.pointerUp(element, {pointerType: 'touch', ...opts}); } +// TODO: expose from aria testing package, and re-export from this package? // Triggers a "longPress" event on an element. export const DEFAULT_LONG_PRESS_TIME = 500; @@ -38,70 +41,8 @@ export function triggerLongPress(element, opts = {}) { fireEvent.pointerUp(element, {pointerType: 'touch', ...opts}); } -/** - * Enables reading pageX/pageY from fireEvent.mouse*(..., {pageX: ..., pageY: ...}). - */ -export function installMouseEvent() { - beforeAll(() => { - let oldMouseEvent = MouseEvent; - // @ts-ignore - global.MouseEvent = class FakeMouseEvent extends MouseEvent { - _init: {pageX: number, pageY: number}; - constructor(name, init) { - super(name, init); - this._init = init; - } - get pageX() { - return this._init.pageX; - } - get pageY() { - return this._init.pageY; - } - }; - // @ts-ignore - global.MouseEvent.oldMouseEvent = oldMouseEvent; - }); - afterAll(() => { - // @ts-ignore - global.MouseEvent = global.MouseEvent.oldMouseEvent; - }); -} - -export function installPointerEvent() { - beforeAll(() => { - // @ts-ignore - global.PointerEvent = class FakePointerEvent extends MouseEvent { - _init: {pageX: number, pageY: number, pointerType: string, pointerId: number, width: number, height: number}; - constructor(name, init) { - super(name, init); - this._init = init; - } - get pointerType() { - return this._init.pointerType ?? 'mouse'; - } - get pointerId() { - return this._init.pointerId; - } - get pageX() { - return this._init.pageX; - } - get pageY() { - return this._init.pageY; - } - get width() { - return this._init.width; - } - get height() { - return this._init.height; - } - }; - }); - afterAll(() => { - // @ts-ignore - delete global.PointerEvent; - }); -} +// TODO: expose from aria testing package, and re-export from this package? /** * Must **not** be called inside an `act` callback! * diff --git a/packages/@react-spectrum/test-utils/src/index.ts b/packages/@react-spectrum/test-utils/src/index.ts index 19010e66919..d80813ced6c 100644 --- a/packages/@react-spectrum/test-utils/src/index.ts +++ b/packages/@react-spectrum/test-utils/src/index.ts @@ -13,6 +13,7 @@ /// export * from './events'; +export * from './testSetup'; export * from './testSSR'; export * from './renderOverride'; export * from './StrictModeWrapper'; diff --git a/packages/@react-spectrum/test-utils/src/testSetup.ts b/packages/@react-spectrum/test-utils/src/testSetup.ts new file mode 100644 index 00000000000..cb932491472 --- /dev/null +++ b/packages/@react-spectrum/test-utils/src/testSetup.ts @@ -0,0 +1,92 @@ +/* + * Copyright 2023 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +/** + * Mocks screen width to simulate mobile experience, useful for testing Tray rendering. + * @param width Optional width to apply. Automatically clamped to the maximum value allowed for mobile rendering. + */ +export function simulateMobile(width: number = 700) { + jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => Math.min(Math.max(width, 0), 700)); +} + +/** + * Mocks screen width to simulate standard desktop experience. + * @param width Optional width to apply. Automatically clamped to the minimum value allowed for desktop rendering. + */ +export function simulateDesktop(width: number = 701) { + jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => Math.max(width, 701)); +} + +// TODO: move to aria test util package +/** + * Enables reading pageX/pageY from fireEvent.mouse*(..., {pageX: ..., pageY: ...}). + */ +export function installMouseEvent() { + beforeAll(() => { + let oldMouseEvent = MouseEvent; + // @ts-ignore + global.MouseEvent = class FakeMouseEvent extends MouseEvent { + _init: {pageX: number, pageY: number}; + constructor(name, init) { + super(name, init); + this._init = init; + } + get pageX() { + return this._init.pageX; + } + get pageY() { + return this._init.pageY; + } + }; + // @ts-ignore + global.MouseEvent.oldMouseEvent = oldMouseEvent; + }); + afterAll(() => { + // @ts-ignore + global.MouseEvent = global.MouseEvent.oldMouseEvent; + }); +} + +export function installPointerEvent() { + beforeAll(() => { + // @ts-ignore + global.PointerEvent = class FakePointerEvent extends MouseEvent { + _init: {pageX: number, pageY: number, pointerType: string, pointerId: number, width: number, height: number}; + constructor(name, init) { + super(name, init); + this._init = init; + } + get pointerType() { + return this._init.pointerType ?? 'mouse'; + } + get pointerId() { + return this._init.pointerId; + } + get pageX() { + return this._init.pageX; + } + get pageY() { + return this._init.pageY; + } + get width() { + return this._init.width; + } + get height() { + return this._init.height; + } + }; + }); + afterAll(() => { + // @ts-ignore + delete global.PointerEvent; + }); +} From 8d022686d932f6f4cfe34ffd0dc9bb61f6454098 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Thu, 30 Nov 2023 17:59:16 -0800 Subject: [PATCH 06/31] starting to remove triggerPress in favor of user event library click --- .../aria-modal-polyfill/test/index.test.tsx | 31 +- .../actionbar/test/ActionBar.test.js | 32 +- .../actiongroup/test/ActionGroup.test.js | 102 +++--- .../test/SearchAutocomplete.test.js | 111 +++--- .../breadcrumbs/test/BreadcrumbItem.test.js | 13 +- .../breadcrumbs/test/Breadcrumbs.test.js | 33 +- .../button/test/ActionButton.test.js | 8 +- .../button/test/Button.test.js | 24 +- .../button/test/ClearButton.test.js | 8 +- .../button/test/ToggleButton.test.js | 18 +- .../buttongroup/test/ButtonGroup.test.js | 21 +- .../calendar/test/Calendar.test.js | 51 +-- .../calendar/test/CalendarBase.test.js | 20 +- .../card/test/CardView.test.js | 122 +++---- .../combobox/test/ComboBox.test.js | 335 +++++++++--------- 15 files changed, 474 insertions(+), 455 deletions(-) diff --git a/packages/@react-aria/aria-modal-polyfill/test/index.test.tsx b/packages/@react-aria/aria-modal-polyfill/test/index.test.tsx index 8aa48d403a9..c406e55be10 100644 --- a/packages/@react-aria/aria-modal-polyfill/test/index.test.tsx +++ b/packages/@react-aria/aria-modal-polyfill/test/index.test.tsx @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, render, simulateMobile, triggerPress, waitFor} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, simulateMobile, waitFor} from '@react-spectrum/test-utils'; import {ActionButton, Button} from '@react-spectrum/button'; import {Content} from '@react-spectrum/view'; import {Dialog, DialogTrigger} from '@react-spectrum/dialog'; @@ -18,10 +18,14 @@ import {Item, Menu, MenuTrigger, Section} from '@react-spectrum/menu'; import {Provider} from '@react-spectrum/provider'; import React from 'react'; import {theme} from '@react-spectrum/theme-default'; +import userEvent from '@testing-library/user-event'; import {watchModals} from '../'; describe('watchModals', () => { + let user; + beforeAll(() => { + user = userEvent.setup({delay: null, pointerMap}); jest.useFakeTimers(); }); @@ -73,9 +77,7 @@ describe('watchModals', () => { ); expect(getByRole('separator')).toBeVisible(); - act(() => { - triggerPress(getByLabelText('Trigger')); - }); + await user.click(getByLabelText('Trigger')); act(() => { jest.runAllTimers(); }); @@ -106,9 +108,7 @@ describe('watchModals', () => { ); // expect just the button labeled Trigger, and open the first dialog expect(getByRole('separator')).toBeVisible(); - act(() => { - triggerPress(getByLabelText('Trigger')); - }); + await user.click(getByLabelText('Trigger')); act(() => { jest.runAllTimers(); }); @@ -123,9 +123,7 @@ describe('watchModals', () => { let buttons = getAllByRole('button'); expect(buttons.length).toBe(1); expect(buttons[0]).toBe(getByLabelText('Nested Trigger')); - act(() => { - triggerPress(getByLabelText('Nested Trigger')); - }); + await user.click(getByLabelText('Nested Trigger')); act(() => { jest.runAllTimers(); }); @@ -196,9 +194,8 @@ describe('watchModals', () => { ); expect(getByRole('separator')).toBeVisible(); - act(() => { - triggerPress(getByLabelText('Trigger')); - }); + await user.click(getByLabelText('Trigger')); + act(() => { jest.runAllTimers(); }); @@ -235,9 +232,7 @@ describe('watchModals', () => { ); expect(getByRole('separator')).toBeVisible(); - act(() => { - triggerPress(getByLabelText('Trigger')); - }); + await user.click(getByLabelText('Trigger')); act(() => { jest.runAllTimers(); }); @@ -259,9 +254,7 @@ describe('watchModals', () => { ); expect(getByRole('separator')).toBeVisible(); - act(() => { - triggerPress(getByLabelText('Trigger')); - }); + await user.click(getByLabelText('Trigger')); act(() => { jest.runAllTimers(); }); diff --git a/packages/@react-spectrum/actionbar/test/ActionBar.test.js b/packages/@react-spectrum/actionbar/test/ActionBar.test.js index 04cd3a056a7..1d979954785 100644 --- a/packages/@react-spectrum/actionbar/test/ActionBar.test.js +++ b/packages/@react-spectrum/actionbar/test/ActionBar.test.js @@ -12,7 +12,7 @@ jest.mock('@react-aria/live-announcer'); -import {act, fireEvent, pointerMap, render, triggerPress, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; import {announce} from '@react-aria/live-announcer'; import {Example} from '../stories/Example'; import {getFocusableTreeWalker} from '@react-aria/focus'; @@ -34,7 +34,7 @@ describe('ActionBar', () => { act(() => jest.runAllTimers()); }); - it('should open when there are selected items', () => { + it('should open when there are selected items', async () => { let tree = render(); act(() => {jest.runAllTimers();}); @@ -42,7 +42,7 @@ describe('ActionBar', () => { let rows = within(table).getAllByRole('row'); expect(tree.queryByRole('toolbar')).toBeNull(); - triggerPress(rows[1]); + await user.click(rows[1]); expect(announce).toHaveBeenCalledWith('Actions available.'); @@ -58,32 +58,32 @@ describe('ActionBar', () => { expect(clearButton.tagName).toBe('BUTTON'); }); - it('should update the selected count when selecting more items', () => { + it('should update the selected count when selecting more items', async () => { let tree = render(); act(() => {jest.runAllTimers();}); let table = tree.getByRole('grid'); let rows = within(table).getAllByRole('row'); - triggerPress(rows[1]); + await user.click(rows[1]); let selectedCount = tree.getByText('1 selected'); - triggerPress(rows[2]); + await user.click(rows[2]); expect(selectedCount).toHaveTextContent('2 selected'); }); - it('should work with select all', () => { + it('should work with select all', async () => { let tree = render(); act(() => {jest.runAllTimers();}); let selectAll = tree.getByLabelText('Select All'); - triggerPress(selectAll); + await user.click(selectAll); expect(tree.getByText('All selected')).toBeInTheDocument(); }); - it('should close and restore focus when pressing the clear button', () => { + it('should close and restore focus when pressing the clear button', async () => { let tree = render(); act(() => {jest.runAllTimers();}); @@ -91,14 +91,14 @@ describe('ActionBar', () => { let rows = within(table).getAllByRole('row'); let checkbox = within(rows[1]).getByRole('checkbox'); - triggerPress(checkbox); + await user.click(checkbox); act(() => jest.runAllTimers()); expect(document.activeElement).toBe(checkbox); let clearButton = tree.getByLabelText('Clear selection'); act(() => clearButton.focus()); - triggerPress(clearButton); + await user.click(clearButton); act(() => jest.runAllTimers()); act(() => jest.runAllTimers()); @@ -106,7 +106,7 @@ describe('ActionBar', () => { expect(document.activeElement).toBe(checkbox); }); - it('should close when pressing the escape key', () => { + it('should close when pressing the escape key', async () => { let tree = render(); act(() => {jest.runAllTimers();}); @@ -114,7 +114,7 @@ describe('ActionBar', () => { let rows = within(table).getAllByRole('row'); let checkbox = within(rows[1]).getByRole('checkbox'); - triggerPress(checkbox); + await user.click(checkbox); act(() => jest.runAllTimers()); expect(document.activeElement).toBe(checkbox); @@ -281,7 +281,7 @@ describe('ActionBar', () => { expect(document.activeElement).toBe(rows[1]); }); - it('should fire onAction when clicking on an action', () => { + it('should fire onAction when clicking on an action', async () => { let onAction = jest.fn(); let tree = render(); act(() => {jest.runAllTimers();}); @@ -289,10 +289,10 @@ describe('ActionBar', () => { let table = tree.getByRole('grid'); let rows = within(table).getAllByRole('row'); - triggerPress(rows[1]); + await user.click(rows[1]); let toolbar = tree.getByRole('toolbar'); - triggerPress(within(toolbar).getAllByRole('button')[0]); + await user.click(within(toolbar).getAllByRole('button')[0]); expect(onAction).toHaveBeenCalledWith('edit'); }); diff --git a/packages/@react-spectrum/actiongroup/test/ActionGroup.test.js b/packages/@react-spectrum/actiongroup/test/ActionGroup.test.js index c874af3d3f6..860cc019ae4 100644 --- a/packages/@react-spectrum/actiongroup/test/ActionGroup.test.js +++ b/packages/@react-spectrum/actiongroup/test/ActionGroup.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, screen, triggerPress, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, screen, within} from '@react-spectrum/test-utils'; import {ActionGroup} from '../'; import {Button} from '@react-spectrum/button'; import {Dialog, DialogTrigger} from '@react-spectrum/dialog'; @@ -316,36 +316,36 @@ describe('ActionGroup', function () { expect(document.activeElement).toBe(buttons[1]); }); - it('ActionGroup handles single selection', function () { + it('ActionGroup handles single selection', async function () { let {getAllByRole} = renderComponent({selectionMode: 'single'}); let [button1, button2] = getAllByRole('radio'); - triggerPress(button1); + await user.click(button1); expect(button1).toHaveAttribute('aria-checked', 'true'); - triggerPress(button2); + await user.click(button2); expect(button1).toHaveAttribute('aria-checked', 'false'); expect(button2).toHaveAttribute('aria-checked', 'true'); }); - it('ActionGroup handles multiple selection', function () { + it('ActionGroup handles multiple selection', async function () { let {getByRole, getAllByRole} = renderComponent({selectionMode: 'multiple'}); expect(getByRole('toolbar')).toBeTruthy(); let [button1, button2] = getAllByRole('checkbox'); - triggerPress(button1); + await user.click(button1); expect(button1).toHaveAttribute('aria-checked', 'true'); - triggerPress(button2); + await user.click(button2); expect(button1).toHaveAttribute('aria-checked', 'true'); expect(button2).toHaveAttribute('aria-checked', 'true'); }); - it('ActionGroup should not allow selecting all items with cmd + a', function () { + it('ActionGroup should not allow selecting all items with cmd + a', async function () { let {getAllByRole} = renderComponent({selectionMode: 'multiple'}); let [button1, button2] = getAllByRole('checkbox'); - triggerPress(button1); + await user.click(button1); expect(button1).toHaveAttribute('aria-checked', 'true'); expect(button2).toHaveAttribute('aria-checked', 'false'); @@ -354,7 +354,7 @@ describe('ActionGroup', function () { expect(button2).toHaveAttribute('aria-checked', 'false'); }); - it('ActionGroup handles none selection', function () { + it('ActionGroup handles none selection', async function () { let {getByRole} = render( @@ -364,7 +364,7 @@ describe('ActionGroup', function () { ); let button1 = getByRole('button'); - triggerPress(button1); + await user.click(button1); expect(button1).not.toHaveAttribute('aria-checked'); }); @@ -386,54 +386,54 @@ describe('ActionGroup', function () { expect(button1).toHaveAttribute('tabIndex', '0'); }); - it('ActionGroup handles disabledKeys', function () { + it('ActionGroup handles disabledKeys', async function () { let onSelectionChange = jest.fn(); let {getAllByRole} = renderComponent({selectionMode: 'single', disabledKeys: ['1'], onSelectionChange}); let [button1, button2] = getAllByRole('radio'); - triggerPress(button1); + await user.click(button1); expect(button1).toHaveAttribute('disabled'); expect(onSelectionChange).toBeCalledTimes(0); - triggerPress(button2); + await user.click(button2); expect(button2).not.toHaveAttribute('disabled'); expect(onSelectionChange).toBeCalledTimes(1); }); - it('ActionGroup handles selectedKeys (controlled)', function () { + it('ActionGroup handles selectedKeys (controlled)', async function () { let onSelectionChange = jest.fn(); let {getAllByRole} = renderComponent({selectionMode: 'single', selectedKeys: ['1'], onSelectionChange}); let [button1, button2] = getAllByRole('radio'); expect(button1).toHaveAttribute('aria-checked', 'true'); expect(button2).toHaveAttribute('aria-checked', 'false'); - triggerPress(button2); + await user.click(button2); expect(onSelectionChange).toBeCalledTimes(1); expect(button1).toHaveAttribute('aria-checked', 'true'); expect(button2).toHaveAttribute('aria-checked', 'false'); }); - it('ActionGroup handles selectedKeys (uncontrolled)', function () { + it('ActionGroup handles selectedKeys (uncontrolled)', async function () { let onSelectionChange = jest.fn(); let {getAllByRole} = renderComponent({selectionMode: 'single', defaultSelectedKeys: ['1'], onSelectionChange}); let [button1, button2] = getAllByRole('radio'); expect(button1).toHaveAttribute('aria-checked', 'true'); expect(button2).toHaveAttribute('aria-checked', 'false'); - triggerPress(button2); + await user.click(button2); expect(onSelectionChange).toBeCalledTimes(1); expect(button1).toHaveAttribute('aria-checked', 'false'); expect(button2).toHaveAttribute('aria-checked', 'true'); }); - it('ActionGroup deselects the selected button', function () { + it('ActionGroup deselects the selected button', async function () { let onSelectionChange = jest.fn(); let {getAllByRole} = renderComponent({selectionMode: 'single', onSelectionChange}); let [button1] = getAllByRole('radio'); - triggerPress(button1); + await user.click(button1); expect(onSelectionChange).toBeCalledTimes(1); expect(new Set(onSelectionChange.mock.calls[0][0])).toEqual(new Set(['1'])); - triggerPress(button1); + await user.click(button1); expect(onSelectionChange).toBeCalledTimes(2); expect(new Set(onSelectionChange.mock.calls[1][0])).toEqual(new Set([])); }); @@ -518,7 +518,7 @@ describe('ActionGroup', function () { expect(item).toHaveAttribute('data-testid', 'test'); }); - it('fires onAction when a button is pressed', function () { + it('fires onAction when a button is pressed', async function () { let onAction = jest.fn(); let tree = render( @@ -529,13 +529,13 @@ describe('ActionGroup', function () { ); let button = tree.getByRole('button'); - triggerPress(button); + await user.click(button); expect(onAction).toHaveBeenCalledTimes(1); expect(onAction).toHaveBeenCalledWith('test'); }); - it('does not fire onAction if the action group is disabled', function () { + it('does not fire onAction if the action group is disabled', async function () { let onAction = jest.fn(); let tree = render( @@ -546,12 +546,12 @@ describe('ActionGroup', function () { ); let button = tree.getByRole('button'); - triggerPress(button); + await user.click(button); expect(onAction).not.toHaveBeenCalled(); }); - it('does not fire onAction if the item is disabled', function () { + it('does not fire onAction if the item is disabled', async function () { let onAction = jest.fn(); let tree = render( @@ -562,12 +562,12 @@ describe('ActionGroup', function () { ); let button = tree.getByRole('button'); - triggerPress(button); + await user.click(button); expect(onAction).not.toHaveBeenCalled(); }); - it('supports DialogTrigger as a wrapper around items', function () { + it('supports DialogTrigger as a wrapper around items', async function () { let tree = render( @@ -583,7 +583,7 @@ describe('ActionGroup', function () { let button = tree.getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -702,7 +702,7 @@ describe('ActionGroup', function () { }); }); - it('collapses overflowing items into a menu', function () { + it('collapses overflowing items into a menu', async function () { let onAction = jest.fn(); let tree = render( @@ -723,7 +723,7 @@ describe('ActionGroup', function () { expect(buttons[1]).toHaveAttribute('aria-haspopup', 'true'); expect(buttons[1]).not.toHaveAttribute('aria-checked'); - triggerPress(buttons[1]); + await user.click(buttons[1]); let menu = tree.getByRole('menu'); let items = within(menu).getAllByRole('menuitem'); @@ -732,11 +732,11 @@ describe('ActionGroup', function () { expect(items[1]).toHaveTextContent('Three'); expect(items[2]).toHaveTextContent('Four'); - triggerPress(items[1]); + await user.click(items[1]); expect(onAction).toHaveBeenCalledWith('three'); }); - it('collapsed menu items can have DOM attributes passed to them', function () { + it('collapsed menu items can have DOM attributes passed to them', async function () { let onAction = jest.fn(); let tree = render( @@ -752,7 +752,7 @@ describe('ActionGroup', function () { let actiongroup = tree.getByRole('toolbar'); let buttons = within(actiongroup).getAllByRole('button'); - triggerPress(buttons[1]); + await user.click(buttons[1]); let menu = tree.getByRole('menu'); let items = within(menu).getAllByRole('menuitem'); @@ -822,7 +822,7 @@ describe('ActionGroup', function () { expect(buttons[2]).toHaveAttribute('tabIndex', '0'); }); - it('passes aria labeling props through to menu button if it is the only child', function () { + it('passes aria labeling props through to menu button if it is the only child', async function () { jest.spyOn(HTMLElement.prototype, 'getBoundingClientRect').mockImplementation(function () { if (this instanceof HTMLButtonElement) { return {width: 100, height: 0, top: 0, left: 0, bottom: 0, right: 0}; @@ -849,7 +849,7 @@ describe('ActionGroup', function () { expect(button).toHaveAttribute('aria-haspopup', 'true'); expect(button).not.toHaveAttribute('aria-checked'); - triggerPress(button); + await user.click(button); let menu = tree.getByRole('menu'); let items = within(menu).getAllByRole('menuitem'); @@ -859,11 +859,11 @@ describe('ActionGroup', function () { expect(items[2]).toHaveTextContent('Three'); expect(items[3]).toHaveTextContent('Four'); - triggerPress(items[1]); + await user.click(items[1]); expect(onAction).toHaveBeenCalledWith('two'); }); - it('collapses all items if selectionMode="single"', function () { + it('collapses all items if selectionMode="single"', async function () { let onSelectionChange = jest.fn(); let tree = render( @@ -883,7 +883,7 @@ describe('ActionGroup', function () { expect(button).toHaveAttribute('aria-haspopup', 'true'); expect(button).not.toHaveAttribute('aria-checked'); - triggerPress(button); + await user.click(button); let menu = tree.getByRole('menu'); let items = within(menu).getAllByRole('menuitemradio'); @@ -894,11 +894,11 @@ describe('ActionGroup', function () { expect(items[2]).toHaveTextContent('Three'); expect(items[3]).toHaveTextContent('Four'); - triggerPress(items[2]); + await user.click(items[2]); expect(onSelectionChange).toHaveBeenCalledTimes(1); expect(new Set(onSelectionChange.mock.calls[0][0])).toEqual(new Set(['three'])); - triggerPress(button); + await user.click(button); menu = tree.getByRole('menu'); items = within(menu).getAllByRole('menuitemradio'); @@ -906,7 +906,7 @@ describe('ActionGroup', function () { expect(items[2]).toHaveAttribute('aria-checked', 'true'); }); - it('collapses all items if selectionMode="multiple"', function () { + it('collapses all items if selectionMode="multiple"', async function () { let onSelectionChange = jest.fn(); let tree = render( @@ -926,7 +926,7 @@ describe('ActionGroup', function () { expect(button).toHaveAttribute('aria-haspopup', 'true'); expect(button).not.toHaveAttribute('aria-checked'); - triggerPress(button); + await user.click(button); let menu = tree.getByRole('menu'); let items = within(menu).getAllByRole('menuitemcheckbox'); @@ -940,7 +940,7 @@ describe('ActionGroup', function () { expect(items[3]).toHaveTextContent('Four'); expect(items[3]).not.toHaveAttribute('aria-checked', 'true'); - triggerPress(items[3]); + await user.click(items[3]); expect(onSelectionChange).toHaveBeenCalledTimes(1); expect(new Set(onSelectionChange.mock.calls[0][0])).toEqual(new Set(['two', 'three', 'four'])); @@ -973,7 +973,7 @@ describe('ActionGroup', function () { expect(buttons[1]).toBeDisabled(); }); - it('menu items should be disabled for items listed in disabledKeys', function () { + it('menu items should be disabled for items listed in disabledKeys', async function () { const handleOnAction = jest.fn(); render( @@ -995,7 +995,7 @@ describe('ActionGroup', function () { expect(moreButton).not.toHaveAttribute('aria-checked'); expect(moreButton).toBeVisible(); - triggerPress(moreButton); + await user.click(moreButton); const menu = screen.getByRole('menu'); expect(within(menu).getAllByRole('menuitem')).toHaveLength(3); @@ -1012,13 +1012,13 @@ describe('ActionGroup', function () { expect(itemFour).toBeVisible(); expect(itemFour).toHaveAttribute('aria-disabled', 'true'); - triggerPress(itemTwo); + await user.click(itemTwo); expect(handleOnAction).not.toHaveBeenCalled(); - triggerPress(itemFour); + await user.click(itemFour); expect(handleOnAction).not.toHaveBeenCalled(); - triggerPress(itemThree); + await user.click(itemThree); expect(handleOnAction).toHaveBeenCalled(); }); }); @@ -1057,7 +1057,7 @@ describe('ActionGroup', function () { expect(buttons[0]).toHaveAttribute('aria-describedby', tooltip.id); }); - it('should show the text when collapsed into a dropdown', function () { + it('should show the text when collapsed into a dropdown', async function () { let tree = render( @@ -1081,7 +1081,7 @@ describe('ActionGroup', function () { let buttons = within(actiongroup).getAllByRole('button'); expect(buttons.length).toBe(2); - triggerPress(buttons[1]); + await user.click(buttons[1]); let menu = tree.getByRole('menu'); let items = within(menu).getAllByRole('menuitem'); diff --git a/packages/@react-spectrum/autocomplete/test/SearchAutocomplete.test.js b/packages/@react-spectrum/autocomplete/test/SearchAutocomplete.test.js index fe4e7578b8e..6564c3b1a99 100644 --- a/packages/@react-spectrum/autocomplete/test/SearchAutocomplete.test.js +++ b/packages/@react-spectrum/autocomplete/test/SearchAutocomplete.test.js @@ -11,7 +11,7 @@ */ jest.mock('@react-aria/live-announcer'); -import {act, fireEvent, pointerMap, render, screen, simulateDesktop, simulateMobile, triggerPress, waitFor, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, screen, simulateDesktop, simulateMobile, waitFor, within} from '@react-spectrum/test-utils'; import {announce} from '@react-aria/live-announcer'; import {Button} from '@react-spectrum/button'; import Filter from '@spectrum-icons/workflow/Filter'; @@ -675,7 +675,7 @@ describe('SearchAutocomplete', function () { let listbox = getByRole('listbox'); let items = within(listbox).getAllByRole('option'); - triggerPress(items[1]); + await user.click(items[1]); act(() => { jest.runAllTimers(); }); @@ -1174,7 +1174,7 @@ describe('SearchAutocomplete', function () { expect(items[1].textContent).toBe('Kangaroo'); expect(items[2].textContent).toBe('Snake'); - triggerPress(items[0]); + await user.click(items[0]); act(() => { jest.runAllTimers(); }); @@ -1260,7 +1260,7 @@ describe('SearchAutocomplete', function () { expect(items[1]).toHaveTextContent('Two'); expect(items[1]).not.toHaveAttribute('aria-selected', 'true'); - triggerPress(items[0]); + await user.click(items[0]); act(() => { jest.runAllTimers(); }); @@ -1607,11 +1607,11 @@ describe('SearchAutocomplete', function () { expect(button).toHaveAttribute('aria-labelledby', `${getByText('Test').id} label-id ${button.getElementsByTagName('span')[0].id}`); }); - it('readonly searchAutocomplete should not open on press', function () { + it('readonly searchAutocomplete should not open on press', async function () { let {getByRole, getByTestId} = renderSearchAutocomplete({isReadOnly: true}); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -1620,11 +1620,11 @@ describe('SearchAutocomplete', function () { expect(() => getByTestId('tray')).toThrow(); }); - it('opening the tray autofocuses the tray input', function () { + it('opening the tray autofocuses the tray input', async function () { let {getByRole, getByTestId} = renderSearchAutocomplete(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -1639,11 +1639,11 @@ describe('SearchAutocomplete', function () { testSearchAutocompleteTrayOpen(trayInput, tray, listbox); }); - it('closing the tray autofocuses the button', function () { + it('closing the tray autofocuses the button', async function () { let {getByRole, getByTestId} = renderSearchAutocomplete(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -1669,7 +1669,7 @@ describe('SearchAutocomplete', function () { let {getByRole, getByTestId} = renderSearchAutocomplete(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -1698,11 +1698,11 @@ describe('SearchAutocomplete', function () { expect(tray.getAttribute('style')).toBe(style); }); - it('up/down arrows still traverse the items in the tray', function () { + it('up/down arrows still traverse the items in the tray', async function () { let {getByRole, getByTestId} = renderSearchAutocomplete(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -1745,7 +1745,7 @@ describe('SearchAutocomplete', function () { let {getByRole, getByTestId} = renderSearchAutocomplete(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -1785,7 +1785,7 @@ describe('SearchAutocomplete', function () { let {getByRole, getByTestId} = renderSearchAutocomplete(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -1813,7 +1813,7 @@ describe('SearchAutocomplete', function () { let clearButton = within(tray).getByLabelText('Clear'); expect(clearButton.tagName).toBe('DIV'); expect(clearButton).not.toHaveAttribute('tabIndex'); - triggerPress(clearButton); + await user.click(clearButton); expect(onClear).toHaveBeenCalledTimes(1); act(() => { @@ -1828,7 +1828,7 @@ describe('SearchAutocomplete', function () { let {getByRole, getByTestId} = renderSearchAutocomplete(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -1867,11 +1867,11 @@ describe('SearchAutocomplete', function () { expect(() => within(tray).getByText('No results')).toThrow(); }); - it('user can select options by pressing them', function () { + it('user can select options by pressing them', async function () { let {getByRole, getByText, getByTestId} = renderSearchAutocomplete(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -1887,7 +1887,7 @@ describe('SearchAutocomplete', function () { let items = within(tray).getAllByRole('option'); - triggerPress(items[1]); + await user.click(items[1]); act(() => { jest.runAllTimers(); }); @@ -1899,7 +1899,7 @@ describe('SearchAutocomplete', function () { expect(() => getByTestId('tray')).toThrow(); expect(button).toHaveAttribute('aria-labelledby', `${getByText('Test').id} ${getByText('Two').id}`); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -1915,11 +1915,11 @@ describe('SearchAutocomplete', function () { expect(items[1]).toHaveAttribute('aria-selected', 'true'); }); - it('user can select options by focusing them and hitting enter', function () { + it('user can select options by focusing them and hitting enter', async function () { let {getByRole, getByText, getByTestId} = renderSearchAutocomplete(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -1954,7 +1954,7 @@ describe('SearchAutocomplete', function () { expect(() => getByTestId('tray')).toThrow(); expect(button).toHaveAttribute('aria-labelledby', `${getByText('Test').id} ${getByText('Three').id}`); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -1970,11 +1970,11 @@ describe('SearchAutocomplete', function () { expect(items[2]).toHaveAttribute('aria-selected', 'true'); }); - it('input is blurred when the user scrolls the listbox with touch', function () { + it('input is blurred when the user scrolls the listbox with touch', async function () { let {getByRole, getByTestId} = renderSearchAutocomplete(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -2003,14 +2003,14 @@ describe('SearchAutocomplete', function () { expect(document.activeElement).not.toBe(trayInput); }); - it('label of the tray input should match label of button', function () { + it('label of the tray input should match label of button', async function () { let {getByRole, getByTestId, getByText} = renderSearchAutocomplete(); let button = getByRole('button'); let label = getByText(defaultProps.label); expect(button).toHaveAttribute('aria-labelledby', `${label.id} ${button.getElementsByTagName('span')[0].id}`); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -2022,7 +2022,7 @@ describe('SearchAutocomplete', function () { expect(trayInput).toHaveAttribute('aria-labelledby', trayInputLabel.id); }); - it('tray input should recieve the same aria-labelledby as the button if an external label is provided', function () { + it('tray input should recieve the same aria-labelledby as the button if an external label is provided', async function () { let {getByRole, getByTestId, getByText} = render( @@ -2037,7 +2037,7 @@ describe('SearchAutocomplete', function () { expect(button).toHaveAttribute('aria-labelledby', `${label.id} ${button.getElementsByClassName('mobile-value')[0].id}`); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -2051,7 +2051,7 @@ describe('SearchAutocomplete', function () { expect(trayInput).toHaveAttribute('aria-labelledby', label.id); }); - it('user can open the tray even if there aren\'t any items to show', function () { + it('user can open the tray even if there aren\'t any items to show', async function () { let {getAllByRole, getByTestId} = render( @@ -2061,7 +2061,7 @@ describe('SearchAutocomplete', function () { ); let button = getAllByRole('button')[0]; - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -2076,11 +2076,11 @@ describe('SearchAutocomplete', function () { expect(placeholderText).toBeVisible(); }); - it('searchAutocomplete tray remains open on blur', function () { + it('searchAutocomplete tray remains open on blur', async function () { let {getAllByRole, getByTestId} = renderSearchAutocomplete({defaultInputValue: 'Blah'}); let button = getAllByRole('button')[0]; - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -2102,11 +2102,11 @@ describe('SearchAutocomplete', function () { expect(trayInput.value).toBe('Blah'); // does not reset on blur }); - it('searchAutocomplete tray can be closed using the dismiss buttons', function () { + it('searchAutocomplete tray can be closed using the dismiss buttons', async function () { let {getByRole, getByTestId} = renderSearchAutocomplete(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -2118,7 +2118,7 @@ describe('SearchAutocomplete', function () { expect(dismissButtons[0]).toHaveAttribute('aria-label', 'Dismiss'); expect(dismissButtons[1]).toHaveAttribute('aria-label', 'Dismiss'); - triggerPress(dismissButtons[0]); + await user.click(dismissButtons[0]); act(() => { jest.runAllTimers(); }); @@ -2126,11 +2126,11 @@ describe('SearchAutocomplete', function () { expect(() => getByTestId('tray')).toThrow(); }); - it('searchAutocomplete tray doesn\'t close when tray input is virtually clicked', function () { + it('searchAutocomplete tray doesn\'t close when tray input is virtually clicked', async function () { let {getByRole, getByTestId} = renderSearchAutocomplete(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -2179,7 +2179,7 @@ describe('SearchAutocomplete', function () { expect(button).toHaveAttribute('aria-labelledby', `${getByText('Test').id} ${button.getElementsByTagName('span')[0].id} ${getByLabelText('(invalid)').id}`); }); - it('menutrigger=focus doesn\'t reopen the tray on close', function () { + it('menutrigger=focus doesn\'t reopen the tray on close', async function () { let {getByRole, getByTestId} = renderSearchAutocomplete({menuTrigger: 'focus'}); let button = getByRole('button'); @@ -2193,7 +2193,7 @@ describe('SearchAutocomplete', function () { // menutrigger = focus is inapplicable for mobile SearchAutocomplete expect(() => getByTestId('tray')).toThrow(); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -2205,7 +2205,7 @@ describe('SearchAutocomplete', function () { act(() => { trayInput.blur(); }); - triggerPress(document.body); + await user.click(document.body); act(() => { jest.runAllTimers(); }); @@ -2219,15 +2219,15 @@ describe('SearchAutocomplete', function () { expect(document.activeElement).toBe(button); }); - it('searchAutocomplete tray doesn\'t open when controlled input value is updated', function () { + it('searchAutocomplete tray doesn\'t open when controlled input value is updated', async function () { let {getAllByRole, rerender, getByTestId} = render(); let button = getAllByRole('button')[0]; act(() => { button.focus(); - triggerPress(button); - jest.runAllTimers(); }); + await user.click(button); + act(() => jest.runAllTimers()); let tray = getByTestId('tray'); expect(tray).toBeVisible(); @@ -2236,7 +2236,7 @@ describe('SearchAutocomplete', function () { act(() => { trayInput.blur(); }); - triggerPress(document.body); + await user.click(document.body); act(() => { jest.runAllTimers(); }); @@ -2283,13 +2283,13 @@ describe('SearchAutocomplete', function () { }); describe('isLoading', function () { - it('tray input should render a loading circle after a delay of 500ms if loadingState="filtering"', function () { + it('tray input should render a loading circle after a delay of 500ms if loadingState="filtering"', async function () { let {getByRole, queryByRole, getByTestId, rerender} = render(); let button = getByRole('button'); act(() => {jest.advanceTimersByTime(500);}); expect(queryByRole('progressbar')).toBeNull(); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -2307,13 +2307,13 @@ describe('SearchAutocomplete', function () { expect(within(listbox).queryByRole('progressbar')).toBeNull(); }); - it('tray input should hide the loading circle if loadingState is no longer "filtering"', function () { + it('tray input should hide the loading circle if loadingState is no longer "filtering"', async function () { let {getByRole, queryByRole, getByTestId, rerender} = render(); let button = getByRole('button'); act(() => {jest.advanceTimersByTime(500);}); expect(queryByRole('progressbar')).toBeNull(); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -2331,9 +2331,8 @@ describe('SearchAutocomplete', function () { it('tray input loading circle timer should reset on input value change', async function () { let {getByRole, getByTestId, rerender} = render(); let button = getByRole('button'); - + await user.click(button); act(() => { - triggerPress(button); jest.runAllTimers(); }); @@ -2361,12 +2360,12 @@ describe('SearchAutocomplete', function () { ${'filtering'} | ${null} ${'loading'} | ${'invalid'} ${'filtering'} | ${'invalid'} - `('should render the loading swirl in the tray input field when loadingState="$LoadingState" and validationState="$ValidationState"', ({LoadingState, ValidationState}) => { + `('should render the loading swirl in the tray input field when loadingState="$LoadingState" and validationState="$ValidationState"', async ({LoadingState, ValidationState}) => { let {getAllByRole, getByRole, getByTestId} = renderSearchAutocomplete({loadingState: LoadingState, validationState: ValidationState, defaultInputValue: 'O'}); let button = getAllByRole('button')[0]; act(() => {jest.advanceTimersByTime(500);}); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -2408,13 +2407,13 @@ describe('SearchAutocomplete', function () { } }); - it('should render the loading swirl in the listbox when loadingState="loadingMore"', function () { + it('should render the loading swirl in the listbox when loadingState="loadingMore"', async function () { let {getAllByRole, getByRole, queryByRole, getByTestId} = renderSearchAutocomplete({loadingState: 'loadingMore', validationState: 'invalid'}); let button = getAllByRole('button')[0]; expect(queryByRole('progressbar')).toBeNull(); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); diff --git a/packages/@react-spectrum/breadcrumbs/test/BreadcrumbItem.test.js b/packages/@react-spectrum/breadcrumbs/test/BreadcrumbItem.test.js index 6c1a20b9bad..440befff958 100644 --- a/packages/@react-spectrum/breadcrumbs/test/BreadcrumbItem.test.js +++ b/packages/@react-spectrum/breadcrumbs/test/BreadcrumbItem.test.js @@ -11,8 +11,9 @@ */ import {BreadcrumbItem} from '../src/BreadcrumbItem'; +import {pointerMap, render} from '@react-spectrum/test-utils'; import React from 'react'; -import {render, triggerPress} from '@react-spectrum/test-utils'; +import userEvent from '@testing-library/user-event'; // v3 component describe('BreadcrumbItem', function () { @@ -30,21 +31,23 @@ describe('BreadcrumbItem', function () { expect(breadcrumbItem).toHaveAttribute('aria-current', 'page'); }); - it('Handles disabled', () => { + it('Handles disabled', async () => { + let user = userEvent.setup({delay: null, pointerMap}); let onPressSpy = jest.fn(); let {getByText} = render(Breadcrumb item); let breadcrumbItem = getByText('Breadcrumb item'); expect(breadcrumbItem.tabIndex).toBe(-1); expect(breadcrumbItem).toHaveAttribute('aria-disabled', 'true'); - triggerPress(breadcrumbItem); + await user.click(breadcrumbItem); expect(onPressSpy).toHaveBeenCalledTimes(0); }); - it('Handles onPress', () => { + it('Handles onPress', async () => { + let user = userEvent.setup({delay: null, pointerMap}); let onPressSpy = jest.fn(); let {getByText} = render(Breadcrumb item); let breadcrumbItem = getByText('Breadcrumb item'); - triggerPress(breadcrumbItem); + await user.click(breadcrumbItem); expect(onPressSpy).toHaveBeenCalledTimes(1); }); diff --git a/packages/@react-spectrum/breadcrumbs/test/Breadcrumbs.test.js b/packages/@react-spectrum/breadcrumbs/test/Breadcrumbs.test.js index 505bfc68ccf..e83000f942d 100644 --- a/packages/@react-spectrum/breadcrumbs/test/Breadcrumbs.test.js +++ b/packages/@react-spectrum/breadcrumbs/test/Breadcrumbs.test.js @@ -10,15 +10,18 @@ * governing permissions and limitations under the License. */ -import {act, render, triggerPress, within} from '@react-spectrum/test-utils'; +import {act, pointerMap, render, within} from '@react-spectrum/test-utils'; import {Breadcrumbs} from '../'; import {Item} from '@react-stately/collections'; import {Provider} from '@react-spectrum/provider'; import React, {useRef} from 'react'; import {theme} from '@react-spectrum/theme-default'; +import userEvent from '@testing-library/user-event'; describe('Breadcrumbs', function () { + let user; beforeAll(() => { + user = userEvent.setup({delay: null, pointerMap}); jest.useFakeTimers(); }); beforeEach(() => { @@ -295,7 +298,7 @@ describe('Breadcrumbs', function () { }); - it('can open the menu', () => { + it('can open the menu', async () => { let onAction = jest.fn(); let {getAllByText, getByRole, getAllByRole} = render( @@ -310,7 +313,7 @@ describe('Breadcrumbs', function () { ); let menuButton = getByRole('button'); - triggerPress(menuButton); + await user.click(menuButton); act(() => {jest.runAllTimers();}); let menu = getByRole('menu'); @@ -323,19 +326,19 @@ describe('Breadcrumbs', function () { // breadcrumb root item expect(item1[0]).toHaveAttribute('role', 'link'); - triggerPress(item1[0]); + await user.click(item1[0]); // first press closes the menu, second press act(() => {jest.runAllTimers();}); - triggerPress(item1[0]); + await user.click(item1[0]); expect(onAction).toHaveBeenCalledWith('Folder 1'); // menu item expect(item1[1]).not.toHaveAttribute('role'); - triggerPress(item1[1]); + await user.click(item1[1]); expect(onAction).toHaveBeenCalledWith('Folder 1'); }); - it('clicking on current folder does not trigger onAction', () => { + it('clicking on current folder does not trigger onAction', async () => { let onAction = jest.fn(); let {getByRole, getAllByRole} = render( @@ -350,7 +353,7 @@ describe('Breadcrumbs', function () { ); let menuButton = getByRole('button'); - triggerPress(menuButton); + await user.click(menuButton); let menu = getByRole('menu'); expect(menu).toBeTruthy(); @@ -361,7 +364,7 @@ describe('Breadcrumbs', function () { let item = menuItems[4]; expect(item).toHaveAttribute('aria-checked', 'true'); - triggerPress(item); + await user.click(item); expect(onAction).not.toHaveBeenCalled(); }); @@ -411,7 +414,7 @@ describe('Breadcrumbs', function () { expect(breadcrumbs).toHaveAttribute('data-testid', 'test'); }); - it('should support links', function () { + it('should support links', async function () { let {getByRole, getAllByRole} = render( @@ -431,7 +434,7 @@ describe('Breadcrumbs', function () { expect(links[2]).toHaveAttribute('href', 'https://example.com/foo/bar/baz/qux'); let menuButton = getByRole('button'); - triggerPress(menuButton); + await user.click(menuButton); act(() => {jest.runAllTimers();}); let menu = getByRole('menu'); @@ -441,7 +444,7 @@ describe('Breadcrumbs', function () { expect(items[0]).toHaveAttribute('href', 'https://example.com'); }); - it('should support RouterProvider', () => { + it('should support RouterProvider', async () => { let navigate = jest.fn(); let {getByRole, getAllByRole} = render( @@ -456,17 +459,17 @@ describe('Breadcrumbs', function () { ); let links = getAllByRole('link'); - triggerPress(links[0]); + await user.click(links[0]); expect(navigate).toHaveBeenCalledWith('/foo/bar'); navigate.mockReset(); let menuButton = getByRole('button'); - triggerPress(menuButton); + await user.click(menuButton); act(() => {jest.runAllTimers();}); let menu = getByRole('menu'); let items = within(menu).getAllByRole('menuitemradio'); - triggerPress(items[1]); + await user.click(items[1]); expect(navigate).toHaveBeenCalledWith('/foo'); }); }); diff --git a/packages/@react-spectrum/button/test/ActionButton.test.js b/packages/@react-spectrum/button/test/ActionButton.test.js index 9a5ad9b4d85..a77ca4faa7b 100644 --- a/packages/@react-spectrum/button/test/ActionButton.test.js +++ b/packages/@react-spectrum/button/test/ActionButton.test.js @@ -11,8 +11,9 @@ */ import {ActionButton} from '../'; +import {pointerMap, render} from '@react-spectrum/test-utils'; import React from 'react'; -import {render, triggerPress} from '@react-spectrum/test-utils'; +import userEvent from '@testing-library/user-event'; describe('ActionButton', function () { let onPressSpy = jest.fn(); @@ -24,11 +25,12 @@ describe('ActionButton', function () { it.each` Name | Component | props ${'ActionButton'} | ${ActionButton} | ${{onPress: onPressSpy}} - `('$Name handles defaults', function ({Component, props}) { + `('$Name handles defaults', async function ({Component, props}) { + let user = userEvent.setup({delay: null, pointerMap}); let {getByRole} = render(Click Me); let button = getByRole('button'); - triggerPress(button); + await user.click(button); expect(onPressSpy).toHaveBeenCalledTimes(1); expect(button).not.toHaveAttribute('aria-pressed'); expect(button).not.toHaveAttribute('aria-checked'); diff --git a/packages/@react-spectrum/button/test/Button.test.js b/packages/@react-spectrum/button/test/Button.test.js index 57d55881715..cfae5902263 100644 --- a/packages/@react-spectrum/button/test/Button.test.js +++ b/packages/@react-spectrum/button/test/Button.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, triggerPress} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render} from '@react-spectrum/test-utils'; import {ActionButton, Button, ClearButton, LogicButton} from '../'; import {Checkbox, defaultTheme} from '@adobe/react-spectrum'; import {Form} from '@react-spectrum/form'; @@ -159,12 +159,12 @@ describe('Button', function () { ${'Button'} | ${Button} ${'ClearButton'} | ${ClearButton} ${'LogicButton'} | ${LogicButton} - `('$Name handles deprecated onClick', function ({Component}) { + `('$Name handles deprecated onClick', async function ({Component}) { let spyWarn = jest.spyOn(console, 'warn').mockImplementation(() => {}); let {getByRole} = render(Click Me); let button = getByRole('button'); - triggerPress(button); + await user.click(button); expect(onPressSpy).toHaveBeenCalledTimes(1); expect(spyWarn).toHaveBeenCalledWith('onClick is deprecated, please use onPress'); }); @@ -174,13 +174,13 @@ describe('Button', function () { ${'ActionButton'} | ${ActionButton}| ${{onPress: onPressSpy, elementType: 'a'}} ${'Button'} | ${Button} | ${{onPress: onPressSpy, elementType: 'a'}} ${'LogicButton'} | ${LogicButton} | ${{onPress: onPressSpy, elementType: 'a'}} - `('$Name can have elementType=a', function ({Component, props}) { + `('$Name can have elementType=a', async function ({Component, props}) { let {getByRole} = render(Click Me); let button = getByRole('button'); expect(button).toHaveAttribute('tabindex', '0'); expect(button).not.toHaveAttribute('type', 'button'); - triggerPress(button); + await user.click(button); expect(onPressSpy).toHaveBeenCalledTimes(1); fireEvent.keyDown(button, {key: 'Enter', code: 13}); @@ -197,13 +197,13 @@ describe('Button', function () { ${'ActionButton'} | ${ActionButton}| ${{onPress: onPressSpy, elementType: 'a', href: '#only-hash-in-jsdom'}} ${'Button'} | ${Button} | ${{onPress: onPressSpy, elementType: 'a', href: '#only-hash-in-jsdom'}} ${'LogicButton'} | ${LogicButton} | ${{onPress: onPressSpy, elementType: 'a', href: '#only-hash-in-jsdom'}} - `('$Name can have elementType=a with an href', function ({Component, props}) { + `('$Name can have elementType=a with an href', async function ({Component, props}) { let {getByRole} = render(Click Me); let button = getByRole('button'); expect(button).toHaveAttribute('tabindex', '0'); expect(button).toHaveAttribute('href', '#only-hash-in-jsdom'); - triggerPress(button); + await user.click(button); expect(onPressSpy).toHaveBeenCalledTimes(1); }); @@ -213,11 +213,11 @@ describe('Button', function () { ${'Button'} | ${Button} | ${{onPress: onPressSpy, isDisabled: true}} ${'ClearButton'} | ${ClearButton} | ${{onPress: onPressSpy, isDisabled: true}} ${'LogicButton'} | ${LogicButton} | ${{onPress: onPressSpy, isDisabled: true}} - `('$Name does not respond when disabled', function ({Component, props}) { + `('$Name does not respond when disabled', async function ({Component, props}) { let {getByRole} = render(Click Me); let button = getByRole('button'); - triggerPress(button); + await user.click(button); expect(button).toBeDisabled(); expect(onPressSpy).not.toHaveBeenCalled(); }); @@ -306,7 +306,7 @@ describe('Button', function () { }); // isPending state - it('displays a spinner after a short delay when isPending prop is true', function () { + it('displays a spinner after a short delay when isPending prop is true', async function () { let onPressSpy = jest.fn(); function TestComponent() { let [pending, setPending] = useState(false); @@ -324,13 +324,13 @@ describe('Button', function () { let {getByRole, queryByRole} = render(); let button = getByRole('button'); expect(button).not.toHaveAttribute('aria-disabled'); - triggerPress(button); + await user.click(button); // Button is disabled immediately, but spinner visibility is delayed expect(button).toHaveAttribute('aria-disabled', 'true'); let spinner = queryByRole('progressbar'); expect(spinner).not.toBeInTheDocument(); // Multiple clicks shouldn't call onPressSpy - triggerPress(button); + await user.click(button); act(() => { jest.advanceTimersByTime(spinnerVisibilityDelay); }); diff --git a/packages/@react-spectrum/button/test/ClearButton.test.js b/packages/@react-spectrum/button/test/ClearButton.test.js index 42c65a69ae4..d6377f88c53 100644 --- a/packages/@react-spectrum/button/test/ClearButton.test.js +++ b/packages/@react-spectrum/button/test/ClearButton.test.js @@ -10,9 +10,10 @@ * governing permissions and limitations under the License. */ -import {act, render, triggerPress} from '@react-spectrum/test-utils'; +import {act, pointerMap, render} from '@react-spectrum/test-utils'; import {ClearButton} from '../'; import React from 'react'; +import userEvent from '@testing-library/user-event'; // NOTE: ClearButton doesn't use Button.tsx as a base and thus differs from v2 ClearButton in a couple ways // Refinement of ClearButton to be done later @@ -27,11 +28,12 @@ describe('ClearButton', function () { it.each` Name | Component | props ${'v3 ClearButton'} | ${ClearButton} | ${{onPress: onPressSpy}} - `('$Name handles defaults', function ({Component, props}) { + `('$Name handles defaults', async function ({Component, props}) { + let user = userEvent.setup({delay: null, pointerMap}); let {getByRole} = render(Click Me); let button = getByRole('button', {hidden: true}); - triggerPress(button); + await user.click(button); expect(onPressSpy).toHaveBeenCalledTimes(1); }); diff --git a/packages/@react-spectrum/button/test/ToggleButton.test.js b/packages/@react-spectrum/button/test/ToggleButton.test.js index 2feff10d956..7cc78782415 100644 --- a/packages/@react-spectrum/button/test/ToggleButton.test.js +++ b/packages/@react-spectrum/button/test/ToggleButton.test.js @@ -10,12 +10,14 @@ * governing permissions and limitations under the License. */ +import {pointerMap, render} from '@react-spectrum/test-utils'; import React from 'react'; -import {render, triggerPress} from '@react-spectrum/test-utils'; import {ToggleButton} from '../'; +import userEvent from '@testing-library/user-event'; describe('ToggleButton', function () { - it('handles defaults', function () { + it('handles defaults', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let onPress = jest.fn(); let onChange = jest.fn(); let {getByRole} = render(Click Me); @@ -23,13 +25,14 @@ describe('ToggleButton', function () { let button = getByRole('button'); expect(button).toHaveAttribute('aria-pressed', 'false'); - triggerPress(button); + await user.click(button); expect(onPress).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith(true); expect(button).toHaveAttribute('aria-pressed', 'true'); }); - it('supports defaultSelected', function () { + it('supports defaultSelected', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let onPress = jest.fn(); let onChange = jest.fn(); let {getByRole} = render(Click Me); @@ -37,13 +40,14 @@ describe('ToggleButton', function () { let button = getByRole('button'); expect(button).toHaveAttribute('aria-pressed', 'true'); - triggerPress(button); + await user.click(button); expect(onPress).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith(false); expect(button).toHaveAttribute('aria-pressed', 'false'); }); - it('supports isSelected', function () { + it('supports isSelected', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let onPress = jest.fn(); let onChange = jest.fn(); let {getByRole} = render(Click Me); @@ -51,7 +55,7 @@ describe('ToggleButton', function () { let button = getByRole('button'); expect(button).toHaveAttribute('aria-pressed', 'true'); - triggerPress(button); + await user.click(button); expect(onPress).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith(false); expect(button).toHaveAttribute('aria-pressed', 'true'); diff --git a/packages/@react-spectrum/buttongroup/test/ButtonGroup.test.js b/packages/@react-spectrum/buttongroup/test/ButtonGroup.test.js index c6c2734ea8e..e5f42dfaa8a 100644 --- a/packages/@react-spectrum/buttongroup/test/ButtonGroup.test.js +++ b/packages/@react-spectrum/buttongroup/test/ButtonGroup.test.js @@ -10,12 +10,13 @@ * governing permissions and limitations under the License. */ -import {act, render, triggerPress, within} from '@react-spectrum/test-utils'; +import {act, pointerMap, render, within} from '@react-spectrum/test-utils'; import {Button} from '@react-spectrum/button'; import {ButtonGroup} from '../'; import {Provider} from '@react-spectrum/provider'; import React, {useEffect, useRef} from 'react'; import {theme} from '@react-spectrum/theme-default'; +import userEvent from '@testing-library/user-event'; let buttonGroupId = 'button-group'; let onPressSpy1 = jest.fn(); @@ -48,7 +49,8 @@ describe('ButtonGroup', function () { it.each` Name | Component | props ${'ButtonGroup'} | ${ButtonGroup} | ${{}} - `('$Name renders multiple buttons', function ({Component, props}) { + `('$Name renders multiple buttons', async function ({Component, props}) { + let user = userEvent.setup({delay: null, pointerMap}); let tree = renderComponent(Component, props); let buttonGroup = tree.getByTestId(buttonGroupId); expect(buttonGroup).toBeTruthy(); @@ -61,9 +63,9 @@ describe('ButtonGroup', function () { expect(button2).toBeTruthy(); expect(button3).toBeTruthy(); - triggerPress(button1); - triggerPress(button2); - triggerPress(button3); + await user.click(button1); + await user.click(button2); + await user.click(button3); expect(onPressSpy1).toHaveBeenCalledTimes(1); expect(onPressSpy2).toHaveBeenCalledTimes(1); @@ -93,7 +95,8 @@ describe('ButtonGroup', function () { it.each` Name | Component | props ${'ButtonGroup'} | ${ButtonGroup} | ${{isDisabled: true}} - `('$Name supports disabling all buttons within via isDisabled', function ({Component, props}) { + `('$Name supports disabling all buttons within via isDisabled', async function ({Component, props}) { + let user = userEvent.setup({delay: null, pointerMap}); let tree = renderComponent(Component, props); let buttonGroup = tree.getByTestId(buttonGroupId); expect(buttonGroup).toBeTruthy(); @@ -102,9 +105,9 @@ describe('ButtonGroup', function () { let button2 = within(buttonGroup).getByText('Button2'); let button3 = within(buttonGroup).getByText('Button3'); - triggerPress(button1); - triggerPress(button2); - triggerPress(button3); + await user.click(button1); + await user.click(button2); + await user.click(button3); expect(onPressSpy1).toHaveBeenCalledTimes(0); expect(onPressSpy2).toHaveBeenCalledTimes(0); diff --git a/packages/@react-spectrum/calendar/test/Calendar.test.js b/packages/@react-spectrum/calendar/test/Calendar.test.js index 79cf3439081..ebfcbda31e3 100644 --- a/packages/@react-spectrum/calendar/test/Calendar.test.js +++ b/packages/@react-spectrum/calendar/test/Calendar.test.js @@ -16,9 +16,10 @@ jest.mock('@react-aria/live-announcer'); import {announce} from '@react-aria/live-announcer'; import {Calendar} from '../'; import {CalendarDate, isWeekend} from '@internationalized/date'; -import {fireEvent, render, triggerPress} from '@react-spectrum/test-utils'; +import {fireEvent, pointerMap, render} from '@react-spectrum/test-utils'; import React from 'react'; import {useLocale} from '@react-aria/i18n'; +import userEvent from '@testing-library/user-event'; let keyCodes = {'Enter': 13, ' ': 32, 'PageUp': 33, 'PageDown': 34, 'End': 35, 'Home': 36, 'ArrowLeft': 37, 'ArrowUp': 38, 'ArrowRight': 39, 'ArrowDown': 40}; @@ -206,7 +207,8 @@ describe('Calendar', () => { it.each` Name | Calendar ${'v3'} | ${Calendar} - `('$Name selects a date on click (uncontrolled)', ({Calendar}) => { + `('$Name selects a date on click (uncontrolled)', async ({Calendar}) => { + let user = userEvent.setup({delay: null, pointerMap}); let onChange = jest.fn(); let {getByLabelText, getByText} = render( { ); let newDate = getByText('17'); - triggerPress(newDate); + await user.click(newDate); let selectedDate = getByLabelText('selected', {exact: false}); expect(selectedDate.textContent).toBe('17'); @@ -226,7 +228,8 @@ describe('Calendar', () => { it.each` Name | Calendar ${'v3'} | ${Calendar} - `('$Name selects a date on click (controlled)', ({Calendar}) => { + `('$Name selects a date on click (controlled)', async ({Calendar}) => { + let user = userEvent.setup({delay: null, pointerMap}); let onChange = jest.fn(); let {getByLabelText, getByText} = render( { ); let newDate = getByText('17'); - triggerPress(newDate); + await user.click(newDate); let selectedDate = getByLabelText('selected', {exact: false}); expect(selectedDate.textContent).toBe('5'); @@ -246,7 +249,8 @@ describe('Calendar', () => { it.each` Name | Calendar | props ${'v3'} | ${Calendar} | ${{isDisabled: true}} - `('$Name does not select a date on click if isDisabled', ({Calendar, props}) => { + `('$Name does not select a date on click if isDisabled', async ({Calendar, props}) => { + let user = userEvent.setup({delay: null, pointerMap}); let onChange = jest.fn(); let {getAllByLabelText, getByText} = render( { ); let newDate = getByText('17'); - triggerPress(newDate); + await user.click(newDate); expect(() => { getAllByLabelText('selected', {exact: false}); @@ -267,7 +271,8 @@ describe('Calendar', () => { it.each` Name | Calendar | props ${'v3'} | ${Calendar} | ${{isReadOnly: true}} - `('$Name does not select a date on click if isReadOnly', ({Calendar, props}) => { + `('$Name does not select a date on click if isReadOnly', async ({Calendar, props}) => { + let user = userEvent.setup({delay: null, pointerMap}); let onChange = jest.fn(); let {getByLabelText, getByText} = render( { ); let newDate = getByText('17'); - triggerPress(newDate); + await user.click(newDate); let selectedDate = getByLabelText('selected', {exact: false}); expect(selectedDate.textContent).toBe('5'); @@ -287,7 +292,8 @@ describe('Calendar', () => { it.each` Name | Calendar | props ${'v3'} | ${Calendar} | ${{defaultValue: new CalendarDate(2019, 2, 8), minValue: new CalendarDate(2019, 2, 5), maxValue: new CalendarDate(2019, 2, 15)}} - `('$Name does not select a date on click if outside the valid date range', ({Calendar, props}) => { + `('$Name does not select a date on click if outside the valid date range', async ({Calendar, props}) => { + let user = userEvent.setup({delay: null, pointerMap}); let onChange = jest.fn(); let {getByLabelText} = render( { {...props} /> ); - triggerPress(getByLabelText('Sunday, February 3, 2019')); + await user.click(getByLabelText('Sunday, February 3, 2019')); let selectedDate = getByLabelText('selected', {exact: false}); expect(selectedDate.textContent).toBe('8'); expect(onChange).not.toHaveBeenCalled(); - triggerPress(getByLabelText('Sunday, February 17, 2019')); + await user.click(getByLabelText('Sunday, February 17, 2019')); selectedDate = getByLabelText('selected', {exact: false}); expect(selectedDate.textContent).toBe('8'); expect(onChange).not.toHaveBeenCalled(); - triggerPress(getByLabelText('Tuesday, February 5, 2019, First available date')); + await user.click(getByLabelText('Tuesday, February 5, 2019, First available date')); selectedDate = getByLabelText('selected', {exact: false}); expect(selectedDate.textContent).toBe('5'); expect(onChange).toHaveBeenCalledTimes(1); - triggerPress(getByLabelText('Friday, February 15, 2019, Last available date')); + await user.click(getByLabelText('Friday, February 15, 2019, Last available date')); selectedDate = getByLabelText('selected', {exact: false}); expect(selectedDate.textContent).toBe('15'); @@ -390,22 +396,24 @@ describe('Calendar', () => { }); describe('announcing', () => { - it('announces when the current month changes', () => { + it('announces when the current month changes', async () => { + let user = userEvent.setup({delay: null, pointerMap}); let {getAllByLabelText} = render(); let nextButton = getAllByLabelText('Next')[0]; - triggerPress(nextButton); + await user.click(nextButton); act(() => {jest.runAllTimers();}); expect(announce).toHaveBeenCalledTimes(1); expect(announce).toHaveBeenCalledWith('July 2019'); }); - it('announces when the selected date changes', () => { + it('announces when the selected date changes', async () => { + let user = userEvent.setup({delay: null, pointerMap}); let {getByText} = render(); let newDate = getByText('17'); - triggerPress(newDate); + await user.click(newDate); act(() => {jest.runAllTimers();}); expect(announce).toHaveBeenCalledTimes(1); @@ -425,11 +433,12 @@ describe('Calendar', () => { expect(getByLabelText('Thursday, June 6, 2019', {exact: false})).toHaveFocus(); }); - it('includes era in BC dates', () => { + it('includes era in BC dates', async () => { + let user = userEvent.setup({delay: null, pointerMap}); let {getByText, getAllByLabelText} = render(); let newDate = getByText('17'); - triggerPress(newDate); + await user.click(newDate); act(() => {jest.runAllTimers();}); expect(announce).toHaveBeenCalledTimes(1); @@ -437,7 +446,7 @@ describe('Calendar', () => { announce.mockReset(); let nextButton = getAllByLabelText('Next')[0]; - triggerPress(nextButton); + await user.click(nextButton); act(() => {jest.runAllTimers();}); expect(announce).toHaveBeenCalledTimes(1); diff --git a/packages/@react-spectrum/calendar/test/CalendarBase.test.js b/packages/@react-spectrum/calendar/test/CalendarBase.test.js index 38143edda2e..07be131880f 100644 --- a/packages/@react-spectrum/calendar/test/CalendarBase.test.js +++ b/packages/@react-spectrum/calendar/test/CalendarBase.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, triggerPress, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; import {Calendar, RangeCalendar} from '../'; import {CalendarDate, GregorianCalendar, today} from '@internationalized/date'; import {Provider} from '@react-spectrum/provider'; @@ -168,7 +168,7 @@ describe('CalendarBase', () => { Name | Calendar | props ${'v3 Calendar'} | ${Calendar} | ${{defaultValue: new CalendarDate(2019, 6, 5)}} ${'v3 RangeCalendar'} | ${RangeCalendar} | ${{defaultValue: {start: new CalendarDate(2019, 6, 5), end: new CalendarDate(2019, 6, 10)}}} - `('$Name should change the month when previous or next buttons are clicked', ({Calendar, props}) => { + `('$Name should change the month when previous or next buttons are clicked', async ({Calendar, props}) => { let {getByRole, getByLabelText, getAllByLabelText, getAllByRole} = render(); let heading = getByRole('heading'); @@ -179,7 +179,7 @@ describe('CalendarBase', () => { expect(getAllByLabelText('selected', {exact: false}).length).toBeGreaterThan(0); let nextButton = getAllByLabelText('Next')[0]; - triggerPress(nextButton); + await user.click(nextButton); expect(() => { getAllByLabelText('selected', {exact: false}); @@ -192,7 +192,7 @@ describe('CalendarBase', () => { expect(nextButton).toHaveFocus(); let prevButton = getByLabelText('Previous'); - triggerPress(prevButton); + await user.click(prevButton); expect(heading).toHaveTextContent('June 2019'); gridCells = getAllByRole('gridcell').filter(cell => cell.getAttribute('aria-disabled') !== 'true'); @@ -205,7 +205,7 @@ describe('CalendarBase', () => { Name | Calendar | props ${'v3 Calendar'} | ${Calendar} | ${{defaultValue: new CalendarDate(2019, 6, 5)}} ${'v3 RangeCalendar'} | ${RangeCalendar} | ${{defaultValue: {start: new CalendarDate(2019, 6, 5), end: new CalendarDate(2019, 6, 10)}}} - `('$Name should change the month when previous or next buttons are clicked and multiple months are visible', ({Calendar, props}) => { + `('$Name should change the month when previous or next buttons are clicked and multiple months are visible', async ({Calendar, props}) => { let {getAllByRole, getByLabelText, getAllByLabelText} = render(); let grids = getAllByRole('grid'); @@ -215,7 +215,7 @@ describe('CalendarBase', () => { expect(grids[2]).toHaveAttribute('aria-label', 'July 2019'); let nextButton = getAllByLabelText('Next')[0]; - triggerPress(nextButton); + await user.click(nextButton); grids = getAllByRole('grid'); expect(grids).toHaveLength(3); @@ -224,7 +224,7 @@ describe('CalendarBase', () => { expect(grids[2]).toHaveAttribute('aria-label', 'October 2019'); let prevButton = getByLabelText('Previous'); - triggerPress(prevButton); + await user.click(prevButton); grids = getAllByRole('grid'); expect(grids).toHaveLength(3); @@ -356,7 +356,7 @@ describe('CalendarBase', () => { Name | Calendar | props ${'v3 Calendar'} | ${Calendar} | ${{defaultValue: new CalendarDate(2021, 12, 15)}} ${'v3 RangeCalendar'} | ${RangeCalendar} | ${{defaultValue: {start: new CalendarDate(2021, 12, 15), end: new CalendarDate(2021, 12, 15)}}} - `('$Name should set aria-disabled on cells for which isDateUnavailable returns true', ({Calendar, props}) => { + `('$Name should set aria-disabled on cells for which isDateUnavailable returns true', async ({Calendar, props}) => { const isDateUnavailable = (date) => { const disabledIntervals = [[new CalendarDate(2021, 12, 6), new CalendarDate(2021, 12, 10)], [new CalendarDate(2021, 12, 22), new CalendarDate(2021, 12, 26)]]; return disabledIntervals.some((interval) => date.compare(interval[0]) >= 0 && date.compare(interval[1]) <= 0); @@ -379,11 +379,11 @@ describe('CalendarBase', () => { expect(gridCells.length).toBe(21); let cell = getByRole('button', {name: 'Wednesday, December 22, 2021'}); - triggerPress(cell); + await user.click(cell); expect(cell.parentElement).not.toHaveAttribute('aria-selected'); cell = getByRole('button', {name: 'Sunday, December 12, 2021'}); - triggerPress(cell); + await user.click(cell); expect(cell.parentElement).toHaveAttribute('aria-selected', 'true'); }); diff --git a/packages/@react-spectrum/card/test/CardView.test.js b/packages/@react-spectrum/card/test/CardView.test.js index 95f3729689f..abb340fe612 100644 --- a/packages/@react-spectrum/card/test/CardView.test.js +++ b/packages/@react-spectrum/card/test/CardView.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, triggerPress, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; import {Card, CardView, GalleryLayout, GridLayout, WaterfallLayout} from '../'; import {composeStories} from '@storybook/testing-react'; import {Content} from '@react-spectrum/view'; @@ -307,14 +307,14 @@ describe('CardView', function () { }); describe('keyboard nav', function () { - it('should move focus via Arrow Down', function () { + it('should move focus via Arrow Down', async function () { let tree = render(); act(() => { jest.runAllTimers(); }); let cards = tree.getAllByRole('gridcell'); - triggerPress(cards[1]); + await user.click(cards[1]); expect(document.activeElement).toBe(cards[1]); let cardStyles = getCardStyles(cards[1]); let expectedLeft = cardStyles.left; @@ -331,14 +331,14 @@ describe('CardView', function () { expect(cardStyles.left).toEqual(expectedLeft); }); - it('should move focus via Arrow Up', function () { + it('should move focus via Arrow Up', async function () { let tree = render(); act(() => { jest.runAllTimers(); }); let cards = tree.getAllByRole('gridcell'); - triggerPress(cards[5]); + await user.click(cards[5]); expect(document.activeElement).toBe(cards[5]); let cardStyles = getCardStyles(cards[5]); let expectedLeft = cardStyles.left; @@ -359,7 +359,7 @@ describe('CardView', function () { Name | layout ${'Grid layout'} | ${GridLayout} ${'Gallery layout'} | ${GalleryLayout} - `('$Name CardView should move focus via Arrow Left', function ({Name, layout}) { + `('$Name CardView should move focus via Arrow Left', async function ({Name, layout}) { let tree = render(); act(() => { jest.runAllTimers(); @@ -367,7 +367,7 @@ describe('CardView', function () { let cards = tree.getAllByRole('gridcell'); - triggerPress(cards[1]); + await user.click(cards[1]); expect(document.activeElement).toBe(cards[1]); let cardStyles = getCardStyles(cards[1]); let expectedLeft = cardStyles.left; @@ -392,7 +392,7 @@ describe('CardView', function () { Name | layout ${'Grid layout'} | ${GridLayout} ${'Gallery layout'} | ${GalleryLayout} - `('$Name CardView should move focus via Arrow Left (RTL)', function ({Name, layout}) { + `('$Name CardView should move focus via Arrow Left (RTL)', async function ({Name, layout}) { let tree = render(); act(() => { jest.runAllTimers(); @@ -402,7 +402,7 @@ describe('CardView', function () { let expectedTop; let cards = tree.getAllByRole('gridcell'); - triggerPress(cards[0]); + await user.click(cards[0]); expect(document.activeElement).toBe(cards[0]); let cardStyles = getCardStyles(cards[0]); expectedRight = cardStyles.right; @@ -427,7 +427,7 @@ describe('CardView', function () { Name | layout ${'Grid layout'} | ${GridLayout} ${'Gallery layout'} | ${GalleryLayout} - `('$Name CardView should move focus via Arrow Right', function ({Name, layout}) { + `('$Name CardView should move focus via Arrow Right', async function ({Name, layout}) { let tree = render(); act(() => { jest.runAllTimers(); @@ -435,7 +435,7 @@ describe('CardView', function () { let cards = tree.getAllByRole('gridcell'); - triggerPress(cards[0]); + await user.click(cards[0]); expect(document.activeElement).toBe(cards[0]); let cardStyles = getCardStyles(cards[0]); let expectedLeft = cardStyles.left; @@ -460,7 +460,7 @@ describe('CardView', function () { Name | layout ${'Grid layout'} | ${GridLayout} ${'Gallery layout'} | ${GalleryLayout} - `('$Name CardView should move focus via Arrow Right (RTL)', function ({Name, layout}) { + `('$Name CardView should move focus via Arrow Right (RTL)', async function ({Name, layout}) { let tree = render(); act(() => { jest.runAllTimers(); @@ -470,7 +470,7 @@ describe('CardView', function () { let expectedTop; let cards = tree.getAllByRole('gridcell'); - triggerPress(cards[1]); + await user.click(cards[1]); expect(document.activeElement).toBe(cards[1]); let cardStyles = getCardStyles(cards[1]); expectedRight = cardStyles.right; @@ -491,14 +491,14 @@ describe('CardView', function () { expect(cardStyles.right).toEqual(expectedRight); }); - it('should move focus via Page Up', function () { + it('should move focus via Page Up', async function () { let tree = render(); act(() => { jest.runAllTimers(); }); let cards = tree.getAllByRole('gridcell'); - triggerPress(cards[5]); + await user.click(cards[5]); fireEvent.keyDown(document.activeElement, {key: 'End', code: 35, charCode: 35}); fireEvent.keyUp(document.activeElement, {key: 'End', code: 35, charCode: 35}); @@ -525,14 +525,14 @@ describe('CardView', function () { expect(cardStyles.left).toEqual(expectedLeft); }); - it('should move focus via Page Down', function () { + it('should move focus via Page Down', async function () { let tree = render(); act(() => { jest.runAllTimers(); }); let cards = tree.getAllByRole('gridcell'); - triggerPress(cards[1]); + await user.click(cards[1]); expect(document.activeElement).toBe(cards[1]); let cardStyles = getCardStyles(document.activeElement); @@ -594,14 +594,14 @@ describe('CardView', function () { }); describe('keyboard nav', function () { - it('should move focus via Arrow Down', function () { + it('should move focus via Arrow Down', async function () { let tree = render(); act(() => { jest.runAllTimers(); }); let cards = tree.getAllByRole('gridcell'); - triggerPress(cards[0]); + await user.click(cards[0]); expect(document.activeElement).toBe(cards[0]); expect(within(document.activeElement).getByText('Title 1')).toBeTruthy(); @@ -619,14 +619,14 @@ describe('CardView', function () { expect(within(document.activeElement).getByText('Title 4')).toBeTruthy(); }); - it('should move focus via Arrow Up', function () { + it('should move focus via Arrow Up', async function () { let tree = render(); act(() => { jest.runAllTimers(); }); let cards = tree.getAllByRole('gridcell'); - triggerPress(cards[3]); + await user.click(cards[3]); expect(document.activeElement).toBe(cards[3]); expect(within(document.activeElement).getByText('Title 4')).toBeTruthy(); @@ -645,14 +645,14 @@ describe('CardView', function () { expect(within(document.activeElement).getByText('Title 1')).toBeTruthy(); }); - it('should move focus via Page Up', function () { + it('should move focus via Page Up', async function () { let tree = render(); act(() => { jest.runAllTimers(); }); let cards = tree.getAllByRole('gridcell'); - triggerPress(cards[0]); + await user.click(cards[0]); fireEvent.keyDown(document.activeElement, {key: 'End', code: 35, charCode: 35}); fireEvent.keyUp(document.activeElement, {key: 'End', code: 35, charCode: 35}); @@ -688,14 +688,14 @@ describe('CardView', function () { expect(document.activeElement).toEqual(pageUpElement); }); - it('should move focus via Page Down', function () { + it('should move focus via Page Down', async function () { let tree = render(); act(() => { jest.runAllTimers(); }); let cards = tree.getAllByRole('gridcell'); - triggerPress(cards[0]); + await user.click(cards[0]); fireEvent.keyDown(document.activeElement, {key: 'PageDown', code: 34, charCode: 34}); fireEvent.keyUp(document.activeElement, {key: 'PageDown', code: 34, charCode: 34}); @@ -775,13 +775,13 @@ describe('CardView', function () { }); describe('keyboard nav', function () { - it('should move focus via Arrow Down', function () { + it('should move focus via Arrow Down', async function () { let tree = render(); act(() => jest.runAllTimers()); // relayout raf act(() => jest.runAllTimers()); // update size let cards = tree.getAllByRole('gridcell'); - triggerPress(cards[0]); + await user.click(cards[0]); expect(document.activeElement).toBe(cards[0]); expect(within(document.activeElement).getByText('Title 1')).toBeTruthy(); @@ -801,13 +801,13 @@ describe('CardView', function () { expect(within(document.activeElement).getByText('Title 3')).toBeTruthy(); }); - it('should move focus via Arrow Up', function () { + it('should move focus via Arrow Up', async function () { let tree = render(); act(() => jest.runAllTimers()); // relayout raf act(() => jest.runAllTimers()); // update size let cards = tree.getAllByRole('gridcell'); - triggerPress(cards[2]); + await user.click(cards[2]); expect(document.activeElement).toBe(cards[2]); expect(within(document.activeElement).getByText('Title 3')).toBeTruthy(); @@ -828,7 +828,7 @@ describe('CardView', function () { expect(within(document.activeElement).getByText('Title 1')).toBeTruthy(); }); - it('should move focus via Arrow Left', function () { + it('should move focus via Arrow Left', async function () { let tree = render(); act(() => { jest.runAllTimers(); @@ -836,7 +836,7 @@ describe('CardView', function () { let cards = tree.getAllByRole('gridcell'); - triggerPress(cards[1]); + await user.click(cards[1]); act(() => { jest.runAllTimers(); }); @@ -858,14 +858,14 @@ describe('CardView', function () { expect(cardStyles.left).toEqual(expectedLeft); }); - it('should move focus via Arrow Left (RTL)', function () { + it('should move focus via Arrow Left (RTL)', async function () { let tree = render(); act(() => { jest.runAllTimers(); }); let cards = tree.getAllByRole('gridcell'); - triggerPress(cards[0]); + await user.click(cards[0]); act(() => { jest.runAllTimers(); }); @@ -887,7 +887,7 @@ describe('CardView', function () { expect(cardStyles.right).toEqual(expectedRight); }); - it('should move focus via Arrow Right', function () { + it('should move focus via Arrow Right', async function () { let tree = render(); act(() => { jest.runAllTimers(); @@ -895,7 +895,7 @@ describe('CardView', function () { let cards = tree.getAllByRole('gridcell'); - triggerPress(cards[0]); + await user.click(cards[0]); act(() => { jest.runAllTimers(); }); @@ -917,7 +917,7 @@ describe('CardView', function () { expect(cardStyles.left).toEqual(expectedLeft); }); - it('should move focus via Arrow Right (RTL)', function () { + it('should move focus via Arrow Right (RTL)', async function () { let tree = render(); act(() => { jest.runAllTimers(); @@ -925,7 +925,7 @@ describe('CardView', function () { let cards = tree.getAllByRole('gridcell'); - triggerPress(cards[1]); + await user.click(cards[1]); act(() => { jest.runAllTimers(); }); @@ -958,14 +958,14 @@ describe('CardView', function () { ${'Grid layout'} | ${GridLayout} ${'Gallery layout'} | ${GalleryLayout} ${'Waterfall layout'} | ${WaterfallLayout} - `('$Name CardView should move focus via Home', function ({layout}) { + `('$Name CardView should move focus via Home', async function ({layout}) { let tree = render(); act(() => { jest.runAllTimers(); }); let cards = tree.getAllByRole('gridcell'); - triggerPress(cards[2]); + await user.click(cards[2]); expect(document.activeElement).toBe(cards[2]); fireEvent.keyDown(document.activeElement, {key: 'Home', code: 36, charCode: 36}); @@ -982,14 +982,14 @@ describe('CardView', function () { ${'Grid layout'} | ${GridLayout} ${'Gallery layout'} | ${GalleryLayout} ${'Waterfall layout'} | ${WaterfallLayout} - `('$Name CardView should move focus via End', function ({layout}) { + `('$Name CardView should move focus via End', async function ({layout}) { let tree = render(); act(() => { jest.runAllTimers(); }); let cards = tree.getAllByRole('gridcell'); - triggerPress(cards[2]); + await user.click(cards[2]); expect(document.activeElement).toBe(cards[2]); fireEvent.keyDown(document.activeElement, {key: 'End', code: 35, charCode: 35}); @@ -1014,7 +1014,7 @@ describe('CardView', function () { }); let cards = tree.getAllByRole('gridcell'); - triggerPress(cards[1]); + await user.click(cards[1]); expect(document.activeElement).toBe(cards[1]); await user.keyboard('Title 12'); @@ -1041,14 +1041,14 @@ describe('CardView', function () { expect(within(cards[1]).getByRole('checkbox').checked).toBeTruthy(); }); - it('CardView should support disabledKeys', function () { + it('CardView should support disabledKeys', async function () { let tree = render(); act(() => { jest.runAllTimers(); }); let cards = tree.getAllByRole('gridcell'); - triggerPress(cards[0]); + await user.click(cards[0]); expect(document.activeElement).not.toBe(cards[0]); expect(cards[0].parentNode).not.toHaveAttribute('aria-selected', 'true'); expect(within(cards[0]).getByRole('checkbox')).toHaveAttribute('disabled'); @@ -1056,18 +1056,18 @@ describe('CardView', function () { expect(onSelectionChange).not.toHaveBeenCalled(); }); - it('CardView should support multiple selection', function () { + it('CardView should support multiple selection', async function () { let tree = render(); act(() => { jest.runAllTimers(); }); let cards = tree.getAllByRole('gridcell'); - triggerPress(cards[0]); + await user.click(cards[0]); expect(new Set(onSelectionChange.mock.calls[0][0])).toEqual(new Set(['Title 1'])); expect(onSelectionChange).toHaveBeenCalledTimes(1); - triggerPress(cards[2]); + await user.click(cards[2]); expect(new Set(onSelectionChange.mock.calls[1][0])).toEqual(new Set(['Title 1', 'Title 3'])); expect(onSelectionChange).toHaveBeenCalledTimes(2); @@ -1076,7 +1076,7 @@ describe('CardView', function () { expect(within(cards[0]).getByRole('checkbox').checked).toBeTruthy(); expect(within(cards[2]).getByRole('checkbox').checked).toBeTruthy(); - triggerPress(cards[0]); + await user.click(cards[0]); expect(new Set(onSelectionChange.mock.calls[2][0])).toEqual(new Set(['Title 3'])); expect(onSelectionChange).toHaveBeenCalledTimes(3); @@ -1086,20 +1086,20 @@ describe('CardView', function () { expect(within(cards[2]).getByRole('checkbox').checked).toBeTruthy(); }); - it('CardView should support single selection', function () { + it('CardView should support single selection', async function () { let tree = render(); act(() => { jest.runAllTimers(); }); let cards = tree.getAllByRole('gridcell'); - triggerPress(cards[0]); + await user.click(cards[0]); expect(new Set(onSelectionChange.mock.calls[0][0])).toEqual(new Set(['Title 1'])); expect(onSelectionChange).toHaveBeenCalledTimes(1); expect(cards[0].parentNode).toHaveAttribute('aria-selected', 'true'); expect(within(cards[0]).getByRole('checkbox').checked).toBeTruthy(); - triggerPress(cards[2]); + await user.click(cards[2]); expect(new Set(onSelectionChange.mock.calls[1][0])).toEqual(new Set(['Title 3'])); expect(onSelectionChange).toHaveBeenCalledTimes(2); expect(cards[0].parentNode).toHaveAttribute('aria-selected', 'false'); @@ -1107,7 +1107,7 @@ describe('CardView', function () { expect(within(cards[0]).getByRole('checkbox').checked).toBeFalsy(); expect(within(cards[2]).getByRole('checkbox').checked).toBeTruthy(); - triggerPress(cards[2]); + await user.click(cards[2]); expect(new Set(onSelectionChange.mock.calls[2][0])).toEqual(new Set([])); expect(onSelectionChange).toHaveBeenCalledTimes(3); expect(cards[0].parentNode).toHaveAttribute('aria-selected', 'false'); @@ -1116,19 +1116,19 @@ describe('CardView', function () { expect(within(cards[2]).getByRole('checkbox').checked).toBeFalsy(); }); - it('CardView should support no selection', function () { + it('CardView should support no selection', async function () { let tree = render(); act(() => { jest.runAllTimers(); }); let cards = tree.getAllByRole('gridcell'); - triggerPress(cards[0]); + await user.click(cards[0]); expect(onSelectionChange).toHaveBeenCalledTimes(0); expect(cards[0].parentNode).not.toHaveAttribute('aria-selected'); expect(within(cards[0]).queryByRole('checkbox')).toBeNull(); - triggerPress(cards[2]); + await user.click(cards[2]); expect(onSelectionChange).toHaveBeenCalledTimes(0); expect(cards[2].parentNode).not.toHaveAttribute('aria-selected'); expect(within(cards[2]).queryByRole('checkbox')).toBeNull(); @@ -1173,7 +1173,7 @@ describe('CardView', function () { ${'Grid layout'} | ${GridLayout} ${'Gallery layout'} | ${GalleryLayout} ${'Waterfall layout'} | ${WaterfallLayout} - `('$Name CardView should render a loading spinner at the bottom when loading more', function ({layout}) { + `('$Name CardView should render a loading spinner at the bottom when loading more', async function ({layout}) { let tree = render(); act(() => { jest.runAllTimers(); @@ -1185,7 +1185,7 @@ describe('CardView', function () { let cards = tree.getAllByRole('gridcell'); expect(cards).toBeTruthy(); - triggerPress(cards[1]); + await user.click(cards[1]); // Scroll to the 'ideal' end, however, this won't be the true y position after everything has // been rendered and layout infos are all calculated. So scroll to the beginning again and then back one more time. @@ -1219,7 +1219,7 @@ describe('CardView', function () { Name | layout ${'Grid layout'} | ${GridLayout} ${'Gallery layout'} | ${GalleryLayout} - `('$Name CardView should call loadMore when scrolling to the bottom', function ({layout}) { + `('$Name CardView should call loadMore when scrolling to the bottom', async function ({layout}) { let onLoadMore = jest.fn(); let tree = render(); @@ -1231,7 +1231,7 @@ describe('CardView', function () { expect(cards).toBeTruthy(); // Virtualizer calls onLoadMore twice due to initial layout expect(onLoadMore).toHaveBeenCalledTimes(1); - triggerPress(cards[1]); + await user.click(cards[1]); fireEvent.keyDown(document.activeElement, {key: 'End', code: 35, charCode: 35}); fireEvent.keyUp(document.activeElement, {key: 'End', code: 35, charCode: 35}); @@ -1298,7 +1298,7 @@ describe('CardView', function () { Name | layout ${'Grid layout'} | ${GridLayout} ${'Gallery layout'} | ${GalleryLayout} - `('$Name CardView should only scroll an item into view when in keyboard modality', function ({layout}) { + `('$Name CardView should only scroll an item into view when in keyboard modality', async function ({layout}) { let tree = render(); act(() => { jest.runAllTimers(); @@ -1307,7 +1307,7 @@ describe('CardView', function () { expect(cards).toBeTruthy(); let grid = tree.getByRole('grid'); let initialScrollTop = grid.scrollTop; - triggerPress(cards[cards.length - 1]); + await user.click(cards[cards.length - 1]); act(() => { jest.runAllTimers(); }); diff --git a/packages/@react-spectrum/combobox/test/ComboBox.test.js b/packages/@react-spectrum/combobox/test/ComboBox.test.js index 6f83810d0b6..c246a68da4c 100644 --- a/packages/@react-spectrum/combobox/test/ComboBox.test.js +++ b/packages/@react-spectrum/combobox/test/ComboBox.test.js @@ -11,7 +11,7 @@ */ jest.mock('@react-aria/live-announcer'); -import {act, fireEvent, pointerMap, render, screen, simulateDesktop, simulateMobile, triggerPress, waitFor, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, screen, simulateDesktop, simulateMobile, waitFor, within} from '@react-spectrum/test-utils'; import {announce} from '@react-aria/live-announcer'; import {Button} from '@react-spectrum/button'; import {chain} from '@react-aria/utils'; @@ -330,7 +330,7 @@ describe('ComboBox', function () { expect(onOpenChange).not.toHaveBeenCalled(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -356,6 +356,7 @@ describe('ComboBox', function () { expect(combobox.value).toBe('Blargh'); expect(onOpenChange).not.toHaveBeenCalled(); expect(onFocus).toHaveBeenCalled(); + expect(onInputChange).not.toHaveBeenCalled(); fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); @@ -365,16 +366,18 @@ describe('ComboBox', function () { expect(queryByRole('listbox')).toBeNull(); expect(onOpenChange).not.toHaveBeenCalled(); + expect(onInputChange).not.toHaveBeenCalled(); let button = getByRole('button'); - triggerPress(button); + // user event click on the button actually makes focus leave the combobox + // so onInputChange will fire + await user.click(button); act(() => { jest.runAllTimers(); }); expect(queryByRole('listbox')).toBeNull(); expect(onOpenChange).not.toHaveBeenCalled(); - expect(onInputChange).not.toHaveBeenCalled(); }); it('features default behavior of completionMode suggest and menuTrigger input', async function () { @@ -455,12 +458,12 @@ describe('ComboBox', function () { testComboBoxOpen(combobox, button, listbox); }); - it('opens menu when combobox is focused by clicking button', function () { + it('opens menu when combobox is focused by clicking button', async function () { let {getByRole} = renderComboBox({menuTrigger: 'focus'}); let button = getByRole('button'); let combobox = getByRole('combobox'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -473,7 +476,7 @@ describe('ComboBox', function () { }); describe('button click', function () { - it('keeps focus within the textfield after opening the menu', function () { + it('keeps focus within the textfield after opening the menu', async function () { let {getByRole, queryByRole} = renderComboBox(); let button = getByRole('button'); @@ -483,7 +486,7 @@ describe('ComboBox', function () { act(() => { combobox.focus(); }); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -492,7 +495,7 @@ describe('ComboBox', function () { expect(listbox).toBeTruthy(); expect(document.activeElement).toBe(combobox); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -500,12 +503,12 @@ describe('ComboBox', function () { expect(queryByRole('listbox')).toBeNull(); }); - it('doesn\'t focus first item if there are items loaded', function () { + it('doesn\'t focus first item if there are items loaded', async function () { let {getByRole} = renderComboBox(); let button = getByRole('button'); let combobox = getByRole('combobox'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -552,7 +555,7 @@ describe('ComboBox', function () { act(() => { combobox.focus(); }); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -568,7 +571,7 @@ describe('ComboBox', function () { expect(combobox.value).toBe('One'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -577,7 +580,7 @@ describe('ComboBox', function () { expect(combobox).not.toHaveAttribute('aria-activedescendant'); }); - it('shows all items', function () { + it('shows all items', async function () { let {getByRole, queryByRole} = renderComboBox({defaultInputValue: 'gibberish'}); let button = getByRole('button'); @@ -587,7 +590,7 @@ describe('ComboBox', function () { act(() => { combobox.focus(); }); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -743,7 +746,7 @@ describe('ComboBox', function () { expect(onOpenChange).not.toHaveBeenCalled(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -771,12 +774,12 @@ describe('ComboBox', function () { }); }); describe('showing menu', function () { - it('doesn\'t moves to selected key', function () { + it('doesn\'t moves to selected key', async function () { let {getByRole} = renderComboBox({selectedKey: '2'}); let button = getByRole('button'); let combobox = getByRole('combobox'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -821,12 +824,12 @@ describe('ComboBox', function () { expect(combobox).not.toHaveAttribute('aria-activedescendant'); }); - it('allows the user to navigate the menu via arrow keys', function () { + it('allows the user to navigate the menu via arrow keys', async function () { let {getByRole} = renderComboBox(); let button = getByRole('button'); let combobox = getByRole('combobox'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -853,13 +856,13 @@ describe('ComboBox', function () { expect(combobox).toHaveAttribute('aria-activedescendant', items[0].id); }); - it('allows the user to select an item via Enter', function () { + it('allows the user to select an item via Enter', async function () { let {getByRole, queryByRole} = renderComboBox(); let button = getByRole('button'); let combobox = getByRole('combobox'); expect(combobox.value).toBe(''); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -923,7 +926,7 @@ describe('ComboBox', function () { expect(onInputChange).toHaveBeenLastCalledWith('Two'); }); - it('resets input text if reselecting a selected option with click', function () { + it('resets input text if reselecting a selected option with click', async function () { let {getByRole, queryByRole} = renderComboBox({defaultSelectedKey: '2'}); let combobox = getByRole('combobox'); @@ -940,7 +943,7 @@ describe('ComboBox', function () { let items = within(listbox).getAllByRole('option'); expect(items.length).toBe(1); - triggerPress(items[0]); + await user.click(items[0]); act(() => jest.runAllTimers()); expect(queryByRole('listbox')).toBeNull(); @@ -1047,10 +1050,10 @@ describe('ComboBox', function () { ${'uncontrolled items (static items)'} | ${ExampleComboBox} ${'controlled items'} | ${ControlledItemsComboBox} `('$Name ComboBox', ({Name, Component}) => { - it('displays all items when opened via trigger button', function () { + it('displays all items when opened via trigger button', async function () { let {getByRole} = render(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -1064,7 +1067,7 @@ describe('ComboBox', function () { } }); - it('displays all items when opened via arrow keys', function () { + it('displays all items when opened via arrow keys', async function () { let {getByRole, queryByRole} = render(); let combobox = getByRole('combobox'); let button = getByRole('button'); @@ -1083,7 +1086,7 @@ describe('ComboBox', function () { expect(items).toHaveLength(1); } - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -1131,7 +1134,7 @@ describe('ComboBox', function () { act(() => { combobox.focus(); }); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -1197,7 +1200,7 @@ describe('ComboBox', function () { act(() => { combobox.focus(); }); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -1224,11 +1227,11 @@ describe('ComboBox', function () { }); }); - it('works with SSR', () => { + it('works with SSR', async () => { let {getByRole} = render(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); @@ -1299,7 +1302,7 @@ describe('ComboBox', function () { let listbox = getByRole('listbox'); let items = within(listbox).getAllByRole('option'); - triggerPress(items[1]); + await user.click(items[1]); act(() => { jest.runAllTimers(); }); @@ -1757,7 +1760,7 @@ describe('ComboBox', function () { expect(combobox.value).toBe(''); }); - it('input field doesn\'t lose focus when user mouse downs on a menu item', function () { + it('input field doesn\'t lose focus when user mouse downs on a menu item', async function () { let {getByRole} = renderComboBox({}); let combobox = getByRole('combobox'); let button = getByRole('button'); @@ -1765,7 +1768,7 @@ describe('ComboBox', function () { act(() => { combobox.focus(); }); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -1826,7 +1829,7 @@ describe('ComboBox', function () { act(() => { combobox.focus(); }); - triggerPress(comboboxButton); + await user.click(comboboxButton); act(() => { jest.runAllTimers(); }); @@ -2005,7 +2008,7 @@ describe('ComboBox', function () { act(() => { jest.runAllTimers(); }); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -2030,13 +2033,13 @@ describe('ComboBox', function () { expect(items[0]).not.toHaveAttribute('aria-selected', 'true'); }); - it('when inputValue is controlled', function () { + it('when inputValue is controlled', async function () { let {getByRole, rerender} = render(); let combobox = getByRole('combobox'); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -2162,7 +2165,7 @@ describe('ComboBox', function () { expect(onLoadMore).toHaveBeenCalledTimes(0); // open menu - triggerPress(button); + await user.click(button); // use async act to resolve initial load await act(async () => { // advance to open state from Transition @@ -2209,7 +2212,7 @@ describe('ComboBox', function () { expect(onLoadMore).toHaveBeenCalledTimes(0); // open menu - triggerPress(button); + await user.click(button); // use async act to resolve initial load await act(async () => { // advance to open state from Transition @@ -2247,7 +2250,7 @@ describe('ComboBox', function () { clientHeightSpy.mockRestore(); clientHeightSpy = jest.spyOn(window.HTMLElement.prototype, 'clientHeight', 'get').mockImplementationOnce(() => 0).mockImplementation(() => 40); // reopen menu - triggerPress(button); + await user.click(button); await act(async () => { // advance to open state from Transition jest.advanceTimersToNextTimer(); @@ -2277,7 +2280,7 @@ describe('ComboBox', function () { let combobox = getByRole('combobox'); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -2354,7 +2357,7 @@ describe('ComboBox', function () { act(() => { combobox.focus(); }); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -2385,7 +2388,7 @@ describe('ComboBox', function () { act(() => { combobox.focus(); }); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -2414,7 +2417,7 @@ describe('ComboBox', function () { let combobox = getByRole('combobox'); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -2474,7 +2477,7 @@ describe('ComboBox', function () { let combobox = getByRole('combobox'); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -2548,7 +2551,7 @@ describe('ComboBox', function () { let combobox = getByRole('combobox'); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -2615,11 +2618,11 @@ describe('ComboBox', function () { ${'controlled value and key'} | ${ControlledValueKeyComboBox} `('$Name ComboBox', ({Name, Component}) => { describe('blur and commit flows', function () { - it('should reset the input text and close the menu on committing a previously selected option', () => { + it('should reset the input text and close the menu on committing a previously selected option', async () => { let {getByRole, queryByRole} = render(); let combobox = getByRole('combobox'); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -2629,7 +2632,7 @@ describe('ComboBox', function () { let items = within(listbox).getAllByRole('option'); expect(items.length).toBe(3); - triggerPress(items[0]); + await user.click(items[0]); act(() => { jest.runAllTimers(); }); @@ -2678,7 +2681,7 @@ describe('ComboBox', function () { expect(onOpenChange).toHaveBeenLastCalledWith(false, undefined); } - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -2732,7 +2735,7 @@ describe('ComboBox', function () { } let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -2757,7 +2760,7 @@ describe('ComboBox', function () { expect(listbox).toBeVisible(); let items = within(listbox).getAllByRole('option'); - triggerPress(items[0]); + await user.click(items[0]); act(() => { jest.runAllTimers(); }); @@ -2866,7 +2869,7 @@ describe('ComboBox', function () { expect(listbox).toBeVisible(); let items = within(listbox).getAllByRole('option'); - triggerPress(items[0]); + await user.click(items[0]); act(() => { jest.runAllTimers(); }); @@ -2933,7 +2936,7 @@ describe('ComboBox', function () { expect(listbox).toBeVisible(); let items = within(listbox).getAllByRole('option'); - triggerPress(items[0]); + await user.click(items[0]); act(() => { jest.runAllTimers(); }); @@ -2960,11 +2963,11 @@ describe('ComboBox', function () { }); }); - it('updates the list of items when items update', function () { + it('updates the list of items when items update', async function () { let {getByRole, rerender} = render(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -2995,7 +2998,7 @@ describe('ComboBox', function () { expect(items[2].textContent).toBe('Item 3'); }); - it('updates the list of items when items update (items provided by map)', function () { + it('updates the list of items when items update (items provided by map)', async function () { function ComboBoxWithMap(props) { let defaultItems = initialFilterItems; let { @@ -3018,7 +3021,7 @@ describe('ComboBox', function () { let combobox = getByRole('combobox'); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -3032,7 +3035,7 @@ describe('ComboBox', function () { expect(items[1].textContent).toBe('Kangaroo'); expect(items[2].textContent).toBe('Snake'); - triggerPress(items[0]); + await user.click(items[0]); act(() => { jest.runAllTimers(); }); @@ -3077,7 +3080,7 @@ describe('ComboBox', function () { act(() => { combobox.focus(); }); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -3113,7 +3116,7 @@ describe('ComboBox', function () { expect(items[1]).toHaveTextContent('Two'); expect(items[1]).not.toHaveAttribute('aria-selected', 'true'); - triggerPress(items[0]); + await user.click(items[0]); act(() => { jest.runAllTimers(); }); @@ -3125,7 +3128,7 @@ describe('ComboBox', function () { expect(onSelectionChange).toHaveBeenCalledTimes(1); expect(onSelectionChange).toHaveBeenCalledWith('1'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -3149,7 +3152,7 @@ describe('ComboBox', function () { expect(onSelectionChange).toHaveBeenCalledWith(null); }); - it('supports defaultSelectedKey and defaultInputValue (matching)', function () { + it('supports defaultSelectedKey and defaultInputValue (matching)', async function () { let {getByRole} = renderComboBox({defaultSelectedKey: '2', defaultInputValue: 'Two'}); let combobox = getByRole('combobox'); let button = getByRole('button'); @@ -3158,7 +3161,7 @@ describe('ComboBox', function () { act(() => { combobox.focus(); }); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -3171,7 +3174,7 @@ describe('ComboBox', function () { expect(items[1]).toHaveAttribute('aria-selected', 'true'); }); - it('should keep defaultInputValue if it doesn\'t match defaultSelectedKey', function () { + it('should keep defaultInputValue if it doesn\'t match defaultSelectedKey', async function () { let {getByRole} = renderComboBox({defaultSelectedKey: '2', defaultInputValue: 'One'}); let combobox = getByRole('combobox'); expect(combobox.value).toBe('One'); @@ -3185,13 +3188,13 @@ describe('ComboBox', function () { let items = within(listbox).getAllByRole('option'); expect(items).toHaveLength(3); - triggerPress(items[2]); + await user.click(items[2]); act(() => jest.runAllTimers()); expect(combobox.value).toBe('Three'); }); - it('defaultInputValue should not set selected item', function () { + it('defaultInputValue should not set selected item', async function () { let {getByRole} = renderComboBox({defaultInputValue: 'Two'}); let combobox = getByRole('combobox'); let button = getByRole('button'); @@ -3200,7 +3203,7 @@ describe('ComboBox', function () { act(() => { combobox.focus(); }); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -3213,7 +3216,7 @@ describe('ComboBox', function () { expect(items[1]).toHaveAttribute('aria-selected', 'false'); }); - it('defaultSelectedKey should set input value', function () { + it('defaultSelectedKey should set input value', async function () { let {getByRole} = renderComboBox({defaultSelectedKey: '2'}); let combobox = getByRole('combobox'); let button = getByRole('button'); @@ -3222,7 +3225,7 @@ describe('ComboBox', function () { act(() => { combobox.focus(); }); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -3235,7 +3238,7 @@ describe('ComboBox', function () { expect(items[1]).toHaveAttribute('aria-selected', 'true'); }); - it('should close the menu if user clicks on a already selected item', function () { + it('should close the menu if user clicks on a already selected item', async function () { let {getByRole, queryByRole} = renderComboBox({defaultSelectedKey: '2'}); let combobox = getByRole('combobox'); let button = getByRole('button'); @@ -3244,7 +3247,7 @@ describe('ComboBox', function () { act(() => { combobox.focus(); }); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -3255,7 +3258,7 @@ describe('ComboBox', function () { expect(items).toHaveLength(3); expect(onOpenChange).toHaveBeenCalledTimes(1); - triggerPress(items[1]); + await user.click(items[1]); act(() => { jest.runAllTimers(); }); @@ -3268,7 +3271,7 @@ describe('ComboBox', function () { }); describe('combobox with sections', function () { - it('supports rendering sections', function () { + it('supports rendering sections', async function () { let {getByRole, queryByRole, getByText} = renderSectionComboBox(); let combobox = getByRole('combobox'); @@ -3340,7 +3343,7 @@ describe('ComboBox', function () { expect(onSelectionChange).toHaveBeenCalledTimes(1); expect(onSelectionChange).toHaveBeenCalledWith('4'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -3358,14 +3361,14 @@ describe('ComboBox', function () { expect(groups[1]).toHaveAttribute('aria-labelledby', getByText('Section Two').id); }); - it('sections are not valid selectable values', function () { + it('sections are not valid selectable values', async function () { let {getByRole} = renderSectionComboBox({selectedKey: 'section 1'}); let combobox = getByRole('combobox'); let button = getByRole('button'); expect(combobox.value).toBe(''); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -3451,7 +3454,7 @@ describe('ComboBox', function () { jest.runAllTimers(); }); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -3459,14 +3462,14 @@ describe('ComboBox', function () { expect(combobox).toHaveAttribute('value', ''); } - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); listbox = getByRole('listbox'); let items = within(listbox).getAllByRole('option'); - triggerPress(items[1]); + await user.click(items[1]); act(() => { jest.runAllTimers(); }); @@ -3531,7 +3534,7 @@ describe('ComboBox', function () { expect(queryByRole('progressbar')).toBeNull(); }); - it('combobox should not render a loading circle until a delay of 500ms passes (loadingState: loading)', function () { + it('combobox should not render a loading circle until a delay of 500ms passes (loadingState: loading)', async function () { let {getByRole, queryByRole} = renderComboBox({loadingState: 'loading'}); let combobox = getByRole('combobox'); @@ -3543,14 +3546,14 @@ describe('ComboBox', function () { let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); expect(() => within(combobox).getByRole('progressbar')).toBeTruthy(); }); - it('combobox should not render a loading circle until a delay of 500ms passes and the menu is open (loadingState: filtering)', function () { + it('combobox should not render a loading circle until a delay of 500ms passes and the menu is open (loadingState: filtering)', async function () { let {getByRole, queryByRole} = renderComboBox({loadingState: 'filtering'}); let combobox = getByRole('combobox'); @@ -3559,20 +3562,20 @@ describe('ComboBox', function () { let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); expect(() => within(combobox).getByRole('progressbar')).toBeTruthy(); }); - it('combobox should hide the loading circle when loadingState changes to a non-loading state', function () { + it('combobox should hide the loading circle when loadingState changes to a non-loading state', async function () { let {getByRole, queryByRole, rerender} = render(); let combobox = getByRole('combobox'); let button = getByRole('button'); expect(queryByRole('progressbar')).toBeNull(); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -3585,13 +3588,13 @@ describe('ComboBox', function () { expect(queryByRole('progressbar')).toBeNull(); }); - it('combobox should hide the loading circle when if the menu closes', function () { + it('combobox should hide the loading circle when if the menu closes', async function () { let {getByRole, queryByRole} = render(); let combobox = getByRole('combobox'); let button = getByRole('button'); expect(queryByRole('progressbar')).toBeNull(); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -3600,7 +3603,7 @@ describe('ComboBox', function () { expect(listbox).toBeVisible(); expect(() => within(combobox).getByRole('progressbar')).toBeTruthy(); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -3653,7 +3656,7 @@ describe('ComboBox', function () { ${'filtering'} | ${null} ${'loading'} | ${'invalid'} ${'filtering'} | ${'invalid'} - `('should render the loading swirl in the input field when loadingState="$LoadingState" and validationState="$ValidationState"', ({LoadingState, ValidationState}) => { + `('should render the loading swirl in the input field when loadingState="$LoadingState" and validationState="$ValidationState"', async ({LoadingState, ValidationState}) => { let {getByRole} = renderComboBox({loadingState: LoadingState, validationState: ValidationState}); let combobox = getByRole('combobox'); let button = getByRole('button'); @@ -3666,7 +3669,7 @@ describe('ComboBox', function () { // validation icon should not be present expect(within(combobox).queryByRole('img', {hidden: true})).toBeNull(); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -3680,13 +3683,13 @@ describe('ComboBox', function () { expect(within(listbox).queryByRole('progressbar')).toBeNull(); }); - it('should render the loading swirl in the listbox when loadingState="loadingMore"', function () { + it('should render the loading swirl in the listbox when loadingState="loadingMore"', async function () { let {getByRole, queryByRole} = renderComboBox({loadingState: 'loadingMore'}); let button = getByRole('button'); expect(queryByRole('progressbar')).toBeNull(); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -3699,7 +3702,7 @@ describe('ComboBox', function () { expect(progressSpinner).toHaveAttribute('aria-label', 'Loading more…'); }); - it('should render "Loading..." placeholder in menu when loadingState="loading" and no items present', function () { + it('should render "Loading..." placeholder in menu when loadingState="loading" and no items present', async function () { let {getByRole} = render( @@ -3710,7 +3713,7 @@ describe('ComboBox', function () { let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -3802,11 +3805,11 @@ describe('ComboBox', function () { expect(button).toHaveAttribute('aria-labelledby', `${getByText('Test').id} label-id ${getByText('Two').id}`); }); - it('readonly combobox should not open on press', function () { + it('readonly combobox should not open on press', async function () { let {getByRole, getByTestId} = renderComboBox({isReadOnly: true}); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -3815,11 +3818,11 @@ describe('ComboBox', function () { expect(() => getByTestId('tray')).toThrow(); }); - it('opening the tray autofocuses the tray input', function () { + it('opening the tray autofocuses the tray input', async function () { let {getByRole, getByTestId} = renderComboBox(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -3834,12 +3837,12 @@ describe('ComboBox', function () { testComboBoxTrayOpen(trayInput, tray, listbox); }); - it('closing the tray autofocuses the button', function () { + it('closing the tray autofocuses the button', async function () { let {getByRole, getByTestId, queryByTestId} = renderComboBox(); let button = getByRole('button'); + await user.click(button); act(() => { - triggerPress(button); jest.runAllTimers(); }); @@ -3862,7 +3865,7 @@ describe('ComboBox', function () { let {getByRole, getByTestId} = renderComboBox(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -3889,11 +3892,11 @@ describe('ComboBox', function () { expect(tray.getAttribute('style')).toBe(style); }); - it('up/down arrows still traverse the items in the tray', function () { + it('up/down arrows still traverse the items in the tray', async function () { let {getByRole, getByTestId} = renderComboBox(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -3936,7 +3939,7 @@ describe('ComboBox', function () { let {getByRole, getByTestId} = renderComboBox(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -3974,7 +3977,7 @@ describe('ComboBox', function () { let {getByRole, getByTestId} = renderComboBox(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -4000,9 +4003,7 @@ describe('ComboBox', function () { let clearButton = within(tray).getByLabelText('Clear'); expect(clearButton.tagName).toBe('DIV'); expect(clearButton).not.toHaveAttribute('tabIndex'); - act(() => { - triggerPress(clearButton); - }); + await user.click(clearButton); act(() => { jest.runAllTimers(); @@ -4016,7 +4017,7 @@ describe('ComboBox', function () { let {getByRole, getByTestId} = renderComboBox(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -4053,11 +4054,11 @@ describe('ComboBox', function () { expect(() => within(tray).getByText('No results')).toThrow(); }); - it('user can select options by pressing them', function () { + it('user can select options by pressing them', async function () { let {getByRole, getByText, getByTestId} = renderComboBox(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -4073,7 +4074,7 @@ describe('ComboBox', function () { let items = within(tray).getAllByRole('option'); - triggerPress(items[1]); + await user.click(items[1]); act(() => { jest.runAllTimers(); }); @@ -4087,7 +4088,7 @@ describe('ComboBox', function () { expect(() => getByTestId('tray')).toThrow(); expect(button).toHaveAttribute('aria-labelledby', `${getByText('Test').id} ${getByText('Two').id}`); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -4103,12 +4104,12 @@ describe('ComboBox', function () { expect(items[1]).toHaveAttribute('aria-selected', 'true'); }); - it('user can select options by focusing them and hitting enter', function () { + it('user can select options by focusing them and hitting enter', async function () { let {getByRole, getByText, getByTestId} = renderComboBox(); let button = getByRole('button'); - act(() => { - triggerPress(button); + await user.click(button); + await act(async () => { jest.runAllTimers(); }); @@ -4144,7 +4145,7 @@ describe('ComboBox', function () { expect(() => getByTestId('tray')).toThrow(); expect(button).toHaveAttribute('aria-labelledby', `${getByText('Test').id} ${getByText('Three').id}`); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -4160,11 +4161,11 @@ describe('ComboBox', function () { expect(items[2]).toHaveAttribute('aria-selected', 'true'); }); - it('input is blurred when the user scrolls the listbox with touch', function () { + it('input is blurred when the user scrolls the listbox with touch', async function () { let {getByRole, getByTestId} = renderComboBox(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -4197,7 +4198,7 @@ describe('ComboBox', function () { let {getByRole, getByText, getByTestId} = renderComboBox({allowsCustomValue: true}); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -4234,14 +4235,14 @@ describe('ComboBox', function () { expect(button).toHaveAttribute('aria-labelledby', `${getByText('Test').id} ${getByText('Bleh').id}`); }); - it('label of the tray input should match label of button', function () { + it('label of the tray input should match label of button', async function () { let {getByRole, getByTestId, getByText} = renderComboBox({selectedKey: '2'}); let button = getByRole('button'); let label = getByText(defaultProps.label); expect(button).toHaveAttribute('aria-labelledby', `${label.id} ${getByText('Two').id}`); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -4253,7 +4254,7 @@ describe('ComboBox', function () { expect(trayInput).toHaveAttribute('aria-labelledby', trayInputLabel.id); }); - it('tray input should recieve the same aria-labelledby as the button if an external label is provided', function () { + it('tray input should recieve the same aria-labelledby as the button if an external label is provided', async function () { let {getByRole, getByTestId, getByText} = render( @@ -4268,7 +4269,7 @@ describe('ComboBox', function () { expect(button).toHaveAttribute('aria-labelledby', `${label.id} ${getByText('Item One').id}`); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -4282,7 +4283,7 @@ describe('ComboBox', function () { expect(trayInput).toHaveAttribute('aria-labelledby', label.id); }); - it('user can open the tray even if there aren\'t any items to show', function () { + it('user can open the tray even if there aren\'t any items to show', async function () { let {getByRole, getByTestId} = render( @@ -4292,7 +4293,7 @@ describe('ComboBox', function () { ); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -4307,11 +4308,11 @@ describe('ComboBox', function () { expect(placeholderText).toBeVisible(); }); - it('combobox tray remains open on blur', function () { + it('combobox tray remains open on blur', async function () { let {getByRole, getByTestId} = renderComboBox({defaultInputValue: 'Blah'}); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -4333,11 +4334,11 @@ describe('ComboBox', function () { expect(trayInput.value).toBe('Blah'); // does not reset on blur }); - it('combobox tray can be closed using the dismiss buttons', function () { + it('combobox tray can be closed using the dismiss buttons', async function () { let {getByRole, getByTestId} = renderComboBox(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -4349,7 +4350,7 @@ describe('ComboBox', function () { expect(dismissButtons[0]).toHaveAttribute('aria-label', 'Dismiss'); expect(dismissButtons[1]).toHaveAttribute('aria-label', 'Dismiss'); - triggerPress(dismissButtons[0]); + await user.click(dismissButtons[0]); act(() => { jest.runAllTimers(); }); @@ -4357,11 +4358,11 @@ describe('ComboBox', function () { expect(() => getByTestId('tray')).toThrow(); }); - it('combobox tray doesn\'t close when tray input is virtually clicked', function () { + it('combobox tray doesn\'t close when tray input is virtually clicked', async function () { let {getByRole, getByTestId} = renderComboBox(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -4419,7 +4420,7 @@ describe('ComboBox', function () { // If there is a selected key and allowCustomValue is false, closing the tray should reset the input value let tree = render(); let button = tree.getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -4434,10 +4435,10 @@ describe('ComboBox', function () { let dismissButtons = within(tray).getAllByRole('button'); switch (Method) { case 'clicking outside tray': - triggerPress(document.body); + await user.click(document.body); break; case 'dismiss button': - triggerPress(dismissButtons[0]); + await user.click(dismissButtons[0]); break; case 'escape key': fireEvent.keyDown(trayInput, {key: 'Escape', code: 27, charCode: 27}); @@ -4458,7 +4459,7 @@ describe('ComboBox', function () { // update the input value to the custom value. If the user closes the tray via escape key, then the input value should be reset and the selected key isn't cleared tree = render(); button = tree.getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -4475,7 +4476,7 @@ describe('ComboBox', function () { // If there is a pre-existing custom value, closing the tray should update the custom value if any changes were made in the tray input tree = render(); button = tree.getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -4485,7 +4486,7 @@ describe('ComboBox', function () { expect(button).toHaveAttribute('aria-labelledby', `${tree.getByText('Test').id} ${tree.getByText('Twor').id}`); }); - it('menutrigger=focus doesn\'t reopen the tray on close', function () { + it('menutrigger=focus doesn\'t reopen the tray on close', async function () { let {getByRole, getByTestId} = renderComboBox({menuTrigger: 'focus'}); let button = getByRole('button'); @@ -4499,7 +4500,7 @@ describe('ComboBox', function () { // menutrigger = focus is inapplicable for mobile ComboBox expect(() => getByTestId('tray')).toThrow(); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -4511,7 +4512,7 @@ describe('ComboBox', function () { act(() => { trayInput.blur(); }); - triggerPress(document.body); + await user.click(document.body); act(() => { jest.runAllTimers(); }); @@ -4525,14 +4526,14 @@ describe('ComboBox', function () { expect(document.activeElement).toBe(button); }); - it('combobox tray doesn\'t open when controlled input value is updated', function () { + it('combobox tray doesn\'t open when controlled input value is updated', async function () { let {getByRole, rerender, getByTestId} = render(); let button = getByRole('button'); act(() => { button.focus(); }); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -4544,7 +4545,7 @@ describe('ComboBox', function () { act(() => { trayInput.blur(); }); - triggerPress(document.body); + await user.click(document.body); act(() => { jest.runAllTimers(); }); @@ -4566,14 +4567,14 @@ describe('ComboBox', function () { expect(() => getByTestId('tray')).toThrow(); }); - it('shows all items when opening the tray', function () { + it('shows all items when opening the tray', async function () { let {getByTestId, getByRole} = renderComboBox({defaultInputValue: 'gibberish'}); let button = getByRole('button'); act(() => { button.focus(); }); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -4616,13 +4617,13 @@ describe('ComboBox', function () { }); describe('isLoading', function () { - it('tray input should render a loading circle after a delay of 500ms if loadingState="filtering"', function () { + it('tray input should render a loading circle after a delay of 500ms if loadingState="filtering"', async function () { let {getByRole, queryByRole, getByTestId, rerender} = render(); let button = getByRole('button'); act(() => {jest.advanceTimersByTime(500);}); expect(queryByRole('progressbar')).toBeNull(); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -4640,13 +4641,13 @@ describe('ComboBox', function () { expect(within(listbox).queryByRole('progressbar')).toBeNull(); }); - it('tray input should hide the loading circle if loadingState is no longer "filtering"', function () { + it('tray input should hide the loading circle if loadingState is no longer "filtering"', async function () { let {getByRole, queryByRole, getByTestId, rerender} = render(); let button = getByRole('button'); act(() => {jest.advanceTimersByTime(500);}); expect(queryByRole('progressbar')).toBeNull(); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -4665,7 +4666,7 @@ describe('ComboBox', function () { let {getByRole, getByTestId, rerender} = render(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -4692,12 +4693,12 @@ describe('ComboBox', function () { ${'filtering'} | ${null} ${'loading'} | ${'invalid'} ${'filtering'} | ${'invalid'} - `('should render the loading swirl in the tray input field when loadingState="$LoadingState" and validationState="$ValidationState"', ({LoadingState, ValidationState}) => { + `('should render the loading swirl in the tray input field when loadingState="$LoadingState" and validationState="$ValidationState"', async ({LoadingState, ValidationState}) => { let {getByRole, getByTestId} = renderComboBox({loadingState: LoadingState, validationState: ValidationState, defaultInputValue: 'O'}); let button = getByRole('button'); act(() => {jest.advanceTimersByTime(500);}); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -4739,13 +4740,13 @@ describe('ComboBox', function () { } }); - it('should render the loading swirl in the listbox when loadingState="loadingMore"', function () { + it('should render the loading swirl in the listbox when loadingState="loadingMore"', async function () { let {getByRole, queryByRole, getByTestId} = renderComboBox({loadingState: 'loadingMore', validationState: 'invalid'}); let button = getByRole('button'); expect(queryByRole('progressbar')).toBeNull(); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -4790,7 +4791,7 @@ describe('ComboBox', function () { }) ); - triggerPress(button); + await user.click(button); await act(async () => { jest.runAllTimers(); }); @@ -5041,11 +5042,11 @@ describe('ComboBox', function () { expect(announce).toHaveBeenLastCalledWith('1 option available.'); }); - it('should announce the number of options available when opening the menu', function () { + it('should announce the number of options available when opening the menu', async function () { let {getByRole} = renderComboBox(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -5893,7 +5894,7 @@ describe('ComboBox', function () { let combobox = tree.getByRole('combobox'); let button = tree.getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -5907,7 +5908,7 @@ describe('ComboBox', function () { expect(items[1]).toHaveAttribute('href', 'https://adobe.com'); if (type === 'mouse') { - triggerPress(items[0]); + await user.click(items[0]); } else { fireEvent.keyDown(combobox, {key: 'Enter'}); fireEvent.keyUp(combobox, {key: 'Enter'}); @@ -5933,14 +5934,14 @@ describe('ComboBox', function () { let combobox = tree.getByRole('combobox'); let button = tree.getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); let listbox = tree.getByRole('listbox'); let items = within(listbox).getAllByRole('option'); - triggerPress(items[0]); + await user.click(items[0]); act(() => { jest.runAllTimers(); @@ -5952,14 +5953,14 @@ describe('ComboBox', function () { navigate.mockReset(); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); listbox = tree.getByRole('listbox'); items = within(listbox).getAllByRole('option'); - triggerPress(items[1]); + await user.click(items[1]); act(() => { jest.runAllTimers(); From 3c1eadfd0670406ef8db9cb5bdfc467eaaf03952 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Fri, 1 Dec 2023 13:08:16 -0800 Subject: [PATCH 07/31] remove triggerPress --- .../test/ContextualHelp.test.js | 18 +- .../datepicker/test/DatePicker.test.js | 76 +++++---- .../datepicker/test/DatePickerBase.test.js | 23 ++- .../datepicker/test/DateRangePicker.test.js | 71 ++++---- .../dialog/test/AlertDialog.test.js | 34 ++-- .../dialog/test/DialogContainer.test.js | 54 +++--- .../dialog/test/DialogTrigger.test.js | 76 ++++----- .../@react-spectrum/form/test/Form.test.js | 6 +- .../@react-spectrum/link/test/Link.test.js | 50 +++--- .../list/test/ListView.test.js | 124 +++++++------- .../list/test/ListViewDnd.test.js | 63 ++++--- .../listbox/test/ListBox.test.js | 75 ++++---- .../menu/test/ActionMenu.test.js | 20 +-- .../@react-spectrum/menu/test/Menu.test.js | 73 ++++---- .../menu/test/MenuTrigger.test.js | 161 +++++++++--------- .../numberfield/test/NumberField.test.js | 98 +++++------ .../overlays/test/Popover.test.js | 6 +- .../picker/test/Picker.test.js | 142 +++++++-------- .../provider/test/Provider.test.tsx | 6 +- .../searchfield/test/SearchField.test.js | 7 +- .../searchwithin/test/SearchWithin.test.js | 14 +- .../table/test/TreeGridTable.test.tsx | 70 ++++---- .../@react-spectrum/tabs/test/Tabs.test.js | 36 ++-- .../@react-spectrum/tag/test/TagGroup.test.js | 12 +- .../@react-spectrum/test-utils/src/events.ts | 9 - .../toast/test/ToastContainer.test.js | 90 +++++----- .../tooltip/test/TooltipTrigger.test.js | 4 +- .../@react-spectrum/utils/test/Slots.test.js | 9 +- 28 files changed, 736 insertions(+), 691 deletions(-) diff --git a/packages/@react-spectrum/contextualhelp/test/ContextualHelp.test.js b/packages/@react-spectrum/contextualhelp/test/ContextualHelp.test.js index 2a622f3cb73..91e71221d10 100644 --- a/packages/@react-spectrum/contextualhelp/test/ContextualHelp.test.js +++ b/packages/@react-spectrum/contextualhelp/test/ContextualHelp.test.js @@ -10,13 +10,14 @@ * governing permissions and limitations under the License. */ -import {act, render, simulateDesktop, triggerPress} from '@react-spectrum/test-utils'; +import {act, pointerMap, render, simulateDesktop} from '@react-spectrum/test-utils'; import {Content, Footer, Header} from '@react-spectrum/view'; import {ContextualHelp} from '../'; import {Link} from '@react-spectrum/link'; import {Provider} from '@react-spectrum/provider'; import React from 'react'; import {theme} from '@react-spectrum/theme-default'; +import userEvent from '@testing-library/user-event'; describe('ContextualHelp', function () { beforeAll(() => { @@ -48,7 +49,8 @@ describe('ContextualHelp', function () { expect(button).toHaveClass('spectrum-ActionButton--quiet'); }); - it('opens a popover', function () { + it('opens a popover', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let {getByRole, queryByRole, getByTestId, getByText} = render( @@ -60,7 +62,7 @@ describe('ContextualHelp', function () { expect(queryByRole('dialog')).toBeNull(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); @@ -75,7 +77,8 @@ describe('ContextualHelp', function () { expect(getByText('Test title')).toBeVisible(); }); - it('renders content', function () { + it('renders content', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let {getByRole, getByText} = render( @@ -86,7 +89,7 @@ describe('ContextualHelp', function () { ); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); @@ -99,7 +102,8 @@ describe('ContextualHelp', function () { expect(content).toBeVisible(); }); - it('renders a link', function () { + it('renders a link', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let {getByRole, getByText} = render( @@ -113,7 +117,7 @@ describe('ContextualHelp', function () { ); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); diff --git a/packages/@react-spectrum/datepicker/test/DatePicker.test.js b/packages/@react-spectrum/datepicker/test/DatePicker.test.js index e2715955f0e..7cfb1eb4ad5 100644 --- a/packages/@react-spectrum/datepicker/test/DatePicker.test.js +++ b/packages/@react-spectrum/datepicker/test/DatePicker.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render as render_, triggerPress, waitFor, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render as render_, waitFor, within} from '@react-spectrum/test-utils'; import {Button} from '@react-spectrum/button'; import {CalendarDate, CalendarDateTime, EthiopicCalendar, getLocalTimeZone, JapaneseCalendar, toCalendarDateTime, today} from '@internationalized/date'; import {DatePicker} from '../'; @@ -225,7 +225,7 @@ describe('DatePicker', function () { expect(onFocusChangeSpy).toHaveBeenCalledTimes(1); expect(onFocusSpy).toHaveBeenCalledTimes(1); - triggerPress(button); + await user.click(button); act(() => jest.runAllTimers()); let dialog = getByRole('dialog'); @@ -256,7 +256,7 @@ describe('DatePicker', function () { expect(onFocusSpy).toHaveBeenCalledTimes(1); }); - it('should open popover and call picker onFocus', function () { + it('should open popover and call picker onFocus', async function () { let {getByRole} = render(); let button = getByRole('button'); @@ -264,7 +264,7 @@ describe('DatePicker', function () { expect(onFocusChangeSpy).not.toHaveBeenCalled(); expect(onFocusSpy).not.toHaveBeenCalled(); - triggerPress(button); + await user.click(button); act(() => jest.runAllTimers()); let dialog = getByRole('dialog'); @@ -282,7 +282,7 @@ describe('DatePicker', function () { expect(onFocusChangeSpy).not.toHaveBeenCalled(); expect(onFocusSpy).not.toHaveBeenCalled(); - triggerPress(button); + await user.click(button); act(() => jest.runAllTimers()); let dialog = getByRole('dialog'); @@ -337,7 +337,7 @@ describe('DatePicker', function () { expect(onKeyUpSpy).toHaveBeenCalledTimes(2); }); - it('should trigger key event in popover and focus/blur/key events are not called', function () { + it('should trigger key event in popover and focus/blur/key events are not called', async function () { let {getByRole} = render(); let button = getByRole('button'); @@ -347,7 +347,7 @@ describe('DatePicker', function () { expect(onFocusChangeSpy).not.toHaveBeenCalled(); expect(onFocusSpy).not.toHaveBeenCalled(); - triggerPress(button); + await user.click(button); let dialog = getByRole('dialog'); expect(dialog).toBeVisible(); @@ -366,7 +366,7 @@ describe('DatePicker', function () { }); describe('calendar popover', function () { - it('should emit onChange when selecting a date in the calendar in controlled mode', function () { + it('should emit onChange when selecting a date in the calendar in controlled mode', async function () { let onChange = jest.fn(); let {getByRole, getAllByRole, queryByLabelText} = render( @@ -378,7 +378,7 @@ describe('DatePicker', function () { expect(getTextValue(combobox)).toBe('2/3/2019'); let button = getByRole('button'); - triggerPress(button); + await user.click(button); let dialog = getByRole('dialog'); expect(dialog).toBeVisible(); @@ -389,15 +389,17 @@ describe('DatePicker', function () { let selected = cells.find(cell => cell.getAttribute('aria-selected') === 'true'); expect(selected.children[0]).toHaveAttribute('aria-label', 'Sunday, February 3, 2019 selected'); - triggerPress(selected.nextSibling.children[0]); + await user.click(selected.nextSibling.children[0]); - expect(dialog).not.toBeInTheDocument(); + await waitFor(() => { + expect(dialog).not.toBeInTheDocument(); + }); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith(new CalendarDate(2019, 2, 4)); expect(getTextValue(combobox)).toBe('2/3/2019'); // controlled }); - it('should emit onChange when selecting a date in the calendar in uncontrolled mode', function () { + it('should emit onChange when selecting a date in the calendar in uncontrolled mode', async function () { let onChange = jest.fn(); let {getByRole, getAllByRole} = render( @@ -409,7 +411,7 @@ describe('DatePicker', function () { expect(getTextValue(combobox)).toBe('2/3/2019'); let button = getByRole('button'); - triggerPress(button); + await user.click(button); let dialog = getByRole('dialog'); expect(dialog).toBeVisible(); @@ -418,15 +420,17 @@ describe('DatePicker', function () { let selected = cells.find(cell => cell.getAttribute('aria-selected') === 'true'); expect(selected.children[0]).toHaveAttribute('aria-label', 'Sunday, February 3, 2019 selected'); - triggerPress(selected.nextSibling.children[0]); + await user.click(selected.nextSibling.children[0]); - expect(dialog).not.toBeInTheDocument(); + await waitFor(() => { + expect(dialog).not.toBeInTheDocument(); + }); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith(new CalendarDate(2019, 2, 4)); expect(getTextValue(combobox)).toBe('2/4/2019'); // uncontrolled }); - it('should display a time field when a CalendarDateTime value is used', function () { + it('should display a time field when a CalendarDateTime value is used', async function () { let onChange = jest.fn(); let {getByRole, getAllByRole, getAllByLabelText} = render( @@ -438,7 +442,7 @@ describe('DatePicker', function () { expect(getTextValue(combobox)).toBe('2/3/2019, 8:45 AM'); let button = getByRole('button'); - triggerPress(button); + await user.click(button); let dialog = getByRole('dialog'); expect(dialog).toBeVisible(); @@ -451,7 +455,7 @@ describe('DatePicker', function () { expect(getTextValue(timeField)).toBe('8:45 AM'); // selecting a date should not close the popover - triggerPress(selected.nextSibling.children[0]); + await user.click(selected.nextSibling.children[0]); expect(dialog).toBeVisible(); expect(onChange).toHaveBeenCalledTimes(1); @@ -474,7 +478,7 @@ describe('DatePicker', function () { expect(getTextValue(combobox)).toBe('2/4/2019, 9:45 AM'); }); - it('should not throw error when deleting values from time field when CalendarDateTime value is used', function () { + it('should not throw error when deleting values from time field when CalendarDateTime value is used', async function () { let onChange = jest.fn(); let {getByRole, getAllByRole, getAllByLabelText} = render( @@ -486,7 +490,7 @@ describe('DatePicker', function () { expect(getTextValue(combobox)).toBe('2/3/2019, 10:45 AM'); let button = getByRole('button'); - triggerPress(button); + await user.click(button); let dialog = getByRole('dialog'); expect(dialog).toBeVisible(); @@ -499,7 +503,7 @@ describe('DatePicker', function () { expect(getTextValue(timeField)).toBe('10:45 AM'); // selecting a date should not close the popover - triggerPress(selected.nextSibling.children[0]); + await user.click(selected.nextSibling.children[0]); expect(dialog).toBeVisible(); expect(onChange).toHaveBeenCalledTimes(1); @@ -523,7 +527,7 @@ describe('DatePicker', function () { expect(getTextValue(combobox)).toBe('2/4/2019, 1:45 AM'); }); - it('should fire onChange until both date and time are selected', function () { + it('should fire onChange until both date and time are selected', async function () { let onChange = jest.fn(); let {getByRole, getAllByRole, getAllByLabelText} = render( @@ -536,7 +540,7 @@ describe('DatePicker', function () { expectPlaceholder(combobox, 'mm/dd/yyyy, ––:–– AM'); let button = getByRole('button'); - triggerPress(button); + await user.click(button); let dialog = getByRole('dialog'); expect(dialog).toBeVisible(); @@ -550,7 +554,7 @@ describe('DatePicker', function () { // selecting a date should not close the popover let todayCell = cells.find(cell => cell.firstChild.getAttribute('aria-label')?.startsWith('Today')); - triggerPress(todayCell.firstChild); + await user.click(todayCell.firstChild); expect(todayCell).toHaveAttribute('aria-selected', 'true'); @@ -615,7 +619,7 @@ describe('DatePicker', function () { expectPlaceholder(combobox, 'mm/dd/yyyy, ––:–– AM'); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => jest.runAllTimers()); let dialog = getByRole('dialog'); @@ -623,7 +627,7 @@ describe('DatePicker', function () { let cells = getAllByRole('gridcell'); let todayCell = cells.find(cell => cell.firstChild.getAttribute('aria-label')?.startsWith('Today')); - triggerPress(todayCell.firstChild); + await user.click(todayCell.firstChild); expect(todayCell).toHaveAttribute('aria-selected', 'true'); expect(onChange).not.toHaveBeenCalled(); @@ -650,7 +654,7 @@ describe('DatePicker', function () { expectPlaceholder(combobox, 'mm/dd/yyyy, ––:–– AM'); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => jest.runAllTimers()); let dialog = getByRole('dialog'); @@ -763,7 +767,7 @@ describe('DatePicker', function () { let cells = getAllByRole('gridcell'); let timeField = getAllByLabelText('Time')[0]; let todayCell = cells.find(cell => cell.firstChild.getAttribute('aria-label')?.startsWith('Today')); - triggerPress(todayCell.firstChild); + await user.click(todayCell.firstChild); expect(todayCell).toHaveAttribute('aria-selected', 'true'); @@ -792,10 +796,10 @@ describe('DatePicker', function () { expectPlaceholder(combobox, formatter.format(value.toDate(getLocalTimeZone()))); let clear = getAllByRole('button')[1]; - triggerPress(clear); + await user.click(clear); expectPlaceholder(combobox, 'mm/dd/yyyy, ––:–– AM'); - triggerPress(button); + await user.click(button); cells = getAllByRole('gridcell'); let selected = cells.find(cell => cell.getAttribute('aria-selected') === 'true'); expect(selected).toBeUndefined(); @@ -996,16 +1000,16 @@ describe('DatePicker', function () { }); describe('focus management', function () { - it('should focus the first segment on mouse down in the field', function () { + it('should focus the first segment on mouse down in the field', async function () { let {getAllByRole, getByTestId} = render(); let field = getByTestId('date-field'); let segments = getAllByRole('spinbutton'); - triggerPress(field); + await user.click(field); expect(segments[0]).toHaveFocus(); }); - it('should focus the first unfilled segment on mouse down in the field', function () { + it('should focus the first unfilled segment on mouse down in the field', async function () { let {getAllByRole, getByTestId} = render(); let field = getByTestId('date-field'); let segments = getAllByRole('spinbutton'); @@ -1015,16 +1019,16 @@ describe('DatePicker', function () { fireEvent.keyUp(segments[0], {key: 'ArrowUp'}); expect(segments[0]).toHaveFocus(); - triggerPress(field); + await user.click(field); expect(segments[1]).toHaveFocus(); }); - it('should focus the last segment on mouse down in the field with a value', function () { + it('should focus the last segment on mouse down in the field with a value', async function () { let {getAllByRole, getByTestId} = render(); let field = getByTestId('date-field'); let segments = getAllByRole('spinbutton'); - triggerPress(field); + await user.click(field); expect(segments[2]).toHaveFocus(); }); diff --git a/packages/@react-spectrum/datepicker/test/DatePickerBase.test.js b/packages/@react-spectrum/datepicker/test/DatePickerBase.test.js index 5543810eb74..a4541d2586a 100644 --- a/packages/@react-spectrum/datepicker/test/DatePickerBase.test.js +++ b/packages/@react-spectrum/datepicker/test/DatePickerBase.test.js @@ -10,12 +10,13 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, installPointerEvent, render as render_, simulateDesktop, triggerPress, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, installPointerEvent, pointerMap, render as render_, simulateDesktop, within} from '@react-spectrum/test-utils'; import {CalendarDate, parseZonedDateTime} from '@internationalized/date'; import {DatePicker, DateRangePicker} from '../'; import {Provider} from '@react-spectrum/provider'; import React from 'react'; import {theme} from '@react-spectrum/theme-default'; +import userEvent from '@testing-library/user-event'; function pointerEvent(type, opts) { let evt = new Event(type, {bubbles: true, cancelable: true}); @@ -167,11 +168,12 @@ describe('DatePickerBase', function () { Name | Component ${'DatePicker'} | ${DatePicker} ${'DateRangePicker'} | ${DateRangePicker} - `('$Name should focus placeholderValue in calendar', ({Component}) => { + `('$Name should focus placeholderValue in calendar', async ({Component}) => { + let user = userEvent.setup({delay: null, pointerMap}); let {getByRole} = render(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); let grid = getByRole('grid'); expect(grid).toHaveAttribute('aria-label', 'June 2019'); @@ -182,11 +184,12 @@ describe('DatePickerBase', function () { Name | Component | props ${'DatePicker'} | ${DatePicker} | ${{defaultValue: new CalendarDate(2019, 7, 5)}} ${'DateRangePicker'} | ${DateRangePicker} | ${{defaultValue: {start: new CalendarDate(2019, 7, 5), end: new CalendarDate(2019, 7, 10)}}} - `('$Name should focus selected date over placeholderValue', ({Component, props}) => { + `('$Name should focus selected date over placeholderValue', async ({Component, props}) => { + let user = userEvent.setup({delay: null, pointerMap}); let {getByRole} = render(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); let grid = getByRole('grid'); expect(grid).toHaveAttribute('aria-label', 'July 2019'); @@ -239,7 +242,8 @@ describe('DatePickerBase', function () { Name | Component ${'DatePicker'} | ${DatePicker} ${'DateRangePicker'} | ${DateRangePicker} - `('$Name should open a calendar popover when clicking the button', ({Component}) => { + `('$Name should open a calendar popover when clicking the button', async ({Component}) => { + let user = userEvent.setup({delay: null, pointerMap}); let {getAllByRole} = render( @@ -262,7 +266,7 @@ describe('DatePickerBase', function () { expect(button).toHaveAttribute('aria-expanded', 'false'); expect(button).not.toHaveAttribute('aria-controls'); - triggerPress(button); + await user.click(button); let dialog = getAllByRole('dialog')[0]; expect(dialog).toBeVisible(); @@ -373,7 +377,8 @@ describe('DatePickerBase', function () { Name | Component | props ${'DatePicker'} | ${DatePicker} | ${{defaultValue: new CalendarDate(2021, 10, 3)}} ${'DateRangePicker'} | ${DateRangePicker} | ${{defaultValue: {start: new CalendarDate(2021, 10, 3), end: new CalendarDate(2021, 10, 4)}}} - `('$Name should pass validationState and errorMessage to calendar', ({Component, props}) => { + `('$Name should pass validationState and errorMessage to calendar', async ({Component, props}) => { + let user = userEvent.setup({delay: null, pointerMap}); let {getAllByRole} = render( @@ -385,7 +390,7 @@ describe('DatePickerBase', function () { expect(button).toHaveAttribute('aria-expanded', 'false'); expect(button).not.toHaveAttribute('aria-controls'); - triggerPress(button); + await user.click(button); let dialog = getAllByRole('dialog')[0]; let grid = within(dialog).getByRole('grid'); diff --git a/packages/@react-spectrum/datepicker/test/DateRangePicker.test.js b/packages/@react-spectrum/datepicker/test/DateRangePicker.test.js index 0c969a0f7ef..5476004a9c9 100644 --- a/packages/@react-spectrum/datepicker/test/DateRangePicker.test.js +++ b/packages/@react-spectrum/datepicker/test/DateRangePicker.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, getAllByRole as getAllByRoleInContainer, pointerMap, render as render_, triggerPress, waitFor, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, getAllByRole as getAllByRoleInContainer, pointerMap, render as render_, waitFor, within} from '@react-spectrum/test-utils'; import {Button} from '@react-spectrum/button'; import {CalendarDate, CalendarDateTime, getLocalTimeZone, toCalendarDateTime, today} from '@internationalized/date'; import {DateRangePicker} from '../'; @@ -305,7 +305,7 @@ describe('DateRangePicker', function () { expect(onFocusChangeSpy).toHaveBeenCalledTimes(1); expect(onFocusSpy).toHaveBeenCalledTimes(1); - triggerPress(button); + await user.click(button); act(() => jest.runAllTimers()); let dialog = getByRole('dialog'); @@ -336,7 +336,7 @@ describe('DateRangePicker', function () { expect(onFocusSpy).toHaveBeenCalledTimes(1); }); - it('should open popover and call picker onFocus', function () { + it('should open popover and call picker onFocus', async function () { let {getByRole} = render(); let button = getByRole('button'); @@ -344,7 +344,7 @@ describe('DateRangePicker', function () { expect(onFocusChangeSpy).not.toHaveBeenCalled(); expect(onFocusSpy).not.toHaveBeenCalled(); - triggerPress(button); + await user.click(button); act(() => jest.runAllTimers()); let dialog = getByRole('dialog'); @@ -362,7 +362,7 @@ describe('DateRangePicker', function () { expect(onFocusChangeSpy).not.toHaveBeenCalled(); expect(onFocusSpy).not.toHaveBeenCalled(); - triggerPress(button); + await user.click(button); act(() => jest.runAllTimers()); let dialog = getByRole('dialog'); @@ -417,7 +417,7 @@ describe('DateRangePicker', function () { expect(onKeyUpSpy).toHaveBeenCalledTimes(2); }); - it('should trigger key event in popover and focus/blur/key events are not called', function () { + it('should trigger key event in popover and focus/blur/key events are not called', async function () { let {getByRole} = render(); let button = getByRole('button'); @@ -427,7 +427,7 @@ describe('DateRangePicker', function () { expect(onFocusChangeSpy).not.toHaveBeenCalled(); expect(onFocusSpy).not.toHaveBeenCalled(); - triggerPress(button); + await user.click(button); let dialog = getByRole('dialog'); expect(dialog).toBeVisible(); @@ -446,7 +446,7 @@ describe('DateRangePicker', function () { }); describe('calendar popover', function () { - it('should emit onChange when selecting a date range in the calendar in uncontrolled mode', function () { + it('should emit onChange when selecting a date range in the calendar in uncontrolled mode', async function () { let onChange = jest.fn(); let {getByRole, getByTestId, getAllByRole, getByLabelText} = render( @@ -460,7 +460,7 @@ describe('DateRangePicker', function () { expect(getTextValue(endDate)).toBe('5/6/2019'); let button = getByRole('button'); - triggerPress(button); + await user.click(button); let dialog = getByRole('dialog'); expect(dialog).toBeVisible(); @@ -469,17 +469,20 @@ describe('DateRangePicker', function () { let selected = cells.filter(cell => cell.getAttribute('aria-selected') === 'true'); expect(selected[0].children[0]).toHaveAttribute('aria-label', 'Selected Range: Sunday, February 3 to Monday, May 6, 2019, Sunday, February 3, 2019 selected'); - triggerPress(getByLabelText('Sunday, February 10, 2019 selected')); - triggerPress(getByLabelText('Sunday, February 17, 2019')); + await user.click(getByLabelText('Sunday, February 10, 2019 selected')); + await user.click(getByLabelText('Sunday, February 17, 2019')); + act(() => jest.runAllTimers()); - expect(dialog).not.toBeInTheDocument(); + await waitFor(() => { + expect(dialog).not.toBeInTheDocument(); + }); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith({start: new CalendarDate(2019, 2, 10), end: new CalendarDate(2019, 2, 17)}); expect(getTextValue(startDate)).toBe('2/10/2019'); // uncontrolled expect(getTextValue(endDate)).toBe('2/17/2019'); }); - it('should display time fields when a CalendarDateTime value is used', function () { + it('should display time fields when a CalendarDateTime value is used', async function () { let onChange = jest.fn(); let {getByRole, getByTestId, getAllByRole, getByLabelText, getAllByLabelText} = render( @@ -493,7 +496,7 @@ describe('DateRangePicker', function () { expect(getTextValue(endDate)).toBe('5/6/2019, 10:45 AM'); let button = getByRole('button'); - triggerPress(button); + await user.click(button); let dialog = getByRole('dialog'); expect(dialog).toBeVisible(); @@ -509,8 +512,8 @@ describe('DateRangePicker', function () { expect(getTextValue(endTimeField)).toBe('10:45 AM'); // selecting a date should not close the popover - triggerPress(getByLabelText('Sunday, February 10, 2019 selected')); - triggerPress(getByLabelText('Sunday, February 17, 2019')); + await user.click(getByLabelText('Sunday, February 10, 2019 selected')); + await user.click(getByLabelText('Sunday, February 17, 2019')); expect(dialog).toBeVisible(); expect(onChange).toHaveBeenCalledTimes(1); @@ -551,7 +554,7 @@ describe('DateRangePicker', function () { expect(getTextValue(endDate)).toBe('2/17/2019, 11:45 AM'); }); - it('should not fire onChange until both date range and time range are selected', function () { + it('should not fire onChange until both date range and time range are selected', async function () { let onChange = jest.fn(); let {getByRole, getAllByRole, getByTestId, getAllByLabelText} = render( @@ -566,7 +569,7 @@ describe('DateRangePicker', function () { expectPlaceholder(endDate, 'mm/dd/yyyy, ––:–– AM'); let button = getByRole('button'); - triggerPress(button); + await user.click(button); let dialog = getByRole('dialog'); expect(dialog).toBeVisible(); @@ -583,8 +586,8 @@ describe('DateRangePicker', function () { // selecting a date should not close the popover let enabledCells = cells.filter(cell => !cell.hasAttribute('aria-disabled')); - triggerPress(enabledCells[0].firstChild); - triggerPress(enabledCells[1].firstChild); + await user.click(enabledCells[0].firstChild); + await user.click(enabledCells[1].firstChild); expect(dialog).toBeVisible(); expect(onChange).not.toHaveBeenCalled(); @@ -662,7 +665,7 @@ describe('DateRangePicker', function () { expectPlaceholder(endDate, 'mm/dd/yyyy, ––:–– AM'); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => jest.runAllTimers()); let dialog = getByRole('dialog'); @@ -670,8 +673,8 @@ describe('DateRangePicker', function () { let cells = getAllByRole('gridcell'); let enabledCells = cells.filter(cell => !cell.hasAttribute('aria-disabled')); - triggerPress(enabledCells[0].firstChild); - triggerPress(enabledCells[1].firstChild); + await user.click(enabledCells[0].firstChild); + await user.click(enabledCells[1].firstChild); expect(onChange).not.toHaveBeenCalled(); await user.click(document.body); @@ -701,7 +704,7 @@ describe('DateRangePicker', function () { expectPlaceholder(endDate, 'mm/dd/yyyy, ––:–– AM'); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => jest.runAllTimers()); let dialog = getByRole('dialog'); @@ -749,15 +752,15 @@ describe('DateRangePicker', function () { expectPlaceholder(endDate, 'mm/dd/yyyy, ––:–– AM'); let button = getAllByRole('button')[0]; - triggerPress(button); + await user.click(button); let cells = getAllByRole('gridcell'); let startTimeField = getAllByLabelText('Start time')[0]; let endTimeField = getAllByLabelText('End time')[0]; let enabledCells = cells.filter(cell => !cell.hasAttribute('aria-disabled')); - triggerPress(enabledCells[0].firstChild); - triggerPress(enabledCells[1].firstChild); + await user.click(enabledCells[0].firstChild); + await user.click(enabledCells[1].firstChild); for (let timeField of [startTimeField, endTimeField]) { let hour = within(timeField).getByLabelText('hour,'); @@ -787,11 +790,11 @@ describe('DateRangePicker', function () { expect(getTextValue(endDate).replace(' ', ' ')).toBe(formatter.format(endValue.toDate(getLocalTimeZone()))); let clear = getAllByRole('button')[1]; - triggerPress(clear); + await user.click(clear); expectPlaceholder(startDate, 'mm/dd/yyyy, ––:–– AM'); expectPlaceholder(endDate, 'mm/dd/yyyy, ––:–– AM'); - triggerPress(button); + await user.click(button); cells = getAllByRole('gridcell'); let selected = cells.find(cell => cell.getAttribute('aria-selected') === 'true'); expect(selected).toBeUndefined(); @@ -1083,30 +1086,30 @@ describe('DateRangePicker', function () { }); describe('focus management', function () { - it('should focus the first segment of each field on mouse down', function () { + it('should focus the first segment of each field on mouse down', async function () { let {getByTestId} = render(); let startDate = getByTestId('start-date'); let endDate = getByTestId('end-date'); let startSegments = getAllByRoleInContainer(startDate, 'spinbutton'); let endSegments = getAllByRoleInContainer(endDate, 'spinbutton'); - triggerPress(startDate); + await user.click(startDate); expect(startSegments[0]).toHaveFocus(); act(() => document.activeElement.blur()); - triggerPress(endDate); + await user.click(endDate); expect(endSegments[0]).toHaveFocus(); }); - it('should focus the first segment of the end date on mouse down on the dash', function () { + it('should focus the first segment of the end date on mouse down on the dash', async function () { let {getByTestId} = render(); let rangeDash = getByTestId('date-range-dash'); let startDate = getByTestId('start-date'); let startSegments = getAllByRoleInContainer(startDate, 'spinbutton'); fireEvent(rangeDash, pointerEvent('pointerdown', {pointerId: 1, pointerType: 'mouse'})); - triggerPress(rangeDash); + await user.click(rangeDash); expect(startSegments[0]).toHaveFocus(); }); }); diff --git a/packages/@react-spectrum/dialog/test/AlertDialog.test.js b/packages/@react-spectrum/dialog/test/AlertDialog.test.js index 47ba66c9ea1..6f8a47eb725 100644 --- a/packages/@react-spectrum/dialog/test/AlertDialog.test.js +++ b/packages/@react-spectrum/dialog/test/AlertDialog.test.js @@ -11,13 +11,15 @@ */ import {AlertDialog} from '../'; +import {pointerMap, render} from '@react-spectrum/test-utils'; import {Provider} from '@react-spectrum/provider'; import React from 'react'; -import {render, triggerPress} from '@react-spectrum/test-utils'; import {theme} from '@react-spectrum/theme-default'; +import userEvent from '@testing-library/user-event'; describe('AlertDialog', function () { - it('renders alert dialog with onPrimaryAction', function () { + it('renders alert dialog with onPrimaryAction', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let onPrimaryAction = jest.fn(); let {getByRole} = render( @@ -31,12 +33,13 @@ describe('AlertDialog', function () { expect(document.activeElement).toBe(dialog); let button = getByRole('button'); - triggerPress(button); + await user.click(button); expect(onPrimaryAction).toHaveBeenCalledTimes(1); expect(onPrimaryAction).toHaveBeenCalledWith(); }); - it('renders 2 button alert dialog with onPrimaryAction / onCancel', function () { + it('renders 2 button alert dialog with onPrimaryAction / onCancel', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let onCancelSpy = jest.fn(); let onPrimaryAction = jest.fn(); let {getByRole, getByText} = render( @@ -51,19 +54,20 @@ describe('AlertDialog', function () { expect(document.activeElement).toBe(dialog); let cancelButton = getByText('cancel'); - triggerPress(cancelButton); + await user.click(cancelButton); expect(onPrimaryAction).toHaveBeenCalledTimes(0); expect(onCancelSpy).toHaveBeenCalledTimes(1); expect(onCancelSpy).toHaveBeenCalledWith(); let confirmButton = getByText('confirm'); - triggerPress(confirmButton); + await user.click(confirmButton); expect(onPrimaryAction).toHaveBeenCalledTimes(1); expect(onCancelSpy).toHaveBeenCalledTimes(1); expect(onPrimaryAction).toHaveBeenCalledWith(); }); - it('renders a 3 button alert dialog with onPrimaryAction / onCancel', function () { + it('renders a 3 button alert dialog with onPrimaryAction / onCancel', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let onCancelSpy = jest.fn(); let onPrimaryAction = jest.fn(); let onSecondaryAction = jest.fn(); @@ -81,23 +85,24 @@ describe('AlertDialog', function () { let confirmButton = getByText('confirm'); let secondaryButton = getByText('secondary'); let cancelButton = getByText('cancel'); - triggerPress(secondaryButton); + await user.click(secondaryButton); expect(onSecondaryAction).toHaveBeenCalledTimes(1); expect(onSecondaryAction).toHaveBeenLastCalledWith(); expect(onCancelSpy).toHaveBeenCalledTimes(0); - triggerPress(confirmButton); + await user.click(confirmButton); expect(onPrimaryAction).toHaveBeenCalledTimes(1); expect(onPrimaryAction).toHaveBeenLastCalledWith(); expect(onCancelSpy).toHaveBeenCalledTimes(0); - triggerPress(cancelButton); + await user.click(cancelButton); expect(onPrimaryAction).toHaveBeenCalledTimes(1); expect(onCancelSpy).toHaveBeenCalledTimes(1); expect(onCancelSpy).toHaveBeenLastCalledWith(); }); - it('disable its confirm button', function () { + it('disable its confirm button', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let onPrimaryAction = jest.fn(); let {getByRole, getByText} = render( @@ -111,7 +116,7 @@ describe('AlertDialog', function () { expect(document.activeElement).toBe(dialog); let button = getByText('confirm'); - triggerPress(button); + await user.click(button); expect(onPrimaryAction).toHaveBeenCalledTimes(0); }); @@ -141,7 +146,8 @@ describe('AlertDialog', function () { expect(document.activeElement).toBe(button); }); - it('disable its secondary button', function () { + it('disable its secondary button', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let onPrimaryAction = jest.fn(); let {getByRole, getByText} = render( @@ -155,7 +161,7 @@ describe('AlertDialog', function () { expect(document.activeElement).toBe(dialog); let button = getByText('secondary'); - triggerPress(button); + await user.click(button); expect(onPrimaryAction).toHaveBeenCalledTimes(0); }); diff --git a/packages/@react-spectrum/dialog/test/DialogContainer.test.js b/packages/@react-spectrum/dialog/test/DialogContainer.test.js index 44e0ddad0db..c43dd253e39 100644 --- a/packages/@react-spectrum/dialog/test/DialogContainer.test.js +++ b/packages/@react-spectrum/dialog/test/DialogContainer.test.js @@ -10,11 +10,12 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, render, triggerPress, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; import {DialogContainerExample, MenuExample, NestedDialogContainerExample} from '../stories/DialogContainerExamples'; import {Provider} from '@react-spectrum/provider'; import React from 'react'; import {theme} from '@react-spectrum/theme-default'; +import userEvent from '@testing-library/user-event'; describe('DialogContainer', function () { beforeAll(() => { @@ -25,7 +26,8 @@ describe('DialogContainer', function () { act(() => {jest.runAllTimers();}); }); - it('should open and close a dialog based on controlled state', function () { + it('should open and close a dialog based on controlled state', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let {getByRole, queryByRole} = render( @@ -35,7 +37,7 @@ describe('DialogContainer', function () { let button = getByRole('button'); expect(queryByRole('dialog')).toBeNull(); - triggerPress(button); + await user.click(button); act(() => {jest.runAllTimers();}); let dialog = getByRole('dialog'); @@ -43,13 +45,14 @@ describe('DialogContainer', function () { button = within(dialog).getByText('Confirm'); - triggerPress(button); + await user.click(button); act(() => {jest.runAllTimers();}); expect(queryByRole('dialog')).toBeNull(); }); - it('should support closing a dialog via the Escape key', function () { + it('should support closing a dialog via the Escape key', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let {getByRole, queryByRole} = render( @@ -59,7 +62,7 @@ describe('DialogContainer', function () { let button = getByRole('button'); expect(queryByRole('dialog')).toBeNull(); - triggerPress(button); + await user.click(button); act(() => {jest.runAllTimers();}); let dialog = getByRole('dialog'); @@ -72,7 +75,8 @@ describe('DialogContainer', function () { expect(queryByRole('dialog')).toBeNull(); }); - it('should not close a dialog via the Escape key if isKeyboardDismissDisabled', function () { + it('should not close a dialog via the Escape key if isKeyboardDismissDisabled', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let {getByRole, queryByRole} = render( @@ -82,7 +86,7 @@ describe('DialogContainer', function () { let button = getByRole('button'); expect(queryByRole('dialog')).toBeNull(); - triggerPress(button); + await user.click(button); act(() => {jest.runAllTimers();}); let dialog = getByRole('dialog'); @@ -95,7 +99,8 @@ describe('DialogContainer', function () { expect(getByRole('dialog')).toBeVisible(); }); - it('should not close when clicking outside the dialog by default', function () { + it('should not close when clicking outside the dialog by default', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let {getByRole, queryByRole} = render( @@ -105,18 +110,19 @@ describe('DialogContainer', function () { let button = getByRole('button'); expect(queryByRole('dialog')).toBeNull(); - triggerPress(button); + await user.click(button); act(() => {jest.runAllTimers();}); expect(getByRole('dialog')).toBeVisible(); - triggerPress(document.body); + await user.click(document.body); act(() => {jest.runAllTimers();}); expect(getByRole('dialog')).toBeVisible(); }); - it('should close when clicking outside the dialog when isDismissible', function () { + it('should close when clicking outside the dialog when isDismissible', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let {getByRole, queryByRole} = render( @@ -126,18 +132,19 @@ describe('DialogContainer', function () { let button = getByRole('button'); expect(queryByRole('dialog')).toBeNull(); - triggerPress(button); + await user.click(button); act(() => {jest.runAllTimers();}); expect(getByRole('dialog')).toBeVisible(); - triggerPress(document.body); + await user.click(document.body); act(() => {jest.runAllTimers();}); expect(queryByRole('dialog')).toBeNull(); }); - it('should not close the dialog when a trigger unmounts', function () { + it('should not close the dialog when a trigger unmounts', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let {getByRole, queryByRole} = render( @@ -147,7 +154,7 @@ describe('DialogContainer', function () { let button = getByRole('button'); expect(queryByRole('dialog')).toBeNull(); - triggerPress(button); + await user.click(button); act(() => {jest.runAllTimers();}); expect(queryByRole('dialog')).toBeNull(); @@ -155,7 +162,7 @@ describe('DialogContainer', function () { let menu = getByRole('menu'); let menuitem = within(menu).getByRole('menuitem'); - triggerPress(menuitem); + await user.click(menuitem); act(() => {jest.runAllTimers();}); expect(queryByRole('menu')).toBeNull(); @@ -164,14 +171,15 @@ describe('DialogContainer', function () { let dialog = getByRole('dialog'); button = within(dialog).getByText('Confirm'); - triggerPress(button); + await user.click(button); act(() => {jest.runAllTimers();}); act(() => {jest.runAllTimers();}); expect(queryByRole('dialog')).toBeNull(); }); - it('should be able to have dialogs open dialogs and still restore focus', function () { + it('should be able to have dialogs open dialogs and still restore focus', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let {getByRole} = render( @@ -179,19 +187,19 @@ describe('DialogContainer', function () { ); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => {jest.runAllTimers();}); let menu = getByRole('menu'); let menuitem = within(menu).getAllByRole('menuitem')[0]; - triggerPress(menuitem); + await user.click(menuitem); act(() => {jest.runAllTimers();}); let dialog = getByRole('dialog'); let confirmButton = within(dialog).getByText('Do that'); - triggerPress(confirmButton); + await user.click(confirmButton); act(() => {jest.runAllTimers();}); dialog = getByRole('dialog'); @@ -201,7 +209,7 @@ describe('DialogContainer', function () { let closeButton = getByRole('button', {name: 'Dismiss'}); - triggerPress(closeButton); + await user.click(closeButton); act(() => {jest.runAllTimers();}); act(() => {jest.runAllTimers();}); diff --git a/packages/@react-spectrum/dialog/test/DialogTrigger.test.js b/packages/@react-spectrum/dialog/test/DialogTrigger.test.js index f4025d95ade..3cdf0cc1b27 100644 --- a/packages/@react-spectrum/dialog/test/DialogTrigger.test.js +++ b/packages/@react-spectrum/dialog/test/DialogTrigger.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, simulateDesktop, simulateMobile, triggerPress, waitFor, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, simulateDesktop, simulateMobile, waitFor, within} from '@react-spectrum/test-utils'; import {ActionButton, Button} from '@react-spectrum/button'; import {ButtonGroup} from '@react-spectrum/buttongroup'; import {Content} from '@react-spectrum/view'; @@ -58,7 +58,7 @@ describe('DialogTrigger', function () { } }); - it('should trigger a modal by default', function () { + it('should trigger a modal by default', async function () { let {queryByRole, getByRole, getByTestId} = render( @@ -71,7 +71,7 @@ describe('DialogTrigger', function () { expect(queryByRole('dialog')).toBeNull(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); @@ -84,7 +84,7 @@ describe('DialogTrigger', function () { expect(modal).toBeVisible(); }); - it('should trigger a tray', function () { + it('should trigger a tray', async function () { let {getByRole, queryByRole, getByTestId} = render( @@ -97,7 +97,7 @@ describe('DialogTrigger', function () { expect(queryByRole('dialog')).toBeNull(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); @@ -110,7 +110,7 @@ describe('DialogTrigger', function () { expect(tray).toBeVisible(); }); - it('should trigger a popover', function () { + it('should trigger a popover', async function () { let {getByRole, queryByRole, getByTestId} = render( @@ -123,7 +123,7 @@ describe('DialogTrigger', function () { expect(queryByRole('dialog')).toBeNull(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); @@ -137,7 +137,7 @@ describe('DialogTrigger', function () { expect(popover).toHaveAttribute('style'); }); - it('popovers should be closeable', function () { + it('popovers should be closeable', async function () { let {getByRole, getByText, queryByRole} = render( @@ -157,7 +157,7 @@ describe('DialogTrigger', function () { ); let triggerButton = getByRole('button'); - triggerPress(triggerButton); + await user.click(triggerButton); act(() => { jest.runAllTimers(); @@ -167,7 +167,7 @@ describe('DialogTrigger', function () { expect(dialog).toBeVisible(); let cancelButton = getByText('Cancel'); - triggerPress(cancelButton); + await user.click(cancelButton); act(() => { jest.runAllTimers(); @@ -177,7 +177,7 @@ describe('DialogTrigger', function () { expect(dialog).toBeNull(); }); - it('should trigger a modal instead of a popover on mobile', function () { + it('should trigger a modal instead of a popover on mobile', async function () { simulateMobile(); let {getByRole, queryByRole, getByTestId} = render( @@ -191,7 +191,7 @@ describe('DialogTrigger', function () { expect(queryByRole('dialog')).toBeNull(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); @@ -204,7 +204,7 @@ describe('DialogTrigger', function () { expect(modal).toBeVisible(); }); - it('should trigger a tray instead of a popover on mobile if mobileType="tray"', function () { + it('should trigger a tray instead of a popover on mobile if mobileType="tray"', async function () { simulateMobile(); let {getByRole, queryByRole, getByTestId} = render( @@ -218,7 +218,7 @@ describe('DialogTrigger', function () { expect(queryByRole('dialog')).toBeNull(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); @@ -231,7 +231,7 @@ describe('DialogTrigger', function () { expect(tray).toBeVisible(); }); - it.each(['modal', 'popover', 'tray'])('contains focus within the dialog when rendered as a %s', function (type) { + it.each(['modal', 'popover', 'tray'])('contains focus within the dialog when rendered as a %s', async function (type) { let {getByRole, getByTestId} = render( @@ -245,7 +245,7 @@ describe('DialogTrigger', function () { ); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); @@ -323,7 +323,7 @@ describe('DialogTrigger', function () { ); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); @@ -338,7 +338,7 @@ describe('DialogTrigger', function () { expect(document.activeElement).toBe(dialog); let dismiss = getAllByRole('button')[0]; - triggerPress(dismiss); + await user.click(dismiss); act(() => { jest.runAllTimers(); @@ -368,7 +368,7 @@ describe('DialogTrigger', function () { ); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); @@ -383,7 +383,7 @@ describe('DialogTrigger', function () { expect(document.activeElement).toBe(dialog); expect(onOpenChange).toHaveBeenCalledTimes(1); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); @@ -416,7 +416,7 @@ describe('DialogTrigger', function () { expect(rootProviderRef.current.UNSAFE_getDOMNode().closest('[aria-hidden=true]')).not.toBeInTheDocument(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); @@ -460,7 +460,7 @@ describe('DialogTrigger', function () { expect(queryByRole('dialog')).toBeNull(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); @@ -563,7 +563,7 @@ describe('DialogTrigger', function () { expect(dialog).toBeVisible(); }); // wait for animation - triggerPress(closeBtn); + await user.click(closeBtn); expect(dialog).toBeVisible(); expect(onOpenChange).toHaveBeenCalledTimes(1); expect(onOpenChange).toHaveBeenCalledWith(false); @@ -602,7 +602,7 @@ describe('DialogTrigger', function () { }); // wait for animation let closeButton = getByLabelText('Dismiss'); - triggerPress(closeButton); + await user.click(closeButton); expect(dialog).toBeVisible(); expect(onOpenChange).toHaveBeenCalledTimes(1); expect(onOpenChange).toHaveBeenCalledWith(false); @@ -640,7 +640,7 @@ describe('DialogTrigger', function () { expect(dialog).toBeVisible(); }); // wait for animation - triggerPress(document.body); + await user.click(document.body); expect(dialog).toBeVisible(); expect(onOpenChange).toHaveBeenCalledTimes(1); expect(onOpenChange).toHaveBeenCalledWith(false); @@ -678,7 +678,7 @@ describe('DialogTrigger', function () { expect(dialog).toBeVisible(); }); // wait for animation - triggerPress(document.body); + await user.click(document.body); act(() => { jest.runAllTimers(); }); @@ -711,7 +711,7 @@ describe('DialogTrigger', function () { expect(modal).toBeVisible(); }); // wait for animation - triggerPress(document.body); + await user.click(document.body); expect(modal).toBeVisible(); expect(onOpenChange).toHaveBeenCalledTimes(1); expect(onOpenChange).toHaveBeenCalledWith(false); @@ -749,7 +749,7 @@ describe('DialogTrigger', function () { await waitFor(() => { expect(dialog).toBeVisible(); }); // wait for animation - triggerPress(document.body); + await user.click(document.body); expect(dialog).toBeVisible(); expect(onOpenChange).toHaveBeenCalledTimes(1); expect(onOpenChange).toHaveBeenCalledWith(false); @@ -774,7 +774,7 @@ describe('DialogTrigger', function () { ); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); @@ -803,7 +803,7 @@ describe('DialogTrigger', function () { // Close the dialog by clicking the button inside button = within(dialog).getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -811,7 +811,7 @@ describe('DialogTrigger', function () { expect(queryByRole('dialog')).toBeNull(); }); - it('should warn when unmounting a dialog trigger while a modal is open', function () { + it('should warn when unmounting a dialog trigger while a modal is open', async function () { let warn = jest.spyOn(console, 'warn').mockImplementation(() => {}); let {getByRole, queryByRole} = render( @@ -829,7 +829,7 @@ describe('DialogTrigger', function () { let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -837,7 +837,7 @@ describe('DialogTrigger', function () { let menu = getByRole('menu'); let menuitem = within(menu).getByRole('menuitem'); - triggerPress(menuitem); + await user.click(menuitem); act(() => { jest.runAllTimers(); }); @@ -873,7 +873,7 @@ describe('DialogTrigger', function () { ); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); @@ -888,7 +888,7 @@ describe('DialogTrigger', function () { let outerInput = getByRole('textbox'); expect(document.activeElement).toBe(outerInput); - triggerPress(outerButton); + await user.click(outerButton); act(() => { jest.runAllTimers(); @@ -943,7 +943,7 @@ describe('DialogTrigger', function () { ); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); @@ -957,7 +957,7 @@ describe('DialogTrigger', function () { let outerButton = getByText('Trigger2'); - triggerPress(outerButton); + await user.click(outerButton); act(() => { jest.runAllTimers(); @@ -998,7 +998,7 @@ describe('DialogTrigger', function () { ); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); diff --git a/packages/@react-spectrum/form/test/Form.test.js b/packages/@react-spectrum/form/test/Form.test.js index ad21ad4d8a2..1c52e2c311e 100644 --- a/packages/@react-spectrum/form/test/Form.test.js +++ b/packages/@react-spectrum/form/test/Form.test.js @@ -16,7 +16,7 @@ import {Content, Header} from '@react-spectrum/view'; import {ContextualHelp} from '@react-spectrum/contextualhelp'; import {Form} from '../'; import {Item, Picker} from '@react-spectrum/picker'; -import {pointerMap, render, simulateMobile, triggerPress} from '@react-spectrum/test-utils'; +import {pointerMap, render, simulateMobile} from '@react-spectrum/test-utils'; import {Provider} from '@react-spectrum/provider'; import React from 'react'; import {TextField} from '@react-spectrum/textfield'; @@ -223,7 +223,7 @@ describe('Form', function () { ); let button = getByLabelText('Help'); - triggerPress(button); + await user.click(button); let dialog = getByRole('dialog'); await user.tab(); @@ -231,7 +231,7 @@ describe('Form', function () { let dismissButton = within(dialog).getByRole('button'); expect(document.activeElement).toBe(dismissButton); - triggerPress(dismissButton); + await user.click(dismissButton); act(() => {jest.runAllTimers();}); act(() => {jest.runAllTimers();}); diff --git a/packages/@react-spectrum/link/test/Link.test.js b/packages/@react-spectrum/link/test/Link.test.js index ebac60ec731..8dd9e58b8ae 100644 --- a/packages/@react-spectrum/link/test/Link.test.js +++ b/packages/@react-spectrum/link/test/Link.test.js @@ -10,20 +10,13 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, render} from '@react-spectrum/test-utils'; +import {act, pointerMap, render} from '@react-spectrum/test-utils'; import {Link} from '../'; import {Provider} from '@react-spectrum/provider'; import React from 'react'; import {theme} from '@react-spectrum/theme-default'; import {Tooltip, TooltipTrigger} from '@react-spectrum/tooltip'; - -// Triggers a "press" event on an element. -// TODO: import from somewhere more common -export function triggerPress(element) { - fireEvent.mouseDown(element); - fireEvent.mouseUp(element); - fireEvent.click(element); -} +import userEvent from '@testing-library/user-event'; describe('Link', function () { let onPressSpy = jest.fn(); @@ -34,20 +27,21 @@ describe('Link', function () { }); afterEach(() => { - onOpenChange.mockClear(); - onPressSpy.mockClear(); + act(() => {jest.runAllTimers();}); + jest.clearAllMocks(); }); it.each` Name | Component | props ${'Link'} | ${Link} | ${{onPress: onPressSpy}} - `('$Name handles defaults', function ({Component, props}) { + `('$Name handles defaults', async function ({Component, props}) { + let user = userEvent.setup({delay: null, pointerMap}); let {getByText} = render(Click me); let link = getByText('Click me'); expect(link).not.toBeNull(); - triggerPress(link); + await user.click(link); expect(onPressSpy).toHaveBeenCalledTimes(1); }); @@ -76,7 +70,8 @@ describe('Link', function () { expect(link.href).toBe('https://adobe.com/'); }); - it('Wraps custom child element', () => { + it('Wraps custom child element', async () => { + let user = userEvent.setup({delay: null, pointerMap}); let ref = React.createRef(); let {getByRole} = render( @@ -89,15 +84,17 @@ describe('Link', function () { expect(ref.current).toBe(link); expect(link).toHaveAttribute('class', expect.stringContaining('test-class')); expect(link).toHaveAttribute('href', '#only-hash-in-jsdom'); - triggerPress(link); + await user.click(link); expect(onPressSpy).toHaveBeenCalledTimes(1); }); - it('Handles deprecated onClick', () => { + it('Handles deprecated onClick', async () => { + let user = userEvent.setup({delay: null, pointerMap}); let spyWarn = jest.spyOn(console, 'warn').mockImplementation(() => {}); let {getByRole} = render(Click me); let link = getByRole('link'); - triggerPress(link); + await user.click(link); + act(() => {jest.runAllTimers();}); expect(onPressSpy).toHaveBeenCalledTimes(1); expect(spyWarn).toHaveBeenCalledWith('onClick is deprecated, please use onPress'); }); @@ -109,15 +106,14 @@ describe('Link', function () { }); it('supports autofocus', () => { - jest.useFakeTimers(); let {getByRole} = render(Click me); act(() => {jest.runAllTimers();}); let link = getByRole('link'); expect(document.activeElement).toBe(link); - jest.useRealTimers(); }); - it('supports a wrapping tooltip trigger', () => { + it('supports a wrapping tooltip trigger', async () => { + let user = userEvent.setup({delay: null, pointerMap}); let {getByRole, queryByRole} = render( @@ -128,16 +124,11 @@ describe('Link', function () { ); expect(queryByRole('tooltip')).toBeNull(); - let link = getByRole('link'); - act(() => { - link.focus(); - }); + await user.tab(); expect(onOpenChange).toHaveBeenCalledWith(true); let tooltip = getByRole('tooltip'); expect(tooltip).toBeVisible(); - act(() => { - link.blur(); - }); + await user.tab(); expect(onOpenChange).toHaveBeenCalledTimes(2); expect(onOpenChange).toHaveBeenCalledWith(false); act(() => { @@ -147,11 +138,12 @@ describe('Link', function () { expect(tooltip).not.toBeInTheDocument(); }); - it('supports RouterProvider', () => { + it('supports RouterProvider', async () => { + let user = userEvent.setup({delay: null, pointerMap}); let navigate = jest.fn(); let {getByRole} = render(Click me); let link = getByRole('link'); - triggerPress(link); + await user.click(link); expect(navigate).toHaveBeenCalledWith('/foo'); }); }); diff --git a/packages/@react-spectrum/list/test/ListView.test.js b/packages/@react-spectrum/list/test/ListView.test.js index 2ba182c84cf..56be56d998b 100644 --- a/packages/@react-spectrum/list/test/ListView.test.js +++ b/packages/@react-spectrum/list/test/ListView.test.js @@ -12,7 +12,7 @@ jest.mock('@react-aria/live-announcer'); -import {act, fireEvent, installPointerEvent, pointerMap, render as renderComponent, triggerPress, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, installPointerEvent, pointerMap, render as renderComponent, within} from '@react-spectrum/test-utils'; import {ActionButton} from '@react-spectrum/button'; import {announce} from '@react-aria/live-announcer'; import {FocusExample} from '../stories/ListViewActions.stories'; @@ -230,17 +230,17 @@ describe('ListView', function () { expect(gridCells[0]).toHaveTextContent('Foo'); }); - it('should retain focus on the pressed child', function () { + it('should retain focus on the pressed child', async function () { let tree = renderListWithFocusables(); let button = within(getRow(tree, 'Foo')).getAllByRole('button')[1]; - triggerPress(button); + await user.click(button); expect(document.activeElement).toBe(button); }); - it('should focus the row if the cell is pressed', function () { + it('should focus the row if the cell is pressed', async function () { let tree = renderList({selectionMode: 'single'}); let cell = within(getRow(tree, 'Bar')).getByRole('gridcell'); - triggerPress(cell); + await user.click(cell); act(() => { jest.runAllTimers(); }); @@ -336,13 +336,13 @@ describe('ListView', function () { expect(document.activeElement).toBe(start); }); - it('should move focus to previous cell in RTL', function () { + it('should move focus to previous cell in RTL', async function () { let tree = renderListWithFocusables({locale: 'ar-AE'}); // Should move from button two to button one let start = within(getRow(tree, 'Foo')).getAllByRole('button')[1]; let end = within(getRow(tree, 'Foo')).getAllByRole('button')[0]; // Need to press to set a modality, otherwise useSelectableCollection will think this is a tab operation - triggerPress(start); + await user.click(start); expect(document.activeElement).toHaveTextContent('button2 Foo'); expect(document.activeElement).toBe(start); moveFocus('ArrowRight'); @@ -375,13 +375,13 @@ describe('ListView', function () { expect(document.activeElement).toBe(start); }); - it('should move focus to next cell in RTL', function () { + it('should move focus to next cell in RTL', async function () { let tree = renderListWithFocusables({locale: 'ar-AE'}); // Should move from button one to button two let start = within(getRow(tree, 'Foo')).getAllByRole('button')[0]; let end = within(getRow(tree, 'Foo')).getAllByRole('button')[1]; // Need to press to set a modality, otherwise useSelectableCollection will think this is a tab operation - triggerPress(start); + await user.click(start); expect(document.activeElement).toHaveTextContent('button1 Foo'); expect(document.activeElement).toBe(start); moveFocus('ArrowLeft'); @@ -400,85 +400,85 @@ describe('ListView', function () { expect(document.activeElement).toBe(start); }); - it('should move focus to above row', function () { + it('should move focus to above row', async function () { let tree = renderListWithFocusables({selectionMode: 'single'}); let start = getRow(tree, 'Bar'); let end = getRow(tree, 'Foo'); - triggerPress(start); + await user.click(start); moveFocus('ArrowUp'); expect(document.activeElement).toBe(end); }); - it('should skip disabled rows', function () { + it('should skip disabled rows', async function () { let tree = renderListWithFocusables({disabledKeys: ['bar'], selectionMode: 'single'}); let start = getRow(tree, 'Baz'); let end = getRow(tree, 'Foo'); - triggerPress(start); + await user.click(start); moveFocus('ArrowUp'); expect(document.activeElement).toBe(end); }); - it('should allow focus on disabled rows with disabledBehavior="selection"', function () { + it('should allow focus on disabled rows with disabledBehavior="selection"', async function () { let tree = renderListWithFocusables({disabledKeys: ['foo'], disabledBehavior: 'selection', selectionMode: 'single'}); let start = getRow(tree, 'Bar'); let end = getRow(tree, 'Foo'); - triggerPress(start); + await user.click(start); moveFocus('ArrowUp'); expect(document.activeElement).toBe(end); }); }); describe('ArrowDown', function () { - it('should not wrap focus', function () { + it('should not wrap focus', async function () { let tree = renderListWithFocusables({selectionMode: 'single'}); let start = getRow(tree, 'Baz'); - triggerPress(start); + await user.click(start); moveFocus('ArrowDown'); expect(document.activeElement).toBe(start); }); - it('should move focus to below row', function () { + it('should move focus to below row', async function () { let tree = renderListWithFocusables({selectionMode: 'single'}); let start = getRow(tree, 'Foo'); let end = getRow(tree, 'Bar'); - triggerPress(start); + await user.click(start); moveFocus('ArrowDown'); expect(document.activeElement).toBe(end); }); - it('should skip disabled rows', function () { + it('should skip disabled rows', async function () { let tree = renderListWithFocusables({disabledKeys: ['bar'], selectionMode: 'single'}); let start = getRow(tree, 'Foo'); let end = getRow(tree, 'Baz'); - triggerPress(start); + await user.click(start); moveFocus('ArrowDown'); expect(document.activeElement).toBe(end); }); - it('should allow focus on disabled rows with disabledBehavior="selection"', function () { + it('should allow focus on disabled rows with disabledBehavior="selection"', async function () { let tree = renderListWithFocusables({disabledKeys: ['bar'], disabledBehavior: 'selection', selectionMode: 'single'}); let start = getRow(tree, 'Foo'); let end = getRow(tree, 'Bar'); - triggerPress(start); + await user.click(start); moveFocus('ArrowDown'); expect(document.activeElement).toBe(end); }); }); describe('PageUp', function () { - it('should move focus to a row a page above when focus starts on a row', function () { + it('should move focus to a row a page above when focus starts on a row', async function () { let tree = renderListWithFocusables({items: manyItems, selectionMode: 'single'}); let start = getRow(tree, 'Foo 25'); - triggerPress(start); + await user.click(start); moveFocus('PageUp'); expect(document.activeElement).toBe(getRow(tree, 'Foo 1')); }); - it('should move focus to a row a page above when focus starts in the row cell', function () { + it('should move focus to a row a page above when focus starts in the row cell', async function () { let tree = renderListWithFocusables({items: manyItems}); let focusables = within(getRow(tree, 'Foo 25')).getAllByRole('button'); let start = focusables[0]; - triggerPress(start); + await user.click(start); expect(document.activeElement).toBe(start); moveFocus('PageUp'); expect(document.activeElement).toBe(getRow(tree, 'Foo 1')); @@ -495,11 +495,11 @@ describe('ListView', function () { expect(document.activeElement).toBe(getRow(tree, 'Foo 49')); }); - it('should move focus to a row a page below when focus starts in the row cell', function () { + it('should move focus to a row a page below when focus starts in the row cell', async function () { let tree = renderListWithFocusables({items: manyItems}); let focusables = within(getRow(tree, 'Foo 1')).getAllByRole('button'); let start = focusables[0]; - triggerPress(start); + await user.click(start); expect(document.activeElement).toBe(start); moveFocus('PageDown'); expect(document.activeElement).toBe(getRow(tree, 'Foo 25')); @@ -509,19 +509,19 @@ describe('ListView', function () { }); describe('Home', function () { - it('should move focus to the first row when focus starts on a row', function () { + it('should move focus to the first row when focus starts on a row', async function () { let tree = renderListWithFocusables({items: manyItems, selectionMode: 'single'}); let start = getRow(tree, 'Foo 15'); - triggerPress(start); + await user.click(start); moveFocus('Home'); expect(document.activeElement).toBe(getRow(tree, 'Foo 1')); }); - it('should move focus to the first row when focus starts in the row cell', function () { + it('should move focus to the first row when focus starts in the row cell', async function () { let tree = renderListWithFocusables({items: manyItems}); let focusables = within(getRow(tree, 'Foo 15')).getAllByRole('button'); let start = focusables[0]; - triggerPress(start); + await user.click(start); expect(document.activeElement).toBe(start); moveFocus('Home'); expect(document.activeElement).toBe(getRow(tree, 'Foo 1')); @@ -536,18 +536,18 @@ describe('ListView', function () { expect(document.activeElement).toBe(getRow(tree, 'Foo 100')); }); - it('should move focus to the last row when focus starts in the row cell', function () { + it('should move focus to the last row when focus starts in the row cell', async function () { let tree = renderListWithFocusables({items: manyItems}); let focusables = within(getRow(tree, 'Foo 1')).getAllByRole('button'); let start = focusables[0]; - triggerPress(start); + await user.click(start); expect(document.activeElement).toBe(start); moveFocus('End'); expect(document.activeElement).toBe(getRow(tree, 'Foo 100')); }); }); - it('should move focus to the next item that is not disabled when the focused item is removed', () => { + it('should move focus to the next item that is not disabled when the focused item is removed', async () => { let tree = render(); let rows = tree.getAllByRole('row'); act(() => rows[3].focus()); @@ -555,7 +555,7 @@ describe('ListView', function () { moveFocus('ArrowRight'); expect(document.activeElement).toBe(within(rows[3]).getByRole('button')); expect(rows[4]).toHaveAttribute('aria-disabled', 'true'); - triggerPress(document.activeElement); + await user.click(document.activeElement); act(() => { jest.runAllTimers(); }); @@ -565,7 +565,7 @@ describe('ListView', function () { expect(document.activeElement).toBe(rows[rows.length - 1]); moveFocus('ArrowRight'); expect(document.activeElement).toBe(within(rows[rows.length - 1]).getByRole('button')); - triggerPress(document.activeElement); + await user.click(document.activeElement); act(() => { jest.runAllTimers(); }); @@ -573,7 +573,7 @@ describe('ListView', function () { expect(document.activeElement).toBe(rows[rows.length - 1]); moveFocus('ArrowRight'); expect(document.activeElement).toBe(within(rows[rows.length - 1]).getByRole('button')); - triggerPress(document.activeElement); + await user.click(document.activeElement); act(() => { jest.runAllTimers(); }); @@ -581,7 +581,7 @@ describe('ListView', function () { expect(document.activeElement).toBe(rows[rows.length - 1]); moveFocus('ArrowRight'); expect(document.activeElement).toBe(within(rows[rows.length - 1]).getByRole('button')); - triggerPress(document.activeElement); + await user.click(document.activeElement); act(() => { jest.runAllTimers(); }); @@ -589,7 +589,7 @@ describe('ListView', function () { expect(document.activeElement).toBe(rows[rows.length - 1]); moveFocus('ArrowRight'); expect(document.activeElement).toBe(within(rows[rows.length - 1]).getByRole('button')); - triggerPress(document.activeElement); + await user.click(document.activeElement); act(() => { jest.runAllTimers(); }); @@ -597,7 +597,7 @@ describe('ListView', function () { expect(document.activeElement).toBe(rows[rows.length - 1]); moveFocus('ArrowRight'); expect(document.activeElement).toBe(within(rows[rows.length - 1]).getByRole('button')); - triggerPress(document.activeElement); + await user.click(document.activeElement); act(() => { jest.runAllTimers(); }); @@ -705,16 +705,16 @@ describe('ListView', function () { ); - it('should announce the selected or deselected row', function () { + it('should announce the selected or deselected row', async function () { let onSelectionChange = jest.fn(); let tree = renderSelectionList({onSelectionChange, selectionMode: 'single'}); let row = tree.getAllByRole('row')[1]; - triggerPress(row); + await user.click(row); expect(announce).toHaveBeenLastCalledWith('Bar selected.'); expect(announce).toHaveBeenCalledTimes(1); - triggerPress(row); + await user.click(row); expect(announce).toHaveBeenLastCalledWith('Bar not selected.'); expect(announce).toHaveBeenCalledTimes(2); }); @@ -806,30 +806,34 @@ describe('ListView', function () { expect(announce).toHaveBeenCalledTimes(3); }); - it('should support range selection', function () { + it('should support range selection', async function () { let tree = renderSelectionList({onSelectionChange, selectionMode: 'multiple'}); let rows = tree.getAllByRole('row'); - triggerPress(rows[0]); + await user.click(rows[0]); checkSelection(onSelectionChange, ['foo']); onSelectionChange.mockClear(); - triggerPress(rows[2], {shiftKey: true}); + await user.keyboard('{Shift>}'); + await user.click(rows[2]); + await user.keyboard('{/Shift}'); checkSelection(onSelectionChange, ['foo', 'bar', 'baz']); onSelectionChange.mockClear(); expect(announce).toHaveBeenLastCalledWith('3 items selected.'); expect(announce).toHaveBeenCalledTimes(2); - triggerPress(rows[0], {shiftKey: true}); + await user.keyboard('{Shift>}'); + await user.click(rows[0], {shiftKey: true}); + await user.keyboard('{/Shift}'); checkSelection(onSelectionChange, ['foo']); expect(announce).toHaveBeenLastCalledWith('1 item selected.'); expect(announce).toHaveBeenCalledTimes(3); }); - it('should support select all and clear all via keyboard', function () { + it('should support select all and clear all via keyboard', async function () { let tree = renderSelectionList({onSelectionChange, selectionMode: 'multiple'}); let rows = tree.getAllByRole('row'); - triggerPress(rows[0]); + await user.click(rows[0]); checkSelection(onSelectionChange, ['foo']); onSelectionChange.mockClear(); expect(announce).toHaveBeenLastCalledWith('Foo selected.'); @@ -1528,16 +1532,16 @@ describe('ListView', function () { describe('links', function () { describe.each(['mouse', 'keyboard'])('%s', (type) => { - let trigger = (item, key = 'Enter') => { + let trigger = async (item, key = 'Enter') => { if (type === 'mouse') { - triggerPress(item); + await user.click(item); } else { fireEvent.keyDown(item, {key}); fireEvent.keyUp(item, {key}); } }; - it('should support links with selectionMode="none"', function () { + it('should support links with selectionMode="none"', async function () { let {getAllByRole} = render( @@ -1555,7 +1559,7 @@ describe('ListView', function () { let onClick = jest.fn().mockImplementation(e => e.preventDefault()); window.addEventListener('click', onClick, {once: true}); - trigger(items[0]); + await trigger(items[0]); expect(onClick).toHaveBeenCalledTimes(1); expect(onClick.mock.calls[0][0].target).toBeInstanceOf(HTMLAnchorElement); expect(onClick.mock.calls[0][0].target.href).toBe('https://google.com/'); @@ -1579,7 +1583,7 @@ describe('ListView', function () { let onClick = jest.fn().mockImplementation(e => e.preventDefault()); window.addEventListener('click', onClick, {once: true}); - trigger(items[0]); + await trigger(items[0]); expect(onClick).toHaveBeenCalledTimes(1); expect(onClick.mock.calls[0][0].target).toBeInstanceOf(HTMLAnchorElement); expect(onClick.mock.calls[0][0].target.href).toBe('https://google.com/'); @@ -1589,7 +1593,7 @@ describe('ListView', function () { onClick = jest.fn().mockImplementation(e => e.preventDefault()); window.addEventListener('click', onClick); - trigger(items[1], ' '); + await trigger(items[1], ' '); expect(onClick).not.toHaveBeenCalled(); expect(items[1]).toHaveAttribute('aria-selected', 'true'); window.removeEventListener('click', onClick); @@ -1614,7 +1618,7 @@ describe('ListView', function () { let onClick = jest.fn().mockImplementation(e => e.preventDefault()); window.addEventListener('click', onClick); if (type === 'mouse') { - triggerPress(items[0]); + await user.click(items[0]); } else { fireEvent.keyDown(items[0], {key: ' '}); fireEvent.keyUp(items[0], {key: ' '}); @@ -1648,14 +1652,14 @@ describe('ListView', function () { ); let items = getAllByRole('row'); - trigger(items[0]); + await trigger(items[0]); expect(navigate).toHaveBeenCalledWith('/one'); navigate.mockReset(); let onClick = jest.fn().mockImplementation(e => e.preventDefault()); window.addEventListener('click', onClick, {once: true}); - trigger(items[1]); + await trigger(items[1]); expect(navigate).not.toHaveBeenCalled(); expect(onClick).toHaveBeenCalledTimes(1); }); diff --git a/packages/@react-spectrum/list/test/ListViewDnd.test.js b/packages/@react-spectrum/list/test/ListViewDnd.test.js index 7025d00179e..70439a9872a 100644 --- a/packages/@react-spectrum/list/test/ListViewDnd.test.js +++ b/packages/@react-spectrum/list/test/ListViewDnd.test.js @@ -17,7 +17,6 @@ import { installPointerEvent, pointerMap, render as renderComponent, - triggerPress, waitFor, within } from '@react-spectrum/test-utils'; @@ -272,10 +271,10 @@ describe('ListView', function () { let droppable = getByText('Drop here'); let rows = getAllByRole('row'); - triggerPress(within(rows[0]).getByRole('checkbox')); - triggerPress(within(rows[1]).getByRole('checkbox')); - triggerPress(within(rows[2]).getByRole('checkbox')); - triggerPress(within(rows[3]).getByRole('checkbox')); + await user.click(within(rows[0]).getByRole('checkbox')); + await user.click(within(rows[1]).getByRole('checkbox')); + await user.click(within(rows[2]).getByRole('checkbox')); + await user.click(within(rows[3]).getByRole('checkbox')); // TODO: reinstate these when https://github.com/testing-library/user-event/issues/1119 is fixed // await user.click(within(rows[0]).getByRole('checkbox')); // await user.click(within(rows[1]).getByRole('checkbox')); @@ -455,8 +454,8 @@ describe('ListView', function () { expect(within(rows[2]).getByRole('gridcell')).toHaveTextContent('Item Three'); expect(within(rows[3]).getByRole('gridcell')).toHaveTextContent('Item Four'); - triggerPress(within(rows[1]).getByRole('checkbox')); - triggerPress(within(rows[2]).getByRole('checkbox')); + await user.click(within(rows[1]).getByRole('checkbox')); + await user.click(within(rows[2]).getByRole('checkbox')); // TODO: reinstate these when https://github.com/testing-library/user-event/issues/1119 is fixed // await user.click(within(rows[1]).getByRole('checkbox')); // await user.click(within(rows[2]).getByRole('checkbox')); @@ -562,8 +561,8 @@ describe('ListView', function () { expect(within(list2rows[1]).getByRole('gridcell')).toHaveTextContent('Item Eight'); expect(within(list2rows[2]).getByRole('gridcell')).toHaveTextContent('Item Nine'); - triggerPress(within(list1rows[0]).getByRole('checkbox')); - triggerPress(within(list1rows[2]).getByRole('checkbox')); + await user.click(within(list1rows[0]).getByRole('checkbox')); + await user.click(within(list1rows[2]).getByRole('checkbox')); // TODO: reinstate these when https://github.com/testing-library/user-event/issues/1119 is fixed // await user.click(within(list1rows[0]).getByRole('checkbox')); // await user.click(within(list1rows[2]).getByRole('checkbox')); @@ -651,7 +650,7 @@ describe('ListView', function () { expect(document.activeElement).toBe(rows[7]); }); - it('should update the global DnD state properly if dropping on a non-collection', function () { + it('should update the global DnD state properly if dropping on a non-collection', async function () { let {getAllByRole, getByRole, getByText} = render( ); @@ -659,10 +658,10 @@ describe('ListView', function () { let grid = getByRole('grid'); let droppable = getByText('Drop here'); let rows = getAllByRole('row'); - triggerPress(within(rows[0]).getByRole('checkbox')); - triggerPress(within(rows[1]).getByRole('checkbox')); - triggerPress(within(rows[2]).getByRole('checkbox')); - triggerPress(within(rows[3]).getByRole('checkbox')); + await user.click(within(rows[0]).getByRole('checkbox')); + await user.click(within(rows[1]).getByRole('checkbox')); + await user.click(within(rows[2]).getByRole('checkbox')); + await user.click(within(rows[3]).getByRole('checkbox')); // TODO: reinstate these when https://github.com/testing-library/user-event/issues/1119 is fixed // await user.click(within(rows[0]).getByRole('checkbox')); // await user.click(within(rows[1]).getByRole('checkbox')); @@ -699,14 +698,14 @@ describe('ListView', function () { expect(onDragEnd).toHaveBeenCalledTimes(1); }); - it('should reset the global drop state on drag end even if a drop doesn\'t happen', function () { + it('should reset the global drop state on drag end even if a drop doesn\'t happen', async function () { let {getAllByRole, getByRole} = render( ); let grid = getByRole('grid'); let rows = getAllByRole('row'); - triggerPress(within(rows[0]).getByRole('checkbox')); + await user.click(within(rows[0]).getByRole('checkbox')); // TODO: reinstate these when https://github.com/testing-library/user-event/issues/1119 is fixed // await user.click(within(rows[0]).getByRole('checkbox')); let cellA = within(rows[0]).getByRole('gridcell'); @@ -754,7 +753,7 @@ describe('ListView', function () { }); }); - it('should update the dropCollectionRef during drag operations', function () { + it('should update the dropCollectionRef during drag operations', async function () { let {getAllByRole} = render( ); @@ -763,7 +762,7 @@ describe('ListView', function () { let rows = within(list).getAllByRole('row'); let internalFolder = rows[2]; - triggerPress(within(rows[0]).getByRole('checkbox')); + await user.click(within(rows[0]).getByRole('checkbox')); // TODO: reinstate these when https://github.com/testing-library/user-event/issues/1119 is fixed // await user.click(within(rows[0]).getByRole('checkbox')); let dragCell = within(rows[0]).getByRole('gridcell'); @@ -793,8 +792,8 @@ describe('ListView', function () { describe('using util handlers', function () { async function dragWithinList(rows, dropTarget, targetX = 1, targetY = 1) { - triggerPress(within(rows[0]).getByRole('checkbox')); - triggerPress(within(rows[1]).getByRole('checkbox')); + await user.click(within(rows[0]).getByRole('checkbox')); + await user.click(within(rows[1]).getByRole('checkbox')); // TODO: reinstate these when https://github.com/testing-library/user-event/issues/1119 is fixed // await user.click(within(rows[0]).getByRole('checkbox')); // await user.click(within(rows[1]).getByRole('checkbox')); @@ -816,8 +815,8 @@ describe('ListView', function () { } async function dragBetweenLists(sourceRows, dropTarget, targetX = 1, targetY = 1) { - triggerPress(within(sourceRows[0]).getByRole('checkbox')); - triggerPress(within(sourceRows[1]).getByRole('checkbox')); + await user.click(within(sourceRows[0]).getByRole('checkbox')); + await user.click(within(sourceRows[1]).getByRole('checkbox')); // TODO: reinstate these when https://github.com/testing-library/user-event/issues/1119 is fixed // await user.click(within(sourceRows[0]).getByRole('checkbox')); // await user.click(within(sourceRows[1]).getByRole('checkbox')); @@ -1299,7 +1298,7 @@ describe('ListView', function () { }); }); - it('should automatically disallow various drops if their respective util handler isn\'t provided', function () { + it('should automatically disallow various drops if their respective util handler isn\'t provided', async function () { let {getAllByRole} = render( ); @@ -1311,8 +1310,8 @@ describe('ListView', function () { let list1Rows = within(grids[0]).getAllByRole('row', {hidden: true}); expect(list1Rows).toHaveLength(6); let list2Rows = within(grids[1]).getAllByRole('row'); - triggerPress(within(list2Rows[0]).getByRole('checkbox')); - triggerPress(within(list2Rows[1]).getByRole('checkbox')); + await user.click(within(list2Rows[0]).getByRole('checkbox')); + await user.click(within(list2Rows[1]).getByRole('checkbox')); // TODO: reinstate these when https://github.com/testing-library/user-event/issues/1119 is fixed // await user.click(within(list2Rows[0]).getByRole('checkbox')); // await user.click(within(list2Rows[1]).getByRole('checkbox')); @@ -1584,8 +1583,8 @@ describe('ListView', function () { let dropTarget = within(grids[0]).getAllByRole('row')[0]; let list2Rows = within(grids[1]).getAllByRole('row'); - triggerPress(within(list2Rows[0]).getByRole('checkbox')); - triggerPress(within(list2Rows[6]).getByRole('checkbox')); + await user.click(within(list2Rows[0]).getByRole('checkbox')); + await user.click(within(list2Rows[6]).getByRole('checkbox')); // TODO: reinstate these when https://github.com/testing-library/user-event/issues/1119 is fixed // await user.click(within(list2Rows[0]).getByRole('checkbox')); // await user.click(within(list2Rows[6]).getByRole('checkbox')); @@ -2921,7 +2920,7 @@ describe('ListView', function () { checkSelection(onSelectionChange, ['a']); }); - it('should toggle selection upon clicking the row checkbox', function () { + it('should toggle selection upon clicking the row checkbox', async function () { let {getAllByRole} = render( ); @@ -2929,7 +2928,7 @@ describe('ListView', function () { let row = getAllByRole('row')[0]; expect(row).toHaveAttribute('aria-selected', 'false'); expect(row).toHaveAttribute('draggable', 'true'); - triggerPress(within(row).getByRole('checkbox')); + await user.click(within(row).getByRole('checkbox')); // TODO: reinstate these when https://github.com/testing-library/user-event/issues/1119 is fixed // await user.click(within(row).getByRole('checkbox')); expect(row).toHaveAttribute('aria-selected', 'true'); @@ -3318,7 +3317,7 @@ describe('ListView', function () { }); describe('accessibility', function () { - it('drag handle should reflect the correct number of draggable rows', function () { + it('drag handle should reflect the correct number of draggable rows', async function () { let {getAllByRole} = render( @@ -3343,14 +3342,14 @@ describe('ListView', function () { expect(dragButtonD).toHaveAttribute('aria-label', 'Drag Adobe InDesign'); // After selecting row 4, the aria-label should reflect 4 selected items rather than just "Drag Adobe InDesign" - triggerPress(within(rows[3]).getByRole('checkbox')); + await user.click(within(rows[3]).getByRole('checkbox')); // TODO: reinstate these when https://github.com/testing-library/user-event/issues/1119 is fixed // await user.click(within(rows[3]).getByRole('checkbox')); expect(dragButtonA).toHaveAttribute('aria-label', 'Drag 4 selected items'); expect(dragButtonB).toHaveAttribute('aria-label', 'Drag 4 selected items'); expect(dragButtonD).toHaveAttribute('aria-label', 'Drag 4 selected items'); - triggerPress(within(rows[0]).getByRole('checkbox')); + await user.click(within(rows[0]).getByRole('checkbox')); // TODO: reinstate these when https://github.com/testing-library/user-event/issues/1119 is fixed // await user.click(within(rows[0]).getByRole('checkbox')); expect(dragButtonA).toHaveAttribute('aria-label', 'Drag Adobe Photoshop'); diff --git a/packages/@react-spectrum/listbox/test/ListBox.test.js b/packages/@react-spectrum/listbox/test/ListBox.test.js index f60ea193012..036b0bbb145 100644 --- a/packages/@react-spectrum/listbox/test/ListBox.test.js +++ b/packages/@react-spectrum/listbox/test/ListBox.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, render, triggerPress, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; import Bell from '@spectrum-icons/workflow/Bell'; import {FocusExample} from '../stories/ListBox.stories'; import {Item, ListBox, Section} from '../'; @@ -18,6 +18,7 @@ import {Provider} from '@react-spectrum/provider'; import React from 'react'; import {Text} from '@react-spectrum/text'; import {theme} from '@react-spectrum/theme-default'; +import userEvent from '@testing-library/user-event'; let withSection = [ {name: 'Heading 1', children: [ @@ -270,14 +271,15 @@ describe('ListBox', function () { expect(onSelectionChange.mock.calls[0][0].has('Bleh')).toBeTruthy(); }); - it('supports using click to change item selection', function () { + it('supports using click to change item selection', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let tree = renderComponent({onSelectionChange, selectionMode: 'single'}); let listbox = tree.getByRole('listbox'); let options = within(listbox).getAllByRole('option'); // Trigger a menu item via press let item = options[4]; - triggerPress(item); + await user.click(item); expect(item).toHaveAttribute('aria-selected', 'true'); let checkmark = within(item).getByRole('img', {hidden: true}); expect(checkmark).toBeTruthy(); @@ -291,14 +293,15 @@ describe('ListBox', function () { expect(onSelectionChange.mock.calls[0][0].has('Bleh')).toBeTruthy(); }); - it('supports disabled items', function () { + it('supports disabled items', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let tree = renderComponent({onSelectionChange, selectionMode: 'single', disabledKeys: ['Baz'], autoFocus: 'first'}); let listbox = tree.getByRole('listbox'); let options = within(listbox).getAllByRole('option'); // Attempt to trigger the disabled item let disabledItem = options[2]; - triggerPress(disabledItem); + await user.click(disabledItem); expect(disabledItem).toHaveAttribute('aria-selected', 'false'); expect(disabledItem).toHaveAttribute('aria-disabled', 'true'); @@ -323,7 +326,8 @@ describe('ListBox', function () { }); describe('supports multi selection', function () { - it('supports selecting multiple items', function () { + it('supports selecting multiple items', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let tree = renderComponent({onSelectionChange, selectionMode: 'multiple'}); let listbox = tree.getByRole('listbox'); expect(listbox).toHaveAttribute('aria-multiselectable', 'true'); @@ -334,14 +338,14 @@ describe('ListBox', function () { let options = within(listbox).getAllByRole('option'); let firstItem = options[3]; - triggerPress(firstItem); + await user.click(firstItem); expect(firstItem).toHaveAttribute('aria-selected', 'true'); let checkmark = within(firstItem).getByRole('img', {hidden: true}); expect(checkmark).toBeTruthy(); // Select a different menu item let secondItem = options[1]; - triggerPress(secondItem); + await user.click(secondItem); expect(secondItem).toHaveAttribute('aria-selected', 'true'); checkmark = within(secondItem).getByRole('img', {hidden: true}); expect(checkmark).toBeTruthy(); @@ -355,7 +359,8 @@ describe('ListBox', function () { expect(onSelectionChange.mock.calls[1][0].has('Bar')).toBeTruthy(); }); - it('supports multiple defaultSelectedKeys (uncontrolled)', function () { + it('supports multiple defaultSelectedKeys (uncontrolled)', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let tree = renderComponent({onSelectionChange, selectionMode: 'multiple', defaultSelectedKeys: ['Foo', 'Bar']}); let listbox = tree.getByRole('listbox'); expect(listbox).toHaveAttribute('aria-multiselectable', 'true'); @@ -381,7 +386,7 @@ describe('ListBox', function () { // Select a different menu item let thirdItem = options[4]; - triggerPress(thirdItem); + await user.click(thirdItem); expect(thirdItem).toHaveAttribute('aria-selected', 'true'); checkmark = within(thirdItem).getByRole('img', {hidden: true}); expect(checkmark).toBeTruthy(); @@ -396,7 +401,8 @@ describe('ListBox', function () { expect(onSelectionChange.mock.calls[0][0].has('Bar')).toBeTruthy(); }); - it('supports multiple selectedKeys (controlled)', function () { + it('supports multiple selectedKeys (controlled)', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let tree = renderComponent({onSelectionChange, selectionMode: 'multiple', selectedKeys: ['Foo', 'Bar']}); let listbox = tree.getByRole('listbox'); expect(listbox).toHaveAttribute('aria-multiselectable', 'true'); @@ -422,7 +428,7 @@ describe('ListBox', function () { // Select a different menu item let thirdItem = options[4]; - triggerPress(thirdItem); + await user.click(thirdItem); expect(thirdItem).toHaveAttribute('aria-selected', 'false'); checkmark = within(thirdItem).queryByRole('img', {hidden: true}); expect(checkmark).toBeNull(); @@ -435,7 +441,8 @@ describe('ListBox', function () { expect(onSelectionChange.mock.calls[0][0].has('Bleh')).toBeTruthy(); }); - it('supports deselection', function () { + it('supports deselection', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let tree = renderComponent({onSelectionChange, selectionMode: 'multiple', defaultSelectedKeys: ['Foo', 'Bar']}); let listbox = tree.getByRole('listbox'); expect(listbox).toHaveAttribute('aria-multiselectable', 'true'); @@ -460,7 +467,7 @@ describe('ListBox', function () { expect(checkmark).toBeTruthy(); // Deselect the first item - triggerPress(firstItem); + await user.click(firstItem); expect(firstItem).toHaveAttribute('aria-selected', 'false'); checkmark = within(firstItem).queryByRole('img', {hidden: true}); expect(checkmark).toBeNull(); @@ -473,7 +480,8 @@ describe('ListBox', function () { expect(onSelectionChange.mock.calls[0][0].has('Bar')).toBeTruthy(); }); - it('supports disabledKeys', function () { + it('supports disabledKeys', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let tree = renderComponent({onSelectionChange, selectionMode: 'multiple', defaultSelectedKeys: ['Foo', 'Bar'], disabledKeys: ['Baz']}); let listbox = tree.getByRole('listbox'); expect(listbox).toHaveAttribute('aria-multiselectable', 'true'); @@ -481,7 +489,7 @@ describe('ListBox', function () { // Attempt to trigger disabled item let options = within(listbox).getAllByRole('option'); let disabledItem = options[2]; - triggerPress(disabledItem); + await user.click(disabledItem); expect(disabledItem).toHaveAttribute('aria-selected', 'false'); expect(disabledItem).toHaveAttribute('aria-disabled', 'true'); @@ -495,7 +503,8 @@ describe('ListBox', function () { }); describe('supports no selection', function () { - it('prevents selection of any items', function () { + it('prevents selection of any items', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let tree = renderComponent({onSelectionChange, selectionMode: 'none'}); let listbox = tree.getByRole('listbox'); @@ -508,7 +517,7 @@ describe('ListBox', function () { let firstItem = options[3]; let secondItem = options[4]; let thirdItem = options[1]; - triggerPress(firstItem); + await user.click(firstItem); fireEvent.keyDown(secondItem, {key: ' ', code: 32, charCode: 32}); fireEvent.keyDown(thirdItem, {key: 'Enter', code: 13, charCode: 13}); expect(firstItem).not.toHaveAttribute('aria-selected', 'true'); @@ -889,7 +898,8 @@ describe('ListBox', function () { }); describe('When focused item is removed', function () { - it('should move focus to the next item that is not disabled', () => { + it('should move focus to the next item that is not disabled', async () => { + let user = userEvent.setup({delay: null, pointerMap}); let tree = render(); act(() => jest.runAllTimers()); let listbox = tree.getByRole('listbox'); @@ -904,13 +914,13 @@ describe('ListBox', function () { expect(removeButton).toBeInTheDocument(); act(() => {removeButton.focus();}); expect(document.activeElement).toBe(removeButton); - triggerPress(removeButton); + await user.click(removeButton); act(() => jest.runAllTimers()); let confirmationDialog = tree.getByRole('alertdialog'); expect(document.activeElement).toBe(confirmationDialog); let confirmationDialogButton = within(confirmationDialog).getByRole('button'); expect(confirmationDialogButton).toBeInTheDocument(); - triggerPress(confirmationDialogButton); + await user.click(confirmationDialogButton); act(() => jest.runAllTimers()); options = within(listbox).getAllByRole('option'); expect(options.length).toBe(5); @@ -930,13 +940,13 @@ describe('ListBox', function () { expect(removeButton).toBeInTheDocument(); act(() => {removeButton.focus();}); expect(document.activeElement).toBe(removeButton); - triggerPress(removeButton); + await user.click(removeButton); act(() => jest.runAllTimers()); confirmationDialog = tree.getByRole('alertdialog'); expect(document.activeElement).toBe(confirmationDialog); confirmationDialogButton = within(confirmationDialog).getByRole('button'); expect(confirmationDialogButton).toBeInTheDocument(); - triggerPress(confirmationDialogButton); + await user.click(confirmationDialogButton); act(() => jest.runAllTimers()); options = within(listbox).getAllByRole('option'); expect(options.length).toBe(3); @@ -950,16 +960,17 @@ describe('ListBox', function () { describe('links', function () { describe.each(['mouse', 'keyboard'])('%s', (type) => { - let trigger = (item) => { + let user = userEvent.setup({delay: null, pointerMap}); + let trigger = async (item) => { if (type === 'mouse') { - triggerPress(item); + await user.click(item); } else { fireEvent.keyDown(item, {key: 'Enter'}); fireEvent.keyUp(item, {key: 'Enter'}); } }; - it('should support links with selectionMode="none"', function () { + it('should support links with selectionMode="none"', async function () { let {getAllByRole} = render( @@ -977,13 +988,13 @@ describe('ListBox', function () { let onClick = jest.fn().mockImplementation(e => e.preventDefault()); window.addEventListener('click', onClick, {once: true}); - trigger(items[0]); + await trigger(items[0]); expect(onClick).toHaveBeenCalledTimes(1); expect(onClick.mock.calls[0][0].target).toBeInstanceOf(HTMLAnchorElement); expect(onClick.mock.calls[0][0].target.href).toBe('https://google.com/'); }); - it.each(['single', 'multiple'])('should support links with selectionMode="%s"', function (selectionMode) { + it.each(['single', 'multiple'])('should support links with selectionMode="%s"', async function (selectionMode) { let {getAllByRole} = render( @@ -1001,7 +1012,7 @@ describe('ListBox', function () { let onClick = jest.fn().mockImplementation(e => e.preventDefault()); window.addEventListener('click', onClick, {once: true}); - trigger(items[0]); + await trigger(items[0]); expect(onClick).toHaveBeenCalledTimes(1); expect(onClick.mock.calls[0][0].target).toBeInstanceOf(HTMLAnchorElement); expect(onClick.mock.calls[0][0].target.href).toBe('https://google.com/'); @@ -1009,7 +1020,7 @@ describe('ListBox', function () { onClick = jest.fn().mockImplementation(e => e.preventDefault()); window.addEventListener('click', onClick, {once: true}); - trigger(items[1]); + await trigger(items[1]); expect(onClick).toHaveBeenCalledTimes(1); expect(onClick.mock.calls[0][0].target).toBeInstanceOf(HTMLAnchorElement); expect(onClick.mock.calls[0][0].target.href).toBe('https://adobe.com/'); @@ -1028,14 +1039,14 @@ describe('ListBox', function () { ); let items = getAllByRole('option'); - trigger(items[0]); + await trigger(items[0]); expect(navigate).toHaveBeenCalledWith('/one'); navigate.mockReset(); let onClick = jest.fn().mockImplementation(e => e.preventDefault()); window.addEventListener('click', onClick, {once: true}); - trigger(items[1]); + await trigger(items[1]); expect(navigate).not.toHaveBeenCalled(); expect(onClick).toHaveBeenCalledTimes(1); }); diff --git a/packages/@react-spectrum/menu/test/ActionMenu.test.js b/packages/@react-spectrum/menu/test/ActionMenu.test.js index 830f9fec8a3..b0a81acd236 100644 --- a/packages/@react-spectrum/menu/test/ActionMenu.test.js +++ b/packages/@react-spectrum/menu/test/ActionMenu.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, triggerPress, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; import {ActionMenu, Item} from '../'; import {Provider} from '@react-spectrum/provider'; import React from 'react'; @@ -38,7 +38,7 @@ describe('ActionMenu', function () { }); }); - it('basic test', function () { + it('basic test', async function () { let tree = render( Foo @@ -49,7 +49,7 @@ describe('ActionMenu', function () { let button = tree.getByRole('button'); expect(button).toHaveAttribute('aria-label', 'More actions'); - triggerPress(button); + await user.click(button); let menu = tree.getByRole('menu'); expect(menu).toBeTruthy(); @@ -63,7 +63,7 @@ describe('ActionMenu', function () { expect(menuItem2).toBeTruthy(); expect(menuItem3).toBeTruthy(); - triggerPress(menuItem1); + await user.click(menuItem1); expect(onActionSpy).toHaveBeenCalledTimes(1); }); @@ -80,7 +80,7 @@ describe('ActionMenu', function () { expect(button).toHaveAttribute('aria-label', 'Custom Aria Label'); }); - it('is disabled', function () { + it('is disabled', async function () { let tree = render( Foo @@ -91,7 +91,7 @@ describe('ActionMenu', function () { let button = tree.getByRole('button'); expect(button).toHaveAttribute('aria-label', 'More actions'); - triggerPress(button); + await user.click(button); let menu = tree.queryByRole('menu'); expect(menu).toBeNull(); @@ -110,7 +110,7 @@ describe('ActionMenu', function () { expect(document.activeElement).toBe(button); }); - it('supports a controlled open state ', function () { + it('supports a controlled open state ', async function () { let tree = render( @@ -128,7 +128,7 @@ describe('ActionMenu', function () { expect(menu).toBeTruthy(); let triggerButton = tree.getByLabelText('More actions'); - triggerPress(triggerButton); + await user.click(triggerButton); act(() => {jest.runAllTimers();}); menu = tree.getByRole('menu'); @@ -137,7 +137,7 @@ describe('ActionMenu', function () { expect(triggerButton).toHaveAttribute('aria-expanded', 'true'); }); - it('supports an uncontrolled default open state ', function () { + it('supports an uncontrolled default open state ', async function () { let tree = render( @@ -155,7 +155,7 @@ describe('ActionMenu', function () { expect(menu).toBeTruthy(); let triggerButton = tree.getByLabelText('More actions'); - triggerPress(triggerButton); + await user.click(triggerButton); act(() => {jest.runAllTimers();}); expect(menu).not.toBeInTheDocument(); diff --git a/packages/@react-spectrum/menu/test/Menu.test.js b/packages/@react-spectrum/menu/test/Menu.test.js index 01b6fb19f66..a177e8224c4 100644 --- a/packages/@react-spectrum/menu/test/Menu.test.js +++ b/packages/@react-spectrum/menu/test/Menu.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, render, triggerPress, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; import Bell from '@spectrum-icons/workflow/Bell'; import {Dialog, DialogTrigger} from '@react-spectrum/dialog'; import {Item, Menu, Section} from '../'; @@ -19,6 +19,7 @@ import {MenuContext} from '../src/context'; import {Provider} from '@react-spectrum/provider'; import React from 'react'; import {theme} from '@react-spectrum/theme-default'; +import userEvent from '@testing-library/user-event'; let menuId = 'menu-id'; @@ -243,14 +244,15 @@ describe('Menu', function () { it.each` Name | Component | props ${'Menu'} | ${Menu} | ${{selectionMode: 'single', onSelectionChange}} - `('$Name supports using click to change item selection', function ({Component, props}) { + `('$Name supports using click to change item selection', async function ({Component, props}) { + let user = userEvent.setup({delay: null, pointerMap}); let tree = renderComponent(Component, {}, props); let menu = tree.getByRole('menu'); let menuItems = within(menu).getAllByRole('menuitemradio'); // Trigger a menu item via press let item = menuItems[4]; - triggerPress(item); + await user.click(item); expect(item).toHaveAttribute('aria-checked', 'true'); let checkmark = within(item).getByRole('img', {hidden: true}); expect(checkmark).toBeTruthy(); @@ -267,14 +269,15 @@ describe('Menu', function () { it.each` Name | Component | props ${'Menu'} | ${Menu} | ${{selectionMode: 'single', onSelectionChange, disabledKeys: ['Baz']}} - `('$Name supports disabled items', function ({Component, props}) { + `('$Name supports disabled items', async function ({Component, props}) { + let user = userEvent.setup({delay: null, pointerMap}); let tree = renderComponent(Component, {}, props); let menu = tree.getByRole('menu'); let menuItems = within(menu).getAllByRole('menuitemradio'); // Attempt to trigger the disabled item let disabledItem = menuItems[2]; - triggerPress(disabledItem); + await user.click(disabledItem); expect(disabledItem).toHaveAttribute('aria-checked', 'false'); expect(disabledItem).toHaveAttribute('aria-disabled', 'true'); @@ -291,7 +294,8 @@ describe('Menu', function () { it.each` Name | Component | props ${'Menu'} | ${Menu} | ${{onSelectionChange, selectionMode: 'multiple'}} - `('$Name supports selecting multiple items', function ({Component, props}) { + `('$Name supports selecting multiple items', async function ({Component, props}) { + let user = userEvent.setup({delay: null, pointerMap}); let tree = renderComponent(Component, {}, props); let menu = tree.getByRole('menu'); @@ -301,14 +305,14 @@ describe('Menu', function () { let menuItems = within(menu).getAllByRole('menuitemcheckbox'); let firstItem = menuItems[3]; - triggerPress(firstItem); + await user.click(firstItem); expect(firstItem).toHaveAttribute('aria-checked', 'true'); let checkmark = within(firstItem).getByRole('img', {hidden: true}); expect(checkmark).toBeTruthy(); // Select a different menu item let secondItem = menuItems[1]; - triggerPress(secondItem); + await user.click(secondItem); expect(secondItem).toHaveAttribute('aria-checked', 'true'); checkmark = within(secondItem).getByRole('img', {hidden: true}); expect(checkmark).toBeTruthy(); @@ -325,7 +329,8 @@ describe('Menu', function () { it.each` Name | Component | props ${'Menu'} | ${Menu} | ${{onSelectionChange, selectionMode: 'multiple', defaultSelectedKeys: ['Foo', 'Bar']}} - `('$Name supports multiple defaultSelectedKeys (uncontrolled)', function ({Component, props}) { + `('$Name supports multiple defaultSelectedKeys (uncontrolled)', async function ({Component, props}) { + let user = userEvent.setup({delay: null, pointerMap}); let tree = renderComponent(Component, {}, props); let menu = tree.getByRole('menu'); @@ -350,7 +355,7 @@ describe('Menu', function () { // Select a different menu item let thirdItem = menuItems[4]; - triggerPress(thirdItem); + await user.click(thirdItem); expect(thirdItem).toHaveAttribute('aria-checked', 'true'); checkmark = within(thirdItem).getByRole('img', {hidden: true}); expect(checkmark).toBeTruthy(); @@ -368,7 +373,8 @@ describe('Menu', function () { it.each` Name | Component | props ${'Menu'} | ${Menu} | ${{onSelectionChange, selectionMode: 'multiple', selectedKeys: ['Foo', 'Bar']}} - `('$Name supports multiple selectedKeys (controlled)', function ({Component, props}) { + `('$Name supports multiple selectedKeys (controlled)', async function ({Component, props}) { + let user = userEvent.setup({delay: null, pointerMap}); let tree = renderComponent(Component, {}, props); let menu = tree.getByRole('menu'); @@ -393,7 +399,7 @@ describe('Menu', function () { // Select a different menu item let thirdItem = menuItems[4]; - triggerPress(thirdItem); + await user.click(thirdItem); expect(thirdItem).toHaveAttribute('aria-checked', 'false'); checkmark = within(thirdItem).queryByRole('img', {hidden: true}); expect(checkmark).toBeNull(); @@ -409,7 +415,8 @@ describe('Menu', function () { it.each` Name | Component | props ${'Menu'} | ${Menu} | ${{onSelectionChange, selectionMode: 'multiple', defaultSelectedKeys: ['Foo', 'Bar']}} - `('$Name supports deselection', function ({Component, props}) { + `('$Name supports deselection', async function ({Component, props}) { + let user = userEvent.setup({delay: null, pointerMap}); let tree = renderComponent(Component, {}, props); let menu = tree.getByRole('menu'); @@ -433,7 +440,7 @@ describe('Menu', function () { expect(checkmark).toBeTruthy(); // Deselect the first item - triggerPress(firstItem); + await user.click(firstItem); expect(firstItem).toHaveAttribute('aria-checked', 'false'); checkmark = within(firstItem).queryByRole('img', {hidden: true}); expect(checkmark).toBeNull(); @@ -449,14 +456,15 @@ describe('Menu', function () { it.each` Name | Component | props ${'Menu'} | ${Menu} | ${{onSelectionChange, selectionMode: 'multiple', defaultSelectedKeys: ['Foo', 'Bar'], disabledKeys: ['Baz']}} - `('$Name supports disabledKeys', function ({Component, props}) { + `('$Name supports disabledKeys', async function ({Component, props}) { + let user = userEvent.setup({delay: null, pointerMap}); let tree = renderComponent(Component, {}, props); let menu = tree.getByRole('menu'); // Attempt to trigger disabled item let menuItems = within(menu).getAllByRole('menuitemcheckbox'); let disabledItem = menuItems[2]; - triggerPress(disabledItem); + await user.click(disabledItem); expect(disabledItem).toHaveAttribute('aria-checked', 'false'); expect(disabledItem).toHaveAttribute('aria-disabled', 'true'); @@ -473,7 +481,8 @@ describe('Menu', function () { it.each` Name | Component | props ${'Menu'} | ${Menu} | ${{onSelectionChange, selectionMode: 'none'}} - `('$Name prevents selection of any items', function ({Component, props}) { + `('$Name prevents selection of any items', async function ({Component, props}) { + let user = userEvent.setup({delay: null, pointerMap}); let tree = renderComponent(Component, {}, props); let menu = tree.getByRole('menu'); @@ -486,7 +495,7 @@ describe('Menu', function () { let firstItem = menuItems[3]; let secondItem = menuItems[4]; let thirdItem = menuItems[1]; - triggerPress(firstItem); + await user.click(firstItem); fireEvent.keyDown(secondItem, {key: ' ', code: 32, charCode: 32}); fireEvent.keyDown(thirdItem, {key: 'Enter', code: 13, charCode: 13}); expect(firstItem).not.toHaveAttribute('aria-checked', 'true'); @@ -559,7 +568,8 @@ describe('Menu', function () { }); }); - it('supports DialogTrigger as a wrapper around items', function () { + it('supports DialogTrigger as a wrapper around items', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let tree = render( @@ -578,8 +588,8 @@ describe('Menu', function () { let menu = tree.getByRole('menu'); let menuItem = within(menu).getByRole('menuitem'); + await user.click(menuItem); act(() => { - triggerPress(menuItem); jest.runAllTimers(); }); @@ -596,7 +606,8 @@ describe('Menu', function () { }); describe('supports onAction', function () { - it('Menu with static list supports onAction', function () { + it('Menu with static list supports onAction', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let onAction = jest.fn(); let onSelectionChange = jest.fn(); let tree = render( @@ -617,22 +628,23 @@ describe('Menu', function () { within(menu).getByText('Three') ]; - triggerPress(item1); + await user.click(item1); expect(onAction).toHaveBeenCalledWith('One'); expect(onSelectionChange).toHaveBeenCalledTimes(0); - triggerPress(item2); + await user.click(item2); expect(onAction).toHaveBeenCalledWith('Two'); expect(onSelectionChange).toHaveBeenCalledTimes(0); - triggerPress(item3); + await user.click(item3); expect(onAction).toHaveBeenCalledWith('Three'); expect(onSelectionChange).toHaveBeenCalledTimes(0); }); - it('Menu with generative list supports onAction', function () { + it('Menu with generative list supports onAction', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let onAction = jest.fn(); let onSelectionChange = jest.fn(); let flatItems = [ @@ -658,17 +670,17 @@ describe('Menu', function () { within(menu).getByText('Three') ]; - triggerPress(item1); + await user.click(item1); expect(onAction).toHaveBeenCalledWith('One'); expect(onSelectionChange).toHaveBeenCalledTimes(0); - triggerPress(item2); + await user.click(item2); expect(onAction).toHaveBeenCalledWith('Two'); expect(onSelectionChange).toHaveBeenCalledTimes(0); - triggerPress(item3); + await user.click(item3); expect(onAction).toHaveBeenCalledWith('Three'); expect(onSelectionChange).toHaveBeenCalledTimes(0); }); @@ -738,7 +750,8 @@ describe('Menu', function () { describe('supports links', function () { describe.each(['mouse', 'keyboard'])('%s', (type) => { - it.each(['none', 'single', 'multiple'])('with selectionMode = %s', function (selectionMode) { + it.each(['none', 'single', 'multiple'])('with selectionMode = %s', async function (selectionMode) { + let user = userEvent.setup({delay: null, pointerMap}); let onAction = jest.fn(); let onSelectionChange = jest.fn(); let tree = render( @@ -766,7 +779,7 @@ describe('Menu', function () { window.addEventListener('click', onClick); if (type === 'mouse') { - triggerPress(items[1]); + await user.click(items[1]); } else { fireEvent.keyDown(items[1], {key: 'Enter'}); fireEvent.keyUp(items[1], {key: 'Enter'}); diff --git a/packages/@react-spectrum/menu/test/MenuTrigger.test.js b/packages/@react-spectrum/menu/test/MenuTrigger.test.js index 6659d2b17bd..e895be2d5f0 100644 --- a/packages/@react-spectrum/menu/test/MenuTrigger.test.js +++ b/packages/@react-spectrum/menu/test/MenuTrigger.test.js @@ -21,7 +21,6 @@ import { pointerMap, simulateDesktop, triggerLongPress, - triggerPress, triggerTouch } from '@react-spectrum/test-utils'; import {Dialog} from '@react-spectrum/dialog'; @@ -94,13 +93,13 @@ describe('MenuTrigger', function () { offsetHeight.mockReset(); }); - function verifyMenuToggle(Component, triggerProps = {}, menuProps = {}, triggerEvent) { + async function verifyMenuToggle(Component, triggerProps = {}, menuProps = {}, triggerEvent) { let tree = renderComponent(Component, triggerProps, menuProps); let triggerButton = tree.getByRole('button'); expect(onOpenChange).toBeCalledTimes(0); - triggerEvent(triggerButton); + await triggerEvent(triggerButton); act(() => {jest.runAllTimers();}); let menu = tree.getByRole('menu'); @@ -124,7 +123,7 @@ describe('MenuTrigger', function () { expect(onClose).toBeCalledTimes(0); } - triggerEvent(triggerButton, menu); + await triggerEvent(triggerButton, menu); act(() => {jest.runAllTimers();}); expect(menu).not.toBeInTheDocument(); @@ -159,8 +158,8 @@ describe('MenuTrigger', function () { it.each` Name | Component | props ${'MenuTrigger'} | ${MenuTrigger} | ${{onOpenChange}} - `('$Name toggles the menu display on button click', function ({Component, props}) { - verifyMenuToggle(Component, props, {}, (button) => triggerPress(button)); + `('$Name toggles the menu display on button click', async function ({Component, props}) { + await verifyMenuToggle(Component, props, {}, async (button) => await user.click(button)); }); // Enter and Space keypress tests are ommitted since useMenuTrigger doesn't have space and enter cases in it's key down @@ -169,8 +168,8 @@ describe('MenuTrigger', function () { it.each` Name | Component | props ${'MenuTrigger'} | ${MenuTrigger} | ${{onOpenChange}} - `('$Name can toggle the menu display via ArrowUp key', function ({Component, props}) { - verifyMenuToggle(Component, props, {}, (button, menu) => { + `('$Name can toggle the menu display via ArrowUp key', async function ({Component, props}) { + await verifyMenuToggle(Component, props, {}, (button, menu) => { if (!menu) { fireEvent.keyDown(button, {key: 'ArrowUp', code: 38, charCode: 38}); } else { @@ -182,8 +181,8 @@ describe('MenuTrigger', function () { it.each` Name | Component | props ${'MenuTrigger'} | ${MenuTrigger} | ${{onOpenChange}} - `('$Name can toggle the menu display via ArrowDown key', function ({Component, props}) { - verifyMenuToggle(Component, props, {}, (button, menu) => { + `('$Name can toggle the menu display via ArrowDown key', async function ({Component, props}) { + await verifyMenuToggle(Component, props, {}, (button, menu) => { if (!menu) { fireEvent.keyDown(button, {key: 'ArrowDown', code: 40, charCode: 40}); } else { @@ -196,7 +195,7 @@ describe('MenuTrigger', function () { it.each` Name | Component | props ${'MenuTrigger'} | ${MenuTrigger} | ${{onOpenChange, isOpen: true}} - `('$Name supports a controlled open state ', function ({Component, props}) { + `('$Name supports a controlled open state ', async function ({Component, props}) { let tree = renderComponent(Component, props); act(() => {jest.runAllTimers();}); expect(onOpenChange).toBeCalledTimes(0); @@ -205,7 +204,7 @@ describe('MenuTrigger', function () { expect(menu).toBeTruthy(); let triggerButton = tree.getByText('Menu Button'); - triggerPress(triggerButton); + await user.click(triggerButton); act(() => {jest.runAllTimers();}); menu = tree.getByRole('menu'); @@ -217,7 +216,7 @@ describe('MenuTrigger', function () { it.each` Name | Component | props ${'MenuTrigger'} | ${MenuTrigger} | ${{onOpenChange, defaultOpen: true}} - `('$Name supports a uncontrolled default open state ', function ({Component, props}) { + `('$Name supports a uncontrolled default open state ', async function ({Component, props}) { let tree = renderComponent(Component, props); act(() => {jest.runAllTimers();}); expect(onOpenChange).toBeCalledTimes(0); @@ -226,7 +225,7 @@ describe('MenuTrigger', function () { expect(menu).toBeTruthy(); let triggerButton = tree.getByText('Menu Button'); - triggerPress(triggerButton); + await user.click(triggerButton); act(() => {jest.runAllTimers();}); expect(menu).not.toBeInTheDocument(); @@ -236,10 +235,10 @@ describe('MenuTrigger', function () { it.each` Name | Component | props ${'MenuTrigger'} | ${MenuTrigger} | ${{onOpenChange}} - `('$Name does not trigger on disabled button', function ({Component, props}) { + `('$Name does not trigger on disabled button', async function ({Component, props}) { let tree = renderComponent(Component, props, {}, {isDisabled: true}); let button = tree.getByRole('button'); - triggerPress(button); + await user.click(button); act(() => {jest.runAllTimers();}); let menu = tree.queryByRole('menu'); expect(menu).toBeNull(); @@ -250,18 +249,18 @@ describe('MenuTrigger', function () { it.each` Name | Component | props ${'MenuTrigger'} | ${MenuTrigger} | ${{}} - `('$Name autofocuses the selected item on menu open', function ({Component, props}) { + `('$Name autofocuses the selected item on menu open', async function ({Component, props}) { let tree = renderComponent(Component, props, {selectedKeys: ['Bar']}); act(() => {jest.runAllTimers();}); let button = tree.getByRole('button'); - triggerPress(button); + await user.click(button); act(() => {jest.runAllTimers();}); let menu = tree.getByRole('menu'); expect(menu).toBeTruthy(); let menuItems = within(menu).getAllByRole('menuitem'); let selectedItem = menuItems[1]; expect(selectedItem).toBe(document.activeElement); - triggerPress(button); + await user.click(button); act(() => {jest.runAllTimers();}); expect(menu).not.toBeInTheDocument(); @@ -275,7 +274,7 @@ describe('MenuTrigger', function () { menuItems = within(menu).getAllByRole('menuitem'); selectedItem = menuItems[1]; expect(selectedItem).toBe(document.activeElement); - triggerPress(button); + await user.click(button); act(() => {jest.runAllTimers();}); expect(menu).not.toBeInTheDocument(); @@ -361,9 +360,9 @@ describe('MenuTrigger', function () { tree = null; }); - function openAndTriggerMenuItem(tree, role, selectionMode, triggerEvent) { + async function openAndTriggerMenuItem(tree, role, selectionMode, triggerEvent) { let triggerButton = tree.getByRole('button'); - act(() => triggerPress(triggerButton)); + await user.click(triggerButton); act(() => jest.runAllTimers()); let menu = tree.getByRole('menu'); @@ -380,9 +379,7 @@ describe('MenuTrigger', function () { let menuItems = within(menu).getAllByRole(menuItemRole); let itemToAction = menuItems[1]; - act(() => { - triggerEvent(itemToAction); - }); + await triggerEvent(itemToAction); act(() => {jest.runAllTimers();}); // FocusScope useLayoutEffect cleanup act(() => {jest.runAllTimers();}); // FocusScope raf } @@ -390,10 +387,10 @@ describe('MenuTrigger', function () { it.each` Name | Component | props ${'MenuTrigger'} | ${MenuTrigger} | ${{onOpenChange}} - `('$Name closes the menu upon clicking escape key', function ({Component, props}) { + `('$Name closes the menu upon clicking escape key', async function ({Component, props}) { tree = renderComponent(Component, props); let button = tree.getByRole('button'); - triggerPress(button); + await user.click(button); act(() => {jest.runAllTimers();}); let menu = tree.getByRole('menu'); @@ -408,11 +405,11 @@ describe('MenuTrigger', function () { it.each` Name | Component | props ${'MenuTrigger'} | ${MenuTrigger} | ${{onOpenChange}} - `('$Name does not clear selection with escape', function ({Component, props}) { + `('$Name does not clear selection with escape', async function ({Component, props}) { let onSelectionChange = jest.fn(); tree = renderComponent(Component, props, {selectionMode: 'multiple', defaultSelectedKeys: ['Foo'], onSelectionChange}); let button = tree.getByRole('button'); - triggerPress(button); + await user.click(button); act(() => {jest.runAllTimers();}); expect(onSelectionChange).not.toHaveBeenCalled(); @@ -427,7 +424,7 @@ describe('MenuTrigger', function () { expect(onSelectionChange).not.toHaveBeenCalled(); // reopen and make sure we still have the selection - triggerPress(button); + await user.click(button); act(() => {jest.runAllTimers();}); expect(onSelectionChange).not.toHaveBeenCalled(); @@ -441,10 +438,10 @@ describe('MenuTrigger', function () { it.each` Name | Component | props ${'MenuTrigger'} | ${MenuTrigger} | ${{onOpenChange}} - `('$Name closes the menu upon clicking outside the menu', function ({Component, props}) { + `('$Name closes the menu upon clicking outside the menu', async function ({Component, props}) { tree = renderComponent(Component, props); let button = tree.getByRole('button'); - triggerPress(button); + await user.click(button); act(() => {jest.runAllTimers();}); let menu = tree.getByRole('menu'); @@ -460,11 +457,11 @@ describe('MenuTrigger', function () { it.each` Name | Component | props ${'MenuTrigger'} | ${MenuTrigger} | ${{onOpenChange, closeOnSelect: false}} - `('$Name doesn\'t close on menu item selection if closeOnSelect=false', function ({Component, props}) { + `('$Name doesn\'t close on menu item selection if closeOnSelect=false', async function ({Component, props}) { tree = renderComponent(Component, props, {selectionMode: 'single', onSelectionChange}); expect(onOpenChange).toBeCalledTimes(0); let button = tree.getByRole('button'); - triggerPress(button); + await user.click(button); act(() => {jest.runAllTimers();}); let menu = tree.getByRole('menu'); @@ -480,7 +477,7 @@ describe('MenuTrigger', function () { let menuItem1 = within(menu).getByText('Foo'); expect(menuItem1).toBeTruthy(); - triggerPress(menuItem1); + await user.click(menuItem1); if (Component === MenuTrigger) { expect(onSelectionChange).toBeCalledTimes(1); @@ -503,11 +500,11 @@ describe('MenuTrigger', function () { it.each` Name | Component | props ${'MenuTrigger'} | ${MenuTrigger} | ${{onOpenChange, closeOnSelect: false}} - `('$Name doesn\'t closes menu on item selection via ENTER press if closeOnSelect=false', function ({Component, props}) { + `('$Name doesn\'t closes menu on item selection via ENTER press if closeOnSelect=false', async function ({Component, props}) { tree = renderComponent(Component, props, {selectionMode: 'single', onSelectionChange}); expect(onOpenChange).toBeCalledTimes(0); let button = tree.getByRole('button'); - triggerPress(button); + await user.click(button); act(() => {jest.runAllTimers();}); let menu = tree.getByRole('menu'); @@ -530,9 +527,9 @@ describe('MenuTrigger', function () { it.each` Name | Component | props | menuProps ${'MenuTrigger multiple'} | ${MenuTrigger} | ${{}} | ${{selectionMode: 'multiple'}} - `('$Name doesn\'t close menu on item selection via mouse with multiple selection', function ({Component, props, menuProps}) { + `('$Name doesn\'t close menu on item selection via mouse with multiple selection', async function ({Component, props, menuProps}) { tree = renderComponent(Component, props, menuProps); - openAndTriggerMenuItem(tree, props.role, menuProps.selectionMode, (item) => triggerPress(item)); + await openAndTriggerMenuItem(tree, props.role, menuProps.selectionMode, async (item) => await user.click(item)); let menu = tree.getByRole('menu'); expect(menu).toBeTruthy(); @@ -543,9 +540,9 @@ describe('MenuTrigger', function () { ${'MenuTrigger single'} | ${MenuTrigger} | ${{}} | ${{selectionMode: 'single', onClose}} ${'MenuTrigger multiple'} | ${MenuTrigger} | ${{closeOnSelect: true}} | ${{selectionMode: 'multiple', onClose}} ${'MenuTrigger none'} | ${MenuTrigger} | ${{}} | ${{selectionMode: 'none', onClose}} - `('$Name closes on menu item selection if toggled by mouse click', function ({Component, props, menuProps}) { + `('$Name closes on menu item selection if toggled by mouse click', async function ({Component, props, menuProps}) { tree = renderComponent(Component, props, menuProps); - openAndTriggerMenuItem(tree, props.role, menuProps.selectionMode, (item) => triggerPress(item)); + await openAndTriggerMenuItem(tree, props.role, menuProps.selectionMode, async (item) => await user.click(item)); let menu = tree.queryByRole('menu'); expect(menu).toBeNull(); @@ -558,9 +555,9 @@ describe('MenuTrigger', function () { ${'MenuTrigger single'} | ${MenuTrigger} | ${{}} | ${{selectionMode: 'single', onClose}} ${'MenuTrigger multiple'} | ${MenuTrigger} | ${{}} | ${{selectionMode: 'multiple', onClose}} ${'MenuTrigger none'} | ${MenuTrigger} | ${{}} | ${{selectionMode: 'none', onClose}} - `('$Name closes on menu item selection if toggled by ENTER key', function ({Component, props, menuProps}) { + `('$Name closes on menu item selection if toggled by ENTER key', async function ({Component, props, menuProps}) { tree = renderComponent(Component, props, menuProps); - openAndTriggerMenuItem(tree, props.role, menuProps.selectionMode, (item) => fireEvent.keyDown(item, {key: 'Enter', code: 13, charCode: 13})); + await openAndTriggerMenuItem(tree, props.role, menuProps.selectionMode, (item) => fireEvent.keyDown(item, {key: 'Enter', code: 13, charCode: 13})); let menu = tree.queryByRole('menu'); expect(menu).toBeNull(); @@ -572,9 +569,9 @@ describe('MenuTrigger', function () { Name | Component | props | menuProps ${'MenuTrigger single'} | ${MenuTrigger} | ${{}} | ${{selectionMode: 'single', onClose}} ${'MenuTrigger multiple'} | ${MenuTrigger} | ${{}} | ${{selectionMode: 'multiple', onClose}} - `('$Name doesn\'t close on menu item selection if toggled by SPACE key (all selection modes except "none")', function ({Component, props, menuProps}) { + `('$Name doesn\'t close on menu item selection if toggled by SPACE key (all selection modes except "none")', async function ({Component, props, menuProps}) { tree = renderComponent(Component, props, menuProps); - openAndTriggerMenuItem(tree, props.role, menuProps.selectionMode, (item) => fireEvent.keyDown(item, {key: ' ', code: 32, charCode: 32})); + await openAndTriggerMenuItem(tree, props.role, menuProps.selectionMode, (item) => fireEvent.keyDown(item, {key: ' ', code: 32, charCode: 32})); let menu = tree.queryByRole('menu'); expect(menu).toBeTruthy(); @@ -584,9 +581,9 @@ describe('MenuTrigger', function () { it.each` Name | Component | props | menuProps ${'MenuTrigger none'} | ${MenuTrigger} | ${{}} | ${{selectionMode: 'none', onClose}} - `('$Name closes on menu item selection if toggled by SPACE key (selectionMode=none)', function ({Component, props, menuProps}) { + `('$Name closes on menu item selection if toggled by SPACE key (selectionMode=none)', async function ({Component, props, menuProps}) { tree = renderComponent(Component, props, menuProps); - openAndTriggerMenuItem(tree, props.role, menuProps.selectionMode, (item) => fireEvent.keyDown(item, {key: ' ', code: 32, charCode: 32})); + await openAndTriggerMenuItem(tree, props.role, menuProps.selectionMode, (item) => fireEvent.keyDown(item, {key: ' ', code: 32, charCode: 32})); let menu = tree.queryByRole('menu'); expect(menu).toBeNull(); @@ -597,11 +594,11 @@ describe('MenuTrigger', function () { it.each` Name | Component | props ${'MenuTrigger'} | ${MenuTrigger} | ${{onOpenChange, onClose}} - `('$Name closes the menu when blurring the menu', function ({Component, props}) { + `('$Name closes the menu when blurring the menu', async function ({Component, props}) { tree = renderComponent(Component, props, {}); expect(onOpenChange).toBeCalledTimes(0); let button = tree.getByRole('button'); - triggerPress(button); + await user.click(button); act(() => {jest.runAllTimers();}); let menu = tree.getByRole('menu'); @@ -622,15 +619,15 @@ describe('MenuTrigger', function () { ${'MenuTrigger single'} | ${MenuTrigger} | ${{}} | ${{selectionMode: 'single'}} ${'MenuTrigger multiple'} | ${MenuTrigger} | ${{}} | ${{selectionMode: 'multiple'}} ${'MenuTrigger none'} | ${MenuTrigger} | ${{}} | ${{selectionMode: 'none'}} - `('$Name ignores repeating keyboard events', function ({Component, props, menuProps}) { + `('$Name ignores repeating keyboard events', async function ({Component, props, menuProps}) { tree = renderComponent(Component, props, menuProps); - openAndTriggerMenuItem(tree, props.role, menuProps.selectionMode, (item) => fireEvent.keyDown(item, {key: 'Enter', code: 13, charCode: 13, repeat: true})); + await openAndTriggerMenuItem(tree, props.role, menuProps.selectionMode, (item) => fireEvent.keyDown(item, {key: 'Enter', code: 13, charCode: 13, repeat: true})); let menu = tree.queryByRole('menu'); expect(menu).toBeTruthy(); }); - it('tabs to the next element after the trigger and closes the menu', function () { + it('tabs to the next element after the trigger and closes the menu', async function () { tree = render( @@ -651,7 +648,7 @@ describe('MenuTrigger', function () { ); let button = tree.getByRole('button'); - triggerPress(button); + await user.click(button); act(() => {jest.runAllTimers();}); let menu = tree.getByRole('menu'); @@ -669,7 +666,7 @@ describe('MenuTrigger', function () { expect(onOpenChange).toBeCalledTimes(2); }); - it('should have a hidden dismiss button for screen readers', function () { + it('should have a hidden dismiss button for screen readers', async function () { let {getByRole, getAllByLabelText} = render( @@ -688,9 +685,7 @@ describe('MenuTrigger', function () { ); let button = getByRole('button'); - act(() => { - triggerPress(button); - }); + await user.click(button); act(() => jest.runAllTimers()); let menu = getByRole('menu'); @@ -772,7 +767,7 @@ describe('MenuTrigger', function () { expect(checkmark).toBeNull(); }); - it('two menus can not be open at the same time', function () { + it('two menus can not be open at the same time', async function () { let {getAllByRole, getByRole, queryByRole} = render( @@ -797,20 +792,20 @@ describe('MenuTrigger', function () { ); let [button1, button2] = getAllByRole('button'); - triggerPress(button1); + await user.click(button1); act(() => jest.runAllTimers()); let menu = getByRole('menu'); let menuItem1 = within(menu).getByText('Alpha'); expect(menuItem1).toBeInTheDocument(); // pressing once on button 2 should close menu1, but not open menu2 yet - triggerPress(button2); + await user.click(button2); act(() => {jest.runAllTimers();}); // FocusScope useLayoutEffect cleanup act(() => {jest.runAllTimers();}); // FocusScope raf expect(queryByRole('menu')).toBeNull(); // second press of button2 should open menu2 - triggerPress(button2); + await user.click(button2); act(() => jest.runAllTimers()); let menu2 = getByRole('menu'); let menu2Item1 = within(menu2).getByText('Whiskey'); @@ -831,9 +826,9 @@ describe('MenuTrigger', function () { } }; - it('should open the menu on longPress', function () { + it('should open the menu on longPress', async function () { const props = {onOpenChange, trigger: 'longPress'}; - verifyMenuToggle(MenuTrigger, props, {}, (button, menu) => { + await verifyMenuToggle(MenuTrigger, props, {}, (button, menu) => { expect(button).toHaveAttribute('aria-describedby'); expect(document.getElementById(button.getAttribute('aria-describedby'))).toHaveTextContent('Long press or press Alt + ArrowDown to open menu'); @@ -899,9 +894,9 @@ describe('MenuTrigger', function () { }); }); - it('should open the menu on Alt+ArrowUp', function () { + it('should open the menu on Alt+ArrowUp', async function () { const props = {onOpenChange, trigger: 'longPress'}; - verifyMenuToggle(MenuTrigger, props, {}, (button, menu) => { + await verifyMenuToggle(MenuTrigger, props, {}, (button, menu) => { if (!menu) { fireEvent.keyDown(button, {key: 'ArrowUp', altKey: true}); } else { @@ -910,9 +905,9 @@ describe('MenuTrigger', function () { }); }); - it('should open the menu on Alt+ArrowDown', function () { + it('should open the menu on Alt+ArrowDown', async function () { const props = {onOpenChange, trigger: 'longPress'}; - verifyMenuToggle(MenuTrigger, props, {}, (button, menu) => { + await verifyMenuToggle(MenuTrigger, props, {}, (button, menu) => { if (!menu) { fireEvent.keyDown(button, {key: 'ArrowDown', altKey: true}); } else { @@ -1030,17 +1025,17 @@ describe('MenuTrigger', function () { ); }; - let openMenu = () => { + let openMenu = async () => { let triggerButton = tree.getByRole('button'); - triggerPress(triggerButton); + await user.click(triggerButton); act(() => {jest.runAllTimers();}); return tree.getByRole('menu'); }; - it('adds the expected spectrum icon', function () { + it('adds the expected spectrum icon', async function () { renderTree(); - let menu = openMenu(); + let menu = await openMenu(); let unavailableItem = within(menu).getAllByRole('menuitem')[1]; expect(unavailableItem).toBeVisible(); @@ -1048,9 +1043,9 @@ describe('MenuTrigger', function () { expect(icon).not.toHaveAttribute('aria-hidden'); }); - it('can open a sub dialog with hover', function () { + it('can open a sub dialog with hover', async function () { renderTree(); - let menu = openMenu(); + let menu = await openMenu(); let menuItems = within(menu).getAllByRole('menuitem'); let unavailableItem = menuItems[1]; expect(unavailableItem).toBeVisible(); @@ -1069,9 +1064,9 @@ describe('MenuTrigger', function () { expect(document.activeElement).toBe(menuItems[2]); }); - it('can not open a sub dialog with hover if isUnavailable is false', function () { + it('can not open a sub dialog with hover if isUnavailable is false', async function () { renderTree({isItem2Unavailable: false}); - let menu = openMenu(); + let menu = await openMenu(); let menuItems = within(menu).getAllByRole('menuitem'); let availableItem = menuItems[1]; expect(availableItem).toBeVisible(); @@ -1088,9 +1083,9 @@ describe('MenuTrigger', function () { expect(tree.queryByRole('dialog')).toBeNull(); }); - it('can open a sub dialog with keyboard', function () { + it('can open a sub dialog with keyboard', async function () { renderTree(); - let menu = openMenu(); + let menu = await openMenu(); fireEvent.keyDown(document.activeElement, {key: 'ArrowDown'}); fireEvent.keyUp(document.activeElement, {key: 'ArrowDown'}); fireEvent.keyDown(document.activeElement, {key: 'ArrowDown'}); @@ -1107,7 +1102,7 @@ describe('MenuTrigger', function () { it('will close sub dialogs as you hover other items even if you click open it', async function () { renderTree(); - let menu = openMenu(); + let menu = await openMenu(); let menuItems = within(menu).getAllByRole('menuitem'); let unavailableItem = menuItems[1]; expect(unavailableItem).toBeVisible(); @@ -1150,7 +1145,7 @@ describe('MenuTrigger', function () { it('will close everything if the user shift tabs out of the subdialog', async function () { renderTree(); - let menu = openMenu(); + let menu = await openMenu(); let menuItems = within(menu).getAllByRole('menuitem'); let unavailableItem = menuItems[4]; expect(unavailableItem).toBeVisible(); @@ -1171,9 +1166,9 @@ describe('MenuTrigger', function () { expect(document.activeElement).toBe(unavailableItem); }); - it('will close everything if the user shift tabs out of the subdialog', function () { + it('will close everything if the user shift tabs out of the subdialog', async function () { renderTree({providerProps: {locale: 'ar-AE'}}); - let menu = openMenu(); + let menu = await openMenu(); fireEvent.keyDown(document.activeElement, {key: 'ArrowDown'}); fireEvent.keyUp(document.activeElement, {key: 'ArrowDown'}); fireEvent.keyDown(document.activeElement, {key: 'ArrowDown'}); @@ -1188,9 +1183,9 @@ describe('MenuTrigger', function () { expect(dialog).toBeVisible(); }); - it('should close everything if the user clicks on the underlay of the root menu', function () { + it('should close everything if the user clicks on the underlay of the root menu', async function () { renderTree(); - let menu = openMenu(); + let menu = await openMenu(); let menuItems = within(menu).getAllByRole('menuitem'); let unavailableItem = menuItems[4]; expect(unavailableItem).toBeVisible(); diff --git a/packages/@react-spectrum/numberfield/test/NumberField.test.js b/packages/@react-spectrum/numberfield/test/NumberField.test.js index 05cdb9a5f8f..68b3afbcbcf 100644 --- a/packages/@react-spectrum/numberfield/test/NumberField.test.js +++ b/packages/@react-spectrum/numberfield/test/NumberField.test.js @@ -11,7 +11,7 @@ */ jest.mock('@react-aria/live-announcer'); -import {act, fireEvent, pointerMap, render, triggerPress, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; import {announce} from '@react-aria/live-announcer'; import {Button} from '@react-spectrum/button'; import {chain} from '@react-aria/utils'; @@ -267,7 +267,7 @@ describe('NumberField', function () { act(() => {textField.blur();}); expect(onChangeSpy).toHaveBeenLastCalledWith(0); expect(onChangeSpy).toHaveBeenCalledTimes(1); - triggerPress(incrementButton); + await user.click(incrementButton); expect(onChangeSpy).toHaveBeenLastCalledWith(5); expect(onChangeSpy).toHaveBeenCalledTimes(2); expect(onBlurSpy).toHaveBeenCalledTimes(1); @@ -278,7 +278,7 @@ describe('NumberField', function () { act(() => {textField.blur();}); expect(onChangeSpy).toHaveBeenLastCalledWith(5); expect(onChangeSpy).toHaveBeenCalledTimes(2); - triggerPress(incrementButton); + await user.click(incrementButton); expect(onChangeSpy).toHaveBeenLastCalledWith(10); expect(onChangeSpy).toHaveBeenCalledTimes(3); expect(onBlurSpy).toHaveBeenCalledTimes(2); // blur spy is called after each blur @@ -371,34 +371,34 @@ describe('NumberField', function () { it.each` Name ${'NumberField'} - `('$Name increment value by one when increment button is pressed', () => { + `('$Name increment value by one when increment button is pressed', async () => { let {incrementButton} = renderNumberField({defaultValue: 0, onChange: onChangeSpy}); - triggerPress(incrementButton); + await user.click(incrementButton); expect(onChangeSpy).toHaveBeenCalledWith(1); }); it.each` Name ${'NumberField'} - `('$Name decrement value by one when increment button is pressed', () => { + `('$Name decrement value by one when increment button is pressed', async () => { let {decrementButton} = renderNumberField({defaultValue: 0, onChange: onChangeSpy}); - triggerPress(decrementButton); + await user.click(decrementButton); expect(onChangeSpy).toHaveBeenCalledWith(-1); }); it.each` Name ${'NumberField'} - `('$Name use step for increasing and decreasing value', () => { + `('$Name use step for increasing and decreasing value', async () => { let {decrementButton, incrementButton} = renderNumberField({defaultValue: 0, step: 10, onChange: onChangeSpy}); - triggerPress(decrementButton); + await user.click(decrementButton); expect(onChangeSpy).toHaveBeenCalledWith(-10); onChangeSpy.mockReset(); - triggerPress(incrementButton); + await user.click(incrementButton); expect(onChangeSpy).toHaveBeenCalledWith(0); }); @@ -471,7 +471,7 @@ describe('NumberField', function () { it.each` Name ${'NumberField'} - `('$Name onChange is not called when controlled at minValue and decrement is pressed', () => { + `('$Name onChange is not called when controlled at minValue and decrement is pressed', async () => { let { container, decrementButton @@ -480,14 +480,14 @@ describe('NumberField', function () { expect(container).toBeTruthy(); expect(container).toHaveAttribute('role', 'group'); expect(container).not.toHaveAttribute('aria-invalid'); - triggerPress(decrementButton); + await user.click(decrementButton); expect(onChangeSpy).toHaveBeenCalledTimes(0); }); it.each` Name ${'v3 NumberField'} - `('$Name onChange is not called when controlled at maxValue and increment is pressed', () => { + `('$Name onChange is not called when controlled at maxValue and increment is pressed', async () => { let { container, incrementButton @@ -496,7 +496,7 @@ describe('NumberField', function () { expect(container).toBeTruthy(); expect(container).toHaveAttribute('role', 'group'); expect(container).not.toHaveAttribute('aria-invalid'); - triggerPress(incrementButton); + await user.click(incrementButton); expect(onChangeSpy).toHaveBeenCalledTimes(0); }); @@ -544,7 +544,7 @@ describe('NumberField', function () { } = renderNumberField({onChange: onChangeSpy, onBlur: onBlurSpy}); expect(textField).toHaveAttribute('value', ''); - triggerPress(incrementButton); + await user.click(incrementButton); expect(textField).toHaveAttribute('value', '0'); expect(onChangeSpy).toHaveBeenCalledTimes(1); expect(onChangeSpy).toHaveBeenCalledWith(0); @@ -558,7 +558,7 @@ describe('NumberField', function () { expect(onChangeSpy).toHaveBeenLastCalledWith(NaN); expect(onBlurSpy).toHaveBeenCalledTimes(1); - triggerPress(decrementButton); + await user.click(decrementButton); expect(textField).toHaveAttribute('value', '0'); expect(onChangeSpy).toHaveBeenCalledTimes(3); expect(onChangeSpy).toHaveBeenCalledWith(0); @@ -576,7 +576,7 @@ describe('NumberField', function () { } = renderNumberField({onChange: onChangeSpy, minValue: 3}); expect(textField).toHaveAttribute('value', ''); - triggerPress(incrementButton); + await user.click(incrementButton); expect(textField).toHaveAttribute('value', '3'); expect(onChangeSpy).toHaveBeenCalledTimes(1); expect(onChangeSpy).toHaveBeenCalledWith(3); @@ -588,7 +588,7 @@ describe('NumberField', function () { expect(onChangeSpy).toHaveBeenCalledTimes(2); expect(onChangeSpy).toHaveBeenLastCalledWith(NaN); - triggerPress(decrementButton); + await user.click(decrementButton); expect(textField).toHaveAttribute('value', '3'); expect(onChangeSpy).toHaveBeenCalledTimes(3); expect(onChangeSpy).toHaveBeenLastCalledWith(3); @@ -605,7 +605,7 @@ describe('NumberField', function () { } = renderNumberField({onChange: onChangeSpy, maxValue: 3}); expect(textField).toHaveAttribute('value', ''); - triggerPress(decrementButton); + await user.click(decrementButton); expect(textField).toHaveAttribute('value', '3'); expect(onChangeSpy).toHaveBeenCalledTimes(1); expect(onChangeSpy).toHaveBeenCalledWith(3); @@ -617,7 +617,7 @@ describe('NumberField', function () { expect(onChangeSpy).toHaveBeenCalledTimes(2); expect(onChangeSpy).toHaveBeenLastCalledWith(NaN); - triggerPress(incrementButton); + await user.click(incrementButton); expect(textField).toHaveAttribute('value', '0'); expect(onChangeSpy).toHaveBeenCalledTimes(3); expect(onChangeSpy).toHaveBeenLastCalledWith(0); @@ -777,7 +777,7 @@ describe('NumberField', function () { expect(textField).toHaveAttribute('value', '25%'); expect(onChangeSpy).toHaveBeenLastCalledWith(0.25); act(() => {textField.focus();}); - triggerPress(incrementButton); + await user.click(incrementButton); act(() => {textField.blur();}); expect(textField).toHaveAttribute('value', '26%'); expect(onChangeSpy).toHaveBeenLastCalledWith(0.26); @@ -827,14 +827,14 @@ describe('NumberField', function () { it.each` Name ${'NumberField'} - `('$Name properly formats value when value changes', () => { + `('$Name properly formats value when value changes', async () => { let {textField, incrementButton, decrementButton} = renderNumberField({defaultValue: 10, formatOptions: {style: 'currency', currency: 'EUR'}}); expect(textField).toHaveAttribute('value', '€10.00'); - triggerPress(incrementButton); + await user.click(incrementButton); expect(textField).toHaveAttribute('value', '€11.00'); - triggerPress(decrementButton); - triggerPress(decrementButton); + await user.click(decrementButton); + await user.click(decrementButton); expect(textField).toHaveAttribute('value', '€9.00'); }); @@ -867,7 +867,7 @@ describe('NumberField', function () { let {textField, incrementButton} = renderNumberField({onChange: onChangeSpy, defaultValue: -10, formatOptions: {style: 'currency', currency: 'USD', currencySign: 'accounting'}}); expect(textField).toHaveAttribute('value', '($10.00)'); - triggerPress(incrementButton); + await user.click(incrementButton); expect(textField).toHaveAttribute('value', '($9.00)'); expect(onChangeSpy).toHaveBeenCalledTimes(1); expect(onChangeSpy).toHaveBeenCalledWith(-9); @@ -947,7 +947,7 @@ describe('NumberField', function () { }, {locale: 'el-GR'}); expect(textField).toHaveAttribute('value', '-10,00 $'); - triggerPress(incrementButton); + await user.click(incrementButton); expect(textField).toHaveAttribute('value', '-9,00 $'); expect(onChangeSpy).toHaveBeenCalledTimes(1); expect(onChangeSpy).toHaveBeenCalledWith(-9); @@ -1002,14 +1002,14 @@ describe('NumberField', function () { ${'US Euros negative'} | ${{defaultValue: -10, formatOptions: {style: 'currency', currency: 'EUR'}}} | ${'en-US'} | ${['-€10.00', '-€9.00', '-€11.00']} ${'French Euros negative'} | ${{defaultValue: -10, formatOptions: {style: 'currency', currency: 'EUR'}}} | ${'fr-FR'} | ${['-10,00 €', '-9,00 €', '-11,00 €']} ${'Arabic Euros negative'} | ${{defaultValue: -10, formatOptions: {style: 'currency', currency: 'EUR'}}} | ${'ar-AE'} | ${['‏‎-10.00 €', '‏‎-9.00 €', '‏‎-11.00 €']} - `('$Name pressing increment & decrement keeps formatting', ({props, locale, expected}) => { + `('$Name pressing increment & decrement keeps formatting', async ({props, locale, expected}) => { let {textField, incrementButton, decrementButton} = renderNumberField({minValue: -15, ...props}, {locale}); expect(textField).toHaveAttribute('value', expected[0]); - triggerPress(incrementButton); + await user.click(incrementButton); expect(textField).toHaveAttribute('value', expected[1]); - triggerPress(decrementButton); - triggerPress(decrementButton); + await user.click(decrementButton); + await user.click(decrementButton); expect(textField).toHaveAttribute('value', expected[2]); }); @@ -1413,13 +1413,13 @@ describe('NumberField', function () { act(() => {textField.focus();}); await user.keyboard('1'); - triggerPress(incrementButton); + await user.click(incrementButton); expect(onChangeSpy).toHaveBeenCalledWith(1.001); - triggerPress(incrementButton); + await user.click(incrementButton); expect(onChangeSpy).toHaveBeenCalledWith(1.002); - triggerPress(incrementButton); + await user.click(incrementButton); expect(onChangeSpy).toHaveBeenCalledWith(1.003); - triggerPress(incrementButton); + await user.click(incrementButton); expect(onChangeSpy).toHaveBeenCalledWith(1.004); act(() => {textField.blur();}); }); @@ -1432,7 +1432,7 @@ describe('NumberField', function () { act(() => {textField.focus();}); await user.keyboard('2'); - triggerPress(incrementButton); + await user.click(incrementButton); expect(onChangeSpy).toHaveBeenCalledTimes(1); expect(onChangeSpy).toHaveBeenLastCalledWith(5); act(() => {textField.blur();}); @@ -1445,7 +1445,7 @@ describe('NumberField', function () { act(() => {textField.focus();}); await user.keyboard('3'); - triggerPress(incrementButton); + await user.click(incrementButton); expect(onChangeSpy).toHaveBeenCalledTimes(3); expect(onChangeSpy).toHaveBeenLastCalledWith(5); act(() => {textField.blur();}); @@ -1466,7 +1466,7 @@ describe('NumberField', function () { act(() => {textField.focus();}); await user.keyboard('2'); expect(textField).toHaveAttribute('value', '2'); - triggerPress(incrementButton); + await user.click(incrementButton); expect(onChangeSpy).toHaveBeenCalledTimes(1); expect(onChangeSpy).toHaveBeenCalledWith(3); expect(textField).toHaveAttribute('value', '3'); @@ -1476,7 +1476,7 @@ describe('NumberField', function () { await user.clear(textField); await user.keyboard('2'); expect(textField).toHaveAttribute('value', '2'); - triggerPress(incrementButton); + await user.click(incrementButton); expect(onChangeSpy).toHaveBeenCalledTimes(1); expect(textField).toHaveAttribute('value', '3'); act(() => {textField.blur();}); @@ -1491,7 +1491,7 @@ describe('NumberField', function () { act(() => {textField.focus();}); await user.keyboard('2'); expect(textField).toHaveAttribute('value', '2'); - triggerPress(decrementButton); + await user.click(decrementButton); expect(onChangeSpy).toHaveBeenCalledTimes(1); expect(onChangeSpy).toHaveBeenCalledWith(1); expect(textField).toHaveAttribute('value', '1'); @@ -1501,7 +1501,7 @@ describe('NumberField', function () { await user.clear(textField); await user.keyboard('2'); expect(textField).toHaveAttribute('value', '2'); - triggerPress(decrementButton); + await user.click(decrementButton); expect(onChangeSpy).toHaveBeenCalledTimes(1); expect(textField).toHaveAttribute('value', '1'); act(() => {textField.blur();}); @@ -1712,14 +1712,14 @@ describe('NumberField', function () { it.each` Name | props ${'NumberField controlled'} | ${{value: 10, onChange: onChangeSpy}} - `('$Name 10 is rendered and will not change the value in the input for steppers', ({props}) => { + `('$Name 10 is rendered and will not change the value in the input for steppers', async ({props}) => { let {textField, incrementButton, decrementButton} = renderNumberField(props); expect(textField).toHaveAttribute('value', '10'); - triggerPress(incrementButton); + await user.click(incrementButton); expect(textField).toHaveAttribute('value', '10'); expect(onChangeSpy).toHaveBeenCalledTimes(1); expect(onChangeSpy).toHaveBeenCalledWith(11); - triggerPress(decrementButton); + await user.click(decrementButton); expect(textField).toHaveAttribute('value', '10'); expect(onChangeSpy).toHaveBeenCalledTimes(2); expect(onChangeSpy).toHaveBeenCalledWith(9); @@ -1742,7 +1742,7 @@ describe('NumberField', function () { it.each` Name ${'NumberField controlled'} - `('$Name 10 is rendered and will change if the controlled version is implemented', () => { + `('$Name 10 is rendered and will change if the controlled version is implemented', async () => { function NumberFieldControlled(props) { let {onChange} = props; let [value, setValue] = useState(10); @@ -1759,11 +1759,11 @@ describe('NumberField', function () { let incrementButton = buttons[0]; let decrementButton = buttons[1]; expect(textField).toHaveAttribute('value', '€10.00'); - triggerPress(incrementButton); + await user.click(incrementButton); expect(textField).toHaveAttribute('value', '€11.00'); expect(onChangeSpy).toHaveBeenCalledTimes(1); expect(onChangeSpy).toHaveBeenCalledWith(11); - triggerPress(decrementButton); + await user.click(decrementButton); expect(onChangeSpy).toHaveBeenCalledTimes(2); expect(onChangeSpy).toHaveBeenLastCalledWith(10); expect(textField).toHaveAttribute('value', '€10.00'); @@ -2198,7 +2198,7 @@ describe('NumberField', function () { }); }); - it('can be reset to blank using null', () => { + it('can be reset to blank using null', async () => { function NumberFieldControlled(props) { let {onChange} = props; let [value, setValue] = useState(10); @@ -2219,7 +2219,7 @@ describe('NumberField', function () { let resetButton = getByText('Reset'); expect(textField).toHaveAttribute('value', '10'); - triggerPress(resetButton); + await user.click(resetButton); expect(resetSpy).toHaveBeenCalledTimes(1); expect(textField).toHaveAttribute('value', ''); }); diff --git a/packages/@react-spectrum/overlays/test/Popover.test.js b/packages/@react-spectrum/overlays/test/Popover.test.js index 0050b801766..a688f680ea5 100644 --- a/packages/@react-spectrum/overlays/test/Popover.test.js +++ b/packages/@react-spectrum/overlays/test/Popover.test.js @@ -10,13 +10,14 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, render, triggerPress, waitFor} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, waitFor} from '@react-spectrum/test-utils'; import {Dialog} from '@react-spectrum/dialog'; import {Popover} from '../'; import {Provider} from '@react-spectrum/provider'; import React, {useRef} from 'react'; import {theme} from '@react-spectrum/theme-default'; import {useOverlayTriggerState} from '@react-stately/overlays'; +import userEvent from '@testing-library/user-event'; function PopoverWithDialog({children}) { let ref = useRef(); @@ -203,6 +204,7 @@ describe('Popover', function () { }); it('hides the popover when clicking outside', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let onOpenChange = jest.fn(); let {getByTestId} = render( @@ -216,7 +218,7 @@ describe('Popover', function () { await waitFor(() => { expect(getByTestId('popover')).toBeVisible(); }); // wait for animation - triggerPress(document.body); + await user.click(document.body); expect(onOpenChange).toHaveBeenCalledTimes(1); }); diff --git a/packages/@react-spectrum/picker/test/Picker.test.js b/packages/@react-spectrum/picker/test/Picker.test.js index acfe90e4283..ce4af54fa9f 100644 --- a/packages/@react-spectrum/picker/test/Picker.test.js +++ b/packages/@react-spectrum/picker/test/Picker.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, simulateDesktop, triggerPress, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, simulateDesktop, within} from '@react-spectrum/test-utils'; import AlignCenter from '@spectrum-icons/workflow/AlignCenter'; import AlignLeft from '@spectrum-icons/workflow/AlignLeft'; import AlignRight from '@spectrum-icons/workflow/AlignRight'; @@ -76,7 +76,7 @@ describe('Picker', function () { }); describe('opening', function () { - it('can be opened on mouse down', function () { + it('can be opened on mouse down', async function () { let onOpenChange = jest.fn(); let {getByRole, queryByRole} = render( @@ -93,7 +93,7 @@ describe('Picker', function () { let picker = getByRole('button'); // make sure to run through mousedown AND mouseup, like would really happen, otherwise a mouseup listener // sits around until the component is unmounted - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); @@ -406,7 +406,7 @@ describe('Picker', function () { expect(document.activeElement).toBe(listbox); }); - it('scrolls the selected item into view on menu open', function () { + it('scrolls the selected item into view on menu open', async function () { let scrollToSpy = jest.fn(); let virtualizerMock = jest.spyOn(Virtualizer.prototype, 'scrollToItem').mockImplementationOnce(scrollToSpy); // Mock scroll height so that the picker heights actually have a value @@ -424,7 +424,7 @@ describe('Picker', function () { expect(queryByRole('listbox')).toBeNull(); let picker = getByRole('button'); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); @@ -438,7 +438,7 @@ describe('Picker', function () { }); describe('closing', function () { - it('can be closed by clicking on the button', function () { + it('can be closed by clicking on the button', async function () { let onOpenChange = jest.fn(); let {getByRole, queryByRole} = render( @@ -453,7 +453,7 @@ describe('Picker', function () { expect(queryByRole('listbox')).toBeNull(); let picker = getByRole('button'); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); @@ -463,7 +463,7 @@ describe('Picker', function () { expect(picker).toHaveAttribute('aria-expanded', 'true'); expect(picker).toHaveAttribute('aria-controls', listbox.id); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); expect(listbox).not.toBeInTheDocument(); @@ -477,7 +477,7 @@ describe('Picker', function () { expect(document.activeElement).toBe(picker); }); - it('can be closed by clicking outside', function () { + it('can be closed by clicking outside', async function () { let onOpenChange = jest.fn(); let {getByRole, queryByRole} = render( @@ -492,7 +492,7 @@ describe('Picker', function () { expect(queryByRole('listbox')).toBeNull(); let picker = getByRole('button'); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); @@ -502,7 +502,7 @@ describe('Picker', function () { expect(picker).toHaveAttribute('aria-expanded', 'true'); expect(picker).toHaveAttribute('aria-controls', listbox.id); - triggerPress(document.body); + await user.click(document.body); act(() => jest.runAllTimers()); expect(listbox).not.toBeInTheDocument(); @@ -512,7 +512,7 @@ describe('Picker', function () { expect(onOpenChange).toHaveBeenCalledWith(false); }); - it('can be closed by pressing the Escape key', function () { + it('can be closed by pressing the Escape key', async function () { let onOpenChange = jest.fn(); let {getByRole, queryByRole} = render( @@ -527,7 +527,7 @@ describe('Picker', function () { expect(queryByRole('listbox')).toBeNull(); let picker = getByRole('button'); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); @@ -551,7 +551,7 @@ describe('Picker', function () { expect(document.activeElement).toBe(picker); }); - it('closes on blur', function () { + it('closes on blur', async function () { let onOpenChange = jest.fn(); let {getByRole, queryByRole} = render( @@ -566,7 +566,7 @@ describe('Picker', function () { expect(queryByRole('listbox')).toBeNull(); let picker = getByRole('button'); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); @@ -589,7 +589,7 @@ describe('Picker', function () { expect(document.activeElement).toBe(picker); }); - it('tabs to the next element after the trigger and closes the menu', function () { + it('tabs to the next element after the trigger and closes the menu', async function () { let onOpenChange = jest.fn(); let {getByRole, getByTestId} = render( @@ -604,7 +604,7 @@ describe('Picker', function () { ); let picker = getByRole('button'); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); @@ -626,7 +626,7 @@ describe('Picker', function () { expect(document.activeElement).toBe(getByTestId('after-input')); }); - it('shift tabs to the previous element before the trigger and closes the menu', function () { + it('shift tabs to the previous element before the trigger and closes the menu', async function () { let onOpenChange = jest.fn(); let {getByRole, getByTestId} = render( @@ -641,7 +641,7 @@ describe('Picker', function () { ); let picker = getByRole('button'); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); @@ -677,7 +677,7 @@ describe('Picker', function () { ); let picker = getByRole('button'); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); @@ -692,7 +692,7 @@ describe('Picker', function () { expect(dismissButtons[0]).toHaveAttribute('aria-label', 'Dismiss'); expect(dismissButtons[1]).toHaveAttribute('aria-label', 'Dismiss'); - triggerPress(dismissButtons[0]); + await user.click(dismissButtons[0]); expect(onOpenChange).toHaveBeenCalledTimes(2); expect(onOpenChange).toHaveBeenCalledWith(true); act(() => jest.runAllTimers()); @@ -794,7 +794,7 @@ describe('Picker', function () { expect(document.activeElement).toBe(picker); }); - it('supports labeling with a visible label', function () { + it('supports labeling with a visible label', async function () { let {getAllByText, getByText, getByRole} = render( @@ -814,7 +814,7 @@ describe('Picker', function () { expect(value).toHaveAttribute('id'); expect(picker).toHaveAttribute('aria-labelledby', `${value.id} ${label.id}`); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); @@ -822,7 +822,7 @@ describe('Picker', function () { expect(listbox).toHaveAttribute('aria-labelledby', label.id); }); - it('supports labeling via aria-label', function () { + it('supports labeling via aria-label', async function () { let {getByText, getByRole} = render( @@ -840,7 +840,7 @@ describe('Picker', function () { expect(picker).toHaveAttribute('aria-label', 'Test'); expect(picker).toHaveAttribute('aria-labelledby', `${value.id} ${picker.id}`); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); @@ -848,7 +848,7 @@ describe('Picker', function () { expect(listbox).toHaveAttribute('aria-labelledby', picker.id); }); - it('supports labeling via aria-labelledby', function () { + it('supports labeling via aria-labelledby', async function () { let {getByText, getByRole} = render( @@ -865,7 +865,7 @@ describe('Picker', function () { expect(value).toHaveAttribute('id'); expect(picker).toHaveAttribute('aria-labelledby', `${value.id} foo`); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); @@ -873,7 +873,7 @@ describe('Picker', function () { expect(listbox).toHaveAttribute('aria-labelledby', 'foo'); }); - it('supports labeling via aria-label and aria-labelledby', function () { + it('supports labeling via aria-label and aria-labelledby', async function () { let {getByText, getByRole} = render( @@ -891,7 +891,7 @@ describe('Picker', function () { expect(picker).toHaveAttribute('aria-label', 'Test'); expect(picker).toHaveAttribute('aria-labelledby', `${value.id} ${picker.id} foo`); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); @@ -900,7 +900,7 @@ describe('Picker', function () { }); describe('isRequired', function () { - it('supports labeling with a visible label that includes the necessity indicator', function () { + it('supports labeling with a visible label that includes the necessity indicator', async function () { let {getByText, getByRole} = render( @@ -924,7 +924,7 @@ describe('Picker', function () { expect(value).toHaveAttribute('id'); expect(picker).toHaveAttribute('aria-labelledby', `${value.id} ${label.id}`); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); @@ -971,7 +971,7 @@ describe('Picker', function () { }); describe('selection', function () { - it('can select items on press', function () { + it('can select items on press', async function () { let {getByRole} = render( @@ -984,7 +984,7 @@ describe('Picker', function () { let picker = getByRole('button'); expect(picker).toHaveTextContent('Select an option…'); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); @@ -996,7 +996,7 @@ describe('Picker', function () { expect(document.activeElement).toBe(listbox); - triggerPress(items[2]); + await user.click(items[2]); expect(onSelectionChange).toHaveBeenCalledTimes(1); expect(onSelectionChange).toHaveBeenLastCalledWith('three'); act(() => jest.runAllTimers()); @@ -1008,7 +1008,7 @@ describe('Picker', function () { expect(picker).toHaveTextContent('Three'); }); - it('can select items with falsy keys', function () { + it('can select items with falsy keys', async function () { let {getByRole} = render( @@ -1021,7 +1021,7 @@ describe('Picker', function () { let picker = getByRole('button'); expect(picker).toHaveTextContent('Select an option…'); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); @@ -1033,7 +1033,7 @@ describe('Picker', function () { expect(document.activeElement).toBe(listbox); - triggerPress(items[0]); + await user.click(items[0]); expect(onSelectionChange).toHaveBeenCalledTimes(1); expect(onSelectionChange).toHaveBeenLastCalledWith(''); act(() => jest.runAllTimers()); @@ -1044,13 +1044,13 @@ describe('Picker', function () { expect(document.activeElement).toBe(picker); expect(picker).toHaveTextContent('Empty'); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); listbox = getByRole('listbox'); let item1 = within(listbox).getByText('Zero'); - triggerPress(item1); + await user.click(item1); expect(onSelectionChange).toHaveBeenCalledTimes(2); expect(onSelectionChange).toHaveBeenLastCalledWith('0'); act(() => jest.runAllTimers()); @@ -1061,13 +1061,13 @@ describe('Picker', function () { expect(document.activeElement).toBe(picker); expect(picker).toHaveTextContent('Zero'); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); listbox = getByRole('listbox'); let item2 = within(listbox).getByText('False'); - triggerPress(item2); + await user.click(item2); expect(onSelectionChange).toHaveBeenCalledTimes(3); expect(onSelectionChange).toHaveBeenLastCalledWith('false'); act(() => jest.runAllTimers()); @@ -1079,7 +1079,7 @@ describe('Picker', function () { expect(picker).toHaveTextContent('False'); }); - it('can select items with the Space key', function () { + it('can select items with the Space key', async function () { let {getByRole} = render( @@ -1092,7 +1092,7 @@ describe('Picker', function () { let picker = getByRole('button'); expect(picker).toHaveTextContent('Select an option…'); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); @@ -1170,7 +1170,7 @@ describe('Picker', function () { expect(picker).toHaveTextContent('Two'); }); - it('focuses items on hover', function () { + it('focuses items on hover', async function () { let {getByRole} = render( @@ -1183,7 +1183,7 @@ describe('Picker', function () { let picker = getByRole('button'); expect(picker).toHaveTextContent('Select an option…'); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); @@ -1215,7 +1215,7 @@ describe('Picker', function () { expect(picker).toHaveTextContent('Three'); }); - it('does not clear selection on escape closing the listbox', function () { + it('does not clear selection on escape closing the listbox', async function () { let onOpenChangeSpy = jest.fn(); let {getAllByText, getByRole, queryByRole} = render( @@ -1230,7 +1230,7 @@ describe('Picker', function () { let picker = getByRole('button'); expect(picker).toHaveTextContent('Select an option…'); expect(onOpenChangeSpy).toHaveBeenCalledTimes(0); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); expect(onOpenChangeSpy).toHaveBeenCalledTimes(1); @@ -1246,14 +1246,14 @@ describe('Picker', function () { expect(item2).toBeTruthy(); expect(item3).toBeTruthy(); - triggerPress(item3); + await user.click(item3); expect(onSelectionChange).toHaveBeenCalledTimes(1); act(() => jest.runAllTimers()); expect(onOpenChangeSpy).toHaveBeenCalledTimes(2); expect(queryByRole('listbox')).toBeNull(); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); expect(onOpenChangeSpy).toHaveBeenCalledTimes(3); @@ -1275,7 +1275,7 @@ describe('Picker', function () { expect(picker).toHaveTextContent('Three'); }); - it('supports controlled selection', function () { + it('supports controlled selection', async function () { let {getByRole} = render( @@ -1288,7 +1288,7 @@ describe('Picker', function () { let picker = getByRole('button'); expect(picker).toHaveTextContent('Two'); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); @@ -1319,7 +1319,7 @@ describe('Picker', function () { expect(picker).toHaveTextContent('Two'); }); - it('supports default selection', function () { + it('supports default selection', async function () { let {getByRole} = render( @@ -1332,7 +1332,7 @@ describe('Picker', function () { let picker = getByRole('button'); expect(picker).toHaveTextContent('Two'); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); @@ -1363,7 +1363,7 @@ describe('Picker', function () { expect(picker).toHaveTextContent('One'); }); - it('skips disabled items', function () { + it('skips disabled items', async function () { let {getByRole} = render( @@ -1376,7 +1376,7 @@ describe('Picker', function () { let picker = getByRole('button'); expect(picker).toHaveTextContent('Select an option…'); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); @@ -1410,7 +1410,7 @@ describe('Picker', function () { expect(picker).toHaveTextContent('Three'); }); - it('supports sections and complex items', function () { + it('supports sections and complex items', async function () { let {getAllByRole, getByRole, getByText} = render( @@ -1449,7 +1449,7 @@ describe('Picker', function () { let picker = getByRole('button'); expect(picker).toHaveTextContent('Select an option…'); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); @@ -1502,7 +1502,7 @@ describe('Picker', function () { expect(getAllByRole('img', {hidden: true})).toHaveLength(2); // Open again - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); listbox = getByRole('listbox'); @@ -1600,7 +1600,7 @@ describe('Picker', function () { expect(onSelectionChange).toHaveBeenLastCalledWith(''); }); - it('does not deselect when pressing an already selected item', function () { + it('does not deselect when pressing an already selected item', async function () { let {getByRole} = render( @@ -1613,7 +1613,7 @@ describe('Picker', function () { let picker = getByRole('button'); expect(picker).toHaveTextContent('Two'); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); @@ -1621,7 +1621,7 @@ describe('Picker', function () { expect(document.activeElement).toBe(items[1]); - triggerPress(items[1]); + await user.click(items[1]); expect(onSelectionChange).toHaveBeenCalledTimes(1); expect(onSelectionChange).toHaveBeenCalledWith('two'); act(() => jest.runAllTimers()); @@ -1877,7 +1877,7 @@ describe('Picker', function () { expect(picker).toHaveAttribute('aria-describedby', `${description.id}`); }); - it('should display a spinner inside the listbox when loading more', function () { + it('should display a spinner inside the listbox when loading more', async function () { let items = [{name: 'Foo'}, {name: 'Bar'}]; let {getByRole, rerender} = render( @@ -1888,7 +1888,7 @@ describe('Picker', function () { ); let picker = getByRole('button'); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); @@ -1930,7 +1930,7 @@ describe('Picker', function () { expect(select).toBeDisabled(); }); - it('does not open on mouse down when isDisabled is true', function () { + it('does not open on mouse down when isDisabled is true', async function () { let onOpenChange = jest.fn(); let {getByRole, queryByRole} = render( @@ -1945,7 +1945,7 @@ describe('Picker', function () { expect(queryByRole('listbox')).toBeNull(); let picker = getByRole('button'); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); expect(queryByRole('listbox')).toBeNull(); @@ -2214,13 +2214,13 @@ describe('Picker', function () { let input = document.querySelector('[name=picker]'); expect(input).toHaveValue('one'); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); let items = within(listbox).getAllByRole('option'); expect(items.length).toBe(3); - triggerPress(items[1]); + await user.click(items[1]); expect(input).toHaveValue('two'); let button = getByTestId('reset'); @@ -2480,7 +2480,7 @@ describe('Picker', function () { ); let button = tree.getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); @@ -2494,7 +2494,7 @@ describe('Picker', function () { expect(items[1]).toHaveAttribute('href', 'https://adobe.com'); if (type === 'mouse') { - triggerPress(items[0]); + await user.click(items[0]); } else { fireEvent.keyDown(items[0], {key: 'Enter'}); fireEvent.keyUp(items[0], {key: 'Enter'}); @@ -2519,14 +2519,14 @@ describe('Picker', function () { ); let button = tree.getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); let listbox = tree.getByRole('listbox'); let items = within(listbox).getAllByRole('option'); - triggerPress(items[0]); + await user.click(items[0]); expect(navigate).toHaveBeenCalledWith('/one'); }); }); diff --git a/packages/@react-spectrum/provider/test/Provider.test.tsx b/packages/@react-spectrum/provider/test/Provider.test.tsx index ed7d068e411..0256bcd671f 100644 --- a/packages/@react-spectrum/provider/test/Provider.test.tsx +++ b/packages/@react-spectrum/provider/test/Provider.test.tsx @@ -13,7 +13,7 @@ // needs to be imported first import MatchMediaMock from 'jest-matchmedia-mock'; // eslint-disable-next-line rsp-rules/sort-imports -import {act, fireEvent, pointerMap, render, triggerPress} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render} from '@react-spectrum/test-utils'; import {ActionButton, Button} from '@react-spectrum/button'; import {Checkbox} from '@react-spectrum/checkbox'; import {Provider} from '../'; @@ -146,7 +146,7 @@ describe('Provider', () => { expect(provider2.classList.contains('spectrum--light')).toBeTruthy(); }); - it('Nested providers pass props to children', () => { + it('Nested providers pass props to children', async () => { let onPressSpy = jest.fn(); let {getByRole} = render( @@ -156,7 +156,7 @@ describe('Provider', () => { ); let button = getByRole('button'); - triggerPress(button); + await user.click(button); expect(onPressSpy).not.toHaveBeenCalled(); expect(button.classList.contains('spectrum-ActionButton--quiet')).toBeTruthy(); onPressSpy.mockClear(); diff --git a/packages/@react-spectrum/searchfield/test/SearchField.test.js b/packages/@react-spectrum/searchfield/test/SearchField.test.js index 6e7ac8fc756..4ca4146ff0d 100644 --- a/packages/@react-spectrum/searchfield/test/SearchField.test.js +++ b/packages/@react-spectrum/searchfield/test/SearchField.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, triggerPress, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; import Checkmark from '@spectrum-icons/workflow/Checkmark'; import React from 'react'; import {SearchField} from '../'; @@ -183,12 +183,13 @@ describe('Search', () => { it.each` Name | Component ${'v3 SearchField'} | ${SearchField} - `('$Name clears the input field if the clear button is pressed and the field is uncontrolled', ({Component}) => { + `('$Name clears the input field if the clear button is pressed and the field is uncontrolled', async ({Component}) => { + let user = userEvent.setup({delay: null, pointerMap}); let tree = renderComponent(Component, {defaultValue: inputText, onChange, onClear}); let input = tree.getByTestId(testId); let clearButton = tree.getByLabelText('Clear search'); expect(input.value).toBe(inputText); - triggerPress(clearButton); + await user.click(clearButton); expect(onChange).toBeCalledTimes(1); expect(onChange).toHaveBeenLastCalledWith(''); diff --git a/packages/@react-spectrum/searchwithin/test/SearchWithin.test.js b/packages/@react-spectrum/searchwithin/test/SearchWithin.test.js index db9fe94f68d..1eae6baeaac 100644 --- a/packages/@react-spectrum/searchwithin/test/SearchWithin.test.js +++ b/packages/@react-spectrum/searchwithin/test/SearchWithin.test.js @@ -9,7 +9,7 @@ * OF ANY KIND, either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ -import {act, pointerMap, render, triggerPress} from '@react-spectrum/test-utils'; +import {act, pointerMap, render} from '@react-spectrum/test-utils'; import Filter from '@spectrum-icons/workflow/Filter'; import {Item, Picker} from '@react-spectrum/picker'; import {Provider} from '@react-spectrum/provider'; @@ -96,12 +96,12 @@ describe('SearchWithin', function () { expect(onChange).toBeCalledTimes(11); }); - it('can open menu and get onChange', function () { + it('can open menu and get onChange', async function () { let onOpenChange = jest.fn(); let {getByRole} = renderSearchWithin({}, {}, {onOpenChange}); let picker = getByRole('button'); - triggerPress(picker); + await user.click(picker); let listbox = getByRole('listbox'); expect(listbox).toBeVisible(); @@ -109,14 +109,14 @@ describe('SearchWithin', function () { expect(onOpenChange).toHaveBeenCalledWith(true); }); - it('searchfield and picker are labelled correctly', function () { + it('searchfield and picker are labelled correctly', async function () { let {getByRole, getAllByText, getByText} = renderSearchWithin(); let searchfield = getByRole('searchbox'); let picker = getByRole('button'); let group = getByRole('group'); let hiddenLabel = getByText('Search within'); - triggerPress(picker); + await user.click(picker); let listbox = getByRole('listbox'); let label = getAllByText('Test')[0]; @@ -151,7 +151,7 @@ describe('SearchWithin', function () { expect(picker).toHaveFocus(); }); - it('slot props override props provided to children', function () { + it('slot props override props provided to children', async function () { let {getByRole, getAllByText, getByText} = renderSearchWithin( {isDisabled: true, isRequired: false, label: 'Test1'}, {isDisabled: false, isRequired: true, label: 'Test2', isQuiet: true}, @@ -162,7 +162,7 @@ describe('SearchWithin', function () { let picker = getByRole('button'); let group = getByRole('group'); let hiddenLabel = getByText('Search within'); - triggerPress(picker); + await user.click(picker); let label = getAllByText('Test1')[0]; expect(searchfield).toHaveAttribute('disabled'); diff --git a/packages/@react-spectrum/table/test/TreeGridTable.test.tsx b/packages/@react-spectrum/table/test/TreeGridTable.test.tsx index 54902c253ad..b6903bf4fb3 100644 --- a/packages/@react-spectrum/table/test/TreeGridTable.test.tsx +++ b/packages/@react-spectrum/table/test/TreeGridTable.test.tsx @@ -17,7 +17,6 @@ import { installPointerEvent, pointerMap, render as renderComponent, - triggerPress, within } from '@react-spectrum/test-utils'; import {announce} from '@react-aria/live-announcer'; @@ -80,8 +79,15 @@ let rerender = (tree, children, scale = 'medium' as Scale) => { return newTree; }; + describe('TableView with expandable rows', function () { let user; + let shiftClick = async (node) => { + await user.keyboard('{Shift>}'); + await user.click(node); + await user.keyboard('{/Shift}'); + }; + beforeAll(function () { jest.spyOn(window.HTMLElement.prototype, 'clientWidth', 'get').mockImplementation(() => 1000); jest.spyOn(window.HTMLElement.prototype, 'clientHeight', 'get').mockImplementation(() => 1000); @@ -335,7 +341,7 @@ describe('TableView with expandable rows', function () { describe('collapsing and expanding rows', function () { describe('with press', function () { - it('should expand a row when pressing the chevron', function () { + it('should expand a row when pressing the chevron', async function () { let treegrid = render(); let rowgroups = treegrid.getAllByRole('rowgroup'); let rows = within(rowgroups[1]).getAllByRole('row'); @@ -351,7 +357,7 @@ describe('TableView with expandable rows', function () { let chevron = within(rowToExpand).getByRole('button'); expect(chevron).toBeTruthy(); expect(chevron).toHaveAttribute('aria-label', 'Expand'); - triggerPress(chevron); + await user.click(chevron); act(() => jest.runAllTimers()); expect(onExpandedChange).toHaveBeenCalledTimes(1); @@ -377,7 +383,7 @@ describe('TableView with expandable rows', function () { expect(fourthRow).toHaveTextContent('Lvl 2 Foo 2'); }); - it('should collapse a row when pressing the chevron', function () { + it('should collapse a row when pressing the chevron', async function () { let treegrid = render(); let rowgroups = treegrid.getAllByRole('rowgroup'); let rows = within(rowgroups[1]).getAllByRole('row'); @@ -392,7 +398,7 @@ describe('TableView with expandable rows', function () { let chevron = within(rowToCollapse).getByRole('button'); expect(chevron).toBeTruthy(); expect(chevron).toHaveAttribute('aria-label', 'Collapse'); - triggerPress(chevron); + await user.click(chevron); act(() => jest.runAllTimers()); expect(onExpandedChange).toHaveBeenCalledTimes(1); @@ -882,7 +888,7 @@ describe('TableView with expandable rows', function () { describe('row selection', function () { describe('with pointer', function () { - it('should select a row when clicking on the chevron cell', function () { + it('should select a row when clicking on the chevron cell', async function () { let treegrid = render(); let rowgroups = treegrid.getAllByRole('rowgroup'); let rows = within(rowgroups[1]).getAllByRole('row'); @@ -891,26 +897,26 @@ describe('TableView with expandable rows', function () { expect(chevron).toHaveAttribute('aria-label', 'Collapse'); checkRowSelection(rows, false); - triggerPress(chevronCell); + await user.click(chevronCell); checkSelection(onSelectionChange, [ 'Row 1 Lvl 1' ]); checkRowSelection(rows.slice(0, 1), true); onSelectionChange.mockReset(); - triggerPress(chevron); + await user.click(chevron); expect(onSelectionChange).not.toHaveBeenCalled(); checkRowSelection(rows.slice(0, 1), true); }); - it('should select a nested row on click', function () { + it('should select a nested row on click', async function () { let treegrid = render(); let rowgroups = treegrid.getAllByRole('rowgroup'); let rows = within(rowgroups[1]).getAllByRole('row'); let cell = getCell(treegrid, 'Row 1, Lvl 3, Foo'); checkRowSelection(rows, false); - triggerPress(cell); + await user.click(cell); checkSelection(onSelectionChange, [ 'Row 1 Lvl 3' ]); @@ -978,28 +984,28 @@ describe('TableView with expandable rows', function () { }); }); - it('should select nested rows if select all checkbox is pressed', function () { + it('should select nested rows if select all checkbox is pressed', async function () { let treegrid = render(); let checkbox = treegrid.getByLabelText('Select All'); let rowgroups = treegrid.getAllByRole('rowgroup'); let rows = within(rowgroups[1]).getAllByRole('row'); - triggerPress(checkbox); + await user.click(checkbox); checkRowSelection(rows, true); checkSelectAll(treegrid, 'checked'); }); - it('should not allow selection of disabled nested rows', function () { + it('should not allow selection of disabled nested rows', async function () { let treegrid = render(); let rowgroups = treegrid.getAllByRole('rowgroup'); let rows = within(rowgroups[1]).getAllByRole('row'); let cell = getCell(treegrid, 'Row 1, Lvl 2, Foo'); - triggerPress(cell); + await user.click(cell); expect(onSelectionChange).not.toHaveBeenCalled(); checkRowSelection(rows, false); let checkbox = treegrid.getByLabelText('Select All'); - triggerPress(checkbox); + await user.click(checkbox); expect(onSelectionChange).toHaveBeenCalledTimes(1); expect(new Set(onSelectionChange.mock.calls[0][0]).has('Row 1 Lvl 2')).toBeFalsy(); checkRowSelection([rows[1]], false); @@ -1008,16 +1014,16 @@ describe('TableView with expandable rows', function () { describe('range selection', function () { describe('with pointer', function () { - it('should support selecting a range from a top level row to a nested row', function () { + it('should support selecting a range from a top level row to a nested row', async function () { let treegrid = render(); let rowgroups = treegrid.getAllByRole('rowgroup'); let rows = within(rowgroups[1]).getAllByRole('row'); checkRowSelection(rows, false); - triggerPress(getCell(treegrid, 'Row 1, Lvl 1, Foo')); + await user.click(getCell(treegrid, 'Row 1, Lvl 1, Foo')); onSelectionChange.mockReset(); - triggerPress(getCell(treegrid, 'Row 2, Lvl 3, Foo'), {shiftKey: true}); + await shiftClick(getCell(treegrid, 'Row 2, Lvl 3, Foo')); checkSelection(onSelectionChange, [ 'Row 1 Lvl 1', 'Row 1 Lvl 2', 'Row 1 Lvl 3', 'Row 2 Lvl 1', 'Row 2 Lvl 2', 'Row 2 Lvl 3' ]); @@ -1025,16 +1031,16 @@ describe('TableView with expandable rows', function () { checkRowSelection(rows.slice(6), false); }); - it('should support selecting a range from a nested row to a top level row', function () { + it('should support selecting a range from a nested row to a top level row', async function () { let treegrid = render(); let rowgroups = treegrid.getAllByRole('rowgroup'); let rows = within(rowgroups[1]).getAllByRole('row'); checkRowSelection(rows, false); - triggerPress(getCell(treegrid, 'Row 2, Lvl 3, Foo')); + await user.click(getCell(treegrid, 'Row 2, Lvl 3, Foo')); onSelectionChange.mockReset(); - triggerPress(getCell(treegrid, 'Row 1, Lvl 1, Foo'), {shiftKey: true}); + await shiftClick(getCell(treegrid, 'Row 1, Lvl 1, Foo')); checkSelection(onSelectionChange, [ 'Row 1 Lvl 1', 'Row 1 Lvl 2', 'Row 1 Lvl 3', 'Row 2 Lvl 1', 'Row 2 Lvl 2', 'Row 2 Lvl 3' ]); @@ -1042,16 +1048,16 @@ describe('TableView with expandable rows', function () { checkRowSelection(rows.slice(6), false); }); - it('should support selecting a range from a top level row to a descendent child row', function () { + it('should support selecting a range from a top level row to a descendent child row', async function () { let treegrid = render(); let rowgroups = treegrid.getAllByRole('rowgroup'); let rows = within(rowgroups[1]).getAllByRole('row'); checkRowSelection(rows, false); - triggerPress(getCell(treegrid, 'Row 1, Lvl 1, Foo')); + await user.click(getCell(treegrid, 'Row 1, Lvl 1, Foo')); onSelectionChange.mockReset(); - triggerPress(getCell(treegrid, 'Row 1, Lvl 3, Foo'), {shiftKey: true}); + await shiftClick(getCell(treegrid, 'Row 1, Lvl 3, Foo')); checkSelection(onSelectionChange, [ 'Row 1 Lvl 1', 'Row 1 Lvl 2', 'Row 1 Lvl 3' ]); @@ -1059,16 +1065,16 @@ describe('TableView with expandable rows', function () { checkRowSelection(rows.slice(3), false); }); - it('should support selecting a range from a nested child row to its top level row ancestor', function () { + it('should support selecting a range from a nested child row to its top level row ancestor', async function () { let treegrid = render(); let rowgroups = treegrid.getAllByRole('rowgroup'); let rows = within(rowgroups[1]).getAllByRole('row'); checkRowSelection(rows, false); - triggerPress(getCell(treegrid, 'Row 1, Lvl 3, Foo')); + await user.click(getCell(treegrid, 'Row 1, Lvl 3, Foo')); onSelectionChange.mockReset(); - triggerPress(getCell(treegrid, 'Row 1, Lvl 1, Foo'), {shiftKey: true}); + await shiftClick(getCell(treegrid, 'Row 1, Lvl 1, Foo')); checkSelection(onSelectionChange, [ 'Row 1 Lvl 1', 'Row 1 Lvl 2', 'Row 1 Lvl 3' ]); @@ -1076,16 +1082,16 @@ describe('TableView with expandable rows', function () { checkRowSelection(rows.slice(3), false); }); - it('should not include disabled rows', function () { + it('should not include disabled rows', async function () { let treegrid = render(); let rowgroups = treegrid.getAllByRole('rowgroup'); let rows = within(rowgroups[1]).getAllByRole('row'); checkRowSelection(rows, false); - triggerPress(getCell(treegrid, 'Row 1, Lvl 1, Foo')); + await user.click(getCell(treegrid, 'Row 1, Lvl 1, Foo')); onSelectionChange.mockReset(); - triggerPress(getCell(treegrid, 'Row 2, Lvl 3, Foo'), {shiftKey: true}); + await shiftClick(getCell(treegrid, 'Row 2, Lvl 3, Foo')); checkSelection(onSelectionChange, [ 'Row 1 Lvl 1', 'Row 1 Lvl 3', 'Row 2 Lvl 1', 'Row 2 Lvl 2', 'Row 2 Lvl 3' ]); @@ -1494,7 +1500,7 @@ describe('TableView with expandable rows', function () { expect(heading).toHaveTextContent('No results'); let showItemsButton = treegrid.getAllByRole('button')[0]; - triggerPress(showItemsButton); + await user.click(showItemsButton); act(() => jest.runAllTimers()); rowgroups = treegrid.getAllByRole('rowgroup'); rows = within(rowgroups[1]).getAllByRole('row'); @@ -1524,7 +1530,7 @@ describe('TableView with expandable rows', function () { expect(spinner).not.toHaveAttribute('aria-valuenow'); let showItemsButton = treegrid.getAllByRole('button')[0]; - triggerPress(showItemsButton); + await user.click(showItemsButton); act(() => jest.runAllTimers()); rowgroups = treegrid.getAllByRole('rowgroup'); rows = within(rowgroups[1]).getAllByRole('row'); diff --git a/packages/@react-spectrum/tabs/test/Tabs.test.js b/packages/@react-spectrum/tabs/test/Tabs.test.js index 216d1fc7b0e..28fb6c886e4 100644 --- a/packages/@react-spectrum/tabs/test/Tabs.test.js +++ b/packages/@react-spectrum/tabs/test/Tabs.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, mockImplementation, pointerMap, render, triggerPress, waitFor, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, mockImplementation, pointerMap, render, waitFor, within} from '@react-spectrum/test-utils'; import {Item, TabList, TabPanels, Tabs} from '../src'; import {Links as LinksExample} from '../stories/Tabs.stories'; import {Provider} from '@react-spectrum/provider'; @@ -211,7 +211,7 @@ describe('Tabs', function () { expect(onSelectionChange).toBeCalledTimes(1); }); - it('supports using click to change tab', function () { + it('supports using click to change tab', async function () { let container = renderComponent({keyboardActivation: 'manual', defaultSelectedKey: defaultItems[0].name, onSelectionChange}); let tablist = container.getByRole('tablist'); let tabs = within(tablist).getAllByRole('tab'); @@ -219,7 +219,7 @@ describe('Tabs', function () { expect(firstItem).toHaveAttribute('aria-selected', 'true'); let secondItem = tabs[1]; - triggerPress(secondItem); + await user.click(secondItem); expect(secondItem).toHaveAttribute('aria-selected', 'true'); expect(secondItem).toHaveAttribute('aria-controls'); let tabpanel = document.getElementById(secondItem.getAttribute('aria-controls')); @@ -361,7 +361,7 @@ describe('Tabs', function () { expect(document.activeElement).toBe(tabpanel); }); - it('collapses when it can\'t render all the tabs horizontally', function () { + it('collapses when it can\'t render all the tabs horizontally', async function () { let target = [HTMLDivElement.prototype, 'getBoundingClientRect']; let mockCalls = [ function () { @@ -408,11 +408,11 @@ describe('Tabs', function () { expect(picker).toHaveAttribute('aria-label', 'Test Tabs'); expect(picker).toHaveAttribute('aria-labelledby', `${pickerLabel.id} ${picker.id} external label`); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); let option = within(listbox).getByText('Tab 3'); - triggerPress(option); + await user.click(option); act(() => jest.runAllTimers()); expect(onSelectionChange).toBeCalledTimes(1); @@ -655,7 +655,7 @@ describe('Tabs', function () { }); - it('disabled tabs cannot be selected via collapse picker', function () { + it('disabled tabs cannot be selected via collapse picker', async function () { let target = [HTMLDivElement.prototype, 'getBoundingClientRect']; let mockCalls = [ function () { @@ -699,16 +699,16 @@ describe('Tabs', function () { let picker = getByRole('button'); - triggerPress(picker); + await user.click(picker); act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); let option = within(listbox).getByText('Tab 3'); - triggerPress(option); + await user.click(option); act(() => jest.runAllTimers()); expect(onSelectionChange).not.toHaveBeenCalled(); option = within(listbox).getByText('Tab 2 body'); - triggerPress(option); + await user.click(option); act(() => jest.runAllTimers()); expect(onSelectionChange).toHaveBeenCalledWith(''); tabpanel = getByRole('tabpanel'); @@ -739,18 +739,18 @@ describe('Tabs', function () { await waitFor(() => expect(tabpanel).not.toHaveAttribute('tabindex')); let tabs = getAllByRole('tab'); - triggerPress(tabs[1]); + await user.click(tabs[1]); tabpanel = getByRole('tabpanel'); await waitFor(() => expect(tabpanel).toHaveAttribute('tabindex', '0')); - triggerPress(tabs[0]); + await user.click(tabs[0]); tabpanel = getByRole('tabpanel'); await waitFor(() => expect(tabpanel).not.toHaveAttribute('tabindex')); }); - it('TabPanel children do not share values between panels', () => { + it('TabPanel children do not share values between panels', async () => { let {getByDisplayValue, getAllByRole, getByTestId} = render( @@ -776,7 +776,7 @@ describe('Tabs', function () { expect(getByDisplayValue('A String')).toBeTruthy(); let tabs = getAllByRole('tab'); - triggerPress(tabs[1]); + await user.click(tabs[1]); tabPanelInput = getByTestId('panel2_input'); expect(tabPanelInput.value).toBe(''); @@ -827,14 +827,14 @@ describe('Tabs', function () { } }); - it('fires onSelectionChange when clicking on the current tab', function () { + it('fires onSelectionChange when clicking on the current tab', async function () { let container = renderComponent({defaultSelectedKey: defaultItems[0].name, onSelectionChange}); let tablist = container.getByRole('tablist'); let tabs = within(tablist).getAllByRole('tab'); let firstItem = tabs[0]; expect(firstItem).toHaveAttribute('aria-selected', 'true'); - triggerPress(firstItem); + await user.click(firstItem); expect(onSelectionChange).toBeCalledTimes(1); expect(onSelectionChange).toHaveBeenCalledWith(defaultItems[0].name); }); @@ -872,7 +872,7 @@ describe('Tabs', function () { expect(tabs[2]).toHaveAttribute('tabindex', '-1'); }); - it('should support tabs as links', function () { + it('should support tabs as links', async function () { let {getAllByRole} = render(); let tabs = getAllByRole('tab'); @@ -884,7 +884,7 @@ describe('Tabs', function () { expect(tabs[2]).toHaveAttribute('href', '/three'); expect(tabs[0]).toHaveAttribute('aria-selected', 'true'); - triggerPress(tabs[1]); + await user.click(tabs[1]); expect(tabs[1]).toHaveAttribute('aria-selected', 'true'); fireEvent.keyDown(tabs[1], {key: 'ArrowRight'}); diff --git a/packages/@react-spectrum/tag/test/TagGroup.test.js b/packages/@react-spectrum/tag/test/TagGroup.test.js index 43b8bf30f1e..ba086d91178 100644 --- a/packages/@react-spectrum/tag/test/TagGroup.test.js +++ b/packages/@react-spectrum/tag/test/TagGroup.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, mockImplementation, pointerMap, render, triggerPress, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, mockImplementation, pointerMap, render, within} from '@react-spectrum/test-utils'; import {Button} from '@react-spectrum/button'; import {chain} from '@react-aria/utils'; import {Item} from '@react-stately/collections'; @@ -348,7 +348,7 @@ describe('TagGroup', function () { expect(onRemoveSpy).toHaveBeenCalledTimes(0); }); - it('should remove tag when remove button is clicked', function () { + it('should remove tag when remove button is clicked', async function () { let {getAllByRole} = render( @@ -360,11 +360,11 @@ describe('TagGroup', function () { ); let tags = getAllByRole('row'); - triggerPress(tags[0]); + await user.click(tags[0]); expect(onRemoveSpy).not.toHaveBeenCalled(); let removeButton = within(tags[0]).getByRole('button'); - triggerPress(removeButton); + await user.click(removeButton); expect(onRemoveSpy).toHaveBeenCalledTimes(1); expect(onRemoveSpy).toHaveBeenCalledWith(new Set(['1'])); }); @@ -732,7 +732,7 @@ describe('TagGroup', function () { expect(tags[1]).toHaveAttribute('data-foo', 'two'); }); - it('should support links', function () { + it('should support links', async function () { let {getAllByRole} = render( @@ -750,7 +750,7 @@ describe('TagGroup', function () { let onClick = jest.fn().mockImplementation(e => e.preventDefault()); window.addEventListener('click', onClick, {once: true}); - triggerPress(tags[0]); + await user.click(tags[0]); expect(onClick).toHaveBeenCalledTimes(1); expect(onClick.mock.calls[0][0].target).toBeInstanceOf(HTMLAnchorElement); expect(onClick.mock.calls[0][0].target.href).toBe('https://google.com/'); diff --git a/packages/@react-spectrum/test-utils/src/events.ts b/packages/@react-spectrum/test-utils/src/events.ts index f5c0dc74277..556b8d3d2e2 100644 --- a/packages/@react-spectrum/test-utils/src/events.ts +++ b/packages/@react-spectrum/test-utils/src/events.ts @@ -13,15 +13,6 @@ import {act, fireEvent} from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -// TODO: try to get rid of this in favor of user event -// Triggers a "press" event on an element. -// TODO: move to somewhere more common -export function triggerPress(element, opts = {}) { - fireEvent.mouseDown(element, {detail: 1, ...opts}); - fireEvent.mouseUp(element, {detail: 1, ...opts}); - fireEvent.click(element, {detail: 1, ...opts}); -} - // TODO: try to get rid of this in favor of user event // Triggers a "touch" event on an element. export function triggerTouch(element, opts = {}) { diff --git a/packages/@react-spectrum/toast/test/ToastContainer.test.js b/packages/@react-spectrum/toast/test/ToastContainer.test.js index 47b4bfd9982..4c496f3d74f 100644 --- a/packages/@react-spectrum/toast/test/ToastContainer.test.js +++ b/packages/@react-spectrum/toast/test/ToastContainer.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, triggerPress, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; import {Button} from '@react-spectrum/button'; import {clearToastQueue, ToastContainer, ToastQueue} from '../src/ToastContainer'; import {defaultTheme} from '@adobe/react-spectrum'; @@ -60,12 +60,12 @@ describe('Toast Provider and Container', function () { act(() => jest.runAllTimers()); }); - it('renders a button that triggers a toast', () => { + it('renders a button that triggers a toast', async () => { let {getByRole, queryByRole} = renderComponent(); let button = getByRole('button'); expect(queryByRole('alert')).toBeNull(); - triggerPress(button); + await user.click(button); let region = getByRole('region'); expect(region).toHaveAttribute('aria-label', 'Notifications'); @@ -75,27 +75,27 @@ describe('Toast Provider and Container', function () { button = within(alert).getByRole('button'); expect(button).toHaveAttribute('aria-label', 'Close'); - triggerPress(button); + await user.click(button); fireAnimationEnd(alert); expect(queryByRole('alert')).toBeNull(); }); - it('should label icon by variant', () => { + it('should label icon by variant', async () => { let {getByRole} = renderComponent(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); let alert = getByRole('alert'); let icon = within(alert).getByRole('img'); expect(icon).toHaveAttribute('aria-label', 'Success'); }); - it('removes a toast via timeout', () => { + it('removes a toast via timeout', async () => { let {getByRole, queryByRole} = renderComponent(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); let toast = getByRole('alert'); expect(toast).toBeVisible(); @@ -114,7 +114,7 @@ describe('Toast Provider and Container', function () { let {getByRole, queryByRole} = renderComponent(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); let toast = getByRole('alert'); expect(toast).toBeVisible(); @@ -134,11 +134,11 @@ describe('Toast Provider and Container', function () { expect(queryByRole('alert')).toBeNull(); }); - it('pauses timers when focusing', () => { + it('pauses timers when focusing', async () => { let {getByRole, queryByRole} = renderComponent(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); let toast = getByRole('alert'); expect(toast).toBeVisible(); @@ -158,41 +158,41 @@ describe('Toast Provider and Container', function () { expect(queryByRole('alert')).toBeNull(); }); - it('renders a toast with an action', () => { + it('renders a toast with an action', async () => { let onAction = jest.fn(); let onClose = jest.fn(); let {getByRole, queryByRole} = renderComponent(); let button = getByRole('button'); expect(queryByRole('alert')).toBeNull(); - triggerPress(button); + await user.click(button); let alert = getByRole('alert'); expect(alert).toBeVisible(); let buttons = within(alert).getAllByRole('button'); expect(buttons[0]).toHaveTextContent('Action'); - triggerPress(buttons[0]); + await user.click(buttons[0]); expect(onAction).toHaveBeenCalledTimes(1); expect(onClose).not.toHaveBeenCalled(); }); - it('closes toast on action', () => { + it('closes toast on action', async () => { let onAction = jest.fn(); let onClose = jest.fn(); let {getByRole, queryByRole} = renderComponent(); let button = getByRole('button'); expect(queryByRole('alert')).toBeNull(); - triggerPress(button); + await user.click(button); let alert = getByRole('alert'); expect(alert).toBeVisible(); let buttons = within(alert).getAllByRole('button'); expect(buttons[0]).toHaveTextContent('Action'); - triggerPress(buttons[0]); + await user.click(buttons[0]); expect(onAction).toHaveBeenCalledTimes(1); expect(onClose).toHaveBeenCalledTimes(1); @@ -202,7 +202,7 @@ describe('Toast Provider and Container', function () { expect(queryByRole('alert')).toBeNull(); }); - it('prioritizes toasts based on variant', () => { + it('prioritizes toasts based on variant', async () => { function ToastPriorites(props = {}) { return (
@@ -226,54 +226,54 @@ describe('Toast Provider and Container', function () { // show info toast first. error toast should supersede it. expect(queryByRole('alert')).toBeNull(); - triggerPress(buttons[0]); + await user.click(buttons[0]); let alert = getByRole('alert'); expect(alert).toBeVisible(); expect(alert).toHaveTextContent('Info'); - triggerPress(buttons[1]); + await user.click(buttons[1]); fireAnimationEnd(alert); alert = getByRole('alert'); expect(alert).toHaveTextContent('Error'); - triggerPress(within(alert).getByRole('button')); + await user.click(within(alert).getByRole('button')); fireAnimationEnd(alert); alert = getByRole('alert'); expect(alert).toHaveTextContent('Info'); - triggerPress(within(alert).getByRole('button')); + await user.click(within(alert).getByRole('button')); fireAnimationEnd(alert); expect(queryByRole('alert')).toBeNull(); // again, but with error toast first. - triggerPress(buttons[1]); + await user.click(buttons[1]); alert = getByRole('alert'); expect(alert).toHaveTextContent('Error'); - triggerPress(buttons[0]); + await user.click(buttons[0]); alert = getByRole('alert'); expect(alert).toHaveTextContent('Error'); - triggerPress(within(alert).getByRole('button')); + await user.click(within(alert).getByRole('button')); fireAnimationEnd(alert); alert = getByRole('alert'); expect(alert).toHaveTextContent('Info'); - triggerPress(within(alert).getByRole('button')); + await user.click(within(alert).getByRole('button')); fireAnimationEnd(alert); expect(queryByRole('alert')).toBeNull(); }); - it('can focus toast region using F6', () => { + it('can focus toast region using F6', async () => { let {getByRole} = renderComponent(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); let toast = getByRole('alert'); expect(toast).toBeVisible(); @@ -286,46 +286,46 @@ describe('Toast Provider and Container', function () { expect(document.activeElement).toBe(region); }); - it('should restore focus when a toast exits', () => { + it('should restore focus when a toast exits', async () => { let {getByRole, queryByRole} = renderComponent(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); let toast = getByRole('alert'); let closeButton = within(toast).getByRole('button'); act(() => closeButton.focus()); - triggerPress(closeButton); + await user.click(closeButton); fireAnimationEnd(toast); expect(queryByRole('alert')).toBeNull(); expect(document.activeElement).toBe(button); }); - it('should move focus to container when a toast exits and there are more', () => { + it('should move focus to container when a toast exits and there are more', async () => { let {getByRole, queryByRole} = renderComponent(); let button = getByRole('button'); - triggerPress(button); - triggerPress(button); + await user.click(button); + await user.click(button); let toast = getByRole('alert'); let closeButton = within(toast).getByRole('button'); - triggerPress(closeButton); + await user.click(closeButton); fireAnimationEnd(toast); expect(document.activeElement).toBe(getByRole('region')); toast = getByRole('alert'); closeButton = within(toast).getByRole('button'); - triggerPress(closeButton); + await user.click(closeButton); fireAnimationEnd(toast); expect(queryByRole('alert')).toBeNull(); expect(document.activeElement).toBe(button); }); - it('should support programmatically closing toasts', () => { + it('should support programmatically closing toasts', async () => { function ToastToggle() { let [close, setClose] = useState(null); @@ -348,17 +348,17 @@ describe('Toast Provider and Container', function () { let {getByRole, queryByRole} = renderComponent(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); let toast = getByRole('alert'); expect(toast).toBeVisible(); - triggerPress(button); + await user.click(button); fireAnimationEnd(toast); expect(queryByRole('alert')).toBeNull(); }); - it('should only render one ToastContainer', () => { + it('should only render one ToastContainer', async () => { let {getByRole, getAllByRole, rerender} = render( @@ -368,7 +368,7 @@ describe('Toast Provider and Container', function () { ); let button = getByRole('button'); - triggerPress(button); + await user.click(button); expect(getAllByRole('region')).toHaveLength(1); expect(getAllByRole('alert')).toHaveLength(1); @@ -405,14 +405,14 @@ describe('Toast Provider and Container', function () { expect(getAllByRole('alert')).toHaveLength(1); }); - it('should support custom toast events', () => { + it('should support custom toast events', async () => { let {getByRole, queryByRole} = renderComponent(); let onToast = jest.fn().mockImplementation(e => e.preventDefault()); window.addEventListener('react-spectrum-toast', onToast); let button = getByRole('button'); - triggerPress(button); + await user.click(button); expect(queryByRole('alert')).toBeNull(); expect(onToast).toHaveBeenCalledTimes(1); @@ -425,7 +425,7 @@ describe('Toast Provider and Container', function () { window.removeEventListener('react-spectrum-toast', onToast); }); - it('should support custom aria-label', () => { + it('should support custom aria-label', async () => { let {getByRole} = render( @@ -434,7 +434,7 @@ describe('Toast Provider and Container', function () { ); let button = getByRole('button'); - triggerPress(button); + await user.click(button); let region = getByRole('region'); expect(region).toHaveAttribute('aria-label', 'Toasts'); diff --git a/packages/@react-spectrum/tooltip/test/TooltipTrigger.test.js b/packages/@react-spectrum/tooltip/test/TooltipTrigger.test.js index 07944908d30..b7672194896 100644 --- a/packages/@react-spectrum/tooltip/test/TooltipTrigger.test.js +++ b/packages/@react-spectrum/tooltip/test/TooltipTrigger.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, triggerPress} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render} from '@react-spectrum/test-utils'; import {ActionButton} from '@react-spectrum/button'; import {Provider} from '@react-spectrum/provider'; import React from 'react'; @@ -282,7 +282,7 @@ describe('TooltipTrigger', function () { expect(onOpenChange).toHaveBeenCalledWith(true); let tooltip = getByRole('tooltip'); expect(tooltip).toBeVisible(); - triggerPress(button); + await user.click(button); expect(onOpenChange).toHaveBeenCalledWith(false); act(() => { jest.advanceTimersByTime(CLOSE_TIME); diff --git a/packages/@react-spectrum/utils/test/Slots.test.js b/packages/@react-spectrum/utils/test/Slots.test.js index 7ced4ba4732..a2ef43e3734 100644 --- a/packages/@react-spectrum/utils/test/Slots.test.js +++ b/packages/@react-spectrum/utils/test/Slots.test.js @@ -10,12 +10,12 @@ * governing permissions and limitations under the License. */ +import {pointerMap, render} from '@react-spectrum/test-utils'; import React, {useRef} from 'react'; -import {render, triggerPress} from '@react-spectrum/test-utils'; import {SlotProvider, useSlotProps} from '../'; import {useId, useSlotId} from '@react-aria/utils'; import {usePress} from '@react-aria/interactions'; - +import userEvent from '@testing-library/user-event'; describe('Slots', function () { let results = {}; @@ -80,7 +80,8 @@ describe('Slots', function () { }); }); - it('chains functions', function () { + it('chains functions', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let onPress = jest.fn(); let onPressUser = jest.fn(); let slots = { @@ -91,7 +92,7 @@ describe('Slots', function () { ); - triggerPress(getByRole('button')); + await user.click(getByRole('button')); expect(onPress).toHaveBeenCalledTimes(1); expect(onPressUser).toHaveBeenCalledTimes(1); }); From 04c7290c43147d5aa4badc0db193d5d8b0a3a408 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Mon, 4 Dec 2023 11:27:06 -0800 Subject: [PATCH 08/31] fix SSR tests and react 16/17 tests --- packages/@react-aria/test-utils/package.json | 5 ----- packages/@react-spectrum/combobox/test/ComboBox.test.js | 8 ++++++++ packages/@react-spectrum/picker/test/Picker.test.js | 8 ++++++++ packages/@react-spectrum/test-utils/package.json | 5 ----- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/packages/@react-aria/test-utils/package.json b/packages/@react-aria/test-utils/package.json index 9f98559b106..c8e7c1750c0 100644 --- a/packages/@react-aria/test-utils/package.json +++ b/packages/@react-aria/test-utils/package.json @@ -7,11 +7,6 @@ "main": "dist/main.js", "module": "dist/module.js", "types": "dist/types.d.ts", - "exports": { - "types": "./dist/types.d.ts", - "import": "./dist/import.mjs", - "require": "./dist/main.js" - }, "source": "src/index.ts", "files": [ "dist", diff --git a/packages/@react-spectrum/combobox/test/ComboBox.test.js b/packages/@react-spectrum/combobox/test/ComboBox.test.js index c246a68da4c..5a3ca761f1f 100644 --- a/packages/@react-spectrum/combobox/test/ComboBox.test.js +++ b/packages/@react-spectrum/combobox/test/ComboBox.test.js @@ -5907,8 +5907,12 @@ describe('ComboBox', function () { expect(items[1].tagName).toBe('A'); expect(items[1]).toHaveAttribute('href', 'https://adobe.com'); + let onClick = jest.fn().mockImplementation(e => e.preventDefault()); + window.addEventListener('click', onClick); if (type === 'mouse') { await user.click(items[0]); + expect(onClick.mock.calls[0][0].target).toBeInstanceOf(HTMLAnchorElement); + expect(onClick.mock.calls[0][0].target.href).toBe('https://google.com/'); } else { fireEvent.keyDown(combobox, {key: 'Enter'}); fireEvent.keyUp(combobox, {key: 'Enter'}); @@ -5919,6 +5923,7 @@ describe('ComboBox', function () { expect(combobox).toHaveValue(''); expect(listbox).not.toBeInTheDocument(); + window.removeEventListener('click', onClick); }); it('supports RouterProvider', async () => { @@ -5960,6 +5965,8 @@ describe('ComboBox', function () { listbox = tree.getByRole('listbox'); items = within(listbox).getAllByRole('option'); + let onClick = jest.fn().mockImplementation(e => e.preventDefault()); + window.addEventListener('click', onClick); await user.click(items[1]); act(() => { @@ -5970,6 +5977,7 @@ describe('ComboBox', function () { expect(navigate).not.toHaveBeenCalled(); expect(combobox).toHaveValue(''); expect(listbox).not.toBeInTheDocument(); + window.removeEventListener('click', onClick); }); }); }); diff --git a/packages/@react-spectrum/picker/test/Picker.test.js b/packages/@react-spectrum/picker/test/Picker.test.js index ce4af54fa9f..482b464be1b 100644 --- a/packages/@react-spectrum/picker/test/Picker.test.js +++ b/packages/@react-spectrum/picker/test/Picker.test.js @@ -2493,6 +2493,8 @@ describe('Picker', function () { expect(items[1].tagName).toBe('A'); expect(items[1]).toHaveAttribute('href', 'https://adobe.com'); + let onClick = jest.fn().mockImplementation(e => e.preventDefault()); + window.addEventListener('click', onClick); if (type === 'mouse') { await user.click(items[0]); } else { @@ -2505,6 +2507,9 @@ describe('Picker', function () { expect(button).toHaveTextContent('Select an option…'); expect(listbox).not.toBeInTheDocument(); + expect(onClick.mock.calls[0][0].target).toBeInstanceOf(HTMLAnchorElement); + expect(onClick.mock.calls[0][0].target.href).toBe('https://google.com/'); + window.removeEventListener('click', onClick); }); it('works with RouterProvider', async () => { @@ -2526,8 +2531,11 @@ describe('Picker', function () { let listbox = tree.getByRole('listbox'); let items = within(listbox).getAllByRole('option'); + let onClick = jest.fn().mockImplementation(e => e.preventDefault()); + window.addEventListener('click', onClick); await user.click(items[0]); expect(navigate).toHaveBeenCalledWith('/one'); + window.removeEventListener('click', onClick); }); }); }); diff --git a/packages/@react-spectrum/test-utils/package.json b/packages/@react-spectrum/test-utils/package.json index e7e141d158f..1df1ab1245c 100644 --- a/packages/@react-spectrum/test-utils/package.json +++ b/packages/@react-spectrum/test-utils/package.json @@ -7,11 +7,6 @@ "main": "dist/main.js", "module": "dist/module.js", "types": "dist/types.d.ts", - "exports": { - "types": "./dist/types.d.ts", - "import": "./dist/import.mjs", - "require": "./dist/main.js" - }, "source": "src/index.ts", "files": [ "dist", From 7760e9560ce157934b64e544c50e61689a43f47e Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Mon, 4 Dec 2023 13:51:59 -0800 Subject: [PATCH 09/31] work around weird react16/17 test failure for now --- packages/@react-spectrum/combobox/test/ComboBox.test.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/@react-spectrum/combobox/test/ComboBox.test.js b/packages/@react-spectrum/combobox/test/ComboBox.test.js index 5a3ca761f1f..c7945c81017 100644 --- a/packages/@react-spectrum/combobox/test/ComboBox.test.js +++ b/packages/@react-spectrum/combobox/test/ComboBox.test.js @@ -4438,7 +4438,10 @@ describe('ComboBox', function () { await user.click(document.body); break; case 'dismiss button': - await user.click(dismissButtons[0]); + // TODO: not entirely sure why using user.click here breaks the test... It seems to cause the selectedKey + // to not update in time in useComboboxState... + // await user.click(dismissButtons[0]); + fireEvent.click(dismissButtons[0]); break; case 'escape key': fireEvent.keyDown(trayInput, {key: 'Escape', code: 27, charCode: 27}); From 4848110b24f53d4ee5e7f1f2d1303718fd852dda Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Mon, 4 Dec 2023 14:11:11 -0800 Subject: [PATCH 10/31] get rid of triggerTouch and typeText --- packages/@react-aria/test-utils/src/events.ts | 25 ------- .../menu/test/MenuTrigger.test.js | 71 +++++++------------ .../table/test/TableSizing.test.tsx | 10 +-- .../@react-spectrum/test-utils/src/events.ts | 30 -------- 4 files changed, 30 insertions(+), 106 deletions(-) diff --git a/packages/@react-aria/test-utils/src/events.ts b/packages/@react-aria/test-utils/src/events.ts index 38b295c1630..d526c8af7fc 100644 --- a/packages/@react-aria/test-utils/src/events.ts +++ b/packages/@react-aria/test-utils/src/events.ts @@ -11,11 +11,6 @@ */ import {act, fireEvent} from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; - -// TODO: delete the dev/test-utils equivalent -// try to get rid of triggerPress and triggerTouch entirely from our code base so I can get rid of the -// file in dev/test-utils // Triggers a "longPress" event on an element. export const DEFAULT_LONG_PRESS_TIME = 500; @@ -91,23 +86,3 @@ export function installPointerEvent() { delete global.PointerEvent; }); } - -/** - * Must **not** be called inside an `act` callback! - * - * \@testing-library/user-event's `type` helper doesn't call `act` every keystroke. - * But we want to run all event handles after every character. - * @param el The input element to type into. - * @param value The text. - * @deprecated Use `user.keyboard` instead. - */ -export function typeText(el: HTMLElement, value: string, opts?: any) { - let skipClick = document.activeElement === el; - for (let char of value) { - act(() => { - userEvent.type(el, char, {skipClick, ...opts}); - }); - - skipClick = true; - } -} diff --git a/packages/@react-spectrum/menu/test/MenuTrigger.test.js b/packages/@react-spectrum/menu/test/MenuTrigger.test.js index e895be2d5f0..de001f44637 100644 --- a/packages/@react-spectrum/menu/test/MenuTrigger.test.js +++ b/packages/@react-spectrum/menu/test/MenuTrigger.test.js @@ -20,8 +20,7 @@ import { installPointerEvent, pointerMap, simulateDesktop, - triggerLongPress, - triggerTouch + triggerLongPress } from '@react-spectrum/test-utils'; import {Dialog} from '@react-spectrum/dialog'; import {Heading, Text} from '@react-spectrum/text'; @@ -81,6 +80,7 @@ describe('MenuTrigger', function () { }); afterEach(() => { + jest.runAllTimers(); onOpenChange.mockClear(); onOpen.mockClear(); onClose.mockClear(); @@ -828,90 +828,71 @@ describe('MenuTrigger', function () { it('should open the menu on longPress', async function () { const props = {onOpenChange, trigger: 'longPress'}; - await verifyMenuToggle(MenuTrigger, props, {}, (button, menu) => { + await verifyMenuToggle(MenuTrigger, props, {}, async (button, menu) => { expect(button).toHaveAttribute('aria-describedby'); expect(document.getElementById(button.getAttribute('aria-describedby'))).toHaveTextContent('Long press or press Alt + ArrowDown to open menu'); if (!menu) { triggerLongPress(button); } else { - triggerTouch(button); + await user.pointer({target: button, keys: '[TouchA]'}); } }); }); - it('should not open menu on click', function () { + it('should not open menu on click', async function () { const props = {onOpenChange, trigger: 'longPress'}; let tree = renderComponent(MenuTrigger, props, {}); let button = tree.getByRole('button'); - act(() => { - triggerTouch(button); - setTimeout(() => { - expect(getMenuOrThrow).toThrowError(ERROR_MENU_NOT_FOUND); - }, 0, tree, button); - jest.runAllTimers(); - }); + await user.pointer({target: button, keys: '[TouchA]'}); + expect(getMenuOrThrow).toThrowError(ERROR_MENU_NOT_FOUND); }); - it(`should not open menu on short press (default threshold set to ${DEFAULT_LONG_PRESS_TIME}ms)`, function () { + it(`should not open menu on short press (default threshold set to ${DEFAULT_LONG_PRESS_TIME}ms)`, async function () { const props = {onOpenChange, trigger: 'longPress'}; let tree = renderComponent(MenuTrigger, props, {}); let button = tree.getByRole('button'); - act(() => { - triggerTouch(button); - setTimeout(() => { - expect(getMenuOrThrow).toThrowError(ERROR_MENU_NOT_FOUND); - }, DEFAULT_LONG_PRESS_TIME / 2, tree, button); - jest.runAllTimers(); - }); + await user.pointer({target: button, keys: '[TouchA]'}); + expect(getMenuOrThrow).toThrowError(ERROR_MENU_NOT_FOUND); }); - it('should not open the menu on Enter', function () { + it('should not open the menu on Enter', async function () { const props = {onOpenChange, trigger: 'longPress'}; let tree = renderComponent(MenuTrigger, props, {}); let button = tree.getByRole('button'); - act(() => { - triggerTouch(button); - setTimeout(() => { - expect(getMenuOrThrow).toThrowError(ERROR_MENU_NOT_FOUND); - }, 0, tree, button); - jest.runAllTimers(); - }); + + await user.pointer({target: button, keys: '[TouchA]'}); + expect(getMenuOrThrow).toThrowError(ERROR_MENU_NOT_FOUND); }); - it('should not open the menu on Space', function () { + it('should not open the menu on Space', async function () { const props = {onOpenChange, trigger: 'longPress'}; let tree = renderComponent(MenuTrigger, props, {}); let button = tree.getByRole('button'); - act(() => { - triggerTouch(button); - setTimeout(() => { - expect(getMenuOrThrow).toThrowError(ERROR_MENU_NOT_FOUND); - }, 0, tree, button); - jest.runAllTimers(); - }); + await user.pointer({target: button, keys: '[TouchA]'}); + expect(getMenuOrThrow).toThrowError(ERROR_MENU_NOT_FOUND); }); it('should open the menu on Alt+ArrowUp', async function () { const props = {onOpenChange, trigger: 'longPress'}; - await verifyMenuToggle(MenuTrigger, props, {}, (button, menu) => { + await verifyMenuToggle(MenuTrigger, props, {}, async (button, menu) => { if (!menu) { fireEvent.keyDown(button, {key: 'ArrowUp', altKey: true}); } else { - triggerTouch(button); + await user.pointer({target: button, keys: '[TouchA]'});; } }); }); it('should open the menu on Alt+ArrowDown', async function () { const props = {onOpenChange, trigger: 'longPress'}; - await verifyMenuToggle(MenuTrigger, props, {}, (button, menu) => { + await verifyMenuToggle(MenuTrigger, props, {}, async (button, menu) => { if (!menu) { fireEvent.keyDown(button, {key: 'ArrowDown', altKey: true}); } else { - triggerTouch(button); + await user.pointer({target: button, keys: '[TouchA]'});; } }); }); @@ -929,7 +910,7 @@ describe('MenuTrigger', function () { return menu; } - it('should focus the selected item on menu open', function () { + it('should focus the selected item on menu open', async function () { let tree = renderComponent(MenuTrigger, {trigger: 'longPress'}, {selectedKeys: ['Bar']}); let button = tree.getByRole('button'); act(() => { @@ -937,8 +918,8 @@ describe('MenuTrigger', function () { jest.runAllTimers(); }); let menu = expectMenuItemToBeActive(tree, 1); + await user.pointer({target: button, keys: '[TouchA]'}); act(() => { - triggerTouch(button); jest.runAllTimers(); }); expect(menu).not.toBeInTheDocument(); @@ -946,9 +927,8 @@ describe('MenuTrigger', function () { // Opening menu via Alt+ArrowUp still autofocuses the selected item fireEvent.keyDown(button, {key: 'ArrowUp', altKey: true}); menu = expectMenuItemToBeActive(tree, 1); - + await user.pointer({target: button, keys: '[TouchA]'}); act(() => { - triggerTouch(button); jest.runAllTimers(); }); expect(menu).not.toBeInTheDocument(); @@ -956,9 +936,8 @@ describe('MenuTrigger', function () { // Opening menu via Alt+ArrowDown still autofocuses the selected item fireEvent.keyDown(button, {key: 'ArrowDown', altKey: true}); menu = expectMenuItemToBeActive(tree, 1); - + await user.pointer({target: button, keys: '[TouchA]'}); act(() => { - triggerTouch(button); jest.runAllTimers(); }); expect(menu).not.toBeInTheDocument(); diff --git a/packages/@react-spectrum/table/test/TableSizing.test.tsx b/packages/@react-spectrum/table/test/TableSizing.test.tsx index e1ec78668de..09835524319 100644 --- a/packages/@react-spectrum/table/test/TableSizing.test.tsx +++ b/packages/@react-spectrum/table/test/TableSizing.test.tsx @@ -17,7 +17,7 @@ import Add from '@spectrum-icons/workflow/Add'; import {Cell, Column, Row, TableBody, TableHeader, TableView} from '../'; import {ColumnSize} from '@react-types/table'; import {ControllingResize} from '../stories/ControllingResize'; -import {fireEvent, installPointerEvent, pointerMap, simulateDesktop, triggerTouch} from '@react-spectrum/test-utils'; +import {fireEvent, installPointerEvent, pointerMap, simulateDesktop} from '@react-spectrum/test-utils'; import {HidingColumns} from '../stories/HidingColumns'; import {Key} from '@react-types/shared'; import {Provider} from '@react-spectrum/provider'; @@ -857,7 +857,7 @@ describe('TableViewSizing', function () { describe('touch', () => { installPointerEvent(); - it('dragging the resizer works - desktop', () => { + it('dragging the resizer works - desktop', async () => { setInteractionModality('pointer'); simulateDesktop(); let onResizeEnd = jest.fn(); @@ -878,7 +878,7 @@ describe('TableViewSizing', function () { ); - triggerTouch(document.body); + await user.pointer({target: document.body, keys: '[TouchA]'}); act(() => {jest.runAllTimers();}); expect(tree.queryByRole('slider')).toBeNull(); @@ -894,12 +894,12 @@ describe('TableViewSizing', function () { let header = tree.getAllByRole('columnheader')[0]; let resizableHeader = within(header).getByRole('button'); - triggerTouch(resizableHeader); + await user.pointer({target: resizableHeader, keys: '[TouchA]'}); act(() => {jest.runAllTimers();}); let resizeMenuItem = tree.getAllByRole('menuitem')[0]; - triggerTouch(resizeMenuItem); + await user.pointer({target: resizeMenuItem, keys: '[TouchA]'}); act(() => {jest.runAllTimers();}); expect(tree.getByRole('slider')).toBeVisible(); diff --git a/packages/@react-spectrum/test-utils/src/events.ts b/packages/@react-spectrum/test-utils/src/events.ts index 556b8d3d2e2..9c8a1da031f 100644 --- a/packages/@react-spectrum/test-utils/src/events.ts +++ b/packages/@react-spectrum/test-utils/src/events.ts @@ -11,14 +11,6 @@ */ import {act, fireEvent} from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; - -// TODO: try to get rid of this in favor of user event -// Triggers a "touch" event on an element. -export function triggerTouch(element, opts = {}) { - fireEvent.pointerDown(element, {pointerType: 'touch', ...opts}); - fireEvent.pointerUp(element, {pointerType: 'touch', ...opts}); -} // TODO: expose from aria testing package, and re-export from this package? // Triggers a "longPress" event on an element. @@ -31,25 +23,3 @@ export function triggerLongPress(element, opts = {}) { }); fireEvent.pointerUp(element, {pointerType: 'touch', ...opts}); } - - -// TODO: expose from aria testing package, and re-export from this package? -/** - * Must **not** be called inside an `act` callback! - * - * \@testing-library/user-event's `type` helper doesn't call `act` every keystroke. - * But we want to run all event handles after every character. - * @param el The input element to type into. - * @param value The text. - * @deprecated Use `user.keyboard` instead. - */ -export function typeText(el: HTMLElement, value: string, opts?: any) { - let skipClick = document.activeElement === el; - for (let char of value) { - act(() => { - userEvent.type(el, char, {skipClick, ...opts}); - }); - - skipClick = true; - } -} From af7ce339a4e3c589cc7790c0d2026d6b3318f35a Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Mon, 4 Dec 2023 14:50:20 -0800 Subject: [PATCH 11/31] move stuff to aria/test-utils package --- packages/@react-aria/test-utils/src/events.ts | 66 +--------------- packages/@react-aria/test-utils/src/index.ts | 2 + .../@react-aria/test-utils/src/testSetup.ts | 75 +++++++++++++++++++ .../test-utils/src/userEventMaps.ts | 1 - .../@react-spectrum/test-utils/package.json | 1 + .../@react-spectrum/test-utils/src/events.ts | 25 ------- .../@react-spectrum/test-utils/src/index.ts | 3 +- .../test-utils/src/testSetup.ts | 65 ---------------- .../test-utils/src/userEventMaps.ts | 10 --- 9 files changed, 80 insertions(+), 168 deletions(-) create mode 100644 packages/@react-aria/test-utils/src/testSetup.ts delete mode 100644 packages/@react-spectrum/test-utils/src/events.ts delete mode 100644 packages/@react-spectrum/test-utils/src/userEventMaps.ts diff --git a/packages/@react-aria/test-utils/src/events.ts b/packages/@react-aria/test-utils/src/events.ts index d526c8af7fc..ea38f1f4496 100644 --- a/packages/@react-aria/test-utils/src/events.ts +++ b/packages/@react-aria/test-utils/src/events.ts @@ -1,5 +1,5 @@ /* - * Copyright 2020 Adobe. All rights reserved. + * Copyright 2023 Adobe. All rights reserved. * This file is licensed to you under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 @@ -22,67 +22,3 @@ export function triggerLongPress(element, opts = {}) { }); fireEvent.pointerUp(element, {pointerType: 'touch', ...opts}); } - -/** - * Enables reading pageX/pageY from fireEvent.mouse*(..., {pageX: ..., pageY: ...}). - */ -export function installMouseEvent() { - beforeAll(() => { - let oldMouseEvent = MouseEvent; - // @ts-ignore - global.MouseEvent = class FakeMouseEvent extends MouseEvent { - _init: {pageX: number, pageY: number}; - constructor(name, init) { - super(name, init); - this._init = init; - } - get pageX() { - return this._init.pageX; - } - get pageY() { - return this._init.pageY; - } - }; - // @ts-ignore - global.MouseEvent.oldMouseEvent = oldMouseEvent; - }); - afterAll(() => { - // @ts-ignore - global.MouseEvent = global.MouseEvent.oldMouseEvent; - }); -} - -export function installPointerEvent() { - beforeAll(() => { - // @ts-ignore - global.PointerEvent = class FakePointerEvent extends MouseEvent { - _init: {pageX: number, pageY: number, pointerType: string, pointerId: number, width: number, height: number}; - constructor(name, init) { - super(name, init); - this._init = init; - } - get pointerType() { - return this._init.pointerType ?? 'mouse'; - } - get pointerId() { - return this._init.pointerId; - } - get pageX() { - return this._init.pageX; - } - get pageY() { - return this._init.pageY; - } - get width() { - return this._init.width; - } - get height() { - return this._init.height; - } - }; - }); - afterAll(() => { - // @ts-ignore - delete global.PointerEvent; - }); -} diff --git a/packages/@react-aria/test-utils/src/index.ts b/packages/@react-aria/test-utils/src/index.ts index 51b67b7f7af..6a721573422 100644 --- a/packages/@react-aria/test-utils/src/index.ts +++ b/packages/@react-aria/test-utils/src/index.ts @@ -12,3 +12,5 @@ // TODO update export * from './events'; +export * from './testSetup'; +export * from './userEventMaps'; diff --git a/packages/@react-aria/test-utils/src/testSetup.ts b/packages/@react-aria/test-utils/src/testSetup.ts new file mode 100644 index 00000000000..bb356e96f1e --- /dev/null +++ b/packages/@react-aria/test-utils/src/testSetup.ts @@ -0,0 +1,75 @@ +/* + * Copyright 2023 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +/** + * Enables reading pageX/pageY from fireEvent.mouse*(..., {pageX: ..., pageY: ...}). + */ +export function installMouseEvent() { + beforeAll(() => { + let oldMouseEvent = MouseEvent; + // @ts-ignore + global.MouseEvent = class FakeMouseEvent extends MouseEvent { + _init: {pageX: number, pageY: number}; + constructor(name, init) { + super(name, init); + this._init = init; + } + get pageX() { + return this._init.pageX; + } + get pageY() { + return this._init.pageY; + } + }; + // @ts-ignore + global.MouseEvent.oldMouseEvent = oldMouseEvent; + }); + afterAll(() => { + // @ts-ignore + global.MouseEvent = global.MouseEvent.oldMouseEvent; + }); +} + +export function installPointerEvent() { + beforeAll(() => { + // @ts-ignore + global.PointerEvent = class FakePointerEvent extends MouseEvent { + _init: {pageX: number, pageY: number, pointerType: string, pointerId: number, width: number, height: number}; + constructor(name, init) { + super(name, init); + this._init = init; + } + get pointerType() { + return this._init.pointerType ?? 'mouse'; + } + get pointerId() { + return this._init.pointerId; + } + get pageX() { + return this._init.pageX; + } + get pageY() { + return this._init.pageY; + } + get width() { + return this._init.width; + } + get height() { + return this._init.height; + } + }; + }); + afterAll(() => { + // @ts-ignore + delete global.PointerEvent; + }); +} diff --git a/packages/@react-aria/test-utils/src/userEventMaps.ts b/packages/@react-aria/test-utils/src/userEventMaps.ts index 9a91a9d918d..ae355d83c9a 100644 --- a/packages/@react-aria/test-utils/src/userEventMaps.ts +++ b/packages/@react-aria/test-utils/src/userEventMaps.ts @@ -1,6 +1,5 @@ import {pointerKey} from '@testing-library/user-event/system/pointer/shared'; -// TODO: delete the dev test-utils equivalent export let pointerMap: pointerKey[] = [ {name: 'MouseLeft', pointerType: 'mouse', button: 'primary', height: 1, width: 1, pressure: 0.5}, {name: 'MouseRight', pointerType: 'mouse', button: 'secondary'}, diff --git a/packages/@react-spectrum/test-utils/package.json b/packages/@react-spectrum/test-utils/package.json index 1df1ab1245c..9196a48915e 100644 --- a/packages/@react-spectrum/test-utils/package.json +++ b/packages/@react-spectrum/test-utils/package.json @@ -33,6 +33,7 @@ }, "dependencies": { "@react-aria/ssr": "^3.9.0", + "@react-aria/test-utils": "3.0.0-alpha.1", "@swc/helpers": "^0.5.0", "resolve": "^1.17.0" }, diff --git a/packages/@react-spectrum/test-utils/src/events.ts b/packages/@react-spectrum/test-utils/src/events.ts deleted file mode 100644 index 9c8a1da031f..00000000000 --- a/packages/@react-spectrum/test-utils/src/events.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2020 Adobe. All rights reserved. - * This file is licensed to you under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. You may obtain a copy - * of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under - * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS - * OF ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. - */ - -import {act, fireEvent} from '@testing-library/react'; - -// TODO: expose from aria testing package, and re-export from this package? -// Triggers a "longPress" event on an element. -export const DEFAULT_LONG_PRESS_TIME = 500; - -export function triggerLongPress(element, opts = {}) { - fireEvent.pointerDown(element, {pointerType: 'touch', ...opts}); - act(() => { - jest.advanceTimersByTime(DEFAULT_LONG_PRESS_TIME); - }); - fireEvent.pointerUp(element, {pointerType: 'touch', ...opts}); -} diff --git a/packages/@react-spectrum/test-utils/src/index.ts b/packages/@react-spectrum/test-utils/src/index.ts index d80813ced6c..affbece0595 100644 --- a/packages/@react-spectrum/test-utils/src/index.ts +++ b/packages/@react-spectrum/test-utils/src/index.ts @@ -12,10 +12,9 @@ /// -export * from './events'; +export * from '@react-aria/test-utils'; export * from './testSetup'; export * from './testSSR'; export * from './renderOverride'; export * from './StrictModeWrapper'; export * from './mockImplementation'; -export * from './userEventMaps'; diff --git a/packages/@react-spectrum/test-utils/src/testSetup.ts b/packages/@react-spectrum/test-utils/src/testSetup.ts index cb932491472..03e42416b22 100644 --- a/packages/@react-spectrum/test-utils/src/testSetup.ts +++ b/packages/@react-spectrum/test-utils/src/testSetup.ts @@ -25,68 +25,3 @@ export function simulateMobile(width: number = 700) { export function simulateDesktop(width: number = 701) { jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => Math.max(width, 701)); } - -// TODO: move to aria test util package -/** - * Enables reading pageX/pageY from fireEvent.mouse*(..., {pageX: ..., pageY: ...}). - */ -export function installMouseEvent() { - beforeAll(() => { - let oldMouseEvent = MouseEvent; - // @ts-ignore - global.MouseEvent = class FakeMouseEvent extends MouseEvent { - _init: {pageX: number, pageY: number}; - constructor(name, init) { - super(name, init); - this._init = init; - } - get pageX() { - return this._init.pageX; - } - get pageY() { - return this._init.pageY; - } - }; - // @ts-ignore - global.MouseEvent.oldMouseEvent = oldMouseEvent; - }); - afterAll(() => { - // @ts-ignore - global.MouseEvent = global.MouseEvent.oldMouseEvent; - }); -} - -export function installPointerEvent() { - beforeAll(() => { - // @ts-ignore - global.PointerEvent = class FakePointerEvent extends MouseEvent { - _init: {pageX: number, pageY: number, pointerType: string, pointerId: number, width: number, height: number}; - constructor(name, init) { - super(name, init); - this._init = init; - } - get pointerType() { - return this._init.pointerType ?? 'mouse'; - } - get pointerId() { - return this._init.pointerId; - } - get pageX() { - return this._init.pageX; - } - get pageY() { - return this._init.pageY; - } - get width() { - return this._init.width; - } - get height() { - return this._init.height; - } - }; - }); - afterAll(() => { - // @ts-ignore - delete global.PointerEvent; - }); -} diff --git a/packages/@react-spectrum/test-utils/src/userEventMaps.ts b/packages/@react-spectrum/test-utils/src/userEventMaps.ts deleted file mode 100644 index ae355d83c9a..00000000000 --- a/packages/@react-spectrum/test-utils/src/userEventMaps.ts +++ /dev/null @@ -1,10 +0,0 @@ -import {pointerKey} from '@testing-library/user-event/system/pointer/shared'; - -export let pointerMap: pointerKey[] = [ - {name: 'MouseLeft', pointerType: 'mouse', button: 'primary', height: 1, width: 1, pressure: 0.5}, - {name: 'MouseRight', pointerType: 'mouse', button: 'secondary'}, - {name: 'MouseMiddle', pointerType: 'mouse', button: 'auxiliary'}, - {name: 'TouchA', pointerType: 'touch', height: 1, width: 1}, - {name: 'TouchB', pointerType: 'touch'}, - {name: 'TouchC', pointerType: 'touch'} -] as unknown as pointerKey[]; From 488da8e6b61ca49d0ee1eb7ef809763c67efed04 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Mon, 4 Dec 2023 14:55:02 -0800 Subject: [PATCH 12/31] fix menutrigger tests --- packages/@react-spectrum/menu/test/MenuTrigger.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@react-spectrum/menu/test/MenuTrigger.test.js b/packages/@react-spectrum/menu/test/MenuTrigger.test.js index de001f44637..3109aab450b 100644 --- a/packages/@react-spectrum/menu/test/MenuTrigger.test.js +++ b/packages/@react-spectrum/menu/test/MenuTrigger.test.js @@ -80,12 +80,12 @@ describe('MenuTrigger', function () { }); afterEach(() => { - jest.runAllTimers(); onOpenChange.mockClear(); onOpen.mockClear(); onClose.mockClear(); onSelect.mockClear(); onSelectionChange.mockClear(); + act(() => jest.runAllTimers()); }); afterAll(function () { From a84a6df9856ef33d7237fc655d4e51ac89b176c1 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Mon, 4 Dec 2023 16:41:40 -0800 Subject: [PATCH 13/31] replacing fireEvent with userEvent equivalents in hooks tests pt1 --- .../aria-modal-polyfill/test/index.test.tsx | 13 +- .../calendar/test/useCalendar.test.js | 50 ++-- .../color/test/useColorWheel.test.tsx | 28 +- packages/@react-aria/dnd/test/dnd.test.js | 147 ++++------ .../dnd/test/useDraggableCollection.test.js | 85 ++---- .../dnd/test/useDroppableCollection.test.js | 119 ++++---- .../@react-aria/focus/test/FocusScope.test.js | 79 +++--- .../@react-aria/grid/test/useGrid.test.js | 54 ++-- .../interactions/test/PressResponder.test.js | 17 +- .../interactions/test/Pressable.test.js | 18 +- .../interactions/test/useKeyboard.test.js | 31 +- .../landmark/test/useLandmark.test.tsx | 265 +++++++----------- .../test/useSelectableCollection.test.js | 9 +- 13 files changed, 390 insertions(+), 525 deletions(-) diff --git a/packages/@react-aria/aria-modal-polyfill/test/index.test.tsx b/packages/@react-aria/aria-modal-polyfill/test/index.test.tsx index c406e55be10..7cdb04e077c 100644 --- a/packages/@react-aria/aria-modal-polyfill/test/index.test.tsx +++ b/packages/@react-aria/aria-modal-polyfill/test/index.test.tsx @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, simulateMobile, waitFor} from '@react-spectrum/test-utils'; +import {act, pointerMap, render, simulateMobile, waitFor} from '@react-spectrum/test-utils'; import {ActionButton, Button} from '@react-spectrum/button'; import {Content} from '@react-spectrum/view'; import {Dialog, DialogTrigger} from '@react-spectrum/dialog'; @@ -48,9 +48,7 @@ describe('watchModals', () => { expect(queryByRole('separator')).toBeNull(); expect(document.activeElement).toBe(modal); - - fireEvent.keyDown(modal, {key: 'Escape'}); - fireEvent.keyUp(modal, {key: 'Escape'}); + await user.keyboard('{Escape}'); act(() => { jest.runAllTimers(); @@ -137,8 +135,8 @@ describe('watchModals', () => { expect(queryByRole('separator')).toBeNull(); // start closing dialogs - fireEvent.keyDown(innerDialog, {key: 'Escape'}); - fireEvent.keyUp(innerDialog, {key: 'Escape'}); + await user.keyboard('{Escape}'); + act(() => { jest.runAllTimers(); }); @@ -153,8 +151,7 @@ describe('watchModals', () => { expect(queryByRole('separator')).toBeNull(); // close the outer dialog - fireEvent.keyDown(dialog, {key: 'Escape'}); - fireEvent.keyUp(dialog, {key: 'Escape'}); + await user.keyboard('{Escape}'); act(() => { jest.runAllTimers(); }); diff --git a/packages/@react-aria/calendar/test/useCalendar.test.js b/packages/@react-aria/calendar/test/useCalendar.test.js index 38ff03a2bed..8e6015eaacd 100644 --- a/packages/@react-aria/calendar/test/useCalendar.test.js +++ b/packages/@react-aria/calendar/test/useCalendar.test.js @@ -10,14 +10,17 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, render} from '@react-spectrum/test-utils'; +import {act, pointerMap, render} from '@react-spectrum/test-utils'; import {CalendarDate} from '@internationalized/date'; import {Example} from '../stories/Example'; import React from 'react'; +import userEvent from '@testing-library/user-event'; describe('useCalendar', () => { + let user; beforeAll(() => { jest.useFakeTimers(); + user = userEvent.setup({delay: null, pointerMap}); }); afterEach(() => { @@ -36,8 +39,15 @@ describe('useCalendar', () => { expect(document.activeElement).toBe(cell); for (let i = 0; i < count; i++) { - fireEvent.keyDown(document.activeElement, {key, ...opts}); - fireEvent.keyUp(document.activeElement, {key, ...opts}); + if (opts?.shiftKey) { + await user.keyboard('{Shift>}'); + } + + await user.keyboard(`{${key}}`); + + if (opts?.shiftKey) { + await user.keyboard('{/Shift}'); + } } cell = getByLabelText(value, {exact: false}); @@ -142,21 +152,19 @@ describe('useCalendar', () => { }); }); - function testPagination(defaultValue, rangeBefore, rangeAfter, rel, count, visibleDuration, pageBehavior) { + async function testPagination(defaultValue, rangeBefore, rangeAfter, rel, count, visibleDuration, pageBehavior) { let {getByTestId, getByLabelText, unmount} = render(); let grid = getByTestId('range'); expect(grid).toHaveTextContent(rangeBefore); - let btn = getByLabelText(rel); for (let i = 0; i < count; i++) { - fireEvent.click(btn); + await user.click(btn); } expect(grid).toHaveTextContent(rangeAfter); - unmount(); - } + } describe('pagination', () => { it.each` @@ -165,18 +173,18 @@ describe('useCalendar', () => { ${'going forward two'} | ${new CalendarDate(2019, 1, 1)} | ${'January to February 2019'} | ${'May to June 2019'} | ${'Next'} | ${2} | ${{months: 2}} ${'going backward one'} | ${new CalendarDate(2019, 1, 1)} | ${'January to February 2019'} | ${'November to December 2018'} | ${'Previous'} | ${1} | ${{months: 2}} ${'going backward two'} | ${new CalendarDate(2019, 1, 1)} | ${'January to February 2019'} | ${'September to October 2018'} | ${'Previous'} | ${2} | ${{months: 2}} - `('should use visible as default value $Name', ({defaultValue, rangeBefore, rangeAfter, rel, count, visibleDuration}) => { - testPagination(defaultValue, rangeBefore, rangeAfter, rel, count, visibleDuration); + `('should use visible as default value $Name', async ({defaultValue, rangeBefore, rangeAfter, rel, count, visibleDuration}) => { + await testPagination(defaultValue, rangeBefore, rangeAfter, rel, count, visibleDuration); }); - + it.each` Name | defaultValue | rangeBefore | rangeAfter | rel | count | visibleDuration | pageBehavior ${'going forward one'} | ${new CalendarDate(2019, 1, 1)} | ${'January to February 2019'} | ${'February to March 2019'} | ${'Next'} | ${1} | ${{months: 2}} | ${'single'} ${'going forward two'} | ${new CalendarDate(2019, 1, 1)} | ${'January to February 2019'} | ${'March to April 2019'} | ${'Next'} | ${2} | ${{months: 2}} | ${'single'} ${'going backward one'} | ${new CalendarDate(2019, 1, 1)} | ${'January to February 2019'} | ${'December 2018 to January 2019'} | ${'Previous'} | ${1} | ${{months: 2}} | ${'single'} ${'going backward two'} | ${new CalendarDate(2019, 1, 1)} | ${'January to February 2019'} | ${'November to December 2018'} | ${'Previous'} | ${2} | ${{months: 2}} | ${'single'} - `('should use pageBehavior single $Name', ({defaultValue, rangeBefore, rangeAfter, rel, count, visibleDuration, pageBehavior}) => { - testPagination(defaultValue, rangeBefore, rangeAfter, rel, count, visibleDuration, pageBehavior); + `('should use pageBehavior single $Name', async ({defaultValue, rangeBefore, rangeAfter, rel, count, visibleDuration, pageBehavior}) => { + await testPagination(defaultValue, rangeBefore, rangeAfter, rel, count, visibleDuration, pageBehavior); }); it.each` @@ -185,8 +193,8 @@ describe('useCalendar', () => { ${'week going forward two'} | ${new CalendarDate(2019, 1, 1)} | ${'December 23, 2018 to January 12, 2019'} | ${'February 3 to 23, 2019'} | ${'Next'} | ${2} | ${{weeks: 3}} ${'week going backward one'} | ${new CalendarDate(2019, 1, 1)} | ${'December 23, 2018 to January 12, 2019'} | ${'December 2 to 22, 2018'} | ${'Previous'} | ${1} | ${{weeks: 3}} ${'week going backward two'} | ${new CalendarDate(2019, 1, 1)} | ${'December 23, 2018 to January 12, 2019'} | ${'November 11 to December 1, 2018'} | ${'Previous'} | ${2} | ${{weeks: 3}} - `('should use visible as default $Name', ({defaultValue, rangeBefore, rangeAfter, rel, count, visibleDuration, pageBehavior}) => { - testPagination(defaultValue, rangeBefore, rangeAfter, rel, count, visibleDuration, pageBehavior); + `('should use visible as default $Name', async ({defaultValue, rangeBefore, rangeAfter, rel, count, visibleDuration, pageBehavior}) => { + await testPagination(defaultValue, rangeBefore, rangeAfter, rel, count, visibleDuration, pageBehavior); }); it.each` @@ -195,8 +203,8 @@ describe('useCalendar', () => { ${'week going forward four'} | ${new CalendarDate(2019, 1, 1)} | ${'December 23, 2018 to January 12, 2019'} | ${'January 20 to February 9, 2019'} | ${'Next'} | ${4} | ${{weeks: 3}} | ${'single'} ${'week going backward one'} | ${new CalendarDate(2019, 1, 1)} | ${'December 23, 2018 to January 12, 2019'} | ${'December 16, 2018 to January 5, 2019'} | ${'Previous'} | ${1} | ${{weeks: 3}} | ${'single'} ${'week going backward four'} | ${new CalendarDate(2019, 1, 1)} | ${'December 23, 2018 to January 12, 2019'} | ${'November 25 to December 15, 2018'} | ${'Previous'} | ${4} | ${{weeks: 3}} | ${'single'} - `('should use pageBehavior single $Name', ({defaultValue, rangeBefore, rangeAfter, rel, count, visibleDuration, pageBehavior}) => { - testPagination(defaultValue, rangeBefore, rangeAfter, rel, count, visibleDuration, pageBehavior); + `('should use pageBehavior single $Name', async ({defaultValue, rangeBefore, rangeAfter, rel, count, visibleDuration, pageBehavior}) => { + await testPagination(defaultValue, rangeBefore, rangeAfter, rel, count, visibleDuration, pageBehavior); }); it.each` @@ -205,8 +213,8 @@ describe('useCalendar', () => { ${'day going forward two'} | ${new CalendarDate(2019, 1, 1)} | ${'December 30, 2018 to January 3, 2019'} | ${'January 9 to 13, 2019'} | ${'Next'} | ${2} | ${{days: 5}} ${'day going backward one'} | ${new CalendarDate(2019, 1, 1)} | ${'December 30, 2018 to January 3, 2019'} | ${'December 25 to 29, 2018'} | ${'Previous'} | ${1} | ${{days: 5}} ${'day going backward two'} | ${new CalendarDate(2019, 1, 1)} | ${'December 30, 2018 to January 3, 2019'} | ${'December 20 to 24, 2018'} | ${'Previous'} | ${2} | ${{days: 5}} - `('should use visible as default $Name', ({defaultValue, rangeBefore, rangeAfter, rel, count, visibleDuration, pageBehavior}) => { - testPagination(defaultValue, rangeBefore, rangeAfter, rel, count, visibleDuration, pageBehavior); + `('should use visible as default $Name', async ({defaultValue, rangeBefore, rangeAfter, rel, count, visibleDuration, pageBehavior}) => { + await testPagination(defaultValue, rangeBefore, rangeAfter, rel, count, visibleDuration, pageBehavior); }); it.each` @@ -215,8 +223,8 @@ describe('useCalendar', () => { ${'day going forward five'} | ${new CalendarDate(2019, 1, 1)} | ${'December 30, 2018 to January 3, 2019'} | ${'January 3 to 7, 2019'} | ${'Next'} | ${4} | ${{days: 5}} | ${'single'} ${'day going backward one'} | ${new CalendarDate(2019, 1, 1)} | ${'December 30, 2018 to January 3, 2019'} | ${'December 29, 2018 to January 2, 2019'} | ${'Previous'} | ${1} | ${{days: 5}} | ${'single'} ${'day going backward five'} | ${new CalendarDate(2019, 1, 1)} | ${'December 30, 2018 to January 3, 2019'} | ${'December 26 to 30, 2018'} | ${'Previous'} | ${4} | ${{days: 5}} | ${'single'} - `('should use pageBehavior single $Name', ({defaultValue, rangeBefore, rangeAfter, rel, count, visibleDuration, pageBehavior}) => { - testPagination(defaultValue, rangeBefore, rangeAfter, rel, count, visibleDuration, pageBehavior); + `('should use pageBehavior single $Name', async ({defaultValue, rangeBefore, rangeAfter, rel, count, visibleDuration, pageBehavior}) => { + await testPagination(defaultValue, rangeBefore, rangeAfter, rel, count, visibleDuration, pageBehavior); }); }); }); diff --git a/packages/@react-aria/color/test/useColorWheel.test.tsx b/packages/@react-aria/color/test/useColorWheel.test.tsx index 05b11dbfe8c..874a3eb3630 100644 --- a/packages/@react-aria/color/test/useColorWheel.test.tsx +++ b/packages/@react-aria/color/test/useColorWheel.test.tsx @@ -112,73 +112,73 @@ describe('useColorWheel', () => { }); describe('keyboard events', () => { - it('left/right works', () => { + it('left/right works', async () => { let defaultColor = parseColor('hsl(0, 100%, 50%)'); let {getByRole} = render(); let slider = getByRole('slider'); act(() => {slider.focus();}); - fireEvent.keyDown(slider, {key: 'Right'}); + await user.keyboard('{Right}'); expect(onChangeSpy).toHaveBeenCalledTimes(1); expect(onChangeSpy.mock.calls[0][0].toString('hsla')).toBe(defaultColor.withChannelValue('hue', 1).toString('hsla')); expect(slider).toHaveAttribute('value', '1'); - fireEvent.keyDown(slider, {key: 'Left'}); + await user.keyboard('{Left}'); expect(onChangeSpy).toHaveBeenCalledTimes(2); expect(onChangeSpy.mock.calls[1][0].toString('hsla')).toBe(defaultColor.withChannelValue('hue', 0).toString('hsla')); expect(slider).toHaveAttribute('value', '0'); }); - it('up/down works', () => { + it('up/down works', async () => { let defaultColor = parseColor('hsl(0, 100%, 50%)'); let {getByRole} = render(); let slider = getByRole('slider'); act(() => {slider.focus();}); - fireEvent.keyDown(slider, {key: 'Up'}); + await user.keyboard('{Up}'); expect(onChangeSpy).toHaveBeenCalledTimes(1); expect(onChangeSpy.mock.calls[0][0].toString('hsla')).toBe(defaultColor.withChannelValue('hue', 1).toString('hsla')); expect(slider).toHaveAttribute('value', '1'); - fireEvent.keyDown(slider, {key: 'Down'}); + await user.keyboard('{Down}'); expect(onChangeSpy).toHaveBeenCalledTimes(2); expect(onChangeSpy.mock.calls[1][0].toString('hsla')).toBe(defaultColor.withChannelValue('hue', 0).toString('hsla')); expect(slider).toHaveAttribute('value', '0'); }); - it('doesn\'t work when disabled', () => { + it('doesn\'t work when disabled', async () => { let defaultColor = parseColor('hsl(0, 100%, 50%)'); let {getByRole} = render(); let slider = getByRole('slider'); act(() => {slider.focus();}); - fireEvent.keyDown(slider, {key: 'Right'}); + await user.keyboard('{Right}'); expect(onChangeSpy).toHaveBeenCalledTimes(0); - fireEvent.keyDown(slider, {key: 'Left'}); + await user.keyboard('{Left}'); expect(onChangeSpy).toHaveBeenCalledTimes(0); }); - it('wraps around', () => { + it('wraps around', async () => { let defaultColor = parseColor('hsl(0, 100%, 50%)'); let {getByRole} = render(); let slider = getByRole('slider'); act(() => {slider.focus();}); - fireEvent.keyDown(slider, {key: 'Left'}); + await user.keyboard('{Left}'); expect(onChangeSpy).toHaveBeenCalledTimes(1); expect(onChangeSpy.mock.calls[0][0].toString('hsla')).toBe(defaultColor.withChannelValue('hue', 359).toString('hsla')); expect(slider).toHaveAttribute('value', '359'); }); - it('steps with page up/down', () => { + it('steps with page up/down', async () => { let defaultColor = parseColor('hsl(0, 100%, 50%)'); let {getByRole} = render(); let slider = getByRole('slider'); act(() => {slider.focus();}); - fireEvent.keyDown(slider, {key: 'PageUp'}); + await user.keyboard('{PageUp}'); expect(onChangeSpy).toHaveBeenCalledTimes(1); expect(onChangeSpy.mock.calls[0][0].toString('hsla')).toBe(defaultColor.withChannelValue('hue', 15).toString('hsla')); expect(slider).toHaveAttribute('value', '15'); - fireEvent.keyDown(slider, {key: 'PageDown'}); + await user.keyboard('{PageDown}'); expect(onChangeSpy).toHaveBeenCalledTimes(2); expect(onChangeSpy.mock.calls[1][0].toString('hsla')).toBe(defaultColor.withChannelValue('hue', 0).toString('hsla')); expect(slider).toHaveAttribute('value', '0'); diff --git a/packages/@react-aria/dnd/test/dnd.test.js b/packages/@react-aria/dnd/test/dnd.test.js index 614d2ca1721..c0220cca2ca 100644 --- a/packages/@react-aria/dnd/test/dnd.test.js +++ b/packages/@react-aria/dnd/test/dnd.test.js @@ -1296,9 +1296,8 @@ describe('useDrag and useDrop', function () { }); describe('keyboard', () => { - afterEach(() => { - fireEvent.keyDown(document.body, {key: 'Escape'}); - fireEvent.keyUp(document.body, {key: 'Escape'}); + afterEach(async () => { + await user.keyboard('{Escape}'); act(() => jest.runAllTimers()); }); @@ -1334,8 +1333,7 @@ describe('useDrag and useDrop', function () { expect(draggable).toHaveAttribute('aria-describedby'); expect(document.getElementById(draggable.getAttribute('aria-describedby'))).toHaveTextContent('Press Enter to start dragging'); - fireEvent.keyDown(draggable, {key: 'Enter'}); - fireEvent.keyUp(draggable, {key: 'Enter'}); + await user.keyboard('{Enter}'); expect(draggable).toHaveAttribute('data-dragging', 'true'); expect(onDragStart).toHaveBeenCalledTimes(1); @@ -1389,8 +1387,7 @@ describe('useDrag and useDrop', function () { expect(droppable).toHaveAttribute('data-droptarget', 'false'); expect(droppable2).toHaveAttribute('data-droptarget', 'true'); - fireEvent.keyDown(droppable2, {key: 'Enter'}); - fireEvent.keyUp(droppable2, {key: 'Enter'}); + await user.keyboard('{Enter}'); expect(document.activeElement).toBe(droppable2); expect(droppable).not.toHaveAttribute('aria-describedby'); @@ -1454,8 +1451,7 @@ describe('useDrag and useDrop', function () { await user.tab(); expect(document.activeElement).toBe(draggable); - fireEvent.keyDown(draggable, {key: 'Enter'}); - fireEvent.keyUp(draggable, {key: 'Enter'}); + await user.keyboard('{Enter}'); act(() => jest.runAllTimers()); expect(document.activeElement).toBe(droppable); @@ -1483,8 +1479,7 @@ describe('useDrag and useDrop', function () { await user.tab(); expect(document.activeElement).toBe(draggable); - fireEvent.keyDown(draggable, {key: 'Enter'}); - fireEvent.keyUp(draggable, {key: 'Enter'}); + await user.keyboard('{Enter}'); act(() => jest.runAllTimers()); expect(document.activeElement).toBe(droppable); @@ -1510,13 +1505,11 @@ describe('useDrag and useDrop', function () { await user.tab(); expect(document.activeElement).toBe(draggable); - fireEvent.keyDown(draggable, {key: 'Enter'}); - fireEvent.keyUp(draggable, {key: 'Enter'}); + await user.keyboard('{Enter}'); act(() => jest.runAllTimers()); expect(document.activeElement).toBe(droppable); - fireEvent.keyDown(droppable, {key: 'Escape'}); - fireEvent.keyUp(droppable, {key: 'Escape'}); + await user.keyboard('{Escape}'); expect(document.activeElement).toBe(draggable); expect(announce).toHaveBeenCalledWith('Drop canceled.'); @@ -1536,8 +1529,7 @@ describe('useDrag and useDrop', function () { await user.tab(); expect(document.activeElement).toBe(draggable); - fireEvent.keyDown(draggable, {key: 'Enter'}); - fireEvent.keyUp(draggable, {key: 'Enter'}); + await user.keyboard('{Enter}'); act(() => jest.runAllTimers()); expect(document.activeElement).toBe(droppable); expect(onDragStart).toHaveBeenCalledTimes(1); @@ -1545,8 +1537,7 @@ describe('useDrag and useDrop', function () { await user.tab(); expect(document.activeElement).toBe(draggable); - fireEvent.keyDown(draggable, {key: 'Enter'}); - fireEvent.keyUp(draggable, {key: 'Enter'}); + await user.keyboard('{Enter}'); act(() => jest.runAllTimers()); expect(document.activeElement).toBe(draggable); @@ -1567,8 +1558,7 @@ describe('useDrag and useDrop', function () { await user.tab(); expect(document.activeElement).toBe(draggable); - fireEvent.keyDown(draggable, {key: 'Enter'}); - fireEvent.keyUp(draggable, {key: 'Enter'}); + await user.keyboard('{Enter}'); act(() => jest.runAllTimers()); expect(document.activeElement).toBe(droppable); @@ -1595,8 +1585,7 @@ describe('useDrag and useDrop', function () { await user.tab(); expect(document.activeElement).toBe(draggable); - fireEvent.keyDown(draggable, {key: 'Enter'}); - fireEvent.keyUp(draggable, {key: 'Enter'}); + await user.keyboard('{Enter}'); act(() => {jest.runAllTimers();}); expect(document.activeElement).toBe(droppable2); }); @@ -1621,8 +1610,7 @@ describe('useDrag and useDrop', function () { await user.tab(); expect(document.activeElement).toBe(draggable); - fireEvent.keyDown(draggable, {key: 'Enter'}); - fireEvent.keyUp(draggable, {key: 'Enter'}); + await user.keyboard('{Enter}'); act(() => jest.runAllTimers()); expect(document.activeElement).toBe(droppable); @@ -1660,8 +1648,7 @@ describe('useDrag and useDrop', function () { await user.tab(); expect(document.activeElement).toBe(draggable); - fireEvent.keyDown(draggable, {key: 'Enter'}); - fireEvent.keyUp(draggable, {key: 'Enter'}); + await user.keyboard('{Enter}'); act(() => jest.runAllTimers()); expect(document.activeElement).toBe(droppable); @@ -1697,14 +1684,12 @@ describe('useDrag and useDrop', function () { await user.tab(); expect(document.activeElement).toBe(draggable); - fireEvent.keyDown(draggable, {key: 'Enter'}); - fireEvent.keyUp(draggable, {key: 'Enter'}); + await user.keyboard('{Enter}'); act(() => jest.runAllTimers()); expect(document.activeElement).toBe(droppable); expect(droppable).toHaveAttribute('data-droptarget', 'true'); - fireEvent.keyDown(droppable, {key: 'Escape'}); - fireEvent.keyUp(droppable, {key: 'Escape'}); + await user.keyboard('{Escape}'); expect(droppable).toHaveAttribute('data-droptarget', 'false'); expect(document.activeElement).toBe(droppable); }); @@ -1728,13 +1713,11 @@ describe('useDrag and useDrop', function () { await user.tab(); expect(document.activeElement).toBe(draggable); - fireEvent.keyDown(draggable, {key: 'Enter'}); - fireEvent.keyUp(draggable, {key: 'Enter'}); + await user.keyboard('{Enter}'); act(() => jest.runAllTimers()); expect(document.activeElement).toBe(droppable); - fireEvent.keyDown(droppable, {key: 'Enter'}); - fireEvent.keyUp(droppable, {key: 'Enter'}); + await user.keyboard('{Enter}'); expect(onDrop).toHaveBeenCalledTimes(1); expect(onDrop).toHaveBeenCalledWith({ type: 'drop', @@ -1772,13 +1755,11 @@ describe('useDrag and useDrop', function () { await user.tab(); expect(document.activeElement).toBe(draggable); - fireEvent.keyDown(draggable, {key: 'Enter'}); - fireEvent.keyUp(draggable, {key: 'Enter'}); + await user.keyboard('{Enter}'); act(() => jest.runAllTimers()); expect(document.activeElement).toBe(droppable); - fireEvent.keyDown(droppable, {key: 'Enter'}); - fireEvent.keyUp(droppable, {key: 'Enter'}); + await user.keyboard('{Enter}'); expect(onDrop).toHaveBeenCalledTimes(1); expect(onDrop).toHaveBeenCalledWith({ type: 'drop', @@ -1821,13 +1802,11 @@ describe('useDrag and useDrop', function () { await user.tab(); expect(document.activeElement).toBe(draggable); - fireEvent.keyDown(draggable, {key: 'Enter'}); - fireEvent.keyUp(draggable, {key: 'Enter'}); + await user.keyboard('{Enter}'); act(() => jest.runAllTimers()); expect(document.activeElement).toBe(droppable); - fireEvent.keyDown(droppable, {key: 'Enter'}); - fireEvent.keyUp(droppable, {key: 'Enter'}); + await user.keyboard('{Enter}'); expect(onDrop).toHaveBeenCalledTimes(1); expect(onDrop).toHaveBeenCalledWith({ type: 'drop', @@ -1868,13 +1847,11 @@ describe('useDrag and useDrop', function () { await user.tab(); expect(document.activeElement).toBe(draggable); - fireEvent.keyDown(draggable, {key: 'Enter'}); - fireEvent.keyUp(draggable, {key: 'Enter'}); + await user.keyboard('{Enter}'); act(() => jest.runAllTimers()); expect(document.activeElement).toBe(droppable); - fireEvent.keyDown(droppable, {key: 'Enter'}); - fireEvent.keyUp(droppable, {key: 'Enter'}); + await user.keyboard('{Enter}'); expect(onDrop).toHaveBeenCalledTimes(1); expect(onDrop).toHaveBeenCalledWith({ type: 'drop', @@ -1918,16 +1895,14 @@ describe('useDrag and useDrop', function () { await user.tab(); expect(document.activeElement).toBe(draggable); - fireEvent.keyDown(draggable, {key: 'Enter'}); - fireEvent.keyUp(draggable, {key: 'Enter'}); + await user.keyboard('{Enter}'); act(() => jest.runAllTimers()); expect(document.activeElement).toBe(droppable); expect(getDropOperation).toHaveBeenCalledWith(new Set(['text/plain']), ['move', 'copy', 'link']); expect(droppable).toHaveAttribute('data-droptarget', 'true'); - fireEvent.keyDown(droppable, {key: 'Enter'}); - fireEvent.keyUp(droppable, {key: 'Enter'}); + await user.keyboard('{Enter}'); expect(onDrop).toHaveBeenCalledWith({ type: 'drop', x: 50, @@ -1967,16 +1942,14 @@ describe('useDrag and useDrop', function () { await user.tab(); expect(document.activeElement).toBe(draggable); - fireEvent.keyDown(draggable, {key: 'Enter'}); - fireEvent.keyUp(draggable, {key: 'Enter'}); + await user.keyboard('{Enter}'); act(() => jest.runAllTimers()); expect(document.activeElement).toBe(droppable); expect(getDropOperation).toHaveBeenCalledWith(new Set(['text/plain']), ['copy']); expect(droppable).toHaveAttribute('data-droptarget', 'true'); - fireEvent.keyDown(droppable, {key: 'Enter'}); - fireEvent.keyUp(droppable, {key: 'Enter'}); + await user.keyboard('{Enter}'); expect(onDrop).toHaveBeenCalledWith({ type: 'drop', x: 50, @@ -2018,8 +1991,7 @@ describe('useDrag and useDrop', function () { await user.tab(); expect(document.activeElement).toBe(draggable); - fireEvent.keyDown(draggable, {key: 'Enter'}); - fireEvent.keyUp(draggable, {key: 'Enter'}); + await user.keyboard('{Enter}'); act(() => jest.runAllTimers()); expect(document.activeElement).toBe(droppable2); @@ -2067,8 +2039,7 @@ describe('useDrag and useDrop', function () { expect(draggable).toHaveAttribute('aria-describedby'); expect(document.getElementById(draggable.getAttribute('aria-describedby'))).toHaveTextContent('Press Enter to start dragging'); - fireEvent.keyDown(draggable, {key: 'Enter'}); - fireEvent.keyUp(draggable, {key: 'Enter'}); + await user.keyboard('{Enter}'); expect(draggable).toHaveAttribute('data-dragging', 'true'); expect(onDragStart).toHaveBeenCalledTimes(1); @@ -2122,8 +2093,7 @@ describe('useDrag and useDrop', function () { expect(droppable).toHaveAttribute('data-droptarget', 'true'); expect(droppable2).toHaveAttribute('data-droptarget', 'false'); - fireEvent.keyDown(droppable, {key: 'Enter'}); - fireEvent.keyUp(droppable, {key: 'Enter'}); + await user.keyboard('{Enter}'); expect(document.activeElement).toBe(droppable); expect(droppable).not.toHaveAttribute('aria-describedby'); @@ -2176,9 +2146,8 @@ describe('useDrag and useDrop', function () { fireEvent.focus(document.body); }); - afterEach(() => { - fireEvent.keyDown(document.body, {key: 'Escape'}); - fireEvent.keyUp(document.body, {key: 'Escape'}); + afterEach(async () => { + await user.keyboard('{Escape}'); }); it('should allow navigating with only focus events', async () => { @@ -2209,7 +2178,7 @@ describe('useDrag and useDrop', function () { expect(document.getElementById(draggable.getAttribute('aria-describedby'))).toHaveTextContent('Click to start dragging'); expect(draggable).toHaveAttribute('data-dragging', 'false'); - fireEvent.click(draggable); + await user.click(draggable); act(() => jest.runAllTimers()); expect(document.activeElement).toBe(draggable); expect(draggable).toHaveAttribute('aria-describedby'); @@ -2311,7 +2280,7 @@ describe('useDrag and useDrop', function () { expect(droppable2).toHaveAttribute('data-droptarget', 'false'); }); - it('should hide all non drop target elements from screen readers while dragging', () => { + it('should hide all non drop target elements from screen readers while dragging', async () => { let tree = render(<> @@ -2328,7 +2297,7 @@ describe('useDrag and useDrop', function () { let buttons = tree.getAllByRole('button'); expect(buttons).toHaveLength(4); - fireEvent.click(draggable); + await user.click(draggable); act(() => jest.runAllTimers()); buttons = tree.getAllByRole('button'); @@ -2338,7 +2307,7 @@ describe('useDrag and useDrop', function () { expect(tree.getByText('Text')).toHaveAttribute('aria-hidden', 'true'); }); - it('should support clicking the original drag target to cancel drag', () => { + it('should support clicking the original drag target to cancel drag', async () => { let tree = render(<> @@ -2361,7 +2330,7 @@ describe('useDrag and useDrop', function () { expect(announce).toHaveBeenCalledWith('Drop canceled.'); }); - it('should support clicking the original drag target to cancel drag (virtual pointer event)', () => { + it('should support clicking the original drag target to cancel drag (virtual pointer event)', async () => { let tree = render(<> @@ -2372,7 +2341,7 @@ describe('useDrag and useDrop', function () { fireEvent.focus(draggable); fireEvent(draggable, pointerEvent('pointerdown', {pointerId: 1, width: 1, height: 1, pressure: 0, detail: 0})); fireEvent(draggable, pointerEvent('pointerup', {pointerId: 1, width: 1, height: 1, pressure: 0, detail: 0})); - fireEvent.click(draggable); + await user.click(draggable); act(() => jest.runAllTimers()); expect(draggable).toHaveAttribute('data-dragging', 'true'); expect(draggable).toHaveAttribute('aria-describedby'); @@ -2389,7 +2358,7 @@ describe('useDrag and useDrop', function () { expect(announce).toHaveBeenCalledWith('Drop canceled.'); }); - it('should support double tapping the drop target to complete drag (virtual pointer event)', () => { + it('should support double tapping the drop target to complete drag (virtual pointer event)', async () => { let onDrop = jest.fn(); let tree = render(<> @@ -2402,7 +2371,7 @@ describe('useDrag and useDrop', function () { fireEvent.focus(draggable); fireEvent(draggable, pointerEvent('pointerdown', {pointerId: 1, width: 1, height: 1, pressure: 0, detail: 0})); fireEvent(draggable, pointerEvent('pointerup', {pointerId: 1, width: 1, height: 1, pressure: 0, detail: 0})); - fireEvent.click(draggable); + await user.click(draggable); act(() => jest.runAllTimers()); expect(draggable).toHaveAttribute('data-dragging', 'true'); @@ -2420,7 +2389,7 @@ describe('useDrag and useDrop', function () { expect(onDrop).toHaveBeenCalledTimes(1); }); - it('should handle when a drop target is added', () => { + it('should handle when a drop target is added', async () => { let setShowTarget2; let Test = () => { let [showTarget2, _setShowTarget2] = React.useState(false); @@ -2439,7 +2408,7 @@ describe('useDrag and useDrop', function () { let draggable = tree.getByText('Drag me'); fireEvent.focus(draggable); - fireEvent.click(draggable); + await user.click(draggable); act(() => jest.runAllTimers()); expect(tree.getAllByRole('button')).toHaveLength(2); @@ -2481,7 +2450,7 @@ describe('useDrag and useDrop', function () { expect(tree.getAllByRole('textbox')).toHaveLength(2); }); - it('should handle when a drop target is removed', () => { + it('should handle when a drop target is removed', async () => { let setShowTarget2; let Test = () => { let [showTarget2, _setShowTarget2] = React.useState(true); @@ -2500,7 +2469,7 @@ describe('useDrag and useDrop', function () { let draggable = tree.getByText('Drag me'); fireEvent.focus(draggable); - fireEvent.click(draggable); + await user.click(draggable); act(() => jest.runAllTimers()); expect(tree.getAllByRole('button')).toHaveLength(3); @@ -2525,7 +2494,7 @@ describe('useDrag and useDrop', function () { let draggable = tree.getByText('Drag me'); fireEvent.focus(draggable); - fireEvent.click(draggable); + await user.click(draggable); act(() => jest.runAllTimers()); expect(tree.getAllByRole('button')).toHaveLength(3); @@ -2536,7 +2505,7 @@ describe('useDrag and useDrop', function () { expect(tree.getAllByRole('button')).toHaveLength(2); }); - it('should restore focus to the current drop target when focusing a non drop target element', () => { + it('should restore focus to the current drop target when focusing a non drop target element', async () => { let tree = render(<> @@ -2548,7 +2517,7 @@ describe('useDrag and useDrop', function () { let input = tree.getByRole('textbox'); fireEvent.focus(draggable); - fireEvent.click(draggable); + await user.click(draggable); act(() => jest.runAllTimers()); act(() => droppable.focus()); @@ -2557,7 +2526,7 @@ describe('useDrag and useDrop', function () { expect(document.activeElement).toBe(droppable); }); - it('should restore focus to the drag target when focusing a non drop target element and there is no current drop target', () => { + it('should restore focus to the drag target when focusing a non drop target element and there is no current drop target', async () => { let tree = render(<> @@ -2568,14 +2537,14 @@ describe('useDrag and useDrop', function () { let input = tree.getByRole('textbox'); fireEvent.focus(draggable); - fireEvent.click(draggable); + await user.click(draggable); act(() => jest.runAllTimers()); act(() => input.focus()); expect(document.activeElement).toBe(draggable); }); - it('should restore focus to the current drop target when blurring all elements', () => { + it('should restore focus to the current drop target when blurring all elements', async () => { let tree = render(<> @@ -2585,7 +2554,7 @@ describe('useDrag and useDrop', function () { let droppable = tree.getByText('Drop here'); fireEvent.focus(draggable); - fireEvent.click(draggable); + await user.click(draggable); act(() => jest.runAllTimers()); act(() => droppable.focus()); @@ -2594,7 +2563,7 @@ describe('useDrag and useDrop', function () { expect(document.activeElement).toBe(droppable); }); - it('should restore focus to the drag target when blurring all elements and there is no current drop target', () => { + it('should restore focus to the drag target when blurring all elements and there is no current drop target', async () => { let tree = render(<> @@ -2603,7 +2572,7 @@ describe('useDrag and useDrop', function () { let draggable = tree.getByText('Drag me'); act(() => draggable.focus()); - fireEvent.click(draggable); + await user.click(draggable); act(() => jest.runAllTimers()); act(() => draggable.blur()); @@ -2625,7 +2594,7 @@ describe('useDrag and useDrop', function () { expect(draggable).toHaveAttribute('data-dragging', 'false'); }); - it('should ignore clicks not from screen readers during dragging', () => { + it('should ignore clicks not from screen readers during dragging', async () => { let tree = render(<> @@ -2635,7 +2604,7 @@ describe('useDrag and useDrop', function () { let droppable = tree.getByText('Drop here'); fireEvent.focus(draggable); - fireEvent.click(draggable); + await user.click(draggable); act(() => jest.runAllTimers()); expect(draggable).toHaveAttribute('data-dragging', 'true'); @@ -2644,7 +2613,7 @@ describe('useDrag and useDrop', function () { expect(draggable).toHaveAttribute('data-dragging', 'true'); }); - it('should use touch specific aria descriptions when available', () => { + it('should use touch specific aria descriptions when available', async () => { window.ontouchstart = () => {}; let tree = render(<> @@ -2660,7 +2629,7 @@ describe('useDrag and useDrop', function () { expect(draggable).toHaveAttribute('aria-describedby'); expect(document.getElementById(draggable.getAttribute('aria-describedby'))).toHaveTextContent('Double tap to start dragging'); - fireEvent.click(draggable); + await user.click(draggable); act(() => jest.runAllTimers()); expect(document.activeElement).toBe(draggable); expect(draggable).toHaveAttribute('aria-describedby'); diff --git a/packages/@react-aria/dnd/test/useDraggableCollection.test.js b/packages/@react-aria/dnd/test/useDraggableCollection.test.js index d6fda713dba..1e4f2c41bb6 100644 --- a/packages/@react-aria/dnd/test/useDraggableCollection.test.js +++ b/packages/@react-aria/dnd/test/useDraggableCollection.test.js @@ -316,9 +316,8 @@ describe('useDraggableCollection', () => { }); describe('keyboard', () => { - afterEach(() => { - fireEvent.keyDown(document.body, {key: 'Escape'}); - fireEvent.keyUp(document.body, {key: 'Escape'}); + afterEach(async () => { + await user.keyboard('[Escape]'); }); it('should drag a single item', async () => { @@ -341,17 +340,14 @@ describe('useDraggableCollection', () => { await user.tab(); expect(document.activeElement).toBe(cells[0]); - fireEvent.keyDown(cells[0], {key: 'ArrowDown'}); - fireEvent.keyUp(cells[0], {key: 'ArrowDown'}); + await user.keyboard('[ArrowDown]'); expect(document.activeElement).toBe(cells[1]); - fireEvent.keyDown(cells[1], {key: 'ArrowRight'}); - fireEvent.keyUp(cells[1], {key: 'ArrowRight'}); + await user.keyboard('[ArrowRight]'); let dragButton = within(cells[1]).getByRole('button'); expect(document.activeElement).toBe(dragButton); - fireEvent.keyDown(dragButton, {key: 'Enter'}); - fireEvent.keyUp(dragButton, {key: 'Enter'}); + await user.keyboard('[Enter]'); act(() => jest.runAllTimers()); expect(cells[0]).not.toHaveClass('is-dragging'); expect(cells[1]).toHaveClass('is-dragging'); @@ -367,8 +363,7 @@ describe('useDraggableCollection', () => { expect(document.activeElement).toBe(droppable); - fireEvent.keyDown(dragButton, {key: 'Enter'}); - fireEvent.keyUp(dragButton, {key: 'Enter'}); + await user.keyboard('[Enter]'); act(() => jest.runAllTimers()); expect(onDrop).toHaveBeenCalledTimes(1); expect(onDrop).toHaveBeenCalledWith({ @@ -424,25 +419,20 @@ describe('useDraggableCollection', () => { await user.tab(); expect(document.activeElement).toBe(cells[0]); - fireEvent.keyDown(cells[0], {key: ' '}); - fireEvent.keyUp(cells[0], {key: ' '}); + await user.keyboard('[Space]'); expect(rows[0]).toHaveAttribute('aria-selected', 'true'); - fireEvent.keyDown(cells[0], {key: 'ArrowDown'}); - fireEvent.keyUp(cells[0], {key: 'ArrowDown'}); + await user.keyboard('[ArrowDown]'); expect(document.activeElement).toBe(cells[1]); - fireEvent.keyDown(cells[1], {key: ' '}); - fireEvent.keyUp(cells[1], {key: ' '}); + await user.keyboard('[Space]'); expect(rows[1]).toHaveAttribute('aria-selected', 'true'); - fireEvent.keyDown(cells[1], {key: 'ArrowRight'}); - fireEvent.keyUp(cells[1], {key: 'ArrowRight'}); + await user.keyboard('[ArrowRight]'); let dragButton = within(cells[1]).getByRole('button'); expect(document.activeElement).toBe(dragButton); - fireEvent.keyDown(dragButton, {key: 'Enter'}); - fireEvent.keyUp(dragButton, {key: 'Enter'}); + await user.keyboard('[Enter]'); act(() => jest.runAllTimers()); expect(cells[0]).toHaveClass('is-dragging'); expect(cells[1]).toHaveClass('is-dragging'); @@ -458,8 +448,7 @@ describe('useDraggableCollection', () => { expect(document.activeElement).toBe(droppable); - fireEvent.keyDown(dragButton, {key: 'Enter'}); - fireEvent.keyUp(dragButton, {key: 'Enter'}); + await user.keyboard('[Enter]'); act(() => jest.runAllTimers()); expect(onDrop).toHaveBeenCalledTimes(1); expect(onDrop).toHaveBeenCalledWith({ @@ -523,21 +512,17 @@ describe('useDraggableCollection', () => { await user.tab(); expect(document.activeElement).toBe(cells[0]); - fireEvent.keyDown(cells[0], {key: 'ArrowDown'}); - fireEvent.keyUp(cells[0], {key: 'ArrowDown'}); + await user.keyboard('[ArrowDown]'); expect(document.activeElement).toBe(cells[1]); - fireEvent.keyDown(cells[1], {key: ' '}); - fireEvent.keyUp(cells[1], {key: ' '}); + await user.keyboard('[Space]'); expect(rows[1]).toHaveAttribute('aria-selected', 'true'); - fireEvent.keyDown(cells[1], {key: 'ArrowRight'}); - fireEvent.keyUp(cells[1], {key: 'ArrowRight'}); + await user.keyboard('[ArrowRight]'); let dragButton = within(cells[1]).getByRole('button'); expect(document.activeElement).toBe(dragButton); - fireEvent.keyDown(dragButton, {key: 'Enter'}); - fireEvent.keyUp(dragButton, {key: 'Enter'}); + await user.keyboard('[Enter]'); act(() => jest.runAllTimers()); expect(cells[0]).not.toHaveClass('is-dragging'); expect(cells[1]).toHaveClass('is-dragging'); @@ -553,8 +538,7 @@ describe('useDraggableCollection', () => { expect(document.activeElement).toBe(droppable); - fireEvent.keyDown(dragButton, {key: 'Enter'}); - fireEvent.keyUp(dragButton, {key: 'Enter'}); + await user.keyboard('[Enter]'); act(() => jest.runAllTimers()); expect(onDrop).toHaveBeenCalledTimes(1); expect(onDrop).toHaveBeenCalledWith({ @@ -613,23 +597,19 @@ describe('useDraggableCollection', () => { await user.tab(); expect(document.activeElement).toBe(options[0]); - fireEvent.keyDown(options[0], {key: ' '}); - fireEvent.keyUp(options[0], {key: ' '}); + await user.keyboard('[Space]'); expect(options[0]).toHaveAttribute('aria-selected', 'true'); expect(document.getElementById(options[0].getAttribute('aria-describedby'))).toHaveTextContent('Press Enter to start dragging'); - fireEvent.keyDown(options[0], {key: 'ArrowDown'}); - fireEvent.keyUp(options[0], {key: 'ArrowDown'}); + await user.keyboard('[ArrowDown]'); expect(document.activeElement).toBe(options[1]); - fireEvent.keyDown(options[1], {key: ' '}); - fireEvent.keyUp(options[1], {key: ' '}); + await user.keyboard('[Space]'); expect(options[1]).toHaveAttribute('aria-selected', 'true'); expect(options[1]).toHaveAttribute('aria-describedby'); expect(document.getElementById(options[1].getAttribute('aria-describedby'))).toHaveTextContent('Press Enter to drag 2 selected items.'); - fireEvent.keyDown(options[1], {key: 'Enter'}); - fireEvent.keyUp(options[1], {key: 'Enter'}); + await user.keyboard('[Enter]'); act(() => jest.runAllTimers()); expect(onDragStart).toHaveBeenCalledTimes(1); @@ -642,8 +622,7 @@ describe('useDraggableCollection', () => { expect(document.activeElement).toBe(droppable); - fireEvent.keyDown(document.activeElement, {key: 'Enter'}); - fireEvent.keyUp(document.activeElement, {key: 'Enter'}); + await user.keyboard('[Enter]'); act(() => jest.runAllTimers()); expect(onDrop).toHaveBeenCalledTimes(1); expect(onDrop).toHaveBeenCalledWith({ @@ -704,28 +683,24 @@ describe('useDraggableCollection', () => { await user.tab(); expect(document.activeElement).toBe(options[0]); - fireEvent.keyDown(options[0], {key: ' '}); - fireEvent.keyUp(options[0], {key: ' '}); + await user.keyboard('[Space]'); expect(options[0]).toHaveAttribute('aria-selected', 'true'); expect(document.getElementById(options[0].getAttribute('aria-describedby'))).toHaveTextContent('Press Alt + Enter to start dragging'); - fireEvent.keyDown(options[0], {key: 'ArrowDown', shiftKey: true}); - fireEvent.keyUp(options[0], {key: 'ArrowDown', shiftKey: true}); + await user.keyboard('{Shift>}{ArrowDown}{/Shift}'); expect(document.activeElement).toBe(options[1]); expect(options[1]).toHaveAttribute('aria-selected', 'true'); expect(options[1]).toHaveAttribute('aria-describedby'); expect(document.getElementById(options[1].getAttribute('aria-describedby'))).toHaveTextContent('Press Alt + Enter to drag 2 selected items.'); - fireEvent.keyDown(options[1], {key: 'Enter'}); - fireEvent.keyUp(options[1], {key: 'Enter'}); + await user.keyboard('[Enter]'); act(() => jest.runAllTimers()); expect(onAction).toHaveBeenCalledTimes(1); expect(onDragStart).toHaveBeenCalledTimes(0); - fireEvent.keyDown(options[1], {key: 'Enter', altKey: true}); - fireEvent.keyUp(options[1], {key: 'Enter', altKey: true}); + await user.keyboard('{Alt>}{Enter}{/Alt}'); act(() => jest.runAllTimers()); expect(onDragStart).toHaveBeenCalledTimes(1); @@ -738,8 +713,7 @@ describe('useDraggableCollection', () => { expect(document.activeElement).toBe(droppable); - fireEvent.keyDown(document.activeElement, {key: 'Enter'}); - fireEvent.keyUp(document.activeElement, {key: 'Enter'}); + await user.keyboard('[Enter]'); act(() => jest.runAllTimers()); expect(onDrop).toHaveBeenCalledTimes(1); expect(onDrop).toHaveBeenCalledWith({ @@ -784,9 +758,8 @@ describe('useDraggableCollection', () => { fireEvent.focus(document.body); }); - afterEach(() => { - fireEvent.keyDown(document.body, {key: 'Escape'}); - fireEvent.keyUp(document.body, {key: 'Escape'}); + afterEach(async () => { + await user.keyboard('[Escape]'); }); it('should drag a single item', async () => { diff --git a/packages/@react-aria/dnd/test/useDroppableCollection.test.js b/packages/@react-aria/dnd/test/useDroppableCollection.test.js index 81d184294b9..53f5d446b6f 100644 --- a/packages/@react-aria/dnd/test/useDroppableCollection.test.js +++ b/packages/@react-aria/dnd/test/useDroppableCollection.test.js @@ -319,14 +319,12 @@ describe('useDroppableCollection', () => { }); describe('keyboard', () => { - let pressKey = (key) => { - fireEvent.keyDown(document.activeElement, {key}); - fireEvent.keyUp(document.activeElement, {key}); + let pressKey = async (key) => { + await user.keyboard(`[${key}]`); }; - afterEach(() => { - fireEvent.keyDown(document.body, {key: 'Escape'}); - fireEvent.keyUp(document.body, {key: 'Escape'}); + afterEach(async () => { + await user.keyboard('[Escape]'); }); it('should perform basic drag and drop', async () => { @@ -344,7 +342,7 @@ describe('useDroppableCollection', () => { await user.tab(); expect(document.activeElement).toBe(draggable); - pressKey('Enter'); + await pressKey('Enter'); act(() => jest.runAllTimers()); cells = within(grid).getAllByRole('gridcell'); @@ -352,16 +350,16 @@ describe('useDroppableCollection', () => { expect(document.activeElement).toBe(within(cells[0]).getByRole('button')); - pressKey('ArrowDown'); + await pressKey('ArrowDown'); expect(document.activeElement).toBe(within(cells[1]).getByRole('button')); - pressKey('ArrowDown'); + await pressKey('ArrowDown'); expect(document.activeElement).toBe(within(cells[2]).getByRole('button')); - pressKey('ArrowDown'); + await pressKey('ArrowDown'); expect(document.activeElement).toBe(within(cells[3]).getByRole('button')); - pressKey('Enter'); + await pressKey('Enter'); expect(onDrop).toHaveBeenCalledTimes(1); expect(onDrop).toHaveBeenCalledWith({ type: 'drop', @@ -405,7 +403,7 @@ describe('useDroppableCollection', () => { await user.tab(); expect(document.activeElement).toBe(draggable); - pressKey('Enter'); + await pressKey('Enter'); act(() => jest.runAllTimers()); cells = within(grid).getAllByRole('gridcell'); @@ -423,7 +421,7 @@ describe('useDroppableCollection', () => { for (let i = 0; i < cells.length; i++) { if (i > 0) { - pressKey('ArrowDown'); + await pressKey('ArrowDown'); } expect(document.activeElement).toBe(within(cells[i]).getByRole('button')); @@ -446,7 +444,7 @@ describe('useDroppableCollection', () => { }); } - pressKey('ArrowDown'); + await pressKey('ArrowDown'); expect(document.activeElement).toBe(within(cells[0]).getByRole('button')); expect(onDragExit).toHaveBeenCalledTimes(7); expect(onDragExit).toHaveBeenLastCalledWith({ @@ -465,7 +463,7 @@ describe('useDroppableCollection', () => { }); for (let i = cells.length - 1; i >= 0; i--) { - pressKey('ArrowUp'); + await pressKey('ArrowUp'); expect(document.activeElement).toBe(within(cells[i]).getByRole('button')); expect(onDragExit).toHaveBeenCalledTimes(7 + cells.length - i); @@ -485,7 +483,7 @@ describe('useDroppableCollection', () => { }); } - pressKey('ArrowUp'); + await pressKey('ArrowUp'); expect(document.activeElement).toBe(within(cells[cells.length - 1]).getByRole('button')); expect(onDragExit).toHaveBeenCalledTimes(cells.length * 2 + 1); expect(onDragExit).toHaveBeenLastCalledWith({ @@ -521,7 +519,7 @@ describe('useDroppableCollection', () => { await user.tab(); expect(document.activeElement).toBe(draggable); - pressKey('Enter'); + await pressKey('Enter'); act(() => jest.runAllTimers()); cells = within(grid).getAllByRole('gridcell'); @@ -535,7 +533,7 @@ describe('useDroppableCollection', () => { target: {type: 'root'} }); - pressKey('End'); + await pressKey('End'); expect(onDragExit).toHaveBeenCalledTimes(1); expect(onDragExit).toHaveBeenLastCalledWith({ type: 'dropexit', @@ -552,7 +550,7 @@ describe('useDroppableCollection', () => { target: {type: 'item', key: '3', dropPosition: 'after'} }); - pressKey('Home'); + await pressKey('Home'); expect(onDragExit).toHaveBeenCalledTimes(2); expect(onDragExit).toHaveBeenLastCalledWith({ type: 'dropexit', @@ -591,7 +589,7 @@ describe('useDroppableCollection', () => { await user.tab(); expect(document.activeElement).toBe(draggable); - pressKey('Enter'); + await pressKey('Enter'); act(() => jest.runAllTimers()); cells = within(grid).getAllByRole('gridcell'); @@ -606,7 +604,7 @@ describe('useDroppableCollection', () => { for (let i = 0; i < pageDownTargets.length; i++) { if (i > 0) { - pressKey('PageDown'); + await pressKey('PageDown'); expect(onDragExit).toHaveBeenCalledTimes(i); expect(onDragExit).toHaveBeenLastCalledWith({ @@ -634,7 +632,7 @@ describe('useDroppableCollection', () => { ]; for (let i = 0; i < pageUpTargets.length; i++) { - pressKey('PageUp'); + await pressKey('PageUp'); expect(onDragExit).toHaveBeenCalledTimes(pageDownTargets.length + i); expect(onDragExit).toHaveBeenLastCalledWith({ type: 'dropexit', @@ -675,7 +673,7 @@ describe('useDroppableCollection', () => { await user.tab(); expect(document.activeElement).toBe(draggable); - pressKey('Enter'); + await pressKey('Enter'); act(() => jest.runAllTimers()); cells = within(grid).getAllByRole('gridcell'); @@ -690,7 +688,7 @@ describe('useDroppableCollection', () => { for (let i = 0; i < pageDownTargets.length; i++) { if (i > 0) { - pressKey('PageDown'); + await pressKey('PageDown'); expect(onDragExit).toHaveBeenCalledTimes(i); expect(onDragExit).toHaveBeenLastCalledWith({ @@ -717,7 +715,7 @@ describe('useDroppableCollection', () => { ]; for (let i = 0; i < pageUpTargets.length; i++) { - pressKey('PageUp'); + await pressKey('PageUp'); expect(onDragExit).toHaveBeenCalledTimes(pageDownTargets.length + i); expect(onDragExit).toHaveBeenLastCalledWith({ type: 'dropexit', @@ -758,7 +756,7 @@ describe('useDroppableCollection', () => { await user.tab(); expect(document.activeElement).toBe(draggable); - pressKey('Enter'); + await pressKey('Enter'); act(() => jest.runAllTimers()); cells = within(grid).getAllByRole('gridcell'); @@ -773,7 +771,7 @@ describe('useDroppableCollection', () => { for (let i = 0; i < pageDownTargets.length; i++) { if (i > 0) { - pressKey('PageDown'); + await pressKey('PageDown'); expect(onDragExit).toHaveBeenCalledTimes(i); expect(onDragExit).toHaveBeenLastCalledWith({ @@ -800,7 +798,7 @@ describe('useDroppableCollection', () => { ]; for (let i = 0; i < pageUpTargets.length; i++) { - pressKey('PageUp'); + await pressKey('PageUp'); expect(onDragExit).toHaveBeenCalledTimes(pageDownTargets.length + i); expect(onDragExit).toHaveBeenLastCalledWith({ type: 'dropexit', @@ -835,13 +833,13 @@ describe('useDroppableCollection', () => { await user.tab(); expect(document.activeElement).toBe(cells[0]); - pressKey('ArrowDown'); + await pressKey('ArrowDown'); expect(document.activeElement).toBe(cells[1]); await user.tab({shift: true}); expect(document.activeElement).toBe(draggable); - pressKey('Enter'); + await pressKey('Enter'); act(() => jest.runAllTimers()); expect(document.activeElement).toHaveAttribute('aria-label', 'Insert between Two and Three'); @@ -862,25 +860,25 @@ describe('useDroppableCollection', () => { await user.tab(); await user.tab(); - pressKey(' '); + await pressKey('Space'); expect(document.activeElement).toBe(cells[0]); expect(rows[0]).toHaveAttribute('aria-selected', 'true'); - pressKey('ArrowDown'); - pressKey('ArrowDown'); - pressKey(' '); + await pressKey('ArrowDown'); + await pressKey('ArrowDown'); + await pressKey('Space'); expect(document.activeElement).toBe(cells[2]); expect(rows[2]).toHaveAttribute('aria-selected', 'true'); - pressKey('ArrowUp'); - pressKey(' '); + await pressKey('ArrowUp'); + await pressKey('Space'); expect(document.activeElement).toBe(cells[1]); expect(rows[1]).toHaveAttribute('aria-selected', 'true'); await user.tab({shift: true}); expect(document.activeElement).toBe(draggable); - pressKey('Enter'); + await pressKey('Enter'); act(() => jest.runAllTimers()); expect(document.activeElement).toHaveAttribute('aria-label', 'Insert after Three'); @@ -903,22 +901,22 @@ describe('useDroppableCollection', () => { await user.tab(); expect(document.activeElement).toBe(cells[0]); - pressKey('ArrowDown'); - pressKey('ArrowDown'); - pressKey('ArrowDown'); - pressKey(' '); + await pressKey('ArrowDown'); + await pressKey('ArrowDown'); + await pressKey('ArrowDown'); + await pressKey('Space'); expect(document.activeElement).toBe(cells[2]); expect(rows[2]).toHaveAttribute('aria-selected', 'true'); - pressKey('ArrowUp'); - pressKey(' '); + await pressKey('ArrowUp'); + await pressKey('Space'); expect(document.activeElement).toBe(cells[1]); expect(rows[1]).toHaveAttribute('aria-selected', 'true'); await user.tab({shift: true}); expect(document.activeElement).toBe(draggable); - pressKey('Enter'); + await pressKey('Enter'); act(() => jest.runAllTimers()); expect(document.activeElement).toHaveAttribute('aria-label', 'Insert between One and Two'); @@ -942,22 +940,22 @@ describe('useDroppableCollection', () => { await user.tab(); expect(document.activeElement).toBe(cells[0]); - pressKey('ArrowDown'); - pressKey('ArrowDown'); - pressKey('ArrowDown'); - pressKey(' '); + await pressKey('ArrowDown'); + await pressKey('ArrowDown'); + await pressKey('ArrowDown'); + await pressKey('Space'); expect(document.activeElement).toBe(cells[2]); expect(rows[2]).toHaveAttribute('aria-selected', 'true'); - pressKey('ArrowUp'); - pressKey(' '); + await pressKey('ArrowUp'); + await pressKey('Space'); expect(document.activeElement).toBe(cells[1]); expect(rows[1]).toHaveAttribute('aria-selected', 'true'); await user.tab({shift: true}); expect(document.activeElement).toBe(draggable); - pressKey('Enter'); + await pressKey('Enter'); act(() => jest.runAllTimers()); expect(document.activeElement).toHaveAttribute('aria-label', 'Drop on Two'); @@ -979,25 +977,25 @@ describe('useDroppableCollection', () => { await user.tab(); await user.tab(); - pressKey(' '); + await pressKey('Space'); expect(document.activeElement).toBe(cells[0]); expect(rows[0]).toHaveAttribute('aria-selected', 'true'); - pressKey('ArrowDown'); - pressKey('ArrowDown'); - pressKey(' '); + await pressKey('ArrowDown'); + await pressKey('ArrowDown'); + await pressKey('Space'); expect(document.activeElement).toBe(cells[2]); expect(rows[2]).toHaveAttribute('aria-selected', 'true'); - pressKey('ArrowUp'); - pressKey(' '); + await pressKey('ArrowUp'); + await pressKey('Space'); expect(document.activeElement).toBe(cells[1]); expect(rows[1]).toHaveAttribute('aria-selected', 'true'); await user.tab({shift: true}); expect(document.activeElement).toBe(draggable); - pressKey('Enter'); + await pressKey('Enter'); act(() => jest.runAllTimers()); expect(document.activeElement).toHaveAttribute('aria-label', 'Drop on Three'); @@ -1010,9 +1008,8 @@ describe('useDroppableCollection', () => { fireEvent.focus(document.body); }); - afterEach(() => { - fireEvent.keyDown(document.body, {key: 'Escape'}); - fireEvent.keyUp(document.body, {key: 'Escape'}); + afterEach(async () => { + await user.keyboard('[Escape]'); }); it('should perform basic drag and drop', async () => { diff --git a/packages/@react-aria/focus/test/FocusScope.test.js b/packages/@react-aria/focus/test/FocusScope.test.js index 0e80c9c12f6..432a009fe3f 100644 --- a/packages/@react-aria/focus/test/FocusScope.test.js +++ b/packages/@react-aria/focus/test/FocusScope.test.js @@ -622,20 +622,20 @@ describe('FocusScope', function () { ${false} | ${true} ${true} | ${true} `('contain=$contain, isPortaled=$isPortaled should restore focus to previous nodeToRestore when the nodeToRestore for the unmounting scope in no longer in the DOM', - function ({contain, isPortaled}) { + async function ({contain, isPortaled}) { expect(focusScopeTree.size).toBe(1); let {getAllByText, getAllByRole} = render(); expect(focusScopeTree.size).toBe(1); act(() => {getAllByText('Open dialog')[0].focus();}); - fireEvent.click(document.activeElement); + await user.click(document.activeElement); act(() => {jest.runAllTimers();}); expect(document.activeElement).toBe(getAllByRole('textbox')[2]); act(() => {getAllByText('Open dialog')[1].focus();}); - fireEvent.click(document.activeElement); + await user.click(document.activeElement); act(() => {jest.runAllTimers();}); expect(document.activeElement).toBe(getAllByRole('textbox')[5]); act(() => {getAllByText('Open dialog')[2].focus();}); - fireEvent.click(document.activeElement); + await user.click(document.activeElement); act(() => {jest.runAllTimers();}); expect(document.activeElement).toBe(getAllByRole('textbox')[8]); expect(focusScopeTree.size).toBe(4); @@ -643,14 +643,14 @@ describe('FocusScope', function () { act(() => { getAllByText('close')[1].focus(); }); - fireEvent.click(document.activeElement); + await user.click(document.activeElement); } else { fireEvent.click(getAllByText('close')[1]); } act(() => {jest.runAllTimers();}); expect(document.activeElement).toBe(getAllByText('Open dialog')[1]); act(() => {getAllByText('close')[0].focus();}); - fireEvent.click(document.activeElement); + await user.click(document.activeElement); act(() => {jest.runAllTimers();}); expect(document.activeElement).toBe(getAllByText('Open dialog')[0]); expect(focusScopeTree.size).toBe(1); @@ -688,13 +688,13 @@ describe('FocusScope', function () { let item1 = getByTestId('item1'); let item2 = getByTestId('item2'); expect(document.activeElement).toBe(tabbable1); - fireEvent.click(tabbable1); + await user.click(tabbable1); expect(tabbable1).not.toBeInTheDocument(); await waitFor(() => expect(document.activeElement).toBe(item1)); - fireEvent.click(item1); + await user.click(item1); expect(item1).not.toBeInTheDocument(); await waitFor(() => expect(document.activeElement).toBe(item2)); - fireEvent.click(item2); + await user.click(item2); expect(item2).not.toBeInTheDocument(); await waitFor(() => expect(document.activeElement).toBe(focusable)); }); @@ -798,7 +798,7 @@ describe('FocusScope', function () { }); describe('focus manager', function () { - it('should move focus forward', function () { + it('should move focus forward', async function () { function Test() { return ( @@ -825,17 +825,17 @@ describe('FocusScope', function () { act(() => {item1.focus();}); - fireEvent.click(item1); + await user.click(item1); expect(document.activeElement).toBe(item2); - fireEvent.click(item2); + await user.click(item2); expect(document.activeElement).toBe(item3); - fireEvent.click(item3); + await user.click(item3); expect(document.activeElement).toBe(item3); }); - it('should move focus forward and wrap around', function () { + it('should move focus forward and wrap around', async function () { function Test() { return ( @@ -862,17 +862,17 @@ describe('FocusScope', function () { act(() => {item1.focus();}); - fireEvent.click(item1); + await user.click(item1); expect(document.activeElement).toBe(item2); - fireEvent.click(item2); + await user.click(item2); expect(document.activeElement).toBe(item3); - fireEvent.click(item3); + await user.click(item3); expect(document.activeElement).toBe(item1); }); - it('should move focus forward but only to tabbable elements', function () { + it('should move focus forward but only to tabbable elements', async function () { function Test() { return ( @@ -901,7 +901,7 @@ describe('FocusScope', function () { act(() => {item1.focus();}); - fireEvent.click(item1); + await user.click(item1); expect(document.activeElement).toBe(item3); }); @@ -949,7 +949,7 @@ describe('FocusScope', function () { expect(document.activeElement).toBe(item2); }); - it('should move focus forward and allow users to skip certain elements', function () { + it('should move focus forward and allow users to skip certain elements', async function () { function Test() { return ( @@ -978,14 +978,14 @@ describe('FocusScope', function () { act(() => {item1.focus();}); - fireEvent.click(item1); + await user.click(item1); expect(document.activeElement).toBe(item3); - fireEvent.click(item3); + await user.click(item3); expect(document.activeElement).toBe(item1); }); - it('should move focus backward', function () { + it('should move focus backward', async function () { function Test() { return ( @@ -1012,17 +1012,17 @@ describe('FocusScope', function () { act(() => {item3.focus();}); - fireEvent.click(item3); + await user.click(item3); expect(document.activeElement).toBe(item2); - fireEvent.click(item2); + await user.click(item2); expect(document.activeElement).toBe(item1); - fireEvent.click(item1); + await user.click(item1); expect(document.activeElement).toBe(item1); }); - it('should move focus backward and wrap around', function () { + it('should move focus backward and wrap around', async function () { function Test() { return ( @@ -1049,17 +1049,17 @@ describe('FocusScope', function () { act(() => {item3.focus();}); - fireEvent.click(item3); + await user.click(item3); expect(document.activeElement).toBe(item2); - fireEvent.click(item2); + await user.click(item2); expect(document.activeElement).toBe(item1); - fireEvent.click(item1); + await user.click(item1); expect(document.activeElement).toBe(item3); }); - it('should move focus backward but only to tabbable elements', function () { + it('should move focus backward but only to tabbable elements', async function () { function Test() { return ( @@ -1088,7 +1088,7 @@ describe('FocusScope', function () { act(() => {item3.focus();}); - fireEvent.click(item3); + await user.click(item3); expect(document.activeElement).toBe(item1); }); @@ -1138,7 +1138,7 @@ describe('FocusScope', function () { expect(document.activeElement).toBe(item1); }); - it('should move focus backward and allow users to skip certain elements', function () { + it('should move focus backward and allow users to skip certain elements', async function () { function Test() { return ( @@ -1167,10 +1167,10 @@ describe('FocusScope', function () { act(() => {item1.focus();}); - fireEvent.click(item1); + await user.click(item1); expect(document.activeElement).toBe(item3); - fireEvent.click(item3); + await user.click(item3); expect(document.activeElement).toBe(item1); }); }); @@ -1581,16 +1581,14 @@ describe('FocusScope', function () { await user.tab(); expect(document.activeElement.textContent).toBe('Open Menu'); - fireEvent.keyDown(document.activeElement, {key: 'Enter'}); - fireEvent.keyUp(document.activeElement, {key: 'Enter'}); +await user.keyboard('[Enter]'); act(() => { jest.runAllTimers(); }); expect(document.activeElement.textContent).toBe('Open Dialog'); - fireEvent.keyDown(document.activeElement, {key: 'Enter'}); - fireEvent.keyUp(document.activeElement, {key: 'Enter'}); +await user.keyboard('[Enter]'); // Needed for onBlur raf in useFocusContainment act(() => { @@ -1603,8 +1601,7 @@ describe('FocusScope', function () { expect(document.activeElement.textContent).toBe('Close'); - fireEvent.keyDown(document.activeElement, {key: 'Enter'}); - fireEvent.keyUp(document.activeElement, {key: 'Enter'}); +await user.keyboard('[Enter]'); act(() => { jest.runAllTimers(); }); diff --git a/packages/@react-aria/grid/test/useGrid.test.js b/packages/@react-aria/grid/test/useGrid.test.js index e1ecb793f26..2ba8c5e61e7 100644 --- a/packages/@react-aria/grid/test/useGrid.test.js +++ b/packages/@react-aria/grid/test/useGrid.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render} from '@react-spectrum/test-utils'; +import {act, pointerMap, render} from '@react-spectrum/test-utils'; import {Grid} from '../stories/example'; import {Item} from '@react-stately/collections'; import React from 'react'; @@ -54,30 +54,30 @@ describe('useGrid', () => { await user.tab(); expect(document.activeElement).toBe(tree.getAllByRole('row')[0]); - fireEvent.keyDown(document.activeElement, {key: 'ArrowRight'}); + await user.keyboard('[ArrowRight]'); expect(document.activeElement).toBe(tree.getAllByRole('gridcell')[0]); - fireEvent.keyDown(document.activeElement, {key: 'ArrowRight'}); + await user.keyboard('[ArrowRight]'); expect(document.activeElement).toBe(tree.getAllByRole('switch')[0]); - fireEvent.keyDown(document.activeElement, {key: 'ArrowRight'}); + await user.keyboard('[ArrowRight]'); expect(document.activeElement).toBe(tree.getAllByRole('switch')[1]); - fireEvent.keyDown(document.activeElement, {key: 'ArrowRight'}); + await user.keyboard('[ArrowRight]'); expect(document.activeElement).toBe(tree.getAllByRole('row')[0]); - fireEvent.keyDown(document.activeElement, {key: 'ArrowLeft'}); + await user.keyboard('[ArrowLeft]'); expect(document.activeElement).toBe(tree.getAllByRole('gridcell')[0]); act(() => tree.getAllByRole('switch')[1].focus()); - fireEvent.keyDown(document.activeElement, {key: 'ArrowLeft'}); + await user.keyboard('[ArrowLeft]'); expect(document.activeElement).toBe(tree.getAllByRole('switch')[0]); - fireEvent.keyDown(document.activeElement, {key: 'ArrowLeft'}); + await user.keyboard('[ArrowLeft]'); expect(document.activeElement).toBe(tree.getAllByRole('gridcell')[0]); - fireEvent.keyDown(document.activeElement, {key: 'ArrowLeft'}); + await user.keyboard('[ArrowLeft]'); expect(document.activeElement).toBe(tree.getAllByRole('row')[0]); }); @@ -87,25 +87,25 @@ describe('useGrid', () => { await user.tab(); expect(document.activeElement).toBe(tree.getAllByRole('row')[0]); - fireEvent.keyDown(document.activeElement, {key: 'ArrowRight'}); + await user.keyboard('[ArrowRight]'); expect(document.activeElement).toBe(tree.getAllByRole('switch')[0]); - fireEvent.keyDown(document.activeElement, {key: 'ArrowRight'}); + await user.keyboard('[ArrowRight]'); expect(document.activeElement).toBe(tree.getAllByRole('switch')[1]); - fireEvent.keyDown(document.activeElement, {key: 'ArrowRight'}); + await user.keyboard('[ArrowRight]'); expect(document.activeElement).toBe(tree.getAllByRole('row')[0]); - fireEvent.keyDown(document.activeElement, {key: 'ArrowLeft'}); + await user.keyboard('[ArrowLeft]'); expect(document.activeElement).toBe(tree.getAllByRole('switch')[1]); - fireEvent.keyDown(document.activeElement, {key: 'ArrowLeft'}); + await user.keyboard('[ArrowLeft]'); expect(document.activeElement).toBe(tree.getAllByRole('switch')[0]); - fireEvent.keyDown(document.activeElement, {key: 'ArrowLeft'}); + await user.keyboard('[ArrowLeft]'); expect(document.activeElement).toBe(tree.getAllByRole('row')[0]); - fireEvent.keyDown(document.activeElement, {key: 'ArrowLeft'}); + await user.keyboard('[ArrowLeft]'); expect(document.activeElement).toBe(tree.getAllByRole('switch')[1]); }); @@ -115,19 +115,19 @@ describe('useGrid', () => { await user.tab(); expect(document.activeElement).toBe(tree.getAllByRole('switch')[0]); - fireEvent.keyDown(document.activeElement, {key: 'ArrowRight'}); + await user.keyboard('[ArrowRight]'); expect(document.activeElement).toBe(tree.getAllByRole('switch')[1]); - fireEvent.keyDown(document.activeElement, {key: 'ArrowRight'}); + await user.keyboard('[ArrowRight]'); expect(document.activeElement).toBe(tree.getAllByRole('switch')[0]); - fireEvent.keyDown(document.activeElement, {key: 'ArrowLeft'}); + await user.keyboard('[ArrowLeft]'); expect(document.activeElement).toBe(tree.getAllByRole('switch')[1]); - fireEvent.keyDown(document.activeElement, {key: 'ArrowLeft'}); + await user.keyboard('[ArrowLeft]'); expect(document.activeElement).toBe(tree.getAllByRole('switch')[0]); - fireEvent.keyDown(document.activeElement, {key: 'ArrowLeft'}); + await user.keyboard('[ArrowLeft]'); expect(document.activeElement).toBe(tree.getAllByRole('switch')[1]); }); @@ -137,22 +137,22 @@ describe('useGrid', () => { await user.tab(); expect(document.activeElement).toBe(tree.getAllByRole('gridcell')[0]); - fireEvent.keyDown(document.activeElement, {key: 'ArrowRight'}); + await user.keyboard('[ArrowRight]'); expect(document.activeElement).toBe(tree.getAllByRole('switch')[0]); - fireEvent.keyDown(document.activeElement, {key: 'ArrowRight'}); + await user.keyboard('[ArrowRight]'); expect(document.activeElement).toBe(tree.getAllByRole('switch')[1]); - fireEvent.keyDown(document.activeElement, {key: 'ArrowRight'}); + await user.keyboard('[ArrowRight]'); expect(document.activeElement).toBe(tree.getAllByRole('gridcell')[0]); - fireEvent.keyDown(document.activeElement, {key: 'ArrowLeft'}); + await user.keyboard('[ArrowLeft]'); expect(document.activeElement).toBe(tree.getAllByRole('switch')[1]); - fireEvent.keyDown(document.activeElement, {key: 'ArrowLeft'}); + await user.keyboard('[ArrowLeft]'); expect(document.activeElement).toBe(tree.getAllByRole('switch')[0]); - fireEvent.keyDown(document.activeElement, {key: 'ArrowLeft'}); + await user.keyboard('[ArrowLeft]'); expect(document.activeElement).toBe(tree.getAllByRole('gridcell')[0]); }); }); diff --git a/packages/@react-aria/interactions/test/PressResponder.test.js b/packages/@react-aria/interactions/test/PressResponder.test.js index 87a0bf1e4bf..72baa31250d 100644 --- a/packages/@react-aria/interactions/test/PressResponder.test.js +++ b/packages/@react-aria/interactions/test/PressResponder.test.js @@ -10,12 +10,14 @@ * governing permissions and limitations under the License. */ -import {fireEvent, render} from '@react-spectrum/test-utils'; +import {pointerMap, render} from '@react-spectrum/test-utils'; import {Pressable, PressResponder} from '../'; import React from 'react'; +import userEvent from '@testing-library/user-event'; describe('PressResponder', function () { - it('should handle press events on nested pressable children', function () { + it('should handle press events on nested pressable children', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let onPress = jest.fn(); let {getByRole} = render( @@ -26,9 +28,7 @@ describe('PressResponder', function () { ); let button = getByRole('button'); - fireEvent.mouseDown(button); - fireEvent.mouseUp(button); - fireEvent.click(button); + await user.click(button); expect(onPress).toHaveBeenCalledTimes(1); }); @@ -75,7 +75,8 @@ describe('PressResponder', function () { warn.mockRestore(); }); - it('should merge with existing props, not overwrite', function () { + it('should merge with existing props, not overwrite', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let onPress = jest.fn(); let onClick = jest.fn(); let {getByRole} = render( @@ -89,9 +90,7 @@ describe('PressResponder', function () { ); let button = getByRole('button'); - fireEvent.mouseDown(button); - fireEvent.mouseUp(button); - fireEvent.click(button); + await user.click(button); expect(onPress).toHaveBeenCalledTimes(1); expect(onClick).toHaveBeenCalledTimes(1); diff --git a/packages/@react-aria/interactions/test/Pressable.test.js b/packages/@react-aria/interactions/test/Pressable.test.js index 8f58dc898a5..8a9484512f7 100644 --- a/packages/@react-aria/interactions/test/Pressable.test.js +++ b/packages/@react-aria/interactions/test/Pressable.test.js @@ -10,13 +10,14 @@ * governing permissions and limitations under the License. */ -import {fireEvent, render} from '@react-spectrum/test-utils'; +import {pointerMap, render} from '@react-spectrum/test-utils'; import {Pressable} from '../'; import React from 'react'; +import userEvent from '@testing-library/user-event'; describe('Pressable', function () { - - it('should apply press events to child element', function () { + it('should apply press events to child element', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let onPress = jest.fn(); let {getByRole} = render( @@ -25,14 +26,13 @@ describe('Pressable', function () { ); let button = getByRole('button'); - fireEvent.mouseDown(button); - fireEvent.mouseUp(button); - fireEvent.click(button); + await user.click(button); expect(onPress).toHaveBeenCalledTimes(1); }); - it('should should merge with existing props, not overwrite', function () { + it('should should merge with existing props, not overwrite', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let onPress = jest.fn(); let onClick = jest.fn(); let {getByRole} = render( @@ -42,9 +42,7 @@ describe('Pressable', function () { ); let button = getByRole('button'); - fireEvent.mouseDown(button); - fireEvent.mouseUp(button); - fireEvent.click(button); + await user.click(button); expect(onPress).toHaveBeenCalledTimes(1); expect(onClick).toHaveBeenCalledTimes(1); diff --git a/packages/@react-aria/interactions/test/useKeyboard.test.js b/packages/@react-aria/interactions/test/useKeyboard.test.js index a5bf0cad552..b06c98686dd 100644 --- a/packages/@react-aria/interactions/test/useKeyboard.test.js +++ b/packages/@react-aria/interactions/test/useKeyboard.test.js @@ -10,9 +10,10 @@ * governing permissions and limitations under the License. */ -import {fireEvent, render} from '@react-spectrum/test-utils'; +import {act, pointerMap, render} from '@react-spectrum/test-utils'; import React from 'react'; import {useKeyboard} from '../'; +import userEvent from '@testing-library/user-event'; function Example(props) { let {keyboardProps} = useKeyboard(props); @@ -20,7 +21,8 @@ function Example(props) { } describe('useKeyboard', function () { - it('should handle keyboard events', function () { + it('should handle keyboard events', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let events = []; let addEvent = (e) => events.push({type: e.type, target: e.target}); let tree = render( @@ -30,8 +32,8 @@ describe('useKeyboard', function () { ); let el = tree.getByTestId('example'); - fireEvent.keyDown(el, {key: 'A'}); - fireEvent.keyUp(el, {key: 'A'}); + act(() => el.focus()); + await user.keyboard('A'); expect(events).toEqual([ {type: 'keydown', target: el}, @@ -39,7 +41,8 @@ describe('useKeyboard', function () { ]); }); - it('should not handle events when disabled', function () { + it('should not handle events when disabled', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let events = []; let addEvent = (e) => events.push({type: e.type, target: e.target}); let tree = render( @@ -50,13 +53,14 @@ describe('useKeyboard', function () { ); let el = tree.getByTestId('example'); - fireEvent.keyDown(el, {key: 'A'}); - fireEvent.keyUp(el, {key: 'A'}); + act(() => el.focus()); + await user.keyboard('A'); expect(events).toEqual([]); }); - it('events do not bubble by default', function () { + it('events do not bubble by default', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let onWrapperKeyDown = jest.fn(); let onWrapperKeyUp = jest.fn(); let onInnerKeyDown = jest.fn(); @@ -70,8 +74,8 @@ describe('useKeyboard', function () { ); let el = tree.getByTestId('example'); - fireEvent.keyDown(el, {key: 'A'}); - fireEvent.keyUp(el, {key: 'A'}); + act(() => el.focus()); + await user.keyboard('A'); expect(onInnerKeyDown).toHaveBeenCalledTimes(1); expect(onInnerKeyUp).toHaveBeenCalledTimes(1); @@ -79,7 +83,8 @@ describe('useKeyboard', function () { expect(onWrapperKeyUp).not.toHaveBeenCalled(); }); - it('events bubble when continuePropagation is called', function () { + it('events bubble when continuePropagation is called', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let onWrapperKeyDown = jest.fn(); let onWrapperKeyUp = jest.fn(); let onInnerKeyDown = jest.fn(e => e.continuePropagation()); @@ -93,8 +98,8 @@ describe('useKeyboard', function () { ); let el = tree.getByTestId('example'); - fireEvent.keyDown(el, {key: 'A'}); - fireEvent.keyUp(el, {key: 'A'}); + act(() => el.focus()); + await user.keyboard('A'); expect(onInnerKeyDown).toHaveBeenCalledTimes(1); expect(onInnerKeyUp).toHaveBeenCalledTimes(1); diff --git a/packages/@react-aria/landmark/test/useLandmark.test.tsx b/packages/@react-aria/landmark/test/useLandmark.test.tsx index 4fa43a9cbe7..95af202be6c 100644 --- a/packages/@react-aria/landmark/test/useLandmark.test.tsx +++ b/packages/@react-aria/landmark/test/useLandmark.test.tsx @@ -115,7 +115,7 @@ describe('LandmarkManager', function () { expect(document.activeElement!).toBe(tree.getAllByRole('link')[0]); }); - it('can F6 to a landmark region', function () { + it('can F6 to a landmark region', async function () { let tree = render(
@@ -133,16 +133,14 @@ describe('LandmarkManager', function () { let navigation = tree.getByRole('navigation'); let main = tree.getByRole('main'); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(navigation); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(main); }); - it('can F6 to a landmark region when there is only one landmark', function () { + it('can F6 to a landmark region when there is only one landmark', async function () { let tree = render(
@@ -152,12 +150,11 @@ describe('LandmarkManager', function () { ); let main = tree.getByRole('main'); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(main); }); - it('can F6 to a nested landmark region that is first', function () { + it('can F6 to a nested landmark region that is first', async function () { let tree = render(
@@ -172,32 +169,26 @@ describe('LandmarkManager', function () { let main = tree.getByRole('main'); let region = tree.getByRole('region'); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(main); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(region); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(main); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(region); - fireEvent.keyDown(document.activeElement!, {key: 'F6', shiftKey: true}); - fireEvent.keyUp(document.activeElement!, {key: 'F6', shiftKey: true}); + await user.keyboard('{Shift>}{F6}{/Shift}}'); expect(document.activeElement!).toBe(main); - fireEvent.keyDown(document.activeElement!, {key: 'F6', shiftKey: true}); - fireEvent.keyUp(document.activeElement!, {key: 'F6', shiftKey: true}); + await user.keyboard('{Shift>}{F6}{/Shift}}'); expect(document.activeElement!).toBe(region); }); - it('can F6 to a nested landmark region that is last', function () { + it('can F6 to a nested landmark region that is last', async function () { let tree = render(
@@ -212,32 +203,26 @@ describe('LandmarkManager', function () { let main = tree.getByRole('main'); let region = tree.getByRole('region'); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(main); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(region); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(main); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(region); - fireEvent.keyDown(document.activeElement!, {key: 'F6', shiftKey: true}); - fireEvent.keyUp(document.activeElement!, {key: 'F6', shiftKey: true}); + await user.keyboard('{Shift>}{F6}{/Shift}}'); expect(document.activeElement!).toBe(main); - fireEvent.keyDown(document.activeElement!, {key: 'F6', shiftKey: true}); - fireEvent.keyUp(document.activeElement!, {key: 'F6', shiftKey: true}); + await user.keyboard('{Shift>}{F6}{/Shift}}'); expect(document.activeElement!).toBe(region); }); - it('goes in dom order with two nested landmarks', function () { + it('goes in dom order with two nested landmarks', async function () { let tree = render(
@@ -259,32 +244,25 @@ describe('LandmarkManager', function () { let region1 = tree.getAllByRole('region')[0]; let region2 = tree.getAllByRole('region')[1]; - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(main); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(region1); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(region2); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(main); - fireEvent.keyDown(document.activeElement!, {key: 'F6', shiftKey: true}); - fireEvent.keyUp(document.activeElement!, {key: 'F6', shiftKey: true}); + await user.keyboard('{Shift>}{F6}{/Shift}}'); expect(document.activeElement!).toBe(region2); - fireEvent.keyDown(document.activeElement!, {key: 'F6', shiftKey: true}); - fireEvent.keyUp(document.activeElement!, {key: 'F6', shiftKey: true}); + await user.keyboard('{Shift>}{F6}{/Shift}}'); expect(document.activeElement!).toBe(region1); - fireEvent.keyDown(document.activeElement!, {key: 'F6', shiftKey: true}); - fireEvent.keyUp(document.activeElement!, {key: 'F6', shiftKey: true}); + await user.keyboard('{Shift>}{F6}{/Shift}}'); expect(document.activeElement!).toBe(main); }); @@ -308,8 +286,7 @@ describe('LandmarkManager', function () { await user.tab(); expect(document.activeElement!).toBe(tree.getAllByRole('link')[0]); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(main); }); @@ -334,12 +311,10 @@ describe('LandmarkManager', function () { await user.tab(); expect(document.activeElement!).toBe(tree.getAllByRole('link')[0]); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(main); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(tree.getAllByRole('link')[0]); }); @@ -366,7 +341,7 @@ describe('LandmarkManager', function () { expect(document.activeElement!).toBe(tree.getAllByRole('link')[2]); }); - it('can shift+F6 to a landmark region', function () { + it('can shift+F6 to a landmark region', async function () { let tree = render(
@@ -384,12 +359,10 @@ describe('LandmarkManager', function () { let navigation = tree.getByRole('navigation'); let main = tree.getByRole('main'); - fireEvent.keyDown(document.activeElement!, {key: 'F6', shiftKey: true}); - fireEvent.keyUp(document.activeElement!, {key: 'F6', shiftKey: true}); + await user.keyboard('{Shift>}{F6}{/Shift}}'); expect(document.activeElement!).toBe(main); - fireEvent.keyDown(document.activeElement!, {key: 'F6', shiftKey: true}); - fireEvent.keyUp(document.activeElement!, {key: 'F6', shiftKey: true}); + await user.keyboard('{Shift>}{F6}{/Shift}}'); expect(document.activeElement!).toBe(navigation); }); @@ -415,8 +388,7 @@ describe('LandmarkManager', function () { await user.tab(); expect(document.activeElement!).toBe(tree.getByRole('textbox')); - fireEvent.keyDown(document.activeElement!, {key: 'F6', shiftKey: true}); - fireEvent.keyUp(document.activeElement!, {key: 'F6', shiftKey: true}); + await user.keyboard('{Shift>}{F6}{/Shift}}'); expect(document.activeElement!).toBe(tree.getAllByRole('link')[2]); }); @@ -440,8 +412,7 @@ describe('LandmarkManager', function () { await user.tab(); expect(document.activeElement!).toBe(tree.getAllByRole('link')[0]); - fireEvent.keyDown(document.activeElement!, {key: 'F6', shiftKey: true}); - fireEvent.keyUp(document.activeElement!, {key: 'F6', shiftKey: true}); + await user.keyboard('{Shift>}{F6}{/Shift}}'); expect(document.activeElement!).toBe(main); }); @@ -467,8 +438,7 @@ describe('LandmarkManager', function () { await user.tab(); expect(document.activeElement!).toBe(tree.getByRole('textbox')); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(tree.getAllByRole('link')[2]); }); @@ -520,24 +490,19 @@ describe('LandmarkManager', function () { await user.tab(); expect(document.activeElement!).toBe(buttons[0]); - fireEvent.keyDown(document.activeElement!, {key: 'ArrowRight'}); - fireEvent.keyUp(document.activeElement!, {key: 'ArrowRight'}); + await user.keyboard('{ArrowRight}'); expect(document.activeElement!).toBe(buttons[1]); await user.tab(); expect(document.activeElement!).toBe(rows[1]); - fireEvent.keyDown(document.activeElement!, {key: 'ArrowRight'}); - fireEvent.keyUp(document.activeElement!, {key: 'ArrowRight'}); - fireEvent.keyDown(document.activeElement!, {key: 'ArrowRight'}); - fireEvent.keyUp(document.activeElement!, {key: 'ArrowRight'}); + await user.keyboard('{ArrowRight}'); + await user.keyboard('{ArrowRight}'); expect(document.activeElement!).toBe(cells[0]); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(buttons[1]); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(cells[0]); }); @@ -628,7 +593,7 @@ describe('LandmarkManager', function () { expect(spyWarn).toHaveBeenCalledWith('Page contains more than one landmark with the \'navigation\' role and \'First nav\' label. If two or more landmarks on a page share the same role, they must have unique labels: ', navs); }); - it('Should not navigate to a landmark that has been removed from the DOM', function () { + it('Should not navigate to a landmark that has been removed from the DOM', async function () { function Container(props) { return ( @@ -660,27 +625,23 @@ describe('LandmarkManager', function () { let region = tree.getByRole('region'); let main = tree.getByRole('main'); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(navigation); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(region); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(main); tree.rerender(); - fireEvent.keyDown(document.activeElement!, {key: 'F6', shiftKey: true}); - fireEvent.keyUp(document.activeElement!, {key: 'F6', shiftKey: true}); + await user.keyboard('{Shift>}{F6}{/Shift}}'); expect(document.activeElement!).toBe(navigation); }); - it('Should navigate to a landmark that has been added to the DOM', function () { + it('Should navigate to a landmark that has been added to the DOM', async function () { function Container(props) { return ( @@ -704,12 +665,10 @@ describe('LandmarkManager', function () { let navigation = tree.getByRole('navigation'); let main = tree.getByRole('main'); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(navigation); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(main); tree.rerender( @@ -722,12 +681,11 @@ describe('LandmarkManager', function () { let region = tree.getByRole('region'); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(region); }); - it('Should navigate to a landmark that has been added as a child to an existing landmark.', function () { + it('Should navigate to a landmark that has been added as a child to an existing landmark.', async function () { function Container(props) { return ( @@ -759,20 +717,17 @@ describe('LandmarkManager', function () { let navigation = tree.getByRole('navigation'); let region = tree.getByRole('region'); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(navigation); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(main); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(region); }); - it('Should navigate to a landmark that has been added as a parent to an existing landmark.', function () { + it('Should navigate to a landmark that has been added as a parent to an existing landmark.', async function () { function Contained() { return ( @@ -802,12 +757,11 @@ describe('LandmarkManager', function () { let main = tree.getByRole('main'); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(main); }); - it('can alt+F6 to main landmark', function () { + it('can alt+F6 to main landmark', async function () { let tree = render(
@@ -828,24 +782,20 @@ describe('LandmarkManager', function () { let navigation = tree.getByRole('navigation'); let main = tree.getByRole('main'); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(navigation); - fireEvent.keyDown(document.activeElement!, {key: 'F6', altKey: true}); - fireEvent.keyUp(document.activeElement!, {key: 'F6', altKey: true}); + await user.keyboard('{Alt>}{F6}{/Alt}}'); expect(document.activeElement!).toBe(main); - fireEvent.keyDown(document.activeElement!, {key: 'F6', altKey: true}); - fireEvent.keyUp(document.activeElement!, {key: 'F6', altKey: true}); + await user.keyboard('{Alt>}{F6}{/Alt}}'); expect(document.activeElement!).toBe(main); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(navigation); }); - it('alt+F6 does nothing if no main landmark', function () { + it('alt+F6 does nothing if no main landmark', async function () { let tree = render(
@@ -862,16 +812,14 @@ describe('LandmarkManager', function () { ); let navigation = tree.getByRole('navigation'); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(navigation); - fireEvent.keyDown(document.activeElement!, {key: 'F6', altKey: true}); - fireEvent.keyUp(document.activeElement!, {key: 'F6', altKey: true}); + await user.keyboard('{Alt>}{F6}{/Alt}}'); expect(document.activeElement!).toBe(navigation); }); - it('can alt+F6 to main landmark if main is the only landmark', function () { + it('can alt+F6 to main landmark if main is the only landmark', async function () { let tree = render(
@@ -881,20 +829,17 @@ describe('LandmarkManager', function () { ); let main = tree.getByRole('main'); - fireEvent.keyDown(document.activeElement!, {key: 'F6', altKey: true}); - fireEvent.keyUp(document.activeElement!, {key: 'F6', altKey: true}); + await user.keyboard('{Alt>}{F6}{/Alt}}'); expect(document.activeElement!).toBe(main); - fireEvent.keyDown(document.activeElement!, {key: 'F6', altKey: true}); - fireEvent.keyUp(document.activeElement!, {key: 'F6', altKey: true}); + await user.keyboard('{Alt>}{F6}{/Alt}}'); expect(document.activeElement!).toBe(main); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(main); }); - it('landmark has tabIndex="-1" when focused', function () { + it('landmark has tabIndex="-1" when focused', async function () { let tree = render(
@@ -914,14 +859,12 @@ describe('LandmarkManager', function () { expect(navigation).not.toHaveAttribute('tabIndex'); expect(main).not.toHaveAttribute('tabIndex'); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(navigation); expect(navigation).toHaveAttribute('tabIndex', '-1'); expect(main).not.toHaveAttribute('tabIndex'); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(main).toHaveAttribute('tabIndex', '-1'); expect(navigation).not.toHaveAttribute('tabIndex'); }); @@ -949,7 +892,7 @@ describe('LandmarkManager', function () { expect(document.activeElement!).toBe(document.body); }); - it('focuses the landmark again after toggling browser tabs', function () { + it('focuses the landmark again after toggling browser tabs', async function () { let {getByRole} = render(
@@ -966,8 +909,7 @@ describe('LandmarkManager', function () { ); let nav = getByRole('navigation'); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(nav).toHaveAttribute('tabIndex', '-1'); expect(document.activeElement!).toBe(nav); @@ -977,7 +919,7 @@ describe('LandmarkManager', function () { expect(nav).toHaveAttribute('tabIndex', '-1'); }); - it('focuses the landmark again after toggling browser windows', function () { + it('focuses the landmark again after toggling browser windows', async function () { let {getByRole} = render(
@@ -994,8 +936,7 @@ describe('LandmarkManager', function () { ); let nav = getByRole('navigation'); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(nav).toHaveAttribute('tabIndex', '-1'); expect(document.activeElement!).toBe(nav); @@ -1022,8 +963,7 @@ describe('LandmarkManager', function () { ); let nav = getByRole('navigation'); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(nav).toHaveAttribute('tabIndex', '-1'); expect(document.activeElement!).toBe(nav); @@ -1033,7 +973,7 @@ describe('LandmarkManager', function () { expect(nav).not.toHaveAttribute('tabIndex'); }); - it('cleans up event listeners if all landmarks are unmounted', function () { + it('cleans up event listeners if all landmarks are unmounted', async function () { // Because our listener stops propagation of the F6 key to prevent anything // else from handling it, we can render with landmarks to make sure the propagation is stopped // and then when everything is unmounted, we can check again. @@ -1056,8 +996,7 @@ describe('LandmarkManager', function () { act(() => { button.focus(); }); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(nav); expect(onKeyDown).not.toHaveBeenCalled(); @@ -1072,8 +1011,7 @@ describe('LandmarkManager', function () { act(() => { button.focus(); }); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(onKeyDown).toHaveBeenCalled(); }); @@ -1126,7 +1064,7 @@ describe('LandmarkManager', function () { expect(spyWarn).toHaveBeenCalledWith('Page contains more than one landmark with the \'navigation\' role and \'nav label 1\' label. If two or more landmarks on a page share the same role, they must have unique labels: ', navs); }); - it('focus restores to previously focused landmark after blur and F6.', function () { + it('focus restores to previously focused landmark after blur and F6.', async function () { let {getByRole} = render(
@@ -1143,8 +1081,7 @@ describe('LandmarkManager', function () { ); let nav = getByRole('navigation'); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(nav).toHaveAttribute('tabIndex', '-1'); expect(document.activeElement).toBe(nav); @@ -1154,8 +1091,7 @@ describe('LandmarkManager', function () { expect(nav).not.toHaveAttribute('tabIndex', '-1'); expect(document.activeElement!).toBe(document.body); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(nav).toHaveAttribute('tabIndex', '-1'); expect(document.activeElement!).toBe(nav); }); @@ -1183,12 +1119,10 @@ describe('LandmarkManager', function () { await user.tab(); expect(document.activeElement!).toBe(tree.getAllByRole('link')[0]); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(main); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(main); @@ -1222,8 +1156,7 @@ describe('LandmarkManager', function () { await user.tab(); expect(document.activeElement!).toBe(tree.getAllByRole('link')[0]); - fireEvent.keyDown(document.activeElement!, {key: 'F6', shiftKey: true}); - fireEvent.keyUp(document.activeElement!, {key: 'F6', shiftKey: true}); + await user.keyboard('{Shift>}{F6}{/Shift}}'); expect(document.activeElement!).toBe(tree.getAllByRole('link')[0]); expect(onLandmarkNavigation).toHaveBeenCalledTimes(1); @@ -1234,7 +1167,7 @@ describe('LandmarkManager', function () { window.removeEventListener('react-aria-landmark-navigation', onLandmarkNavigation); }); - it('skips over aria-hidden landmarks', function () { + it('skips over aria-hidden landmarks', async function () { let tree = render(
@@ -1257,47 +1190,39 @@ describe('LandmarkManager', function () { let main = tree.getByRole('main'); let region2 = tree.getAllByRole('region')[0]; - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(main); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(region2); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(document.activeElement!).toBe(main); - fireEvent.keyDown(document.activeElement!, {key: 'F6', shiftKey: true}); - fireEvent.keyUp(document.activeElement!, {key: 'F6', shiftKey: true}); + await user.keyboard('{Shift>}{F6}{/Shift}}'); expect(document.activeElement!).toBe(region2); - fireEvent.keyDown(document.activeElement!, {key: 'F6', shiftKey: true}); - fireEvent.keyUp(document.activeElement!, {key: 'F6', shiftKey: true}); + await user.keyboard('{Shift>}{F6}{/Shift}}'); expect(document.activeElement!).toBe(main); }); describe('LandmarkController', function () { - it('should ensure keyboard listeners are active', function () { + it('should ensure keyboard listeners are active', async function () { let onLandmarkNavigation = jest.fn().mockImplementation(e => e.preventDefault()); window.addEventListener('react-aria-landmark-navigation', onLandmarkNavigation); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(onLandmarkNavigation).not.toHaveBeenCalled(); let controller = createLandmarkController(); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(onLandmarkNavigation).toHaveBeenCalledTimes(1); controller.dispose(); onLandmarkNavigation.mockReset(); - fireEvent.keyDown(document.activeElement!, {key: 'F6'}); - fireEvent.keyUp(document.activeElement!, {key: 'F6'}); + await user.keyboard('{F6}'); expect(onLandmarkNavigation).not.toHaveBeenCalled(); window.removeEventListener('react-aria-landmark-navigation', onLandmarkNavigation); diff --git a/packages/@react-aria/selection/test/useSelectableCollection.test.js b/packages/@react-aria/selection/test/useSelectableCollection.test.js index fcfaac77e3f..346de9d3ab3 100644 --- a/packages/@react-aria/selection/test/useSelectableCollection.test.js +++ b/packages/@react-aria/selection/test/useSelectableCollection.test.js @@ -57,20 +57,17 @@ describe('useSelectableCollection', () => { expect(options[0]).toHaveAttribute('aria-selected', 'true'); expect(options[1]).not.toHaveAttribute('aria-selected'); expect(options[2]).not.toHaveAttribute('aria-selected'); - fireEvent.keyDown(document.activeElement, {key: 'ArrowDown', ctrlKey: true}); - fireEvent.keyUp(document.activeElement, {key: 'ArrowDown', ctrlKey: true}); + await user.keyboard('{Control>}{ArrowDown}{/Control}'); expect(document.activeElement).toBe(options[1]); expect(options[0]).toHaveAttribute('aria-selected', 'true'); expect(options[1]).not.toHaveAttribute('aria-selected'); expect(options[2]).not.toHaveAttribute('aria-selected'); - fireEvent.keyDown(document.activeElement, {key: 'ArrowDown', ctrlKey: true}); - fireEvent.keyUp(document.activeElement, {key: 'ArrowDown', ctrlKey: true}); + await user.keyboard('{Control>}{ArrowDown}{/Control}'); expect(document.activeElement).toBe(options[2]); expect(options[0]).toHaveAttribute('aria-selected', 'true'); expect(options[1]).not.toHaveAttribute('aria-selected'); expect(options[2]).not.toHaveAttribute('aria-selected'); - fireEvent.keyDown(document.activeElement, {key: ' '}); - fireEvent.keyUp(document.activeElement, {key: ' '}); + await user.keyboard('[Space]'); expect(options[0]).not.toHaveAttribute('aria-selected'); expect(options[1]).not.toHaveAttribute('aria-selected'); expect(options[2]).toHaveAttribute('aria-selected', 'true'); From 1d8036111b05d236e7963444ac95e526c12695f1 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Mon, 4 Dec 2023 17:27:56 -0800 Subject: [PATCH 14/31] wrapping up hooks tests fireEvent replacements couldnt get the pointer/mouseMoves replaces, will revisit --- .../slider/test/useSliderThumb.test.js | 75 +++++++++---------- .../spinbutton/test/useSpinButton.test.js | 59 ++++++++------- .../@react-aria/tag/test/useTagGroup.test.js | 12 ++- 3 files changed, 73 insertions(+), 73 deletions(-) diff --git a/packages/@react-aria/slider/test/useSliderThumb.test.js b/packages/@react-aria/slider/test/useSliderThumb.test.js index 0e6bf25c513..ac58c27aed6 100644 --- a/packages/@react-aria/slider/test/useSliderThumb.test.js +++ b/packages/@react-aria/slider/test/useSliderThumb.test.js @@ -1,6 +1,7 @@ -import {fireEvent, installMouseEvent, installPointerEvent, render, renderHook, screen} from '@react-spectrum/test-utils'; +import {fireEvent, installMouseEvent, installPointerEvent, pointerMap, render, renderHook, screen} from '@react-spectrum/test-utils'; import * as React from 'react'; import {useRef} from 'react'; +import userEvent from '@testing-library/user-event'; import {useSlider, useSliderThumb} from '../src'; import {useSliderState} from '@react-stately/slider'; @@ -372,23 +373,22 @@ describe('useSliderThumb', () => { }); describe('using KeyEvents', () => { - it('can be moved with keys', () => { + it('can be moved with keys', async () => { + let user = userEvent.setup({delay: null, pointerMap}); let onChangeSpy = jest.fn(); let onChangeEndSpy = jest.fn(); render(); // Drag thumb - let thumb0 = screen.getByTestId('thumb').firstChild; - fireEvent.keyDown(thumb0, {key: 'ArrowRight'}); - fireEvent.keyUp(thumb0, {key: 'ArrowRight'}); + await user.tab(); + await user.keyboard('{ArrowRight}'); expect(onChangeSpy).toHaveBeenLastCalledWith([11]); expect(onChangeSpy).toHaveBeenCalledTimes(1); expect(onChangeEndSpy).toHaveBeenLastCalledWith([11]); expect(onChangeEndSpy).toHaveBeenCalledTimes(1); expect(stateRef.current.values).toEqual([11]); - fireEvent.keyDown(thumb0, {key: 'ArrowLeft'}); - fireEvent.keyUp(thumb0, {key: 'ArrowLeft'}); + await user.keyboard('{ArrowLeft}'); expect(onChangeSpy).toHaveBeenLastCalledWith([10]); expect(onChangeSpy).toHaveBeenCalledTimes(2); expect(onChangeEndSpy).toHaveBeenLastCalledWith([10]); @@ -396,19 +396,18 @@ describe('useSliderThumb', () => { expect(stateRef.current.values).toEqual([10]); }); - it('can be moved with keys at the beginning of the slider', () => { + it('can be moved with keys at the beginning of the slider', async () => { + let user = userEvent.setup({delay: null, pointerMap}); let onChangeSpy = jest.fn(); let onChangeEndSpy = jest.fn(); render(); - let thumb0 = screen.getByTestId('thumb').firstChild; - fireEvent.keyDown(thumb0, {key: 'ArrowLeft'}); - fireEvent.keyUp(thumb0, {key: 'ArrowLeft'}); + await user.tab(); + await user.keyboard('{ArrowLeft}'); expect(onChangeSpy).not.toHaveBeenCalled(); expect(onChangeEndSpy).toHaveBeenCalledWith([0]); - fireEvent.keyDown(thumb0, {key: 'ArrowRight'}); - fireEvent.keyUp(thumb0, {key: 'ArrowRight'}); + await user.keyboard('{ArrowRight}'); expect(onChangeSpy).toHaveBeenLastCalledWith([1]); expect(onChangeSpy).toHaveBeenCalledTimes(1); expect(onChangeEndSpy).toHaveBeenLastCalledWith([1]); @@ -416,19 +415,18 @@ describe('useSliderThumb', () => { expect(stateRef.current.values).toEqual([1]); }); - it('can be moved with keys at the end of the slider', () => { + it('can be moved with keys at the end of the slider', async () => { + let user = userEvent.setup({delay: null, pointerMap}); let onChangeSpy = jest.fn(); let onChangeEndSpy = jest.fn(); render(); - let thumb0 = screen.getByTestId('thumb').firstChild; - fireEvent.keyDown(thumb0, {key: 'ArrowRight'}); - fireEvent.keyUp(thumb0, {key: 'ArrowRight'}); + await user.tab(); + await user.keyboard('{ArrowRight}'); expect(onChangeSpy).not.toHaveBeenCalled(); expect(onChangeEndSpy).toHaveBeenCalledWith([100]); - fireEvent.keyDown(thumb0, {key: 'ArrowLeft'}); - fireEvent.keyUp(thumb0, {key: 'ArrowLeft'}); + await user.keyboard('{ArrowLeft}'); expect(onChangeSpy).toHaveBeenLastCalledWith([99]); expect(onChangeSpy).toHaveBeenCalledTimes(1); expect(onChangeEndSpy).toHaveBeenLastCalledWith([99]); @@ -436,45 +434,41 @@ describe('useSliderThumb', () => { expect(stateRef.current.values).toEqual([99]); }); - it('can be moved with keys (vertical)', () => { + it('can be moved with keys (vertical)', async () => { + let user = userEvent.setup({delay: null, pointerMap}); let onChangeSpy = jest.fn(); let onChangeEndSpy = jest.fn(); render(); // Drag thumb - let thumb0 = screen.getByTestId('thumb').firstChild; - fireEvent.keyDown(thumb0, {key: 'ArrowRight'}); - fireEvent.keyUp(thumb0, {key: 'ArrowRight'}); + await user.tab(); + await user.keyboard('{ArrowRight}'); expect(onChangeSpy).toHaveBeenLastCalledWith([11]); expect(onChangeSpy).toHaveBeenCalledTimes(1); - fireEvent.keyDown(thumb0, {key: 'ArrowUp'}); - fireEvent.keyUp(thumb0, {key: 'ArrowUp'}); + await user.keyboard('{ArrowUp}'); expect(onChangeSpy).toHaveBeenLastCalledWith([12]); expect(onChangeSpy).toHaveBeenCalledTimes(2); - fireEvent.keyDown(thumb0, {key: 'ArrowDown'}); - fireEvent.keyUp(thumb0, {key: 'ArrowDown'}); + await user.keyboard('{ArrowDown}'); expect(onChangeSpy).toHaveBeenLastCalledWith([11]); expect(onChangeSpy).toHaveBeenCalledTimes(3); - fireEvent.keyDown(thumb0, {key: 'ArrowLeft'}); - fireEvent.keyUp(thumb0, {key: 'ArrowLeft'}); + await user.keyboard('{ArrowLeft}'); expect(onChangeSpy).toHaveBeenLastCalledWith([10]); expect(onChangeSpy).toHaveBeenCalledTimes(4); }); - it('can be moved with keys (vertical) at the bottom of the slider', () => { + it('can be moved with keys (vertical) at the bottom of the slider', async () => { + let user = userEvent.setup({delay: null, pointerMap}); let onChangeSpy = jest.fn(); let onChangeEndSpy = jest.fn(); render(); // Drag thumb - let thumb0 = screen.getByTestId('thumb').firstChild; - fireEvent.keyDown(thumb0, {key: 'ArrowDown'}); - fireEvent.keyUp(thumb0, {key: 'ArrowDown'}); + await user.tab(); + await user.keyboard('{ArrowDown}'); expect(onChangeSpy).not.toHaveBeenCalled(); expect(onChangeEndSpy).toHaveBeenCalledWith([0]); - fireEvent.keyDown(thumb0, {key: 'ArrowUp'}); - fireEvent.keyUp(thumb0, {key: 'ArrowUp'}); + await user.keyboard('{ArrowUp}'); expect(onChangeSpy).toHaveBeenLastCalledWith([1]); expect(onChangeSpy).toHaveBeenCalledTimes(1); expect(onChangeEndSpy).toHaveBeenLastCalledWith([1]); @@ -482,20 +476,19 @@ describe('useSliderThumb', () => { expect(stateRef.current.values).toEqual([1]); }); - it('can be moved with keys (vertical) at the top of the slider', () => { + it('can be moved with keys (vertical) at the top of the slider', async () => { + let user = userEvent.setup({delay: null, pointerMap}); let onChangeSpy = jest.fn(); let onChangeEndSpy = jest.fn(); render(); // Drag thumb - let thumb0 = screen.getByTestId('thumb').firstChild; - fireEvent.keyDown(thumb0, {key: 'ArrowUp'}); - fireEvent.keyUp(thumb0, {key: 'ArrowUp'}); + await user.tab(); + await user.keyboard('{ArrowUp}'); expect(onChangeSpy).not.toHaveBeenCalled(); expect(onChangeEndSpy).toHaveBeenCalledWith([100]); - fireEvent.keyDown(thumb0, {key: 'ArrowDown'}); - fireEvent.keyUp(thumb0, {key: 'ArrowDown'}); + await user.keyboard('{ArrowDown}'); expect(onChangeSpy).toHaveBeenLastCalledWith([99]); expect(onChangeSpy).toHaveBeenCalledTimes(1); expect(onChangeEndSpy).toHaveBeenLastCalledWith([99]); diff --git a/packages/@react-aria/spinbutton/test/useSpinButton.test.js b/packages/@react-aria/spinbutton/test/useSpinButton.test.js index 696c8958ba4..413fd223bac 100644 --- a/packages/@react-aria/spinbutton/test/useSpinButton.test.js +++ b/packages/@react-aria/spinbutton/test/useSpinButton.test.js @@ -11,9 +11,10 @@ */ jest.mock('@react-aria/live-announcer'); -import {act, fireEvent, render} from '@react-spectrum/test-utils'; +import {act, pointerMap, render} from '@react-spectrum/test-utils'; import {announce} from '@react-aria/live-announcer'; import React from 'react'; +import userEvent from '@testing-library/user-event'; import {useSpinButton} from '../'; function Example(props) { @@ -46,67 +47,75 @@ describe('useSpinButton', function () { expect(el).toHaveAttribute('aria-readonly', 'true'); }); - it('should trigger onIncrement on arrow up', function () { + it('should trigger onIncrement on arrow up', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let onIncrement = jest.fn(); let res = render(); - let el = res.getByTestId('test'); - fireEvent.keyDown(el, {key: 'ArrowUp'}); + act(() => res.getByTestId('test').focus()); + await user.keyboard('{ArrowUp}'); expect(onIncrement).toHaveBeenCalledTimes(1); }); - it('should trigger onDecrement on arrow down', function () { + it('should trigger onDecrement on arrow down', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let onDecrement = jest.fn(); let res = render(); - let el = res.getByTestId('test'); - fireEvent.keyDown(el, {key: 'ArrowDown'}); + act(() => res.getByTestId('test').focus()); + await user.keyboard('{ArrowDown}'); expect(onDecrement).toHaveBeenCalledTimes(1); }); - it('should trigger onIncrementPage on page up', function () { + it('should trigger onIncrementPage on page up', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let onIncrementPage = jest.fn(); let res = render(); - let el = res.getByTestId('test'); - fireEvent.keyDown(el, {key: 'PageUp'}); + act(() => res.getByTestId('test').focus()); + await user.keyboard('{PageUp}'); expect(onIncrementPage).toHaveBeenCalledTimes(1); }); - it('should fall back to onIncrement on page up if onIncrementPage is not available', function () { + it('should fall back to onIncrement on page up if onIncrementPage is not available', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let onIncrement = jest.fn(); let res = render(); - let el = res.getByTestId('test'); - fireEvent.keyDown(el, {key: 'PageUp'}); + act(() => res.getByTestId('test').focus()); + await user.keyboard('{PageUp}'); expect(onIncrement).toHaveBeenCalledTimes(1); }); - it('should trigger onDecrementPage on page up', function () { + it('should trigger onDecrementPage on page up', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let onDecrementPage = jest.fn(); let res = render(); - let el = res.getByTestId('test'); - fireEvent.keyDown(el, {key: 'PageDown'}); + act(() => res.getByTestId('test').focus()); + await user.keyboard('{PageDown}'); expect(onDecrementPage).toHaveBeenCalledTimes(1); }); - it('should fall back to onDecrement on page up if onDecrementPage is not available', function () { + it('should fall back to onDecrement on page up if onDecrementPage is not available', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let onDecrement = jest.fn(); let res = render(); - let el = res.getByTestId('test'); - fireEvent.keyDown(el, {key: 'PageDown'}); + act(() => res.getByTestId('test').focus()); + await user.keyboard('{PageDown}'); expect(onDecrement).toHaveBeenCalledTimes(1); }); - it('should trigger onDecrementToMin on home key', function () { + it('should trigger onDecrementToMin on home key', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let onDecrementToMin = jest.fn(); let res = render(); - let el = res.getByTestId('test'); - fireEvent.keyDown(el, {key: 'Home'}); + act(() => res.getByTestId('test').focus()); + await user.keyboard('{Home}'); expect(onDecrementToMin).toHaveBeenCalledTimes(1); }); - it('should trigger onIncrementToMax on end key', function () { + it('should trigger onIncrementToMax on end key', async function () { + let user = userEvent.setup({delay: null, pointerMap}); let onIncrementToMax = jest.fn(); let res = render(); - let el = res.getByTestId('test'); - fireEvent.keyDown(el, {key: 'End'}); + act(() => res.getByTestId('test').focus()); + await user.keyboard('{End}'); expect(onIncrementToMax).toHaveBeenCalledTimes(1); }); diff --git a/packages/@react-aria/tag/test/useTagGroup.test.js b/packages/@react-aria/tag/test/useTagGroup.test.js index 0f259a04a01..007d3e5fb17 100644 --- a/packages/@react-aria/tag/test/useTagGroup.test.js +++ b/packages/@react-aria/tag/test/useTagGroup.test.js @@ -10,8 +10,8 @@ * governing permissions and limitations under the License. */ -import {fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; import {Item} from '@react-stately/collections'; +import {pointerMap, render, within} from '@react-spectrum/test-utils'; import React from 'react'; import {useButton} from '@react-aria/button'; import {useListState} from '@react-stately/list'; @@ -96,17 +96,15 @@ describe('useTagGroup', function () { expect(tags[3]).toHaveAttribute('aria-selected', 'true'); expect(tags[4]).toHaveAttribute('aria-selected', 'false'); - fireEvent.keyDown(tags[3], {key: 'Backspace'}); - fireEvent.keyUp(tags[3], {key: 'Backspace'}); - + await user.keyboard('{Backspace}'); expect(onRemove).toHaveBeenCalledTimes(1); expect(onRemove).toHaveBeenLastCalledWith(new Set(['parking', 'pool'])); - fireEvent.keyDown(tags[0], {key: 'Backspace'}); - fireEvent.keyUp(tags[0], {key: 'Backspace'}); + await user.click(tags[0]); + await user.keyboard('{Backspace}'); expect(onRemove).toHaveBeenCalledTimes(2); - expect(onRemove).toHaveBeenLastCalledWith(new Set(['laundry'])); + expect(onRemove).toHaveBeenLastCalledWith(new Set(['laundry', 'parking', 'pool'])); let button = within(tags[3]).getByRole('button'); await user.click(button); From 0cc42d584523a255b128ab7aff55c2aa00c9f7c0 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Mon, 4 Dec 2023 17:42:59 -0800 Subject: [PATCH 15/31] fix some lint issues --- packages/@react-aria/focus/test/FocusScope.test.js | 6 +++--- packages/@react-spectrum/menu/test/MenuTrigger.test.js | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/@react-aria/focus/test/FocusScope.test.js b/packages/@react-aria/focus/test/FocusScope.test.js index 432a009fe3f..645bea6aa71 100644 --- a/packages/@react-aria/focus/test/FocusScope.test.js +++ b/packages/@react-aria/focus/test/FocusScope.test.js @@ -1581,14 +1581,14 @@ describe('FocusScope', function () { await user.tab(); expect(document.activeElement.textContent).toBe('Open Menu'); -await user.keyboard('[Enter]'); + await user.keyboard('[Enter]'); act(() => { jest.runAllTimers(); }); expect(document.activeElement.textContent).toBe('Open Dialog'); -await user.keyboard('[Enter]'); + await user.keyboard('[Enter]'); // Needed for onBlur raf in useFocusContainment act(() => { @@ -1601,7 +1601,7 @@ await user.keyboard('[Enter]'); expect(document.activeElement.textContent).toBe('Close'); -await user.keyboard('[Enter]'); + await user.keyboard('[Enter]'); act(() => { jest.runAllTimers(); }); diff --git a/packages/@react-spectrum/menu/test/MenuTrigger.test.js b/packages/@react-spectrum/menu/test/MenuTrigger.test.js index 3109aab450b..168f5b254a1 100644 --- a/packages/@react-spectrum/menu/test/MenuTrigger.test.js +++ b/packages/@react-spectrum/menu/test/MenuTrigger.test.js @@ -881,7 +881,7 @@ describe('MenuTrigger', function () { if (!menu) { fireEvent.keyDown(button, {key: 'ArrowUp', altKey: true}); } else { - await user.pointer({target: button, keys: '[TouchA]'});; + await user.pointer({target: button, keys: '[TouchA]'}); } }); }); @@ -892,7 +892,7 @@ describe('MenuTrigger', function () { if (!menu) { fireEvent.keyDown(button, {key: 'ArrowDown', altKey: true}); } else { - await user.pointer({target: button, keys: '[TouchA]'});; + await user.pointer({target: button, keys: '[TouchA]'}); } }); }); From 79a71f4dd604bba97bfac97c188602e4d318f5e5 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Tue, 5 Dec 2023 12:06:52 -0800 Subject: [PATCH 16/31] first batch of spectrum test fireEvent -> userEvent replacement --- .../accordion/test/Accordion.test.js | 22 +- .../actionbar/test/ActionBar.test.js | 36 +- .../actiongroup/test/ActionGroup.test.js | 10 +- .../test/SearchAutocomplete.test.js | 256 +++++------- .../button/test/Button.test.js | 36 +- .../calendar/test/Calendar.test.js | 52 ++- .../calendar/test/CalendarBase.test.js | 38 +- .../calendar/test/RangeCalendar.test.js | 56 ++- .../card/test/CardView.test.js | 99 ++--- .../color/test/ColorField.test.js | 26 +- .../color/test/ColorSlider.test.tsx | 24 +- .../color/test/ColorWheel.test.tsx | 32 +- .../combobox/test/ComboBox.test.js | 384 +++++++----------- .../datepicker/test/DateField.test.js | 12 +- .../datepicker/test/DatePicker.test.js | 333 +++++++-------- 15 files changed, 603 insertions(+), 813 deletions(-) diff --git a/packages/@react-spectrum/accordion/test/Accordion.test.js b/packages/@react-spectrum/accordion/test/Accordion.test.js index 62adfa381e1..1a155b3482c 100644 --- a/packages/@react-spectrum/accordion/test/Accordion.test.js +++ b/packages/@react-spectrum/accordion/test/Accordion.test.js @@ -11,7 +11,7 @@ */ import {Accordion, Item} from '../src'; -import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; +import {act, pointerMap, render, within} from '@react-spectrum/test-utils'; import {Provider} from '@react-spectrum/provider'; import React from 'react'; import {theme} from '@react-spectrum/theme-default'; @@ -74,7 +74,7 @@ describe('Accordion', function () { expect(selectedItem).toHaveAttribute('aria-expanded', 'true'); }); - it('allows users to open and close accordion item with enter / space key', function () { + it('allows users to open and close accordion item with enter / space key', async function () { let tree = renderComponent(); let buttons = tree.getAllByRole('button'); let selectedItem = buttons[0]; @@ -82,31 +82,29 @@ describe('Accordion', function () { act(() => {selectedItem.focus();}); expect(document.activeElement).toBe(selectedItem); - fireEvent.keyDown(selectedItem, {key: 'Enter'}); - fireEvent.keyUp(selectedItem, {key: 'Enter'}); + await user.keyboard('{Enter}'); expect(selectedItem).toHaveAttribute('aria-expanded', 'false'); - fireEvent.keyDown(selectedItem, {key: 'Enter'}); - fireEvent.keyUp(selectedItem, {key: 'Enter'}); + await user.keyboard('{Enter}'); expect(selectedItem).toHaveAttribute('aria-expanded', 'true'); }); - it('allows users to naviagte accordion headers through arrow keys', function () { + it('allows users to naviagte accordion headers through arrow keys', async function () { let tree = renderComponent(); let buttons = tree.getAllByRole('button'); let [firstItem, secondItem, thirdItem] = buttons; act(() => {firstItem.focus();}); expect(document.activeElement).toBe(firstItem); - fireEvent.keyDown(firstItem, {key: 'ArrowUp'}); + await user.keyboard('{ArrowUp}'); expect(document.activeElement).toBe(firstItem); - fireEvent.keyDown(firstItem, {key: 'ArrowDown'}); + await user.keyboard('{ArrowDown}'); expect(document.activeElement).toBe(secondItem); - fireEvent.keyDown(secondItem, {key: 'ArrowDown'}); + await user.keyboard('{ArrowDown}'); expect(document.activeElement).toBe(thirdItem); - fireEvent.keyDown(thirdItem, {key: 'ArrowDown'}); + await user.keyboard('{ArrowDown}'); expect(document.activeElement).toBe(thirdItem); - fireEvent.keyDown(thirdItem, {key: 'ArrowUp'}); + await user.keyboard('{ArrowUp}'); expect(document.activeElement).toBe(secondItem); }); diff --git a/packages/@react-spectrum/actionbar/test/ActionBar.test.js b/packages/@react-spectrum/actionbar/test/ActionBar.test.js index 1d979954785..e69ceb26b30 100644 --- a/packages/@react-spectrum/actionbar/test/ActionBar.test.js +++ b/packages/@react-spectrum/actionbar/test/ActionBar.test.js @@ -121,8 +121,7 @@ describe('ActionBar', () => { let toolbar = tree.getByRole('toolbar'); act(() => within(toolbar).getAllByRole('button')[0].focus()); - fireEvent.keyDown(document.activeElement, {key: 'Escape'}); - fireEvent.keyUp(document.activeElement, {key: 'Escape'}); + await user.keyboard('{Escape}'); act(() => jest.runAllTimers()); act(() => jest.runAllTimers()); @@ -140,8 +139,7 @@ describe('ActionBar', () => { await user.tab(); expect(document.activeElement).toBe(rows[1]); - fireEvent.keyDown(document.activeElement, {key: 'Enter'}); - fireEvent.keyUp(document.activeElement, {key: 'Enter'}); + await user.keyboard('{Enter}'); expect(checkbox).toBeChecked(); act(() => jest.runAllTimers()); @@ -157,8 +155,7 @@ describe('ActionBar', () => { fireEvent.keyUp(document.activeElement, {key: 'Tab'}); expect(document.activeElement).toBe(within(toolbar).getAllByRole('button')[0]); - fireEvent.keyDown(document.activeElement, {key: 'Escape'}); - fireEvent.keyUp(document.activeElement, {key: 'Escape'}); + await user.keyboard('{Escape}'); // jsdom doesn't blur to body like a browser, so it was being placed on the first focusable element, conveniently our table row // emulate browser behavior and blur act(() => document.activeElement.blur()); @@ -179,8 +176,7 @@ describe('ActionBar', () => { await user.tab(); expect(document.activeElement).toBe(rows[1]); - fireEvent.keyDown(document.activeElement, {key: 'Enter'}); - fireEvent.keyUp(document.activeElement, {key: 'Enter'}); + await user.keyboard('{Enter}'); expect(checkbox).toBeChecked(); act(() => jest.runAllTimers()); @@ -196,16 +192,13 @@ describe('ActionBar', () => { fireEvent.keyUp(document.activeElement, {key: 'Tab'}); expect(document.activeElement).toBe(within(toolbar).getAllByRole('button')[0]); - fireEvent.keyDown(document.activeElement, {key: 'ArrowRight'}); - fireEvent.keyUp(document.activeElement, {key: 'ArrowRight'}); + await user.keyboard('{ArrowRight}'); - fireEvent.keyDown(document.activeElement, {key: 'ArrowRight'}); - fireEvent.keyUp(document.activeElement, {key: 'ArrowRight'}); + await user.keyboard('{ArrowRight}'); expect(document.activeElement).toBe(within(toolbar).getAllByRole('button')[2]); - fireEvent.keyDown(document.activeElement, {key: 'Enter'}); - fireEvent.keyUp(document.activeElement, {key: 'Enter'}); + await user.keyboard('{Enter}'); act(() => jest.runAllTimers()); act(() => jest.runAllTimers()); @@ -227,8 +220,7 @@ describe('ActionBar', () => { await user.tab(); expect(document.activeElement).toBe(rows[1]); - fireEvent.keyDown(document.activeElement, {key: 'Enter'}); - fireEvent.keyUp(document.activeElement, {key: 'Enter'}); + await user.keyboard('{Enter}'); expect(checkbox).toBeChecked(); act(() => jest.runAllTimers()); @@ -250,24 +242,20 @@ describe('ActionBar', () => { fireEvent.keyUp(document.activeElement, {key: 'Tab'}); expect(document.activeElement).toBe(within(toolbar).getAllByRole('button')[0]); - fireEvent.keyDown(document.activeElement, {key: 'ArrowRight'}); - fireEvent.keyUp(document.activeElement, {key: 'ArrowRight'}); + await user.keyboard('{ArrowRight}'); - fireEvent.keyDown(document.activeElement, {key: 'ArrowRight'}); - fireEvent.keyUp(document.activeElement, {key: 'ArrowRight'}); + await user.keyboard('{ArrowRight}'); expect(within(toolbar).getAllByRole('button')).toHaveLength(3); expect(document.activeElement).toBe(within(toolbar).getAllByRole('button')[2]); - fireEvent.keyDown(document.activeElement, {key: 'Enter'}); - fireEvent.keyUp(document.activeElement, {key: 'Enter'}); + await user.keyboard('{Enter}'); let listItems = tree.getAllByRole('menuitem'); expect(document.activeElement).toBe(listItems[0]); expect(document.activeElement.textContent).toBe('Delete'); - fireEvent.keyDown(document.activeElement, {key: 'Enter'}); - fireEvent.keyUp(document.activeElement, {key: 'Enter'}); + await user.keyboard('{Enter}'); act(() => jest.runAllTimers()); act(() => jest.runAllTimers()); diff --git a/packages/@react-spectrum/actiongroup/test/ActionGroup.test.js b/packages/@react-spectrum/actiongroup/test/ActionGroup.test.js index 860cc019ae4..c3ba8e4c715 100644 --- a/packages/@react-spectrum/actiongroup/test/ActionGroup.test.js +++ b/packages/@react-spectrum/actiongroup/test/ActionGroup.test.js @@ -349,7 +349,7 @@ describe('ActionGroup', function () { expect(button1).toHaveAttribute('aria-checked', 'true'); expect(button2).toHaveAttribute('aria-checked', 'false'); - fireEvent.keyDown(button1, {key: 'a', ctrlKey: true}); + await user.keyboard('{Control>}{a}{/Control}'); expect(button1).toHaveAttribute('aria-checked', 'true'); expect(button2).toHaveAttribute('aria-checked', 'false'); }); @@ -591,8 +591,7 @@ describe('ActionGroup', function () { let dialog = tree.getByRole('dialog'); expect(dialog).toBeVisible(); - fireEvent.keyDown(dialog, {key: 'Escape'}); - fireEvent.keyUp(dialog, {key: 'Escape'}); + await user.keyboard('{Escape}'); act(() => { jest.runAllTimers(); }); @@ -600,7 +599,7 @@ describe('ActionGroup', function () { expect(tree.queryByRole('dialog')).toBeNull(); }); - it('supports TooltipTrigger as a wrapper around items', function () { + it('supports TooltipTrigger as a wrapper around items', async function () { let tree = render( @@ -615,8 +614,7 @@ describe('ActionGroup', function () { ); let button = tree.getByRole('button'); - fireEvent.keyDown(document.body, {key: 'Tab'}); - fireEvent.keyUp(document.body, {key: 'Tab'}); + await user.keyboard('{Tab}'); act(() => button.focus()); let tooltip = tree.getByRole('tooltip'); diff --git a/packages/@react-spectrum/autocomplete/test/SearchAutocomplete.test.js b/packages/@react-spectrum/autocomplete/test/SearchAutocomplete.test.js index 6564c3b1a99..4534e345a55 100644 --- a/packages/@react-spectrum/autocomplete/test/SearchAutocomplete.test.js +++ b/packages/@react-spectrum/autocomplete/test/SearchAutocomplete.test.js @@ -101,45 +101,43 @@ let initialFilterItems = [ {name: 'Snake', id: '3'} ]; -function testSearchAutocompleteOpen(searchAutocomplete, listbox, focusedItemIndex) { - let searchAutocompleteLabelledBy = searchAutocomplete.getAttribute('aria-labelledby'); - - expect(listbox).toBeVisible(); - expect(listbox).toHaveAttribute('aria-label', 'Suggestions'); - expect(listbox).toHaveAttribute('aria-labelledby', `${listbox.id} ${searchAutocompleteLabelledBy}`); - expect(searchAutocomplete).toHaveAttribute('aria-controls', listbox.id); - expect(searchAutocomplete).toHaveAttribute('aria-expanded', 'true'); - - let items = within(listbox).getAllByRole('option'); - expect(items).toHaveLength(3); - expect(items[0]).toHaveTextContent('One'); - expect(items[1]).toHaveTextContent('Two'); - expect(items[2]).toHaveTextContent('Three'); - - expect(listbox).not.toHaveAttribute('tabIndex'); - for (let item of items) { - expect(item).not.toHaveAttribute('tabIndex'); - } +describe('SearchAutocomplete', function () { + let user; + async function testSearchAutocompleteOpen(searchAutocomplete, listbox, focusedItemIndex) { + let searchAutocompleteLabelledBy = searchAutocomplete.getAttribute('aria-labelledby'); - expect(document.activeElement).toBe(searchAutocomplete); + expect(listbox).toBeVisible(); + expect(listbox).toHaveAttribute('aria-label', 'Suggestions'); + expect(listbox).toHaveAttribute('aria-labelledby', `${listbox.id} ${searchAutocompleteLabelledBy}`); + expect(searchAutocomplete).toHaveAttribute('aria-controls', listbox.id); + expect(searchAutocomplete).toHaveAttribute('aria-expanded', 'true'); - if (typeof focusedItemIndex === 'undefined') { - expect(searchAutocomplete).not.toHaveAttribute('aria-activedescendant'); + let items = within(listbox).getAllByRole('option'); + expect(items).toHaveLength(3); + expect(items[0]).toHaveTextContent('One'); + expect(items[1]).toHaveTextContent('Two'); + expect(items[2]).toHaveTextContent('Three'); - act(() => { - fireEvent.keyDown(searchAutocomplete, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(searchAutocomplete, {key: 'ArrowDown', code: 40, charCode: 40}); - jest.runAllTimers(); - }); + expect(listbox).not.toHaveAttribute('tabIndex'); + for (let item of items) { + expect(item).not.toHaveAttribute('tabIndex'); + } - expect(searchAutocomplete).toHaveAttribute('aria-activedescendant', items[0].id); - } else { - expect(searchAutocomplete).toHaveAttribute('aria-activedescendant', items[focusedItemIndex].id); - } -} + expect(document.activeElement).toBe(searchAutocomplete); -describe('SearchAutocomplete', function () { - let user; + if (typeof focusedItemIndex === 'undefined') { + expect(searchAutocomplete).not.toHaveAttribute('aria-activedescendant'); + + await user.keyboard('{ArrowDown}'); + act(() => { + jest.runAllTimers(); + }); + + expect(searchAutocomplete).toHaveAttribute('aria-activedescendant', items[0].id); + } else { + expect(searchAutocomplete).toHaveAttribute('aria-activedescendant', items[focusedItemIndex].id); + } + } beforeAll(function () { user = userEvent.setup({delay: null, pointerMap}); @@ -210,8 +208,7 @@ describe('SearchAutocomplete', function () { expect(onOpenChange).not.toHaveBeenCalled(); expect(onFocus).not.toHaveBeenCalled(); - fireEvent.keyDown(searchAutocomplete, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(searchAutocomplete, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -237,8 +234,7 @@ describe('SearchAutocomplete', function () { expect(onOpenChange).not.toHaveBeenCalled(); expect(onFocus).toHaveBeenCalled(); - fireEvent.keyDown(searchAutocomplete, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(searchAutocomplete, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -273,8 +269,7 @@ describe('SearchAutocomplete', function () { expect(searchAutocomplete).toHaveAttribute('aria-controls', listbox.id); expect(searchAutocomplete).not.toHaveAttribute('aria-activedescendant'); - fireEvent.keyDown(searchAutocomplete, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(searchAutocomplete, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -334,7 +329,7 @@ describe('SearchAutocomplete', function () { }); describe('keyboard input', function () { - it('opens the menu on down arrow press', function () { + it('opens the menu on down arrow press', async function () { let {getByRole, queryByRole} = renderSearchAutocomplete(); let searchAutocomplete = getByRole('combobox'); @@ -342,8 +337,7 @@ describe('SearchAutocomplete', function () { expect(queryByRole('listbox')).toBeNull(); expect(onOpenChange).not.toHaveBeenCalled(); - fireEvent.keyDown(searchAutocomplete, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(searchAutocomplete, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -354,7 +348,7 @@ describe('SearchAutocomplete', function () { testSearchAutocompleteOpen(searchAutocomplete, listbox, 0); }); - it('opens the menu on up arrow press', function () { + it('opens the menu on up arrow press', async function () { let {getByRole, queryByRole} = renderSearchAutocomplete(); let searchAutocomplete = getByRole('combobox'); @@ -362,8 +356,7 @@ describe('SearchAutocomplete', function () { expect(queryByRole('listbox')).toBeNull(); expect(onOpenChange).not.toHaveBeenCalled(); - fireEvent.keyDown(searchAutocomplete, {key: 'ArrowUp', code: 38, charCode: 38}); - fireEvent.keyUp(searchAutocomplete, {key: 'ArrowUp', code: 38, charCode: 38}); + await user.keyboard('{ArrowUp}'); act(() => { jest.runAllTimers(); }); @@ -520,18 +513,15 @@ describe('SearchAutocomplete', function () { expect(document.activeElement).toBe(searchAutocomplete); expect(searchAutocomplete).not.toHaveAttribute('aria-activedescendant'); - fireEvent.keyDown(searchAutocomplete, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(searchAutocomplete, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); expect(searchAutocomplete).toHaveAttribute('aria-activedescendant', items[0].id); - fireEvent.keyDown(searchAutocomplete, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(searchAutocomplete, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); expect(searchAutocomplete).toHaveAttribute('aria-activedescendant', items[1].id); - fireEvent.keyDown(searchAutocomplete, {key: 'ArrowUp', code: 38, charCode: 38}); - fireEvent.keyUp(searchAutocomplete, {key: 'ArrowUp', code: 38, charCode: 38}); + await user.keyboard('{ArrowUp}'); expect(searchAutocomplete).toHaveAttribute('aria-activedescendant', items[0].id); }); @@ -555,13 +545,11 @@ describe('SearchAutocomplete', function () { expect(document.activeElement).toBe(searchAutocomplete); expect(searchAutocomplete).not.toHaveAttribute('aria-activedescendant'); - fireEvent.keyDown(searchAutocomplete, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(searchAutocomplete, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); expect(searchAutocomplete).toHaveAttribute('aria-activedescendant', items[0].id); - fireEvent.keyDown(searchAutocomplete, {key: 'Enter', code: 13, charCode: 13}); - fireEvent.keyUp(searchAutocomplete, {key: 'Enter', code: 13, charCode: 13}); + await user.keyboard('{Enter}'); act(() => { jest.runAllTimers(); }); @@ -581,10 +569,8 @@ describe('SearchAutocomplete', function () { act(() => { jest.runAllTimers(); }); - fireEvent.keyDown(searchAutocomplete, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(searchAutocomplete, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyDown(searchAutocomplete, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(searchAutocomplete, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); + await user.keyboard('{ArrowDown}'); let listbox = getByRole('listbox'); let items = within(listbox).getAllByRole('option'); @@ -605,13 +591,12 @@ describe('SearchAutocomplete', function () { expect(items[0].textContent).toBe('One'); }); - it('closes menu when pressing Enter on an already selected item', function () { + it('closes menu when pressing Enter on an already selected item', async function () { let {getByRole, queryByRole} = renderSearchAutocomplete(); let searchAutocomplete = getByRole('combobox'); act(() => searchAutocomplete.focus()); - fireEvent.keyDown(searchAutocomplete, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(searchAutocomplete, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -619,8 +604,7 @@ describe('SearchAutocomplete', function () { let listbox = getByRole('listbox'); expect(listbox).toBeTruthy(); - fireEvent.keyDown(searchAutocomplete, {key: 'Enter', code: 13, charCode: 13}); - fireEvent.keyUp(searchAutocomplete, {key: 'Enter', code: 13, charCode: 13}); + await user.keyboard('{Enter}'); act(() => { jest.runAllTimers(); }); @@ -854,8 +838,7 @@ describe('SearchAutocomplete', function () { expect(items).toHaveLength(1); expect(searchAutocomplete).not.toHaveAttribute('aria-activedescendant'); - fireEvent.keyDown(searchAutocomplete, {key: 'ArrowDown'}); - fireEvent.keyUp(searchAutocomplete, {key: 'ArrowDown'}); + await user.keyboard('{ArrowDown}'); expect(searchAutocomplete).toHaveAttribute('aria-activedescendant', items[0].id); @@ -1541,7 +1524,7 @@ describe('SearchAutocomplete', function () { jest.clearAllMocks(); }); - function testSearchAutocompleteTrayOpen(input, tray, listbox, focusedItemIndex) { + async function testSearchAutocompleteTrayOpen(input, tray, listbox, focusedItemIndex) { expect(tray).toBeVisible(); let dialog = within(tray).getByRole('dialog'); @@ -1564,9 +1547,8 @@ describe('SearchAutocomplete', function () { if (typeof focusedItemIndex === 'undefined') { expect(input).not.toHaveAttribute('aria-activedescendant'); + await user.keyboard('{ArrowDown}'); act(() => { - fireEvent.keyDown(input, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(input, {key: 'ArrowDown', code: 40, charCode: 40}); jest.runAllTimers(); }); @@ -1636,7 +1618,7 @@ describe('SearchAutocomplete', function () { let listbox = getByRole('listbox'); let trayInput = within(tray).getByRole('searchbox'); - testSearchAutocompleteTrayOpen(trayInput, tray, listbox); + await testSearchAutocompleteTrayOpen(trayInput, tray, listbox); }); it('closing the tray autofocuses the button', async function () { @@ -1651,10 +1633,7 @@ describe('SearchAutocomplete', function () { let tray = getByTestId('tray'); expect(tray).toBeVisible(); - let input = within(tray).getByRole('searchbox'); - - fireEvent.keyDown(input, {key: 'Escape', code: 27, charCode: 27}); - fireEvent.keyUp(input, {key: 'Escape', code: 27, charCode: 27}); + await user.keyboard('{Escape}'); act(() => { jest.runAllTimers(); }); @@ -1713,17 +1692,15 @@ describe('SearchAutocomplete', function () { let input = within(tray).getByRole('searchbox'); expect(document.activeElement).toBe(input); - fireEvent.keyDown(input, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(input, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); let listbox = getByRole('listbox'); - testSearchAutocompleteTrayOpen(input, tray, listbox, 0); + await testSearchAutocompleteTrayOpen(input, tray, listbox, 0); - fireEvent.keyDown(input, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(input, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -1732,8 +1709,7 @@ describe('SearchAutocomplete', function () { expect(input).toHaveAttribute('aria-activedescendant', items[1].id); - fireEvent.keyDown(input, {key: 'ArrowUp', code: 38, charCode: 38}); - fireEvent.keyUp(input, {key: 'ArrowUp', code: 38, charCode: 38}); + await user.keyboard('{ArrowUp}'); act(() => { jest.runAllTimers(); }); @@ -1755,7 +1731,7 @@ describe('SearchAutocomplete', function () { let listbox = getByRole('listbox'); let trayInput = within(tray).getByRole('searchbox'); - testSearchAutocompleteTrayOpen(trayInput, tray, listbox); + await testSearchAutocompleteTrayOpen(trayInput, tray, listbox); act(() => { trayInput.focus(); }); @@ -1797,7 +1773,7 @@ describe('SearchAutocomplete', function () { expect(() => within(tray).getByLabelText('Clear')).toThrow(); - testSearchAutocompleteTrayOpen(trayInput, tray, listbox); + await testSearchAutocompleteTrayOpen(trayInput, tray, listbox); act(() => { trayInput.focus(); }); @@ -1838,7 +1814,7 @@ describe('SearchAutocomplete', function () { let listbox = getByRole('listbox'); let trayInput = within(tray).getByRole('searchbox'); - testSearchAutocompleteTrayOpen(trayInput, tray, listbox); + await testSearchAutocompleteTrayOpen(trayInput, tray, listbox); act(() => { trayInput.focus(); }); @@ -1883,7 +1859,7 @@ describe('SearchAutocomplete', function () { expect(tray).toBeVisible(); let listbox = getByRole('listbox'); let trayInput = within(tray).getByRole('searchbox'); - testSearchAutocompleteTrayOpen(trayInput, tray, listbox); + await testSearchAutocompleteTrayOpen(trayInput, tray, listbox); let items = within(tray).getAllByRole('option'); @@ -1930,8 +1906,7 @@ describe('SearchAutocomplete', function () { let trayInput = within(tray).getByRole('searchbox'); - fireEvent.keyDown(trayInput, {key: 'ArrowUp', code: 38, charCode: 38}); - fireEvent.keyUp(trayInput, {key: 'ArrowUp', code: 38, charCode: 38}); + await user.keyboard('{ArrowUp}'); act(() => { jest.runAllTimers(); }); @@ -1939,10 +1914,9 @@ describe('SearchAutocomplete', function () { expect(onOpenChange).toHaveBeenCalledWith(true, 'manual'); expect(onOpenChange).toHaveBeenCalledTimes(1); - testSearchAutocompleteTrayOpen(trayInput, tray, listbox, 2); + await testSearchAutocompleteTrayOpen(trayInput, tray, listbox, 2); - fireEvent.keyDown(trayInput, {key: 'Enter', code: 13, charCode: 13}); - fireEvent.keyUp(trayInput, {key: 'Enter', code: 13, charCode: 13}); + await user.keyboard('{Enter}'); act(() => { jest.runAllTimers(); }); @@ -3006,8 +2980,7 @@ describe('SearchAutocomplete', function () { expect(listbox).toBeVisible(); expect(searchAutocomplete).toHaveAttribute('aria-controls', listbox.id); - fireEvent.keyDown(searchAutocomplete, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(searchAutocomplete, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -3017,24 +2990,21 @@ describe('SearchAutocomplete', function () { expect(items[0]).toHaveTextContent('One'); expect(searchAutocomplete).toHaveAttribute('aria-activedescendant', items[0].id); - fireEvent.keyDown(searchAutocomplete, {key: 'ArrowLeft', code: 37, charCode: 37}); - fireEvent.keyUp(searchAutocomplete, {key: 'ArrowLeft', code: 37, charCode: 37}); + await user.keyboard('{ArrowLeft}'); act(() => { jest.runAllTimers(); }); expect(searchAutocomplete).not.toHaveAttribute('aria-activedescendant'); - fireEvent.keyDown(searchAutocomplete, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(searchAutocomplete, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); expect(searchAutocomplete).toHaveAttribute('aria-activedescendant', items[0].id); - fireEvent.keyDown(searchAutocomplete, {key: 'ArrowRight', code: 39, charCode: 39}); - fireEvent.keyUp(searchAutocomplete, {key: 'ArrowRight', code: 39, charCode: 39}); + await user.keyboard('{ArrowRight}'); act(() => { jest.runAllTimers(); }); @@ -3055,20 +3025,17 @@ describe('SearchAutocomplete', function () { }); describe('keyboard navigating', function () { - it('should announce items when navigating with the arrow keys', function () { - let {getByRole} = renderSearchAutocomplete(); - let searchAutocomplete = getByRole('combobox'); - - fireEvent.keyDown(searchAutocomplete, {key: 'ArrowDown'}); - fireEvent.keyUp(searchAutocomplete, {key: 'ArrowDown'}); + it('should announce items when navigating with the arrow keys', async function () { + renderSearchAutocomplete(); + await user.tab(); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); expect(announce).toHaveBeenLastCalledWith('One'); - fireEvent.keyDown(searchAutocomplete, {key: 'ArrowDown'}); - fireEvent.keyUp(searchAutocomplete, {key: 'ArrowDown'}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -3076,20 +3043,21 @@ describe('SearchAutocomplete', function () { expect(announce).toHaveBeenLastCalledWith('Two'); }); - it('should announce when navigating into a section with multiple items', function () { + it('should announce when navigating into a section with multiple items', async function () { let {getByRole} = renderSectionSearchAutocomplete(); let searchAutocomplete = getByRole('combobox'); + act(() => { + searchAutocomplete.focus(); + }); - fireEvent.keyDown(searchAutocomplete, {key: 'ArrowDown'}); - fireEvent.keyUp(searchAutocomplete, {key: 'ArrowDown'}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); expect(announce).toHaveBeenLastCalledWith('Entered group Section One, with 3 options. One'); - fireEvent.keyDown(searchAutocomplete, {key: 'ArrowDown'}); - fireEvent.keyUp(searchAutocomplete, {key: 'ArrowDown'}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -3103,13 +3071,11 @@ describe('SearchAutocomplete', function () { act(() => { searchAutocomplete.focus(); }); - await user.keyboard('o'); act(() => { jest.runAllTimers(); }); - fireEvent.keyDown(searchAutocomplete, {key: 'ArrowDown'}); - fireEvent.keyUp(searchAutocomplete, {key: 'ArrowDown'}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -3125,7 +3091,6 @@ describe('SearchAutocomplete', function () { act(() => { searchAutocomplete.focus(); }); - await user.keyboard('o'); act(() => { jest.runAllTimers(); @@ -3158,23 +3123,24 @@ describe('SearchAutocomplete', function () { }); describe('selection', function () { - it('should announce when a selection occurs', function () { + it('should announce when a selection occurs', async function () { let {getByRole} = renderSearchAutocomplete(); let searchAutocomplete = getByRole('combobox'); + act(() => { + searchAutocomplete.focus(); + }); act(() => { searchAutocomplete.focus(); }); - fireEvent.keyDown(searchAutocomplete, {key: 'ArrowDown'}); - fireEvent.keyUp(searchAutocomplete, {key: 'ArrowDown'}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); expect(announce).toHaveBeenLastCalledWith('One'); - fireEvent.keyDown(searchAutocomplete, {key: 'Enter'}); - fireEvent.keyUp(searchAutocomplete, {key: 'Enter'}); + await user.keyboard('{Enter}'); act(() => { jest.runAllTimers(); }); @@ -3185,7 +3151,7 @@ describe('SearchAutocomplete', function () { }); describe('hiding surrounding content', function () { - it('should hide elements outside the searchAutocomplete with aria-hidden', function () { + it('should hide elements outside the searchAutocomplete with aria-hidden', async function () { let {getByRole, queryAllByRole, getAllByRole} = render( <> @@ -3202,8 +3168,7 @@ describe('SearchAutocomplete', function () { act(() => { searchAutocomplete.focus(); }); - fireEvent.keyDown(searchAutocomplete, {key: 'ArrowDown'}); - fireEvent.keyUp(searchAutocomplete, {key: 'ArrowDown'}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -3217,7 +3182,7 @@ describe('SearchAutocomplete', function () { expect(getByRole('combobox')).toBeVisible(); }); - it('should not traverse into a hidden container', function () { + it('should not traverse into a hidden container', async function () { let {getByRole, queryAllByRole, getAllByRole} = render( <>
@@ -3233,12 +3198,9 @@ describe('SearchAutocomplete', function () { expect(outside).toHaveLength(2); - act(() => { - searchAutocomplete.focus(); - fireEvent.keyDown(searchAutocomplete, {key: 'ArrowDown'}); - fireEvent.keyUp(searchAutocomplete, {key: 'ArrowDown'}); - jest.runAllTimers(); - }); + act(() => searchAutocomplete.focus()); + await user.keyboard('{ArrowDown}'); + act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); expect(listbox).toBeVisible(); @@ -3250,7 +3212,7 @@ describe('SearchAutocomplete', function () { expect(getByRole('combobox')).toBeVisible(); }); - it('should not hide the live announcer element', function () { + it('should not hide the live announcer element', async function () { let platformMock = jest.spyOn(navigator, 'platform', 'get').mockImplementation(() => 'MacIntel'); let {getByRole} = render(); @@ -3260,12 +3222,9 @@ describe('SearchAutocomplete', function () { let searchAutocomplete = getByRole('combobox'); - act(() => { - searchAutocomplete.focus(); - fireEvent.keyDown(searchAutocomplete, {key: 'ArrowDown'}); - fireEvent.keyUp(searchAutocomplete, {key: 'ArrowDown'}); - jest.runAllTimers(); - }); + act(() => searchAutocomplete.focus()); + await user.keyboard('{ArrowDown}'); + act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); expect(listbox).toBeVisible(); @@ -3286,12 +3245,9 @@ describe('SearchAutocomplete', function () { let searchAutocomplete = getByRole('combobox'); - act(() => { - searchAutocomplete.focus(); - fireEvent.keyDown(searchAutocomplete, {key: 'ArrowDown'}); - fireEvent.keyUp(searchAutocomplete, {key: 'ArrowDown'}); - jest.runAllTimers(); - }); + act(() => searchAutocomplete.focus()); + await user.keyboard('{ArrowDown}'); + act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); expect(listbox).toBeVisible(); @@ -3323,12 +3279,9 @@ describe('SearchAutocomplete', function () { let searchAutocomplete = getByRole('combobox'); let outer = getByTestId('test'); - act(() => { - searchAutocomplete.focus(); - fireEvent.keyDown(searchAutocomplete, {key: 'ArrowDown'}); - fireEvent.keyUp(searchAutocomplete, {key: 'ArrowDown'}); - jest.runAllTimers(); - }); + act(() => searchAutocomplete.focus()); + await user.keyboard('{ArrowDown}'); + act(() => jest.runAllTimers()); let listbox = getByRole('listbox'); @@ -3369,8 +3322,7 @@ describe('SearchAutocomplete', function () { act(() => { searchAutocomplete.focus(); }); - fireEvent.keyDown(searchAutocomplete, {key: 'ArrowDown'}); - fireEvent.keyUp(searchAutocomplete, {key: 'ArrowDown'}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); diff --git a/packages/@react-spectrum/button/test/Button.test.js b/packages/@react-spectrum/button/test/Button.test.js index cfae5902263..5fa00649296 100644 --- a/packages/@react-spectrum/button/test/Button.test.js +++ b/packages/@react-spectrum/button/test/Button.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render} from '@react-spectrum/test-utils'; +import {act, pointerMap, render} from '@react-spectrum/test-utils'; import {ActionButton, Button, ClearButton, LogicButton} from '../'; import {Checkbox, defaultTheme} from '@adobe/react-spectrum'; import {Form} from '@react-spectrum/form'; @@ -183,12 +183,10 @@ describe('Button', function () { await user.click(button); expect(onPressSpy).toHaveBeenCalledTimes(1); - fireEvent.keyDown(button, {key: 'Enter', code: 13}); - fireEvent.keyUp(button, {key: 'Enter', code: 13}); + await user.keyboard('{Enter}'); expect(onPressSpy).toHaveBeenCalledTimes(2); - fireEvent.keyDown(button, {key: ' ', code: 32}); - fireEvent.keyUp(button, {key: ' ', code: 32}); + await user.keyboard('[Space]'); expect(onPressSpy).toHaveBeenCalledTimes(3); }); @@ -235,7 +233,7 @@ describe('Button', function () { }); - it('prevents default for non-submit types', function () { + it('prevents default for non-submit types', async function () { let eventDown; let eventUp; let btn = React.createRef(); @@ -253,20 +251,19 @@ describe('Button', function () { btn.current.UNSAFE_getDOMNode().addEventListener('keyup', e => eventUp = e); let button = getByRole('button'); - fireEvent.keyDown(button, {key: 'Enter'}); - fireEvent.keyUp(button, {key: 'Enter'}); + act(() => button.focus()); + await user.keyboard('{Enter}'); expect(eventDown.defaultPrevented).toBeTruthy(); expect(eventUp.defaultPrevented).toBeTruthy(); - fireEvent.keyDown(button, {key: ' '}); - fireEvent.keyUp(button, {key: ' '}); + await user.keyboard('[Space]'); expect(eventDown.defaultPrevented).toBeTruthy(); expect(eventUp.defaultPrevented).toBeTruthy(); }); // we only need to test that we allow the browser to do the default thing when space or enter is pressed on a submit button // space submits on key up and is actually a click - it('submit in form using space', function () { + it('submit in form using space', async function () { let eventUp; let btn = React.createRef(); let {getByRole} = render( @@ -280,13 +277,13 @@ describe('Button', function () { btn.current.UNSAFE_getDOMNode().addEventListener('keyup', e => eventUp = e); let button = getByRole('button'); - fireEvent.keyDown(button, {key: ' '}); - fireEvent.keyUp(button, {key: ' '}); + act(() => button.focus()); + await user.keyboard('{Space}'); expect(eventUp.defaultPrevented).toBeFalsy(); }); // enter submits on keydown - it('submit in form using enter', function () { + it('submit in form using enter', async function () { let eventDown; let btn = React.createRef(); let {getByRole} = render( @@ -297,11 +294,14 @@ describe('Button', function () { ); - btn.current.UNSAFE_getDOMNode().addEventListener('keydown', e => eventDown = e); - + btn.current.UNSAFE_getDOMNode().addEventListener('keydown', e => { + eventDown = {...e}; + // Prevent default to avoid "Error: Not implemented: HTMLFormElement.prototype.requestSubmit" + e.preventDefault(); + }); let button = getByRole('button'); - fireEvent.keyDown(button, {key: 'Enter'}); - fireEvent.keyUp(button, {key: 'Enter'}); + act(() => button.focus()); + await user.keyboard('[Enter]'); expect(eventDown.defaultPrevented).toBeFalsy(); }); diff --git a/packages/@react-spectrum/calendar/test/Calendar.test.js b/packages/@react-spectrum/calendar/test/Calendar.test.js index ebfcbda31e3..b1c6dda838f 100644 --- a/packages/@react-spectrum/calendar/test/Calendar.test.js +++ b/packages/@react-spectrum/calendar/test/Calendar.test.js @@ -16,13 +16,11 @@ jest.mock('@react-aria/live-announcer'); import {announce} from '@react-aria/live-announcer'; import {Calendar} from '../'; import {CalendarDate, isWeekend} from '@internationalized/date'; -import {fireEvent, pointerMap, render} from '@react-spectrum/test-utils'; +import {pointerMap, render} from '@react-spectrum/test-utils'; import React from 'react'; import {useLocale} from '@react-aria/i18n'; import userEvent from '@testing-library/user-event'; -let keyCodes = {'Enter': 13, ' ': 32, 'PageUp': 33, 'PageDown': 34, 'End': 35, 'Home': 36, 'ArrowLeft': 37, 'ArrowUp': 38, 'ArrowRight': 39, 'ArrowDown': 40}; - describe('Calendar', () => { beforeAll(() => { jest.useFakeTimers(); @@ -114,29 +112,29 @@ describe('Calendar', () => { it.each` Name | Calendar ${'v3'} | ${Calendar} - `('$Name selects a date on keyDown Enter/Space (uncontrolled)', ({Calendar}) => { + `('$Name selects a date on keyDown Enter/Space (uncontrolled)', async ({Calendar}) => { + let user = userEvent.setup({delay: null, pointerMap}); let onChange = jest.fn(); - let {getByLabelText, getByRole} = render( + let {getByLabelText} = render( ); - let grid = getByRole('grid'); let selectedDate = getByLabelText('selected', {exact: false}); expect(selectedDate.textContent).toBe('5'); // Select a new date - fireEvent.keyDown(grid, {key: 'ArrowLeft', keyCode: keyCodes.ArrowLeft}); - fireEvent.keyDown(grid, {key: 'Enter', keyCode: keyCodes.Enter}); + await user.keyboard('{ArrowLeft}'); + await user.keyboard('{Enter}'); selectedDate = getByLabelText('selected', {exact: false}); expect(selectedDate.textContent).toBe('4'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange.mock.calls[0][0]).toEqual(new CalendarDate(2019, 6, 4)); - fireEvent.keyDown(grid, {key: 'ArrowLeft', keyCode: keyCodes.ArrowLeft}); - fireEvent.keyDown(grid, {key: ' ', keyCode: keyCodes[' ']}); + await user.keyboard('{ArrowLeft}'); + await user.keyboard('[Space]'); selectedDate = getByLabelText('selected', {exact: false}); expect(selectedDate.textContent).toBe('3'); expect(onChange).toHaveBeenCalledTimes(2); @@ -146,29 +144,29 @@ describe('Calendar', () => { it.each` Name | Calendar ${'v3'} | ${Calendar} - `('$Name selects a date on keyDown Enter/Space (controlled)', ({Calendar}) => { + `('$Name selects a date on keyDown Enter/Space (controlled)', async ({Calendar}) => { + let user = userEvent.setup({delay: null, pointerMap}); let onChange = jest.fn(); - let {getByLabelText, getByRole} = render( + let {getByLabelText} = render( ); - let grid = getByRole('grid'); let selectedDate = getByLabelText('selected', {exact: false}); expect(selectedDate.textContent).toBe('5'); // Select a new date - fireEvent.keyDown(grid, {key: 'ArrowLeft', keyCode: keyCodes.ArrowLeft}); - fireEvent.keyDown(grid, {key: 'Enter', keyCode: keyCodes.Enter}); + await user.keyboard('{ArrowLeft}'); + await user.keyboard('{Enter}'); selectedDate = getByLabelText('selected', {exact: false}); expect(selectedDate.textContent).toBe('5'); // controlled expect(onChange).toHaveBeenCalledTimes(1); expect(onChange.mock.calls[0][0]).toEqual(new CalendarDate(2019, 6, 4)); - fireEvent.keyDown(grid, {key: 'ArrowLeft', keyCode: keyCodes.ArrowLeft}); - fireEvent.keyDown(grid, {key: ' ', keyCode: keyCodes[' ']}); + await user.keyboard('{ArrowLeft}'); + await user.keyboard('[Space]'); selectedDate = getByLabelText('selected', {exact: false}); expect(selectedDate.textContent).toBe('5'); // controlled expect(onChange).toHaveBeenCalledTimes(2); @@ -178,7 +176,8 @@ describe('Calendar', () => { it.each` Name | Calendar | props ${'v3'} | ${Calendar} | ${{isReadOnly: true}} - `('$Name does not select a date on keyDown Enter/Space if isReadOnly', ({Calendar, props}) => { + `('$Name does not select a date on keyDown Enter/Space if isReadOnly', async ({Calendar, props}) => { + let user = userEvent.setup({delay: null, pointerMap}); let onChange = jest.fn(); let {getByLabelText} = render( { let selectedDate = getByLabelText('selected', {exact: false}); expect(selectedDate.textContent).toBe('5'); - fireEvent.keyDown(document.activeElement, {key: 'ArrowLeft', keyCode: keyCodes.ArrowLeft}); - fireEvent.keyDown(document.activeElement, {key: 'Enter', keyCode: keyCodes.Enter}); + await user.keyboard('{ArrowLeft}'); + await user.keyboard('{Enter}'); selectedDate = getByLabelText('selected', {exact: false}); expect(selectedDate.textContent).toBe('5'); expect(onChange).not.toHaveBeenCalled(); - fireEvent.keyDown(document.activeElement, {key: 'ArrowLeft', keyCode: keyCodes.ArrowLeft}); - fireEvent.keyDown(document.activeElement, {key: ' ', keyCode: keyCodes[' ']}); + await user.keyboard('{ArrowLeft}'); + await user.keyboard('[Space]'); selectedDate = getByLabelText('selected', {exact: false}); expect(selectedDate.textContent).toBe('5'); expect(onChange).not.toHaveBeenCalled(); @@ -420,15 +419,14 @@ describe('Calendar', () => { expect(announce).toHaveBeenCalledWith('Selected Date: Monday, June 17, 2019', 'polite', 4000); }); - it('ensures that the active descendant is announced when the focused date changes', () => { - let {getByRole, getByLabelText} = render(); + it('ensures that the active descendant is announced when the focused date changes', async () => { + let user = userEvent.setup({delay: null, pointerMap}); + let {getByLabelText} = render(); - let grid = getByRole('grid'); let selectedDate = getByLabelText('selected', {exact: false}); expect(selectedDate).toHaveFocus(); - fireEvent.keyDown(grid, {key: 'ArrowRight'}); - fireEvent.keyUp(document.activeElement, {key: 'ArrowRight'}); + await user.keyboard('{ArrowRight}'); act(() => {jest.runAllTimers();}); expect(getByLabelText('Thursday, June 6, 2019', {exact: false})).toHaveFocus(); }); diff --git a/packages/@react-spectrum/calendar/test/CalendarBase.test.js b/packages/@react-spectrum/calendar/test/CalendarBase.test.js index 07be131880f..23923372e0b 100644 --- a/packages/@react-spectrum/calendar/test/CalendarBase.test.js +++ b/packages/@react-spectrum/calendar/test/CalendarBase.test.js @@ -20,7 +20,6 @@ import userEvent from '@testing-library/user-event'; let cellFormatter = new Intl.DateTimeFormat('en-US', {weekday: 'long', day: 'numeric', month: 'long', year: 'numeric'}); let headingFormatter = new Intl.DateTimeFormat('en-US', {month: 'long', year: 'numeric'}); -let keyCodes = {'Enter': 13, ' ': 32, 'PageUp': 33, 'PageDown': 34, 'End': 35, 'Home': 36, 'ArrowLeft': 37, 'ArrowUp': 38, 'ArrowRight': 39, 'ArrowDown': 40}; describe('CalendarBase', () => { let user; @@ -106,7 +105,7 @@ describe('CalendarBase', () => { Name | Calendar | props ${'v3 Calendar'} | ${Calendar} | ${{}} ${'v3 RangeCalendar'} | ${RangeCalendar} | ${{}} - `('$Name should focus today if autoFocus is set and there is no selected value', ({Name, Calendar}) => { + `('$Name should focus today if autoFocus is set and there is no selected value', ({Calendar}) => { let {getByLabelText} = render(); let cell = getByLabelText('today', {exact: false}); @@ -325,7 +324,7 @@ describe('CalendarBase', () => { Name | Calendar | props ${'v3 Calendar'} | ${Calendar} | ${{defaultValue: new CalendarDate(2019, 6, 5)}} ${'v3 RangeCalendar'} | ${RangeCalendar} | ${{defaultValue: {start: new CalendarDate(2019, 6, 5), end: new CalendarDate(2019, 6, 10)}}} - `('$Name should change the month when keyboard navigating and multiple months are visible', ({Calendar, props}) => { + `('$Name should change the month when keyboard navigating and multiple months are visible', async ({Calendar, props}) => { let {getAllByRole, getByLabelText} = render(); let grids = getAllByRole('grid'); @@ -335,7 +334,7 @@ describe('CalendarBase', () => { expect(grids[2]).toHaveAttribute('aria-label', 'July 2019'); act(() => getByLabelText('Wednesday, July 31, 2019').focus()); - fireEvent.keyDown(document.activeElement, {key: 'ArrowRight'}); + await user.keyboard('{ArrowRight}'); grids = getAllByRole('grid'); expect(grids).toHaveLength(3); @@ -343,7 +342,7 @@ describe('CalendarBase', () => { expect(grids[1]).toHaveAttribute('aria-label', 'September 2019'); expect(grids[2]).toHaveAttribute('aria-label', 'October 2019'); - fireEvent.keyDown(document.activeElement, {key: 'ArrowLeft'}); + await user.keyboard('{ArrowLeft}'); grids = getAllByRole('grid'); expect(grids).toHaveLength(3); @@ -391,7 +390,7 @@ describe('CalendarBase', () => { Name | Calendar ${'v3 Calendar'} | ${Calendar} ${'v3 RangeCalendar'} | ${RangeCalendar} - `('$Name should support defaultFocusedValue', ({Calendar}) => { + `('$Name should support defaultFocusedValue', async ({Calendar}) => { let onFocusChange = jest.fn(); let {getByRole} = render(); @@ -399,8 +398,7 @@ describe('CalendarBase', () => { expect(grid).toHaveAttribute('aria-label', 'June 2019'); expect(document.activeElement.getAttribute('aria-label').startsWith('Wednesday, June 5, 2019')).toBe(true); - fireEvent.keyDown(document.activeElement, {key: 'ArrowRight'}); - fireEvent.keyUp(document.activeElement, {key: 'ArrowRight'}); + await user.keyboard('{ArrowRight}'); expect(document.activeElement.getAttribute('aria-label').startsWith('Thursday, June 6, 2019')).toBe(true); expect(onFocusChange).toHaveBeenCalledWith(new CalendarDate(2019, 6, 6)); }); @@ -409,7 +407,7 @@ describe('CalendarBase', () => { Name | Calendar ${'v3 Calendar'} | ${Calendar} ${'v3 RangeCalendar'} | ${RangeCalendar} - `('$Name should support controlled focusedValue', ({Calendar}) => { + `('$Name should support controlled focusedValue', async ({Calendar}) => { let onFocusChange = jest.fn(); let {getByRole} = render(); @@ -417,8 +415,7 @@ describe('CalendarBase', () => { expect(grid).toHaveAttribute('aria-label', 'June 2019'); expect(document.activeElement.getAttribute('aria-label').startsWith('Wednesday, June 5, 2019')).toBe(true); - fireEvent.keyDown(document.activeElement, {key: 'ArrowRight'}); - fireEvent.keyUp(document.activeElement, {key: 'ArrowRight'}); + await user.keyboard('{ArrowRight}'); expect(document.activeElement.getAttribute('aria-label').startsWith('Wednesday, June 5, 2019')).toBe(true); expect(onFocusChange).toHaveBeenCalledWith(new CalendarDate(2019, 6, 6)); }); @@ -614,8 +611,13 @@ describe('CalendarBase', () => { expect(grid).not.toHaveAttribute('aria-activedescendant'); expect(document.activeElement).toBe(cell); - fireEvent.keyDown(document.activeElement, {key, keyCode: keyCodes[key], ...opts}); - fireEvent.keyUp(document.activeElement, {key, keyCode: keyCodes[key], ...opts}); + if (opts?.shiftKey) { + await user.keyboard('{Shift>}'); + } + await user.keyboard(`[${key}]`); + if (opts?.shiftKey) { + await user.keyboard('{/Shift}'); + } expect(grid).not.toHaveAttribute('aria-activedescendant'); expect(document.activeElement.getAttribute('aria-label')).toMatch(value); @@ -748,7 +750,7 @@ describe('CalendarBase', () => { Name | Calendar | props ${'v3 Calendar'} | ${Calendar} | ${{defaultValue: new CalendarDate(2019, 6, 5)}} ${'v3 RangeCalendar'} | ${RangeCalendar} | ${{defaultValue: {start: new CalendarDate(2019, 6, 5), end: new CalendarDate(2019, 6, 10)}}} - `('$Name should mirror arrow key movement in an RTL locale', ({Calendar, props}) => { + `('$Name should mirror arrow key movement in an RTL locale', async ({Calendar, props}) => { // LTR let {getByRole, getAllByRole, rerender} = render( @@ -760,10 +762,10 @@ describe('CalendarBase', () => { let selected = getAllByRole('button').find(cell => cell.getAttribute('tabIndex') === '0'); expect(document.activeElement).toBe(selected); - fireEvent.keyDown(grid, {key: 'ArrowLeft'}); + await user.keyboard('{ArrowLeft}'); expect(document.activeElement).toBe(selected.parentNode.previousSibling.children[0]); - fireEvent.keyDown(grid, {key: 'ArrowRight'}); + await user.keyboard('{ArrowRight}'); expect(document.activeElement).toBe(selected); // RTL @@ -780,11 +782,11 @@ describe('CalendarBase', () => { selected = getAllByRole('button').find(cell => cell.getAttribute('tabIndex') === '0'); expect(document.activeElement).toBe(selected); - fireEvent.keyDown(grid, {key: 'ArrowLeft'}); + await user.keyboard('{ArrowLeft}'); expect(document.activeElement).toBe(selected.parentNode.nextSibling.children[0]); - fireEvent.keyDown(grid, {key: 'ArrowRight'}); + await user.keyboard('{ArrowRight}'); expect(document.activeElement).toBe(selected); }); }); diff --git a/packages/@react-spectrum/calendar/test/RangeCalendar.test.js b/packages/@react-spectrum/calendar/test/RangeCalendar.test.js index 8915d9a1deb..9332c1a2cf4 100644 --- a/packages/@react-spectrum/calendar/test/RangeCalendar.test.js +++ b/packages/@react-spectrum/calendar/test/RangeCalendar.test.js @@ -20,12 +20,6 @@ import {useLocale} from '@react-aria/i18n'; import userEvent from '@testing-library/user-event'; let cellFormatter = new Intl.DateTimeFormat('en-US', {weekday: 'long', day: 'numeric', month: 'long', year: 'numeric'}); -let keyCodes = {'Enter': 13, ' ': 32, 'PageUp': 33, 'PageDown': 34, 'End': 35, 'Home': 36, 'ArrowLeft': 37, 'ArrowUp': 38, 'ArrowRight': 39, 'ArrowDown': 40, Escape: 27}; - -function type(key) { - fireEvent.keyDown(document.activeElement, {key}); - fireEvent.keyUp(document.activeElement, {key}); -} describe('RangeCalendar', () => { let user; @@ -248,7 +242,7 @@ describe('RangeCalendar', () => { expect(document.getElementById(cell.getAttribute('aria-describedby'))).toHaveTextContent('Click to start selecting date range'); // enter selection mode - fireEvent.keyDown(grid, {key: 'Enter', keyCode: keyCodes.Enter}); + fireEvent.keyDown(grid, {key: 'Enter'}); expect(grid).not.toHaveAttribute('aria-activedescendant'); expect(cell.parentElement).toHaveAttribute('aria-selected'); expect(cell).toHaveAttribute('aria-label', `Today, ${cellFormatter.format(new Date())} selected`); @@ -259,7 +253,7 @@ describe('RangeCalendar', () => { it.each` Name | RangeCalendar | props ${'v3'} | ${RangeCalendar} | ${{defaultValue: {start: new CalendarDate(2019, 6, 5), end: new CalendarDate(2019, 6, 10)}}} - `('$Name can select a range with the keyboard (uncontrolled)', ({RangeCalendar, props}) => { + `('$Name can select a range with the keyboard (uncontrolled)', async ({RangeCalendar, props}) => { let onChange = jest.fn(); let {getAllByLabelText} = render( { expect(selectedDates[selectedDates.length - 1].textContent).toBe('10'); // Select a new date - type('ArrowLeft'); + await user.keyboard('{ArrowLeft}'); // Begin selecting - type('Enter'); + await user.keyboard('{Enter}'); // Auto advances by one day selectedDates = getAllByLabelText('selected', {exact: false}); @@ -285,10 +279,10 @@ describe('RangeCalendar', () => { expect(onChange).toHaveBeenCalledTimes(0); // Move focus - type('ArrowRight'); - type('ArrowRight'); - type('ArrowRight'); - type('ArrowRight'); + await user.keyboard('{ArrowRight}'); + await user.keyboard('{ArrowRight}'); + await user.keyboard('{ArrowRight}'); + await user.keyboard('{ArrowRight}'); selectedDates = getAllByLabelText('selected', {exact: false}); expect(selectedDates[0].textContent).toBe('4'); @@ -296,7 +290,7 @@ describe('RangeCalendar', () => { expect(onChange).toHaveBeenCalledTimes(0); // End selection - type(' '); + await user.keyboard('[Space]'); selectedDates = getAllByLabelText('selected', {exact: false}); expect(selectedDates[0].textContent).toBe('4'); // uncontrolled expect(selectedDates[selectedDates.length - 1].textContent).toBe('9'); @@ -310,7 +304,7 @@ describe('RangeCalendar', () => { it.each` Name | RangeCalendar | props ${'v3'} | ${RangeCalendar} | ${{value: {start: new CalendarDate(2019, 6, 5), end: new CalendarDate(2019, 6, 10)}}} - `('$Name can select a range with the keyboard (controlled)', ({RangeCalendar, props}) => { + `('$Name can select a range with the keyboard (controlled)', async ({RangeCalendar, props}) => { let onChange = jest.fn(); let {getAllByLabelText} = render( { expect(selectedDates[selectedDates.length - 1].textContent).toBe('10'); // Select a new date - type('ArrowLeft'); + await user.keyboard('{ArrowLeft}'); // Begin selecting - type('Enter'); + await user.keyboard('{Enter}'); // Auto advances by one day selectedDates = getAllByLabelText('selected', {exact: false}); @@ -336,10 +330,10 @@ describe('RangeCalendar', () => { expect(onChange).toHaveBeenCalledTimes(0); // Move focus - type('ArrowRight'); - type('ArrowRight'); - type('ArrowRight'); - type('ArrowRight'); + await user.keyboard('{ArrowRight}'); + await user.keyboard('{ArrowRight}'); + await user.keyboard('{ArrowRight}'); + await user.keyboard('{ArrowRight}'); selectedDates = getAllByLabelText('selected', {exact: false}); expect(selectedDates[0].textContent).toBe('4'); @@ -347,7 +341,7 @@ describe('RangeCalendar', () => { expect(onChange).toHaveBeenCalledTimes(0); // End selection - type(' '); + await user.keyboard('[Space]'); selectedDates = getAllByLabelText('selected', {exact: false}); expect(selectedDates[0].textContent).toBe('5'); // controlled expect(selectedDates[selectedDates.length - 1].textContent).toBe('10'); @@ -358,7 +352,7 @@ describe('RangeCalendar', () => { expect(end).toEqual(new CalendarDate(2019, 6, 9)); }); - it('does not enter selection mode with the keyboard if isReadOnly', () => { + it('does not enter selection mode with the keyboard if isReadOnly', async () => { let {getByRole, getByLabelText} = render(); let grid = getByRole('grid'); @@ -368,7 +362,7 @@ describe('RangeCalendar', () => { expect(document.activeElement).toBe(cell); // try to enter selection mode - fireEvent.keyDown(grid, {key: 'Enter', keyCode: keyCodes.Enter}); + await user.keyboard('{Enter}'); expect(grid).not.toHaveAttribute('aria-activedescendant'); expect(cell.parentElement).not.toHaveAttribute('aria-selected'); expect(cell).toHaveAttribute('aria-label', `Today, ${cellFormatter.format(new Date())}`); @@ -1017,7 +1011,7 @@ describe('RangeCalendar', () => { expect(onChange).not.toHaveBeenCalled(); // Cancel - type('Escape'); + await user.keyboard('{Escape}'); // Should revert selection selectedDates = getAllByLabelText('selected', {exact: false}); @@ -1159,7 +1153,7 @@ describe('RangeCalendar', () => { expect(cell).toHaveAttribute('aria-disabled', 'true'); }); - it('advances selection backwards when starting a selection at the end of an available range', () => { + it('advances selection backwards when starting a selection at the end of an available range', async () => { const isDateUnavailable = (date) => { const disabledIntervals = [[new CalendarDate(2021, 12, 6), new CalendarDate(2021, 12, 10)], [new CalendarDate(2021, 12, 22), new CalendarDate(2021, 12, 26)]]; return disabledIntervals.some((interval) => date.compare(interval[0]) >= 0 && date.compare(interval[1]) <= 0); @@ -1173,7 +1167,7 @@ describe('RangeCalendar', () => { let cell = getByRole('button', {name: 'Tuesday, December 21, 2021'}); act(() => cell.focus()); - act(() => type('Enter')); + await user.keyboard('{Enter}'); let cell2 = getByRole('button', {name: /Monday, December 20, 2021/}); expect(document.activeElement).toBe(cell2); @@ -1229,7 +1223,7 @@ describe('RangeCalendar', () => { await user.click(cell); expect(cell.parentElement).toHaveAttribute('aria-selected', 'true'); - act(() => type('PageDown')); + await user.keyboard('{PageDown}'); cell = getByRole('button', {name: 'Saturday, April 9, 2022'}); expect(document.activeElement).toBe(cell); @@ -1353,13 +1347,13 @@ describe('RangeCalendar', () => { expect(announce).toHaveBeenCalledWith('Selected Range: Monday, June 10 to Monday, June 17, 2019', 'polite', 4000); }); - it('ensures that the active descendant is announced when the focused date changes', () => { + it('ensures that the active descendant is announced when the focused date changes', async () => { let {getAllByLabelText} = render(); let selectedDates = getAllByLabelText('selected', {exact: false}); expect(selectedDates[0]).toHaveFocus(); - type('ArrowRight'); + await user.keyboard('{ArrowRight}'); expect(selectedDates[1]).toHaveFocus(); }); diff --git a/packages/@react-spectrum/card/test/CardView.test.js b/packages/@react-spectrum/card/test/CardView.test.js index abb340fe612..b7fcfea1382 100644 --- a/packages/@react-spectrum/card/test/CardView.test.js +++ b/packages/@react-spectrum/card/test/CardView.test.js @@ -320,8 +320,7 @@ describe('CardView', function () { let expectedLeft = cardStyles.left; let expectedTop = `${parseInt(cardStyles.top, 10) + parseInt(cardStyles.height, 10) + 18}px`; - fireEvent.keyDown(document.activeElement, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(document.activeElement, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -344,8 +343,7 @@ describe('CardView', function () { let expectedLeft = cardStyles.left; let expectedTop = `${parseInt(cardStyles.top, 10) - parseInt(cardStyles.height, 10) - 18}px`; - fireEvent.keyDown(document.activeElement, {key: 'ArrowUp', code: 38, charCode: 38}); - fireEvent.keyUp(document.activeElement, {key: 'ArrowUp', code: 38, charCode: 38}); + await user.keyboard('{ArrowUp}'); act(() => { jest.runAllTimers(); }); @@ -373,8 +371,7 @@ describe('CardView', function () { let expectedLeft = cardStyles.left; let expectedTop = cardStyles.top; - fireEvent.keyDown(document.activeElement, {key: 'ArrowLeft', code: 37, charCode: 37}); - fireEvent.keyUp(document.activeElement, {key: 'ArrowLeft', code: 37, charCode: 37}); + await user.keyboard('{ArrowLeft}'); act(() => { jest.runAllTimers(); }); @@ -408,8 +405,7 @@ describe('CardView', function () { expectedRight = cardStyles.right; expectedTop = cardStyles.top; - fireEvent.keyDown(document.activeElement, {key: 'ArrowLeft', code: 37, charCode: 37}); - fireEvent.keyUp(document.activeElement, {key: 'ArrowLeft', code: 37, charCode: 37}); + await user.keyboard('{ArrowLeft}'); act(() => { jest.runAllTimers(); }); @@ -441,8 +437,7 @@ describe('CardView', function () { let expectedLeft = cardStyles.left; let expectedTop = cardStyles.top; - fireEvent.keyDown(document.activeElement, {key: 'ArrowRight', code: 39, charCode: 39}); - fireEvent.keyUp(document.activeElement, {key: 'ArrowRight', code: 39, charCode: 39}); + await user.keyboard('{ArrowRight}'); act(() => { jest.runAllTimers(); }); @@ -476,8 +471,7 @@ describe('CardView', function () { expectedRight = cardStyles.right; expectedTop = cardStyles.top; - fireEvent.keyDown(document.activeElement, {key: 'ArrowRight', code: 39, charCode: 39}); - fireEvent.keyUp(document.activeElement, {key: 'ArrowRight', code: 39, charCode: 39}); + await user.keyboard('{ArrowRight}'); act(() => { jest.runAllTimers(); }); @@ -500,8 +494,7 @@ describe('CardView', function () { let cards = tree.getAllByRole('gridcell'); await user.click(cards[5]); - fireEvent.keyDown(document.activeElement, {key: 'End', code: 35, charCode: 35}); - fireEvent.keyUp(document.activeElement, {key: 'End', code: 35, charCode: 35}); + await user.keyboard('{End}'); act(() => { jest.runAllTimers(); }); @@ -514,8 +507,7 @@ describe('CardView', function () { let numCardsInPage = Math.floor(mockHeight / (parseInt(cardStyles.height, 10) + 18)); let expectedTop = `${parseInt(cardStyles.top, 10) - numCardsInPage * (parseInt(cardStyles.height, 10) + 18)}px`; - fireEvent.keyDown(document.activeElement, {key: 'PageUp', code: 33, charCode: 33}); - fireEvent.keyUp(document.activeElement, {key: 'PageUp', code: 33, charCode: 33}); + await user.keyboard('{PageUp}'); act(() => { jest.runAllTimers(); }); @@ -541,8 +533,7 @@ describe('CardView', function () { let numCardsInPage = Math.floor(mockHeight / (parseInt(cardStyles.height, 10) + 18)); let expectedTop = `${parseInt(cardStyles.top, 10) + numCardsInPage * (parseInt(cardStyles.height, 10) + 18)}px`; - fireEvent.keyDown(document.activeElement, {key: 'PageDown', code: 34, charCode: 34}); - fireEvent.keyUp(document.activeElement, {key: 'PageDown', code: 34, charCode: 34}); + await user.keyboard('{PageDown}'); act(() => { jest.runAllTimers(); }); @@ -608,8 +599,7 @@ describe('CardView', function () { let cardStyles = getCardStyles(cards[0]); let expectedTop = `${parseInt(cardStyles.top, 10) + parseInt(cardStyles.height, 10) + 18}px`; - fireEvent.keyDown(document.activeElement, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(document.activeElement, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -633,8 +623,7 @@ describe('CardView', function () { let cardStyles = getCardStyles(cards[3]); let expectedTop = cardStyles.top; - fireEvent.keyDown(document.activeElement, {key: 'ArrowUp', code: 38, charCode: 38}); - fireEvent.keyUp(document.activeElement, {key: 'ArrowUp', code: 38, charCode: 38}); + await user.keyboard('{ArrowUp}'); act(() => { jest.runAllTimers(); }); @@ -654,22 +643,19 @@ describe('CardView', function () { let cards = tree.getAllByRole('gridcell'); await user.click(cards[0]); - fireEvent.keyDown(document.activeElement, {key: 'End', code: 35, charCode: 35}); - fireEvent.keyUp(document.activeElement, {key: 'End', code: 35, charCode: 35}); + await user.keyboard('{End}'); act(() => { jest.runAllTimers(); }); - fireEvent.keyDown(document.activeElement, {key: 'PageUp', code: 33, charCode: 33}); - fireEvent.keyUp(document.activeElement, {key: 'PageUp', code: 33, charCode: 33}); + await user.keyboard('{PageUp}'); act(() => { jest.runAllTimers(); }); let pageUpElement = document.activeElement; - fireEvent.keyDown(document.activeElement, {key: 'End', code: 35, charCode: 35}); - fireEvent.keyUp(document.activeElement, {key: 'End', code: 35, charCode: 35}); + await user.keyboard('{End}'); act(() => { jest.runAllTimers(); }); @@ -678,8 +664,7 @@ describe('CardView', function () { let numCardsInPage = Math.floor(mockHeight / (parseInt(cardStyles.height, 10) + 32)); for (let i = 0; i < numCardsInPage; i++) { - fireEvent.keyDown(document.activeElement, {key: 'ArrowUp', code: 38, charCode: 38}); - fireEvent.keyUp(document.activeElement, {key: 'ArrowUp', code: 38, charCode: 38}); + await user.keyboard('{ArrowUp}'); act(() => { jest.runAllTimers(); }); @@ -697,16 +682,14 @@ describe('CardView', function () { let cards = tree.getAllByRole('gridcell'); await user.click(cards[0]); - fireEvent.keyDown(document.activeElement, {key: 'PageDown', code: 34, charCode: 34}); - fireEvent.keyUp(document.activeElement, {key: 'PageDown', code: 34, charCode: 34}); + await user.keyboard('{PageDown}'); act(() => { jest.runAllTimers(); }); let pageDownElement = document.activeElement; - fireEvent.keyDown(document.activeElement, {key: 'Home', code: 36, charCode: 36}); - fireEvent.keyUp(document.activeElement, {key: 'Home', code: 36, charCode: 36}); + await user.keyboard('{Home}'); act(() => { jest.runAllTimers(); }); @@ -715,8 +698,7 @@ describe('CardView', function () { let numCardsInPage = Math.floor(mockHeight / (parseInt(cardStyles.height, 10) + 18)); for (let i = 0; i < numCardsInPage; i++) { - fireEvent.keyDown(document.activeElement, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(document.activeElement, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -789,8 +771,7 @@ describe('CardView', function () { let expectedTop = `${parseInt(cardStyles.top, 10) + parseInt(cardStyles.height, 10) + 18}px`; let expectedLeft = cardStyles.left; - fireEvent.keyDown(document.activeElement, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(document.activeElement, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -815,8 +796,7 @@ describe('CardView', function () { let expectedTop = cardStyles.top; let expectedLeft = cardStyles.left; - fireEvent.keyDown(document.activeElement, {key: 'ArrowUp', code: 38, charCode: 38}); - fireEvent.keyUp(document.activeElement, {key: 'ArrowUp', code: 38, charCode: 38}); + await user.keyboard('{ArrowUp}'); act(() => { jest.runAllTimers(); }); @@ -845,8 +825,7 @@ describe('CardView', function () { let expectedLeft = cardStyles.left; let expectedTop = cardStyles.top; - fireEvent.keyDown(document.activeElement, {key: 'ArrowLeft', code: 37, charCode: 37}); - fireEvent.keyUp(document.activeElement, {key: 'ArrowLeft', code: 37, charCode: 37}); + await user.keyboard('{ArrowLeft}'); act(() => { jest.runAllTimers(); }); @@ -874,8 +853,7 @@ describe('CardView', function () { let expectedRight = cardStyles.right; let expectedTop = cardStyles.top; - fireEvent.keyDown(document.activeElement, {key: 'ArrowLeft', code: 37, charCode: 37}); - fireEvent.keyUp(document.activeElement, {key: 'ArrowLeft', code: 37, charCode: 37}); + await user.keyboard('{ArrowLeft}'); act(() => { jest.runAllTimers(); }); @@ -904,8 +882,7 @@ describe('CardView', function () { let expectedLeft = cardStyles.left; let expectedTop = cardStyles.top; - fireEvent.keyDown(document.activeElement, {key: 'ArrowRight', code: 39, charCode: 39}); - fireEvent.keyUp(document.activeElement, {key: 'ArrowRight', code: 39, charCode: 39}); + await user.keyboard('{ArrowRight}'); act(() => { jest.runAllTimers(); }); @@ -934,8 +911,7 @@ describe('CardView', function () { let expectedRight = cardStyles.right; let expectedTop = cardStyles.top; - fireEvent.keyDown(document.activeElement, {key: 'ArrowRight', code: 39, charCode: 39}); - fireEvent.keyUp(document.activeElement, {key: 'ArrowRight', code: 39, charCode: 39}); + await user.keyboard('{ArrowRight}'); act(() => { jest.runAllTimers(); }); @@ -968,8 +944,7 @@ describe('CardView', function () { await user.click(cards[2]); expect(document.activeElement).toBe(cards[2]); - fireEvent.keyDown(document.activeElement, {key: 'Home', code: 36, charCode: 36}); - fireEvent.keyUp(document.activeElement, {key: 'Home', code: 36, charCode: 36}); + await user.keyboard('{Home}'); act(() => { jest.runAllTimers(); }); @@ -992,8 +967,7 @@ describe('CardView', function () { await user.click(cards[2]); expect(document.activeElement).toBe(cards[2]); - fireEvent.keyDown(document.activeElement, {key: 'End', code: 35, charCode: 35}); - fireEvent.keyUp(document.activeElement, {key: 'End', code: 35, charCode: 35}); + await user.keyboard('{End}'); act(() => { jest.runAllTimers(); }); @@ -1190,14 +1164,10 @@ describe('CardView', function () { // Scroll to the 'ideal' end, however, this won't be the true y position after everything has // been rendered and layout infos are all calculated. So scroll to the beginning again and then back one more time. // This time we'll end up at the true end and the progress bar will be visible. - fireEvent.keyDown(document.activeElement, {key: 'End', code: 35, charCode: 35}); - fireEvent.keyUp(document.activeElement, {key: 'End', code: 35, charCode: 35}); + await user.keyboard('{End}'); + await user.keyboard('{Home}'); - fireEvent.keyDown(document.activeElement, {key: 'Home', code: 35, charCode: 35}); - fireEvent.keyUp(document.activeElement, {key: 'Home', code: 35, charCode: 35}); - - fireEvent.keyDown(document.activeElement, {key: 'End', code: 35, charCode: 35}); - fireEvent.keyUp(document.activeElement, {key: 'End', code: 35, charCode: 35}); + await user.keyboard('{End}'); act(() => { grid.scrollTop += 100; @@ -1233,8 +1203,7 @@ describe('CardView', function () { expect(onLoadMore).toHaveBeenCalledTimes(1); await user.click(cards[1]); - fireEvent.keyDown(document.activeElement, {key: 'End', code: 35, charCode: 35}); - fireEvent.keyUp(document.activeElement, {key: 'End', code: 35, charCode: 35}); + await user.keyboard('{End}'); act(() => { jest.runAllTimers(); }); @@ -1250,7 +1219,7 @@ describe('CardView', function () { ${'Grid layout'} | ${GridLayout} ${'Gallery layout'} | ${GalleryLayout} ${'Waterfall layout'} | ${WaterfallLayout} - `('$Name CardView should not render a loading spinner when filtering', function ({layout}) { + `('$Name CardView should not render a loading spinner when filtering', async function ({layout}) { let tree = render(); act(() => { jest.runAllTimers(); @@ -1260,8 +1229,7 @@ describe('CardView', function () { expect(grid).toHaveAttribute('aria-rowcount', defaultItems.length.toString()); expect(within(grid).getByText('Title 1')).toBeTruthy(); - fireEvent.keyDown(document.activeElement, {key: 'End', code: 35, charCode: 35}); - fireEvent.keyUp(document.activeElement, {key: 'End', code: 35, charCode: 35}); + await user.keyboard('{End}'); act(() => { jest.runAllTimers(); }); @@ -1313,8 +1281,7 @@ describe('CardView', function () { }); expect(grid.scrollTop).toBe(initialScrollTop); - fireEvent.keyDown(document.activeElement, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(document.activeElement, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); diff --git a/packages/@react-spectrum/color/test/ColorField.test.js b/packages/@react-spectrum/color/test/ColorField.test.js index ee8a006862e..23522b46e5c 100644 --- a/packages/@react-spectrum/color/test/ColorField.test.js +++ b/packages/@react-spectrum/color/test/ColorField.test.js @@ -293,7 +293,7 @@ describe('ColorField', function () { Name | expected | key ${'increment with arrow up key'} | ${parseColor('#AAAAAB')} | ${'ArrowUp'} ${'decrement with arrow down key'} | ${parseColor('#AAAAA9')} | ${'ArrowDown'} - `('should handle $Name event', function ({expected, key}) { + `('should handle $Name event', async function ({expected, key}) { let onChangeSpy = jest.fn(); let {getByLabelText} = renderComponent({ defaultValue: '#aaa', @@ -302,8 +302,8 @@ describe('ColorField', function () { let colorField = getByLabelText('Primary Color'); expect(colorField.value).toBe('#AAAAAA'); - fireEvent.keyDown(colorField, {key}); - fireEvent.keyUp(colorField, {key}); + await user.tab(); + await user.keyboard(`{${key}}`); expect(onChangeSpy).toHaveBeenCalledWith(expected); expect(colorField.value).toBe(expected.toString('hex')); }); @@ -332,22 +332,22 @@ describe('ColorField', function () { Name | props | initExpected | key ${'not increment beyond max value'} | ${{defaultValue: '#fffffe'}} | ${'#FFFFFE'} | ${'ArrowUp'} ${'increment to max value'} | ${{defaultValue: '#aabbcc'}} | ${'#AABBCC'} | ${'End'} - `('should $Name', function ({props, initExpected, key}) { + `('should $Name', async function ({props, initExpected, key}) { let onChangeSpy = jest.fn(); let {getByLabelText} = renderComponent({...props, onChange: onChangeSpy}); let colorField = getByLabelText('Primary Color'); expect(colorField.value).toBe(initExpected); let maxColor = parseColor('#FFFFFF'); - fireEvent.keyDown(colorField, {key}); - fireEvent.keyUp(colorField, {key}); + await user.tab(); + await user.keyboard(`{${key}}`); expect(onChangeSpy).toHaveBeenCalledWith(maxColor); expect(onChangeSpy).toHaveBeenCalledTimes(1); expect(colorField.value).toBe(maxColor.toString('hex')); // repeat action to make sure onChange is not called when already at max - fireEvent.keyDown(colorField, {key}); - fireEvent.keyUp(colorField, {key}); + await user.tab(); + await user.keyboard(`{${key}}`); expect(onChangeSpy).toHaveBeenCalledTimes(1); }); @@ -355,22 +355,22 @@ describe('ColorField', function () { Name | props | initExpected | key ${'not decrement beyond min value'} | ${{defaultValue: '#000001'}} | ${'#000001'} | ${'ArrowDown'} ${'decrement to min value'} | ${{defaultValue: '#aabbcc'}} | ${'#AABBCC'} | ${'Home'} - `('should $Name', function ({props, initExpected, key}) { + `('should $Name', async function ({props, initExpected, key}) { let onChangeSpy = jest.fn(); let {getByLabelText} = renderComponent({...props, onChange: onChangeSpy}); let colorField = getByLabelText('Primary Color'); expect(colorField.value).toBe(initExpected); let minColor = parseColor('#000000'); - fireEvent.keyDown(colorField, {key}); - fireEvent.keyUp(colorField, {key}); + await user.tab(); + await user.keyboard(`{${key}}`); expect(onChangeSpy).toHaveBeenCalledWith(minColor); expect(onChangeSpy).toHaveBeenCalledTimes(1); expect(colorField.value).toBe(minColor.toString('hex')); // repeat action to make sure onChange is not called when already at min - fireEvent.keyDown(colorField, {key}); - fireEvent.keyUp(colorField, {key}); + await user.tab(); + await user.keyboard(`{${key}}`); expect(onChangeSpy).toHaveBeenCalledTimes(1); }); diff --git a/packages/@react-spectrum/color/test/ColorSlider.test.tsx b/packages/@react-spectrum/color/test/ColorSlider.test.tsx index e8e6735ba2d..aee60e67852 100644 --- a/packages/@react-spectrum/color/test/ColorSlider.test.tsx +++ b/packages/@react-spectrum/color/test/ColorSlider.test.tsx @@ -292,62 +292,62 @@ describe('ColorSlider', () => { }); describe('keyboard events', () => { - it('works', () => { + it('works', async () => { let defaultColor = parseColor('#000000'); let {getByRole} = render(); let slider = getByRole('slider'); act(() => {slider.focus();}); - fireEvent.keyDown(slider, {key: 'Right'}); + await user.keyboard('{ArrowRight}'); act(() => {jest.runAllTimers();}); expect(onChangeSpy).toHaveBeenCalledTimes(1); expect(onChangeSpy.mock.calls[0][0].toString('hexa')).toBe(defaultColor.withChannelValue('red', 1).toString('hexa')); expect(onChangeEndSpy).toHaveBeenCalledTimes(1); expect(onChangeEndSpy.mock.calls[0][0].toString('hexa')).toBe(defaultColor.withChannelValue('red', 1).toString('hexa')); - fireEvent.keyDown(slider, {key: 'Left'}); + await user.keyboard('{ArrowLeft}'); act(() => {jest.runAllTimers();}); expect(onChangeSpy).toHaveBeenCalledTimes(2); expect(onChangeSpy.mock.calls[1][0].toString('hexa')).toBe(defaultColor.withChannelValue('red', 0).toString('hexa')); expect(onChangeEndSpy).toHaveBeenCalledTimes(2); expect(onChangeEndSpy.mock.calls[1][0].toString('hexa')).toBe(defaultColor.withChannelValue('red', 0).toString('hexa')); - fireEvent.keyDown(slider, {key: 'PageUp'}); + await user.keyboard('{PageUp}'); act(() => {jest.runAllTimers();}); expect(onChangeSpy).toHaveBeenCalledTimes(3); expect(onChangeSpy.mock.calls[2][0].toString('hexa')).toBe(defaultColor.withChannelValue('red', 17).toString('hexa')); expect(onChangeEndSpy).toHaveBeenCalledTimes(3); expect(onChangeEndSpy.mock.calls[2][0].toString('hexa')).toBe(defaultColor.withChannelValue('red', 17).toString('hexa')); - fireEvent.keyDown(slider, {key: 'Right'}); + await user.keyboard('{ArrowRight}'); act(() => {jest.runAllTimers();}); expect(onChangeSpy).toHaveBeenCalledTimes(4); expect(onChangeSpy.mock.calls[3][0].toString('hexa')).toBe(defaultColor.withChannelValue('red', 18).toString('hexa')); expect(onChangeEndSpy).toHaveBeenCalledTimes(4); expect(onChangeEndSpy.mock.calls[3][0].toString('hexa')).toBe(defaultColor.withChannelValue('red', 18).toString('hexa')); - fireEvent.keyDown(slider, {key: 'PageDown'}); + await user.keyboard('{PageDown}'); act(() => {jest.runAllTimers();}); expect(onChangeSpy).toHaveBeenCalledTimes(5); expect(onChangeSpy.mock.calls[4][0].toString('hexa')).toBe(defaultColor.withChannelValue('red', 1).toString('hexa')); expect(onChangeEndSpy).toHaveBeenCalledTimes(5); expect(onChangeEndSpy.mock.calls[4][0].toString('hexa')).toBe(defaultColor.withChannelValue('red', 1).toString('hexa')); - fireEvent.keyDown(slider, {key: 'End'}); + await user.keyboard('{End}'); act(() => {jest.runAllTimers();}); expect(onChangeSpy).toHaveBeenCalledTimes(6); expect(onChangeSpy.mock.calls[5][0].toString('hexa')).toBe(defaultColor.withChannelValue('red', 255).toString('hexa')); expect(onChangeEndSpy).toHaveBeenCalledTimes(6); expect(onChangeEndSpy.mock.calls[5][0].toString('hexa')).toBe(defaultColor.withChannelValue('red', 255).toString('hexa')); - fireEvent.keyDown(slider, {key: 'PageDown'}); + await user.keyboard('{PageDown}'); act(() => {jest.runAllTimers();}); expect(onChangeSpy).toHaveBeenCalledTimes(7); expect(onChangeSpy.mock.calls[6][0].toString('hexa')).toBe(defaultColor.withChannelValue('red', 238).toString('hexa')); expect(onChangeEndSpy).toHaveBeenCalledTimes(7); expect(onChangeEndSpy.mock.calls[6][0].toString('hexa')).toBe(defaultColor.withChannelValue('red', 238).toString('hexa')); - fireEvent.keyDown(slider, {key: 'Home'}); + await user.keyboard('{Home}'); act(() => {jest.runAllTimers();}); expect(onChangeSpy).toHaveBeenCalledTimes(8); expect(onChangeSpy.mock.calls[7][0].toString('hexa')).toBe(defaultColor.withChannelValue('red', 0).toString('hexa')); @@ -355,15 +355,15 @@ describe('ColorSlider', () => { expect(onChangeEndSpy.mock.calls[7][0].toString('hexa')).toBe(defaultColor.withChannelValue('red', 0).toString('hexa')); }); - it('doesn\'t work when disabled', () => { + it('doesn\'t work when disabled', async () => { let defaultColor = parseColor('#000000'); let {getByRole} = render(); let slider = getByRole('slider'); act(() => {slider.focus();}); - fireEvent.keyDown(slider, {key: 'Right'}); + await user.keyboard('{ArrowRight}'); expect(onChangeSpy).toHaveBeenCalledTimes(0); - fireEvent.keyDown(slider, {key: 'Left'}); + await user.keyboard('{ArrowLeft}'); expect(onChangeSpy).toHaveBeenCalledTimes(0); }); }); diff --git a/packages/@react-spectrum/color/test/ColorWheel.test.tsx b/packages/@react-spectrum/color/test/ColorWheel.test.tsx index ca484a0ff8a..529a7afb79e 100644 --- a/packages/@react-spectrum/color/test/ColorWheel.test.tsx +++ b/packages/@react-spectrum/color/test/ColorWheel.test.tsx @@ -145,81 +145,77 @@ describe('ColorWheel', () => { }); describe('keyboard events', () => { - it('works', () => { + it('works', async () => { let defaultColor = parseColor('hsl(0, 100%, 50%)'); let {getByRole} = render(); let slider = getByRole('slider'); act(() => {slider.focus();}); - fireEvent.keyDown(slider, {key: 'Right'}); + await user.keyboard('{ArrowRight}'); expect(onChangeSpy).toHaveBeenCalledTimes(1); expect(onChangeSpy.mock.calls[0][0].toString('hsla')).toBe(defaultColor.withChannelValue('hue', 1).toString('hsla')); expect(onChangeEndSpy).toHaveBeenCalledTimes(1); expect(onChangeEndSpy.mock.calls[0][0].toString('hsla')).toBe(defaultColor.withChannelValue('hue', 1).toString('hsla')); - fireEvent.keyDown(slider, {key: 'Left'}); + await user.keyboard('{ArrowLeft}'); expect(onChangeSpy).toHaveBeenCalledTimes(2); expect(onChangeSpy.mock.calls[1][0].toString('hsla')).toBe(defaultColor.withChannelValue('hue', 0).toString('hsla')); expect(onChangeEndSpy).toHaveBeenCalledTimes(2); expect(onChangeEndSpy.mock.calls[1][0].toString('hsla')).toBe(defaultColor.withChannelValue('hue', 0).toString('hsla')); }); - it('doesn\'t work when disabled', () => { + it('doesn\'t work when disabled', async () => { let defaultColor = parseColor('hsl(0, 100%, 50%)'); let {getByRole} = render(); let slider = getByRole('slider'); act(() => {slider.focus();}); - fireEvent.keyDown(slider, {key: 'Right'}); + await user.keyboard('{ArrowRight}'); expect(onChangeSpy).toHaveBeenCalledTimes(0); - fireEvent.keyDown(slider, {key: 'Left'}); + await user.keyboard('{ArrowLeft}'); expect(onChangeSpy).toHaveBeenCalledTimes(0); }); - it('wraps around', () => { + it('wraps around', async () => { let defaultColor = parseColor('hsl(0, 100%, 50%)'); let {getByRole} = render(); let slider = getByRole('slider'); act(() => {slider.focus();}); - fireEvent.keyDown(slider, {key: 'Left'}); + await user.keyboard('{ArrowLeft}'); expect(onChangeSpy).toHaveBeenCalledTimes(1); expect(onChangeSpy.mock.calls[0][0].toString('hsla')).toBe(defaultColor.withChannelValue('hue', 359).toString('hsla')); }); - it('respects page steps', () => { + it('respects page steps', async () => { let defaultColor = parseColor('hsl(0, 100%, 50%)'); let {getByRole} = render(); let slider = getByRole('slider'); act(() => {slider.focus();}); - fireEvent.keyDown(slider, {key: 'PageUp'}); - fireEvent.keyUp(slider, {key: 'PageUp'}); + await user.keyboard('{PageUp}'); expect(onChangeSpy).toHaveBeenCalledTimes(1); expect(onChangeSpy.mock.calls[0][0].toString('hsla')).toBe(defaultColor.withChannelValue('hue', 15).toString('hsla')); expect(onChangeEndSpy).toHaveBeenCalledTimes(1); expect(onChangeEndSpy.mock.calls[0][0].toString('hsla')).toBe(defaultColor.withChannelValue('hue', 15).toString('hsla')); - fireEvent.keyDown(slider, {key: 'PageDown'}); - fireEvent.keyUp(slider, {key: 'PageDown'}); + await user.keyboard('{PageDown}'); expect(onChangeSpy).toHaveBeenCalledTimes(2); expect(onChangeSpy.mock.calls[1][0].toString('hsla')).toBe(defaultColor.withChannelValue('hue', 0).toString('hsla')); expect(onChangeEndSpy).toHaveBeenCalledTimes(2); expect(onChangeEndSpy.mock.calls[1][0].toString('hsla')).toBe(defaultColor.withChannelValue('hue', 0).toString('hsla')); }); - it('respects page steps from shift arrow', () => { + it('respects page steps from shift arrow', async () => { let defaultColor = parseColor('hsl(0, 100%, 50%)'); let {getByRole} = render(); let slider = getByRole('slider'); act(() => {slider.focus();}); - fireEvent.keyDown(slider, {key: 'Right', shiftKey: true}); - fireEvent.keyUp(slider, {key: 'Right', shiftKey: true}); + await user.keyboard('{Shift>}{ArrowRight}{/Shift}'); expect(onChangeSpy).toHaveBeenCalledTimes(1); expect(onChangeSpy.mock.calls[0][0].toString('hsla')).toBe(defaultColor.withChannelValue('hue', 15).toString('hsla')); expect(onChangeEndSpy).toHaveBeenCalledTimes(1); expect(onChangeEndSpy.mock.calls[0][0].toString('hsla')).toBe(defaultColor.withChannelValue('hue', 15).toString('hsla')); - fireEvent.keyDown(slider, {key: 'Left', shiftKey: true}); - fireEvent.keyUp(slider, {key: 'Left', shiftKey: true}); + await user.keyboard('{Shift>}{ArrowLeft}{/Shift}'); expect(onChangeSpy).toHaveBeenCalledTimes(2); expect(onChangeSpy.mock.calls[1][0].toString('hsla')).toBe(defaultColor.withChannelValue('hue', 0).toString('hsla')); expect(onChangeEndSpy).toHaveBeenCalledTimes(2); diff --git a/packages/@react-spectrum/combobox/test/ComboBox.test.js b/packages/@react-spectrum/combobox/test/ComboBox.test.js index c7945c81017..62d97c8fa4a 100644 --- a/packages/@react-spectrum/combobox/test/ComboBox.test.js +++ b/packages/@react-spectrum/combobox/test/ComboBox.test.js @@ -201,50 +201,48 @@ let AsyncComboBox = () => { ); }; -function testComboBoxOpen(combobox, button, listbox, focusedItemIndex) { - let buttonId = button.id; - let comboboxLabelledBy = combobox.getAttribute('aria-labelledby'); - - expect(listbox).toBeVisible(); - expect(listbox).toHaveAttribute('aria-label', 'Suggestions'); - expect(listbox).toHaveAttribute('aria-labelledby', `${listbox.id} ${comboboxLabelledBy}`); - expect(button).toHaveAttribute('aria-expanded', 'true'); - expect(button).toHaveAttribute('aria-controls', listbox.id); - expect(button).toHaveAttribute('aria-label', 'Show suggestions'); - expect(button).toHaveAttribute('aria-labelledby', `${buttonId} ${comboboxLabelledBy}`); - expect(combobox).toHaveAttribute('aria-controls', listbox.id); - expect(combobox).toHaveAttribute('aria-expanded', 'true'); - - let items = within(listbox).getAllByRole('option'); - expect(items).toHaveLength(3); - expect(items[0]).toHaveTextContent('One'); - expect(items[1]).toHaveTextContent('Two'); - expect(items[2]).toHaveTextContent('Three'); - - expect(listbox).not.toHaveAttribute('tabIndex'); - for (let item of items) { - expect(item).not.toHaveAttribute('tabIndex'); - } +describe('ComboBox', function () { + let user; + async function testComboBoxOpen(combobox, button, listbox, focusedItemIndex) { + let buttonId = button.id; + let comboboxLabelledBy = combobox.getAttribute('aria-labelledby'); + + expect(listbox).toBeVisible(); + expect(listbox).toHaveAttribute('aria-label', 'Suggestions'); + expect(listbox).toHaveAttribute('aria-labelledby', `${listbox.id} ${comboboxLabelledBy}`); + expect(button).toHaveAttribute('aria-expanded', 'true'); + expect(button).toHaveAttribute('aria-controls', listbox.id); + expect(button).toHaveAttribute('aria-label', 'Show suggestions'); + expect(button).toHaveAttribute('aria-labelledby', `${buttonId} ${comboboxLabelledBy}`); + expect(combobox).toHaveAttribute('aria-controls', listbox.id); + expect(combobox).toHaveAttribute('aria-expanded', 'true'); - expect(document.activeElement).toBe(combobox); + let items = within(listbox).getAllByRole('option'); + expect(items).toHaveLength(3); + expect(items[0]).toHaveTextContent('One'); + expect(items[1]).toHaveTextContent('Two'); + expect(items[2]).toHaveTextContent('Three'); - if (typeof focusedItemIndex === 'undefined') { - expect(combobox).not.toHaveAttribute('aria-activedescendant'); + expect(listbox).not.toHaveAttribute('tabIndex'); + for (let item of items) { + expect(item).not.toHaveAttribute('tabIndex'); + } - act(() => { - fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - jest.runAllTimers(); - }); + expect(document.activeElement).toBe(combobox); - expect(combobox).toHaveAttribute('aria-activedescendant', items[0].id); - } else { - expect(combobox).toHaveAttribute('aria-activedescendant', items[focusedItemIndex].id); + if (typeof focusedItemIndex === 'undefined') { + expect(combobox).not.toHaveAttribute('aria-activedescendant'); + await user.keyboard('{ArrowDown}'); + act(() => { + jest.runAllTimers(); + }); + + expect(combobox).toHaveAttribute('aria-activedescendant', items[0].id); + } else { + expect(combobox).toHaveAttribute('aria-activedescendant', items[focusedItemIndex].id); + } } -} -describe('ComboBox', function () { - let user; beforeAll(function () { user = userEvent.setup({delay: null, pointerMap}); jest.spyOn(window.HTMLElement.prototype, 'clientWidth', 'get').mockImplementation(() => 1000); @@ -320,8 +318,7 @@ describe('ComboBox', function () { expect(onOpenChange).not.toHaveBeenCalled(); expect(onFocus).not.toHaveBeenCalled(); - fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -358,8 +355,7 @@ describe('ComboBox', function () { expect(onFocus).toHaveBeenCalled(); expect(onInputChange).not.toHaveBeenCalled(); - fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -406,8 +402,7 @@ describe('ComboBox', function () { expect(combobox).toHaveAttribute('aria-controls', listbox.id); expect(combobox).not.toHaveAttribute('aria-activedescendant'); - fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -603,7 +598,7 @@ describe('ComboBox', function () { }); describe('keyboard input', function () { - it('opens the menu on down arrow press', function () { + it('opens the menu on down arrow press', async function () { let {getByRole, queryByRole} = renderComboBox(); let button = getByRole('button'); @@ -612,8 +607,7 @@ describe('ComboBox', function () { expect(queryByRole('listbox')).toBeNull(); expect(onOpenChange).not.toHaveBeenCalled(); - fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -624,7 +618,7 @@ describe('ComboBox', function () { testComboBoxOpen(combobox, button, listbox, 0); }); - it('opens the menu on up arrow press', function () { + it('opens the menu on up arrow press', async function () { let {getByRole, queryByRole} = renderComboBox(); let button = getByRole('button'); @@ -633,8 +627,7 @@ describe('ComboBox', function () { expect(queryByRole('listbox')).toBeNull(); expect(onOpenChange).not.toHaveBeenCalled(); - fireEvent.keyDown(combobox, {key: 'ArrowUp', code: 38, charCode: 38}); - fireEvent.keyUp(combobox, {key: 'ArrowUp', code: 38, charCode: 38}); + await user.keyboard('{ArrowUp}'); act(() => { jest.runAllTimers(); }); @@ -840,18 +833,15 @@ describe('ComboBox', function () { expect(document.activeElement).toBe(combobox); expect(combobox).not.toHaveAttribute('aria-activedescendant'); - fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); expect(combobox).toHaveAttribute('aria-activedescendant', items[0].id); - fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); expect(combobox).toHaveAttribute('aria-activedescendant', items[1].id); - fireEvent.keyDown(combobox, {key: 'ArrowUp', code: 38, charCode: 38}); - fireEvent.keyUp(combobox, {key: 'ArrowUp', code: 38, charCode: 38}); + await user.keyboard('{ArrowUp}'); expect(combobox).toHaveAttribute('aria-activedescendant', items[0].id); }); @@ -873,14 +863,12 @@ describe('ComboBox', function () { expect(document.activeElement).toBe(combobox); expect(combobox).not.toHaveAttribute('aria-activedescendant'); - fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); expect(combobox).toHaveAttribute('aria-activedescendant', items[0].id); - fireEvent.keyDown(combobox, {key: 'Enter', code: 13, charCode: 13}); - fireEvent.keyUp(combobox, {key: 'Enter', code: 13, charCode: 13}); + await user.keyboard('{Enter}'); act(() => { jest.runAllTimers(); }); @@ -891,7 +879,7 @@ describe('ComboBox', function () { expect(onSelectionChange).toHaveBeenCalledTimes(1); }); - it('resets input text if reselecting a selected option with Enter', function () { + it('resets input text if reselecting a selected option with Enter', async function () { let {getByRole, queryByRole} = renderComboBox({defaultSelectedKey: '2'}); let combobox = getByRole('combobox'); @@ -907,16 +895,11 @@ describe('ComboBox', function () { let listbox = getByRole('listbox'); let items = within(listbox).getAllByRole('option'); expect(items.length).toBe(1); - - act(() => { - fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - }); + await user.keyboard('{ArrowDown}'); expect(combobox).toHaveAttribute('aria-activedescendant', items[0].id); - fireEvent.keyDown(combobox, {key: 'Enter', code: 13, charCode: 13}); - fireEvent.keyUp(combobox, {key: 'Enter', code: 13, charCode: 13}); + await user.keyboard('{Enter}'); act(() => jest.runAllTimers()); expect(queryByRole('listbox')).toBeNull(); @@ -955,7 +938,7 @@ describe('ComboBox', function () { expect(onInputChange).toHaveBeenLastCalledWith('Two'); }); - it('closes menu and resets selected key if allowsCustomValue=true and no item is focused', function () { + it('closes menu and resets selected key if allowsCustomValue=true and no item is focused', async function () { let {getByRole, queryByRole} = render(); let combobox = getByRole('combobox'); @@ -970,10 +953,8 @@ describe('ComboBox', function () { expect(document.activeElement).toBe(combobox); expect(combobox).not.toHaveAttribute('aria-activedescendant'); - + await user.keyboard('{Enter}'); act(() => { - fireEvent.keyDown(combobox, {key: 'Enter', code: 13, charCode: 13}); - fireEvent.keyUp(combobox, {key: 'Enter', code: 13, charCode: 13}); jest.runAllTimers(); }); @@ -995,11 +976,9 @@ describe('ComboBox', function () { await user.keyboard('O'); act(() => { jest.runAllTimers(); - fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); }); + await user.keyboard('{ArrowDown}'); + await user.keyboard('{ArrowDown}'); let listbox = getByRole('listbox'); let items = within(listbox).getAllByRole('option'); @@ -1020,23 +999,21 @@ describe('ComboBox', function () { expect(items[0].textContent).toBe('One'); }); - it('closes menu when pressing Enter on an already selected item', function () { + it('closes menu when pressing Enter on an already selected item', async function () { let {getByRole, queryByRole} = renderComboBox({selectedKey: '2'}); let combobox = getByRole('combobox'); act(() => combobox.focus()); + await user.keyboard('{ArrowDown}'); act(() => { - fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); jest.runAllTimers(); }); let listbox = getByRole('listbox'); expect(listbox).toBeTruthy(); + await user.keyboard('{Enter}'); act(() => { - fireEvent.keyDown(combobox, {key: 'Enter', code: 13, charCode: 13}); - fireEvent.keyUp(combobox, {key: 'Enter', code: 13, charCode: 13}); jest.runAllTimers(); }); @@ -1069,11 +1046,10 @@ describe('ComboBox', function () { it('displays all items when opened via arrow keys', async function () { let {getByRole, queryByRole} = render(); - let combobox = getByRole('combobox'); let button = getByRole('button'); - fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.tab(); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -1092,8 +1068,7 @@ describe('ComboBox', function () { }); expect(queryByRole('listbox')).toBeNull(); - fireEvent.keyDown(combobox, {key: 'ArrowUp', code: 38, charCode: 38}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 38, charCode: 38}); + await user.keyboard('{ArrowUp}'); act(() => { jest.runAllTimers(); }); @@ -1158,8 +1133,7 @@ describe('ComboBox', function () { // Arrow keys will only navigate through menu if open, won't show full list // Not sure why, test blows up for controlled items combobox when trying to fire arrow down here if (Name.includes('uncontrolled')) { - fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -1177,8 +1151,7 @@ describe('ComboBox', function () { combobox = getByRole('combobox'); // Not sure why, test blows up for controlled items combobox when trying to fire arrow down here if (Name.includes('uncontrolled')) { - fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -1209,8 +1182,7 @@ describe('ComboBox', function () { let items = within(listbox).getAllByRole('option'); expect(items).toHaveLength(1); - fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -1484,8 +1456,7 @@ describe('ComboBox', function () { expect(items).toHaveLength(1); expect(combobox).not.toHaveAttribute('aria-activedescendant'); - fireEvent.keyDown(combobox, {key: 'ArrowDown'}); - fireEvent.keyUp(combobox, {key: 'ArrowDown'}); + await user.keyboard('{ArrowDown}'); expect(combobox).toHaveAttribute('aria-activedescendant', items[0].id); @@ -1499,7 +1470,7 @@ describe('ComboBox', function () { describe('blur', function () { it('closes and commits selection on tab', async function () { - let {queryByRole, getAllByRole, getByRole} = render( + let {queryByRole, getAllByRole} = render( Bulbasaur @@ -1512,13 +1483,11 @@ describe('ComboBox', function () { let button = getAllByRole('button')[0]; let secondaryButton = getAllByRole('button')[1]; - let combobox = getByRole('combobox'); await user.click(button); act(() => { jest.runAllTimers(); }); - fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); // something about the implementation of await user.tab() fails to trigger an extra render like on web // on the browser, it triggers a resetInput, the old implementation of userEvent.tab though looked like this and matched // what we saw in the browser. I suspect it's because of when focus is called + the act around the focus forcing a render flush @@ -1680,9 +1649,8 @@ describe('ComboBox', function () { jest.runAllTimers(); }); + await user.keyboard('{Enter}'); act(() => { - fireEvent.keyDown(combobox, {key: 'Enter', code: 13, charCode: 13}); - fireEvent.keyUp(combobox, {key: 'Enter', code: 13, charCode: 13}); jest.runAllTimers(); }); @@ -1838,8 +1806,7 @@ describe('ComboBox', function () { let listbox = getByRole('listbox'); expect(listbox).toBeVisible(); - fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -1882,8 +1849,7 @@ describe('ComboBox', function () { expect(combobox.value).toBe('B'); expect(document.activeElement).toBe(combobox); - fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -1930,8 +1896,7 @@ describe('ComboBox', function () { act(() => { jest.runAllTimers(); }); - fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); expect(document.activeElement).toBe(combobox); let listbox = getByRole('listbox'); @@ -1995,16 +1960,14 @@ describe('ComboBox', function () { act(() => { jest.runAllTimers(); }); - fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); let listbox = getByRole('listbox'); expect(listbox).toBeVisible(); let items = within(listbox).getAllByRole('option'); expect(combobox).toHaveAttribute('aria-activedescendant', items[0].id); - fireEvent.keyDown(combobox, {key: 'Enter', code: 13, charCode: 13}); - fireEvent.keyUp(combobox, {key: 'Enter', code: 13, charCode: 13}); + await user.keyboard('{Enter}'); act(() => { jest.runAllTimers(); }); @@ -2073,15 +2036,14 @@ describe('ComboBox', function () { expect(items[0]).not.toHaveAttribute('aria-selected', 'true'); }); - it('doesn\'t happen if user deletes all text in input (controlled)', function () { + it('doesn\'t happen if user deletes all text in input (controlled)', async function () { let {getByRole} = renderComboBox({selectedKey: '2'}); let combobox = getByRole('combobox'); act(() => { combobox.focus(); }); - fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -2652,10 +2614,8 @@ describe('ComboBox', function () { expect(items[0]).toHaveTextContent('One'); expect(items[0]).toHaveAttribute('aria-selected', 'true'); - fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyDown(combobox, {key: 'Enter', code: 13, charCode: 13}); - fireEvent.keyUp(combobox, {key: 'Enter', code: 13, charCode: 13}); + await user.keyboard('{ArrowDown}'); + await user.keyboard('{Enter}'); act(() => { jest.runAllTimers(); }); @@ -2705,10 +2665,8 @@ describe('ComboBox', function () { let items = within(listbox).getAllByRole('option'); expect(items.length).toBe(1); - fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyDown(combobox, {key: 'Enter', code: 13, charCode: 13}); - fireEvent.keyUp(combobox, {key: 'Enter', code: 13, charCode: 13}); + await user.keyboard('{ArrowDown}'); + await user.keyboard('{Enter}'); act(() => { jest.runAllTimers(); }); @@ -3279,8 +3237,7 @@ describe('ComboBox', function () { act(() => { combobox.focus(); }); - fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -3312,26 +3269,22 @@ describe('ComboBox', function () { expect(items[5]).toHaveAttribute('aria-labelledby', within(items[5]).getByText('Six').id); expect(groups[1]).toContainElement(items[5]); - fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); - fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); - fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); expect(combobox).toHaveAttribute('aria-activedescendant', items[3].id); - fireEvent.keyDown(combobox, {key: 'Enter', code: 13, charCode: 13}); - fireEvent.keyUp(combobox, {key: 'Enter', code: 13, charCode: 13}); + await user.keyboard('{Enter}'); act(() => { jest.runAllTimers(); }); @@ -3387,39 +3340,33 @@ describe('ComboBox', function () { describe.each` Name | Component | action ${'uncontrolled combobox (Enter)'} | ${} | ${ - (combobox) => { - fireEvent.keyDown(combobox, {key: 'Enter', code: 13, charCode: 13}); - fireEvent.keyUp(combobox, {key: 'Enter', code: 13, charCode: 13}); + async () => { + await user.keyboard('{Enter}'); } } ${'controlled combobox (Enter)'} | ${} | ${ - (combobox) => { - fireEvent.keyDown(combobox, {key: 'Enter', code: 13, charCode: 13}); - fireEvent.keyUp(combobox, {key: 'Enter', code: 13, charCode: 13}); + async () => { + await user.keyboard('{Enter}'); } } ${'allows custom value combobox (Enter)'} | ${} | ${ - (combobox) => { - fireEvent.keyDown(combobox, {key: 'Enter', code: 13, charCode: 13}); - fireEvent.keyUp(combobox, {key: 'Enter', code: 13, charCode: 13}); + async () => { + await user.keyboard('{Enter}'); } } ${'uncontrolled combobox (Escape)'} | ${} | ${ - (combobox) => { - fireEvent.keyDown(combobox, {key: 'Escape', code: 27, charCode: 27}); - fireEvent.keyUp(combobox, {key: 'Escape', code: 27, charCode: 27}); + async () => { + await user.keyboard('{Escape}'); } } ${'controlled combobox (Escape)'} | ${} | ${ - (combobox) => { - fireEvent.keyDown(combobox, {key: 'Escape', code: 27, charCode: 27}); - fireEvent.keyUp(combobox, {key: 'Escape', code: 27, charCode: 27}); + async () => { + await user.keyboard('{Escape}'); } } ${'allows custom value combobox (Escape)'} | ${} | ${ - (combobox) => { - fireEvent.keyDown(combobox, {key: 'Escape', code: 27, charCode: 27}); - fireEvent.keyUp(combobox, {key: 'Escape', code: 27, charCode: 27}); + async () => { + await user.keyboard('{Escape}'); } } `('$Name', ({Name, Component, action}) => { @@ -3435,9 +3382,7 @@ describe('ComboBox', function () { expect(listbox).toBeVisible(); expect(combobox).toHaveAttribute('value', 'One'); - act(() => { - action(combobox); - }); + await action(combobox); act(() => { jest.runAllTimers(); }); @@ -3486,7 +3431,7 @@ describe('ComboBox', function () { expect(combobox).toHaveAttribute('value', 'T'); expect(combobox).not.toHaveAttribute('aria-activedescendant'); - action(combobox); + await action(combobox); act(() => { jest.runAllTimers(); }); @@ -3739,7 +3684,7 @@ describe('ComboBox', function () { jest.clearAllMocks(); }); - function testComboBoxTrayOpen(input, tray, listbox, focusedItemIndex) { + async function testComboBoxTrayOpen(input, tray, listbox, focusedItemIndex) { expect(tray).toBeVisible(); let dialog = within(tray).getByRole('dialog'); @@ -3762,8 +3707,7 @@ describe('ComboBox', function () { if (typeof focusedItemIndex === 'undefined') { expect(input).not.toHaveAttribute('aria-activedescendant'); - fireEvent.keyDown(input, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(input, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -3834,7 +3778,7 @@ describe('ComboBox', function () { let listbox = getByRole('listbox'); let trayInput = within(tray).getByRole('searchbox'); - testComboBoxTrayOpen(trayInput, tray, listbox); + await testComboBoxTrayOpen(trayInput, tray, listbox); }); it('closing the tray autofocuses the button', async function () { @@ -3849,10 +3793,7 @@ describe('ComboBox', function () { let tray = getByTestId('tray'); expect(tray).toBeVisible(); - let input = within(tray).getByRole('searchbox'); - - fireEvent.keyDown(input, {key: 'Escape', code: 27, charCode: 27}); - fireEvent.keyUp(input, {key: 'Escape', code: 27, charCode: 27}); + await user.keyboard('{Escape}'); act(() => { jest.runAllTimers(); }); @@ -3907,17 +3848,15 @@ describe('ComboBox', function () { let input = within(tray).getByRole('searchbox'); expect(document.activeElement).toBe(input); - fireEvent.keyDown(input, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(input, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); let listbox = getByRole('listbox'); - testComboBoxTrayOpen(input, tray, listbox, 0); + await testComboBoxTrayOpen(input, tray, listbox, 0); - fireEvent.keyDown(input, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(input, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -3926,8 +3865,7 @@ describe('ComboBox', function () { expect(input).toHaveAttribute('aria-activedescendant', items[1].id); - fireEvent.keyDown(input, {key: 'ArrowUp', code: 38, charCode: 38}); - fireEvent.keyUp(input, {key: 'ArrowUp', code: 38, charCode: 38}); + await user.keyboard('{ArrowUp}'); act(() => { jest.runAllTimers(); }); @@ -3949,7 +3887,7 @@ describe('ComboBox', function () { let listbox = getByRole('listbox'); let trayInput = within(tray).getByRole('searchbox'); - testComboBoxTrayOpen(trayInput, tray, listbox); + await testComboBoxTrayOpen(trayInput, tray, listbox); act(() => {trayInput.focus();}); await user.keyboard('r'); @@ -3989,7 +3927,7 @@ describe('ComboBox', function () { expect(() => within(tray).getByLabelText('Clear')).toThrow(); - testComboBoxTrayOpen(trayInput, tray, listbox); + await testComboBoxTrayOpen(trayInput, tray, listbox); act(() => {trayInput.focus();}); await user.keyboard('r'); @@ -4027,7 +3965,7 @@ describe('ComboBox', function () { let listbox = getByRole('listbox'); let trayInput = within(tray).getByRole('searchbox'); - testComboBoxTrayOpen(trayInput, tray, listbox); + await testComboBoxTrayOpen(trayInput, tray, listbox); act(() => {trayInput.focus();}); await user.keyboard('blah'); @@ -4070,7 +4008,7 @@ describe('ComboBox', function () { expect(tray).toBeVisible(); let listbox = getByRole('listbox'); let trayInput = within(tray).getByRole('searchbox'); - testComboBoxTrayOpen(trayInput, tray, listbox); + await testComboBoxTrayOpen(trayInput, tray, listbox); let items = within(tray).getAllByRole('option'); @@ -4119,8 +4057,7 @@ describe('ComboBox', function () { let trayInput = within(tray).getByRole('searchbox'); - fireEvent.keyDown(trayInput, {key: 'ArrowUp', code: 38, charCode: 38}); - fireEvent.keyUp(trayInput, {key: 'ArrowUp', code: 38, charCode: 38}); + await user.keyboard('{ArrowUp}'); act(() => { jest.runAllTimers(); }); @@ -4128,10 +4065,9 @@ describe('ComboBox', function () { expect(onOpenChange).toHaveBeenCalledWith(true, 'manual'); expect(onOpenChange).toHaveBeenCalledTimes(1); - testComboBoxTrayOpen(trayInput, tray, listbox, 2); + await testComboBoxTrayOpen(trayInput, tray, listbox, 2); - fireEvent.keyDown(trayInput, {key: 'Enter', code: 13, charCode: 13}); - fireEvent.keyUp(trayInput, {key: 'Enter', code: 13, charCode: 13}); + await user.keyboard('{Enter}'); act(() => { jest.runAllTimers(); }); @@ -4220,8 +4156,7 @@ describe('ComboBox', function () { expect(onInputChange).toHaveBeenCalledWith('Bleh'); expect(onInputChange).toHaveBeenCalledTimes(4); - fireEvent.keyDown(trayInput, {key: 'Escape', code: 27, charCode: 27}); - fireEvent.keyUp(trayInput, {key: 'Escape', code: 27, charCode: 27}); + await user.keyboard('{Escape}'); act(() => { jest.runAllTimers(); }); @@ -4444,8 +4379,7 @@ describe('ComboBox', function () { fireEvent.click(dismissButtons[0]); break; case 'escape key': - fireEvent.keyDown(trayInput, {key: 'Escape', code: 27, charCode: 27}); - fireEvent.keyUp(trayInput, {key: 'Escape', code: 27, charCode: 27}); + await user.keyboard('{Escape}'); break; } act(() => { @@ -4589,7 +4523,7 @@ describe('ComboBox', function () { let listbox = getByRole('listbox'); let trayInput = within(tray).getByRole('searchbox'); - testComboBoxTrayOpen(trayInput, tray, listbox); + await testComboBoxTrayOpen(trayInput, tray, listbox); let items = within(tray).getAllByRole('option'); expect(items.length).toBe(3); @@ -4870,8 +4804,7 @@ describe('ComboBox', function () { expect(listbox).toBeVisible(); expect(combobox).toHaveAttribute('aria-controls', listbox.id); - fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -4881,24 +4814,21 @@ describe('ComboBox', function () { expect(items[0]).toHaveTextContent('One'); expect(combobox).toHaveAttribute('aria-activedescendant', items[0].id); - fireEvent.keyDown(combobox, {key: 'ArrowLeft', code: 37, charCode: 37}); - fireEvent.keyUp(combobox, {key: 'ArrowLeft', code: 37, charCode: 37}); + await user.keyboard('{ArrowLeft}'); act(() => { jest.runAllTimers(); }); expect(combobox).not.toHaveAttribute('aria-activedescendant'); - fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); expect(combobox).toHaveAttribute('aria-activedescendant', items[0].id); - fireEvent.keyDown(combobox, {key: 'ArrowRight', code: 39, charCode: 39}); - fireEvent.keyUp(combobox, {key: 'ArrowRight', code: 39, charCode: 39}); + await user.keyboard('{ArrowRight}'); act(() => { jest.runAllTimers(); }); @@ -4919,20 +4849,17 @@ describe('ComboBox', function () { }); describe('keyboard navigating', function () { - it('should announce items when navigating with the arrow keys', function () { - let {getByRole} = renderComboBox(); - let combobox = getByRole('combobox'); - - fireEvent.keyDown(combobox, {key: 'ArrowDown'}); - fireEvent.keyUp(combobox, {key: 'ArrowDown'}); + it('should announce items when navigating with the arrow keys', async function () { + renderComboBox(); + await user.tab(); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); expect(announce).toHaveBeenLastCalledWith('One'); - fireEvent.keyDown(combobox, {key: 'ArrowDown'}); - fireEvent.keyUp(combobox, {key: 'ArrowDown'}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -4940,12 +4867,13 @@ describe('ComboBox', function () { expect(announce).toHaveBeenLastCalledWith('Two'); }); - it('should announce when navigating to the selected item', function () { + it('should announce when navigating to the selected item', async function () { let {getByRole} = renderComboBox({selectedKey: '2'}); let combobox = getByRole('combobox'); - - fireEvent.keyDown(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); - fireEvent.keyUp(combobox, {key: 'ArrowDown', code: 40, charCode: 40}); + act(() => { + combobox.focus(); + }); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -4953,20 +4881,21 @@ describe('ComboBox', function () { expect(announce).toHaveBeenLastCalledWith('Two, selected'); }); - it('should announce when navigating into a section with multiple items', function () { + it('should announce when navigating into a section with multiple items', async function () { let {getByRole} = renderSectionComboBox(); let combobox = getByRole('combobox'); + act(() => { + combobox.focus(); + }); - fireEvent.keyDown(combobox, {key: 'ArrowDown'}); - fireEvent.keyUp(combobox, {key: 'ArrowDown'}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); expect(announce).toHaveBeenLastCalledWith('Entered group Section One, with 3 options. One'); - fireEvent.keyDown(combobox, {key: 'ArrowDown'}); - fireEvent.keyUp(combobox, {key: 'ArrowDown'}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -4985,8 +4914,7 @@ describe('ComboBox', function () { act(() => { jest.runAllTimers(); }); - fireEvent.keyDown(combobox, {key: 'ArrowDown'}); - fireEvent.keyUp(combobox, {key: 'ArrowDown'}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -5009,8 +4937,7 @@ describe('ComboBox', function () { act(() => { jest.runAllTimers(); }); - fireEvent.keyDown(combobox, {key: 'ArrowDown'}); - fireEvent.keyUp(combobox, {key: 'ArrowDown'}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -5059,23 +4986,21 @@ describe('ComboBox', function () { }); describe('selection', function () { - it('should announce when a selection occurs', function () { + it('should announce when a selection occurs', async function () { let {getByRole} = renderComboBox(); let combobox = getByRole('combobox'); act(() => { combobox.focus(); }); - fireEvent.keyDown(combobox, {key: 'ArrowDown'}); - fireEvent.keyUp(combobox, {key: 'ArrowDown'}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); expect(announce).toHaveBeenLastCalledWith('One'); - fireEvent.keyDown(combobox, {key: 'Enter'}); - fireEvent.keyUp(combobox, {key: 'Enter'}); + await user.keyboard('{Enter}'); act(() => { jest.runAllTimers(); }); @@ -5086,7 +5011,7 @@ describe('ComboBox', function () { }); describe('hiding surrounding content', function () { - it('should hide elements outside the combobox with aria-hidden', function () { + it('should hide elements outside the combobox with aria-hidden', async function () { let {getByRole, queryAllByRole, getAllByRole} = render( <> @@ -5104,8 +5029,7 @@ describe('ComboBox', function () { act(() => { combobox.focus(); }); - fireEvent.keyDown(combobox, {key: 'ArrowDown'}); - fireEvent.keyUp(combobox, {key: 'ArrowDown'}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -5120,7 +5044,7 @@ describe('ComboBox', function () { expect(getByRole('combobox')).toBeVisible(); }); - it('should not traverse into a hidden container', function () { + it('should not traverse into a hidden container', async function () { let {getByRole, queryAllByRole, getAllByRole} = render( <>
@@ -5140,8 +5064,7 @@ describe('ComboBox', function () { act(() => { combobox.focus(); }); - fireEvent.keyDown(combobox, {key: 'ArrowDown'}); - fireEvent.keyUp(combobox, {key: 'ArrowDown'}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -5157,7 +5080,7 @@ describe('ComboBox', function () { expect(getByRole('combobox')).toBeVisible(); }); - it('should not hide the live announcer element', function () { + it('should not hide the live announcer element', async function () { let platformMock = jest.spyOn(navigator, 'platform', 'get').mockImplementation(() => 'MacIntel'); let {getByRole} = render(); @@ -5170,8 +5093,7 @@ describe('ComboBox', function () { act(() => { combobox.focus(); }); - fireEvent.keyDown(combobox, {key: 'ArrowDown'}); - fireEvent.keyUp(combobox, {key: 'ArrowDown'}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -5199,8 +5121,7 @@ describe('ComboBox', function () { act(() => { combobox.focus(); }); - fireEvent.keyDown(combobox, {key: 'ArrowDown'}); - fireEvent.keyUp(combobox, {key: 'ArrowDown'}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -5240,8 +5161,7 @@ describe('ComboBox', function () { act(() => { combobox.focus(); }); - fireEvent.keyDown(combobox, {key: 'ArrowDown'}); - fireEvent.keyUp(combobox, {key: 'ArrowDown'}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -5286,8 +5206,7 @@ describe('ComboBox', function () { act(() => { combobox.focus(); }); - fireEvent.keyDown(combobox, {key: 'ArrowDown'}); - fireEvent.keyUp(combobox, {key: 'ArrowDown'}); + await user.keyboard('{ArrowDown}'); act(() => { jest.runAllTimers(); }); @@ -5917,8 +5836,7 @@ describe('ComboBox', function () { expect(onClick.mock.calls[0][0].target).toBeInstanceOf(HTMLAnchorElement); expect(onClick.mock.calls[0][0].target.href).toBe('https://google.com/'); } else { - fireEvent.keyDown(combobox, {key: 'Enter'}); - fireEvent.keyUp(combobox, {key: 'Enter'}); + await user.keyboard('{Enter}'); } act(() => { jest.runAllTimers(); diff --git a/packages/@react-spectrum/datepicker/test/DateField.test.js b/packages/@react-spectrum/datepicker/test/DateField.test.js index e457ad93c0d..128dd27dda3 100644 --- a/packages/@react-spectrum/datepicker/test/DateField.test.js +++ b/packages/@react-spectrum/datepicker/test/DateField.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render as render_, within} from '@react-spectrum/test-utils'; +import {act, pointerMap, render as render_, within} from '@react-spectrum/test-utils'; import {Button} from '@react-spectrum/button'; import {CalendarDate, CalendarDateTime, ZonedDateTime} from '@internationalized/date'; import {DateField} from '../'; @@ -317,8 +317,7 @@ describe('DateField', function () { expect(onKeyDownSpy).not.toHaveBeenCalled(); expect(onKeyUpSpy).toHaveBeenCalledTimes(1); - fireEvent.keyDown(document.activeElement, {key: 'ArrowRight'}); - fireEvent.keyUp(document.activeElement, {key: 'ArrowRight'}); + await user.keyboard('{ArrowRight}'); expect(segments[1]).toHaveFocus(); expect(onKeyDownSpy).toHaveBeenCalledTimes(1); expect(onKeyUpSpy).toHaveBeenCalledTimes(2); @@ -349,18 +348,17 @@ describe('DateField', function () { ); } - let {getByTestId, getByRole, getAllByRole} = render(); + let {getByTestId, getByRole} = render(); let group = getByRole('group'); let input = document.querySelector('input[name=date]'); - let segments = getAllByRole('spinbutton'); let getDescription = () => group.getAttribute('aria-describedby').split(' ').map(d => document.getElementById(d).textContent).join(' '); expect(getDescription()).toBe('Selected Date: February 3, 2020'); expect(input).toHaveValue('2020-02-03'); expect(input).toHaveAttribute('name', 'date'); - fireEvent.keyDown(segments[0], {key: 'ArrowUp'}); - fireEvent.keyUp(segments[0], {key: 'ArrowUp'}); + await user.tab(); + await user.keyboard('{ArrowUp}'); expect(getDescription()).toBe('Selected Date: March 3, 2020'); expect(input).toHaveValue('2020-03-03'); diff --git a/packages/@react-spectrum/datepicker/test/DatePicker.test.js b/packages/@react-spectrum/datepicker/test/DatePicker.test.js index 7cfb1eb4ad5..db389b228d3 100644 --- a/packages/@react-spectrum/datepicker/test/DatePicker.test.js +++ b/packages/@react-spectrum/datepicker/test/DatePicker.test.js @@ -291,8 +291,7 @@ describe('DatePicker', function () { expect(onFocusChangeSpy).toHaveBeenCalledTimes(1); expect(onFocusSpy).toHaveBeenCalledTimes(1); - fireEvent.keyDown(document.activeElement, {key: 'Escape'}); - fireEvent.keyUp(document.activeElement, {key: 'Escape'}); + await user.keyboard('{Escape}'); act(() => jest.runAllTimers()); await waitFor(() => { @@ -330,8 +329,7 @@ describe('DatePicker', function () { expect(onKeyDownSpy).not.toHaveBeenCalled(); expect(onKeyUpSpy).toHaveBeenCalledTimes(1); - fireEvent.keyDown(document.activeElement, {key: 'ArrowRight'}); - fireEvent.keyUp(document.activeElement, {key: 'ArrowRight'}); + await user.keyboard('{ArrowRight}'); expect(segments[1]).toHaveFocus(); expect(onKeyDownSpy).toHaveBeenCalledTimes(1); expect(onKeyUpSpy).toHaveBeenCalledTimes(2); @@ -355,8 +353,7 @@ describe('DatePicker', function () { expect(onFocusChangeSpy).toHaveBeenCalledTimes(1); expect(onFocusSpy).toHaveBeenCalledTimes(1); - fireEvent.keyDown(document.activeElement, {key: 'ArrowRight'}); - fireEvent.keyUp(document.activeElement, {key: 'ArrowRight'}); + await user.keyboard('{ArrowRight}'); expect(onKeyDownSpy).toHaveBeenCalledTimes(0); expect(onKeyUpSpy).toHaveBeenCalledTimes(0); expect(onBlurSpy).not.toHaveBeenCalled(); @@ -467,8 +464,7 @@ describe('DatePicker', function () { expect(hour).toHaveAttribute('aria-valuetext', '8 AM'); act(() => hour.focus()); - fireEvent.keyDown(hour, {key: 'ArrowUp'}); - fireEvent.keyUp(hour, {key: 'ArrowUp'}); + await user.keyboard('{ArrowUp}'); expect(hour).toHaveAttribute('aria-valuetext', '9 AM'); @@ -515,10 +511,10 @@ describe('DatePicker', function () { expect(hour).toHaveAttribute('aria-valuetext', '10 AM'); act(() => hour.focus()); - fireEvent.keyDown(hour, {key: 'Backspace'}); + await user.keyboard('{Backspace}'); expect(hour).toHaveAttribute('aria-valuetext', '1 AM'); - fireEvent.keyDown(hour, {key: 'Backspace'}); + await user.keyboard('{Backspace}'); expect(hour).toHaveAttribute('aria-valuetext', '1 AM'); expect(dialog).toBeVisible(); @@ -567,21 +563,18 @@ describe('DatePicker', function () { expect(hour).toHaveAttribute('aria-valuetext', 'Empty'); act(() => hour.focus()); - fireEvent.keyDown(hour, {key: 'ArrowUp'}); - fireEvent.keyUp(hour, {key: 'ArrowUp'}); + await user.keyboard('{ArrowUp}'); expect(hour).toHaveAttribute('aria-valuetext', '12 AM'); expect(onChange).not.toHaveBeenCalled(); expectPlaceholder(combobox, 'mm/dd/yyyy, ––:–– AM'); - fireEvent.keyDown(hour, {key: 'ArrowRight'}); - fireEvent.keyUp(hour, {key: 'ArrowRight'}); + await user.keyboard('{ArrowRight}'); expect(document.activeElement).toHaveAttribute('aria-label', 'minute, '); expect(document.activeElement).toHaveAttribute('aria-valuetext', 'Empty'); - fireEvent.keyDown(document.activeElement, {key: 'ArrowUp'}); - fireEvent.keyUp(document.activeElement, {key: 'ArrowUp'}); + await user.keyboard('{ArrowUp}'); expect(document.activeElement).toHaveAttribute('aria-valuetext', '00'); @@ -593,8 +586,7 @@ describe('DatePicker', function () { // eslint-disable-next-line no-irregular-whitespace expectPlaceholder(combobox, `${month}/${day}/${year}, 12:00 AM`); - fireEvent.keyDown(hour, {key: 'ArrowRight'}); - fireEvent.keyUp(hour, {key: 'ArrowRight'}); + await user.keyboard('{ArrowRight}'); expect(document.activeElement).toHaveAttribute('aria-label', 'AM/PM, '); expect(document.activeElement).toHaveAttribute('aria-valuetext', 'AM'); @@ -668,8 +660,7 @@ describe('DatePicker', function () { expect(hour).toHaveAttribute('aria-valuetext', 'Empty'); act(() => hour.focus()); - fireEvent.keyDown(hour, {key: 'ArrowUp'}); - fireEvent.keyUp(hour, {key: 'ArrowUp'}); + await user.keyboard('{ArrowUp}'); expect(hour).toHaveAttribute('aria-valuetext', '12 AM'); @@ -712,8 +703,7 @@ describe('DatePicker', function () { expect(hour).toHaveAttribute('aria-valuetext', 'Empty'); act(() => hour.focus()); - fireEvent.keyDown(hour, {key: 'ArrowUp'}); - fireEvent.keyUp(hour, {key: 'ArrowUp'}); + await user.keyboard('{ArrowUp}'); expect(hour).toHaveAttribute('aria-valuetext', '12 AM'); @@ -722,10 +712,8 @@ describe('DatePicker', function () { expect(minute).toHaveAttribute('aria-valuetext', 'Empty'); act(() => minute.focus()); - fireEvent.keyDown(minute, {key: 'ArrowUp'}); - fireEvent.keyUp(minute, {key: 'ArrowUp'}); - fireEvent.keyDown(minute, {key: 'ArrowUp'}); - fireEvent.keyUp(minute, {key: 'ArrowUp'}); + await user.keyboard('{ArrowUp}'); + await user.keyboard('{ArrowUp}'); expect(minute).toHaveAttribute('aria-valuetext', '01'); @@ -773,19 +761,15 @@ describe('DatePicker', function () { let hour = within(timeField).getByLabelText('hour,'); act(() => hour.focus()); - fireEvent.keyDown(hour, {key: 'ArrowUp'}); - fireEvent.keyUp(hour, {key: 'ArrowUp'}); + await user.keyboard('{ArrowUp}'); expect(hour).toHaveAttribute('aria-valuetext', '12 AM'); - fireEvent.keyDown(hour, {key: 'ArrowRight'}); - fireEvent.keyUp(hour, {key: 'ArrowRight'}); + await user.keyboard('{ArrowRight}'); expect(document.activeElement).toHaveAttribute('aria-label', 'minute, '); - fireEvent.keyDown(document.activeElement, {key: 'ArrowUp'}); - fireEvent.keyUp(document.activeElement, {key: 'ArrowUp'}); + await user.keyboard('{ArrowUp}'); expect(document.activeElement).toHaveAttribute('aria-valuetext', '00'); - fireEvent.keyDown(hour, {key: 'ArrowRight'}); - fireEvent.keyUp(hour, {key: 'ArrowRight'}); + await user.keyboard('{ArrowRight}'); expect(document.activeElement).toHaveAttribute('aria-label', 'AM/PM, '); expect(document.activeElement).toHaveAttribute('aria-valuetext', 'AM'); @@ -1015,8 +999,7 @@ describe('DatePicker', function () { let segments = getAllByRole('spinbutton'); act(() => segments[0].focus()); - fireEvent.keyDown(segments[0], {key: 'ArrowUp'}); - fireEvent.keyUp(segments[0], {key: 'ArrowUp'}); + await user.keyboard('{ArrowUp}'); expect(segments[0]).toHaveFocus(); await user.click(field); @@ -1032,21 +1015,20 @@ describe('DatePicker', function () { expect(segments[2]).toHaveFocus(); }); - it('should focus the previous segment when the era is removed', function () { + it('should focus the previous segment when the era is removed', async function () { let {getByTestId, queryByTestId} = render(); let field = getByTestId('date-field'); let era = getByTestId('era'); expect(era).toBe(within(field).getAllByRole('spinbutton').pop()); act(() => era.focus()); - fireEvent.keyDown(era, {key: 'ArrowUp'}); - fireEvent.keyUp(era, {key: 'ArrowUp'}); + await user.keyboard('{ArrowUp}'); expect(queryByTestId('era')).toBeNull(); expect(document.activeElement).toBe(within(field).getAllByRole('spinbutton').pop()); }); - it('should focus the next segment when the era is removed and is the first segment', function () { + it('should focus the next segment when the era is removed and is the first segment', async function () { let {getByTestId, queryByTestId} = render( @@ -1057,8 +1039,7 @@ describe('DatePicker', function () { expect(era).toBe(field.firstChild); act(() => era.focus()); - fireEvent.keyDown(era, {key: 'ArrowUp'}); - fireEvent.keyUp(era, {key: 'ArrowUp'}); + await user.keyboard('{ArrowUp}'); expect(queryByTestId('era')).toBeNull(); expect(document.activeElement).toBe(field.firstChild); @@ -1078,7 +1059,7 @@ describe('DatePicker', function () { describe('editing', function () { describe('arrow keys', function () { - function testArrows(label, value, incremented, decremented, options = {}) { + async function testArrows(label, value, incremented, decremented, options = {}) { let onChange = jest.fn(); // Test controlled mode @@ -1091,12 +1072,12 @@ describe('DatePicker', function () { let textContent = segment.textContent; act(() => {segment.focus();}); - fireEvent.keyDown(segment, {key: options.upKey || 'ArrowUp'}); + await user.keyboard(`{${options?.upKey || 'ArrowUp'}}`); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith(incremented); expect(segment.textContent).toBe(textContent); - fireEvent.keyDown(segment, {key: options.downKey || 'ArrowDown'}); + await user.keyboard(`{${options?.downKey || 'ArrowDown'}}`); expect(onChange).toHaveBeenCalledTimes(2); expect(onChange).toHaveBeenCalledWith(decremented); expect(segment.textContent).toBe(textContent); @@ -1113,7 +1094,7 @@ describe('DatePicker', function () { textContent = segment.textContent; act(() => {segment.focus();}); - fireEvent.keyDown(segment, {key: options.upKey || 'ArrowUp'}); + await user.keyboard(`{${options?.upKey || 'ArrowUp'}}`); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith(incremented); expect(segment.textContent).not.toBe(textContent); @@ -1130,7 +1111,7 @@ describe('DatePicker', function () { textContent = segment.textContent; act(() => {segment.focus();}); - fireEvent.keyDown(segment, {key: options.downKey || 'ArrowDown'}); + await user.keyboard(`{${options?.downKey || 'ArrowDown'}}`); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith(decremented); expect(segment.textContent).not.toBe(textContent); @@ -1147,7 +1128,7 @@ describe('DatePicker', function () { textContent = segment.textContent; act(() => {segment.focus();}); - fireEvent.keyDown(segment, {key: options.upKey || 'ArrowUp'}); + await user.keyboard(`{${options?.upKey || 'ArrowUp'}}`); expect(onChange).not.toHaveBeenCalled(); expect(segment.textContent).toBe(textContent); unmount(); @@ -1163,162 +1144,161 @@ describe('DatePicker', function () { textContent = segment.textContent; act(() => {segment.focus();}); - fireEvent.keyDown(segment, {key: options.downKey || 'ArrowDown'}); + await user.keyboard(`{${options?.downKey || 'ArrowDown'}}`); expect(onChange).not.toHaveBeenCalled(); expect(segment.textContent).toBe(textContent); unmount(); } describe('month', function () { - it('should support using the arrow keys to increment and decrement the month', function () { - testArrows('month,', new CalendarDate(2019, 2, 3), new CalendarDate(2019, 3, 3), new CalendarDate(2019, 1, 3)); + it('should support using the arrow keys to increment and decrement the month', async function () { + await testArrows('month,', new CalendarDate(2019, 2, 3), new CalendarDate(2019, 3, 3), new CalendarDate(2019, 1, 3)); }); - it('should wrap around when incrementing and decrementing the month', function () { - testArrows('month,', new CalendarDate(2019, 12, 3), new CalendarDate(2019, 1, 3), new CalendarDate(2019, 11, 3)); - testArrows('month,', new CalendarDate(2019, 1, 3), new CalendarDate(2019, 2, 3), new CalendarDate(2019, 12, 3)); + it('should wrap around when incrementing and decrementing the month', async function () { + await testArrows('month,', new CalendarDate(2019, 12, 3), new CalendarDate(2019, 1, 3), new CalendarDate(2019, 11, 3)); + await testArrows('month,', new CalendarDate(2019, 1, 3), new CalendarDate(2019, 2, 3), new CalendarDate(2019, 12, 3)); }); - it('should support using the page up and down keys to increment and decrement the month by 2', function () { - testArrows('month,', new CalendarDate(2019, 1, 3), new CalendarDate(2019, 3, 3), new CalendarDate(2019, 11, 3), {upKey: 'PageUp', downKey: 'PageDown'}); - testArrows('month,', new CalendarDate(2019, 2, 3), new CalendarDate(2019, 4, 3), new CalendarDate(2019, 12, 3), {upKey: 'PageUp', downKey: 'PageDown'}); + it('should support using the page up and down keys to increment and decrement the month by 2', async function () { + await testArrows('month,', new CalendarDate(2019, 1, 3), new CalendarDate(2019, 3, 3), new CalendarDate(2019, 11, 3), {upKey: 'PageUp', downKey: 'PageDown'}); + await testArrows('month,', new CalendarDate(2019, 2, 3), new CalendarDate(2019, 4, 3), new CalendarDate(2019, 12, 3), {upKey: 'PageUp', downKey: 'PageDown'}); }); - it('should support using the home and end keys to jump to the min and max month', function () { - testArrows('month,', new CalendarDate(2019, 6, 3), new CalendarDate(2019, 12, 3), new CalendarDate(2019, 1, 3), {upKey: 'End', downKey: 'Home'}); + it('should support using the home and end keys to jump to the min and max month', async function () { + await testArrows('month,', new CalendarDate(2019, 6, 3), new CalendarDate(2019, 12, 3), new CalendarDate(2019, 1, 3), {upKey: 'End', downKey: 'Home'}); }); }); describe('day', function () { - it('should support using the arrow keys to increment and decrement the day', function () { - testArrows('day,', new CalendarDate(2019, 2, 3), new CalendarDate(2019, 2, 4), new CalendarDate(2019, 2, 2)); + it('should support using the arrow keys to increment and decrement the day', async function () { + await testArrows('day,', new CalendarDate(2019, 2, 3), new CalendarDate(2019, 2, 4), new CalendarDate(2019, 2, 2)); }); - it('should wrap around when incrementing and decrementing the day', function () { - testArrows('day,', new CalendarDate(2019, 2, 28), new CalendarDate(2019, 2, 1), new CalendarDate(2019, 2, 27)); - testArrows('day,', new CalendarDate(2019, 2, 1), new CalendarDate(2019, 2, 2), new CalendarDate(2019, 2, 28)); + it('should wrap around when incrementing and decrementing the day', async function () { + await testArrows('day,', new CalendarDate(2019, 2, 28), new CalendarDate(2019, 2, 1), new CalendarDate(2019, 2, 27)); + await testArrows('day,', new CalendarDate(2019, 2, 1), new CalendarDate(2019, 2, 2), new CalendarDate(2019, 2, 28)); }); - it('should support using the page up and down keys to increment and decrement the day by 7', function () { - testArrows('day,', new CalendarDate(2019, 2, 3), new CalendarDate(2019, 2, 10), new CalendarDate(2019, 2, 24), {upKey: 'PageUp', downKey: 'PageDown'}); + it('should support using the page up and down keys to increment and decrement the day by 7', async function () { + await testArrows('day,', new CalendarDate(2019, 2, 3), new CalendarDate(2019, 2, 10), new CalendarDate(2019, 2, 24), {upKey: 'PageUp', downKey: 'PageDown'}); }); - it('should support using the home and end keys to jump to the min and max day', function () { - testArrows('day,', new CalendarDate(2019, 2, 5), new CalendarDate(2019, 2, 28), new CalendarDate(2019, 2, 1), {upKey: 'End', downKey: 'Home'}); + it('should support using the home and end keys to jump to the min and max day', async function () { + await testArrows('day,', new CalendarDate(2019, 2, 5), new CalendarDate(2019, 2, 28), new CalendarDate(2019, 2, 1), {upKey: 'End', downKey: 'Home'}); }); }); describe('year', function () { - it('should support using the arrow keys to increment and decrement the year', function () { - testArrows('year,', new CalendarDate(2019, 2, 3), new CalendarDate(2020, 2, 3), new CalendarDate(2018, 2, 3)); + it('should support using the arrow keys to increment and decrement the year', async function () { + await testArrows('year,', new CalendarDate(2019, 2, 3), new CalendarDate(2020, 2, 3), new CalendarDate(2018, 2, 3)); }); - it('should support using the page up and down keys to increment and decrement the year to the nearest 5', function () { - testArrows('year,', new CalendarDate(2019, 2, 3), new CalendarDate(2020, 2, 3), new CalendarDate(2015, 2, 3), {upKey: 'PageUp', downKey: 'PageDown'}); + it('should support using the page up and down keys to increment and decrement the year to the nearest 5', async function () { + await testArrows('year,', new CalendarDate(2019, 2, 3), new CalendarDate(2020, 2, 3), new CalendarDate(2015, 2, 3), {upKey: 'PageUp', downKey: 'PageDown'}); }); }); describe('hour', function () { - it('should support using the arrow keys to increment and decrement the hour', function () { - testArrows('hour,', new CalendarDateTime(2019, 2, 3, 8), new CalendarDateTime(2019, 2, 3, 9), new CalendarDateTime(2019, 2, 3, 7)); + it('should support using the arrow keys to increment and decrement the hour', async function () { + await testArrows('hour,', new CalendarDateTime(2019, 2, 3, 8), new CalendarDateTime(2019, 2, 3, 9), new CalendarDateTime(2019, 2, 3, 7)); }); - it('should wrap around when incrementing and decrementing the hour in 12 hour time', function () { + it('should wrap around when incrementing and decrementing the hour in 12 hour time', async function () { // AM - testArrows('hour,', new CalendarDateTime(2019, 2, 3, 11), new CalendarDateTime(2019, 2, 3, 0), new CalendarDateTime(2019, 2, 3, 10)); - testArrows('hour,', new CalendarDateTime(2019, 2, 3, 0), new CalendarDateTime(2019, 2, 3, 1), new CalendarDateTime(2019, 2, 3, 11)); + await testArrows('hour,', new CalendarDateTime(2019, 2, 3, 11), new CalendarDateTime(2019, 2, 3, 0), new CalendarDateTime(2019, 2, 3, 10)); + await testArrows('hour,', new CalendarDateTime(2019, 2, 3, 0), new CalendarDateTime(2019, 2, 3, 1), new CalendarDateTime(2019, 2, 3, 11)); // PM - testArrows('hour,', new CalendarDateTime(2019, 2, 3, 23), new CalendarDateTime(2019, 2, 3, 12), new CalendarDateTime(2019, 2, 3, 22)); - testArrows('hour,', new CalendarDateTime(2019, 2, 3, 12), new CalendarDateTime(2019, 2, 3, 13), new CalendarDateTime(2019, 2, 3, 23)); + await testArrows('hour,', new CalendarDateTime(2019, 2, 3, 23), new CalendarDateTime(2019, 2, 3, 12), new CalendarDateTime(2019, 2, 3, 22)); + await testArrows('hour,', new CalendarDateTime(2019, 2, 3, 12), new CalendarDateTime(2019, 2, 3, 13), new CalendarDateTime(2019, 2, 3, 23)); }); - it('should wrap around when incrementing and decrementing the hour in 24 hour time', function () { - testArrows('hour,', new CalendarDateTime(2019, 2, 3, 23), new CalendarDateTime(2019, 2, 3, 0), new CalendarDateTime(2019, 2, 3, 22), {props: {hourCycle: 24}}); - testArrows('hour,', new CalendarDateTime(2019, 2, 3, 0), new CalendarDateTime(2019, 2, 3, 1), new CalendarDateTime(2019, 2, 3, 23), {props: {hourCycle: 24}}); + it('should wrap around when incrementing and decrementing the hour in 24 hour time', async function () { + await testArrows('hour,', new CalendarDateTime(2019, 2, 3, 23), new CalendarDateTime(2019, 2, 3, 0), new CalendarDateTime(2019, 2, 3, 22), {props: {hourCycle: 24}}); + await testArrows('hour,', new CalendarDateTime(2019, 2, 3, 0), new CalendarDateTime(2019, 2, 3, 1), new CalendarDateTime(2019, 2, 3, 23), {props: {hourCycle: 24}}); }); - it('should support using the page up and down keys to increment and decrement the hour by 2', function () { - testArrows('hour,', new CalendarDateTime(2019, 2, 3, 8), new CalendarDateTime(2019, 2, 3, 10), new CalendarDateTime(2019, 2, 3, 6), {upKey: 'PageUp', downKey: 'PageDown'}); + it('should support using the page up and down keys to increment and decrement the hour by 2', async function () { + await testArrows('hour,', new CalendarDateTime(2019, 2, 3, 8), new CalendarDateTime(2019, 2, 3, 10), new CalendarDateTime(2019, 2, 3, 6), {upKey: 'PageUp', downKey: 'PageDown'}); }); - it('should support using the home and end keys to jump to the min and max hour in 12 hour time', function () { + it('should support using the home and end keys to jump to the min and max hour in 12 hour time', async function () { // AM - testArrows('hour,', new CalendarDateTime(2019, 2, 3, 8), new CalendarDateTime(2019, 2, 3, 11), new CalendarDateTime(2019, 2, 3, 0), {upKey: 'End', downKey: 'Home'}); + await testArrows('hour,', new CalendarDateTime(2019, 2, 3, 8), new CalendarDateTime(2019, 2, 3, 11), new CalendarDateTime(2019, 2, 3, 0), {upKey: 'End', downKey: 'Home'}); // PM - testArrows('hour,', new CalendarDateTime(2019, 2, 3, 16), new CalendarDateTime(2019, 2, 3, 23), new CalendarDateTime(2019, 2, 3, 12), {upKey: 'End', downKey: 'Home'}); + await testArrows('hour,', new CalendarDateTime(2019, 2, 3, 16), new CalendarDateTime(2019, 2, 3, 23), new CalendarDateTime(2019, 2, 3, 12), {upKey: 'End', downKey: 'Home'}); }); - it('should support using the home and end keys to jump to the min and max hour in 24 hour time', function () { - testArrows('hour,', new CalendarDateTime(2019, 2, 3, 8), new CalendarDateTime(2019, 2, 3, 23), new CalendarDateTime(2019, 2, 3, 0), {upKey: 'End', downKey: 'Home', props: {hourCycle: 24}}); + it('should support using the home and end keys to jump to the min and max hour in 24 hour time', async function () { + await testArrows('hour,', new CalendarDateTime(2019, 2, 3, 8), new CalendarDateTime(2019, 2, 3, 23), new CalendarDateTime(2019, 2, 3, 0), {upKey: 'End', downKey: 'Home', props: {hourCycle: 24}}); }); }); describe('minute', function () { - it('should support using the arrow keys to increment and decrement the minute', function () { - testArrows('minute,', new CalendarDateTime(2019, 2, 3, 8, 5), new CalendarDateTime(2019, 2, 3, 8, 6), new CalendarDateTime(2019, 2, 3, 8, 4)); + it('should support using the arrow keys to increment and decrement the minute', async function () { + await testArrows('minute,', new CalendarDateTime(2019, 2, 3, 8, 5), new CalendarDateTime(2019, 2, 3, 8, 6), new CalendarDateTime(2019, 2, 3, 8, 4)); }); - it('should wrap around when incrementing and decrementing the minute', function () { - testArrows('minute,', new CalendarDateTime(2019, 2, 3, 8, 59), new CalendarDateTime(2019, 2, 3, 8, 0), new CalendarDateTime(2019, 2, 3, 8, 58)); - testArrows('minute,', new CalendarDateTime(2019, 2, 3, 8, 0), new CalendarDateTime(2019, 2, 3, 8, 1), new CalendarDateTime(2019, 2, 3, 8, 59)); + it('should wrap around when incrementing and decrementing the minute', async function () { + await testArrows('minute,', new CalendarDateTime(2019, 2, 3, 8, 59), new CalendarDateTime(2019, 2, 3, 8, 0), new CalendarDateTime(2019, 2, 3, 8, 58)); + await testArrows('minute,', new CalendarDateTime(2019, 2, 3, 8, 0), new CalendarDateTime(2019, 2, 3, 8, 1), new CalendarDateTime(2019, 2, 3, 8, 59)); }); - it('should support using the page up and down keys to increment and decrement the minute to the nearest 15', function () { - testArrows('minute,', new CalendarDateTime(2019, 2, 3, 8, 22), new CalendarDateTime(2019, 2, 3, 8, 30), new CalendarDateTime(2019, 2, 3, 8, 15), {upKey: 'PageUp', downKey: 'PageDown'}); + it('should support using the page up and down keys to increment and decrement the minute to the nearest 15', async function () { + await testArrows('minute,', new CalendarDateTime(2019, 2, 3, 8, 22), new CalendarDateTime(2019, 2, 3, 8, 30), new CalendarDateTime(2019, 2, 3, 8, 15), {upKey: 'PageUp', downKey: 'PageDown'}); }); - it('should support using the home and end keys to jump to the min and max minute', function () { - testArrows('minute,', new CalendarDateTime(2019, 2, 3, 8, 22), new CalendarDateTime(2019, 2, 3, 8, 59), new CalendarDateTime(2019, 2, 3, 8, 0), {upKey: 'End', downKey: 'Home', props: {hourCycle: 24}}); + it('should support using the home and end keys to jump to the min and max minute', async function () { + await testArrows('minute,', new CalendarDateTime(2019, 2, 3, 8, 22), new CalendarDateTime(2019, 2, 3, 8, 59), new CalendarDateTime(2019, 2, 3, 8, 0), {upKey: 'End', downKey: 'Home', props: {hourCycle: 24}}); }); }); describe('second', function () { - it('should support using the arrow keys to increment and decrement the second', function () { - testArrows('second,', new CalendarDateTime(2019, 2, 3, 8, 5, 10), new CalendarDateTime(2019, 2, 3, 8, 5, 11), new CalendarDateTime(2019, 2, 3, 8, 5, 9), {props: {granularity: 'second'}}); + it('should support using the arrow keys to increment and decrement the second', async function () { + await testArrows('second,', new CalendarDateTime(2019, 2, 3, 8, 5, 10), new CalendarDateTime(2019, 2, 3, 8, 5, 11), new CalendarDateTime(2019, 2, 3, 8, 5, 9), {props: {granularity: 'second'}}); }); - it('should wrap around when incrementing and decrementing the second', function () { - testArrows('second,', new CalendarDateTime(2019, 2, 3, 8, 5, 59), new CalendarDateTime(2019, 2, 3, 8, 5, 0), new CalendarDateTime(2019, 2, 3, 8, 5, 58), {props: {granularity: 'second'}}); - testArrows('second,', new CalendarDateTime(2019, 2, 3, 8, 5, 0), new CalendarDateTime(2019, 2, 3, 8, 5, 1), new CalendarDateTime(2019, 2, 3, 8, 5, 59), {props: {granularity: 'second'}}); + it('should wrap around when incrementing and decrementing the second', async function () { + await testArrows('second,', new CalendarDateTime(2019, 2, 3, 8, 5, 59), new CalendarDateTime(2019, 2, 3, 8, 5, 0), new CalendarDateTime(2019, 2, 3, 8, 5, 58), {props: {granularity: 'second'}}); + await testArrows('second,', new CalendarDateTime(2019, 2, 3, 8, 5, 0), new CalendarDateTime(2019, 2, 3, 8, 5, 1), new CalendarDateTime(2019, 2, 3, 8, 5, 59), {props: {granularity: 'second'}}); }); - it('should support using the page up and down keys to increment and decrement the second to the nearest 15', function () { - testArrows('second,', new CalendarDateTime(2019, 2, 3, 8, 5, 22), new CalendarDateTime(2019, 2, 3, 8, 5, 30), new CalendarDateTime(2019, 2, 3, 8, 5, 15), {upKey: 'PageUp', downKey: 'PageDown', props: {granularity: 'second'}}); + it('should support using the page up and down keys to increment and decrement the second to the nearest 15', async function () { + await testArrows('second,', new CalendarDateTime(2019, 2, 3, 8, 5, 22), new CalendarDateTime(2019, 2, 3, 8, 5, 30), new CalendarDateTime(2019, 2, 3, 8, 5, 15), {upKey: 'PageUp', downKey: 'PageDown', props: {granularity: 'second'}}); }); - it('should support using the home and end keys to jump to the min and max second', function () { - testArrows('second,', new CalendarDateTime(2019, 2, 3, 8, 5, 22), new CalendarDateTime(2019, 2, 3, 8, 5, 59), new CalendarDateTime(2019, 2, 3, 8, 5, 0), {upKey: 'End', downKey: 'Home', props: {granularity: 'second', hourCycle: 24}}); + it('should support using the home and end keys to jump to the min and max second', async function () { + await testArrows('second,', new CalendarDateTime(2019, 2, 3, 8, 5, 22), new CalendarDateTime(2019, 2, 3, 8, 5, 59), new CalendarDateTime(2019, 2, 3, 8, 5, 0), {upKey: 'End', downKey: 'Home', props: {granularity: 'second', hourCycle: 24}}); }); }); describe('day period', function () { - it('should support using the arrow keys to increment and decrement the day period', function () { - testArrows('AM/PM,', new CalendarDateTime(2019, 2, 3, 8), new CalendarDateTime(2019, 2, 3, 20), new CalendarDateTime(2019, 2, 3, 20)); - testArrows('AM/PM,', new CalendarDateTime(2019, 2, 3, 20), new CalendarDateTime(2019, 2, 3, 8), new CalendarDateTime(2019, 2, 3, 8)); + it('should support using the arrow keys to increment and decrement the day period', async function () { + await testArrows('AM/PM,', new CalendarDateTime(2019, 2, 3, 8), new CalendarDateTime(2019, 2, 3, 20), new CalendarDateTime(2019, 2, 3, 20)); + await testArrows('AM/PM,', new CalendarDateTime(2019, 2, 3, 20), new CalendarDateTime(2019, 2, 3, 8), new CalendarDateTime(2019, 2, 3, 8)); }); }); describe('era', function () { - it('should support using the arrow keys to increment and decrement the era', function () { - testArrows('era,', new CalendarDate(new JapaneseCalendar(), 'heisei', 5, 2, 3), new CalendarDate(new JapaneseCalendar(), 'reiwa', 5, 2, 3), new CalendarDate(new JapaneseCalendar(), 'showa', 5, 2, 3), {locale: 'en-US-u-ca-japanese'}); + it('should support using the arrow keys to increment and decrement the era', async function () { + await testArrows('era,', new CalendarDate(new JapaneseCalendar(), 'heisei', 5, 2, 3), new CalendarDate(new JapaneseCalendar(), 'reiwa', 5, 2, 3), new CalendarDate(new JapaneseCalendar(), 'showa', 5, 2, 3), {locale: 'en-US-u-ca-japanese'}); }); - it('should show and hide the era field as needed', function () { + it('should show and hide the era field as needed', async function () { let {queryByTestId} = render(); let year = queryByTestId('year'); expect(queryByTestId('era')).toBeNull(); beforeInput(year, '1'); - fireEvent.keyDown(year, {key: 'ArrowDown'}); - fireEvent.keyUp(year, {key: 'ArrowDown'}); + act(() => year.focus()); + await user.keyboard('{ArrowDown}'); let era = queryByTestId('era'); expect(era).not.toBeNull(); - - fireEvent.keyDown(era, {key: 'ArrowDown'}); - fireEvent.keyUp(era, {key: 'ArrowDown'}); + act(() => era.focus()); + await user.keyboard('{ArrowDown}'); expect(queryByTestId('era')).toBeNull(); }); @@ -1538,7 +1518,7 @@ describe('DatePicker', function () { }); describe('backspace', function () { - function testBackspace(label, value, newValue, options) { + async function testBackspace(label, value, newValue, options) { let onChange = jest.fn(); // Test controlled mode @@ -1547,7 +1527,7 @@ describe('DatePicker', function () { let textContent = segment.textContent; act(() => {segment.focus();}); - fireEvent.keyDown(segment, {key: 'Backspace'}); + await user.keyboard('{Backspace}'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith(newValue); expect(segment.textContent).toBe(textContent); @@ -1560,64 +1540,64 @@ describe('DatePicker', function () { textContent = segment.textContent; act(() => {segment.focus();}); - fireEvent.keyDown(segment, {key: 'Backspace'}); + await user.keyboard('{Backspace}'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith(newValue); expect(segment.textContent).not.toBe(textContent); unmount(); } - it('should support backspace in the month segment', function () { - testBackspace('month,', new CalendarDate(2019, 2, 3), null); - testBackspace('month,', new CalendarDate(2019, 6, 3), null); - testBackspace('month,', new CalendarDate(2019, 12, 3), new CalendarDate(2019, 1, 3)); + it('should support backspace in the month segment', async function () { + await testBackspace('month,', new CalendarDate(2019, 2, 3), null); + await testBackspace('month,', new CalendarDate(2019, 6, 3), null); + await testBackspace('month,', new CalendarDate(2019, 12, 3), new CalendarDate(2019, 1, 3)); }); - it('should support backspace in the day segment', function () { - testBackspace('day,', new CalendarDate(2019, 2, 3), null); - testBackspace('day,', new CalendarDate(2019, 2, 20), new CalendarDate(2019, 2, 2)); + it('should support backspace in the day segment', async function () { + await testBackspace('day,', new CalendarDate(2019, 2, 3), null); + await testBackspace('day,', new CalendarDate(2019, 2, 20), new CalendarDate(2019, 2, 2)); }); - it('should support backspace in the year segment', function () { - testBackspace('year,', new CalendarDate(2019, 2, 3), new CalendarDate(201, 2, 3)); - testBackspace('year,', new CalendarDate(2, 2, 3), null); + it('should support backspace in the year segment', async function () { + await testBackspace('year,', new CalendarDate(2019, 2, 3), new CalendarDate(201, 2, 3)); + await testBackspace('year,', new CalendarDate(2, 2, 3), null); }); - it('should support backspace in the hour segment in 12 hour time', function () { + it('should support backspace in the hour segment in 12 hour time', async function () { // AM - testBackspace('hour,', new CalendarDateTime(2019, 2, 3, 8), null); - testBackspace('hour,', new CalendarDateTime(2019, 2, 3, 11), new CalendarDateTime(2019, 2, 3, 1)); + await testBackspace('hour,', new CalendarDateTime(2019, 2, 3, 8), null); + await testBackspace('hour,', new CalendarDateTime(2019, 2, 3, 11), new CalendarDateTime(2019, 2, 3, 1)); // PM - testBackspace('hour,', new CalendarDateTime(2019, 2, 3, 16), null); - testBackspace('hour,', new CalendarDateTime(2019, 2, 3, 23), new CalendarDateTime(2019, 2, 3, 13)); + await testBackspace('hour,', new CalendarDateTime(2019, 2, 3, 16), null); + await testBackspace('hour,', new CalendarDateTime(2019, 2, 3, 23), new CalendarDateTime(2019, 2, 3, 13)); }); - it('should support backspace in the hour segment in 24 hour time', function () { - testBackspace('hour,', new CalendarDateTime(2019, 2, 3, 8), null, {hourCycle: 24}); - testBackspace('hour,', new CalendarDateTime(2019, 2, 3, 11), new CalendarDateTime(2019, 2, 3, 1), {hourCycle: 24}); - testBackspace('hour,', new CalendarDateTime(2019, 2, 3, 16), new CalendarDateTime(2019, 2, 3, 1), {hourCycle: 24}); - testBackspace('hour,', new CalendarDateTime(2019, 2, 3, 23), new CalendarDateTime(2019, 2, 3, 2), {hourCycle: 24}); + it('should support backspace in the hour segment in 24 hour time', async function () { + await testBackspace('hour,', new CalendarDateTime(2019, 2, 3, 8), null, {hourCycle: 24}); + await testBackspace('hour,', new CalendarDateTime(2019, 2, 3, 11), new CalendarDateTime(2019, 2, 3, 1), {hourCycle: 24}); + await testBackspace('hour,', new CalendarDateTime(2019, 2, 3, 16), new CalendarDateTime(2019, 2, 3, 1), {hourCycle: 24}); + await testBackspace('hour,', new CalendarDateTime(2019, 2, 3, 23), new CalendarDateTime(2019, 2, 3, 2), {hourCycle: 24}); }); - it('should support backspace in the am/pm field', function () { - testBackspace('AM/PM,', new CalendarDateTime(2019, 2, 3, 8), null); - testBackspace('AM/PM,', new CalendarDateTime(2019, 2, 3, 16), null); + it('should support backspace in the am/pm field', async function () { + await testBackspace('AM/PM,', new CalendarDateTime(2019, 2, 3, 8), null); + await testBackspace('AM/PM,', new CalendarDateTime(2019, 2, 3, 16), null); }); - it('should support backspace in the minute segment', function () { - testBackspace('minute,', new CalendarDateTime(2019, 2, 3, 5, 8), null); - testBackspace('minute,', new CalendarDateTime(2019, 2, 3, 5, 25), new CalendarDateTime(2019, 2, 3, 5, 2)); - testBackspace('minute,', new CalendarDateTime(2019, 2, 3, 5, 59), new CalendarDateTime(2019, 2, 3, 5, 5)); + it('should support backspace in the minute segment', async function () { + await testBackspace('minute,', new CalendarDateTime(2019, 2, 3, 5, 8), null); + await testBackspace('minute,', new CalendarDateTime(2019, 2, 3, 5, 25), new CalendarDateTime(2019, 2, 3, 5, 2)); + await testBackspace('minute,', new CalendarDateTime(2019, 2, 3, 5, 59), new CalendarDateTime(2019, 2, 3, 5, 5)); }); - it('should support second in the minute segment', function () { - testBackspace('second,', new CalendarDateTime(2019, 2, 3, 5, 5, 8), null, {granularity: 'second'}); - testBackspace('second,', new CalendarDateTime(2019, 2, 3, 5, 5, 25), new CalendarDateTime(2019, 2, 3, 5, 5, 2), {granularity: 'second'}); - testBackspace('second,', new CalendarDateTime(2019, 2, 3, 5, 5, 59), new CalendarDateTime(2019, 2, 3, 5, 5, 5), {granularity: 'second'}); + it('should support second in the minute segment', async function () { + await testBackspace('second,', new CalendarDateTime(2019, 2, 3, 5, 5, 8), null, {granularity: 'second'}); + await testBackspace('second,', new CalendarDateTime(2019, 2, 3, 5, 5, 25), new CalendarDateTime(2019, 2, 3, 5, 5, 2), {granularity: 'second'}); + await testBackspace('second,', new CalendarDateTime(2019, 2, 3, 5, 5, 59), new CalendarDateTime(2019, 2, 3, 5, 5, 5), {granularity: 'second'}); }); - it('should support backspace with arabic digits', function () { + it('should support backspace with arabic digits', async function () { let onChange = jest.fn(); let {getByLabelText} = render( @@ -1628,7 +1608,7 @@ describe('DatePicker', function () { expect(segment).toHaveTextContent('٢٠١٩'); act(() => {segment.focus();}); - fireEvent.keyDown(segment, {key: 'Backspace'}); + await user.keyboard('{Backspace}'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith(new CalendarDate(201, 2, 3)); expect(segment).toHaveTextContent('٢٠١'); @@ -1642,16 +1622,17 @@ describe('DatePicker', function () { expect(getByTestId('invalid-icon')).toBeVisible(); }); - it('should display an error icon when date is less than the minimum (uncontrolled)', function () { + it('should display an error icon when date is less than the minimum (uncontrolled)', async function () { let {getByTestId, getByLabelText, queryByTestId} = render(); expect(queryByTestId('invalid-icon')).toBeNull(); let year = getByLabelText('year,'); - fireEvent.keyDown(year, {key: 'ArrowDown'}); + act(() => year.focus()); + await user.keyboard('{ArrowDown}'); expect(getByTestId('invalid-icon')).toBeVisible(); - fireEvent.keyDown(year, {key: 'ArrowUp'}); + await user.keyboard('{ArrowUp}'); expect(queryByTestId('invalid-icon')).toBeNull(); }); @@ -1660,16 +1641,17 @@ describe('DatePicker', function () { expect(getByTestId('invalid-icon')).toBeVisible(); }); - it('should display an error icon when date is greater than the maximum (uncontrolled)', function () { + it('should display an error icon when date is greater than the maximum (uncontrolled)', async function () { let {getByTestId, getByLabelText, queryByTestId} = render(); expect(queryByTestId('invalid-icon')).toBeNull(); let year = getByLabelText('year,'); - fireEvent.keyDown(year, {key: 'ArrowUp'}); + act(() => year.focus()); + await user.keyboard('{ArrowUp}'); expect(getByTestId('invalid-icon')).toBeVisible(); - fireEvent.keyDown(year, {key: 'ArrowDown'}); + await user.keyboard('{ArrowDown}'); expect(queryByTestId('invalid-icon')).toBeNull(); }); }); @@ -1699,7 +1681,7 @@ describe('DatePicker', function () { expectPlaceholder(combobox, 'mm/dd/yyyy'); }); - it('should use arrow keys to modify placeholder (uncontrolled)', function () { + it('should use arrow keys to modify placeholder (uncontrolled)', async function () { let onChange = jest.fn(); let {getAllByRole} = render(); @@ -1710,8 +1692,8 @@ describe('DatePicker', function () { let segments = getAllByRole('spinbutton'); act(() => {segments[0].focus();}); - fireEvent.keyDown(document.activeElement, {key: 'ArrowUp'}); - fireEvent.keyDown(document.activeElement, {key: 'ArrowRight'}); + await user.keyboard('{ArrowUp}'); + await user.keyboard('{ArrowRight}'); expect(segments[1]).toHaveFocus(); expect(onChange).not.toHaveBeenCalled(); let value = today(getLocalTimeZone()); @@ -1719,8 +1701,8 @@ describe('DatePicker', function () { let month = parts.find(p => p.type === 'month').value; expectPlaceholder(combobox, `${month}/dd/yyyy`); - fireEvent.keyDown(document.activeElement, {key: 'ArrowUp'}); - fireEvent.keyDown(document.activeElement, {key: 'ArrowRight'}); + await user.keyboard('{ArrowUp}'); + await user.keyboard('{ArrowRight}'); expect(segments[2]).toHaveFocus(); expect(onChange).not.toHaveBeenCalled(); parts = formatter.formatToParts(value.toDate(getLocalTimeZone())); @@ -1728,13 +1710,13 @@ describe('DatePicker', function () { let day = parts.find(p => p.type === 'day').value; expectPlaceholder(combobox, `${month}/${day}/yyyy`); - fireEvent.keyDown(document.activeElement, {key: 'ArrowUp'}); + await user.keyboard('{ArrowUp}'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith(value); expectPlaceholder(combobox, formatter.format(value.toDate(getLocalTimeZone()))); }); - it('should use arrow keys to modify placeholder (controlled)', function () { + it('should use arrow keys to modify placeholder (controlled)', async function () { let onChange = jest.fn(); let {getAllByRole, rerender} = render(); @@ -1745,8 +1727,8 @@ describe('DatePicker', function () { let segments = getAllByRole('spinbutton'); act(() => {segments[0].focus();}); - fireEvent.keyDown(document.activeElement, {key: 'ArrowUp'}); - fireEvent.keyDown(document.activeElement, {key: 'ArrowRight'}); + await user.keyboard('{ArrowUp}'); + await user.keyboard('{ArrowRight}'); expect(segments[1]).toHaveFocus(); expect(onChange).not.toHaveBeenCalled(); let value = today(getLocalTimeZone()); @@ -1754,8 +1736,8 @@ describe('DatePicker', function () { let month = parts.find(p => p.type === 'month').value; expectPlaceholder(combobox, `${month}/dd/yyyy`); - fireEvent.keyDown(document.activeElement, {key: 'ArrowUp'}); - fireEvent.keyDown(document.activeElement, {key: 'ArrowRight'}); + await user.keyboard('{ArrowUp}'); + await user.keyboard('{ArrowRight}'); expect(segments[2]).toHaveFocus(); expect(onChange).not.toHaveBeenCalled(); parts = formatter.formatToParts(value.toDate(getLocalTimeZone())); @@ -1763,7 +1745,7 @@ describe('DatePicker', function () { let day = parts.find(p => p.type === 'day').value; expectPlaceholder(combobox, `${month}/${day}/yyyy`); - fireEvent.keyDown(document.activeElement, {key: 'ArrowUp'}); + await user.keyboard('{ArrowUp}'); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledWith(value); expectPlaceholder(combobox, 'mm/dd/yyyy'); // controlled @@ -1917,18 +1899,17 @@ describe('DatePicker', function () { ); } - let {getByTestId, getByRole, getAllByRole} = render(); + let {getByTestId, getByRole} = render(); let group = getByRole('group'); let input = document.querySelector('input[name=date]'); - let segments = getAllByRole('spinbutton'); let getDescription = () => group.getAttribute('aria-describedby').split(' ').map(d => document.getElementById(d).textContent).join(' '); expect(getDescription()).toBe('Selected Date: February 3, 2020'); expect(input).toHaveValue('2020-02-03'); expect(input).toHaveAttribute('name', 'date'); - fireEvent.keyDown(segments[0], {key: 'ArrowUp'}); - fireEvent.keyUp(segments[0], {key: 'ArrowUp'}); + await user.tab(); + await user.keyboard('{ArrowUp}'); expect(getDescription()).toBe('Selected Date: March 3, 2020'); expect(input).toHaveValue('2020-03-03'); From 6537adb698592e39e281ecb0faba300a56e81008 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Wed, 6 Dec 2023 14:06:24 -0800 Subject: [PATCH 17/31] fix tests in 16/17 again missing asyncs --- .../autocomplete/test/SearchAutocomplete.test.js | 8 ++++---- .../@react-spectrum/combobox/test/ComboBox.test.js | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/@react-spectrum/autocomplete/test/SearchAutocomplete.test.js b/packages/@react-spectrum/autocomplete/test/SearchAutocomplete.test.js index 4534e345a55..370350952d6 100644 --- a/packages/@react-spectrum/autocomplete/test/SearchAutocomplete.test.js +++ b/packages/@react-spectrum/autocomplete/test/SearchAutocomplete.test.js @@ -310,7 +310,7 @@ describe('SearchAutocomplete', function () { describe('opening', function () { describe('menuTrigger = focus', function () { - it('opens menu when searchAutocomplete is focused', function () { + it('opens menu when searchAutocomplete is focused', async function () { let {getByRole} = renderSearchAutocomplete({menuTrigger: 'focus'}); let searchAutocomplete = getByRole('combobox'); @@ -324,7 +324,7 @@ describe('SearchAutocomplete', function () { let listbox = getByRole('listbox'); expect(onOpenChange).toBeCalledTimes(1); expect(onOpenChange).toHaveBeenCalledWith(true, 'focus'); - testSearchAutocompleteOpen(searchAutocomplete, listbox); + await testSearchAutocompleteOpen(searchAutocomplete, listbox); }); }); @@ -345,7 +345,7 @@ describe('SearchAutocomplete', function () { let listbox = getByRole('listbox'); expect(onOpenChange).toHaveBeenCalledTimes(1); expect(onOpenChange).toHaveBeenCalledWith(true, 'manual'); - testSearchAutocompleteOpen(searchAutocomplete, listbox, 0); + await testSearchAutocompleteOpen(searchAutocomplete, listbox, 0); }); it('opens the menu on up arrow press', async function () { @@ -364,7 +364,7 @@ describe('SearchAutocomplete', function () { let listbox = getByRole('listbox'); expect(onOpenChange).toHaveBeenCalledTimes(1); expect(onOpenChange).toHaveBeenCalledWith(true, 'manual'); - testSearchAutocompleteOpen(searchAutocomplete, listbox, 2); + await testSearchAutocompleteOpen(searchAutocomplete, listbox, 2); }); it('opens the menu on user typing', async function () { diff --git a/packages/@react-spectrum/combobox/test/ComboBox.test.js b/packages/@react-spectrum/combobox/test/ComboBox.test.js index 62d97c8fa4a..472dce0e30c 100644 --- a/packages/@react-spectrum/combobox/test/ComboBox.test.js +++ b/packages/@react-spectrum/combobox/test/ComboBox.test.js @@ -435,7 +435,7 @@ describe('ComboBox', function () { describe('opening', function () { describe('menuTrigger = focus', function () { - it('opens menu when combobox is focused', function () { + it('opens menu when combobox is focused', async function () { let {getByRole} = renderComboBox({menuTrigger: 'focus'}); let button = getByRole('button'); @@ -450,7 +450,7 @@ describe('ComboBox', function () { let listbox = getByRole('listbox'); expect(onOpenChange).toBeCalledTimes(1); expect(onOpenChange).toHaveBeenCalledWith(true, 'focus'); - testComboBoxOpen(combobox, button, listbox); + await testComboBoxOpen(combobox, button, listbox); }); it('opens menu when combobox is focused by clicking button', async function () { @@ -466,7 +466,7 @@ describe('ComboBox', function () { let listbox = getByRole('listbox'); expect(onOpenChange).toBeCalledTimes(1); expect(onOpenChange).toHaveBeenCalledWith(true, 'focus'); - testComboBoxOpen(combobox, button, listbox); + await testComboBoxOpen(combobox, button, listbox); }); }); @@ -511,7 +511,7 @@ describe('ComboBox', function () { expect(onOpenChange).toHaveBeenCalledWith(true, 'manual'); let listbox = getByRole('listbox'); - testComboBoxOpen(combobox, button, listbox); + await testComboBoxOpen(combobox, button, listbox); }); it('opens for touch', () => { @@ -593,7 +593,7 @@ describe('ComboBox', function () { expect(onOpenChange).toHaveBeenCalledWith(true, 'manual'); let listbox = getByRole('listbox'); - testComboBoxOpen(combobox, button, listbox); + await testComboBoxOpen(combobox, button, listbox); }); }); @@ -615,7 +615,7 @@ describe('ComboBox', function () { let listbox = getByRole('listbox'); expect(onOpenChange).toHaveBeenCalledTimes(1); expect(onOpenChange).toHaveBeenCalledWith(true, 'manual'); - testComboBoxOpen(combobox, button, listbox, 0); + await testComboBoxOpen(combobox, button, listbox, 0); }); it('opens the menu on up arrow press', async function () { @@ -635,7 +635,7 @@ describe('ComboBox', function () { let listbox = getByRole('listbox'); expect(onOpenChange).toHaveBeenCalledTimes(1); expect(onOpenChange).toHaveBeenCalledWith(true, 'manual'); - testComboBoxOpen(combobox, button, listbox, 2); + await testComboBoxOpen(combobox, button, listbox, 2); }); it('opens the menu on user typing', async function () { From 409e8b4c33fce5b76d240f605f4ba0878d6fbe1f Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Wed, 6 Dec 2023 17:00:35 -0800 Subject: [PATCH 18/31] updating testing docs and linking to it from various components --- .../autocomplete/docs/SearchAutocomplete.mdx | 19 ++++ .../combobox/docs/ComboBox.mdx | 19 ++++ .../contextualhelp/docs/ContextualHelp.mdx | 9 ++ .../datepicker/docs/DatePicker.mdx | 13 +++ .../datepicker/docs/DateRangePicker.mdx | 13 +++ .../dialog/docs/AlertDialog.mdx | 10 ++ .../dialog/docs/DialogContainer.mdx | 10 ++ .../dialog/docs/DialogTrigger.mdx | 10 ++ .../@react-spectrum/list/docs/ListView.mdx | 18 ++++ .../@react-spectrum/listbox/docs/ListBox.mdx | 12 +++ .../@react-spectrum/menu/docs/ActionMenu.mdx | 13 +++ .../@react-spectrum/menu/docs/MenuTrigger.mdx | 16 ++++ .../@react-spectrum/picker/docs/Picker.mdx | 18 ++++ .../@react-spectrum/table/docs/TableView.mdx | 18 ++++ .../@react-spectrum/tooltip/docs/Tooltip.mdx | 10 ++ .../dev/docs/pages/react-spectrum/testing.mdx | 91 +++++++++++++------ 16 files changed, 270 insertions(+), 29 deletions(-) diff --git a/packages/@react-spectrum/autocomplete/docs/SearchAutocomplete.mdx b/packages/@react-spectrum/autocomplete/docs/SearchAutocomplete.mdx index e23d4c329f9..4f406ea06c2 100644 --- a/packages/@react-spectrum/autocomplete/docs/SearchAutocomplete.mdx +++ b/packages/@react-spectrum/autocomplete/docs/SearchAutocomplete.mdx @@ -458,3 +458,22 @@ For right-to-left (RTL) languages, this is flipped. Snake ``` + +## Testing + +The SearchAutocomplete features an overlay that transitions in and out of the page as it is opened and closed. Depending on +your device configuration, this overlay may render as a tray or a dropdown and the trigger itself may render as a button or a input. Additionally, +the SearchAutocomplete features automatic virtualization and may need specific mocks in a test environment to enable said virtualization properly. +Please see the following sections in the testing docs for more information on how to handle these +behaviors in your test suite. + +[Timers](./testing.html#timers) + +[Desktop vs Mobile](./testing.html#desktop-vs-mobile) + +[Virtualized Components](./testing.html#virtualized-components) + +[Long press](./testing.html#simulating-user-long-press) + +Please also refer to [React Spectrum's test suite](https://github.com/adobe/react-spectrum/blob/main/packages/%40react-spectrum/autocomplete/test/SearchAutocomplete.test.js) if you find that the above +isn't sufficient when resolving issues in your own test cases. diff --git a/packages/@react-spectrum/combobox/docs/ComboBox.mdx b/packages/@react-spectrum/combobox/docs/ComboBox.mdx index 2d62bd5eca4..83685b8938c 100644 --- a/packages/@react-spectrum/combobox/docs/ComboBox.mdx +++ b/packages/@react-spectrum/combobox/docs/ComboBox.mdx @@ -948,3 +948,22 @@ import {Content, ContextualHelp, Heading} from '@adobe/react-spectrum'; Snake ``` + +## Testing + +The ComboBox features an overlay that transitions in and out of the page as it is opened and closed. Depending on +your device configuration, this overlay may render as a tray or a dropdown and the trigger itself may render as a button or a input. Additionally, +the ComboBox features automatic virtualization and may need specific mocks in a test environment to enable said virtualization properly. +Please see the following sections in the testing docs for more information on how to handle these +behaviors in your test suite. + +[Timers](./testing.html#timers) + +[Desktop vs Mobile](./testing.html#desktop-vs-mobile) + +[Virtualized Components](./testing.html#virtualized-components) + +[Long press](./testing.html#simulating-user-long-press) + +Please also refer to [React Spectrum's test suite](https://github.com/adobe/react-spectrum/blob/main/packages/%40react-spectrum/combobox/test/ComboBox.test.js) if you find that the above +isn't sufficient when resolving issues in your own test cases. diff --git a/packages/@react-spectrum/contextualhelp/docs/ContextualHelp.mdx b/packages/@react-spectrum/contextualhelp/docs/ContextualHelp.mdx index 824037edac4..52272fecdb4 100644 --- a/packages/@react-spectrum/contextualhelp/docs/ContextualHelp.mdx +++ b/packages/@react-spectrum/contextualhelp/docs/ContextualHelp.mdx @@ -126,3 +126,12 @@ This may include an image, video, or link and should be [helpful](https://spectr ``` +## Testing + +The ContextualHelpTrigger features an overlay that transitions in and out of the page as it is opened and closed. +Please see the following sections in the testing docs for more information on how to handle these behaviors in your test suite. + +[Timers](./testing.html#timers) + +Please also refer to [React Spectrum's test suite](https://github.com/adobe/react-spectrum/blob/main/packages/%40react-spectrum/dialog/test/AlertDialog.test.js) if you find that the above +isn't sufficient when resolving issues in your own test cases. diff --git a/packages/@react-spectrum/datepicker/docs/DatePicker.mdx b/packages/@react-spectrum/datepicker/docs/DatePicker.mdx index 31a470af4a6..ec1ee6ab226 100644 --- a/packages/@react-spectrum/datepicker/docs/DatePicker.mdx +++ b/packages/@react-spectrum/datepicker/docs/DatePicker.mdx @@ -440,3 +440,16 @@ By default, `DatePicker` displays times in either 12 or 24 hour hour format depe granularity="minute" hourCycle={24} /> ``` + +## Testing + +The DatePicker features an overlay that transitions in and out of the page as it is opened and closed. Depending on +your configuration, this overlay may render as a tray or a popover. Please see the following sections in the +testing docs for more information on how to handle these behaviors in your test suite. + +[Timers](./testing.html#timers) + +[Desktop vs Mobile](./testing.html#desktop-vs-mobile) + +Please also refer to [React Spectrum's test suite](https://github.com/adobe/react-spectrum/blob/main/packages/%40react-spectrum/datepicker/test/DateField.test.js) if you find that the above +isn't sufficient when resolving issues in your own test cases. diff --git a/packages/@react-spectrum/datepicker/docs/DateRangePicker.mdx b/packages/@react-spectrum/datepicker/docs/DateRangePicker.mdx index 9d584d5aee5..68be8285a29 100644 --- a/packages/@react-spectrum/datepicker/docs/DateRangePicker.mdx +++ b/packages/@react-spectrum/datepicker/docs/DateRangePicker.mdx @@ -477,3 +477,16 @@ By default, `DateRangePicker` displays times in either 12 or 24 hour hour format granularity="minute" hourCycle={24} /> ``` + +## Testing + +The DateRangePicker features an overlay that transitions in and out of the page as it is opened and closed. Depending on +your configuration, this overlay may render as a tray or a popover. Please see the following sections in the +testing docs for more information on how to handle these behaviors in your test suite. + +[Timers](./testing.html#timers) + +[Desktop vs Mobile](./testing.html#desktop-vs-mobile) + +Please also refer to [React Spectrum's test suite](https://github.com/adobe/react-spectrum/blob/main/packages/%40react-spectrum/datepicker/docs/DateRangePicker.mdx) if you find that the above +isn't sufficient when resolving issues in your own test cases. diff --git a/packages/@react-spectrum/dialog/docs/AlertDialog.mdx b/packages/@react-spectrum/dialog/docs/AlertDialog.mdx index 6aec1e148bd..5498c3c88dc 100644 --- a/packages/@react-spectrum/dialog/docs/AlertDialog.mdx +++ b/packages/@react-spectrum/dialog/docs/AlertDialog.mdx @@ -240,3 +240,13 @@ Disables the secondary button. ``` + +## Testing + +The AlertDialog features an overlay that transitions in and out of the page as it is opened and closed. +Please see the following sections in the testing docs for more information on how to handle these behaviors in your test suite. + +[Timers](./testing.html#timers) + +Please also refer to [React Spectrum's test suite](https://github.com/adobe/react-spectrum/blob/main/packages/%40react-spectrum/contextualhelp/test/ContextualHelp.test.js) if you find that the above +isn't sufficient when resolving issues in your own test cases. diff --git a/packages/@react-spectrum/dialog/docs/DialogContainer.mdx b/packages/@react-spectrum/dialog/docs/DialogContainer.mdx index e810ef4c19b..a78033de3d5 100644 --- a/packages/@react-spectrum/dialog/docs/DialogContainer.mdx +++ b/packages/@react-spectrum/dialog/docs/DialogContainer.mdx @@ -232,3 +232,13 @@ function EditDialog() { ); } ``` + +## Testing + +The DialogContainer features an overlay that transitions in and out of the page as it is opened and closed. +Please see the following sections in the testing docs for more information on how to handle these behaviors in your test suite. + +[Timers](./testing.html#timers) + +Please also refer to [React Spectrum's test suite](https://github.com/adobe/react-spectrum/blob/main/packages/%40react-spectrum/dialog/test/DialogContainer.test.js) if you find that the above +isn't sufficient when resolving issues in your own test cases. diff --git a/packages/@react-spectrum/dialog/docs/DialogTrigger.mdx b/packages/@react-spectrum/dialog/docs/DialogTrigger.mdx index 8b353478bd6..8d6264d6f58 100644 --- a/packages/@react-spectrum/dialog/docs/DialogTrigger.mdx +++ b/packages/@react-spectrum/dialog/docs/DialogTrigger.mdx @@ -458,3 +458,13 @@ function Example() { ## Props + +## Testing + +The DialogTrigger features an overlay that transitions in and out of the page as it is opened and closed. +Please see the following sections in the testing docs for more information on how to handle these behaviors in your test suite. + +[Timers](./testing.html#timers) + +Please also refer to [React Spectrum's test suite](https://github.com/adobe/react-spectrum/blob/main/packages/%40react-spectrum/dialog/test/DialogTrigger.test.js) if you find that the above +isn't sufficient when resolving issues in your own test cases. diff --git a/packages/@react-spectrum/list/docs/ListView.mdx b/packages/@react-spectrum/list/docs/ListView.mdx index 46aca5113dc..362fa71631f 100644 --- a/packages/@react-spectrum/list/docs/ListView.mdx +++ b/packages/@react-spectrum/list/docs/ListView.mdx @@ -1173,3 +1173,21 @@ function renderEmptyState() { {[]} ``` + +## Testing + +The ListView features automatic virtualization and may need specific mocks in a test environment to enable said virtualization properly. +It also features long press interactions on its rows depending on the row actions provided and if user is interacting with the list on +a touch device. Please see the following sections in the testing docs for more information on how to handle these +behaviors in your test suite. + +[Timers](./testing.html#timers) + +[Desktop vs Mobile](./testing.html#desktop-vs-mobile) + +[Virtualized Components](./testing.html#virtualized-components) + +[Long press](./testing.html#simulating-user-long-press) + +Please also refer to [React Spectrum's test suite](https://github.com/adobe/react-spectrum/blob/main/packages/%40react-spectrum/list/test/ListView.test.js) if you find that the above +isn't sufficient when resolving issues in your own test cases. diff --git a/packages/@react-spectrum/listbox/docs/ListBox.mdx b/packages/@react-spectrum/listbox/docs/ListBox.mdx index 6a199a347ce..ac43e58c682 100644 --- a/packages/@react-spectrum/listbox/docs/ListBox.mdx +++ b/packages/@react-spectrum/listbox/docs/ListBox.mdx @@ -367,3 +367,15 @@ Use the `disabledKeys` prop to specify which item keys to disable in the ListBox ``` + +## Testing + +The ListBox features automatic virtualization and may need specific mocks in a test environment to enable said virtualization properly. +Please see the following sections in the testing docs for more information on how to handle these behaviors in your test suite. + +[Timers](./testing.html#timers) + +[Virtualized Components](./testing.html#virtualized-components) + +Please also refer to [React Spectrum's test suite](https://github.com/adobe/react-spectrum/blob/main/packages/%40react-spectrum/listbox/test/ListBox.test.js) if you find that the above +isn't sufficient when resolving issues in your own test cases. diff --git a/packages/@react-spectrum/menu/docs/ActionMenu.mdx b/packages/@react-spectrum/menu/docs/ActionMenu.mdx index eba9c7271c3..12bad4397ea 100644 --- a/packages/@react-spectrum/menu/docs/ActionMenu.mdx +++ b/packages/@react-spectrum/menu/docs/ActionMenu.mdx @@ -329,3 +329,16 @@ function Example() { ); } ``` + +## Testing + +The ActionMenu features an overlay that transitions in and out of the page as it is opened and closed. Depending on +your configuration, this overlay may render as a tray or a dropdown. Please see the following sections in the +testing docs for more information on how to handle these behaviors in your test suite. + +[Timers](./testing.html#timers) + +[Desktop vs Mobile](./testing.html#desktop-vs-mobile) + +Please also refer to [React Spectrum's test suite](https://github.com/adobe/react-spectrum/blob/main/packages/%40react-spectrum/menu/test/ActionMenu.test.js) if you find that the above +isn't sufficient when resolving issues in your own test cases. diff --git a/packages/@react-spectrum/menu/docs/MenuTrigger.mdx b/packages/@react-spectrum/menu/docs/MenuTrigger.mdx index b93c37510a1..ffcaade3523 100644 --- a/packages/@react-spectrum/menu/docs/MenuTrigger.mdx +++ b/packages/@react-spectrum/menu/docs/MenuTrigger.mdx @@ -240,3 +240,19 @@ function Example() { ); } ``` + +## Testing + +The Menu features an overlay that transitions in and out of the page as it is opened and closed. Depending on +your configuration, this overlay may render as a tray or a dropdown and may feature long press interactions on the +trigger itself. Please see the following sections in the testing docs for more information on how to handle these +behaviors in your test suite. + +[Timers](./testing.html#timers) + +[Desktop vs Mobile](./testing.html#desktop-vs-mobile) + +[Long press](./testing.html#simulating-user-long-press) + +Please also refer to [React Spectrum's test suite](https://github.com/adobe/react-spectrum/blob/main/packages/%40react-spectrum/menu/test/MenuTrigger.test.js) if you find that the above +isn't sufficient when resolving issues in your own test cases. diff --git a/packages/@react-spectrum/picker/docs/Picker.mdx b/packages/@react-spectrum/picker/docs/Picker.mdx index 117e18afe42..4d0c7aa23ce 100644 --- a/packages/@react-spectrum/picker/docs/Picker.mdx +++ b/packages/@react-spectrum/picker/docs/Picker.mdx @@ -544,3 +544,21 @@ knowing that we manage the focus in this way and thus throw this false positive. To facilitate the suppression of this false positive, the `data-a11y-ignore="aria-hidden-focus"` data attribute is automatically applied to the problematic element and references the relevant `AXE` rule. Please use this data attribute to target the problematic element and exclude it from your automated accessibility tests as shown [here](../react-aria/accessibility.html#false-positives). + +## Testing + +The Picker features an overlay that transitions in and out of the page as it is opened and closed. Depending on +your device configuration, this overlay may render as a tray or a dropdown. Additionally, the Picker features automatic virtualization +and may need specific mocks in a test environment to enable said virtualization properly. Please see the following sections in the testing docs +for more information on how to handle these behaviors in your test suite. + +[Timers](./testing.html#timers) + +[Desktop vs Mobile](./testing.html#desktop-vs-mobile) + +[Virtualized Components](./testing.html#virtualized-components) + +[Long press](./testing.html#simulating-user-long-press) + +Please also refer to [React Spectrum's test suite](https://github.com/adobe/react-spectrum/blob/main/packages/%40react-spectrum/picker/test/Picker.test.js) if you find that the above +isn't sufficient when resolving issues in your own test cases. diff --git a/packages/@react-spectrum/table/docs/TableView.mdx b/packages/@react-spectrum/table/docs/TableView.mdx index c7dd7c530a3..25c92f6ffca 100644 --- a/packages/@react-spectrum/table/docs/TableView.mdx +++ b/packages/@react-spectrum/table/docs/TableView.mdx @@ -1939,3 +1939,21 @@ let rows = [ ``` + +## Testing + +The TableView features automatic virtualization and may need specific mocks in a test environment to enable said virtualization properly. +It also features long press interactions on its rows depending on the row actions provided and if user is interacting with the list on +a touch device. Please see the following sections in the testing docs for more information on how to handle these +behaviors in your test suite. + +[Timers](./testing.html#timers) + +[Desktop vs Mobile](./testing.html#desktop-vs-mobile) + +[Virtualized Components](./testing.html#virtualized-components) + +[Long press](./testing.html#simulating-user-long-press) + +Please also refer to [React Spectrum's test suite](https://github.com/adobe/react-spectrum/blob/main/packages/%40react-spectrum/table/test/Table.test.js) if you find that the above +isn't sufficient when resolving issues in your own test cases. diff --git a/packages/@react-spectrum/tooltip/docs/Tooltip.mdx b/packages/@react-spectrum/tooltip/docs/Tooltip.mdx index c8056c837b0..9a44fe3b6f5 100644 --- a/packages/@react-spectrum/tooltip/docs/Tooltip.mdx +++ b/packages/@react-spectrum/tooltip/docs/Tooltip.mdx @@ -194,3 +194,13 @@ A TooltipTrigger can be disabled without disabling the trigger it displays on. Dangerous action. ``` + +## Testing + +The TooltipTrigger features an popover that transitions in and out of the page as it is opened and closed. It also has a warmup and cooldown +time that you've have to account for when interacting with it. Please see the following sections in the testing docs for more information on how to handle these behaviors in your test suite. + +[Timers](./testing.html#timers) + +Please also refer to [React Spectrum's test suite](https://github.com/adobe/react-spectrum/blob/main/packages/%40react-spectrum/tooltip/test/TooltipTrigger.test.js) if you find that the above +isn't sufficient when resolving issues in your own test cases. diff --git a/packages/dev/docs/pages/react-spectrum/testing.mdx b/packages/dev/docs/pages/react-spectrum/testing.mdx index 3dc57e6c80d..b579c955d97 100644 --- a/packages/dev/docs/pages/react-spectrum/testing.mdx +++ b/packages/dev/docs/pages/react-spectrum/testing.mdx @@ -157,7 +157,7 @@ userEvent.tab(); userEvent.click(document.activeElement); ``` -## Test setup +## Test setup and common gotchas ### Providers @@ -174,26 +174,36 @@ TypeError: Cannot read properties of null (reading 'scale') ``` If you are using React Testing Library, you can overwrite the provided `render` function so that it automatically includes a Provider by default. +Note the below example allows you to rerender the component with new Provider props but you'll need to requery any element you are asserting against +to get its updated state (e.g. `button = getByRole('button)`). -// TODO: replace this with our util if we go that direction. Also test this ```tsx +import {RenderOptions as BaseRenderOptions, render} from '@testing-library/react'; import {Provider, defaultTheme} from '@adobe/react-spectrum'; import React, {ReactElement} from 'react'; -import {render} from '@testing-library/react'; // export everything from React Testing Library export * from '@testing-library/react'; function ProviderWrapper(props) { + let {children, ...providerProps} = props; return ( - + {props.children} ); } -export function customRender(ui, options) { - return render(ui, {wrapper: ProviderWrapper, ...options}); +interface RenderOptions extends BaseRenderOptions { + providerProps: Omit +} + +function customRender(ui: ReactElement, options?: RenderOptions) { + let rendered = render(ui, {wrapper: (props) => , ...options}); + return { + ...rendered, + rerender: (ui, options) => providerWrapperRender(ui, {container: rendered.container, ...options}) + }; } // override render method @@ -204,8 +214,9 @@ export {customRender as render}; If you are using fake timers in your test suite, be aware that you may need to advance your timers whenever an animation or load is taking place. Historically, this most commonly happened when a modals, popovers, or trays is opened or closed as a result of a simulated user action (e.g. opening a Picker's dropdown via click). -In Jest, this can be handled by calling `act(() => jest.runAllTimers());` but you may require more precise control depending on the other time sensitive behavior you -are testing. Please see [Jest's timer docs](https://jestjs.io/docs/timer-mocks) or the equivalent docs of your test frameworks for more information on how to do so. +Additionally, we have `requestAnimationFrame` calls in various areas that you will need to also handle by advancing your timers in the tests. This happens most prominently +in our virtualized components due to the internals of our Virtualizer. In Jest, this can be handled by calling `act(() => jest.runAllTimers());` but you may require more precise control +depending on the other time sensitive behavior you are testing. Please see [Jest's timer docs](https://jestjs.io/docs/timer-mocks) or the equivalent docs of your test frameworks for more information on how to do so. It is also a good idea to run all timers to completion after each test case to avoid any left over transitions or timeouts that a component may have setup during its lifecycle. ```tsx @@ -216,7 +227,7 @@ afterEach(() => { Consider adding a `act(() => jest.runAllTimers());` after your simulated user interaction if you run into a test failure that looks like the following: -```tsx +``` TestingLibraryElementError: Unable to find an accessible element with the role "listbox" ``` @@ -234,17 +245,26 @@ await waitFor(() => { Components like ComboBox and Picker render a different experience on mobile versus desktop. If you need to test mobile vs desktop for you app or want to make sure the React Spectrum components are rendered only against a specific experience, you'll need to mock the window screen width accordingly. We currently use a [screen width of 700px](https://github.com/adobe/react-spectrum/blob/5e487532e3ca4714513fb6ab64f7a78d9d1ca281/packages/%40react-spectrum/utils/src/useIsMobileDevice.ts#L15-L23) as the breakpoint -between mobile and desktop, so you should mock the `width` getter of `window.screen` to a value greater or less than this value accordingly. This example shows how you set this up in Jest. +between mobile and desktop, so you should mock the `width` getter of `window.screen` to a value greater or less than this value accordingly. You may use the following utilities from +the '@react-spectrum/test-utils` package to handle this width mocking for you: + +todo typelink and functionapi for the util when I get the docs import actaully working + +The example below shows how you would set this up in Jest. -// TODO replace with helper function if we are going with that ```tsx +import {simulateDesktop, simulateMobile} from '@react-spectrum/test-utils'; + beforeAll(() => { - // Simulate mobile - jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => 650); + simulateMobile(); +}); + +afterAll(() => { + jest.restoreAllMocks(); }); ``` -// TODO: this section assumes that we will turn off virtualization for in test environments, update if aren't going ship with that +TODO: this section assumes that we will turn off virtualization for in test environments, update if aren't going ship with that ### Virtualized components Many of our collection components are virtualized out of the box and thus rely on DOM node measurement to know how large a item should be and how many items can be rendered at once. By default, virtualization for these @@ -260,40 +280,53 @@ beforeAll(function () { jest.spyOn(window.HTMLElement.prototype, 'scrollHeight', 'get').mockImplementation(() => 40); jest.spyOn(window.HTMLElement.prototype, 'scrollWidth', 'get').mockImplementation(() => 40); }); + +afterAll(() => { + jest.restoreAllMocks(); +}); ``` Please note that this is greatly simplified and still won't accurately reflect the behavior of the virtualizer in browser so we highly recommended that you avoid doing the above or use a browser based automated testing framework to test virtualizer behavior. If you run into a test error where your collection component doesn't render any items/rows within it, try adding the above mocks. -// TODO perhaps also note that various component doc pages will have testing sub sections if we deem them applicable - -## Gotchas - -// TODO: revise this if we do/don't decide to offer installPointerEvents and/or triggerLongPress from our utils. -// Also double check with our current version of user event library ### Simulating user long press Components like ListView and TableView support long press to perform specific interactions like drag and drop or entering selection mode on mobile devices. Unfortunately, the approach of using the userEvent library to simulate a press event and running timers to hit the -long press internal timer threshold isn't sufficient due to `useLongPress`'s usage of `PointerEvent`. Call our `installPointerEvent` utility to properly simulate these long press events in your tests. If you don't need to control the specific timings around the long press interaction, -use our `triggerLongPress` utility as shown below. +long press internal timer threshold isn't sufficient due to `useLongPress`'s usage of `PointerEvent` and our own detection of `virtual` vs `mouse`/`touch` pointer types. Call our `installPointerEvent` utility and `fireEvent` to properly simulate these long press events in your tests. +If you don't need to control the specific timings around the long press interaction, use our `triggerLongPress` utility as shown below. + +TODO add typelink/function api for triggerLongPress ```tsx -// top level in your test file +import {installPointerEvent, triggerLongPress} from '@react-spectrum/test-utils'; installPointerEvent(); -let button = getByRole('button); +// In test case +let button = getByRole('button'); -// TODO: test with userevent // With fireEvent and specific timing control -await user.pointer({target: el, keys: '[TouchA>]'}); +fireEvent.pointerDown(el, {pointerType: 'touch'}); act(() => jest.advanceTimersByTime(800)); -await user.pointer({target: el, keys: '[/TouchA]'}); +fireEvent.up(el, {pointerType: 'touch'}); // With triggerLongPress triggerLongPress(button); -... +``` -### Snapshot tests +## Snapshot tests If you are use React 16 or 17, you may run into an issue where the ids generated by the React Spectrum components are changing on every snapshot. To remedy this, simply wrap your component in a [SSRProvider](../react-aria/SSRProvider.html). Note that you can use the SSRProvider even if your component doesn't support server side rendering, it will simply stabilize the ids generated. + +```tsx +import {SSRProvider, Provider, lightTheme} from '@adobe/react-spectrum'; + + + + + + +``` + + +TODO document installMouseEvents and movement? Doublecheck if we can even get it to fire with user event From 8d839cbc7596769283f511ed4b24d55168629084 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Thu, 7 Dec 2023 10:11:25 -0800 Subject: [PATCH 19/31] temporarily restore old test util package and move ssr stuff there --- jest.ssr.config.js | 4 +- packages/@react-aria/dnd/test/dnd.ssr.test.js | 2 +- .../landmark/test/useLandmark.ssr.test.js | 2 +- .../overlays/test/useModal.ssr.test.js | 2 +- .../ssr/test/SSRProvider.ssr.test.js | 2 +- packages/@react-aria/test-utils/package.json | 5 ++ packages/@react-aria/test-utils/src/index.ts | 1 - .../utils/test/useViewportSize.ssr.test.tsx | 2 +- .../actiongroup/test/ActionGroup.ssr.test.js | 2 +- .../badge/test/Badge.ssr.test.js | 2 +- .../breadcrumbs/test/Breadcrumbs.ssr.test.js | 2 +- .../button/test/Button.ssr.test.js | 2 +- .../buttongroup/test/ButtonGroup.ssr.test.js | 2 +- .../calendar/test/Calendar.ssr.test.js | 2 +- .../checkbox/test/Checkbox.ssr.test.js | 2 +- .../datepicker/test/DatePicker.ssr.test.js | 2 +- .../dialog/test/Dialog.ssr.test.js | 2 +- .../divider/test/Divider.ssr.test.js | 2 +- .../form/test/Form.ssr.test.js | 2 +- .../test/IllustratedMessage.ssr.test.js | 2 +- .../layout/test/Flex.ssr.test.js | 2 +- .../layout/test/Grid.ssr.test.js | 2 +- .../link/test/Link.ssr.test.js | 2 +- .../list/test/ListView.ssr.test.js | 2 +- .../listbox/test/ListBox.ssr.test.js | 2 +- .../menu/test/Menu.ssr.test.js | 2 +- .../menu/test/MenuTrigger.ssr.test.js | 2 +- .../meter/test/Meter.ssr.test.js | 2 +- .../numberfield/test/NumberField.ssr.test.js | 2 +- .../picker/test/Picker.ssr.test.js | 2 +- .../progress/test/ProgressBar.ssr.test.js | 2 +- .../progress/test/ProgressCircle.ssr.test.js | 2 +- .../provider/test/Provider.ssr.test.js | 2 +- .../radio/test/Radio.ssr.test.js | 2 +- .../searchfield/test/SearchField.ssr.test.js | 2 +- .../statuslight/test/StatusLight.ssr.test.js | 2 +- .../switch/test/Switch.ssr.test.js | 2 +- .../table/test/Table.ssr.test.js | 2 +- .../tag/test/TagGroup.ssr.test.js | 2 +- .../@react-spectrum/test-utils/package.json | 24 +++------ .../@react-spectrum/test-utils/src/index.ts | 1 - .../text/test/Heading.ssr.test.js | 2 +- .../text/test/Keyboard.ssr.test.js | 2 +- .../text/test/Text.ssr.test.js | 2 +- .../textfield/test/TextArea.ssr.test.js | 2 +- .../textfield/test/TextField.ssr.test.js | 2 +- .../toast/test/ToastContainer.ssr.test.js | 2 +- .../view/test/Content.ssr.test.js | 2 +- .../view/test/Footer.ssr.test.js | 2 +- .../view/test/Header.ssr.test.js | 2 +- .../view/test/View.ssr.test.js | 2 +- .../well/test/Well.ssr.test.js | 2 +- .../dev/docs/pages/react-spectrum/testing.mdx | 11 ++-- packages/dev/test-utils/README.md | 3 ++ packages/dev/test-utils/index.ts | 13 +++++ packages/dev/test-utils/package.json | 51 +++++++++++++++++++ packages/dev/test-utils/src/index.ts | 15 ++++++ .../test-utils/src/ssrSetup.js | 0 .../test-utils/src/ssrTeardown.js | 0 .../test-utils/src/ssrUtils.js | 0 .../test-utils/src/ssrWorker.js | 0 .../test-utils/src/testSSR.js | 0 .../test/Breadcrumbs.ssr.test.js | 3 +- .../test/ComboBox.ssr.test.js | 3 +- .../test/Dialog.ssr.test.js | 3 +- .../test/GridList.ssr.test.js | 3 +- .../test/ListBox.ssr.test.js | 3 +- .../test/Select.ssr.test.js | 3 +- .../test/Table.ssr.test.js | 3 +- .../test/Tabs.ssr.test.js | 3 +- .../test/TagGroup.ssr.test.js | 3 +- 71 files changed, 167 insertions(+), 82 deletions(-) create mode 100644 packages/dev/test-utils/README.md create mode 100644 packages/dev/test-utils/index.ts create mode 100644 packages/dev/test-utils/package.json create mode 100644 packages/dev/test-utils/src/index.ts rename packages/{@react-spectrum => dev}/test-utils/src/ssrSetup.js (100%) rename packages/{@react-spectrum => dev}/test-utils/src/ssrTeardown.js (100%) rename packages/{@react-spectrum => dev}/test-utils/src/ssrUtils.js (100%) rename packages/{@react-spectrum => dev}/test-utils/src/ssrWorker.js (100%) rename packages/{@react-spectrum => dev}/test-utils/src/testSSR.js (100%) diff --git a/jest.ssr.config.js b/jest.ssr.config.js index de207e1c666..efab702ffeb 100644 --- a/jest.ssr.config.js +++ b/jest.ssr.config.js @@ -36,8 +36,8 @@ module.exports = { testTimeout: 30000, - globalSetup: require.resolve('@react-spectrum/test-utils/src/ssrSetup'), - globalTeardown: require.resolve('@react-spectrum/test-utils/src/ssrTeardown'), + globalSetup: require.resolve('@react-spectrum/test-utils-test/src/ssrSetup'), + globalTeardown: require.resolve('@react-spectrum/test-utils-test/src/ssrTeardown'), // The test environment that will be used for testing testEnvironment: 'jsdom', diff --git a/packages/@react-aria/dnd/test/dnd.ssr.test.js b/packages/@react-aria/dnd/test/dnd.ssr.test.js index 17f88d7fd04..a975b4b9e2a 100644 --- a/packages/@react-aria/dnd/test/dnd.ssr.test.js +++ b/packages/@react-aria/dnd/test/dnd.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('useDrag and useDrop SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-aria/landmark/test/useLandmark.ssr.test.js b/packages/@react-aria/landmark/test/useLandmark.ssr.test.js index 666d536492d..1dc5436ecb5 100644 --- a/packages/@react-aria/landmark/test/useLandmark.ssr.test.js +++ b/packages/@react-aria/landmark/test/useLandmark.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('useLandmark SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-aria/overlays/test/useModal.ssr.test.js b/packages/@react-aria/overlays/test/useModal.ssr.test.js index 7fda87e7a0f..0a198f428a6 100644 --- a/packages/@react-aria/overlays/test/useModal.ssr.test.js +++ b/packages/@react-aria/overlays/test/useModal.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('OverlayContainer SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-aria/ssr/test/SSRProvider.ssr.test.js b/packages/@react-aria/ssr/test/SSRProvider.ssr.test.js index d4fafd2bd0d..9ed96f50203 100644 --- a/packages/@react-aria/ssr/test/SSRProvider.ssr.test.js +++ b/packages/@react-aria/ssr/test/SSRProvider.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('SSRProvider SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-aria/test-utils/package.json b/packages/@react-aria/test-utils/package.json index c8e7c1750c0..a275a28c275 100644 --- a/packages/@react-aria/test-utils/package.json +++ b/packages/@react-aria/test-utils/package.json @@ -6,6 +6,11 @@ "license": "Apache-2.0", "main": "dist/main.js", "module": "dist/module.js", + "exports": { + "types": "./dist/types.d.ts", + "import": "./dist/import.mjs", + "require": "./dist/main.js" + }, "types": "dist/types.d.ts", "source": "src/index.ts", "files": [ diff --git a/packages/@react-aria/test-utils/src/index.ts b/packages/@react-aria/test-utils/src/index.ts index 6a721573422..91e20a9137e 100644 --- a/packages/@react-aria/test-utils/src/index.ts +++ b/packages/@react-aria/test-utils/src/index.ts @@ -10,7 +10,6 @@ * governing permissions and limitations under the License. */ -// TODO update export * from './events'; export * from './testSetup'; export * from './userEventMaps'; diff --git a/packages/@react-aria/utils/test/useViewportSize.ssr.test.tsx b/packages/@react-aria/utils/test/useViewportSize.ssr.test.tsx index 8b4cc4d79c1..b5c1b1da64c 100644 --- a/packages/@react-aria/utils/test/useViewportSize.ssr.test.tsx +++ b/packages/@react-aria/utils/test/useViewportSize.ssr.test.tsx @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('useViewportSize SSR', () => { it('should render without errors', async () => { diff --git a/packages/@react-spectrum/actiongroup/test/ActionGroup.ssr.test.js b/packages/@react-spectrum/actiongroup/test/ActionGroup.ssr.test.js index 3b591f2a7fe..fbb24fd386f 100644 --- a/packages/@react-spectrum/actiongroup/test/ActionGroup.ssr.test.js +++ b/packages/@react-spectrum/actiongroup/test/ActionGroup.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('ActionGroup SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/badge/test/Badge.ssr.test.js b/packages/@react-spectrum/badge/test/Badge.ssr.test.js index 4e89efe8ec8..78b038df49c 100644 --- a/packages/@react-spectrum/badge/test/Badge.ssr.test.js +++ b/packages/@react-spectrum/badge/test/Badge.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('Badge SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/breadcrumbs/test/Breadcrumbs.ssr.test.js b/packages/@react-spectrum/breadcrumbs/test/Breadcrumbs.ssr.test.js index f76b4be93eb..409e764b3b6 100644 --- a/packages/@react-spectrum/breadcrumbs/test/Breadcrumbs.ssr.test.js +++ b/packages/@react-spectrum/breadcrumbs/test/Breadcrumbs.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('Breadcrumbs SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/button/test/Button.ssr.test.js b/packages/@react-spectrum/button/test/Button.ssr.test.js index da4fd39cc21..f075059350c 100644 --- a/packages/@react-spectrum/button/test/Button.ssr.test.js +++ b/packages/@react-spectrum/button/test/Button.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('Button SSR', function () { it.each` diff --git a/packages/@react-spectrum/buttongroup/test/ButtonGroup.ssr.test.js b/packages/@react-spectrum/buttongroup/test/ButtonGroup.ssr.test.js index 520c10d5de0..d4cdba81721 100644 --- a/packages/@react-spectrum/buttongroup/test/ButtonGroup.ssr.test.js +++ b/packages/@react-spectrum/buttongroup/test/ButtonGroup.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('ButtonGroup SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/calendar/test/Calendar.ssr.test.js b/packages/@react-spectrum/calendar/test/Calendar.ssr.test.js index 763f5d98a91..a6988fbbbfd 100644 --- a/packages/@react-spectrum/calendar/test/Calendar.ssr.test.js +++ b/packages/@react-spectrum/calendar/test/Calendar.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('Calendar SSR', function () { it('should render a Calendar without errors', async function () { diff --git a/packages/@react-spectrum/checkbox/test/Checkbox.ssr.test.js b/packages/@react-spectrum/checkbox/test/Checkbox.ssr.test.js index 41f1c628c34..6439ca9b8a0 100644 --- a/packages/@react-spectrum/checkbox/test/Checkbox.ssr.test.js +++ b/packages/@react-spectrum/checkbox/test/Checkbox.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('Checkbox SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/datepicker/test/DatePicker.ssr.test.js b/packages/@react-spectrum/datepicker/test/DatePicker.ssr.test.js index 4e96068ef84..568911b8fb5 100644 --- a/packages/@react-spectrum/datepicker/test/DatePicker.ssr.test.js +++ b/packages/@react-spectrum/datepicker/test/DatePicker.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('DatePicker SSR', function () { it('should render a DatePicker without errors', async function () { diff --git a/packages/@react-spectrum/dialog/test/Dialog.ssr.test.js b/packages/@react-spectrum/dialog/test/Dialog.ssr.test.js index 61f902ddecc..85bc264a2c4 100644 --- a/packages/@react-spectrum/dialog/test/Dialog.ssr.test.js +++ b/packages/@react-spectrum/dialog/test/Dialog.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('Dialog SSR', function () { it('Dialog should render without errors', async function () { diff --git a/packages/@react-spectrum/divider/test/Divider.ssr.test.js b/packages/@react-spectrum/divider/test/Divider.ssr.test.js index c69701d20ba..a9f803d406e 100644 --- a/packages/@react-spectrum/divider/test/Divider.ssr.test.js +++ b/packages/@react-spectrum/divider/test/Divider.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('Divider SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/form/test/Form.ssr.test.js b/packages/@react-spectrum/form/test/Form.ssr.test.js index f387bd18b01..be9cf5a9467 100644 --- a/packages/@react-spectrum/form/test/Form.ssr.test.js +++ b/packages/@react-spectrum/form/test/Form.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('Form SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/illustratedmessage/test/IllustratedMessage.ssr.test.js b/packages/@react-spectrum/illustratedmessage/test/IllustratedMessage.ssr.test.js index b2705ea6b3c..dd33fbebfeb 100644 --- a/packages/@react-spectrum/illustratedmessage/test/IllustratedMessage.ssr.test.js +++ b/packages/@react-spectrum/illustratedmessage/test/IllustratedMessage.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('IllustratedMessage SSR', function () { diff --git a/packages/@react-spectrum/layout/test/Flex.ssr.test.js b/packages/@react-spectrum/layout/test/Flex.ssr.test.js index 9cd0b1337e8..dfa02f4f36b 100644 --- a/packages/@react-spectrum/layout/test/Flex.ssr.test.js +++ b/packages/@react-spectrum/layout/test/Flex.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('Flex SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/layout/test/Grid.ssr.test.js b/packages/@react-spectrum/layout/test/Grid.ssr.test.js index 2881a94f8db..3c906af00d5 100644 --- a/packages/@react-spectrum/layout/test/Grid.ssr.test.js +++ b/packages/@react-spectrum/layout/test/Grid.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('Grid SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/link/test/Link.ssr.test.js b/packages/@react-spectrum/link/test/Link.ssr.test.js index ead1be1b260..12103236247 100644 --- a/packages/@react-spectrum/link/test/Link.ssr.test.js +++ b/packages/@react-spectrum/link/test/Link.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('Link SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/list/test/ListView.ssr.test.js b/packages/@react-spectrum/list/test/ListView.ssr.test.js index 9f2e6566a8e..d8717e820fb 100644 --- a/packages/@react-spectrum/list/test/ListView.ssr.test.js +++ b/packages/@react-spectrum/list/test/ListView.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('ListView SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/listbox/test/ListBox.ssr.test.js b/packages/@react-spectrum/listbox/test/ListBox.ssr.test.js index 76123cc6a35..a1288ab2132 100644 --- a/packages/@react-spectrum/listbox/test/ListBox.ssr.test.js +++ b/packages/@react-spectrum/listbox/test/ListBox.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('ListBox SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/menu/test/Menu.ssr.test.js b/packages/@react-spectrum/menu/test/Menu.ssr.test.js index 44ba16ff5ac..659ff0e40f1 100644 --- a/packages/@react-spectrum/menu/test/Menu.ssr.test.js +++ b/packages/@react-spectrum/menu/test/Menu.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('Menu SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/menu/test/MenuTrigger.ssr.test.js b/packages/@react-spectrum/menu/test/MenuTrigger.ssr.test.js index ec5dc15a0b7..8dad227dc2f 100644 --- a/packages/@react-spectrum/menu/test/MenuTrigger.ssr.test.js +++ b/packages/@react-spectrum/menu/test/MenuTrigger.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('MenuTrigger SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/meter/test/Meter.ssr.test.js b/packages/@react-spectrum/meter/test/Meter.ssr.test.js index ecdfce2a670..60c112d1ae2 100644 --- a/packages/@react-spectrum/meter/test/Meter.ssr.test.js +++ b/packages/@react-spectrum/meter/test/Meter.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('Meter SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/numberfield/test/NumberField.ssr.test.js b/packages/@react-spectrum/numberfield/test/NumberField.ssr.test.js index 461193fa1ac..8b9798f8a93 100644 --- a/packages/@react-spectrum/numberfield/test/NumberField.ssr.test.js +++ b/packages/@react-spectrum/numberfield/test/NumberField.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('NumberField SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/picker/test/Picker.ssr.test.js b/packages/@react-spectrum/picker/test/Picker.ssr.test.js index 6eefd1c2622..b02c3003ed2 100644 --- a/packages/@react-spectrum/picker/test/Picker.ssr.test.js +++ b/packages/@react-spectrum/picker/test/Picker.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('Picker SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/progress/test/ProgressBar.ssr.test.js b/packages/@react-spectrum/progress/test/ProgressBar.ssr.test.js index af8030c112e..d7146f768be 100644 --- a/packages/@react-spectrum/progress/test/ProgressBar.ssr.test.js +++ b/packages/@react-spectrum/progress/test/ProgressBar.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('ProgressBar SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/progress/test/ProgressCircle.ssr.test.js b/packages/@react-spectrum/progress/test/ProgressCircle.ssr.test.js index 38107227e71..3f966bb3875 100644 --- a/packages/@react-spectrum/progress/test/ProgressCircle.ssr.test.js +++ b/packages/@react-spectrum/progress/test/ProgressCircle.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('ProgressCircle SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/provider/test/Provider.ssr.test.js b/packages/@react-spectrum/provider/test/Provider.ssr.test.js index b83da16a617..3ea3ee18769 100644 --- a/packages/@react-spectrum/provider/test/Provider.ssr.test.js +++ b/packages/@react-spectrum/provider/test/Provider.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('Provider SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/radio/test/Radio.ssr.test.js b/packages/@react-spectrum/radio/test/Radio.ssr.test.js index b0effbbb856..937f9fad016 100644 --- a/packages/@react-spectrum/radio/test/Radio.ssr.test.js +++ b/packages/@react-spectrum/radio/test/Radio.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('Radio SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/searchfield/test/SearchField.ssr.test.js b/packages/@react-spectrum/searchfield/test/SearchField.ssr.test.js index 3209ae30656..d73941e251b 100644 --- a/packages/@react-spectrum/searchfield/test/SearchField.ssr.test.js +++ b/packages/@react-spectrum/searchfield/test/SearchField.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('SearchField SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/statuslight/test/StatusLight.ssr.test.js b/packages/@react-spectrum/statuslight/test/StatusLight.ssr.test.js index 7be873384d2..a0592b7cc96 100644 --- a/packages/@react-spectrum/statuslight/test/StatusLight.ssr.test.js +++ b/packages/@react-spectrum/statuslight/test/StatusLight.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('StatusLight SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/switch/test/Switch.ssr.test.js b/packages/@react-spectrum/switch/test/Switch.ssr.test.js index d0b31b9b359..7741f3f6f04 100644 --- a/packages/@react-spectrum/switch/test/Switch.ssr.test.js +++ b/packages/@react-spectrum/switch/test/Switch.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('Switch SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/table/test/Table.ssr.test.js b/packages/@react-spectrum/table/test/Table.ssr.test.js index 8c3779c3122..48529b61714 100644 --- a/packages/@react-spectrum/table/test/Table.ssr.test.js +++ b/packages/@react-spectrum/table/test/Table.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('Table SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/tag/test/TagGroup.ssr.test.js b/packages/@react-spectrum/tag/test/TagGroup.ssr.test.js index ad70f9af802..12c7d134325 100644 --- a/packages/@react-spectrum/tag/test/TagGroup.ssr.test.js +++ b/packages/@react-spectrum/tag/test/TagGroup.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('TagGroup SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/test-utils/package.json b/packages/@react-spectrum/test-utils/package.json index 9196a48915e..f747d414b1b 100644 --- a/packages/@react-spectrum/test-utils/package.json +++ b/packages/@react-spectrum/test-utils/package.json @@ -6,27 +6,18 @@ "license": "Apache-2.0", "main": "dist/main.js", "module": "dist/module.js", + "exports": { + "types": "./dist/types.d.ts", + "import": "./dist/import.mjs", + "require": "./dist/main.js" + }, "types": "dist/types.d.ts", "source": "src/index.ts", "files": [ "dist", "src" ], - "sideEffects": [ - "*.css" - ], - "targets": { - "main": { - "includeNodeModules": [ - "@adobe/spectrum-css-temp" - ] - }, - "module": { - "includeNodeModules": [ - "@adobe/spectrum-css-temp" - ] - } - }, + "sideEffects": false, "repository": { "type": "git", "url": "https://github.com/adobe/react-spectrum" @@ -37,9 +28,6 @@ "@swc/helpers": "^0.5.0", "resolve": "^1.17.0" }, - "devDependencies": { - "@adobe/spectrum-css-temp": "3.0.0-alpha.1" - }, "peerDependencies": { "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.4.3", diff --git a/packages/@react-spectrum/test-utils/src/index.ts b/packages/@react-spectrum/test-utils/src/index.ts index affbece0595..6bdaff083db 100644 --- a/packages/@react-spectrum/test-utils/src/index.ts +++ b/packages/@react-spectrum/test-utils/src/index.ts @@ -14,7 +14,6 @@ export * from '@react-aria/test-utils'; export * from './testSetup'; -export * from './testSSR'; export * from './renderOverride'; export * from './StrictModeWrapper'; export * from './mockImplementation'; diff --git a/packages/@react-spectrum/text/test/Heading.ssr.test.js b/packages/@react-spectrum/text/test/Heading.ssr.test.js index 9777d0d004b..3e7b86d028a 100644 --- a/packages/@react-spectrum/text/test/Heading.ssr.test.js +++ b/packages/@react-spectrum/text/test/Heading.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('Heading SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/text/test/Keyboard.ssr.test.js b/packages/@react-spectrum/text/test/Keyboard.ssr.test.js index 186054b33b7..84715ff31f6 100644 --- a/packages/@react-spectrum/text/test/Keyboard.ssr.test.js +++ b/packages/@react-spectrum/text/test/Keyboard.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('Keyboard SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/text/test/Text.ssr.test.js b/packages/@react-spectrum/text/test/Text.ssr.test.js index 3b4be3d227d..5d05756fca9 100644 --- a/packages/@react-spectrum/text/test/Text.ssr.test.js +++ b/packages/@react-spectrum/text/test/Text.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('Text SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/textfield/test/TextArea.ssr.test.js b/packages/@react-spectrum/textfield/test/TextArea.ssr.test.js index 72f22ceccaf..933cafacc48 100644 --- a/packages/@react-spectrum/textfield/test/TextArea.ssr.test.js +++ b/packages/@react-spectrum/textfield/test/TextArea.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('TextArea SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/textfield/test/TextField.ssr.test.js b/packages/@react-spectrum/textfield/test/TextField.ssr.test.js index 0a4f3160489..12628db5f50 100644 --- a/packages/@react-spectrum/textfield/test/TextField.ssr.test.js +++ b/packages/@react-spectrum/textfield/test/TextField.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('TextField SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/toast/test/ToastContainer.ssr.test.js b/packages/@react-spectrum/toast/test/ToastContainer.ssr.test.js index c67b7bb900b..e9e96e4cd9b 100644 --- a/packages/@react-spectrum/toast/test/ToastContainer.ssr.test.js +++ b/packages/@react-spectrum/toast/test/ToastContainer.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('ToastContainer SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/view/test/Content.ssr.test.js b/packages/@react-spectrum/view/test/Content.ssr.test.js index a2a38f3ec18..6ed345a3d82 100644 --- a/packages/@react-spectrum/view/test/Content.ssr.test.js +++ b/packages/@react-spectrum/view/test/Content.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('Content SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/view/test/Footer.ssr.test.js b/packages/@react-spectrum/view/test/Footer.ssr.test.js index 8d141bb7469..0f7bb9ba3ba 100644 --- a/packages/@react-spectrum/view/test/Footer.ssr.test.js +++ b/packages/@react-spectrum/view/test/Footer.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('Footer SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/view/test/Header.ssr.test.js b/packages/@react-spectrum/view/test/Header.ssr.test.js index 8f834f673f0..a553de1d840 100644 --- a/packages/@react-spectrum/view/test/Header.ssr.test.js +++ b/packages/@react-spectrum/view/test/Header.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('Header SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/view/test/View.ssr.test.js b/packages/@react-spectrum/view/test/View.ssr.test.js index 0e1d2917038..fd7be1f2d9a 100644 --- a/packages/@react-spectrum/view/test/View.ssr.test.js +++ b/packages/@react-spectrum/view/test/View.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('View SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/well/test/Well.ssr.test.js b/packages/@react-spectrum/well/test/Well.ssr.test.js index 5f7eb78a379..46938aad036 100644 --- a/packages/@react-spectrum/well/test/Well.ssr.test.js +++ b/packages/@react-spectrum/well/test/Well.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('Well SSR', function () { it('should render without errors', async function () { diff --git a/packages/dev/docs/pages/react-spectrum/testing.mdx b/packages/dev/docs/pages/react-spectrum/testing.mdx index b579c955d97..679e5370144 100644 --- a/packages/dev/docs/pages/react-spectrum/testing.mdx +++ b/packages/dev/docs/pages/react-spectrum/testing.mdx @@ -9,6 +9,7 @@ governing permissions and limitations under the License. */} import {Layout} from '@react-spectrum/docs'; export default Layout; +import docs from 'docs:@react-spectrum/test-utils'; --- category: Concepts @@ -246,7 +247,7 @@ Components like ComboBox and Picker render a different experience on mobile vers components are rendered only against a specific experience, you'll need to mock the window screen width accordingly. We currently use a [screen width of 700px](https://github.com/adobe/react-spectrum/blob/5e487532e3ca4714513fb6ab64f7a78d9d1ca281/packages/%40react-spectrum/utils/src/useIsMobileDevice.ts#L15-L23) as the breakpoint between mobile and desktop, so you should mock the `width` getter of `window.screen` to a value greater or less than this value accordingly. You may use the following utilities from -the '@react-spectrum/test-utils` package to handle this width mocking for you: +the '@react-spectrum/test-utils` package to handle this width mocking for you in Jest: todo typelink and functionapi for the util when I get the docs import actaully working @@ -255,6 +256,7 @@ The example below shows how you would set this up in Jest. ```tsx import {simulateDesktop, simulateMobile} from '@react-spectrum/test-utils'; +// TODO: adds omething for other test frameworks? beforeAll(() => { simulateMobile(); }); @@ -313,6 +315,10 @@ fireEvent.up(el, {pointerType: 'touch'}); triggerLongPress(button); ``` +### Simulating move event + +TODO document installMouseEvent and movement. add links for slider, and color components + ## Snapshot tests If you are use React 16 or 17, you may run into an issue where the ids generated by the React Spectrum components are changing on every snapshot. To remedy this, simply wrap your component in a [SSRProvider](../react-aria/SSRProvider.html). @@ -327,6 +333,3 @@ import {SSRProvider, Provider, lightTheme} from '@adobe/react-spectrum'; ``` - - -TODO document installMouseEvents and movement? Doublecheck if we can even get it to fire with user event diff --git a/packages/dev/test-utils/README.md b/packages/dev/test-utils/README.md new file mode 100644 index 00000000000..0030138c3bf --- /dev/null +++ b/packages/dev/test-utils/README.md @@ -0,0 +1,3 @@ +# @react-spectrum/test-utils + +This package is part of [react-spectrum](https://github.com/adobe/react-spectrum). See the repo for more details. diff --git a/packages/dev/test-utils/index.ts b/packages/dev/test-utils/index.ts new file mode 100644 index 00000000000..1210ae1e402 --- /dev/null +++ b/packages/dev/test-utils/index.ts @@ -0,0 +1,13 @@ +/* + * Copyright 2020 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +export * from './src'; diff --git a/packages/dev/test-utils/package.json b/packages/dev/test-utils/package.json new file mode 100644 index 00000000000..a04ea9bad70 --- /dev/null +++ b/packages/dev/test-utils/package.json @@ -0,0 +1,51 @@ +{ + "name": "@react-spectrum/test-utils-test", + "version": "3.0.0-alpha.1", + "private": true, + "description": "Spectrum UI components in React", + "license": "Apache-2.0", + "main": "dist/main.js", + "module": "dist/module.js", + "types": "dist/types.d.ts", + "source": "src/index.ts", + "files": [ + "dist", + "src" + ], + "sideEffects": [ + "*.css" + ], + "targets": { + "main": { + "includeNodeModules": [ + "@adobe/spectrum-css-temp" + ] + }, + "module": { + "includeNodeModules": [ + "@adobe/spectrum-css-temp" + ] + } + }, + "repository": { + "type": "git", + "url": "https://github.com/adobe/react-spectrum" + }, + "dependencies": { + "@react-aria/ssr": "^3.0.0", + "@swc/helpers": "^0.5.0", + "resolve": "^1.17.0" + }, + "peerDependencies": { + "@testing-library/react": "^14.0.0", + "@testing-library/user-event": "^14.4.3", + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + }, + "devDependencies": { + "@adobe/spectrum-css-temp": "3.0.0-alpha.1" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/dev/test-utils/src/index.ts b/packages/dev/test-utils/src/index.ts new file mode 100644 index 00000000000..98348ae7a2c --- /dev/null +++ b/packages/dev/test-utils/src/index.ts @@ -0,0 +1,15 @@ +/* + * Copyright 2020 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +/// + +export * from './testSSR'; diff --git a/packages/@react-spectrum/test-utils/src/ssrSetup.js b/packages/dev/test-utils/src/ssrSetup.js similarity index 100% rename from packages/@react-spectrum/test-utils/src/ssrSetup.js rename to packages/dev/test-utils/src/ssrSetup.js diff --git a/packages/@react-spectrum/test-utils/src/ssrTeardown.js b/packages/dev/test-utils/src/ssrTeardown.js similarity index 100% rename from packages/@react-spectrum/test-utils/src/ssrTeardown.js rename to packages/dev/test-utils/src/ssrTeardown.js diff --git a/packages/@react-spectrum/test-utils/src/ssrUtils.js b/packages/dev/test-utils/src/ssrUtils.js similarity index 100% rename from packages/@react-spectrum/test-utils/src/ssrUtils.js rename to packages/dev/test-utils/src/ssrUtils.js diff --git a/packages/@react-spectrum/test-utils/src/ssrWorker.js b/packages/dev/test-utils/src/ssrWorker.js similarity index 100% rename from packages/@react-spectrum/test-utils/src/ssrWorker.js rename to packages/dev/test-utils/src/ssrWorker.js diff --git a/packages/@react-spectrum/test-utils/src/testSSR.js b/packages/dev/test-utils/src/testSSR.js similarity index 100% rename from packages/@react-spectrum/test-utils/src/testSSR.js rename to packages/dev/test-utils/src/testSSR.js diff --git a/packages/react-aria-components/test/Breadcrumbs.ssr.test.js b/packages/react-aria-components/test/Breadcrumbs.ssr.test.js index 693ae6dec46..274d18ad4cf 100644 --- a/packages/react-aria-components/test/Breadcrumbs.ssr.test.js +++ b/packages/react-aria-components/test/Breadcrumbs.ssr.test.js @@ -10,7 +10,8 @@ * governing permissions and limitations under the License. */ -import {screen, testSSR} from '@react-spectrum/test-utils'; +import {screen} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('Breadcrumbs SSR', function () { it('should render without errors', async function () { diff --git a/packages/react-aria-components/test/ComboBox.ssr.test.js b/packages/react-aria-components/test/ComboBox.ssr.test.js index dcb931e8fd8..fdfa44c70fe 100644 --- a/packages/react-aria-components/test/ComboBox.ssr.test.js +++ b/packages/react-aria-components/test/ComboBox.ssr.test.js @@ -10,7 +10,8 @@ * governing permissions and limitations under the License. */ -import {screen, testSSR} from '@react-spectrum/test-utils'; +import {screen} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('ComboBox SSR', function () { it('should render text of default selected key', async function () { diff --git a/packages/react-aria-components/test/Dialog.ssr.test.js b/packages/react-aria-components/test/Dialog.ssr.test.js index 0d68e71fcfa..8df2b5894bd 100644 --- a/packages/react-aria-components/test/Dialog.ssr.test.js +++ b/packages/react-aria-components/test/Dialog.ssr.test.js @@ -10,7 +10,8 @@ * governing permissions and limitations under the License. */ -import {screen, testSSR} from '@react-spectrum/test-utils'; +import {screen} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('Dialog SSR', function () { it('should render without errors', async function () { diff --git a/packages/react-aria-components/test/GridList.ssr.test.js b/packages/react-aria-components/test/GridList.ssr.test.js index 3898b9641fe..fe62492dd2b 100644 --- a/packages/react-aria-components/test/GridList.ssr.test.js +++ b/packages/react-aria-components/test/GridList.ssr.test.js @@ -10,7 +10,8 @@ * governing permissions and limitations under the License. */ -import {fireEvent, screen, testSSR} from '@react-spectrum/test-utils'; +import {fireEvent, screen} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('GridList SSR', function () { it('should render without errors', async function () { diff --git a/packages/react-aria-components/test/ListBox.ssr.test.js b/packages/react-aria-components/test/ListBox.ssr.test.js index 2310562479a..2c18aa9fb1e 100644 --- a/packages/react-aria-components/test/ListBox.ssr.test.js +++ b/packages/react-aria-components/test/ListBox.ssr.test.js @@ -10,7 +10,8 @@ * governing permissions and limitations under the License. */ -import {fireEvent, screen, testSSR, within} from '@react-spectrum/test-utils'; +import {fireEvent, screen, within} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('ListBox SSR', function () { it('should render without errors', async function () { diff --git a/packages/react-aria-components/test/Select.ssr.test.js b/packages/react-aria-components/test/Select.ssr.test.js index f39f307ac21..fa0d592cd0f 100644 --- a/packages/react-aria-components/test/Select.ssr.test.js +++ b/packages/react-aria-components/test/Select.ssr.test.js @@ -10,7 +10,8 @@ * governing permissions and limitations under the License. */ -import {screen, testSSR} from '@react-spectrum/test-utils'; +import {screen} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('Select SSR', function () { it('should render text of default selected key', async function () { diff --git a/packages/react-aria-components/test/Table.ssr.test.js b/packages/react-aria-components/test/Table.ssr.test.js index adc42dc5701..b100a70753c 100644 --- a/packages/react-aria-components/test/Table.ssr.test.js +++ b/packages/react-aria-components/test/Table.ssr.test.js @@ -10,7 +10,8 @@ * governing permissions and limitations under the License. */ -import {fireEvent, screen, testSSR} from '@react-spectrum/test-utils'; +import {fireEvent, screen} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('Table SSR', function () { it('should render without errors', async function () { diff --git a/packages/react-aria-components/test/Tabs.ssr.test.js b/packages/react-aria-components/test/Tabs.ssr.test.js index 0c24660fcc1..2ac15831b05 100644 --- a/packages/react-aria-components/test/Tabs.ssr.test.js +++ b/packages/react-aria-components/test/Tabs.ssr.test.js @@ -10,7 +10,8 @@ * governing permissions and limitations under the License. */ -import {screen, testSSR} from '@react-spectrum/test-utils'; +import {screen} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('Tabs SSR', function () { it('should render without errors', async function () { diff --git a/packages/react-aria-components/test/TagGroup.ssr.test.js b/packages/react-aria-components/test/TagGroup.ssr.test.js index bdf6471aa3d..9e59765bd20 100644 --- a/packages/react-aria-components/test/TagGroup.ssr.test.js +++ b/packages/react-aria-components/test/TagGroup.ssr.test.js @@ -10,7 +10,8 @@ * governing permissions and limitations under the License. */ -import {fireEvent, screen, testSSR} from '@react-spectrum/test-utils'; +import {fireEvent, screen} from '@react-spectrum/test-utils'; +import {testSSR} from '@react-spectrum/test-utils-test'; describe('TagGroup SSR', function () { it('should render without errors', async function () { From 215c2e88b54f1631155f99bb225adc67816deaa5 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Thu, 7 Dec 2023 11:58:58 -0800 Subject: [PATCH 20/31] make react-spectrum/test-util-internal to limit what is exposed from test util package was running into build/docs issues with re-exporting @testing-library/react, this feels like it makes more sense anyways, dont think we wanna expose our render wrapper yet --- jest.ssr.config.js | 4 ++-- .../react-spectrum/test/ActionGroup.test.tsx | 2 +- .../actiongroup/test/useActionGroup.test.ts | 2 +- .../aria-modal-polyfill/test/index.test.tsx | 2 +- .../test/useSearchAutocomplete.test.js | 2 +- .../test/useBreadcrumbItem.test.js | 2 +- .../breadcrumbs/test/useBreadcrumbs.test.js | 2 +- .../@react-aria/button/test/useButton.test.js | 2 +- .../calendar/test/useCalendar.test.js | 2 +- .../checkbox/test/useCheckboxGroup.test.tsx | 2 +- .../color/test/useColorField.test.js | 2 +- .../color/test/useColorWheel.test.tsx | 2 +- .../combobox/test/useComboBox.test.js | 2 +- .../@react-aria/dialog/test/useDialog.test.js | 2 +- packages/@react-aria/dnd/test/dnd.ssr.test.js | 2 +- packages/@react-aria/dnd/test/dnd.test.js | 2 +- .../@react-aria/dnd/test/useClipboard.test.js | 2 +- .../dnd/test/useDraggableCollection.test.js | 2 +- .../dnd/test/useDroppableCollection.test.js | 2 +- .../@react-aria/focus/test/FocusScope.test.js | 2 +- .../@react-aria/grid/test/useGrid.test.js | 2 +- .../interactions/test/PressResponder.test.js | 2 +- .../interactions/test/Pressable.test.js | 2 +- .../interactions/test/useFocus.test.js | 2 +- .../interactions/test/useFocusVisible.test.js | 2 +- .../interactions/test/useFocusWithin.test.js | 2 +- .../interactions/test/useHover.test.js | 2 +- .../test/useInteractOutside.test.js | 2 +- .../interactions/test/useKeyboard.test.js | 2 +- .../interactions/test/useLongPress.test.js | 2 +- .../interactions/test/useMove.test.js | 2 +- .../interactions/test/usePress.test.js | 2 +- .../@react-aria/label/test/useField.test.js | 2 +- .../@react-aria/label/test/useLabel.test.js | 2 +- .../landmark/test/useLandmark.ssr.test.js | 2 +- .../landmark/test/useLandmark.test.tsx | 2 +- .../@react-aria/link/test/useLink.test.js | 2 +- .../menu/test/useMenuTrigger.test.js | 2 +- .../numberfield/test/useNumberField.test.ts | 2 +- .../overlays/test/DismissButton.test.tsx | 2 +- .../overlays/test/ariaHideOutside.test.js | 2 +- .../overlays/test/useModal.ssr.test.js | 2 +- .../overlays/test/useModal.test.js | 2 +- .../overlays/test/useOverlay.test.js | 2 +- .../overlays/test/useOverlayPosition.test.tsx | 2 +- .../overlays/test/useOverlayTrigger.test.js | 2 +- .../overlays/test/usePreventScroll.test.js | 2 +- .../pagination/test/usePagination.test.js | 2 +- .../progress/test/useProgressBar.test.js | 2 +- .../searchfield/test/useSearchField.test.js | 2 +- .../select/test/HiddenSelect.test.tsx | 2 +- .../test/useSelectableCollection.test.js | 2 +- .../@react-aria/slider/test/useSlider.test.js | 2 +- .../slider/test/useSliderThumb.test.js | 2 +- .../spinbutton/test/useSpinButton.test.js | 2 +- .../ssr/test/SSRProvider.ssr.test.js | 2 +- .../@react-aria/ssr/test/SSRProvider.test.js | 2 +- .../table/test/ariaTableResizing.test.tsx | 2 +- .../table/test/tableResizingTests.tsx | 2 +- .../@react-aria/table/test/useTable.test.tsx | 2 +- .../test/useTableBackwardCompat.test.tsx | 2 +- .../@react-aria/tag/test/useTagGroup.test.js | 2 +- packages/@react-aria/test-utils/src/events.ts | 2 +- .../textfield/test/useTextField.test.js | 2 +- .../@react-aria/toast/test/useToast.test.js | 2 +- .../tooltip/test/useTooltip.test.js | 2 +- .../utils/test/useObjectRef.test.js | 2 +- .../utils/test/useViewportSize.ssr.test.tsx | 2 +- .../test/VisuallyHidden.test.tsx | 2 +- .../accordion/test/Accordion.test.js | 2 +- .../actionbar/test/ActionBar.test.js | 2 +- .../actiongroup/test/ActionGroup.ssr.test.js | 2 +- .../actiongroup/test/ActionGroup.test.js | 2 +- .../actiongroup/test/Toolbar.test.tsx | 2 +- .../test/SearchAutocomplete.test.js | 2 +- .../avatar/test/Avatar.test.js | 2 +- .../badge/test/Badge.ssr.test.js | 2 +- .../@react-spectrum/badge/test/Badge.test.js | 2 +- .../breadcrumbs/test/BreadcrumbItem.test.js | 2 +- .../breadcrumbs/test/Breadcrumbs.ssr.test.js | 2 +- .../breadcrumbs/test/Breadcrumbs.test.js | 2 +- packages/@react-spectrum/button/package.json | 2 +- .../button/test/ActionButton.test.js | 2 +- .../button/test/Button.ssr.test.js | 2 +- .../button/test/Button.test.js | 2 +- .../button/test/ClearButton.test.js | 2 +- .../button/test/ToggleButton.test.js | 2 +- .../buttongroup/test/ButtonGroup.ssr.test.js | 2 +- .../buttongroup/test/ButtonGroup.test.js | 2 +- .../@react-spectrum/calendar/package.json | 2 +- .../calendar/test/Calendar.ssr.test.js | 2 +- .../calendar/test/Calendar.test.js | 2 +- .../calendar/test/CalendarBase.test.js | 2 +- .../calendar/test/RangeCalendar.test.js | 2 +- .../@react-spectrum/card/test/Card.test.js | 2 +- .../card/test/CardView.test.js | 2 +- .../checkbox/test/Checkbox.ssr.test.js | 2 +- .../checkbox/test/Checkbox.test.js | 2 +- .../checkbox/test/CheckboxGroup.test.js | 2 +- .../color/test/ColorArea.test.tsx | 2 +- .../color/test/ColorField.test.js | 2 +- .../color/test/ColorSlider.test.tsx | 2 +- .../color/test/ColorWheel.test.tsx | 2 +- .../combobox/test/ComboBox.test.js | 2 +- .../test/ContextualHelp.test.js | 2 +- .../@react-spectrum/datepicker/package.json | 2 +- .../datepicker/test/DateField.test.js | 2 +- .../datepicker/test/DatePicker.ssr.test.js | 2 +- .../datepicker/test/DatePicker.test.js | 2 +- .../datepicker/test/DatePickerBase.test.js | 2 +- .../datepicker/test/DateRangePicker.test.js | 2 +- .../datepicker/test/TimeField.test.js | 2 +- packages/@react-spectrum/dialog/package.json | 2 +- .../dialog/test/AlertDialog.test.js | 2 +- .../dialog/test/Dialog.ssr.test.js | 2 +- .../dialog/test/Dialog.test.js | 2 +- .../dialog/test/DialogContainer.test.js | 2 +- .../dialog/test/DialogTrigger.test.js | 2 +- .../divider/test/Divider.ssr.test.js | 2 +- .../divider/test/Divider.test.js | 2 +- .../@react-spectrum/dropzone/package.json | 2 +- .../dropzone/test/DropZone.test.js | 2 +- .../form/test/Form.ssr.test.js | 2 +- .../@react-spectrum/form/test/Form.test.js | 2 +- .../@react-spectrum/icon/test/Icon.test.js | 2 +- .../icon/test/Illustration.test.js | 4 ++-- .../@react-spectrum/icon/test/UIIcon.test.js | 2 +- .../test/IllustratedMessage.ssr.test.js | 2 +- .../test/IllustratedMessage.test.js | 2 +- .../inlinealert/test/InlineAlert.test.js | 2 +- .../@react-spectrum/label/test/Field.test.js | 2 +- .../labeledvalue/test/LabeledValue.test.js | 2 +- .../layout/test/Flex.ssr.test.js | 2 +- .../layout/test/Grid.ssr.test.js | 2 +- .../link/test/Link.ssr.test.js | 2 +- .../@react-spectrum/link/test/Link.test.js | 2 +- .../list/test/ListView.ssr.test.js | 2 +- .../list/test/ListView.test.js | 2 +- .../list/test/ListViewDnd.test.js | 2 +- .../listbox/test/ListBox.ssr.test.js | 2 +- .../listbox/test/ListBox.test.js | 2 +- .../menu/test/ActionMenu.test.js | 2 +- .../menu/test/Menu.ssr.test.js | 2 +- .../@react-spectrum/menu/test/Menu.test.js | 2 +- .../menu/test/MenuTrigger.ssr.test.js | 2 +- .../menu/test/MenuTrigger.test.js | 2 +- .../meter/test/Meter.ssr.test.js | 2 +- .../@react-spectrum/meter/test/Meter.test.js | 2 +- .../@react-spectrum/numberfield/package.json | 2 +- .../numberfield/test/NumberField.ssr.test.js | 2 +- .../numberfield/test/NumberField.test.js | 2 +- .../overlays/test/Modal.test.js | 2 +- .../overlays/test/Overlay.test.js | 2 +- .../overlays/test/Popover.test.js | 2 +- .../overlays/test/Tray.test.js | 2 +- .../picker/test/Picker.ssr.test.js | 2 +- .../picker/test/Picker.test.js | 2 +- .../progress/test/ProgressBar.ssr.test.js | 2 +- .../progress/test/ProgressBar.test.js | 2 +- .../progress/test/ProgressCircle.ssr.test.js | 2 +- .../progress/test/ProgressCircle.test.js | 2 +- .../provider/test/Provider.ssr.test.js | 2 +- .../provider/test/Provider.test.tsx | 2 +- .../provider/test/mediaQueries.test.ts | 2 +- .../radio/test/Radio.ssr.test.js | 2 +- .../@react-spectrum/radio/test/Radio.test.js | 2 +- .../@react-spectrum/searchfield/package.json | 2 +- .../searchfield/test/SearchField.ssr.test.js | 2 +- .../searchfield/test/SearchField.test.js | 2 +- .../searchwithin/test/SearchWithin.test.js | 2 +- .../slider/test/RangeSlider.test.tsx | 2 +- .../slider/test/Slider.test.tsx | 2 +- packages/@react-spectrum/slider/test/utils.ts | 2 +- .../statuslight/test/StatusLight.ssr.test.js | 2 +- .../statuslight/test/StatusLight.test.js | 2 +- .../steplist/test/StepList.test.tsx | 2 +- .../switch/test/Switch.ssr.test.js | 2 +- .../switch/test/Switch.test.js | 2 +- .../table/test/Table.ssr.test.js | 2 +- .../@react-spectrum/table/test/Table.test.js | 2 +- .../table/test/TableDnd.test.js | 2 +- .../table/test/TableSizing.test.tsx | 2 +- .../table/test/TreeGridTable.test.tsx | 2 +- .../@react-spectrum/tabs/test/Tabs.test.js | 2 +- .../tag/test/TagGroup.ssr.test.js | 2 +- .../@react-spectrum/tag/test/TagGroup.test.js | 2 +- .../@react-spectrum/test-utils/package.json | 11 +++++----- .../@react-spectrum/test-utils/src/index.ts | 3 --- .../test-utils/src/testSetup.ts | 4 ++-- .../text/test/Heading.ssr.test.js | 2 +- .../text/test/Keyboard.ssr.test.js | 2 +- .../text/test/Text.ssr.test.js | 2 +- .../textfield/test/TextArea.ssr.test.js | 2 +- .../textfield/test/TextArea.test.js | 2 +- .../textfield/test/TextField.ssr.test.js | 2 +- .../textfield/test/TextField.test.js | 2 +- packages/@react-spectrum/toast/package.json | 2 +- .../toast/test/ToastContainer.ssr.test.js | 2 +- .../toast/test/ToastContainer.test.js | 2 +- .../tooltip/test/Tooltip.test.js | 2 +- .../tooltip/test/TooltipTrigger.test.js | 2 +- .../@react-spectrum/utils/test/Slots.test.js | 2 +- .../view/test/Content.ssr.test.js | 2 +- .../view/test/Footer.ssr.test.js | 2 +- .../view/test/Header.ssr.test.js | 2 +- .../view/test/View.ssr.test.js | 2 +- .../@react-spectrum/view/test/View.test.js | 2 +- .../well/test/Well.ssr.test.js | 2 +- .../@react-spectrum/well/test/Well.test.js | 2 +- .../test/useCheckboxGroupState.test.tsx | 2 +- .../color/test/useColor.test.js | 2 +- .../color/test/useColorFieldState.test.js | 2 +- .../combobox/test/useComboBoxState.test.js | 2 +- .../data/test/useAsyncList.test.js | 2 +- .../data/test/useListData.test.js | 2 +- .../data/test/useTreeData.test.js | 2 +- .../test/usePaginationState.test.js | 2 +- .../test/useSearchFieldState.test.js | 2 +- .../slider/test/useSliderState.test.js | 2 +- .../toast/test/useToastState.test.js | 2 +- .../test/useTooltipTriggerState.test.js | 3 +-- .../tree/test/useTreeState.test.js | 2 +- .../utils/test/useControlledState.test.tsx | 2 +- .../dev/docs/pages/react-spectrum/testing.mdx | 14 +++++------- packages/dev/test-utils/package.json | 22 +++---------------- .../test-utils/src/StrictModeWrapper.tsx | 0 packages/dev/test-utils/src/index.ts | 4 ++++ .../test-utils/src/mockImplementation.ts | 0 .../test-utils/src/renderOverride.js | 0 .../test/Breadcrumbs.ssr.test.js | 3 +-- .../test/Breadcrumbs.test.js | 2 +- .../react-aria-components/test/Button.test.js | 2 +- .../test/Calendar.test.js | 2 +- .../test/Checkbox.test.js | 2 +- .../test/CheckboxGroup.test.js | 2 +- .../test/ComboBox.ssr.test.js | 3 +-- .../test/ComboBox.test.js | 2 +- .../test/DateField.test.js | 2 +- .../test/DatePicker.test.js | 2 +- .../test/DateRangePicker.test.js | 2 +- .../test/Dialog.ssr.test.js | 3 +-- .../react-aria-components/test/Dialog.test.js | 2 +- .../test/DropZone.test.js | 2 +- .../test/FileTrigger.test.js | 6 ++--- .../react-aria-components/test/Form.test.js | 2 +- .../test/GridList.ssr.test.js | 3 +-- .../test/GridList.test.js | 2 +- .../react-aria-components/test/Group.test.tsx | 2 +- .../react-aria-components/test/Link.test.js | 2 +- .../test/ListBox.ssr.test.js | 3 +-- .../test/ListBox.test.js | 2 +- .../react-aria-components/test/Menu.test.js | 2 +- .../react-aria-components/test/Meter.test.js | 2 +- .../test/NumberField.test.js | 2 +- .../test/Popover.test.js | 2 +- .../test/ProgressBar.test.js | 2 +- .../test/RadioGroup.test.js | 2 +- .../test/RangeCalendar.test.js | 2 +- .../test/SearchField.test.js | 2 +- .../test/Select.ssr.test.js | 3 +-- .../react-aria-components/test/Select.test.js | 2 +- .../react-aria-components/test/Slider.test.js | 2 +- .../react-aria-components/test/Switch.test.js | 2 +- .../test/Table.ssr.test.js | 3 +-- .../react-aria-components/test/Table.test.js | 2 +- .../test/Tabs.ssr.test.js | 3 +-- .../react-aria-components/test/Tabs.test.js | 2 +- .../test/TagGroup.ssr.test.js | 3 +-- .../test/TagGroup.test.js | 2 +- .../test/TextField.test.js | 2 +- .../test/TimeField.test.js | 2 +- .../test/ToggleButton.test.js | 2 +- .../test/Toolbar.test.tsx | 2 +- .../test/Tooltip.test.js | 2 +- .../test/use{{ componentName }}.test.js.hbs | 2 +- .../test/{{ componentName }}.test.js.hbs | 2 +- scripts/bumpVersions.js | 2 +- scripts/checkPublishedDependencies.js | 2 +- scripts/lint-packages.js | 2 +- 279 files changed, 293 insertions(+), 323 deletions(-) rename packages/{@react-spectrum => dev}/test-utils/src/StrictModeWrapper.tsx (100%) rename packages/{@react-spectrum => dev}/test-utils/src/mockImplementation.ts (100%) rename packages/{@react-spectrum => dev}/test-utils/src/renderOverride.js (100%) diff --git a/jest.ssr.config.js b/jest.ssr.config.js index efab702ffeb..88c7f069d26 100644 --- a/jest.ssr.config.js +++ b/jest.ssr.config.js @@ -36,8 +36,8 @@ module.exports = { testTimeout: 30000, - globalSetup: require.resolve('@react-spectrum/test-utils-test/src/ssrSetup'), - globalTeardown: require.resolve('@react-spectrum/test-utils-test/src/ssrTeardown'), + globalSetup: require.resolve('@react-spectrum/test-utils-internal/src/ssrSetup'), + globalTeardown: require.resolve('@react-spectrum/test-utils-internal/src/ssrTeardown'), // The test environment that will be used for testing testEnvironment: 'jsdom', diff --git a/packages/@adobe/react-spectrum/test/ActionGroup.test.tsx b/packages/@adobe/react-spectrum/test/ActionGroup.test.tsx index ef2941a4657..ec16114c8fc 100644 --- a/packages/@adobe/react-spectrum/test/ActionGroup.test.tsx +++ b/packages/@adobe/react-spectrum/test/ActionGroup.test.tsx @@ -13,7 +13,7 @@ import {ActionGroup, Item} from '../'; import {Provider} from '@react-spectrum/provider'; import React from 'react'; -import {render} from '@react-spectrum/test-utils'; +import {render} from '@react-spectrum/test-utils-internal'; import scaleMedium from '@adobe/spectrum-css-temp/vars/spectrum-medium-unique.css'; import themeLight from '@adobe/spectrum-css-temp/vars/spectrum-light-unique.css'; diff --git a/packages/@react-aria/actiongroup/test/useActionGroup.test.ts b/packages/@react-aria/actiongroup/test/useActionGroup.test.ts index ce58e39bb05..47ed9679fc7 100644 --- a/packages/@react-aria/actiongroup/test/useActionGroup.test.ts +++ b/packages/@react-aria/actiongroup/test/useActionGroup.test.ts @@ -12,7 +12,7 @@ import {createRef} from 'react'; import {FocusableElement} from '@react-types/shared'; -import {renderHook} from '@react-spectrum/test-utils'; +import {renderHook} from '@react-spectrum/test-utils-internal'; import {useActionGroup} from '../'; import {useListState} from '@react-stately/list'; diff --git a/packages/@react-aria/aria-modal-polyfill/test/index.test.tsx b/packages/@react-aria/aria-modal-polyfill/test/index.test.tsx index 7cdb04e077c..162cbbe9a4d 100644 --- a/packages/@react-aria/aria-modal-polyfill/test/index.test.tsx +++ b/packages/@react-aria/aria-modal-polyfill/test/index.test.tsx @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, pointerMap, render, simulateMobile, waitFor} from '@react-spectrum/test-utils'; +import {act, pointerMap, render, simulateMobile, waitFor} from '@react-spectrum/test-utils-internal'; import {ActionButton, Button} from '@react-spectrum/button'; import {Content} from '@react-spectrum/view'; import {Dialog, DialogTrigger} from '@react-spectrum/dialog'; diff --git a/packages/@react-aria/autocomplete/test/useSearchAutocomplete.test.js b/packages/@react-aria/autocomplete/test/useSearchAutocomplete.test.js index 3c00f30c57f..cbd2c8f53d4 100644 --- a/packages/@react-aria/autocomplete/test/useSearchAutocomplete.test.js +++ b/packages/@react-aria/autocomplete/test/useSearchAutocomplete.test.js @@ -13,7 +13,7 @@ import {Item} from '@react-stately/collections'; import {ListLayout} from '@react-stately/layout'; import React from 'react'; -import {renderHook} from '@react-spectrum/test-utils'; +import {renderHook} from '@react-spectrum/test-utils-internal'; import {useComboBoxState} from '@react-stately/combobox'; import {useSearchAutocomplete} from '../'; diff --git a/packages/@react-aria/breadcrumbs/test/useBreadcrumbItem.test.js b/packages/@react-aria/breadcrumbs/test/useBreadcrumbItem.test.js index 0075a31e610..48ee36a83e6 100644 --- a/packages/@react-aria/breadcrumbs/test/useBreadcrumbItem.test.js +++ b/packages/@react-aria/breadcrumbs/test/useBreadcrumbItem.test.js @@ -11,7 +11,7 @@ */ import React from 'react'; -import {renderHook} from '@react-spectrum/test-utils'; +import {renderHook} from '@react-spectrum/test-utils-internal'; import {useBreadcrumbItem} from '../'; describe('useBreadcrumbItem', function () { diff --git a/packages/@react-aria/breadcrumbs/test/useBreadcrumbs.test.js b/packages/@react-aria/breadcrumbs/test/useBreadcrumbs.test.js index 521f469c011..7c208d6cfad 100644 --- a/packages/@react-aria/breadcrumbs/test/useBreadcrumbs.test.js +++ b/packages/@react-aria/breadcrumbs/test/useBreadcrumbs.test.js @@ -11,7 +11,7 @@ */ import React from 'react'; -import {renderHook} from '@react-spectrum/test-utils'; +import {renderHook} from '@react-spectrum/test-utils-internal'; import {useBreadcrumbs} from '../'; describe('useBreadcrumbs', function () { diff --git a/packages/@react-aria/button/test/useButton.test.js b/packages/@react-aria/button/test/useButton.test.js index 23bcabfdf4b..913e1586625 100644 --- a/packages/@react-aria/button/test/useButton.test.js +++ b/packages/@react-aria/button/test/useButton.test.js @@ -11,7 +11,7 @@ */ import React from 'react'; -import {renderHook} from '@react-spectrum/test-utils'; +import {renderHook} from '@react-spectrum/test-utils-internal'; import {useButton} from '../'; describe('useButton tests', function () { diff --git a/packages/@react-aria/calendar/test/useCalendar.test.js b/packages/@react-aria/calendar/test/useCalendar.test.js index 8e6015eaacd..db34fd92e66 100644 --- a/packages/@react-aria/calendar/test/useCalendar.test.js +++ b/packages/@react-aria/calendar/test/useCalendar.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, pointerMap, render} from '@react-spectrum/test-utils'; +import {act, pointerMap, render} from '@react-spectrum/test-utils-internal'; import {CalendarDate} from '@internationalized/date'; import {Example} from '../stories/Example'; import React from 'react'; diff --git a/packages/@react-aria/checkbox/test/useCheckboxGroup.test.tsx b/packages/@react-aria/checkbox/test/useCheckboxGroup.test.tsx index a080b41a59f..90e2c85878e 100644 --- a/packages/@react-aria/checkbox/test/useCheckboxGroup.test.tsx +++ b/packages/@react-aria/checkbox/test/useCheckboxGroup.test.tsx @@ -12,7 +12,7 @@ import {AriaCheckboxGroupItemProps, AriaCheckboxGroupProps} from '@react-types/checkbox'; import {CheckboxGroupState, useCheckboxGroupState} from '@react-stately/checkbox'; -import {pointerMap, render} from '@react-spectrum/test-utils'; +import {pointerMap, render} from '@react-spectrum/test-utils-internal'; import React, {useRef} from 'react'; import {useCheckboxGroup, useCheckboxGroupItem} from '../'; import userEvent from '@testing-library/user-event'; diff --git a/packages/@react-aria/color/test/useColorField.test.js b/packages/@react-aria/color/test/useColorField.test.js index 4a2241c7f3a..ad1603520b3 100644 --- a/packages/@react-aria/color/test/useColorField.test.js +++ b/packages/@react-aria/color/test/useColorField.test.js @@ -12,7 +12,7 @@ import {parseColor, useColorFieldState} from '@react-stately/color'; import React from 'react'; -import {renderHook} from '@react-spectrum/test-utils'; +import {renderHook} from '@react-spectrum/test-utils-internal'; import {useColorField} from '../'; describe('useColorField', function () { diff --git a/packages/@react-aria/color/test/useColorWheel.test.tsx b/packages/@react-aria/color/test/useColorWheel.test.tsx index 874a3eb3630..03d343be3f5 100644 --- a/packages/@react-aria/color/test/useColorWheel.test.tsx +++ b/packages/@react-aria/color/test/useColorWheel.test.tsx @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, installMouseEvent, installPointerEvent, pointerMap, render} from '@react-spectrum/test-utils'; +import {act, fireEvent, installMouseEvent, installPointerEvent, pointerMap, render} from '@react-spectrum/test-utils-internal'; import {ColorWheelProps} from '@react-types/color'; import {parseColor, useColorWheelState} from '@react-stately/color'; import React, {useRef} from 'react'; diff --git a/packages/@react-aria/combobox/test/useComboBox.test.js b/packages/@react-aria/combobox/test/useComboBox.test.js index 4032e791cdc..ca8bbc90b03 100644 --- a/packages/@react-aria/combobox/test/useComboBox.test.js +++ b/packages/@react-aria/combobox/test/useComboBox.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {actHook as act, renderHook} from '@react-spectrum/test-utils'; +import {actHook as act, renderHook} from '@react-spectrum/test-utils-internal'; import {Item} from '@react-stately/collections'; import {ListLayout} from '@react-stately/layout'; import React from 'react'; diff --git a/packages/@react-aria/dialog/test/useDialog.test.js b/packages/@react-aria/dialog/test/useDialog.test.js index 3d31c3bdac5..7678c25b1c7 100644 --- a/packages/@react-aria/dialog/test/useDialog.test.js +++ b/packages/@react-aria/dialog/test/useDialog.test.js @@ -11,7 +11,7 @@ */ import React, {useRef} from 'react'; -import {render} from '@react-spectrum/test-utils'; +import {render} from '@react-spectrum/test-utils-internal'; import {useDialog} from '../'; function Example(props) { diff --git a/packages/@react-aria/dnd/test/dnd.ssr.test.js b/packages/@react-aria/dnd/test/dnd.ssr.test.js index a975b4b9e2a..d1a70a3e1df 100644 --- a/packages/@react-aria/dnd/test/dnd.ssr.test.js +++ b/packages/@react-aria/dnd/test/dnd.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('useDrag and useDrop SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-aria/dnd/test/dnd.test.js b/packages/@react-aria/dnd/test/dnd.test.js index c0220cca2ca..014df667e51 100644 --- a/packages/@react-aria/dnd/test/dnd.test.js +++ b/packages/@react-aria/dnd/test/dnd.test.js @@ -11,7 +11,7 @@ */ jest.mock('@react-aria/live-announcer'); -import {act, fireEvent, pointerMap, render} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render} from '@react-spectrum/test-utils-internal'; import {announce} from '@react-aria/live-announcer'; import {CUSTOM_DRAG_TYPE} from '../src/constants'; import {DataTransfer, DataTransferItem, DragEvent, FileSystemDirectoryEntry, FileSystemFileEntry} from './mocks'; diff --git a/packages/@react-aria/dnd/test/useClipboard.test.js b/packages/@react-aria/dnd/test/useClipboard.test.js index 528c1ccf87c..f24a8477faa 100644 --- a/packages/@react-aria/dnd/test/useClipboard.test.js +++ b/packages/@react-aria/dnd/test/useClipboard.test.js @@ -11,7 +11,7 @@ */ import {ClipboardEvent, DataTransfer, DataTransferItem} from './mocks'; -import {fireEvent, pointerMap, render} from '@react-spectrum/test-utils'; +import {fireEvent, pointerMap, render} from '@react-spectrum/test-utils-internal'; import React from 'react'; import {useClipboard} from '../'; import userEvent from '@testing-library/user-event'; diff --git a/packages/@react-aria/dnd/test/useDraggableCollection.test.js b/packages/@react-aria/dnd/test/useDraggableCollection.test.js index 1e4f2c41bb6..55affcdb23a 100644 --- a/packages/@react-aria/dnd/test/useDraggableCollection.test.js +++ b/packages/@react-aria/dnd/test/useDraggableCollection.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, installPointerEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, installPointerEvent, pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import {DataTransfer, DataTransferItem, DragEvent} from './mocks'; import {DraggableCollectionExample} from '../stories/DraggableCollection'; import {DraggableListBox} from '../stories/DraggableListBox'; diff --git a/packages/@react-aria/dnd/test/useDroppableCollection.test.js b/packages/@react-aria/dnd/test/useDroppableCollection.test.js index 53f5d446b6f..6e640d80db0 100644 --- a/packages/@react-aria/dnd/test/useDroppableCollection.test.js +++ b/packages/@react-aria/dnd/test/useDroppableCollection.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, waitFor, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, waitFor, within} from '@react-spectrum/test-utils-internal'; import {DataTransfer, DragEvent} from './mocks'; import {Draggable} from './examples'; import {DroppableGridExample} from '../stories/DroppableGrid'; diff --git a/packages/@react-aria/focus/test/FocusScope.test.js b/packages/@react-aria/focus/test/FocusScope.test.js index 645bea6aa71..00f7a6ba8a2 100644 --- a/packages/@react-aria/focus/test/FocusScope.test.js +++ b/packages/@react-aria/focus/test/FocusScope.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, waitFor} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, waitFor} from '@react-spectrum/test-utils-internal'; import {defaultTheme} from '@adobe/react-spectrum'; import {DialogContainer} from '@react-spectrum/dialog'; import {FocusScope, useFocusManager} from '../'; diff --git a/packages/@react-aria/grid/test/useGrid.test.js b/packages/@react-aria/grid/test/useGrid.test.js index 2ba8c5e61e7..8804655b940 100644 --- a/packages/@react-aria/grid/test/useGrid.test.js +++ b/packages/@react-aria/grid/test/useGrid.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, pointerMap, render} from '@react-spectrum/test-utils'; +import {act, pointerMap, render} from '@react-spectrum/test-utils-internal'; import {Grid} from '../stories/example'; import {Item} from '@react-stately/collections'; import React from 'react'; diff --git a/packages/@react-aria/interactions/test/PressResponder.test.js b/packages/@react-aria/interactions/test/PressResponder.test.js index 72baa31250d..b00099ab405 100644 --- a/packages/@react-aria/interactions/test/PressResponder.test.js +++ b/packages/@react-aria/interactions/test/PressResponder.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {pointerMap, render} from '@react-spectrum/test-utils'; +import {pointerMap, render} from '@react-spectrum/test-utils-internal'; import {Pressable, PressResponder} from '../'; import React from 'react'; import userEvent from '@testing-library/user-event'; diff --git a/packages/@react-aria/interactions/test/Pressable.test.js b/packages/@react-aria/interactions/test/Pressable.test.js index 8a9484512f7..8990ad56617 100644 --- a/packages/@react-aria/interactions/test/Pressable.test.js +++ b/packages/@react-aria/interactions/test/Pressable.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {pointerMap, render} from '@react-spectrum/test-utils'; +import {pointerMap, render} from '@react-spectrum/test-utils-internal'; import {Pressable} from '../'; import React from 'react'; import userEvent from '@testing-library/user-event'; diff --git a/packages/@react-aria/interactions/test/useFocus.test.js b/packages/@react-aria/interactions/test/useFocus.test.js index c95ab03cc5d..85b1196b66a 100644 --- a/packages/@react-aria/interactions/test/useFocus.test.js +++ b/packages/@react-aria/interactions/test/useFocus.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, render, waitFor} from '@react-spectrum/test-utils'; +import {act, render, waitFor} from '@react-spectrum/test-utils-internal'; import React from 'react'; import {useFocus} from '../'; diff --git a/packages/@react-aria/interactions/test/useFocusVisible.test.js b/packages/@react-aria/interactions/test/useFocusVisible.test.js index 14833072d75..e5494bf3185 100644 --- a/packages/@react-aria/interactions/test/useFocusVisible.test.js +++ b/packages/@react-aria/interactions/test/useFocusVisible.test.js @@ -9,7 +9,7 @@ * OF ANY KIND, either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ -import {act, fireEvent, render, renderHook, screen} from '@react-spectrum/test-utils'; +import {act, fireEvent, render, renderHook, screen} from '@react-spectrum/test-utils-internal'; import React from 'react'; import {useFocusVisible, useFocusVisibleListener} from '../'; diff --git a/packages/@react-aria/interactions/test/useFocusWithin.test.js b/packages/@react-aria/interactions/test/useFocusWithin.test.js index 763d480680b..3aa8e13ed19 100644 --- a/packages/@react-aria/interactions/test/useFocusWithin.test.js +++ b/packages/@react-aria/interactions/test/useFocusWithin.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, render, waitFor} from '@react-spectrum/test-utils'; +import {act, render, waitFor} from '@react-spectrum/test-utils-internal'; import React from 'react'; import {useFocusWithin} from '../'; diff --git a/packages/@react-aria/interactions/test/useHover.test.js b/packages/@react-aria/interactions/test/useHover.test.js index d10f9fc692e..32542e59770 100644 --- a/packages/@react-aria/interactions/test/useHover.test.js +++ b/packages/@react-aria/interactions/test/useHover.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, installMouseEvent, installPointerEvent, render} from '@react-spectrum/test-utils'; +import {act, fireEvent, installMouseEvent, installPointerEvent, render} from '@react-spectrum/test-utils-internal'; import {ActionButton} from '@react-spectrum/button'; import {Dialog, DialogTrigger} from '@react-spectrum/dialog'; import MatchMediaMock from 'jest-matchmedia-mock'; diff --git a/packages/@react-aria/interactions/test/useInteractOutside.test.js b/packages/@react-aria/interactions/test/useInteractOutside.test.js index b4e13f3f216..381514f262e 100644 --- a/packages/@react-aria/interactions/test/useInteractOutside.test.js +++ b/packages/@react-aria/interactions/test/useInteractOutside.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {fireEvent, installPointerEvent, render, waitFor} from '@react-spectrum/test-utils'; +import {fireEvent, installPointerEvent, render, waitFor} from '@react-spectrum/test-utils-internal'; import React, {useRef} from 'react'; import {render as ReactDOMRender} from 'react-dom'; import {useInteractOutside} from '../'; diff --git a/packages/@react-aria/interactions/test/useKeyboard.test.js b/packages/@react-aria/interactions/test/useKeyboard.test.js index b06c98686dd..65c69375f0b 100644 --- a/packages/@react-aria/interactions/test/useKeyboard.test.js +++ b/packages/@react-aria/interactions/test/useKeyboard.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, pointerMap, render} from '@react-spectrum/test-utils'; +import {act, pointerMap, render} from '@react-spectrum/test-utils-internal'; import React from 'react'; import {useKeyboard} from '../'; import userEvent from '@testing-library/user-event'; diff --git a/packages/@react-aria/interactions/test/useLongPress.test.js b/packages/@react-aria/interactions/test/useLongPress.test.js index b23f1fb0684..c6b7786cadf 100644 --- a/packages/@react-aria/interactions/test/useLongPress.test.js +++ b/packages/@react-aria/interactions/test/useLongPress.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, installPointerEvent, render} from '@react-spectrum/test-utils'; +import {act, fireEvent, installPointerEvent, render} from '@react-spectrum/test-utils-internal'; import {mergeProps} from '@react-aria/utils'; import React from 'react'; import {useLongPress, usePress} from '../'; diff --git a/packages/@react-aria/interactions/test/useMove.test.js b/packages/@react-aria/interactions/test/useMove.test.js index 66f6a923bff..ef4c0966629 100644 --- a/packages/@react-aria/interactions/test/useMove.test.js +++ b/packages/@react-aria/interactions/test/useMove.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, installMouseEvent, installPointerEvent, render} from '@react-spectrum/test-utils'; +import {act, fireEvent, installMouseEvent, installPointerEvent, render} from '@react-spectrum/test-utils-internal'; import React from 'react'; import {useMove} from '../'; diff --git a/packages/@react-aria/interactions/test/usePress.test.js b/packages/@react-aria/interactions/test/usePress.test.js index cb9770cc94e..ff18805ce86 100644 --- a/packages/@react-aria/interactions/test/usePress.test.js +++ b/packages/@react-aria/interactions/test/usePress.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, installMouseEvent, installPointerEvent, render, waitFor} from '@react-spectrum/test-utils'; +import {act, fireEvent, installMouseEvent, installPointerEvent, render, waitFor} from '@react-spectrum/test-utils-internal'; import {ActionButton} from '@react-spectrum/button'; import {Dialog, DialogTrigger} from '@react-spectrum/dialog'; import MatchMediaMock from 'jest-matchmedia-mock'; diff --git a/packages/@react-aria/label/test/useField.test.js b/packages/@react-aria/label/test/useField.test.js index d2d2c76df5c..9b9d093d07b 100644 --- a/packages/@react-aria/label/test/useField.test.js +++ b/packages/@react-aria/label/test/useField.test.js @@ -12,7 +12,7 @@ import {composeStories} from '@storybook/testing-react'; import React from 'react'; -import {render, renderHook} from '@react-spectrum/test-utils'; +import {render, renderHook} from '@react-spectrum/test-utils-internal'; import * as stories from '../stories/useField.stories'; import {useField} from '../'; diff --git a/packages/@react-aria/label/test/useLabel.test.js b/packages/@react-aria/label/test/useLabel.test.js index f062c34441a..38831799b48 100644 --- a/packages/@react-aria/label/test/useLabel.test.js +++ b/packages/@react-aria/label/test/useLabel.test.js @@ -11,7 +11,7 @@ */ import React from 'react'; -import {renderHook} from '@react-spectrum/test-utils'; +import {renderHook} from '@react-spectrum/test-utils-internal'; import {useLabel} from '../'; describe('useLabel hook', () => { diff --git a/packages/@react-aria/landmark/test/useLandmark.ssr.test.js b/packages/@react-aria/landmark/test/useLandmark.ssr.test.js index 1dc5436ecb5..09f21a66703 100644 --- a/packages/@react-aria/landmark/test/useLandmark.ssr.test.js +++ b/packages/@react-aria/landmark/test/useLandmark.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('useLandmark SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-aria/landmark/test/useLandmark.test.tsx b/packages/@react-aria/landmark/test/useLandmark.test.tsx index 95af202be6c..34919310dd4 100644 --- a/packages/@react-aria/landmark/test/useLandmark.test.tsx +++ b/packages/@react-aria/landmark/test/useLandmark.test.tsx @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import {ActionGroup, Item} from '@react-spectrum/actiongroup'; import {Button} from '@react-spectrum/button'; import {Cell, Column, Row, TableBody, TableHeader, TableView} from '@react-spectrum/table'; diff --git a/packages/@react-aria/link/test/useLink.test.js b/packages/@react-aria/link/test/useLink.test.js index 570c852f740..7af03681602 100644 --- a/packages/@react-aria/link/test/useLink.test.js +++ b/packages/@react-aria/link/test/useLink.test.js @@ -11,7 +11,7 @@ */ import React from 'react'; -import {renderHook} from '@react-spectrum/test-utils'; +import {renderHook} from '@react-spectrum/test-utils-internal'; import {useLink} from '../'; describe('useLink', function () { diff --git a/packages/@react-aria/menu/test/useMenuTrigger.test.js b/packages/@react-aria/menu/test/useMenuTrigger.test.js index 56e5777cfa6..7ef284d88ca 100644 --- a/packages/@react-aria/menu/test/useMenuTrigger.test.js +++ b/packages/@react-aria/menu/test/useMenuTrigger.test.js @@ -11,7 +11,7 @@ */ import React from 'react'; -import {renderHook} from '@react-spectrum/test-utils'; +import {renderHook} from '@react-spectrum/test-utils-internal'; import {useMenuTrigger} from '../'; describe('useMenuTrigger', function () { diff --git a/packages/@react-aria/numberfield/test/useNumberField.test.ts b/packages/@react-aria/numberfield/test/useNumberField.test.ts index c2c9f535181..5c4efd9ce29 100644 --- a/packages/@react-aria/numberfield/test/useNumberField.test.ts +++ b/packages/@react-aria/numberfield/test/useNumberField.test.ts @@ -1,6 +1,6 @@ import {AriaNumberFieldProps} from '@react-types/numberfield'; import React from 'react'; -import {renderHook} from '@react-spectrum/test-utils'; +import {renderHook} from '@react-spectrum/test-utils-internal'; import {useLocale} from '@react-aria/i18n'; import {useNumberField} from '../'; import {useNumberFieldState} from '@react-stately/numberfield'; diff --git a/packages/@react-aria/overlays/test/DismissButton.test.tsx b/packages/@react-aria/overlays/test/DismissButton.test.tsx index 85e1cbf5557..15ac79412a6 100644 --- a/packages/@react-aria/overlays/test/DismissButton.test.tsx +++ b/packages/@react-aria/overlays/test/DismissButton.test.tsx @@ -12,7 +12,7 @@ import {DismissButton} from '..'; import React from 'react'; -import {render} from '@react-spectrum/test-utils'; +import {render} from '@react-spectrum/test-utils-internal'; describe('DismissButton', function () { diff --git a/packages/@react-aria/overlays/test/ariaHideOutside.test.js b/packages/@react-aria/overlays/test/ariaHideOutside.test.js index 44434ba32fd..2a9f610f4c2 100644 --- a/packages/@react-aria/overlays/test/ariaHideOutside.test.js +++ b/packages/@react-aria/overlays/test/ariaHideOutside.test.js @@ -12,7 +12,7 @@ import {ariaHideOutside} from '../src'; import React from 'react'; -import {render, waitFor} from '@react-spectrum/test-utils'; +import {render, waitFor} from '@react-spectrum/test-utils-internal'; describe('ariaHideOutside', function () { it('should hide everything except the provided element [button]', function () { diff --git a/packages/@react-aria/overlays/test/useModal.ssr.test.js b/packages/@react-aria/overlays/test/useModal.ssr.test.js index 0a198f428a6..9a785ba8731 100644 --- a/packages/@react-aria/overlays/test/useModal.ssr.test.js +++ b/packages/@react-aria/overlays/test/useModal.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('OverlayContainer SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-aria/overlays/test/useModal.test.js b/packages/@react-aria/overlays/test/useModal.test.js index f87d1258db5..92c5b4f58d1 100644 --- a/packages/@react-aria/overlays/test/useModal.test.js +++ b/packages/@react-aria/overlays/test/useModal.test.js @@ -12,7 +12,7 @@ import {OverlayContainer, OverlayProvider, useModal} from '..'; import React from 'react'; -import {render} from '@react-spectrum/test-utils'; +import {render} from '@react-spectrum/test-utils-internal'; function ModalDOM(props) { let {modalProps} = useModal(); diff --git a/packages/@react-aria/overlays/test/useOverlay.test.js b/packages/@react-aria/overlays/test/useOverlay.test.js index 771885939d8..050de17b0dd 100644 --- a/packages/@react-aria/overlays/test/useOverlay.test.js +++ b/packages/@react-aria/overlays/test/useOverlay.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {fireEvent, installMouseEvent, installPointerEvent, render} from '@react-spectrum/test-utils'; +import {fireEvent, installMouseEvent, installPointerEvent, render} from '@react-spectrum/test-utils-internal'; import {mergeProps} from '@react-aria/utils'; import React, {useRef} from 'react'; import {useOverlay} from '../'; diff --git a/packages/@react-aria/overlays/test/useOverlayPosition.test.tsx b/packages/@react-aria/overlays/test/useOverlayPosition.test.tsx index 2bb2830af26..91da73b37a2 100644 --- a/packages/@react-aria/overlays/test/useOverlayPosition.test.tsx +++ b/packages/@react-aria/overlays/test/useOverlayPosition.test.tsx @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {fireEvent, render} from '@react-spectrum/test-utils'; +import {fireEvent, render} from '@react-spectrum/test-utils-internal'; import React, {useRef} from 'react'; import {useOverlayPosition} from '../'; diff --git a/packages/@react-aria/overlays/test/useOverlayTrigger.test.js b/packages/@react-aria/overlays/test/useOverlayTrigger.test.js index 377dc569ee1..869f4adf7b3 100644 --- a/packages/@react-aria/overlays/test/useOverlayTrigger.test.js +++ b/packages/@react-aria/overlays/test/useOverlayTrigger.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {fireEvent, render} from '@react-spectrum/test-utils'; +import {fireEvent, render} from '@react-spectrum/test-utils-internal'; import React, {useRef} from 'react'; import {useOverlayPosition, useOverlayTrigger} from '../'; import {useOverlayTriggerState} from '@react-stately/overlays'; diff --git a/packages/@react-aria/overlays/test/usePreventScroll.test.js b/packages/@react-aria/overlays/test/usePreventScroll.test.js index 65dc7f880bc..3e198e9f961 100644 --- a/packages/@react-aria/overlays/test/usePreventScroll.test.js +++ b/packages/@react-aria/overlays/test/usePreventScroll.test.js @@ -11,7 +11,7 @@ */ import React from 'react'; -import {render} from '@react-spectrum/test-utils'; +import {render} from '@react-spectrum/test-utils-internal'; import {usePreventScroll} from '..'; function Example(props) { diff --git a/packages/@react-aria/pagination/test/usePagination.test.js b/packages/@react-aria/pagination/test/usePagination.test.js index a5eca6871e9..bb50c6c7c61 100644 --- a/packages/@react-aria/pagination/test/usePagination.test.js +++ b/packages/@react-aria/pagination/test/usePagination.test.js @@ -11,7 +11,7 @@ */ import React from 'react'; -import {renderHook} from '@react-spectrum/test-utils'; +import {renderHook} from '@react-spectrum/test-utils-internal'; import {usePagination} from '../'; describe('usePagination tests', function () { diff --git a/packages/@react-aria/progress/test/useProgressBar.test.js b/packages/@react-aria/progress/test/useProgressBar.test.js index b199291f5d8..833aaf10650 100644 --- a/packages/@react-aria/progress/test/useProgressBar.test.js +++ b/packages/@react-aria/progress/test/useProgressBar.test.js @@ -11,7 +11,7 @@ */ import React from 'react'; -import {renderHook} from '@react-spectrum/test-utils'; +import {renderHook} from '@react-spectrum/test-utils-internal'; import {useProgressBar} from '../'; describe('useProgressBar', function () { diff --git a/packages/@react-aria/searchfield/test/useSearchField.test.js b/packages/@react-aria/searchfield/test/useSearchField.test.js index bc9c7dec036..888ffc4267f 100644 --- a/packages/@react-aria/searchfield/test/useSearchField.test.js +++ b/packages/@react-aria/searchfield/test/useSearchField.test.js @@ -14,7 +14,7 @@ import intlMessages from '../intl/*.json'; import {Provider} from '@react-spectrum/provider'; import React from 'react'; -import {renderHook} from '@react-spectrum/test-utils'; +import {renderHook} from '@react-spectrum/test-utils-internal'; import {theme} from '@react-spectrum/theme-default'; import {useSearchField} from '../'; diff --git a/packages/@react-aria/select/test/HiddenSelect.test.tsx b/packages/@react-aria/select/test/HiddenSelect.test.tsx index 2fb4b4f83b0..43073086d2a 100644 --- a/packages/@react-aria/select/test/HiddenSelect.test.tsx +++ b/packages/@react-aria/select/test/HiddenSelect.test.tsx @@ -1,6 +1,6 @@ import {HiddenSelect, HiddenSelectProps} from '../src'; import {Item} from 'react-stately'; -import {pointerMap} from '@react-spectrum/test-utils'; +import {pointerMap} from '@react-spectrum/test-utils-internal'; import React, {useRef} from 'react'; import {render, screen} from '@testing-library/react'; import {SelectProps, useSelectState} from '@react-stately/select'; diff --git a/packages/@react-aria/selection/test/useSelectableCollection.test.js b/packages/@react-aria/selection/test/useSelectableCollection.test.js index 346de9d3ab3..d8c0801177c 100644 --- a/packages/@react-aria/selection/test/useSelectableCollection.test.js +++ b/packages/@react-aria/selection/test/useSelectableCollection.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {fireEvent, installPointerEvent, pointerMap, render, simulateDesktop, simulateMobile} from '@react-spectrum/test-utils'; +import {fireEvent, installPointerEvent, pointerMap, render, simulateDesktop, simulateMobile} from '@react-spectrum/test-utils-internal'; import {Item} from '@react-stately/collections'; import {List} from '../stories/List'; import React from 'react'; diff --git a/packages/@react-aria/slider/test/useSlider.test.js b/packages/@react-aria/slider/test/useSlider.test.js index 54cce20ac77..7bcaed97e0d 100644 --- a/packages/@react-aria/slider/test/useSlider.test.js +++ b/packages/@react-aria/slider/test/useSlider.test.js @@ -1,4 +1,4 @@ -import {fireEvent, installMouseEvent, installPointerEvent, render, renderHook, screen} from '@react-spectrum/test-utils'; +import {fireEvent, installMouseEvent, installPointerEvent, render, renderHook, screen} from '@react-spectrum/test-utils-internal'; import * as React from 'react'; import {useRef} from 'react'; import {useSlider, useSliderThumb} from '../src'; diff --git a/packages/@react-aria/slider/test/useSliderThumb.test.js b/packages/@react-aria/slider/test/useSliderThumb.test.js index ac58c27aed6..eefe094d5b6 100644 --- a/packages/@react-aria/slider/test/useSliderThumb.test.js +++ b/packages/@react-aria/slider/test/useSliderThumb.test.js @@ -1,4 +1,4 @@ -import {fireEvent, installMouseEvent, installPointerEvent, pointerMap, render, renderHook, screen} from '@react-spectrum/test-utils'; +import {fireEvent, installMouseEvent, installPointerEvent, pointerMap, render, renderHook, screen} from '@react-spectrum/test-utils-internal'; import * as React from 'react'; import {useRef} from 'react'; import userEvent from '@testing-library/user-event'; diff --git a/packages/@react-aria/spinbutton/test/useSpinButton.test.js b/packages/@react-aria/spinbutton/test/useSpinButton.test.js index 413fd223bac..70afbf812a6 100644 --- a/packages/@react-aria/spinbutton/test/useSpinButton.test.js +++ b/packages/@react-aria/spinbutton/test/useSpinButton.test.js @@ -11,7 +11,7 @@ */ jest.mock('@react-aria/live-announcer'); -import {act, pointerMap, render} from '@react-spectrum/test-utils'; +import {act, pointerMap, render} from '@react-spectrum/test-utils-internal'; import {announce} from '@react-aria/live-announcer'; import React from 'react'; import userEvent from '@testing-library/user-event'; diff --git a/packages/@react-aria/ssr/test/SSRProvider.ssr.test.js b/packages/@react-aria/ssr/test/SSRProvider.ssr.test.js index 9ed96f50203..bf7ea3b99e8 100644 --- a/packages/@react-aria/ssr/test/SSRProvider.ssr.test.js +++ b/packages/@react-aria/ssr/test/SSRProvider.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('SSRProvider SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-aria/ssr/test/SSRProvider.test.js b/packages/@react-aria/ssr/test/SSRProvider.test.js index bd8f4f33d74..494de29ffd2 100644 --- a/packages/@react-aria/ssr/test/SSRProvider.test.js +++ b/packages/@react-aria/ssr/test/SSRProvider.test.js @@ -11,7 +11,7 @@ */ import React from 'react'; -import {render} from '@react-spectrum/test-utils'; +import {render} from '@react-spectrum/test-utils-internal'; import {SSRProvider} from '../'; import {useId} from '@react-aria/utils'; diff --git a/packages/@react-aria/table/test/ariaTableResizing.test.tsx b/packages/@react-aria/table/test/ariaTableResizing.test.tsx index 9df53274203..63ca7312f06 100644 --- a/packages/@react-aria/table/test/ariaTableResizing.test.tsx +++ b/packages/@react-aria/table/test/ariaTableResizing.test.tsx @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent} from '@react-spectrum/test-utils'; +import {act, fireEvent} from '@react-spectrum/test-utils-internal'; import {Cell, Column, Row, TableBody, TableHeader} from '@react-stately/table'; import {composeStories} from '@storybook/testing-react'; import {Key} from '@react-types/shared'; diff --git a/packages/@react-aria/table/test/tableResizingTests.tsx b/packages/@react-aria/table/test/tableResizingTests.tsx index ddb90de95c0..d6a7bc15fff 100644 --- a/packages/@react-aria/table/test/tableResizingTests.tsx +++ b/packages/@react-aria/table/test/tableResizingTests.tsx @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, installPointerEvent} from '@react-spectrum/test-utils'; +import {act, installPointerEvent} from '@react-spectrum/test-utils-internal'; import React from 'react'; diff --git a/packages/@react-aria/table/test/useTable.test.tsx b/packages/@react-aria/table/test/useTable.test.tsx index c76b05dcfb2..2e7607770dd 100644 --- a/packages/@react-aria/table/test/useTable.test.tsx +++ b/packages/@react-aria/table/test/useTable.test.tsx @@ -13,7 +13,7 @@ jest.mock('@react-aria/live-announcer'); import {announce} from '@react-aria/live-announcer'; import {Cell, Column, Row, TableBody, TableHeader, useTableState} from '@react-stately/table'; -import {pointerMap, render} from '@react-spectrum/test-utils'; +import {pointerMap, render} from '@react-spectrum/test-utils-internal'; import React, {useRef} from 'react'; import { TableCell, diff --git a/packages/@react-aria/table/test/useTableBackwardCompat.test.tsx b/packages/@react-aria/table/test/useTableBackwardCompat.test.tsx index d6aab63bccb..2e8b13e9def 100644 --- a/packages/@react-aria/table/test/useTableBackwardCompat.test.tsx +++ b/packages/@react-aria/table/test/useTableBackwardCompat.test.tsx @@ -13,7 +13,7 @@ jest.mock('@react-aria/live-announcer'); import {announce} from '@react-aria/live-announcer'; import {Cell, Column, Row, TableBody, TableHeader, useTableState} from '@react-stately/table'; -import {pointerMap, render} from '@react-spectrum/test-utils'; +import {pointerMap, render} from '@react-spectrum/test-utils-internal'; import React, {useRef} from 'react'; import { TableCell, diff --git a/packages/@react-aria/tag/test/useTagGroup.test.js b/packages/@react-aria/tag/test/useTagGroup.test.js index 007d3e5fb17..da49c2eacfe 100644 --- a/packages/@react-aria/tag/test/useTagGroup.test.js +++ b/packages/@react-aria/tag/test/useTagGroup.test.js @@ -11,7 +11,7 @@ */ import {Item} from '@react-stately/collections'; -import {pointerMap, render, within} from '@react-spectrum/test-utils'; +import {pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import React from 'react'; import {useButton} from '@react-aria/button'; import {useListState} from '@react-stately/list'; diff --git a/packages/@react-aria/test-utils/src/events.ts b/packages/@react-aria/test-utils/src/events.ts index ea38f1f4496..a123cf04919 100644 --- a/packages/@react-aria/test-utils/src/events.ts +++ b/packages/@react-aria/test-utils/src/events.ts @@ -15,7 +15,7 @@ import {act, fireEvent} from '@testing-library/react'; // Triggers a "longPress" event on an element. export const DEFAULT_LONG_PRESS_TIME = 500; -export function triggerLongPress(element, opts = {}) { +export function triggerLongPress(element: HTMLElement, opts = {}): void { fireEvent.pointerDown(element, {pointerType: 'touch', ...opts}); act(() => { jest.advanceTimersByTime(DEFAULT_LONG_PRESS_TIME); diff --git a/packages/@react-aria/textfield/test/useTextField.test.js b/packages/@react-aria/textfield/test/useTextField.test.js index dbd49beed52..33994e385fe 100644 --- a/packages/@react-aria/textfield/test/useTextField.test.js +++ b/packages/@react-aria/textfield/test/useTextField.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {actHook, renderHook} from '@react-spectrum/test-utils'; +import {actHook, renderHook} from '@react-spectrum/test-utils-internal'; import React from 'react'; import {useTextField} from '../'; diff --git a/packages/@react-aria/toast/test/useToast.test.js b/packages/@react-aria/toast/test/useToast.test.js index 81ade7cdba9..48ccfcc58d0 100644 --- a/packages/@react-aria/toast/test/useToast.test.js +++ b/packages/@react-aria/toast/test/useToast.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {renderHook} from '@react-spectrum/test-utils'; +import {renderHook} from '@react-spectrum/test-utils-internal'; import {useRef} from 'react'; import {useToast} from '../'; diff --git a/packages/@react-aria/tooltip/test/useTooltip.test.js b/packages/@react-aria/tooltip/test/useTooltip.test.js index 78611cc8690..140ad3ac3c5 100644 --- a/packages/@react-aria/tooltip/test/useTooltip.test.js +++ b/packages/@react-aria/tooltip/test/useTooltip.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, render} from '@react-spectrum/test-utils'; +import {act, fireEvent, render} from '@react-spectrum/test-utils-internal'; import React from 'react'; import {useInteractionModality} from '@react-aria/interactions'; import {useTooltip, useTooltipTrigger} from '../'; diff --git a/packages/@react-aria/utils/test/useObjectRef.test.js b/packages/@react-aria/utils/test/useObjectRef.test.js index 08bf2868c9d..ac8a30c8214 100644 --- a/packages/@react-aria/utils/test/useObjectRef.test.js +++ b/packages/@react-aria/utils/test/useObjectRef.test.js @@ -11,7 +11,7 @@ */ import React, {useEffect} from 'react'; -import {render, renderHook, screen} from '@react-spectrum/test-utils'; +import {render, renderHook, screen} from '@react-spectrum/test-utils-internal'; // eslint-disable-next-line rulesdir/useLayoutEffectRule import {useLayoutEffect, useObjectRef} from '../'; diff --git a/packages/@react-aria/utils/test/useViewportSize.ssr.test.tsx b/packages/@react-aria/utils/test/useViewportSize.ssr.test.tsx index b5c1b1da64c..a5dcf31ae6c 100644 --- a/packages/@react-aria/utils/test/useViewportSize.ssr.test.tsx +++ b/packages/@react-aria/utils/test/useViewportSize.ssr.test.tsx @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('useViewportSize SSR', () => { it('should render without errors', async () => { diff --git a/packages/@react-aria/visually-hidden/test/VisuallyHidden.test.tsx b/packages/@react-aria/visually-hidden/test/VisuallyHidden.test.tsx index 3581cac29b9..0c8c026aa5a 100644 --- a/packages/@react-aria/visually-hidden/test/VisuallyHidden.test.tsx +++ b/packages/@react-aria/visually-hidden/test/VisuallyHidden.test.tsx @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {pointerMap, render} from '@react-spectrum/test-utils'; +import {pointerMap, render} from '@react-spectrum/test-utils-internal'; import React from 'react'; import userEvent from '@testing-library/user-event'; import {VisuallyHidden} from '../'; diff --git a/packages/@react-spectrum/accordion/test/Accordion.test.js b/packages/@react-spectrum/accordion/test/Accordion.test.js index 1a155b3482c..1b47440adca 100644 --- a/packages/@react-spectrum/accordion/test/Accordion.test.js +++ b/packages/@react-spectrum/accordion/test/Accordion.test.js @@ -11,7 +11,7 @@ */ import {Accordion, Item} from '../src'; -import {act, pointerMap, render, within} from '@react-spectrum/test-utils'; +import {act, pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import {Provider} from '@react-spectrum/provider'; import React from 'react'; import {theme} from '@react-spectrum/theme-default'; diff --git a/packages/@react-spectrum/actionbar/test/ActionBar.test.js b/packages/@react-spectrum/actionbar/test/ActionBar.test.js index e69ceb26b30..c3b1a4e3293 100644 --- a/packages/@react-spectrum/actionbar/test/ActionBar.test.js +++ b/packages/@react-spectrum/actionbar/test/ActionBar.test.js @@ -12,7 +12,7 @@ jest.mock('@react-aria/live-announcer'); -import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import {announce} from '@react-aria/live-announcer'; import {Example} from '../stories/Example'; import {getFocusableTreeWalker} from '@react-aria/focus'; diff --git a/packages/@react-spectrum/actiongroup/test/ActionGroup.ssr.test.js b/packages/@react-spectrum/actiongroup/test/ActionGroup.ssr.test.js index fbb24fd386f..9eed9f2c154 100644 --- a/packages/@react-spectrum/actiongroup/test/ActionGroup.ssr.test.js +++ b/packages/@react-spectrum/actiongroup/test/ActionGroup.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('ActionGroup SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/actiongroup/test/ActionGroup.test.js b/packages/@react-spectrum/actiongroup/test/ActionGroup.test.js index c3ba8e4c715..6d5c8d5d83d 100644 --- a/packages/@react-spectrum/actiongroup/test/ActionGroup.test.js +++ b/packages/@react-spectrum/actiongroup/test/ActionGroup.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, screen, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, screen, within} from '@react-spectrum/test-utils-internal'; import {ActionGroup} from '../'; import {Button} from '@react-spectrum/button'; import {Dialog, DialogTrigger} from '@react-spectrum/dialog'; diff --git a/packages/@react-spectrum/actiongroup/test/Toolbar.test.tsx b/packages/@react-spectrum/actiongroup/test/Toolbar.test.tsx index 3c4e65726c9..668c9d9467a 100644 --- a/packages/@react-spectrum/actiongroup/test/Toolbar.test.tsx +++ b/packages/@react-spectrum/actiongroup/test/Toolbar.test.tsx @@ -20,7 +20,7 @@ import { Provider, Text } from '@adobe/react-spectrum'; -import {pointerMap} from '@react-spectrum/test-utils'; +import {pointerMap} from '@react-spectrum/test-utils-internal'; import React from 'react'; import {Toolbar} from '../stories/Toolbar.stories'; import userEvent from '@testing-library/user-event'; diff --git a/packages/@react-spectrum/autocomplete/test/SearchAutocomplete.test.js b/packages/@react-spectrum/autocomplete/test/SearchAutocomplete.test.js index 370350952d6..db922ee18e4 100644 --- a/packages/@react-spectrum/autocomplete/test/SearchAutocomplete.test.js +++ b/packages/@react-spectrum/autocomplete/test/SearchAutocomplete.test.js @@ -11,7 +11,7 @@ */ jest.mock('@react-aria/live-announcer'); -import {act, fireEvent, pointerMap, render, screen, simulateDesktop, simulateMobile, waitFor, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, screen, simulateDesktop, simulateMobile, waitFor, within} from '@react-spectrum/test-utils-internal'; import {announce} from '@react-aria/live-announcer'; import {Button} from '@react-spectrum/button'; import Filter from '@spectrum-icons/workflow/Filter'; diff --git a/packages/@react-spectrum/avatar/test/Avatar.test.js b/packages/@react-spectrum/avatar/test/Avatar.test.js index 44a599849b7..f3b0b689d40 100644 --- a/packages/@react-spectrum/avatar/test/Avatar.test.js +++ b/packages/@react-spectrum/avatar/test/Avatar.test.js @@ -1,6 +1,6 @@ import {Avatar} from '../'; import React from 'react'; -import {render, screen} from '@react-spectrum/test-utils'; +import {render, screen} from '@react-spectrum/test-utils-internal'; import * as Utils from '@react-spectrum/utils'; describe('Avatar', () => { diff --git a/packages/@react-spectrum/badge/test/Badge.ssr.test.js b/packages/@react-spectrum/badge/test/Badge.ssr.test.js index 78b038df49c..6fd2d310a01 100644 --- a/packages/@react-spectrum/badge/test/Badge.ssr.test.js +++ b/packages/@react-spectrum/badge/test/Badge.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('Badge SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/badge/test/Badge.test.js b/packages/@react-spectrum/badge/test/Badge.test.js index 07e137b1cc8..35930981543 100644 --- a/packages/@react-spectrum/badge/test/Badge.test.js +++ b/packages/@react-spectrum/badge/test/Badge.test.js @@ -13,7 +13,7 @@ import {Badge} from '../'; import CheckmarkCircle from '@spectrum-icons/workflow/CheckmarkCircle'; import React from 'react'; -import {render} from '@react-spectrum/test-utils'; +import {render} from '@react-spectrum/test-utils-internal'; import {Text} from '@react-spectrum/text'; import {within} from '@testing-library/dom'; diff --git a/packages/@react-spectrum/breadcrumbs/test/BreadcrumbItem.test.js b/packages/@react-spectrum/breadcrumbs/test/BreadcrumbItem.test.js index 440befff958..bd44c1f7c58 100644 --- a/packages/@react-spectrum/breadcrumbs/test/BreadcrumbItem.test.js +++ b/packages/@react-spectrum/breadcrumbs/test/BreadcrumbItem.test.js @@ -11,7 +11,7 @@ */ import {BreadcrumbItem} from '../src/BreadcrumbItem'; -import {pointerMap, render} from '@react-spectrum/test-utils'; +import {pointerMap, render} from '@react-spectrum/test-utils-internal'; import React from 'react'; import userEvent from '@testing-library/user-event'; diff --git a/packages/@react-spectrum/breadcrumbs/test/Breadcrumbs.ssr.test.js b/packages/@react-spectrum/breadcrumbs/test/Breadcrumbs.ssr.test.js index 409e764b3b6..3fa751c0244 100644 --- a/packages/@react-spectrum/breadcrumbs/test/Breadcrumbs.ssr.test.js +++ b/packages/@react-spectrum/breadcrumbs/test/Breadcrumbs.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('Breadcrumbs SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/breadcrumbs/test/Breadcrumbs.test.js b/packages/@react-spectrum/breadcrumbs/test/Breadcrumbs.test.js index e83000f942d..adc46bdbc66 100644 --- a/packages/@react-spectrum/breadcrumbs/test/Breadcrumbs.test.js +++ b/packages/@react-spectrum/breadcrumbs/test/Breadcrumbs.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, pointerMap, render, within} from '@react-spectrum/test-utils'; +import {act, pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import {Breadcrumbs} from '../'; import {Item} from '@react-stately/collections'; import {Provider} from '@react-spectrum/provider'; diff --git a/packages/@react-spectrum/button/package.json b/packages/@react-spectrum/button/package.json index 48f49264847..1c808e89fe2 100644 --- a/packages/@react-spectrum/button/package.json +++ b/packages/@react-spectrum/button/package.json @@ -52,7 +52,7 @@ }, "devDependencies": { "@adobe/spectrum-css-temp": "3.0.0-alpha.1", - "@react-spectrum/test-utils": "3.0.0-alpha.1" + "@react-spectrum/test-utils-internal": "3.0.0-alpha.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", diff --git a/packages/@react-spectrum/button/test/ActionButton.test.js b/packages/@react-spectrum/button/test/ActionButton.test.js index a77ca4faa7b..3fd868e73b8 100644 --- a/packages/@react-spectrum/button/test/ActionButton.test.js +++ b/packages/@react-spectrum/button/test/ActionButton.test.js @@ -11,7 +11,7 @@ */ import {ActionButton} from '../'; -import {pointerMap, render} from '@react-spectrum/test-utils'; +import {pointerMap, render} from '@react-spectrum/test-utils-internal'; import React from 'react'; import userEvent from '@testing-library/user-event'; diff --git a/packages/@react-spectrum/button/test/Button.ssr.test.js b/packages/@react-spectrum/button/test/Button.ssr.test.js index f075059350c..4eeaf48f0b7 100644 --- a/packages/@react-spectrum/button/test/Button.ssr.test.js +++ b/packages/@react-spectrum/button/test/Button.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('Button SSR', function () { it.each` diff --git a/packages/@react-spectrum/button/test/Button.test.js b/packages/@react-spectrum/button/test/Button.test.js index 5fa00649296..37c52958071 100644 --- a/packages/@react-spectrum/button/test/Button.test.js +++ b/packages/@react-spectrum/button/test/Button.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, pointerMap, render} from '@react-spectrum/test-utils'; +import {act, pointerMap, render} from '@react-spectrum/test-utils-internal'; import {ActionButton, Button, ClearButton, LogicButton} from '../'; import {Checkbox, defaultTheme} from '@adobe/react-spectrum'; import {Form} from '@react-spectrum/form'; diff --git a/packages/@react-spectrum/button/test/ClearButton.test.js b/packages/@react-spectrum/button/test/ClearButton.test.js index d6377f88c53..81e8fef2e2a 100644 --- a/packages/@react-spectrum/button/test/ClearButton.test.js +++ b/packages/@react-spectrum/button/test/ClearButton.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, pointerMap, render} from '@react-spectrum/test-utils'; +import {act, pointerMap, render} from '@react-spectrum/test-utils-internal'; import {ClearButton} from '../'; import React from 'react'; import userEvent from '@testing-library/user-event'; diff --git a/packages/@react-spectrum/button/test/ToggleButton.test.js b/packages/@react-spectrum/button/test/ToggleButton.test.js index 7cc78782415..985fad1991e 100644 --- a/packages/@react-spectrum/button/test/ToggleButton.test.js +++ b/packages/@react-spectrum/button/test/ToggleButton.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {pointerMap, render} from '@react-spectrum/test-utils'; +import {pointerMap, render} from '@react-spectrum/test-utils-internal'; import React from 'react'; import {ToggleButton} from '../'; import userEvent from '@testing-library/user-event'; diff --git a/packages/@react-spectrum/buttongroup/test/ButtonGroup.ssr.test.js b/packages/@react-spectrum/buttongroup/test/ButtonGroup.ssr.test.js index d4cdba81721..b90c7715932 100644 --- a/packages/@react-spectrum/buttongroup/test/ButtonGroup.ssr.test.js +++ b/packages/@react-spectrum/buttongroup/test/ButtonGroup.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('ButtonGroup SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/buttongroup/test/ButtonGroup.test.js b/packages/@react-spectrum/buttongroup/test/ButtonGroup.test.js index e5f42dfaa8a..43131e96193 100644 --- a/packages/@react-spectrum/buttongroup/test/ButtonGroup.test.js +++ b/packages/@react-spectrum/buttongroup/test/ButtonGroup.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, pointerMap, render, within} from '@react-spectrum/test-utils'; +import {act, pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import {Button} from '@react-spectrum/button'; import {ButtonGroup} from '../'; import {Provider} from '@react-spectrum/provider'; diff --git a/packages/@react-spectrum/calendar/package.json b/packages/@react-spectrum/calendar/package.json index a4965c715b6..5ff6fdc08dc 100644 --- a/packages/@react-spectrum/calendar/package.json +++ b/packages/@react-spectrum/calendar/package.json @@ -55,7 +55,7 @@ }, "devDependencies": { "@adobe/spectrum-css-temp": "3.0.0-alpha.1", - "@react-spectrum/test-utils": "3.0.0-alpha.1" + "@react-spectrum/test-utils-internal": "3.0.0-alpha.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", diff --git a/packages/@react-spectrum/calendar/test/Calendar.ssr.test.js b/packages/@react-spectrum/calendar/test/Calendar.ssr.test.js index a6988fbbbfd..91db5a8dbb9 100644 --- a/packages/@react-spectrum/calendar/test/Calendar.ssr.test.js +++ b/packages/@react-spectrum/calendar/test/Calendar.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('Calendar SSR', function () { it('should render a Calendar without errors', async function () { diff --git a/packages/@react-spectrum/calendar/test/Calendar.test.js b/packages/@react-spectrum/calendar/test/Calendar.test.js index b1c6dda838f..cc6fb087623 100644 --- a/packages/@react-spectrum/calendar/test/Calendar.test.js +++ b/packages/@react-spectrum/calendar/test/Calendar.test.js @@ -16,7 +16,7 @@ jest.mock('@react-aria/live-announcer'); import {announce} from '@react-aria/live-announcer'; import {Calendar} from '../'; import {CalendarDate, isWeekend} from '@internationalized/date'; -import {pointerMap, render} from '@react-spectrum/test-utils'; +import {pointerMap, render} from '@react-spectrum/test-utils-internal'; import React from 'react'; import {useLocale} from '@react-aria/i18n'; import userEvent from '@testing-library/user-event'; diff --git a/packages/@react-spectrum/calendar/test/CalendarBase.test.js b/packages/@react-spectrum/calendar/test/CalendarBase.test.js index 23923372e0b..c9420ab497b 100644 --- a/packages/@react-spectrum/calendar/test/CalendarBase.test.js +++ b/packages/@react-spectrum/calendar/test/CalendarBase.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import {Calendar, RangeCalendar} from '../'; import {CalendarDate, GregorianCalendar, today} from '@internationalized/date'; import {Provider} from '@react-spectrum/provider'; diff --git a/packages/@react-spectrum/calendar/test/RangeCalendar.test.js b/packages/@react-spectrum/calendar/test/RangeCalendar.test.js index 9332c1a2cf4..7f69e52c319 100644 --- a/packages/@react-spectrum/calendar/test/RangeCalendar.test.js +++ b/packages/@react-spectrum/calendar/test/RangeCalendar.test.js @@ -11,7 +11,7 @@ */ jest.mock('@react-aria/live-announcer'); -import {act, fireEvent, installPointerEvent, pointerMap, render} from '@react-spectrum/test-utils'; +import {act, fireEvent, installPointerEvent, pointerMap, render} from '@react-spectrum/test-utils-internal'; import {announce} from '@react-aria/live-announcer'; import {CalendarDate, isWeekend} from '@internationalized/date'; import {RangeCalendar} from '../'; diff --git a/packages/@react-spectrum/card/test/Card.test.js b/packages/@react-spectrum/card/test/Card.test.js index a99e09d4eea..66d55002a2f 100644 --- a/packages/@react-spectrum/card/test/Card.test.js +++ b/packages/@react-spectrum/card/test/Card.test.js @@ -13,7 +13,7 @@ import {Card} from '../src'; import {composeStories} from '@storybook/testing-react'; import * as defaultStories from '../chromatic/Card.chromatic'; -import {pointerMap, render} from '@react-spectrum/test-utils'; +import {pointerMap, render} from '@react-spectrum/test-utils-internal'; import * as quietStories from '../chromatic/QuietCard.chromatic'; import React from 'react'; import userEvent from '@testing-library/user-event'; diff --git a/packages/@react-spectrum/card/test/CardView.test.js b/packages/@react-spectrum/card/test/CardView.test.js index b7fcfea1382..b5751d9fd86 100644 --- a/packages/@react-spectrum/card/test/CardView.test.js +++ b/packages/@react-spectrum/card/test/CardView.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import {Card, CardView, GalleryLayout, GridLayout, WaterfallLayout} from '../'; import {composeStories} from '@storybook/testing-react'; import {Content} from '@react-spectrum/view'; diff --git a/packages/@react-spectrum/checkbox/test/Checkbox.ssr.test.js b/packages/@react-spectrum/checkbox/test/Checkbox.ssr.test.js index 6439ca9b8a0..aa2a5ae4b5c 100644 --- a/packages/@react-spectrum/checkbox/test/Checkbox.ssr.test.js +++ b/packages/@react-spectrum/checkbox/test/Checkbox.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('Checkbox SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/checkbox/test/Checkbox.test.js b/packages/@react-spectrum/checkbox/test/Checkbox.test.js index 40bbf5d328a..566a61ab088 100644 --- a/packages/@react-spectrum/checkbox/test/Checkbox.test.js +++ b/packages/@react-spectrum/checkbox/test/Checkbox.test.js @@ -14,7 +14,7 @@ import {act} from 'react-dom/test-utils'; import {Button} from '@react-spectrum/button'; import {Checkbox} from '../'; import {Form} from '@react-spectrum/form'; -import {pointerMap, render} from '@react-spectrum/test-utils'; +import {pointerMap, render} from '@react-spectrum/test-utils-internal'; import {Provider} from '@react-spectrum/provider'; import React from 'react'; import {theme} from '@react-spectrum/theme-default'; diff --git a/packages/@react-spectrum/checkbox/test/CheckboxGroup.test.js b/packages/@react-spectrum/checkbox/test/CheckboxGroup.test.js index fc6dc469ea6..6c0f4a5eb81 100644 --- a/packages/@react-spectrum/checkbox/test/CheckboxGroup.test.js +++ b/packages/@react-spectrum/checkbox/test/CheckboxGroup.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, pointerMap, render, within} from '@react-spectrum/test-utils'; +import {act, pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import {Button} from '@react-spectrum/button'; import {Checkbox, CheckboxGroup} from '../'; import {Form} from '@react-spectrum/form'; diff --git a/packages/@react-spectrum/color/test/ColorArea.test.tsx b/packages/@react-spectrum/color/test/ColorArea.test.tsx index 09204099ae9..5de7d5113bc 100644 --- a/packages/@react-spectrum/color/test/ColorArea.test.tsx +++ b/packages/@react-spectrum/color/test/ColorArea.test.tsx @@ -13,7 +13,7 @@ import {ColorArea} from '../'; import {composeStories} from '@storybook/testing-react'; import {defaultTheme} from '@adobe/react-spectrum'; -import {fireEvent, installMouseEvent, installPointerEvent, pointerMap, render} from '@react-spectrum/test-utils'; +import {fireEvent, installMouseEvent, installPointerEvent, pointerMap, render} from '@react-spectrum/test-utils-internal'; import {parseColor} from '@react-stately/color'; import {Provider} from '@react-spectrum/provider'; import React from 'react'; diff --git a/packages/@react-spectrum/color/test/ColorField.test.js b/packages/@react-spectrum/color/test/ColorField.test.js index 23522b46e5c..1bde4bfb853 100644 --- a/packages/@react-spectrum/color/test/ColorField.test.js +++ b/packages/@react-spectrum/color/test/ColorField.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render} from '@react-spectrum/test-utils-internal'; import {Button} from '@react-spectrum/button'; import {chain} from '@react-aria/utils'; import {ColorField} from '../'; diff --git a/packages/@react-spectrum/color/test/ColorSlider.test.tsx b/packages/@react-spectrum/color/test/ColorSlider.test.tsx index aee60e67852..a6ad8767954 100644 --- a/packages/@react-spectrum/color/test/ColorSlider.test.tsx +++ b/packages/@react-spectrum/color/test/ColorSlider.test.tsx @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, installMouseEvent, installPointerEvent, pointerMap, render} from '@react-spectrum/test-utils'; +import {act, fireEvent, installMouseEvent, installPointerEvent, pointerMap, render} from '@react-spectrum/test-utils-internal'; import {ColorSlider} from '../'; import {parseColor} from '@react-stately/color'; import React from 'react'; diff --git a/packages/@react-spectrum/color/test/ColorWheel.test.tsx b/packages/@react-spectrum/color/test/ColorWheel.test.tsx index 529a7afb79e..ec802d73b33 100644 --- a/packages/@react-spectrum/color/test/ColorWheel.test.tsx +++ b/packages/@react-spectrum/color/test/ColorWheel.test.tsx @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, installMouseEvent, installPointerEvent, pointerMap, render} from '@react-spectrum/test-utils'; +import {act, fireEvent, installMouseEvent, installPointerEvent, pointerMap, render} from '@react-spectrum/test-utils-internal'; import {ColorWheel} from '../'; import {ControlledHSL} from '../stories/ColorWheel.stories'; import {parseColor} from '@react-stately/color'; diff --git a/packages/@react-spectrum/combobox/test/ComboBox.test.js b/packages/@react-spectrum/combobox/test/ComboBox.test.js index 472dce0e30c..ddbf115ccfa 100644 --- a/packages/@react-spectrum/combobox/test/ComboBox.test.js +++ b/packages/@react-spectrum/combobox/test/ComboBox.test.js @@ -11,7 +11,7 @@ */ jest.mock('@react-aria/live-announcer'); -import {act, fireEvent, pointerMap, render, screen, simulateDesktop, simulateMobile, waitFor, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, screen, simulateDesktop, simulateMobile, waitFor, within} from '@react-spectrum/test-utils-internal'; import {announce} from '@react-aria/live-announcer'; import {Button} from '@react-spectrum/button'; import {chain} from '@react-aria/utils'; diff --git a/packages/@react-spectrum/contextualhelp/test/ContextualHelp.test.js b/packages/@react-spectrum/contextualhelp/test/ContextualHelp.test.js index 91e71221d10..659e8f60e04 100644 --- a/packages/@react-spectrum/contextualhelp/test/ContextualHelp.test.js +++ b/packages/@react-spectrum/contextualhelp/test/ContextualHelp.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, pointerMap, render, simulateDesktop} from '@react-spectrum/test-utils'; +import {act, pointerMap, render, simulateDesktop} from '@react-spectrum/test-utils-internal'; import {Content, Footer, Header} from '@react-spectrum/view'; import {ContextualHelp} from '../'; import {Link} from '@react-spectrum/link'; diff --git a/packages/@react-spectrum/datepicker/package.json b/packages/@react-spectrum/datepicker/package.json index 78aaeb43cae..7bcd84ee828 100644 --- a/packages/@react-spectrum/datepicker/package.json +++ b/packages/@react-spectrum/datepicker/package.json @@ -59,7 +59,7 @@ }, "devDependencies": { "@adobe/spectrum-css-temp": "3.0.0-alpha.1", - "@react-spectrum/test-utils": "3.0.0-alpha.1" + "@react-spectrum/test-utils-internal": "3.0.0-alpha.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", diff --git a/packages/@react-spectrum/datepicker/test/DateField.test.js b/packages/@react-spectrum/datepicker/test/DateField.test.js index 128dd27dda3..b5944b9f322 100644 --- a/packages/@react-spectrum/datepicker/test/DateField.test.js +++ b/packages/@react-spectrum/datepicker/test/DateField.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, pointerMap, render as render_, within} from '@react-spectrum/test-utils'; +import {act, pointerMap, render as render_, within} from '@react-spectrum/test-utils-internal'; import {Button} from '@react-spectrum/button'; import {CalendarDate, CalendarDateTime, ZonedDateTime} from '@internationalized/date'; import {DateField} from '../'; diff --git a/packages/@react-spectrum/datepicker/test/DatePicker.ssr.test.js b/packages/@react-spectrum/datepicker/test/DatePicker.ssr.test.js index 568911b8fb5..624c4320029 100644 --- a/packages/@react-spectrum/datepicker/test/DatePicker.ssr.test.js +++ b/packages/@react-spectrum/datepicker/test/DatePicker.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('DatePicker SSR', function () { it('should render a DatePicker without errors', async function () { diff --git a/packages/@react-spectrum/datepicker/test/DatePicker.test.js b/packages/@react-spectrum/datepicker/test/DatePicker.test.js index db389b228d3..11ab11362db 100644 --- a/packages/@react-spectrum/datepicker/test/DatePicker.test.js +++ b/packages/@react-spectrum/datepicker/test/DatePicker.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render as render_, waitFor, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render as render_, waitFor, within} from '@react-spectrum/test-utils-internal'; import {Button} from '@react-spectrum/button'; import {CalendarDate, CalendarDateTime, EthiopicCalendar, getLocalTimeZone, JapaneseCalendar, toCalendarDateTime, today} from '@internationalized/date'; import {DatePicker} from '../'; diff --git a/packages/@react-spectrum/datepicker/test/DatePickerBase.test.js b/packages/@react-spectrum/datepicker/test/DatePickerBase.test.js index a4541d2586a..7d4b4301d26 100644 --- a/packages/@react-spectrum/datepicker/test/DatePickerBase.test.js +++ b/packages/@react-spectrum/datepicker/test/DatePickerBase.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, installPointerEvent, pointerMap, render as render_, simulateDesktop, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, installPointerEvent, pointerMap, render as render_, simulateDesktop, within} from '@react-spectrum/test-utils-internal'; import {CalendarDate, parseZonedDateTime} from '@internationalized/date'; import {DatePicker, DateRangePicker} from '../'; import {Provider} from '@react-spectrum/provider'; diff --git a/packages/@react-spectrum/datepicker/test/DateRangePicker.test.js b/packages/@react-spectrum/datepicker/test/DateRangePicker.test.js index 5476004a9c9..ec12dd8479a 100644 --- a/packages/@react-spectrum/datepicker/test/DateRangePicker.test.js +++ b/packages/@react-spectrum/datepicker/test/DateRangePicker.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, getAllByRole as getAllByRoleInContainer, pointerMap, render as render_, waitFor, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, getAllByRole as getAllByRoleInContainer, pointerMap, render as render_, waitFor, within} from '@react-spectrum/test-utils-internal'; import {Button} from '@react-spectrum/button'; import {CalendarDate, CalendarDateTime, getLocalTimeZone, toCalendarDateTime, today} from '@internationalized/date'; import {DateRangePicker} from '../'; diff --git a/packages/@react-spectrum/datepicker/test/TimeField.test.js b/packages/@react-spectrum/datepicker/test/TimeField.test.js index 8188fd0eac5..b1b0570bf1d 100644 --- a/packages/@react-spectrum/datepicker/test/TimeField.test.js +++ b/packages/@react-spectrum/datepicker/test/TimeField.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render as render_, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render as render_, within} from '@react-spectrum/test-utils-internal'; import {Button} from '@react-spectrum/button'; import {Form} from '@react-spectrum/form'; import {parseZonedDateTime, Time} from '@internationalized/date'; diff --git a/packages/@react-spectrum/dialog/package.json b/packages/@react-spectrum/dialog/package.json index d2d6edce7b1..d261ff9ebeb 100644 --- a/packages/@react-spectrum/dialog/package.json +++ b/packages/@react-spectrum/dialog/package.json @@ -58,7 +58,7 @@ }, "devDependencies": { "@adobe/spectrum-css-temp": "3.0.0-alpha.1", - "@react-spectrum/test-utils": "3.0.0-alpha.1" + "@react-spectrum/test-utils-internal": "3.0.0-alpha.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", diff --git a/packages/@react-spectrum/dialog/test/AlertDialog.test.js b/packages/@react-spectrum/dialog/test/AlertDialog.test.js index 6f8a47eb725..04033c7eafa 100644 --- a/packages/@react-spectrum/dialog/test/AlertDialog.test.js +++ b/packages/@react-spectrum/dialog/test/AlertDialog.test.js @@ -11,7 +11,7 @@ */ import {AlertDialog} from '../'; -import {pointerMap, render} from '@react-spectrum/test-utils'; +import {pointerMap, render} from '@react-spectrum/test-utils-internal'; import {Provider} from '@react-spectrum/provider'; import React from 'react'; import {theme} from '@react-spectrum/theme-default'; diff --git a/packages/@react-spectrum/dialog/test/Dialog.ssr.test.js b/packages/@react-spectrum/dialog/test/Dialog.ssr.test.js index 85bc264a2c4..b8a0a884842 100644 --- a/packages/@react-spectrum/dialog/test/Dialog.ssr.test.js +++ b/packages/@react-spectrum/dialog/test/Dialog.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('Dialog SSR', function () { it('Dialog should render without errors', async function () { diff --git a/packages/@react-spectrum/dialog/test/Dialog.test.js b/packages/@react-spectrum/dialog/test/Dialog.test.js index 9f51237223c..f225f1fb16b 100644 --- a/packages/@react-spectrum/dialog/test/Dialog.test.js +++ b/packages/@react-spectrum/dialog/test/Dialog.test.js @@ -16,7 +16,7 @@ import {Header} from '@react-spectrum/view'; import {Heading} from '@react-spectrum/text'; import {ModalProvider} from '@react-aria/overlays'; import React from 'react'; -import {render} from '@react-spectrum/test-utils'; +import {render} from '@react-spectrum/test-utils-internal'; describe('Dialog', function () { it('does not auto focus anything inside', function () { diff --git a/packages/@react-spectrum/dialog/test/DialogContainer.test.js b/packages/@react-spectrum/dialog/test/DialogContainer.test.js index c43dd253e39..3896e8e5937 100644 --- a/packages/@react-spectrum/dialog/test/DialogContainer.test.js +++ b/packages/@react-spectrum/dialog/test/DialogContainer.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import {DialogContainerExample, MenuExample, NestedDialogContainerExample} from '../stories/DialogContainerExamples'; import {Provider} from '@react-spectrum/provider'; import React from 'react'; diff --git a/packages/@react-spectrum/dialog/test/DialogTrigger.test.js b/packages/@react-spectrum/dialog/test/DialogTrigger.test.js index 3cdf0cc1b27..7fd6b88a504 100644 --- a/packages/@react-spectrum/dialog/test/DialogTrigger.test.js +++ b/packages/@react-spectrum/dialog/test/DialogTrigger.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, simulateDesktop, simulateMobile, waitFor, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, simulateDesktop, simulateMobile, waitFor, within} from '@react-spectrum/test-utils-internal'; import {ActionButton, Button} from '@react-spectrum/button'; import {ButtonGroup} from '@react-spectrum/buttongroup'; import {Content} from '@react-spectrum/view'; diff --git a/packages/@react-spectrum/divider/test/Divider.ssr.test.js b/packages/@react-spectrum/divider/test/Divider.ssr.test.js index a9f803d406e..2567e6bc993 100644 --- a/packages/@react-spectrum/divider/test/Divider.ssr.test.js +++ b/packages/@react-spectrum/divider/test/Divider.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('Divider SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/divider/test/Divider.test.js b/packages/@react-spectrum/divider/test/Divider.test.js index 5b68f1ed8d8..6aa099312a9 100644 --- a/packages/@react-spectrum/divider/test/Divider.test.js +++ b/packages/@react-spectrum/divider/test/Divider.test.js @@ -12,7 +12,7 @@ import {Divider} from '../'; import React from 'react'; -import {render} from '@react-spectrum/test-utils'; +import {render} from '@react-spectrum/test-utils-internal'; describe('Divider', function () { it.each` diff --git a/packages/@react-spectrum/dropzone/package.json b/packages/@react-spectrum/dropzone/package.json index 4b42a936f8c..6cce6d09b3b 100644 --- a/packages/@react-spectrum/dropzone/package.json +++ b/packages/@react-spectrum/dropzone/package.json @@ -45,7 +45,7 @@ }, "devDependencies": { "@adobe/spectrum-css-temp": "3.0.0-alpha.1", - "@react-spectrum/test-utils": "3.0.0-alpha.1" + "@react-spectrum/test-utils-internal": "3.0.0-alpha.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", diff --git a/packages/@react-spectrum/dropzone/test/DropZone.test.js b/packages/@react-spectrum/dropzone/test/DropZone.test.js index 7ef697ce77e..b4343e0dc6c 100644 --- a/packages/@react-spectrum/dropzone/test/DropZone.test.js +++ b/packages/@react-spectrum/dropzone/test/DropZone.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, render} from '@react-spectrum/test-utils'; +import {act, fireEvent, render} from '@react-spectrum/test-utils-internal'; import {Button} from '@react-spectrum/button'; import {Content} from '@react-spectrum/view'; import {DataTransfer, DataTransferItem, DragEvent} from '@react-aria/dnd/test/mocks'; diff --git a/packages/@react-spectrum/form/test/Form.ssr.test.js b/packages/@react-spectrum/form/test/Form.ssr.test.js index be9cf5a9467..aa7c8b0faf3 100644 --- a/packages/@react-spectrum/form/test/Form.ssr.test.js +++ b/packages/@react-spectrum/form/test/Form.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('Form SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/form/test/Form.test.js b/packages/@react-spectrum/form/test/Form.test.js index 1c52e2c311e..15ba29be69d 100644 --- a/packages/@react-spectrum/form/test/Form.test.js +++ b/packages/@react-spectrum/form/test/Form.test.js @@ -16,7 +16,7 @@ import {Content, Header} from '@react-spectrum/view'; import {ContextualHelp} from '@react-spectrum/contextualhelp'; import {Form} from '../'; import {Item, Picker} from '@react-spectrum/picker'; -import {pointerMap, render, simulateMobile} from '@react-spectrum/test-utils'; +import {pointerMap, render, simulateMobile} from '@react-spectrum/test-utils-internal'; import {Provider} from '@react-spectrum/provider'; import React from 'react'; import {TextField} from '@react-spectrum/textfield'; diff --git a/packages/@react-spectrum/icon/test/Icon.test.js b/packages/@react-spectrum/icon/test/Icon.test.js index 9a891c2dbd6..93f6d5d1f58 100644 --- a/packages/@react-spectrum/icon/test/Icon.test.js +++ b/packages/@react-spectrum/icon/test/Icon.test.js @@ -12,7 +12,7 @@ import {Icon} from '../'; import React from 'react'; -import {render} from '@react-spectrum/test-utils'; +import {render} from '@react-spectrum/test-utils-internal'; let FakeIcon = (props) => ; diff --git a/packages/@react-spectrum/icon/test/Illustration.test.js b/packages/@react-spectrum/icon/test/Illustration.test.js index e1b6aa2de66..85ec1115203 100644 --- a/packages/@react-spectrum/icon/test/Illustration.test.js +++ b/packages/@react-spectrum/icon/test/Illustration.test.js @@ -12,7 +12,7 @@ import {Illustration} from '../'; import React from 'react'; -import {render} from '@react-spectrum/test-utils'; +import {render} from '@react-spectrum/test-utils-internal'; let CustomIllustration = (props) => ; @@ -27,7 +27,7 @@ describe('Illustration', function () { expect(illustration).toHaveAttribute('focusable', 'false'); expect(illustration).toHaveAttribute('aria-label', 'custom illustration'); }); - + it.each` Name | Component ${'Illustration'} | ${Illustration} diff --git a/packages/@react-spectrum/icon/test/UIIcon.test.js b/packages/@react-spectrum/icon/test/UIIcon.test.js index 44b01806486..c093640f8ce 100644 --- a/packages/@react-spectrum/icon/test/UIIcon.test.js +++ b/packages/@react-spectrum/icon/test/UIIcon.test.js @@ -11,7 +11,7 @@ */ import React from 'react'; -import {render} from '@react-spectrum/test-utils'; +import {render} from '@react-spectrum/test-utils-internal'; import {UIIcon} from '../'; let FakeIcon = (props) => ; diff --git a/packages/@react-spectrum/illustratedmessage/test/IllustratedMessage.ssr.test.js b/packages/@react-spectrum/illustratedmessage/test/IllustratedMessage.ssr.test.js index dd33fbebfeb..735d1432811 100644 --- a/packages/@react-spectrum/illustratedmessage/test/IllustratedMessage.ssr.test.js +++ b/packages/@react-spectrum/illustratedmessage/test/IllustratedMessage.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('IllustratedMessage SSR', function () { diff --git a/packages/@react-spectrum/illustratedmessage/test/IllustratedMessage.test.js b/packages/@react-spectrum/illustratedmessage/test/IllustratedMessage.test.js index cc894afb465..2794d0aa3f0 100644 --- a/packages/@react-spectrum/illustratedmessage/test/IllustratedMessage.test.js +++ b/packages/@react-spectrum/illustratedmessage/test/IllustratedMessage.test.js @@ -14,7 +14,7 @@ import {Content} from '@react-spectrum/view'; import {Heading} from '@react-spectrum/text'; import {IllustratedMessage} from '../'; import React from 'react'; -import {render} from '@react-spectrum/test-utils'; +import {render} from '@react-spectrum/test-utils-internal'; let dataTestId = 'IMsvg1'; diff --git a/packages/@react-spectrum/inlinealert/test/InlineAlert.test.js b/packages/@react-spectrum/inlinealert/test/InlineAlert.test.js index b121ec3eb71..0bfdff04dab 100644 --- a/packages/@react-spectrum/inlinealert/test/InlineAlert.test.js +++ b/packages/@react-spectrum/inlinealert/test/InlineAlert.test.js @@ -13,7 +13,7 @@ import {Content, Header} from '@react-spectrum/view'; import {InlineAlert} from '../'; import React from 'react'; -import {render} from '@react-spectrum/test-utils'; +import {render} from '@react-spectrum/test-utils-internal'; describe('InlineAlert', function () { it('has alert role', function () { diff --git a/packages/@react-spectrum/label/test/Field.test.js b/packages/@react-spectrum/label/test/Field.test.js index 49ceb521540..b5d5a7ebef0 100644 --- a/packages/@react-spectrum/label/test/Field.test.js +++ b/packages/@react-spectrum/label/test/Field.test.js @@ -12,7 +12,7 @@ import {Content, ContextualHelp, Heading} from '@adobe/react-spectrum'; import {Field} from '../'; -import {pointerMap, render} from '@react-spectrum/test-utils'; +import {pointerMap, render} from '@react-spectrum/test-utils-internal'; import React from 'react'; import {useField} from '@react-aria/label'; import userEvent from '@testing-library/user-event'; diff --git a/packages/@react-spectrum/labeledvalue/test/LabeledValue.test.js b/packages/@react-spectrum/labeledvalue/test/LabeledValue.test.js index 46a174944a5..d12c9a7d7e9 100644 --- a/packages/@react-spectrum/labeledvalue/test/LabeledValue.test.js +++ b/packages/@react-spectrum/labeledvalue/test/LabeledValue.test.js @@ -13,7 +13,7 @@ import {CalendarDate, CalendarDateTime, Time, ZonedDateTime} from '@internationalized/date'; import {LabeledValue} from '../src'; import React from 'react'; -import {render, within} from '@react-spectrum/test-utils'; +import {render, within} from '@react-spectrum/test-utils-internal'; describe('LabeledValue', function () { it('renders a label', function () { diff --git a/packages/@react-spectrum/layout/test/Flex.ssr.test.js b/packages/@react-spectrum/layout/test/Flex.ssr.test.js index dfa02f4f36b..bf3428c1392 100644 --- a/packages/@react-spectrum/layout/test/Flex.ssr.test.js +++ b/packages/@react-spectrum/layout/test/Flex.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('Flex SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/layout/test/Grid.ssr.test.js b/packages/@react-spectrum/layout/test/Grid.ssr.test.js index 3c906af00d5..a75a99b8ddd 100644 --- a/packages/@react-spectrum/layout/test/Grid.ssr.test.js +++ b/packages/@react-spectrum/layout/test/Grid.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('Grid SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/link/test/Link.ssr.test.js b/packages/@react-spectrum/link/test/Link.ssr.test.js index 12103236247..2940f23d5d9 100644 --- a/packages/@react-spectrum/link/test/Link.ssr.test.js +++ b/packages/@react-spectrum/link/test/Link.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('Link SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/link/test/Link.test.js b/packages/@react-spectrum/link/test/Link.test.js index 8dd9e58b8ae..be5a269d2be 100644 --- a/packages/@react-spectrum/link/test/Link.test.js +++ b/packages/@react-spectrum/link/test/Link.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, pointerMap, render} from '@react-spectrum/test-utils'; +import {act, pointerMap, render} from '@react-spectrum/test-utils-internal'; import {Link} from '../'; import {Provider} from '@react-spectrum/provider'; import React from 'react'; diff --git a/packages/@react-spectrum/list/test/ListView.ssr.test.js b/packages/@react-spectrum/list/test/ListView.ssr.test.js index d8717e820fb..aae2eb071cb 100644 --- a/packages/@react-spectrum/list/test/ListView.ssr.test.js +++ b/packages/@react-spectrum/list/test/ListView.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('ListView SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/list/test/ListView.test.js b/packages/@react-spectrum/list/test/ListView.test.js index 56be56d998b..4346b5b00ef 100644 --- a/packages/@react-spectrum/list/test/ListView.test.js +++ b/packages/@react-spectrum/list/test/ListView.test.js @@ -12,7 +12,7 @@ jest.mock('@react-aria/live-announcer'); -import {act, fireEvent, installPointerEvent, pointerMap, render as renderComponent, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, installPointerEvent, pointerMap, render as renderComponent, within} from '@react-spectrum/test-utils-internal'; import {ActionButton} from '@react-spectrum/button'; import {announce} from '@react-aria/live-announcer'; import {FocusExample} from '../stories/ListViewActions.stories'; diff --git a/packages/@react-spectrum/list/test/ListViewDnd.test.js b/packages/@react-spectrum/list/test/ListViewDnd.test.js index 70439a9872a..22db85940dc 100644 --- a/packages/@react-spectrum/list/test/ListViewDnd.test.js +++ b/packages/@react-spectrum/list/test/ListViewDnd.test.js @@ -19,7 +19,7 @@ import { render as renderComponent, waitFor, within -} from '@react-spectrum/test-utils'; +} from '@react-spectrum/test-utils-internal'; import {CUSTOM_DRAG_TYPE} from '@react-aria/dnd/src/constants'; import {DataTransfer, DataTransferItem, DragEvent, FileSystemDirectoryEntry, FileSystemFileEntry} from '@react-aria/dnd/test/mocks'; import {DIRECTORY_DRAG_TYPE} from '@react-aria/dnd'; diff --git a/packages/@react-spectrum/listbox/test/ListBox.ssr.test.js b/packages/@react-spectrum/listbox/test/ListBox.ssr.test.js index a1288ab2132..e0824a0b1a0 100644 --- a/packages/@react-spectrum/listbox/test/ListBox.ssr.test.js +++ b/packages/@react-spectrum/listbox/test/ListBox.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('ListBox SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/listbox/test/ListBox.test.js b/packages/@react-spectrum/listbox/test/ListBox.test.js index 036b0bbb145..8723e59d7a0 100644 --- a/packages/@react-spectrum/listbox/test/ListBox.test.js +++ b/packages/@react-spectrum/listbox/test/ListBox.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import Bell from '@spectrum-icons/workflow/Bell'; import {FocusExample} from '../stories/ListBox.stories'; import {Item, ListBox, Section} from '../'; diff --git a/packages/@react-spectrum/menu/test/ActionMenu.test.js b/packages/@react-spectrum/menu/test/ActionMenu.test.js index b0a81acd236..9a955392f1e 100644 --- a/packages/@react-spectrum/menu/test/ActionMenu.test.js +++ b/packages/@react-spectrum/menu/test/ActionMenu.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import {ActionMenu, Item} from '../'; import {Provider} from '@react-spectrum/provider'; import React from 'react'; diff --git a/packages/@react-spectrum/menu/test/Menu.ssr.test.js b/packages/@react-spectrum/menu/test/Menu.ssr.test.js index 659ff0e40f1..596bf8cb866 100644 --- a/packages/@react-spectrum/menu/test/Menu.ssr.test.js +++ b/packages/@react-spectrum/menu/test/Menu.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('Menu SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/menu/test/Menu.test.js b/packages/@react-spectrum/menu/test/Menu.test.js index a177e8224c4..edeb1dc6dde 100644 --- a/packages/@react-spectrum/menu/test/Menu.test.js +++ b/packages/@react-spectrum/menu/test/Menu.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import Bell from '@spectrum-icons/workflow/Bell'; import {Dialog, DialogTrigger} from '@react-spectrum/dialog'; import {Item, Menu, Section} from '../'; diff --git a/packages/@react-spectrum/menu/test/MenuTrigger.ssr.test.js b/packages/@react-spectrum/menu/test/MenuTrigger.ssr.test.js index 8dad227dc2f..6e407d1aa17 100644 --- a/packages/@react-spectrum/menu/test/MenuTrigger.ssr.test.js +++ b/packages/@react-spectrum/menu/test/MenuTrigger.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('MenuTrigger SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/menu/test/MenuTrigger.test.js b/packages/@react-spectrum/menu/test/MenuTrigger.test.js index 168f5b254a1..7fda693e871 100644 --- a/packages/@react-spectrum/menu/test/MenuTrigger.test.js +++ b/packages/@react-spectrum/menu/test/MenuTrigger.test.js @@ -21,7 +21,7 @@ import { pointerMap, simulateDesktop, triggerLongPress -} from '@react-spectrum/test-utils'; +} from '@react-spectrum/test-utils-internal'; import {Dialog} from '@react-spectrum/dialog'; import {Heading, Text} from '@react-spectrum/text'; import {Link} from '@react-spectrum/link'; diff --git a/packages/@react-spectrum/meter/test/Meter.ssr.test.js b/packages/@react-spectrum/meter/test/Meter.ssr.test.js index 60c112d1ae2..50da9422766 100644 --- a/packages/@react-spectrum/meter/test/Meter.ssr.test.js +++ b/packages/@react-spectrum/meter/test/Meter.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('Meter SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/meter/test/Meter.test.js b/packages/@react-spectrum/meter/test/Meter.test.js index 00662d6942c..fb27c246cf0 100644 --- a/packages/@react-spectrum/meter/test/Meter.test.js +++ b/packages/@react-spectrum/meter/test/Meter.test.js @@ -12,7 +12,7 @@ import {Meter} from '../'; import React from 'react'; -import {render} from '@react-spectrum/test-utils'; +import {render} from '@react-spectrum/test-utils-internal'; describe('Meter', function () { it('handles defaults', function () { diff --git a/packages/@react-spectrum/numberfield/package.json b/packages/@react-spectrum/numberfield/package.json index 74f07816356..e6cc6b6e991 100644 --- a/packages/@react-spectrum/numberfield/package.json +++ b/packages/@react-spectrum/numberfield/package.json @@ -56,7 +56,7 @@ }, "devDependencies": { "@adobe/spectrum-css-temp": "3.0.0-alpha.1", - "@react-spectrum/test-utils": "3.0.0-alpha.1" + "@react-spectrum/test-utils-internal": "3.0.0-alpha.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", diff --git a/packages/@react-spectrum/numberfield/test/NumberField.ssr.test.js b/packages/@react-spectrum/numberfield/test/NumberField.ssr.test.js index 8b9798f8a93..2cceba64d56 100644 --- a/packages/@react-spectrum/numberfield/test/NumberField.ssr.test.js +++ b/packages/@react-spectrum/numberfield/test/NumberField.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('NumberField SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/numberfield/test/NumberField.test.js b/packages/@react-spectrum/numberfield/test/NumberField.test.js index 68b3afbcbcf..957048d7f9a 100644 --- a/packages/@react-spectrum/numberfield/test/NumberField.test.js +++ b/packages/@react-spectrum/numberfield/test/NumberField.test.js @@ -11,7 +11,7 @@ */ jest.mock('@react-aria/live-announcer'); -import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import {announce} from '@react-aria/live-announcer'; import {Button} from '@react-spectrum/button'; import {chain} from '@react-aria/utils'; diff --git a/packages/@react-spectrum/overlays/test/Modal.test.js b/packages/@react-spectrum/overlays/test/Modal.test.js index 6603ccf6857..fabd82907b6 100644 --- a/packages/@react-spectrum/overlays/test/Modal.test.js +++ b/packages/@react-spectrum/overlays/test/Modal.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {fireEvent, render, waitFor} from '@react-spectrum/test-utils'; +import {fireEvent, render, waitFor} from '@react-spectrum/test-utils-internal'; import {Modal} from '../'; import {Provider} from '@react-spectrum/provider'; import React from 'react'; diff --git a/packages/@react-spectrum/overlays/test/Overlay.test.js b/packages/@react-spectrum/overlays/test/Overlay.test.js index a632f811cdd..a7d1f77479c 100644 --- a/packages/@react-spectrum/overlays/test/Overlay.test.js +++ b/packages/@react-spectrum/overlays/test/Overlay.test.js @@ -13,7 +13,7 @@ import {Overlay} from '../'; import {Provider} from '@react-spectrum/provider'; import React from 'react'; -import {render} from '@react-spectrum/test-utils'; +import {render} from '@react-spectrum/test-utils-internal'; import {theme} from '@react-spectrum/theme-default'; function _ExampleOverlay(props, ref) { diff --git a/packages/@react-spectrum/overlays/test/Popover.test.js b/packages/@react-spectrum/overlays/test/Popover.test.js index a688f680ea5..595635f8c0a 100644 --- a/packages/@react-spectrum/overlays/test/Popover.test.js +++ b/packages/@react-spectrum/overlays/test/Popover.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, waitFor} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, waitFor} from '@react-spectrum/test-utils-internal'; import {Dialog} from '@react-spectrum/dialog'; import {Popover} from '../'; import {Provider} from '@react-spectrum/provider'; diff --git a/packages/@react-spectrum/overlays/test/Tray.test.js b/packages/@react-spectrum/overlays/test/Tray.test.js index b303c1d3f76..8ebccb2a347 100644 --- a/packages/@react-spectrum/overlays/test/Tray.test.js +++ b/packages/@react-spectrum/overlays/test/Tray.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, render, waitFor} from '@react-spectrum/test-utils'; +import {act, fireEvent, render, waitFor} from '@react-spectrum/test-utils-internal'; import {Dialog} from '@react-spectrum/dialog'; import {Provider} from '@react-spectrum/provider'; import React from 'react'; diff --git a/packages/@react-spectrum/picker/test/Picker.ssr.test.js b/packages/@react-spectrum/picker/test/Picker.ssr.test.js index b02c3003ed2..daec81bde2e 100644 --- a/packages/@react-spectrum/picker/test/Picker.ssr.test.js +++ b/packages/@react-spectrum/picker/test/Picker.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('Picker SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/picker/test/Picker.test.js b/packages/@react-spectrum/picker/test/Picker.test.js index 482b464be1b..5333d15ea31 100644 --- a/packages/@react-spectrum/picker/test/Picker.test.js +++ b/packages/@react-spectrum/picker/test/Picker.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, simulateDesktop, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, simulateDesktop, within} from '@react-spectrum/test-utils-internal'; import AlignCenter from '@spectrum-icons/workflow/AlignCenter'; import AlignLeft from '@spectrum-icons/workflow/AlignLeft'; import AlignRight from '@spectrum-icons/workflow/AlignRight'; diff --git a/packages/@react-spectrum/progress/test/ProgressBar.ssr.test.js b/packages/@react-spectrum/progress/test/ProgressBar.ssr.test.js index d7146f768be..efb6720dbdf 100644 --- a/packages/@react-spectrum/progress/test/ProgressBar.ssr.test.js +++ b/packages/@react-spectrum/progress/test/ProgressBar.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('ProgressBar SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/progress/test/ProgressBar.test.js b/packages/@react-spectrum/progress/test/ProgressBar.test.js index 1c075cc31e1..c99f5045e57 100644 --- a/packages/@react-spectrum/progress/test/ProgressBar.test.js +++ b/packages/@react-spectrum/progress/test/ProgressBar.test.js @@ -12,7 +12,7 @@ import {ProgressBar} from '../'; import React from 'react'; -import {render} from '@react-spectrum/test-utils'; +import {render} from '@react-spectrum/test-utils-internal'; describe('ProgressBar', function () { diff --git a/packages/@react-spectrum/progress/test/ProgressCircle.ssr.test.js b/packages/@react-spectrum/progress/test/ProgressCircle.ssr.test.js index 3f966bb3875..f8e0862e848 100644 --- a/packages/@react-spectrum/progress/test/ProgressCircle.ssr.test.js +++ b/packages/@react-spectrum/progress/test/ProgressCircle.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('ProgressCircle SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/progress/test/ProgressCircle.test.js b/packages/@react-spectrum/progress/test/ProgressCircle.test.js index 595349842c5..44b958f1cd8 100644 --- a/packages/@react-spectrum/progress/test/ProgressCircle.test.js +++ b/packages/@react-spectrum/progress/test/ProgressCircle.test.js @@ -12,7 +12,7 @@ import {ProgressCircle} from '../'; import React from 'react'; -import {render} from '@react-spectrum/test-utils'; +import {render} from '@react-spectrum/test-utils-internal'; describe('ProgressCircle', function () { diff --git a/packages/@react-spectrum/provider/test/Provider.ssr.test.js b/packages/@react-spectrum/provider/test/Provider.ssr.test.js index 3ea3ee18769..3272b47481d 100644 --- a/packages/@react-spectrum/provider/test/Provider.ssr.test.js +++ b/packages/@react-spectrum/provider/test/Provider.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('Provider SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/provider/test/Provider.test.tsx b/packages/@react-spectrum/provider/test/Provider.test.tsx index 0256bcd671f..5788d945cad 100644 --- a/packages/@react-spectrum/provider/test/Provider.test.tsx +++ b/packages/@react-spectrum/provider/test/Provider.test.tsx @@ -13,7 +13,7 @@ // needs to be imported first import MatchMediaMock from 'jest-matchmedia-mock'; // eslint-disable-next-line rsp-rules/sort-imports -import {act, fireEvent, pointerMap, render} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render} from '@react-spectrum/test-utils-internal'; import {ActionButton, Button} from '@react-spectrum/button'; import {Checkbox} from '@react-spectrum/checkbox'; import {Provider} from '../'; diff --git a/packages/@react-spectrum/provider/test/mediaQueries.test.ts b/packages/@react-spectrum/provider/test/mediaQueries.test.ts index 89094eb8f58..38629192b40 100644 --- a/packages/@react-spectrum/provider/test/mediaQueries.test.ts +++ b/packages/@react-spectrum/provider/test/mediaQueries.test.ts @@ -12,7 +12,7 @@ // needs to be imported first import MatchMediaMock from 'jest-matchmedia-mock'; -import {renderHook} from '@react-spectrum/test-utils'; +import {renderHook} from '@react-spectrum/test-utils-internal'; import {useColorScheme} from '../src/mediaQueries'; let theme = { diff --git a/packages/@react-spectrum/radio/test/Radio.ssr.test.js b/packages/@react-spectrum/radio/test/Radio.ssr.test.js index 937f9fad016..3accbd057c5 100644 --- a/packages/@react-spectrum/radio/test/Radio.ssr.test.js +++ b/packages/@react-spectrum/radio/test/Radio.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('Radio SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/radio/test/Radio.test.js b/packages/@react-spectrum/radio/test/Radio.test.js index 186842fe008..29cf6dd5aec 100644 --- a/packages/@react-spectrum/radio/test/Radio.test.js +++ b/packages/@react-spectrum/radio/test/Radio.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, pointerMap, render} from '@react-spectrum/test-utils'; +import {act, pointerMap, render} from '@react-spectrum/test-utils-internal'; import {Button} from '@react-spectrum/button'; import {Form} from '@react-spectrum/form'; import {Provider} from '@react-spectrum/provider'; diff --git a/packages/@react-spectrum/searchfield/package.json b/packages/@react-spectrum/searchfield/package.json index 90d1db4e92e..db60cfb0b8a 100644 --- a/packages/@react-spectrum/searchfield/package.json +++ b/packages/@react-spectrum/searchfield/package.json @@ -49,7 +49,7 @@ }, "devDependencies": { "@adobe/spectrum-css-temp": "3.0.0-alpha.1", - "@react-spectrum/test-utils": "3.0.0-alpha.1" + "@react-spectrum/test-utils-internal": "3.0.0-alpha.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", diff --git a/packages/@react-spectrum/searchfield/test/SearchField.ssr.test.js b/packages/@react-spectrum/searchfield/test/SearchField.ssr.test.js index d73941e251b..ec782410f85 100644 --- a/packages/@react-spectrum/searchfield/test/SearchField.ssr.test.js +++ b/packages/@react-spectrum/searchfield/test/SearchField.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('SearchField SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/searchfield/test/SearchField.test.js b/packages/@react-spectrum/searchfield/test/SearchField.test.js index 4ca4146ff0d..9314b27bd4e 100644 --- a/packages/@react-spectrum/searchfield/test/SearchField.test.js +++ b/packages/@react-spectrum/searchfield/test/SearchField.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import Checkmark from '@spectrum-icons/workflow/Checkmark'; import React from 'react'; import {SearchField} from '../'; diff --git a/packages/@react-spectrum/searchwithin/test/SearchWithin.test.js b/packages/@react-spectrum/searchwithin/test/SearchWithin.test.js index 1eae6baeaac..f6d1516fdab 100644 --- a/packages/@react-spectrum/searchwithin/test/SearchWithin.test.js +++ b/packages/@react-spectrum/searchwithin/test/SearchWithin.test.js @@ -9,7 +9,7 @@ * OF ANY KIND, either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ -import {act, pointerMap, render} from '@react-spectrum/test-utils'; +import {act, pointerMap, render} from '@react-spectrum/test-utils-internal'; import Filter from '@spectrum-icons/workflow/Filter'; import {Item, Picker} from '@react-spectrum/picker'; import {Provider} from '@react-spectrum/provider'; diff --git a/packages/@react-spectrum/slider/test/RangeSlider.test.tsx b/packages/@react-spectrum/slider/test/RangeSlider.test.tsx index a4957e070ba..0df0c401dde 100644 --- a/packages/@react-spectrum/slider/test/RangeSlider.test.tsx +++ b/packages/@react-spectrum/slider/test/RangeSlider.test.tsx @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {fireEvent, pointerMap, render} from '@react-spectrum/test-utils'; +import {fireEvent, pointerMap, render} from '@react-spectrum/test-utils-internal'; import {press, testKeypresses} from './utils'; import {Provider} from '@adobe/react-spectrum'; import {RangeSlider} from '../'; diff --git a/packages/@react-spectrum/slider/test/Slider.test.tsx b/packages/@react-spectrum/slider/test/Slider.test.tsx index 30e528d45c2..66f5a230b6d 100644 --- a/packages/@react-spectrum/slider/test/Slider.test.tsx +++ b/packages/@react-spectrum/slider/test/Slider.test.tsx @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, installMouseEvent, pointerMap, render} from '@react-spectrum/test-utils'; +import {act, fireEvent, installMouseEvent, pointerMap, render} from '@react-spectrum/test-utils-internal'; import {press, testKeypresses} from './utils'; import {Provider} from '@adobe/react-spectrum'; import React, {useCallback, useState} from 'react'; diff --git a/packages/@react-spectrum/slider/test/utils.ts b/packages/@react-spectrum/slider/test/utils.ts index b284e15a286..2734c68af6c 100644 --- a/packages/@react-spectrum/slider/test/utils.ts +++ b/packages/@react-spectrum/slider/test/utils.ts @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent} from '@react-spectrum/test-utils'; +import {act, fireEvent} from '@react-spectrum/test-utils-internal'; function pressKeyOnButton(key, button) { fireEvent.keyDown(button, {key}); diff --git a/packages/@react-spectrum/statuslight/test/StatusLight.ssr.test.js b/packages/@react-spectrum/statuslight/test/StatusLight.ssr.test.js index a0592b7cc96..733ca394e2c 100644 --- a/packages/@react-spectrum/statuslight/test/StatusLight.ssr.test.js +++ b/packages/@react-spectrum/statuslight/test/StatusLight.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('StatusLight SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/statuslight/test/StatusLight.test.js b/packages/@react-spectrum/statuslight/test/StatusLight.test.js index 464683854df..27158afe158 100644 --- a/packages/@react-spectrum/statuslight/test/StatusLight.test.js +++ b/packages/@react-spectrum/statuslight/test/StatusLight.test.js @@ -11,7 +11,7 @@ */ import React from 'react'; -import {render} from '@react-spectrum/test-utils'; +import {render} from '@react-spectrum/test-utils-internal'; import {StatusLight} from '../'; diff --git a/packages/@react-spectrum/steplist/test/StepList.test.tsx b/packages/@react-spectrum/steplist/test/StepList.test.tsx index 106378215a5..e110baa07b9 100644 --- a/packages/@react-spectrum/steplist/test/StepList.test.tsx +++ b/packages/@react-spectrum/steplist/test/StepList.test.tsx @@ -13,7 +13,7 @@ import {act} from '@testing-library/react'; import {DOMRefValue} from '@react-types/shared'; import {Item} from '@react-stately/collections'; -import {pointerMap, render, within} from '@react-spectrum/test-utils'; +import {pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import {Provider} from '@react-spectrum/provider'; import React from 'react'; import {StepList} from '../'; diff --git a/packages/@react-spectrum/switch/test/Switch.ssr.test.js b/packages/@react-spectrum/switch/test/Switch.ssr.test.js index 7741f3f6f04..36e2765d9c0 100644 --- a/packages/@react-spectrum/switch/test/Switch.ssr.test.js +++ b/packages/@react-spectrum/switch/test/Switch.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('Switch SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/switch/test/Switch.test.js b/packages/@react-spectrum/switch/test/Switch.test.js index b1d01b5eddf..ba5b0c05cd8 100644 --- a/packages/@react-spectrum/switch/test/Switch.test.js +++ b/packages/@react-spectrum/switch/test/Switch.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {pointerMap, render} from '@react-spectrum/test-utils'; +import {pointerMap, render} from '@react-spectrum/test-utils-internal'; import React from 'react'; import {Switch} from '../'; import userEvent from '@testing-library/user-event'; diff --git a/packages/@react-spectrum/table/test/Table.ssr.test.js b/packages/@react-spectrum/table/test/Table.ssr.test.js index 48529b61714..58665ea39a1 100644 --- a/packages/@react-spectrum/table/test/Table.ssr.test.js +++ b/packages/@react-spectrum/table/test/Table.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('Table SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/table/test/Table.test.js b/packages/@react-spectrum/table/test/Table.test.js index 5f07aede145..0130d62194c 100644 --- a/packages/@react-spectrum/table/test/Table.test.js +++ b/packages/@react-spectrum/table/test/Table.test.js @@ -11,7 +11,7 @@ */ jest.mock('@react-aria/live-announcer'); -import {act, fireEvent, installPointerEvent, pointerMap, render as renderComponent, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, installPointerEvent, pointerMap, render as renderComponent, within} from '@react-spectrum/test-utils-internal'; import {ActionButton, Button} from '@react-spectrum/button'; import Add from '@spectrum-icons/workflow/Add'; import {announce} from '@react-aria/live-announcer'; diff --git a/packages/@react-spectrum/table/test/TableDnd.test.js b/packages/@react-spectrum/table/test/TableDnd.test.js index 4ae402a3c97..b33c9d92d4c 100644 --- a/packages/@react-spectrum/table/test/TableDnd.test.js +++ b/packages/@react-spectrum/table/test/TableDnd.test.js @@ -18,7 +18,7 @@ import { render as renderComponent, waitFor, within -} from '@react-spectrum/test-utils'; +} from '@react-spectrum/test-utils-internal'; import {Cell, Column, Row, TableBody, TableHeader, TableView} from '../'; import {CUSTOM_DRAG_TYPE} from '@react-aria/dnd/src/constants'; import {DataTransfer, DataTransferItem, DragEvent, FileSystemDirectoryEntry, FileSystemFileEntry} from '@react-aria/dnd/test/mocks'; diff --git a/packages/@react-spectrum/table/test/TableSizing.test.tsx b/packages/@react-spectrum/table/test/TableSizing.test.tsx index 09835524319..abb21d9bebb 100644 --- a/packages/@react-spectrum/table/test/TableSizing.test.tsx +++ b/packages/@react-spectrum/table/test/TableSizing.test.tsx @@ -17,7 +17,7 @@ import Add from '@spectrum-icons/workflow/Add'; import {Cell, Column, Row, TableBody, TableHeader, TableView} from '../'; import {ColumnSize} from '@react-types/table'; import {ControllingResize} from '../stories/ControllingResize'; -import {fireEvent, installPointerEvent, pointerMap, simulateDesktop} from '@react-spectrum/test-utils'; +import {fireEvent, installPointerEvent, pointerMap, simulateDesktop} from '@react-spectrum/test-utils-internal'; import {HidingColumns} from '../stories/HidingColumns'; import {Key} from '@react-types/shared'; import {Provider} from '@react-spectrum/provider'; diff --git a/packages/@react-spectrum/table/test/TreeGridTable.test.tsx b/packages/@react-spectrum/table/test/TreeGridTable.test.tsx index b6903bf4fb3..7888e2bb166 100644 --- a/packages/@react-spectrum/table/test/TreeGridTable.test.tsx +++ b/packages/@react-spectrum/table/test/TreeGridTable.test.tsx @@ -18,7 +18,7 @@ import { pointerMap, render as renderComponent, within -} from '@react-spectrum/test-utils'; +} from '@react-spectrum/test-utils-internal'; import {announce} from '@react-aria/live-announcer'; import {composeStories} from '@storybook/testing-react'; import {enableTableNestedRows} from '@react-stately/flags'; diff --git a/packages/@react-spectrum/tabs/test/Tabs.test.js b/packages/@react-spectrum/tabs/test/Tabs.test.js index 28fb6c886e4..4b839486b94 100644 --- a/packages/@react-spectrum/tabs/test/Tabs.test.js +++ b/packages/@react-spectrum/tabs/test/Tabs.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, mockImplementation, pointerMap, render, waitFor, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, mockImplementation, pointerMap, render, waitFor, within} from '@react-spectrum/test-utils-internal'; import {Item, TabList, TabPanels, Tabs} from '../src'; import {Links as LinksExample} from '../stories/Tabs.stories'; import {Provider} from '@react-spectrum/provider'; diff --git a/packages/@react-spectrum/tag/test/TagGroup.ssr.test.js b/packages/@react-spectrum/tag/test/TagGroup.ssr.test.js index 12c7d134325..4b12caa8ec0 100644 --- a/packages/@react-spectrum/tag/test/TagGroup.ssr.test.js +++ b/packages/@react-spectrum/tag/test/TagGroup.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('TagGroup SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/tag/test/TagGroup.test.js b/packages/@react-spectrum/tag/test/TagGroup.test.js index ba086d91178..cd7234ab6b8 100644 --- a/packages/@react-spectrum/tag/test/TagGroup.test.js +++ b/packages/@react-spectrum/tag/test/TagGroup.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, mockImplementation, pointerMap, render, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, mockImplementation, pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import {Button} from '@react-spectrum/button'; import {chain} from '@react-aria/utils'; import {Item} from '@react-stately/collections'; diff --git a/packages/@react-spectrum/test-utils/package.json b/packages/@react-spectrum/test-utils/package.json index f747d414b1b..33dd675165c 100644 --- a/packages/@react-spectrum/test-utils/package.json +++ b/packages/@react-spectrum/test-utils/package.json @@ -17,22 +17,21 @@ "dist", "src" ], - "sideEffects": false, + "sideEffects": [ + "*.css" + ], "repository": { "type": "git", "url": "https://github.com/adobe/react-spectrum" }, "dependencies": { - "@react-aria/ssr": "^3.9.0", "@react-aria/test-utils": "3.0.0-alpha.1", - "@swc/helpers": "^0.5.0", - "resolve": "^1.17.0" + "@swc/helpers": "^0.5.0" }, "peerDependencies": { "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.4.3", - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" }, "publishConfig": { "access": "public" diff --git a/packages/@react-spectrum/test-utils/src/index.ts b/packages/@react-spectrum/test-utils/src/index.ts index 6bdaff083db..633aae11369 100644 --- a/packages/@react-spectrum/test-utils/src/index.ts +++ b/packages/@react-spectrum/test-utils/src/index.ts @@ -14,6 +14,3 @@ export * from '@react-aria/test-utils'; export * from './testSetup'; -export * from './renderOverride'; -export * from './StrictModeWrapper'; -export * from './mockImplementation'; diff --git a/packages/@react-spectrum/test-utils/src/testSetup.ts b/packages/@react-spectrum/test-utils/src/testSetup.ts index 03e42416b22..62599b90f91 100644 --- a/packages/@react-spectrum/test-utils/src/testSetup.ts +++ b/packages/@react-spectrum/test-utils/src/testSetup.ts @@ -14,7 +14,7 @@ * Mocks screen width to simulate mobile experience, useful for testing Tray rendering. * @param width Optional width to apply. Automatically clamped to the maximum value allowed for mobile rendering. */ -export function simulateMobile(width: number = 700) { +export function simulateMobile(width: number = 700): void { jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => Math.min(Math.max(width, 0), 700)); } @@ -22,6 +22,6 @@ export function simulateMobile(width: number = 700) { * Mocks screen width to simulate standard desktop experience. * @param width Optional width to apply. Automatically clamped to the minimum value allowed for desktop rendering. */ -export function simulateDesktop(width: number = 701) { +export function simulateDesktop(width: number = 701): void { jest.spyOn(window.screen, 'width', 'get').mockImplementation(() => Math.max(width, 701)); } diff --git a/packages/@react-spectrum/text/test/Heading.ssr.test.js b/packages/@react-spectrum/text/test/Heading.ssr.test.js index 3e7b86d028a..49d809a336a 100644 --- a/packages/@react-spectrum/text/test/Heading.ssr.test.js +++ b/packages/@react-spectrum/text/test/Heading.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('Heading SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/text/test/Keyboard.ssr.test.js b/packages/@react-spectrum/text/test/Keyboard.ssr.test.js index 84715ff31f6..7c23b378bb0 100644 --- a/packages/@react-spectrum/text/test/Keyboard.ssr.test.js +++ b/packages/@react-spectrum/text/test/Keyboard.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('Keyboard SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/text/test/Text.ssr.test.js b/packages/@react-spectrum/text/test/Text.ssr.test.js index 5d05756fca9..92aca7e08f5 100644 --- a/packages/@react-spectrum/text/test/Text.ssr.test.js +++ b/packages/@react-spectrum/text/test/Text.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('Text SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/textfield/test/TextArea.ssr.test.js b/packages/@react-spectrum/textfield/test/TextArea.ssr.test.js index 933cafacc48..51f1e15c98f 100644 --- a/packages/@react-spectrum/textfield/test/TextArea.ssr.test.js +++ b/packages/@react-spectrum/textfield/test/TextArea.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('TextArea SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/textfield/test/TextArea.test.js b/packages/@react-spectrum/textfield/test/TextArea.test.js index 73b4700957a..3c783e7b712 100644 --- a/packages/@react-spectrum/textfield/test/TextArea.test.js +++ b/packages/@react-spectrum/textfield/test/TextArea.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {pointerMap, render} from '@react-spectrum/test-utils'; +import {pointerMap, render} from '@react-spectrum/test-utils-internal'; import React from 'react'; import {TextArea} from '../'; import userEvent from '@testing-library/user-event'; diff --git a/packages/@react-spectrum/textfield/test/TextField.ssr.test.js b/packages/@react-spectrum/textfield/test/TextField.ssr.test.js index 12628db5f50..f988bf0eee9 100644 --- a/packages/@react-spectrum/textfield/test/TextField.ssr.test.js +++ b/packages/@react-spectrum/textfield/test/TextField.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('TextField SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/textfield/test/TextField.test.js b/packages/@react-spectrum/textfield/test/TextField.test.js index e0c7a8e3ac0..e5cdead0993 100644 --- a/packages/@react-spectrum/textfield/test/TextField.test.js +++ b/packages/@react-spectrum/textfield/test/TextField.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, waitFor} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, waitFor} from '@react-spectrum/test-utils-internal'; import {Button} from '@react-spectrum/button'; import Checkmark from '@spectrum-icons/workflow/Checkmark'; import {Form} from '@react-spectrum/form'; diff --git a/packages/@react-spectrum/toast/package.json b/packages/@react-spectrum/toast/package.json index 89992d9acb3..74b7148d648 100644 --- a/packages/@react-spectrum/toast/package.json +++ b/packages/@react-spectrum/toast/package.json @@ -50,7 +50,7 @@ }, "devDependencies": { "@adobe/spectrum-css-temp": "3.0.0-alpha.1", - "@react-spectrum/test-utils": "3.0.0-alpha.1", + "@react-spectrum/test-utils-internal": "3.0.0-alpha.1", "@types/use-sync-external-store": "^0.0.3" }, "peerDependencies": { diff --git a/packages/@react-spectrum/toast/test/ToastContainer.ssr.test.js b/packages/@react-spectrum/toast/test/ToastContainer.ssr.test.js index e9e96e4cd9b..51d07b3605d 100644 --- a/packages/@react-spectrum/toast/test/ToastContainer.ssr.test.js +++ b/packages/@react-spectrum/toast/test/ToastContainer.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('ToastContainer SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/toast/test/ToastContainer.test.js b/packages/@react-spectrum/toast/test/ToastContainer.test.js index 4c496f3d74f..ab958ec4f9a 100644 --- a/packages/@react-spectrum/toast/test/ToastContainer.test.js +++ b/packages/@react-spectrum/toast/test/ToastContainer.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import {Button} from '@react-spectrum/button'; import {clearToastQueue, ToastContainer, ToastQueue} from '../src/ToastContainer'; import {defaultTheme} from '@adobe/react-spectrum'; diff --git a/packages/@react-spectrum/tooltip/test/Tooltip.test.js b/packages/@react-spectrum/tooltip/test/Tooltip.test.js index b80cc957f0a..a85d16ce8e5 100644 --- a/packages/@react-spectrum/tooltip/test/Tooltip.test.js +++ b/packages/@react-spectrum/tooltip/test/Tooltip.test.js @@ -11,7 +11,7 @@ */ import React from 'react'; -import {render} from '@react-spectrum/test-utils'; +import {render} from '@react-spectrum/test-utils-internal'; import {Tooltip} from '../'; describe('Tooltip', function () { diff --git a/packages/@react-spectrum/tooltip/test/TooltipTrigger.test.js b/packages/@react-spectrum/tooltip/test/TooltipTrigger.test.js index b7672194896..7aed303aae8 100644 --- a/packages/@react-spectrum/tooltip/test/TooltipTrigger.test.js +++ b/packages/@react-spectrum/tooltip/test/TooltipTrigger.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render} from '@react-spectrum/test-utils-internal'; import {ActionButton} from '@react-spectrum/button'; import {Provider} from '@react-spectrum/provider'; import React from 'react'; diff --git a/packages/@react-spectrum/utils/test/Slots.test.js b/packages/@react-spectrum/utils/test/Slots.test.js index a2ef43e3734..6a310118adc 100644 --- a/packages/@react-spectrum/utils/test/Slots.test.js +++ b/packages/@react-spectrum/utils/test/Slots.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {pointerMap, render} from '@react-spectrum/test-utils'; +import {pointerMap, render} from '@react-spectrum/test-utils-internal'; import React, {useRef} from 'react'; import {SlotProvider, useSlotProps} from '../'; import {useId, useSlotId} from '@react-aria/utils'; diff --git a/packages/@react-spectrum/view/test/Content.ssr.test.js b/packages/@react-spectrum/view/test/Content.ssr.test.js index 6ed345a3d82..c4668dc128c 100644 --- a/packages/@react-spectrum/view/test/Content.ssr.test.js +++ b/packages/@react-spectrum/view/test/Content.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('Content SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/view/test/Footer.ssr.test.js b/packages/@react-spectrum/view/test/Footer.ssr.test.js index 0f7bb9ba3ba..17658c9c652 100644 --- a/packages/@react-spectrum/view/test/Footer.ssr.test.js +++ b/packages/@react-spectrum/view/test/Footer.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('Footer SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/view/test/Header.ssr.test.js b/packages/@react-spectrum/view/test/Header.ssr.test.js index a553de1d840..1e57af5c162 100644 --- a/packages/@react-spectrum/view/test/Header.ssr.test.js +++ b/packages/@react-spectrum/view/test/Header.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('Header SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/view/test/View.ssr.test.js b/packages/@react-spectrum/view/test/View.ssr.test.js index fd7be1f2d9a..e1fcf3e79ca 100644 --- a/packages/@react-spectrum/view/test/View.ssr.test.js +++ b/packages/@react-spectrum/view/test/View.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('View SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/view/test/View.test.js b/packages/@react-spectrum/view/test/View.test.js index 370e4530a4e..09d311435a3 100644 --- a/packages/@react-spectrum/view/test/View.test.js +++ b/packages/@react-spectrum/view/test/View.test.js @@ -11,7 +11,7 @@ */ import React from 'react'; -import {render} from '@react-spectrum/test-utils'; +import {render} from '@react-spectrum/test-utils-internal'; import {View} from '../'; describe('View', function () { diff --git a/packages/@react-spectrum/well/test/Well.ssr.test.js b/packages/@react-spectrum/well/test/Well.ssr.test.js index 46938aad036..cce5f1e1eb5 100644 --- a/packages/@react-spectrum/well/test/Well.ssr.test.js +++ b/packages/@react-spectrum/well/test/Well.ssr.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {testSSR} from '@react-spectrum/test-utils-test'; +import {testSSR} from '@react-spectrum/test-utils-internal'; describe('Well SSR', function () { it('should render without errors', async function () { diff --git a/packages/@react-spectrum/well/test/Well.test.js b/packages/@react-spectrum/well/test/Well.test.js index 1b84f13598e..c60b45a598d 100644 --- a/packages/@react-spectrum/well/test/Well.test.js +++ b/packages/@react-spectrum/well/test/Well.test.js @@ -11,7 +11,7 @@ */ import React, {useRef} from 'react'; -import {render} from '@react-spectrum/test-utils'; +import {render} from '@react-spectrum/test-utils-internal'; import {Well} from '../'; let refExists = (ComponentToCheck, children, props) => { diff --git a/packages/@react-stately/checkbox/test/useCheckboxGroupState.test.tsx b/packages/@react-stately/checkbox/test/useCheckboxGroupState.test.tsx index 8da761edf02..e0fe0a14152 100644 --- a/packages/@react-stately/checkbox/test/useCheckboxGroupState.test.tsx +++ b/packages/@react-stately/checkbox/test/useCheckboxGroupState.test.tsx @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, render} from '@react-spectrum/test-utils'; +import {act, render} from '@react-spectrum/test-utils-internal'; import React from 'react'; import {useCheckboxGroupState} from '../'; diff --git a/packages/@react-stately/color/test/useColor.test.js b/packages/@react-stately/color/test/useColor.test.js index 7ec02a7a9bd..d9ef9a651c8 100644 --- a/packages/@react-stately/color/test/useColor.test.js +++ b/packages/@react-stately/color/test/useColor.test.js @@ -11,7 +11,7 @@ */ import {parseColor} from '../src/Color'; -import {renderHook} from '@react-spectrum/test-utils'; +import {renderHook} from '@react-spectrum/test-utils-internal'; import {useColor} from '../src/useColor'; describe('useColor tests', function () { diff --git a/packages/@react-stately/color/test/useColorFieldState.test.js b/packages/@react-stately/color/test/useColorFieldState.test.js index 8c96595d291..4b88686bc7b 100644 --- a/packages/@react-stately/color/test/useColorFieldState.test.js +++ b/packages/@react-stately/color/test/useColorFieldState.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {actHook as act, renderHook} from '@react-spectrum/test-utils'; +import {actHook as act, renderHook} from '@react-spectrum/test-utils-internal'; import {parseColor} from '../src/Color'; import {useColorFieldState} from '..'; diff --git a/packages/@react-stately/combobox/test/useComboBoxState.test.js b/packages/@react-stately/combobox/test/useComboBoxState.test.js index 6db93f7f781..96898edc569 100644 --- a/packages/@react-stately/combobox/test/useComboBoxState.test.js +++ b/packages/@react-stately/combobox/test/useComboBoxState.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {actHook as act, renderHook} from '@react-spectrum/test-utils'; +import {actHook as act, renderHook} from '@react-spectrum/test-utils-internal'; import {Item} from '@react-stately/collections'; import React from 'react'; import {useComboBoxState} from '../'; diff --git a/packages/@react-stately/data/test/useAsyncList.test.js b/packages/@react-stately/data/test/useAsyncList.test.js index 80ffbd45499..fdfd30640e2 100644 --- a/packages/@react-stately/data/test/useAsyncList.test.js +++ b/packages/@react-stately/data/test/useAsyncList.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {actHook as act, renderHook} from '@react-spectrum/test-utils'; +import {actHook as act, renderHook} from '@react-spectrum/test-utils-internal'; import React from 'react'; import {useAsyncList} from '../src'; diff --git a/packages/@react-stately/data/test/useListData.test.js b/packages/@react-stately/data/test/useListData.test.js index c066a924ec5..0cd1d87099a 100644 --- a/packages/@react-stately/data/test/useListData.test.js +++ b/packages/@react-stately/data/test/useListData.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {actHook as act, renderHook} from '@react-spectrum/test-utils'; +import {actHook as act, renderHook} from '@react-spectrum/test-utils-internal'; import React from 'react'; import {useListData} from '../src/useListData'; diff --git a/packages/@react-stately/data/test/useTreeData.test.js b/packages/@react-stately/data/test/useTreeData.test.js index 96af76fe8a8..27e66486268 100644 --- a/packages/@react-stately/data/test/useTreeData.test.js +++ b/packages/@react-stately/data/test/useTreeData.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {actHook as act, renderHook} from '@react-spectrum/test-utils'; +import {actHook as act, renderHook} from '@react-spectrum/test-utils-internal'; import React from 'react'; import {useTreeData} from '../src/useTreeData'; diff --git a/packages/@react-stately/pagination/test/usePaginationState.test.js b/packages/@react-stately/pagination/test/usePaginationState.test.js index 9d95a8a41bd..f7426ed9f79 100644 --- a/packages/@react-stately/pagination/test/usePaginationState.test.js +++ b/packages/@react-stately/pagination/test/usePaginationState.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {actHook as act, renderHook} from '@react-spectrum/test-utils'; +import {actHook as act, renderHook} from '@react-spectrum/test-utils-internal'; import React from 'react'; import {usePaginationState} from '../'; diff --git a/packages/@react-stately/searchfield/test/useSearchFieldState.test.js b/packages/@react-stately/searchfield/test/useSearchFieldState.test.js index ba550a1ef07..80ebf7e57a1 100644 --- a/packages/@react-stately/searchfield/test/useSearchFieldState.test.js +++ b/packages/@react-stately/searchfield/test/useSearchFieldState.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {actHook as act, renderHook} from '@react-spectrum/test-utils'; +import {actHook as act, renderHook} from '@react-spectrum/test-utils-internal'; import {useSearchFieldState} from '../'; describe('useSearchFieldState', () => { diff --git a/packages/@react-stately/slider/test/useSliderState.test.js b/packages/@react-stately/slider/test/useSliderState.test.js index d51728abd4e..9482104ca9a 100644 --- a/packages/@react-stately/slider/test/useSliderState.test.js +++ b/packages/@react-stately/slider/test/useSliderState.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {actHook as act, renderHook} from '@react-spectrum/test-utils'; +import {actHook as act, renderHook} from '@react-spectrum/test-utils-internal'; import {useSliderState} from '../'; describe('useSliderState', () => { diff --git a/packages/@react-stately/toast/test/useToastState.test.js b/packages/@react-stately/toast/test/useToastState.test.js index 323a501bb12..2666285c879 100644 --- a/packages/@react-stately/toast/test/useToastState.test.js +++ b/packages/@react-stately/toast/test/useToastState.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {actHook as act, renderHook} from '@react-spectrum/test-utils'; +import {actHook as act, renderHook} from '@react-spectrum/test-utils-internal'; import {useToastState} from '../'; describe('useToastState', () => { diff --git a/packages/@react-stately/tooltip/test/useTooltipTriggerState.test.js b/packages/@react-stately/tooltip/test/useTooltipTriggerState.test.js index f7c64c3dc87..6334fd48568 100644 --- a/packages/@react-stately/tooltip/test/useTooltipTriggerState.test.js +++ b/packages/@react-stately/tooltip/test/useTooltipTriggerState.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, render} from '@react-spectrum/test-utils'; +import {act, fireEvent, render} from '@react-spectrum/test-utils-internal'; import {mergeProps, useTooltip, useTooltipTrigger} from 'react-aria'; import React from 'react'; import {useTooltipTriggerState} from '../src'; @@ -197,4 +197,3 @@ describe('useTooltipTriggerState', function () { }); }); }); - diff --git a/packages/@react-stately/tree/test/useTreeState.test.js b/packages/@react-stately/tree/test/useTreeState.test.js index ab391b88536..8eb67efb05c 100644 --- a/packages/@react-stately/tree/test/useTreeState.test.js +++ b/packages/@react-stately/tree/test/useTreeState.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {fireEvent, pointerMap, render} from '@react-spectrum/test-utils'; +import {fireEvent, pointerMap, render} from '@react-spectrum/test-utils-internal'; import {KeyboardNavigation} from '../stories/useTreeState.stories'; import React from 'react'; import userEvent from '@testing-library/user-event'; diff --git a/packages/@react-stately/utils/test/useControlledState.test.tsx b/packages/@react-stately/utils/test/useControlledState.test.tsx index b04107918a6..ea578a8ba37 100644 --- a/packages/@react-stately/utils/test/useControlledState.test.tsx +++ b/packages/@react-stately/utils/test/useControlledState.test.tsx @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {actHook as act, pointerMap, render, renderHook} from '@react-spectrum/test-utils'; +import {actHook as act, pointerMap, render, renderHook} from '@react-spectrum/test-utils-internal'; import React, {useEffect, useState} from 'react'; import {useControlledState} from '../src'; import userEvent from '@testing-library/user-event'; diff --git a/packages/dev/docs/pages/react-spectrum/testing.mdx b/packages/dev/docs/pages/react-spectrum/testing.mdx index 679e5370144..a68c268526a 100644 --- a/packages/dev/docs/pages/react-spectrum/testing.mdx +++ b/packages/dev/docs/pages/react-spectrum/testing.mdx @@ -9,7 +9,8 @@ governing permissions and limitations under the License. */} import {Layout} from '@react-spectrum/docs'; export default Layout; -import docs from 'docs:@react-spectrum/test-utils'; +import testUtilDocs from 'docs:@react-spectrum/test-utils'; +import {TypeLink} from '@react-spectrum/docs'; --- category: Concepts @@ -246,17 +247,14 @@ await waitFor(() => { Components like ComboBox and Picker render a different experience on mobile versus desktop. If you need to test mobile vs desktop for you app or want to make sure the React Spectrum components are rendered only against a specific experience, you'll need to mock the window screen width accordingly. We currently use a [screen width of 700px](https://github.com/adobe/react-spectrum/blob/5e487532e3ca4714513fb6ab64f7a78d9d1ca281/packages/%40react-spectrum/utils/src/useIsMobileDevice.ts#L15-L23) as the breakpoint -between mobile and desktop, so you should mock the `width` getter of `window.screen` to a value greater or less than this value accordingly. You may use the following utilities from -the '@react-spectrum/test-utils` package to handle this width mocking for you in Jest: - -todo typelink and functionapi for the util when I get the docs import actaully working +between mobile and desktop, so you should mock the `width` getter of `window.screen` to a value greater or less than this value accordingly. You may use and + from the '@react-spectrum/test-utils` package to handle this width mocking for you in Jest: The example below shows how you would set this up in Jest. ```tsx import {simulateDesktop, simulateMobile} from '@react-spectrum/test-utils'; -// TODO: adds omething for other test frameworks? beforeAll(() => { simulateMobile(); }); @@ -295,9 +293,7 @@ test virtualizer behavior. If you run into a test error where your collection co Components like ListView and TableView support long press to perform specific interactions like drag and drop or entering selection mode on mobile devices. Unfortunately, the approach of using the userEvent library to simulate a press event and running timers to hit the long press internal timer threshold isn't sufficient due to `useLongPress`'s usage of `PointerEvent` and our own detection of `virtual` vs `mouse`/`touch` pointer types. Call our `installPointerEvent` utility and `fireEvent` to properly simulate these long press events in your tests. -If you don't need to control the specific timings around the long press interaction, use our `triggerLongPress` utility as shown below. - -TODO add typelink/function api for triggerLongPress +If you are using Jest with fake timers and don't need to control the specific timings around the long press interaction, use our utility as shown below. ```tsx import {installPointerEvent, triggerLongPress} from '@react-spectrum/test-utils'; diff --git a/packages/dev/test-utils/package.json b/packages/dev/test-utils/package.json index a04ea9bad70..74f1e5011e9 100644 --- a/packages/dev/test-utils/package.json +++ b/packages/dev/test-utils/package.json @@ -1,5 +1,5 @@ { - "name": "@react-spectrum/test-utils-test", + "name": "@react-spectrum/test-utils-internal", "version": "3.0.0-alpha.1", "private": true, "description": "Spectrum UI components in React", @@ -12,27 +12,14 @@ "dist", "src" ], - "sideEffects": [ - "*.css" - ], - "targets": { - "main": { - "includeNodeModules": [ - "@adobe/spectrum-css-temp" - ] - }, - "module": { - "includeNodeModules": [ - "@adobe/spectrum-css-temp" - ] - } - }, + "sideEffects": false, "repository": { "type": "git", "url": "https://github.com/adobe/react-spectrum" }, "dependencies": { "@react-aria/ssr": "^3.0.0", + "@react-spectrum/test-utils": "3.0.0-alpha.1", "@swc/helpers": "^0.5.0", "resolve": "^1.17.0" }, @@ -42,9 +29,6 @@ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" }, - "devDependencies": { - "@adobe/spectrum-css-temp": "3.0.0-alpha.1" - }, "publishConfig": { "access": "public" } diff --git a/packages/@react-spectrum/test-utils/src/StrictModeWrapper.tsx b/packages/dev/test-utils/src/StrictModeWrapper.tsx similarity index 100% rename from packages/@react-spectrum/test-utils/src/StrictModeWrapper.tsx rename to packages/dev/test-utils/src/StrictModeWrapper.tsx diff --git a/packages/dev/test-utils/src/index.ts b/packages/dev/test-utils/src/index.ts index 98348ae7a2c..01d126414f7 100644 --- a/packages/dev/test-utils/src/index.ts +++ b/packages/dev/test-utils/src/index.ts @@ -13,3 +13,7 @@ /// export * from './testSSR'; +export * from './renderOverride'; +export * from './StrictModeWrapper'; +export * from './mockImplementation'; +export * from '@react-spectrum/test-utils'; diff --git a/packages/@react-spectrum/test-utils/src/mockImplementation.ts b/packages/dev/test-utils/src/mockImplementation.ts similarity index 100% rename from packages/@react-spectrum/test-utils/src/mockImplementation.ts rename to packages/dev/test-utils/src/mockImplementation.ts diff --git a/packages/@react-spectrum/test-utils/src/renderOverride.js b/packages/dev/test-utils/src/renderOverride.js similarity index 100% rename from packages/@react-spectrum/test-utils/src/renderOverride.js rename to packages/dev/test-utils/src/renderOverride.js diff --git a/packages/react-aria-components/test/Breadcrumbs.ssr.test.js b/packages/react-aria-components/test/Breadcrumbs.ssr.test.js index 274d18ad4cf..3ab6c826490 100644 --- a/packages/react-aria-components/test/Breadcrumbs.ssr.test.js +++ b/packages/react-aria-components/test/Breadcrumbs.ssr.test.js @@ -10,8 +10,7 @@ * governing permissions and limitations under the License. */ -import {screen} from '@react-spectrum/test-utils'; -import {testSSR} from '@react-spectrum/test-utils-test'; +import {screen, testSSR} from '@react-spectrum/test-utils-internal'; describe('Breadcrumbs SSR', function () { it('should render without errors', async function () { diff --git a/packages/react-aria-components/test/Breadcrumbs.test.js b/packages/react-aria-components/test/Breadcrumbs.test.js index 90ed3b68377..5928c621e83 100644 --- a/packages/react-aria-components/test/Breadcrumbs.test.js +++ b/packages/react-aria-components/test/Breadcrumbs.test.js @@ -12,7 +12,7 @@ import {Breadcrumb, Breadcrumbs, BreadcrumbsContext, Link} from 'react-aria-components'; import React from 'react'; -import {render} from '@react-spectrum/test-utils'; +import {render} from '@react-spectrum/test-utils-internal'; let renderBreadcrumbs = (breadcrumbsProps, itemProps) => render( diff --git a/packages/react-aria-components/test/Button.test.js b/packages/react-aria-components/test/Button.test.js index a928b049b3e..d0d29121b55 100644 --- a/packages/react-aria-components/test/Button.test.js +++ b/packages/react-aria-components/test/Button.test.js @@ -11,7 +11,7 @@ */ import {Button, ButtonContext} from '../'; -import {fireEvent, pointerMap, render} from '@react-spectrum/test-utils'; +import {fireEvent, pointerMap, render} from '@react-spectrum/test-utils-internal'; import React from 'react'; import userEvent from '@testing-library/user-event'; diff --git a/packages/react-aria-components/test/Calendar.test.js b/packages/react-aria-components/test/Calendar.test.js index 6e82165b168..889594f6561 100644 --- a/packages/react-aria-components/test/Calendar.test.js +++ b/packages/react-aria-components/test/Calendar.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import {Button, Calendar, CalendarCell, CalendarContext, CalendarGrid, CalendarGridBody, CalendarGridHeader, CalendarHeaderCell, Heading} from 'react-aria-components'; import {CalendarDate, getLocalTimeZone, startOfMonth, startOfWeek, today} from '@internationalized/date'; import React from 'react'; diff --git a/packages/react-aria-components/test/Checkbox.test.js b/packages/react-aria-components/test/Checkbox.test.js index c7b6cb002d2..6f51d091015 100644 --- a/packages/react-aria-components/test/Checkbox.test.js +++ b/packages/react-aria-components/test/Checkbox.test.js @@ -11,7 +11,7 @@ */ import {Checkbox, CheckboxContext} from '../'; -import {fireEvent, pointerMap, render} from '@react-spectrum/test-utils'; +import {fireEvent, pointerMap, render} from '@react-spectrum/test-utils-internal'; import React from 'react'; import userEvent from '@testing-library/user-event'; diff --git a/packages/react-aria-components/test/CheckboxGroup.test.js b/packages/react-aria-components/test/CheckboxGroup.test.js index 0a7adcd812e..0d63b0352d2 100644 --- a/packages/react-aria-components/test/CheckboxGroup.test.js +++ b/packages/react-aria-components/test/CheckboxGroup.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, pointerMap, render} from '@react-spectrum/test-utils'; +import {act, pointerMap, render} from '@react-spectrum/test-utils-internal'; import {Checkbox, CheckboxGroup, CheckboxGroupContext, FieldError, Label, Text} from '../'; import React from 'react'; import userEvent from '@testing-library/user-event'; diff --git a/packages/react-aria-components/test/ComboBox.ssr.test.js b/packages/react-aria-components/test/ComboBox.ssr.test.js index fdfa44c70fe..0a9bd776128 100644 --- a/packages/react-aria-components/test/ComboBox.ssr.test.js +++ b/packages/react-aria-components/test/ComboBox.ssr.test.js @@ -10,8 +10,7 @@ * governing permissions and limitations under the License. */ -import {screen} from '@react-spectrum/test-utils'; -import {testSSR} from '@react-spectrum/test-utils-test'; +import {screen, testSSR} from '@react-spectrum/test-utils-internal'; describe('ComboBox SSR', function () { it('should render text of default selected key', async function () { diff --git a/packages/react-aria-components/test/ComboBox.test.js b/packages/react-aria-components/test/ComboBox.test.js index 87c73a4d335..ad62571a8a2 100644 --- a/packages/react-aria-components/test/ComboBox.test.js +++ b/packages/react-aria-components/test/ComboBox.test.js @@ -12,7 +12,7 @@ import {act} from '@testing-library/react'; import {Button, ComboBox, ComboBoxContext, FieldError, Header, Input, Label, ListBox, ListBoxItem, Popover, Section, Text} from '../'; -import {pointerMap, render, within} from '@react-spectrum/test-utils'; +import {pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import React from 'react'; import userEvent from '@testing-library/user-event'; diff --git a/packages/react-aria-components/test/DateField.test.js b/packages/react-aria-components/test/DateField.test.js index 0ca86115e78..159a97ff06f 100644 --- a/packages/react-aria-components/test/DateField.test.js +++ b/packages/react-aria-components/test/DateField.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, installPointerEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; +import {act, installPointerEvent, pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import {CalendarDate} from '@internationalized/date'; import {DateField, DateFieldContext, DateInput, DateSegment, FieldError, Label, Text} from '../'; import React from 'react'; diff --git a/packages/react-aria-components/test/DatePicker.test.js b/packages/react-aria-components/test/DatePicker.test.js index 65ff70c1707..8de3c0d5f17 100644 --- a/packages/react-aria-components/test/DatePicker.test.js +++ b/packages/react-aria-components/test/DatePicker.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, pointerMap, render, within} from '@react-spectrum/test-utils'; +import {act, pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import {Button, Calendar, CalendarCell, CalendarGrid, DateInput, DatePicker, DatePickerContext, DateSegment, Dialog, FieldError, Group, Heading, Label, Popover, Text} from 'react-aria-components'; import {CalendarDate} from '@internationalized/date'; import React from 'react'; diff --git a/packages/react-aria-components/test/DateRangePicker.test.js b/packages/react-aria-components/test/DateRangePicker.test.js index 9d162427457..ba7f398a636 100644 --- a/packages/react-aria-components/test/DateRangePicker.test.js +++ b/packages/react-aria-components/test/DateRangePicker.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, pointerMap, render, within} from '@react-spectrum/test-utils'; +import {act, pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import {Button, CalendarCell, CalendarGrid, DateInput, DateRangePicker, DateRangePickerContext, DateSegment, Dialog, FieldError, Group, Heading, Label, Popover, RangeCalendar, Text} from 'react-aria-components'; import {CalendarDate} from '@internationalized/date'; import React from 'react'; diff --git a/packages/react-aria-components/test/Dialog.ssr.test.js b/packages/react-aria-components/test/Dialog.ssr.test.js index 8df2b5894bd..45894b71c12 100644 --- a/packages/react-aria-components/test/Dialog.ssr.test.js +++ b/packages/react-aria-components/test/Dialog.ssr.test.js @@ -10,8 +10,7 @@ * governing permissions and limitations under the License. */ -import {screen} from '@react-spectrum/test-utils'; -import {testSSR} from '@react-spectrum/test-utils-test'; +import {screen, testSSR} from '@react-spectrum/test-utils-internal'; describe('Dialog SSR', function () { it('should render without errors', async function () { diff --git a/packages/react-aria-components/test/Dialog.test.js b/packages/react-aria-components/test/Dialog.test.js index 8b1b1b7d901..d22900b683a 100644 --- a/packages/react-aria-components/test/Dialog.test.js +++ b/packages/react-aria-components/test/Dialog.test.js @@ -20,7 +20,7 @@ import { OverlayArrow, Popover } from '../'; -import {pointerMap, render, within} from '@react-spectrum/test-utils'; +import {pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import React from 'react'; import userEvent from '@testing-library/user-event'; diff --git a/packages/react-aria-components/test/DropZone.test.js b/packages/react-aria-components/test/DropZone.test.js index 17319caa334..8bafd8c518c 100644 --- a/packages/react-aria-components/test/DropZone.test.js +++ b/packages/react-aria-components/test/DropZone.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render} from '@react-spectrum/test-utils-internal'; import {Button, DropZone, DropZoneContext, FileTrigger, Link, Text} from '../'; import {ClipboardEvent, DataTransfer, DataTransferItem, DragEvent} from '@react-aria/dnd/test/mocks'; import {Draggable} from '@react-aria/dnd/test/examples'; diff --git a/packages/react-aria-components/test/FileTrigger.test.js b/packages/react-aria-components/test/FileTrigger.test.js index 114f477afa2..d962edcc69e 100644 --- a/packages/react-aria-components/test/FileTrigger.test.js +++ b/packages/react-aria-components/test/FileTrigger.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ import {Button, FileTrigger, Link} from '../'; -import {pointerMap, render} from '@react-spectrum/test-utils'; +import {pointerMap, render} from '@react-spectrum/test-utils-internal'; import React from 'react'; import userEvent from '@testing-library/user-event'; @@ -95,9 +95,9 @@ describe('FileTrigger', () => { ); - + let input = document.querySelector('input[type="file"]'); expect(input).toHaveAttribute('webkitdirectory'); }); - + }); diff --git a/packages/react-aria-components/test/Form.test.js b/packages/react-aria-components/test/Form.test.js index 8f1756109eb..e6f375bf381 100644 --- a/packages/react-aria-components/test/Form.test.js +++ b/packages/react-aria-components/test/Form.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, pointerMap, render} from '@react-spectrum/test-utils'; +import {act, pointerMap, render} from '@react-spectrum/test-utils-internal'; import {Button, FieldError, Form, Input, Label, TextField} from '../'; import React from 'react'; import userEvent from '@testing-library/user-event'; diff --git a/packages/react-aria-components/test/GridList.ssr.test.js b/packages/react-aria-components/test/GridList.ssr.test.js index fe62492dd2b..3b63b5b63d5 100644 --- a/packages/react-aria-components/test/GridList.ssr.test.js +++ b/packages/react-aria-components/test/GridList.ssr.test.js @@ -10,8 +10,7 @@ * governing permissions and limitations under the License. */ -import {fireEvent, screen} from '@react-spectrum/test-utils'; -import {testSSR} from '@react-spectrum/test-utils-test'; +import {fireEvent, screen, testSSR} from '@react-spectrum/test-utils-internal'; describe('GridList SSR', function () { it('should render without errors', async function () { diff --git a/packages/react-aria-components/test/GridList.test.js b/packages/react-aria-components/test/GridList.test.js index dba60d9faaa..905d700a4d8 100644 --- a/packages/react-aria-components/test/GridList.test.js +++ b/packages/react-aria-components/test/GridList.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import {Button, Checkbox, GridList, GridListContext, GridListItem, useDragAndDrop} from '../'; import React from 'react'; import userEvent from '@testing-library/user-event'; diff --git a/packages/react-aria-components/test/Group.test.tsx b/packages/react-aria-components/test/Group.test.tsx index 4c4e1a6da63..4308eca5a9b 100644 --- a/packages/react-aria-components/test/Group.test.tsx +++ b/packages/react-aria-components/test/Group.test.tsx @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ import {Group, GroupContext} from '..'; -import {pointerMap, render} from '@react-spectrum/test-utils'; +import {pointerMap, render} from '@react-spectrum/test-utils-internal'; import React from 'react'; import userEvent from '@testing-library/user-event'; diff --git a/packages/react-aria-components/test/Link.test.js b/packages/react-aria-components/test/Link.test.js index dd5c69dd15d..f1fd54ca89e 100644 --- a/packages/react-aria-components/test/Link.test.js +++ b/packages/react-aria-components/test/Link.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {fireEvent, pointerMap, render} from '@react-spectrum/test-utils'; +import {fireEvent, pointerMap, render} from '@react-spectrum/test-utils-internal'; import {Link, LinkContext, RouterProvider} from '../'; import React from 'react'; import userEvent from '@testing-library/user-event'; diff --git a/packages/react-aria-components/test/ListBox.ssr.test.js b/packages/react-aria-components/test/ListBox.ssr.test.js index 2c18aa9fb1e..b56af8c6bcc 100644 --- a/packages/react-aria-components/test/ListBox.ssr.test.js +++ b/packages/react-aria-components/test/ListBox.ssr.test.js @@ -10,8 +10,7 @@ * governing permissions and limitations under the License. */ -import {fireEvent, screen, within} from '@react-spectrum/test-utils'; -import {testSSR} from '@react-spectrum/test-utils-test'; +import {fireEvent, screen, testSSR, within} from '@react-spectrum/test-utils-internal'; describe('ListBox SSR', function () { it('should render without errors', async function () { diff --git a/packages/react-aria-components/test/ListBox.test.js b/packages/react-aria-components/test/ListBox.test.js index cbb1e926b72..808cb07c3d5 100644 --- a/packages/react-aria-components/test/ListBox.test.js +++ b/packages/react-aria-components/test/ListBox.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import {Header, ListBox, ListBoxContext, ListBoxItem, Section, Text, useDragAndDrop} from '../'; import React, {useState} from 'react'; import userEvent from '@testing-library/user-event'; diff --git a/packages/react-aria-components/test/Menu.test.js b/packages/react-aria-components/test/Menu.test.js index a7f057b3015..e91678932c7 100644 --- a/packages/react-aria-components/test/Menu.test.js +++ b/packages/react-aria-components/test/Menu.test.js @@ -11,7 +11,7 @@ */ import {Button, Header, Keyboard, Menu, MenuContext, MenuItem, MenuTrigger, Popover, Section, Separator, Text} from '../'; -import {fireEvent, pointerMap, render} from '@react-spectrum/test-utils'; +import {fireEvent, pointerMap, render} from '@react-spectrum/test-utils-internal'; import React from 'react'; import userEvent from '@testing-library/user-event'; diff --git a/packages/react-aria-components/test/Meter.test.js b/packages/react-aria-components/test/Meter.test.js index 6eb3d19e158..174c7cc46cc 100644 --- a/packages/react-aria-components/test/Meter.test.js +++ b/packages/react-aria-components/test/Meter.test.js @@ -12,7 +12,7 @@ import {Label, Meter, MeterContext} from 'react-aria-components'; import React from 'react'; -import {render} from '@react-spectrum/test-utils'; +import {render} from '@react-spectrum/test-utils-internal'; let TestMeter = (props) => ( diff --git a/packages/react-aria-components/test/NumberField.test.js b/packages/react-aria-components/test/NumberField.test.js index dfba715d995..29de5db0698 100644 --- a/packages/react-aria-components/test/NumberField.test.js +++ b/packages/react-aria-components/test/NumberField.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, pointerMap, render} from '@react-spectrum/test-utils'; +import {act, pointerMap, render} from '@react-spectrum/test-utils-internal'; import {Button, FieldError, Group, Input, Label, NumberField, NumberFieldContext, Text} from '../'; import React from 'react'; import userEvent from '@testing-library/user-event'; diff --git a/packages/react-aria-components/test/Popover.test.js b/packages/react-aria-components/test/Popover.test.js index 343f4b3130a..6d9a2997bd7 100644 --- a/packages/react-aria-components/test/Popover.test.js +++ b/packages/react-aria-components/test/Popover.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, pointerMap, render} from '@react-spectrum/test-utils'; +import {act, pointerMap, render} from '@react-spectrum/test-utils-internal'; import {Button, Dialog, DialogTrigger, OverlayArrow, Popover} from '../'; import React from 'react'; import userEvent from '@testing-library/user-event'; diff --git a/packages/react-aria-components/test/ProgressBar.test.js b/packages/react-aria-components/test/ProgressBar.test.js index 6733b75728f..8862c782305 100644 --- a/packages/react-aria-components/test/ProgressBar.test.js +++ b/packages/react-aria-components/test/ProgressBar.test.js @@ -12,7 +12,7 @@ import {Label, ProgressBar, ProgressBarContext} from 'react-aria-components'; import React from 'react'; -import {render} from '@react-spectrum/test-utils'; +import {render} from '@react-spectrum/test-utils-internal'; let TestProgressBar = (props) => ( diff --git a/packages/react-aria-components/test/RadioGroup.test.js b/packages/react-aria-components/test/RadioGroup.test.js index 1051ca97e2e..96d64fb70a1 100644 --- a/packages/react-aria-components/test/RadioGroup.test.js +++ b/packages/react-aria-components/test/RadioGroup.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import {Button, Dialog, DialogTrigger, FieldError, Label, Modal, Radio, RadioContext, RadioGroup, RadioGroupContext, Text} from '../'; import React from 'react'; import userEvent from '@testing-library/user-event'; diff --git a/packages/react-aria-components/test/RangeCalendar.test.js b/packages/react-aria-components/test/RangeCalendar.test.js index 23112e703dd..b60b1ae115c 100644 --- a/packages/react-aria-components/test/RangeCalendar.test.js +++ b/packages/react-aria-components/test/RangeCalendar.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import {Button, CalendarCell, CalendarGrid, CalendarGridBody, CalendarGridHeader, CalendarHeaderCell, Heading, RangeCalendar, RangeCalendarContext} from 'react-aria-components'; import {CalendarDate, getLocalTimeZone, startOfMonth, startOfWeek, today} from '@internationalized/date'; import React from 'react'; diff --git a/packages/react-aria-components/test/SearchField.test.js b/packages/react-aria-components/test/SearchField.test.js index 8e76c2bbaa2..6573011c526 100644 --- a/packages/react-aria-components/test/SearchField.test.js +++ b/packages/react-aria-components/test/SearchField.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, pointerMap, render} from '@react-spectrum/test-utils'; +import {act, pointerMap, render} from '@react-spectrum/test-utils-internal'; import {Button, FieldError, Input, Label, SearchField, SearchFieldContext, Text} from '../'; import React from 'react'; import userEvent from '@testing-library/user-event'; diff --git a/packages/react-aria-components/test/Select.ssr.test.js b/packages/react-aria-components/test/Select.ssr.test.js index fa0d592cd0f..cf919272806 100644 --- a/packages/react-aria-components/test/Select.ssr.test.js +++ b/packages/react-aria-components/test/Select.ssr.test.js @@ -10,8 +10,7 @@ * governing permissions and limitations under the License. */ -import {screen} from '@react-spectrum/test-utils'; -import {testSSR} from '@react-spectrum/test-utils-test'; +import {screen, testSSR} from '@react-spectrum/test-utils-internal'; describe('Select SSR', function () { it('should render text of default selected key', async function () { diff --git a/packages/react-aria-components/test/Select.test.js b/packages/react-aria-components/test/Select.test.js index f874efd2fa5..75f3cb0b15f 100644 --- a/packages/react-aria-components/test/Select.test.js +++ b/packages/react-aria-components/test/Select.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, pointerMap, render, within} from '@react-spectrum/test-utils'; +import {act, pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import {Button, FieldError, Label, ListBox, ListBoxItem, Popover, Select, SelectContext, SelectValue, Text} from '../'; import React from 'react'; import userEvent from '@testing-library/user-event'; diff --git a/packages/react-aria-components/test/Slider.test.js b/packages/react-aria-components/test/Slider.test.js index 61af9404cf4..98d380ff0d6 100644 --- a/packages/react-aria-components/test/Slider.test.js +++ b/packages/react-aria-components/test/Slider.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {fireEvent, pointerMap, render} from '@react-spectrum/test-utils'; +import {fireEvent, pointerMap, render} from '@react-spectrum/test-utils-internal'; import {Label, Slider, SliderContext, SliderOutput, SliderThumb, SliderTrack} from '../'; import React from 'react'; import userEvent from '@testing-library/user-event'; diff --git a/packages/react-aria-components/test/Switch.test.js b/packages/react-aria-components/test/Switch.test.js index 647db79feea..3c579cee6f8 100644 --- a/packages/react-aria-components/test/Switch.test.js +++ b/packages/react-aria-components/test/Switch.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {fireEvent, pointerMap, render} from '@react-spectrum/test-utils'; +import {fireEvent, pointerMap, render} from '@react-spectrum/test-utils-internal'; import React from 'react'; import {Switch, SwitchContext} from '../'; import userEvent from '@testing-library/user-event'; diff --git a/packages/react-aria-components/test/Table.ssr.test.js b/packages/react-aria-components/test/Table.ssr.test.js index b100a70753c..5727c6de2a3 100644 --- a/packages/react-aria-components/test/Table.ssr.test.js +++ b/packages/react-aria-components/test/Table.ssr.test.js @@ -10,8 +10,7 @@ * governing permissions and limitations under the License. */ -import {fireEvent, screen} from '@react-spectrum/test-utils'; -import {testSSR} from '@react-spectrum/test-utils-test'; +import {fireEvent, screen, testSSR} from '@react-spectrum/test-utils-internal'; describe('Table SSR', function () { it('should render without errors', async function () { diff --git a/packages/react-aria-components/test/Table.test.js b/packages/react-aria-components/test/Table.test.js index 14442d3dcae..4af42673646 100644 --- a/packages/react-aria-components/test/Table.test.js +++ b/packages/react-aria-components/test/Table.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import {Button, Cell, Checkbox, Collection, Column, ColumnResizer, ResizableTableContainer, Row, Table, TableBody, TableHeader, useDragAndDrop, useTableOptions} from '../'; import React, {useMemo, useState} from 'react'; import {resizingTests} from '@react-aria/table/test/tableResizingTests'; diff --git a/packages/react-aria-components/test/Tabs.ssr.test.js b/packages/react-aria-components/test/Tabs.ssr.test.js index 2ac15831b05..60503c1011f 100644 --- a/packages/react-aria-components/test/Tabs.ssr.test.js +++ b/packages/react-aria-components/test/Tabs.ssr.test.js @@ -10,8 +10,7 @@ * governing permissions and limitations under the License. */ -import {screen} from '@react-spectrum/test-utils'; -import {testSSR} from '@react-spectrum/test-utils-test'; +import {screen, testSSR} from '@react-spectrum/test-utils-internal'; describe('Tabs SSR', function () { it('should render without errors', async function () { diff --git a/packages/react-aria-components/test/Tabs.test.js b/packages/react-aria-components/test/Tabs.test.js index 51f0760f5bb..229fb31744c 100644 --- a/packages/react-aria-components/test/Tabs.test.js +++ b/packages/react-aria-components/test/Tabs.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import React from 'react'; import {Tab, TabList, TabPanel, Tabs} from '../'; import {TabsExample} from '../stories/index.stories'; diff --git a/packages/react-aria-components/test/TagGroup.ssr.test.js b/packages/react-aria-components/test/TagGroup.ssr.test.js index 9e59765bd20..041ccb2a880 100644 --- a/packages/react-aria-components/test/TagGroup.ssr.test.js +++ b/packages/react-aria-components/test/TagGroup.ssr.test.js @@ -10,8 +10,7 @@ * governing permissions and limitations under the License. */ -import {fireEvent, screen} from '@react-spectrum/test-utils'; -import {testSSR} from '@react-spectrum/test-utils-test'; +import {fireEvent, screen, testSSR} from '@react-spectrum/test-utils-internal'; describe('TagGroup SSR', function () { it('should render without errors', async function () { diff --git a/packages/react-aria-components/test/TagGroup.test.js b/packages/react-aria-components/test/TagGroup.test.js index 41311a84a84..624a8c92f2b 100644 --- a/packages/react-aria-components/test/TagGroup.test.js +++ b/packages/react-aria-components/test/TagGroup.test.js @@ -11,7 +11,7 @@ */ import {Button, Label, Tag, TagGroup, TagList, Text} from '../'; -import {fireEvent, pointerMap, render} from '@react-spectrum/test-utils'; +import {fireEvent, pointerMap, render} from '@react-spectrum/test-utils-internal'; import React from 'react'; import userEvent from '@testing-library/user-event'; diff --git a/packages/react-aria-components/test/TextField.test.js b/packages/react-aria-components/test/TextField.test.js index 0b24b8a81df..c6bc158a43a 100644 --- a/packages/react-aria-components/test/TextField.test.js +++ b/packages/react-aria-components/test/TextField.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, pointerMap, render} from '@react-spectrum/test-utils'; +import {act, pointerMap, render} from '@react-spectrum/test-utils-internal'; import {FieldError, Input, Label, Text, TextArea, TextField, TextFieldContext} from '../'; import React from 'react'; import userEvent from '@testing-library/user-event'; diff --git a/packages/react-aria-components/test/TimeField.test.js b/packages/react-aria-components/test/TimeField.test.js index cb64eac85e3..b8e928c1c7d 100644 --- a/packages/react-aria-components/test/TimeField.test.js +++ b/packages/react-aria-components/test/TimeField.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, installPointerEvent, pointerMap, render, within} from '@react-spectrum/test-utils'; +import {act, installPointerEvent, pointerMap, render, within} from '@react-spectrum/test-utils-internal'; import {DateInput, DateSegment, FieldError, Label, Text, TimeField, TimeFieldContext} from '../'; import React from 'react'; import {Time} from '@internationalized/date'; diff --git a/packages/react-aria-components/test/ToggleButton.test.js b/packages/react-aria-components/test/ToggleButton.test.js index 4cd0beaf88a..b3614d80d4c 100644 --- a/packages/react-aria-components/test/ToggleButton.test.js +++ b/packages/react-aria-components/test/ToggleButton.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {fireEvent, pointerMap, render} from '@react-spectrum/test-utils'; +import {fireEvent, pointerMap, render} from '@react-spectrum/test-utils-internal'; import React from 'react'; import {ToggleButton, ToggleButtonContext} from '../'; import userEvent from '@testing-library/user-event'; diff --git a/packages/react-aria-components/test/Toolbar.test.tsx b/packages/react-aria-components/test/Toolbar.test.tsx index cae5261be7e..cc2b9165b3b 100644 --- a/packages/react-aria-components/test/Toolbar.test.tsx +++ b/packages/react-aria-components/test/Toolbar.test.tsx @@ -16,7 +16,7 @@ import {composeStory} from '@storybook/react'; import {I18nProvider} from '@react-aria/i18n'; import Meta, {ToolbarExample as ToolbarExampleStory} from '../stories/index.stories'; -import {pointerMap} from '@react-spectrum/test-utils'; +import {pointerMap} from '@react-spectrum/test-utils-internal'; import React, {createRef} from 'react'; import userEvent from '@testing-library/user-event'; diff --git a/packages/react-aria-components/test/Tooltip.test.js b/packages/react-aria-components/test/Tooltip.test.js index e59dfb0b559..d70771355dd 100644 --- a/packages/react-aria-components/test/Tooltip.test.js +++ b/packages/react-aria-components/test/Tooltip.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render} from '@react-spectrum/test-utils-internal'; import {Button, OverlayArrow, Tooltip, TooltipTrigger} from 'react-aria-components'; import React from 'react'; import userEvent from '@testing-library/user-event'; diff --git a/plop-templates/@react-aria/test/use{{ componentName }}.test.js.hbs b/plop-templates/@react-aria/test/use{{ componentName }}.test.js.hbs index 7bedceab205..c33f671c521 100644 --- a/plop-templates/@react-aria/test/use{{ componentName }}.test.js.hbs +++ b/plop-templates/@react-aria/test/use{{ componentName }}.test.js.hbs @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {render, renderHook} from '@react-spectrum/test-utils'; +import {render, renderHook} from '@react-spectrum/test-utils-internal'; import React, {useRef} from 'react'; import {use{{componentName~}}} from '../'; diff --git a/plop-templates/@react-spectrum/test/{{ componentName }}.test.js.hbs b/plop-templates/@react-spectrum/test/{{ componentName }}.test.js.hbs index 6be9e126835..b846edea608 100644 --- a/plop-templates/@react-spectrum/test/{{ componentName }}.test.js.hbs +++ b/plop-templates/@react-spectrum/test/{{ componentName }}.test.js.hbs @@ -11,7 +11,7 @@ */ import { {{~componentName~}} } from '../'; -import {render} from '@react-spectrum/test-utils'; +import {render} from '@react-spectrum/test-utils-internal'; import React from 'react'; describe('{{componentName}}', function () { diff --git a/scripts/bumpVersions.js b/scripts/bumpVersions.js index 9afffac3d38..4ae17dfe679 100644 --- a/scripts/bumpVersions.js +++ b/scripts/bumpVersions.js @@ -30,7 +30,7 @@ let levels = { // Packages never to release let excludedPackages = new Set([ '@adobe/spectrum-css-temp', - '@react-spectrum/test-utils', + '@react-spectrum/test-utils-internal', '@spectrum-icons/build-tools', '@react-spectrum/docs' ]); diff --git a/scripts/checkPublishedDependencies.js b/scripts/checkPublishedDependencies.js index c14bb80ac9f..dfc7a1c87be 100644 --- a/scripts/checkPublishedDependencies.js +++ b/scripts/checkPublishedDependencies.js @@ -7,7 +7,7 @@ let workspacePackages = JSON.parse(output); let excludedPackages = new Set([ '@adobe/spectrum-css-temp', - '@react-spectrum/test-utils', + '@react-spectrum/test-utils-internal', '@spectrum-icons/build-tools', '@react-spectrum/docs' ]); diff --git a/scripts/lint-packages.js b/scripts/lint-packages.js index 50ec3486ab9..3655f1c2df0 100644 --- a/scripts/lint-packages.js +++ b/scripts/lint-packages.js @@ -109,7 +109,7 @@ for (let pkg of packagePaths) { } softAssert(!json.dependencies || !json.dependencies['@adobe/spectrum-css-temp'], `${pkg} has @adobe/spectrum-css-temp in dependencies instead of devDependencies`); softAssert(json.dependencies && json.dependencies['@swc/helpers'], `${pkg} is missing a dependency on @swc/helpers`); - softAssert(!json.dependencies || !json.dependencies['@react-spectrum/test-utils'], '@react-spectrum/test-utils should be a devDependency'); + softAssert(!json.dependencies || !json.dependencies['@react-spectrum/test-utils-internal'], '@react-spectrum/test-utils should be a devDependency'); softAssert(!json.dependencies || !json.dependencies['react'], `${pkg} has react as a dependency, but it should be a peerDependency`); if (json.peerDependencies?.react) { From e17318eba7354140c765d2c4a9854a3915eb953a Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Thu, 7 Dec 2023 13:23:22 -0800 Subject: [PATCH 21/31] adding docs for installmouseevent --- .../@react-spectrum/color/docs/ColorArea.mdx | 13 +++++++++ .../color/docs/ColorSlider.mdx | 11 ++++++++ .../@react-spectrum/color/docs/ColorWheel.mdx | 11 ++++++++ .../@react-spectrum/slider/docs/Slider.mdx | 11 ++++++++ .../dev/docs/pages/react-spectrum/testing.mdx | 27 ++++++++++++++++--- 5 files changed, 70 insertions(+), 3 deletions(-) diff --git a/packages/@react-spectrum/color/docs/ColorArea.mdx b/packages/@react-spectrum/color/docs/ColorArea.mdx index eafa51df557..0c9a719941e 100644 --- a/packages/@react-spectrum/color/docs/ColorArea.mdx +++ b/packages/@react-spectrum/color/docs/ColorArea.mdx @@ -347,3 +347,16 @@ import {Flex} from '@react-spectrum/layout'; ``` + +## Testing + +The ColorArea features a draggable handle that the user can interact with to change its color value. +Please see the following section in the testing docs for more information on how to simulate this action in your +test suite. + +// TODO need to also mock the client rect? + +[Simulating move event](./testing.html#simulating-move-event) + +Please also refer to [React Spectrum's test suite](https://github.com/adobe/react-spectrum/blob/main/packages/%40react-spectrum/color/test/ColorArea.test.tsx) if you find that the above +isn't sufficient when resolving issues in your own test cases. diff --git a/packages/@react-spectrum/color/docs/ColorSlider.mdx b/packages/@react-spectrum/color/docs/ColorSlider.mdx index 095e901656d..9a3d7005774 100644 --- a/packages/@react-spectrum/color/docs/ColorSlider.mdx +++ b/packages/@react-spectrum/color/docs/ColorSlider.mdx @@ -242,3 +242,14 @@ import {Content, ContextualHelp, Heading} from '@adobe/react-spectrum'; } /> ``` + +## Testing + +The ColorSlider features a draggable handle that the user can interact with to change its color value. +Please see the following section in the testing docs for more information on how to simulate this action in your +test suite. + +[Simulating move event](./testing.html#simulating-move-event) + +Please also refer to [React Spectrum's test suite](https://github.com/adobe/react-spectrum/blob/main/packages/%40react-spectrum/color/test/ColorArea.test.tsx) if you find that the above +isn't sufficient when resolving issues in your own test cases. diff --git a/packages/@react-spectrum/color/docs/ColorWheel.mdx b/packages/@react-spectrum/color/docs/ColorWheel.mdx index 5bce36e8aee..d76f7fd0008 100644 --- a/packages/@react-spectrum/color/docs/ColorWheel.mdx +++ b/packages/@react-spectrum/color/docs/ColorWheel.mdx @@ -136,3 +136,14 @@ function Example() { ```tsx example ``` + +## Testing + +The ColorWheel features a draggable handle that the user can interact with to change its color value. +Please see the following section in the testing docs for more information on how to simulate this action in your +test suite. + +[Simulating move event](./testing.html#simulating-move-event) + +Please also refer to [React Spectrum's test suite](https://github.com/adobe/react-spectrum/blob/main/packages/%40react-spectrum/color/test/ColorWheel.test.tsx) if you find that the above +isn't sufficient when resolving issues in your own test cases. diff --git a/packages/@react-spectrum/slider/docs/Slider.mdx b/packages/@react-spectrum/slider/docs/Slider.mdx index d31534a3eb1..666f536134e 100644 --- a/packages/@react-spectrum/slider/docs/Slider.mdx +++ b/packages/@react-spectrum/slider/docs/Slider.mdx @@ -193,3 +193,14 @@ import {Content, ContextualHelp, Heading} from '@adobe/react-spectrum'; ```tsx example ``` + +## Testing + +The Slider features a draggable handle that the user can interact with to change its value. +Please see the following section in the testing docs for more information on how to simulate this action in your +test suite. + +[Simulating move event](./testing.html#simulating-move-event) + +Please also refer to [React Spectrum's test suite](https://github.com/adobe/react-spectrum/blob/main/packages/%40react-spectrum/color/test/ColorArea.test.tsx) if you find that the above +isn't sufficient when resolving issues in your own test cases. diff --git a/packages/dev/docs/pages/react-spectrum/testing.mdx b/packages/dev/docs/pages/react-spectrum/testing.mdx index a68c268526a..406a7ef18d2 100644 --- a/packages/dev/docs/pages/react-spectrum/testing.mdx +++ b/packages/dev/docs/pages/react-spectrum/testing.mdx @@ -292,10 +292,11 @@ test virtualizer behavior. If you run into a test error where your collection co ### Simulating user long press Components like ListView and TableView support long press to perform specific interactions like drag and drop or entering selection mode on mobile devices. Unfortunately, the approach of using the userEvent library to simulate a press event and running timers to hit the -long press internal timer threshold isn't sufficient due to `useLongPress`'s usage of `PointerEvent` and our own detection of `virtual` vs `mouse`/`touch` pointer types. Call our `installPointerEvent` utility and `fireEvent` to properly simulate these long press events in your tests. -If you are using Jest with fake timers and don't need to control the specific timings around the long press interaction, use our utility as shown below. +long press internal timer threshold isn't sufficient due to `useLongPress`'s usage of `PointerEvent` and our own detection of `virtual` vs `mouse`/`touch` pointer types. Call our `installPointerEvent` utility and `fireEvent` from `@testing-library/react` to properly simulate these long press events in your tests. +If you are using Jest with fake timers and don't need to control the specific timings around the long press interaction, feel free to use our utility as shown below. ```tsx +import {fireEvent} from '@testing-library/react'; import {installPointerEvent, triggerLongPress} from '@react-spectrum/test-utils'; installPointerEvent(); @@ -313,7 +314,27 @@ triggerLongPress(button); ### Simulating move event -TODO document installMouseEvent and movement. add links for slider, and color components +Components like ColorArea, ColorSlider, ColorWheel, and Slider each feature a draggable handle that a user can interact with to change the component's value. Similar to long press, the interactions offered by userEvent library aren't sufficient to trigger +the underlying event handlers governing these drag/move operations. Call our `installMouseEvent` utility and `fireEvent` from `@testing-library/react` to simulate these drag/move events in your tests. Additionally, the track dimensions +for the draggable handle should be mocked so that the move operation calculations can be properly computed. + +```tsx +import {fireEvent} from '@testing-library/react'; +import {installMouseEvent} from '@react-spectrum/test-utils'; +installMouseEvent(); + +beforeAll(() => { + jest.spyOn(window.HTMLElement.prototype, 'getBoundingClientRect').mockImplementation(() => ({top: 0, left: 0, width: 100, height: 10})); +}) + +// In test case +let sliderThumb = getByRole('slider').parentElement; + +// With fireEvent, move thumb from 0 to 50 +fireEvent.mouseDown(thumb, {clientX: 0, pageX: 0}); +fireEvent.mouseMove(thumb, {pageX: 50}); +fireEvent.mouseUp(thumb, {pageX: 50}); +``` ## Snapshot tests From dc74ebedcc04374a5d1b5016811427650a52aa28 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Thu, 7 Dec 2023 14:08:42 -0800 Subject: [PATCH 22/31] add peer deps --- packages/@react-aria/test-utils/package.json | 1 + packages/@react-spectrum/test-utils/package.json | 1 + packages/dev/docs/pages/react-spectrum/testing.mdx | 9 ++++++--- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/@react-aria/test-utils/package.json b/packages/@react-aria/test-utils/package.json index a275a28c275..a56339ad898 100644 --- a/packages/@react-aria/test-utils/package.json +++ b/packages/@react-aria/test-utils/package.json @@ -28,6 +28,7 @@ "peerDependencies": { "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.4.3", + "jest": "^28.0.0", "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" }, "publishConfig": { diff --git a/packages/@react-spectrum/test-utils/package.json b/packages/@react-spectrum/test-utils/package.json index 33dd675165c..7e48e189c86 100644 --- a/packages/@react-spectrum/test-utils/package.json +++ b/packages/@react-spectrum/test-utils/package.json @@ -31,6 +31,7 @@ "peerDependencies": { "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.4.3", + "jest": "^28.0.0", "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" }, "publishConfig": { diff --git a/packages/dev/docs/pages/react-spectrum/testing.mdx b/packages/dev/docs/pages/react-spectrum/testing.mdx index 406a7ef18d2..ceec41155cc 100644 --- a/packages/dev/docs/pages/react-spectrum/testing.mdx +++ b/packages/dev/docs/pages/react-spectrum/testing.mdx @@ -292,8 +292,10 @@ test virtualizer behavior. If you run into a test error where your collection co ### Simulating user long press Components like ListView and TableView support long press to perform specific interactions like drag and drop or entering selection mode on mobile devices. Unfortunately, the approach of using the userEvent library to simulate a press event and running timers to hit the -long press internal timer threshold isn't sufficient due to `useLongPress`'s usage of `PointerEvent` and our own detection of `virtual` vs `mouse`/`touch` pointer types. Call our `installPointerEvent` utility and `fireEvent` from `@testing-library/react` to properly simulate these long press events in your tests. -If you are using Jest with fake timers and don't need to control the specific timings around the long press interaction, feel free to use our utility as shown below. +long press internal timer threshold isn't sufficient due to `useLongPress`'s usage of `PointerEvent` and our own detection of `virtual` vs `mouse`/`touch` pointer types. Mock [PointerEvent](https://github.com/adobe/react-spectrum/blob/16ff0efac57eebeb1cd601ab376ce7c58a4e4efd/packages/dev/test-utils/src/events.ts#L70-L103) +globally and use `fireEvent` from `@testing-library/react` to properly simulate these long press events in your tests. +If you are using Jest, you can call our utility to automatically set up and tear down this mock in your test. +Additionally, you are using fake timers and don't need to control the specific timings around the long press interaction, feel free to use our utility as shown below. ```tsx import {fireEvent} from '@testing-library/react'; @@ -315,7 +317,8 @@ triggerLongPress(button); ### Simulating move event Components like ColorArea, ColorSlider, ColorWheel, and Slider each feature a draggable handle that a user can interact with to change the component's value. Similar to long press, the interactions offered by userEvent library aren't sufficient to trigger -the underlying event handlers governing these drag/move operations. Call our `installMouseEvent` utility and `fireEvent` from `@testing-library/react` to simulate these drag/move events in your tests. Additionally, the track dimensions +the underlying event handlers governing these drag/move operations. [Mock MouseEvent globally](https://github.com/adobe/react-spectrum/blob/16ff0efac57eebeb1cd601ab376ce7c58a4e4efd/packages/dev/test-utils/src/events.ts#L44-L68) and `fireEvent` from `@testing-library/react` to simulate these drag/move events in your tests. +If you are using Jest, you can call our utility to automatically set up and tear down this mock in your test. Additionally, the track dimensions for the draggable handle should be mocked so that the move operation calculations can be properly computed. ```tsx From 0ef44bf9167576a6f84dd9830a508d23b0aedda6 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Thu, 7 Dec 2023 14:30:14 -0800 Subject: [PATCH 23/31] fix combobox test --- packages/@react-spectrum/combobox/test/ComboBox.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@react-spectrum/combobox/test/ComboBox.test.js b/packages/@react-spectrum/combobox/test/ComboBox.test.js index c2a7286b313..56d3ac86425 100644 --- a/packages/@react-spectrum/combobox/test/ComboBox.test.js +++ b/packages/@react-spectrum/combobox/test/ComboBox.test.js @@ -1021,11 +1021,11 @@ describe('ComboBox', function () { expect(onSelectionChange).not.toHaveBeenCalled(); }); - it('should close menu on scroll', function () { + it('should close menu on scroll', async function () { let {getByRole} = renderComboBox(); let button = getByRole('button'); - triggerPress(button); + await user.click(button); act(() => { jest.runAllTimers(); }); From 2ff15bf3c2e7cffb5ed022dc9938b483b4c60fa2 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Thu, 7 Dec 2023 14:39:38 -0800 Subject: [PATCH 24/31] try to fix tsfork --- scripts/buildBranchAPI.js | 2 +- scripts/lint-packages.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/buildBranchAPI.js b/scripts/buildBranchAPI.js index 51c039ffb75..a0f7560820a 100644 --- a/scripts/buildBranchAPI.js +++ b/scripts/buildBranchAPI.js @@ -110,7 +110,7 @@ async function build() { let babelPatch = patches.find(name => name.startsWith('@babel')); fs.copySync(path.join(srcDir, 'patches', babelPatch), path.join(dir, 'patches', babelPatch)); - let excludeList = ['@react-spectrum/story-utils']; + let excludeList = ['@react-spectrum/story-utils', '@react-spectrum/test-utils-internal']; // Copy packages over to temp dir console.log('copying over'); for (let p of packages) { diff --git a/scripts/lint-packages.js b/scripts/lint-packages.js index cf3137a1bc5..7012348c43a 100644 --- a/scripts/lint-packages.js +++ b/scripts/lint-packages.js @@ -117,7 +117,7 @@ for (let pkg of packagePaths) { } softAssert(!json.dependencies || !json.dependencies['@adobe/spectrum-css-temp'], `${pkg} has @adobe/spectrum-css-temp in dependencies instead of devDependencies`); softAssert(json.dependencies && json.dependencies['@swc/helpers'], `${pkg} is missing a dependency on @swc/helpers`); - softAssert(!json.dependencies || !json.dependencies['@react-spectrum/test-utils-internal'], '@react-spectrum/test-utils should be a devDependency'); + softAssert(!json.dependencies || !json.dependencies['@react-spectrum/test-utils-internal'], '@react-spectrum/test-utils-internal should be a devDependency'); softAssert(!json.dependencies || !json.dependencies['react'], `${pkg} has react as a dependency, but it should be a peerDependency`); if (json.peerDependencies?.react) { From 808670db96c49242d233e11bf975a05379bc5278 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Thu, 7 Dec 2023 15:17:31 -0800 Subject: [PATCH 25/31] fix ts fork pt 2 --- scripts/buildBranchAPI.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/buildBranchAPI.js b/scripts/buildBranchAPI.js index a0f7560820a..a321ed6422a 100644 --- a/scripts/buildBranchAPI.js +++ b/scripts/buildBranchAPI.js @@ -104,13 +104,15 @@ async function build() { // does it in a different format fs.copySync(path.join(__dirname, '..', 'packages', 'dev'), path.join(dir, 'packages', 'dev')); fs.copySync(path.join(__dirname, '..', '.parcelrc'), path.join(dir, '.parcelrc')); + // Delete test-utils from copied packages since we don't expose anything from there + fs.removeSync(path.join(dir, 'packages', 'dev', 'test-utils')); // Only copy babel patch over let patches = fs.readdirSync(path.join(srcDir, 'patches')); let babelPatch = patches.find(name => name.startsWith('@babel')); fs.copySync(path.join(srcDir, 'patches', babelPatch), path.join(dir, 'patches', babelPatch)); - let excludeList = ['@react-spectrum/story-utils', '@react-spectrum/test-utils-internal']; + let excludeList = ['@react-spectrum/story-utils']; // Copy packages over to temp dir console.log('copying over'); for (let p of packages) { From 755f06bcadb1e3fc37bd45c6c621eaa0844d1587 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Fri, 8 Dec 2023 11:19:18 -0800 Subject: [PATCH 26/31] test lower version requirements --- packages/@react-aria/test-utils/package.json | 6 +++--- packages/@react-spectrum/test-utils/package.json | 6 +++--- packages/dev/docs/pages/react-spectrum/testing.mdx | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/@react-aria/test-utils/package.json b/packages/@react-aria/test-utils/package.json index a56339ad898..7b52a869129 100644 --- a/packages/@react-aria/test-utils/package.json +++ b/packages/@react-aria/test-utils/package.json @@ -26,9 +26,9 @@ "@swc/helpers": "^0.5.0" }, "peerDependencies": { - "@testing-library/react": "^14.0.0", - "@testing-library/user-event": "^14.4.3", - "jest": "^28.0.0", + "@testing-library/react": "^13.0.0", + "@testing-library/user-event": "^13.0.0", + "jest": "^27.0.0", "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" }, "publishConfig": { diff --git a/packages/@react-spectrum/test-utils/package.json b/packages/@react-spectrum/test-utils/package.json index 7e48e189c86..01519466093 100644 --- a/packages/@react-spectrum/test-utils/package.json +++ b/packages/@react-spectrum/test-utils/package.json @@ -29,9 +29,9 @@ "@swc/helpers": "^0.5.0" }, "peerDependencies": { - "@testing-library/react": "^14.0.0", - "@testing-library/user-event": "^14.4.3", - "jest": "^28.0.0", + "@testing-library/react": "^13.0.0", + "@testing-library/user-event": "^13.0.0", + "jest": "^27.0.0", "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" }, "publishConfig": { diff --git a/packages/dev/docs/pages/react-spectrum/testing.mdx b/packages/dev/docs/pages/react-spectrum/testing.mdx index ceec41155cc..b3e2dc614cc 100644 --- a/packages/dev/docs/pages/react-spectrum/testing.mdx +++ b/packages/dev/docs/pages/react-spectrum/testing.mdx @@ -248,7 +248,7 @@ Components like ComboBox and Picker render a different experience on mobile vers components are rendered only against a specific experience, you'll need to mock the window screen width accordingly. We currently use a [screen width of 700px](https://github.com/adobe/react-spectrum/blob/5e487532e3ca4714513fb6ab64f7a78d9d1ca281/packages/%40react-spectrum/utils/src/useIsMobileDevice.ts#L15-L23) as the breakpoint between mobile and desktop, so you should mock the `width` getter of `window.screen` to a value greater or less than this value accordingly. You may use and - from the '@react-spectrum/test-utils` package to handle this width mocking for you in Jest: + from the `@react-spectrum/test-utils` package to handle this width mocking for you in Jest: The example below shows how you would set this up in Jest. From 66e34cf7adaf62416907618eb60362e5e9fdb7f1 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Tue, 2 Jan 2024 10:52:04 -0800 Subject: [PATCH 27/31] fix tests --- packages/@react-aria/focus/test/FocusScopeOwnerDocument.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@react-aria/focus/test/FocusScopeOwnerDocument.test.js b/packages/@react-aria/focus/test/FocusScopeOwnerDocument.test.js index 2cf4b98e964..e998176d102 100644 --- a/packages/@react-aria/focus/test/FocusScopeOwnerDocument.test.js +++ b/packages/@react-aria/focus/test/FocusScopeOwnerDocument.test.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, pointerMap, render, waitFor} from '@react-spectrum/test-utils'; +import {act, fireEvent, pointerMap, render, waitFor} from '@react-spectrum/test-utils-internal'; import {FocusScope, useFocusManager} from '../'; import React from 'react'; import ReactDOM from 'react-dom'; From 0017ae4bc317a91f03a094c7e7a7fcafe3d3bfb7 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Tue, 2 Jan 2024 11:07:45 -0800 Subject: [PATCH 28/31] missed one test update --- packages/@react-aria/focus/test/focusSafely.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@react-aria/focus/test/focusSafely.test.js b/packages/@react-aria/focus/test/focusSafely.test.js index 8b7534eb1ee..af954c020bb 100644 --- a/packages/@react-aria/focus/test/focusSafely.test.js +++ b/packages/@react-aria/focus/test/focusSafely.test.js @@ -11,7 +11,7 @@ */ -import {act, render} from '@react-spectrum/test-utils'; +import {act, render} from '@react-spectrum/test-utils-internal'; import {focusSafely} from '../'; import React from 'react'; import * as ReactAriaUtils from '../../utils/index'; From 03fdd4da50d2c69118e37a9536bdd19c232c2db1 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Thu, 25 Jan 2024 10:22:20 -0800 Subject: [PATCH 29/31] review updates --- packages/@react-aria/test-utils/src/events.ts | 6 +++++- packages/dev/docs/pages/react-spectrum/testing.mdx | 8 ++++---- packages/dev/test-utils/src/mockImplementation.ts | 1 - 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/@react-aria/test-utils/src/events.ts b/packages/@react-aria/test-utils/src/events.ts index a123cf04919..64d69d1e161 100644 --- a/packages/@react-aria/test-utils/src/events.ts +++ b/packages/@react-aria/test-utils/src/events.ts @@ -12,9 +12,13 @@ import {act, fireEvent} from '@testing-library/react'; -// Triggers a "longPress" event on an element. export const DEFAULT_LONG_PRESS_TIME = 500; +/** + * Simulates a "long press" event on a element. + * @param element - Element to long press. + * @param opts - Options to pass to the simulated event. See https://testing-library.com/docs/dom-testing-library/api-events/#fireevent for more info. + */ export function triggerLongPress(element: HTMLElement, opts = {}): void { fireEvent.pointerDown(element, {pointerType: 'touch', ...opts}); act(() => { diff --git a/packages/dev/docs/pages/react-spectrum/testing.mdx b/packages/dev/docs/pages/react-spectrum/testing.mdx index b3e2dc614cc..fcd4a19d8ec 100644 --- a/packages/dev/docs/pages/react-spectrum/testing.mdx +++ b/packages/dev/docs/pages/react-spectrum/testing.mdx @@ -190,9 +190,9 @@ export * from '@testing-library/react'; function ProviderWrapper(props) { let {children, ...providerProps} = props; return ( - + {props.children} - + ); } @@ -218,7 +218,7 @@ If you are using fake timers in your test suite, be aware that you may need to a Historically, this most commonly happened when a modals, popovers, or trays is opened or closed as a result of a simulated user action (e.g. opening a Picker's dropdown via click). Additionally, we have `requestAnimationFrame` calls in various areas that you will need to also handle by advancing your timers in the tests. This happens most prominently in our virtualized components due to the internals of our Virtualizer. In Jest, this can be handled by calling `act(() => jest.runAllTimers());` but you may require more precise control -depending on the other time sensitive behavior you are testing. Please see [Jest's timer docs](https://jestjs.io/docs/timer-mocks) or the equivalent docs of your test frameworks for more information on how to do so. +depending on the other time-sensitive behavior you are testing. Please see [Jest's timer docs](https://jestjs.io/docs/timer-mocks) or the equivalent docs of your test frameworks for more information on how to do so. It is also a good idea to run all timers to completion after each test case to avoid any left over transitions or timeouts that a component may have setup during its lifecycle. ```tsx @@ -341,7 +341,7 @@ fireEvent.mouseUp(thumb, {pageX: 50}); ## Snapshot tests -If you are use React 16 or 17, you may run into an issue where the ids generated by the React Spectrum components are changing on every snapshot. To remedy this, simply wrap your component in a [SSRProvider](../react-aria/SSRProvider.html). +If you are using React 16 or 17, you may run into an issue where the ids generated by the React Spectrum components are changing on every snapshot. To remedy this, simply wrap your component in a [SSRProvider](../react-aria/SSRProvider.html). Note that you can use the SSRProvider even if your component doesn't support server side rendering, it will simply stabilize the ids generated. ```tsx diff --git a/packages/dev/test-utils/src/mockImplementation.ts b/packages/dev/test-utils/src/mockImplementation.ts index 5c54899d64b..1b4ed951446 100644 --- a/packages/dev/test-utils/src/mockImplementation.ts +++ b/packages/dev/test-utils/src/mockImplementation.ts @@ -15,7 +15,6 @@ type Access = [any, string, 'get' | 'set']; type SpyTarget = Method | Access type MockCalls = Array<() => any> -// TODO: ask if this stuff should also live in the react-spectrum/test-util package? What about the SSR stuff as well? // Util for mockImplementation that automatically handles extra calls needed for strict mode export function mockImplementation(spyTarget: SpyTarget, mockCalls: MockCalls, retainLastMock = true) { if (mockCalls.length === 0) { From 81cf49b819fe89da73966066cd8362ea96c394ab Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Wed, 14 Feb 2024 10:15:52 -0800 Subject: [PATCH 30/31] removing todo --- packages/dev/docs/pages/react-spectrum/testing.mdx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/dev/docs/pages/react-spectrum/testing.mdx b/packages/dev/docs/pages/react-spectrum/testing.mdx index fcd4a19d8ec..09d58c55c37 100644 --- a/packages/dev/docs/pages/react-spectrum/testing.mdx +++ b/packages/dev/docs/pages/react-spectrum/testing.mdx @@ -264,7 +264,6 @@ afterAll(() => { }); ``` -TODO: this section assumes that we will turn off virtualization for in test environments, update if aren't going ship with that ### Virtualized components Many of our collection components are virtualized out of the box and thus rely on DOM node measurement to know how large a item should be and how many items can be rendered at once. By default, virtualization for these From b2200dfb3879e1aef3299bb11aceed4636dc3b82 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Wed, 14 Feb 2024 10:23:16 -0800 Subject: [PATCH 31/31] messed up a copy paste --- packages/@react-aria/interactions/test/useFocusVisible.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@react-aria/interactions/test/useFocusVisible.test.js b/packages/@react-aria/interactions/test/useFocusVisible.test.js index 0dda83bdb38..c80123f54fc 100644 --- a/packages/@react-aria/interactions/test/useFocusVisible.test.js +++ b/packages/@react-aria/interactions/test/useFocusVisible.test.js @@ -9,7 +9,7 @@ * OF ANY KIND, either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ -import {act, fireEvent, render, renderHook, screen, waitFor} from '@react-spectrum/test-utils-updating_testing_docs'; +import {act, fireEvent, render, renderHook, screen, waitFor} from '@react-spectrum/test-utils-internal'; import {addWindowFocusTracking, useFocusVisible, useFocusVisibleListener} from '../'; import {hasSetupGlobalListeners} from '../src/useFocusVisible'; import React from 'react';