From 0812202749cbf02893c48be59d5ccf2e6171226b Mon Sep 17 00:00:00 2001 From: Dani Guardiola Date: Thu, 1 Aug 2024 20:50:00 +0200 Subject: [PATCH 1/8] Added lint rules. --- .eslintrc.js | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 0fc37713dce4d..e31c327494ccc 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -459,13 +459,26 @@ module.exports = { // the `@wordpress/components` package, hence why importing those // dependencies should be allowed in the components package. { - paths: restrictedImports.filter( - ( { name } ) => - ! [ - '@ariakit/react', - 'framer-motion', - ].includes( name ) - ), + paths: [ + ...restrictedImports.filter( + ( { name } ) => + ! [ + '@ariakit/react', + 'framer-motion', + ].includes( name ) + ), + { + name: '@testing-library/user-event', + message: + 'Please use event triggers (`click`, `press`, etc) from `@ariakit/test` instead.', + }, + { + name: '@testing-library/react', + importNames: [ 'render' ], + message: + 'Please use `render` from `@ariakit/test` instead.', + }, + ], }, ], }, From d4b654147d534c26142821603ee74ffe66c95ef0 Mon Sep 17 00:00:00 2001 From: Dani Guardiola Date: Thu, 1 Aug 2024 20:55:57 +0200 Subject: [PATCH 2/8] Add temporary migration (codemod) files. --- migration/migrate.sh | 15 +++++++++++++ migration/patterns/await_render_calls.grit | 21 +++++++++++++++++++ .../patterns/replace_ariakit_test_import.grit | 14 +++++++++++++ 3 files changed, 50 insertions(+) create mode 100755 migration/migrate.sh create mode 100644 migration/patterns/await_render_calls.grit create mode 100644 migration/patterns/replace_ariakit_test_import.grit diff --git a/migration/migrate.sh b/migration/migrate.sh new file mode 100755 index 0000000000000..d8c1290c12ca7 --- /dev/null +++ b/migration/migrate.sh @@ -0,0 +1,15 @@ +# HOW TO RUN THIS SCRIPT +# +# 1. Install grit (https://docs.grit.io/cli/quickstart#installation): +# $ npm install --location=global @getgrit/cli +# +# 2. Run this script from the root of the project (<- IMPORTANT): +# $ ./migration/migrate.sh + +function apply() { + grit apply --force --output none "migration/patterns/$1.grit" packages/components +} + +apply await_render_calls +apply replace_ariakit_test_import +npm run lint:js:fix -- packages/components diff --git a/migration/patterns/await_render_calls.grit b/migration/patterns/await_render_calls.grit new file mode 100644 index 0000000000000..1d85793712b6e --- /dev/null +++ b/migration/patterns/await_render_calls.grit @@ -0,0 +1,21 @@ +engine marzano(0.1) +language js + +pattern await_render_calls() { + `it($description, $test_fn)` where { + $test_fn <: contains bubble `$render_method($render_args)` where { + !$render_method <: within `await $_`, + $render_method <: or { + `render` => `await render`, + `rerender` => `await rerender` + }, + }, + $test_fn <: maybe $test_fn where { + !$test_fn <: arrow_function(async = "async"), + !$test_fn <: function(async = "async"), + $test_fn => `async $test_fn` + } + } +} + +await_render_calls() diff --git a/migration/patterns/replace_ariakit_test_import.grit b/migration/patterns/replace_ariakit_test_import.grit new file mode 100644 index 0000000000000..fdebc26e00f90 --- /dev/null +++ b/migration/patterns/replace_ariakit_test_import.grit @@ -0,0 +1,14 @@ +engine marzano(0.1) +language js + +pattern replace_ariakit_test_import() { + `import { $imports } from '@testing-library/react'` as $import where { + $imports <: contains `render` as $render, + $render => ., + $import => +`$import; +import {render} from "@ariakit/test/react";` + } +} + +replace_ariakit_test_import() From 504e9cc99cad2d1bdf9563e064e62df9eb382ddc Mon Sep 17 00:00:00 2001 From: Dani Guardiola Date: Thu, 1 Aug 2024 21:08:15 +0200 Subject: [PATCH 3/8] Undo changes in react native tests. --- migration/migrate.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/migration/migrate.sh b/migration/migrate.sh index d8c1290c12ca7..857ce9a8ced15 100755 --- a/migration/migrate.sh +++ b/migration/migrate.sh @@ -12,4 +12,5 @@ function apply() { apply await_render_calls apply replace_ariakit_test_import +git checkout '*.native.*' npm run lint:js:fix -- packages/components From a430d0e2cbbc294bec348e38ffa7df68982b846d Mon Sep 17 00:00:00 2001 From: Dani Guardiola Date: Thu, 1 Aug 2024 21:12:05 +0200 Subject: [PATCH 4/8] Temporarily comment out lint rule for events. --- .eslintrc.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index e31c327494ccc..0db0f2e95a9f1 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -467,11 +467,11 @@ module.exports = { 'framer-motion', ].includes( name ) ), - { - name: '@testing-library/user-event', - message: - 'Please use event triggers (`click`, `press`, etc) from `@ariakit/test` instead.', - }, + // { + // name: '@testing-library/user-event', + // message: + // 'Please use event triggers (`click`, `press`, etc) from `@ariakit/test` instead.', + // }, { name: '@testing-library/react', importNames: [ 'render' ], From 0fcf95970a1f253b573f0b5b00ab4a9beccdf15f Mon Sep 17 00:00:00 2001 From: Dani Guardiola Date: Thu, 1 Aug 2024 21:20:38 +0200 Subject: [PATCH 5/8] First codemod passs (await render + rewrite import) --- .../alignment-matrix-control/test/index.tsx | 3 +- .../src/autocomplete/test/index.tsx | 5 +- .../src/base-control/test/index.tsx | 11 +- .../src/border-box-control/test/index.tsx | 67 +++--- .../src/border-control/test/index.js | 97 ++++----- .../components/src/box-control/test/index.tsx | 53 ++--- packages/components/src/button/test/index.tsx | 191 ++++++++--------- packages/components/src/card/test/index.tsx | 89 ++++---- .../src/checkbox-control/test/index.tsx | 39 ++-- .../src/circular-option-picker/test/index.tsx | 17 +- .../src/color-indicator/test/index.tsx | 7 +- .../src/color-palette/test/index.tsx | 33 +-- .../src/color-picker/test/index.tsx | 13 +- .../src/combobox-control/test/index.tsx | 33 +-- .../src/composite/legacy/test/index.tsx | 3 +- .../src/confirm-dialog/test/index.tsx | 45 ++-- .../context/test/context-system-provider.js | 3 +- .../src/date-time/date/test/index.tsx | 21 +- .../src/date-time/time/test/index.tsx | 45 ++-- .../date-time/time/time-input/test/index.tsx | 15 +- .../src/dimension-control/test/index.test.js | 23 ++- .../components/src/disabled/test/index.tsx | 27 +-- .../components/src/divider/test/index.tsx | 3 +- .../src/dropdown-menu-v2/test/index.tsx | 49 ++--- .../src/dropdown-menu/test/index.tsx | 17 +- .../components/src/dropdown/test/index.tsx | 7 +- .../components/src/elevation/test/index.tsx | 3 +- .../src/external-link/test/index.tsx | 3 +- packages/components/src/flex/test/index.tsx | 3 +- .../src/focal-point-picker/test/index.tsx | 29 +-- .../src/focal-point-picker/test/media.tsx | 31 +-- .../src/font-size-picker/test/index.tsx | 4 +- .../src/form-file-upload/test/index.tsx | 11 +- .../components/src/form-toggle/test/index.tsx | 27 +-- .../src/form-token-field/test/index.tsx | 194 ++++++++++-------- packages/components/src/grid/test/grid.tsx | 3 +- packages/components/src/guide/test/index.tsx | 37 ++-- .../components/src/h-stack/test/index.tsx | 3 +- .../components/src/heading/test/index.tsx | 3 +- .../higher-order/with-filters/test/index.tsx | 25 +-- .../with-focus-outside/test/index.tsx | 15 +- .../with-focus-return/test/index.tsx | 21 +- .../higher-order/with-notices/test/index.tsx | 22 +- .../with-spoken-messages/test/index.tsx | 7 +- packages/components/src/icon/test/index.tsx | 45 ++-- .../src/input-control/test/index.js | 45 ++-- .../isolated-event-container/test/index.tsx | 9 +- .../components/src/item-group/test/index.js | 45 ++-- .../src/keyboard-shortcuts/test/index.tsx | 17 +- .../components/src/menu-group/test/index.tsx | 3 +- .../components/src/menu-item/test/index.js | 41 ++-- packages/components/src/modal/test/index.tsx | 49 ++--- .../test/navigable-menu.tsx | 15 +- .../test/tababble-container.tsx | 13 +- .../components/src/navigation/test/index.tsx | 35 ++-- .../components/src/navigator/test/index.tsx | 41 ++-- packages/components/src/notice/test/index.tsx | 41 ++-- packages/components/src/notice/test/list.tsx | 7 +- .../src/number-control/test/index.tsx | 95 +++++---- .../src/palette-edit/test/index.tsx | 37 ++-- packages/components/src/panel/test/body.tsx | 37 ++-- packages/components/src/panel/test/header.tsx | 19 +- packages/components/src/panel/test/index.tsx | 23 ++- packages/components/src/panel/test/row.tsx | 15 +- .../components/src/placeholder/test/index.tsx | 43 ++-- .../components/src/popover/test/index.tsx | 17 +- .../src/progress-bar/test/index.tsx | 23 ++- .../src/radio-control/test/index.tsx | 33 +-- .../src/range-control/test/index.tsx | 85 ++++---- .../components/src/sandbox/test/index.tsx | 7 +- .../components/src/scroll-lock/test/index.tsx | 11 +- .../components/src/scrollable/test/index.tsx | 3 +- .../src/search-control/test/index.tsx | 9 +- .../select-control/test/select-control.tsx | 11 +- .../components/src/shortcut/test/index.tsx | 21 +- .../components/src/slot-fill/test/index.js | 3 +- .../components/src/slot-fill/test/slot.js | 71 +++---- .../components/src/snackbar/test/index.tsx | 53 ++--- .../components/src/snackbar/test/list.tsx | 5 +- packages/components/src/spacer/test/index.tsx | 3 +- .../components/src/surface/test/index.tsx | 3 +- .../components/src/tab-panel/test/index.tsx | 83 ++++---- .../src/text-control/test/text-control.tsx | 21 +- .../src/text-highlight/test/index.tsx | 15 +- packages/components/src/text/test/index.tsx | 3 +- packages/components/src/theme/test/index.tsx | 19 +- .../src/toggle-control/test/index.tsx | 25 ++- .../src/toggle-group-control/test/index.tsx | 43 ++-- .../components/src/toolbar/test/index.tsx | 11 +- .../src/toolbar/test/toolbar-group.tsx | 29 +-- .../components/src/tools-panel/test/index.tsx | 87 ++++---- .../components/src/tooltip/test/index.tsx | 45 ++-- .../components/src/tree-grid/test/cell.tsx | 30 +-- .../components/src/tree-grid/test/index.tsx | 35 ++-- .../tree-grid/test/roving-tab-index-item.tsx | 21 +- .../src/tree-grid/test/roving-tab-index.tsx | 7 +- .../components/src/tree-grid/test/row.tsx | 11 +- .../components/src/truncate/test/index.tsx | 3 +- .../src/unit-control/test/index.tsx | 83 +++++--- .../utils/hooks/test/use-controlled-state.js | 23 ++- .../utils/hooks/test/use-controlled-value.js | 33 +-- .../components/src/utils/hooks/test/use-cx.js | 7 +- .../components/src/v-stack/test/index.tsx | 3 +- packages/components/src/view/test/index.js | 3 +- .../src/visually-hidden/test/index.tsx | 7 +- 105 files changed, 1639 insertions(+), 1398 deletions(-) diff --git a/packages/components/src/alignment-matrix-control/test/index.tsx b/packages/components/src/alignment-matrix-control/test/index.tsx index 57c13f8c92eee..4c20de7747e34 100644 --- a/packages/components/src/alignment-matrix-control/test/index.tsx +++ b/packages/components/src/alignment-matrix-control/test/index.tsx @@ -1,7 +1,8 @@ /** * External dependencies */ -import { render, screen, waitFor, within } from '@testing-library/react'; +import { screen, waitFor, within } from '@testing-library/react'; +import { render } from '@ariakit/test/react'; import { press, click, sleep } from '@ariakit/test'; /** diff --git a/packages/components/src/autocomplete/test/index.tsx b/packages/components/src/autocomplete/test/index.tsx index 0df784f8367cd..90207e6d8c745 100644 --- a/packages/components/src/autocomplete/test/index.tsx +++ b/packages/components/src/autocomplete/test/index.tsx @@ -1,7 +1,8 @@ /** * External dependencies */ -import { render, screen } from '@testing-library/react'; +import { screen } from '@testing-library/react'; +import { render } from '@ariakit/test/react'; import userEvent from '@testing-library/user-event'; /** @@ -82,7 +83,7 @@ describe( 'AutocompleterUI', () => { ); }; - render( ); + await render( ); // Click on autocompleter. await user.click( screen.getByText( 'Apple' ) ); diff --git a/packages/components/src/base-control/test/index.tsx b/packages/components/src/base-control/test/index.tsx index 07623a8b4c3e7..62961a005852c 100644 --- a/packages/components/src/base-control/test/index.tsx +++ b/packages/components/src/base-control/test/index.tsx @@ -1,7 +1,8 @@ /** * External dependencies */ -import { render, screen } from '@testing-library/react'; +import { screen } from '@testing-library/react'; +import { render } from '@ariakit/test/react'; /** * Internal dependencies @@ -21,8 +22,8 @@ const MyBaseControl = ( props: Omit< BaseControlProps, 'children' > ) => { }; describe( 'BaseControl', () => { - it( 'should render help text as description', () => { - render( ); + it( 'should render help text as description', async () => { + await render( ); expect( screen.getByRole( 'textbox', { @@ -31,8 +32,8 @@ describe( 'BaseControl', () => { ).toBeInTheDocument(); } ); - it( 'should still render help as aria-describedby when not plain text', () => { - render( + it( 'should still render help as aria-describedby when not plain text', async () => { + await render( My help text } diff --git a/packages/components/src/border-box-control/test/index.tsx b/packages/components/src/border-box-control/test/index.tsx index fe5f7e7a4f1ff..9f0ae0e3fa56e 100644 --- a/packages/components/src/border-box-control/test/index.tsx +++ b/packages/components/src/border-box-control/test/index.tsx @@ -1,7 +1,8 @@ /** * External dependencies */ -import { render, screen, waitFor } from '@testing-library/react'; +import { screen, waitFor } from '@testing-library/react'; +import { render } from '@ariakit/test/react'; import userEvent from '@testing-library/user-event'; /** @@ -51,8 +52,8 @@ const colorPickerRegex = /Border color picker/; describe( 'BorderBoxControl', () => { describe( 'Linked view rendering', () => { - it( 'should render correctly when no value provided', () => { - render( ); + it( 'should render correctly when no value provided', async () => { + await render( ); const label = screen.getByText( props.label ); const colorButton = screen.getByLabelText( toggleLabelRegex ); @@ -76,8 +77,10 @@ describe( 'BorderBoxControl', () => { expect( linkedButton ).toBeInTheDocument(); } ); - it( 'should hide label', () => { - render( ); + it( 'should hide label', async () => { + await render( + + ); const label = screen.getByText( props.label ); @@ -90,8 +93,10 @@ describe( 'BorderBoxControl', () => { ); } ); - it( 'should show correct width value when flat border value provided', () => { - render( ); + it( 'should show correct width value when flat border value provided', async () => { + await render( + + ); const widthInput = screen.getByRole( 'spinbutton', { name: 'Border width', @@ -100,8 +105,8 @@ describe( 'BorderBoxControl', () => { expect( widthInput.value ).toBe( '1' ); } ); - it( 'should show correct width value when consistent split borders provided', () => { - render( + it( 'should show correct width value when consistent split borders provided', async () => { + await render( ); @@ -115,7 +120,9 @@ describe( 'BorderBoxControl', () => { it( 'should render placeholder and omit unit select when border values are mixed', async () => { const user = userEvent.setup(); - render( ); + await render( + + ); // There are 4 inputs when in unlinked mode (top/right/bottom/left) expect( @@ -153,7 +160,7 @@ describe( 'BorderBoxControl', () => { const user = userEvent.setup(); // Render control with mixed border values but consistent widths. - render( + await render( { it( 'should omit style options when requested', async () => { const user = userEvent.setup(); - render( ); + await render( + + ); const colorButton = screen.getByLabelText( colorPickerRegex ); await user.click( colorButton ); @@ -218,8 +227,10 @@ describe( 'BorderBoxControl', () => { } ); describe( 'Split view rendering', () => { - it( 'should render split view by default when mixed values provided', () => { - render( ); + it( 'should render split view by default when mixed values provided', async () => { + await render( + + ); const colorButtons = screen.getAllByLabelText( toggleLabelRegex ); const widthInputs = screen.getAllByRole( 'spinbutton', { @@ -240,8 +251,10 @@ describe( 'BorderBoxControl', () => { expect( linkedButton ).toBeInTheDocument(); } ); - it( 'should render correct width values in appropriate inputs', () => { - render( ); + it( 'should render correct width values in appropriate inputs', async () => { + await render( + + ); const widthInputs = screen.getAllByRole( 'spinbutton', { name: 'Border width', @@ -256,7 +269,7 @@ describe( 'BorderBoxControl', () => { it( 'should render split view correctly when starting with flat border', async () => { const user = userEvent.setup(); - render( + await render( ); @@ -316,7 +329,7 @@ describe( 'BorderBoxControl', () => { it( 'should set undefined when new border is empty', async () => { const user = userEvent.setup(); - render( + await render( ); @@ -330,7 +343,7 @@ describe( 'BorderBoxControl', () => { it( 'should update with complete flat border', async () => { const user = userEvent.setup(); - render( + await render( ); @@ -349,7 +362,7 @@ describe( 'BorderBoxControl', () => { it( 'should maintain mixed values if not explicitly set via linked control', async () => { const user = userEvent.setup(); - render( + await render( { it( 'should update with consistent split borders', async () => { const user = userEvent.setup(); - render( + await render( ); @@ -401,7 +414,7 @@ describe( 'BorderBoxControl', () => { it( 'should set undefined borders when change results in empty borders', async () => { const user = userEvent.setup(); - render( + await render( { it( 'should set flat border when change results in consistent split borders', async () => { const user = userEvent.setup(); - render( + await render( { left: { ...defaultBorder, width: '4px' }, }; - render( ); + await render( + + ); const widthInput = screen.getAllByRole( 'spinbutton', { name: 'Border width', @@ -487,7 +502,9 @@ describe( 'BorderBoxControl', () => { left: { ...defaultBorder, width: '1px' }, }; - render( ); + await render( + + ); const widthInput = screen.getAllByRole( 'spinbutton', { name: 'Border width', diff --git a/packages/components/src/border-control/test/index.js b/packages/components/src/border-control/test/index.js index c41dce687cc52..0daa269f730a8 100644 --- a/packages/components/src/border-control/test/index.js +++ b/packages/components/src/border-control/test/index.js @@ -1,7 +1,8 @@ /** * External dependencies */ -import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import { fireEvent, screen, waitFor } from '@testing-library/react'; +import { render } from '@ariakit/test/react'; import userEvent from '@testing-library/user-event'; /** @@ -72,9 +73,9 @@ const getWidthInput = () => { describe( 'BorderControl', () => { describe( 'basic rendering', () => { - it( 'should render standard border control', () => { + it( 'should render standard border control', async () => { const props = createProps(); - render( ); + await render( ); const label = screen.getByText( props.label ); const colorButton = screen.getByLabelText( toggleLabelRegex ); @@ -93,9 +94,9 @@ describe( 'BorderControl', () => { expect( slider ).not.toBeInTheDocument(); } ); - it( 'should hide label', () => { + it( 'should hide label', async () => { const props = createProps( { hideLabelFromVision: true } ); - render( ); + await render( ); const label = screen.getByText( props.label ); // As visually hidden labels are still included in the document @@ -107,17 +108,17 @@ describe( 'BorderControl', () => { ); } ); - it( 'should render with slider', () => { + it( 'should render with slider', async () => { const props = createProps( { withSlider: true } ); - render( ); + await render( ); const slider = getSliderInput(); expect( slider ).toBeInTheDocument(); } ); - it( 'should render placeholder in UnitControl', () => { + it( 'should render placeholder in UnitControl', async () => { const props = createProps( { placeholder: 'Mixed' } ); - render( ); + await render( ); const widthInput = getWidthInput(); expect( widthInput ).toHaveAttribute( 'placeholder', 'Mixed' ); @@ -126,7 +127,7 @@ describe( 'BorderControl', () => { it( 'should render color and style popover', async () => { const user = userEvent.setup(); const props = createProps(); - render( ); + await render( ); await openPopover( user ); const customColorPicker = getButton( /Custom color picker/ ); @@ -151,7 +152,7 @@ describe( 'BorderControl', () => { it( 'should render color and style popover header', async () => { const user = userEvent.setup(); const props = createProps( { showDropdownHeader: true } ); - render( ); + await render( ); await openPopover( user ); const headerLabel = screen.getByText( 'Border color' ); @@ -164,7 +165,7 @@ describe( 'BorderControl', () => { it( 'should not render style options when opted out of', async () => { const user = userEvent.setup(); const props = createProps( { enableStyle: false } ); - render( ); + await render( ); await openPopover( user ); const styleLabel = screen.queryByText( 'Style' ); @@ -181,18 +182,18 @@ describe( 'BorderControl', () => { describe( 'color and style picker aria labels', () => { describe( 'with style selection enabled', () => { - it( 'should include both color and style in label', () => { + it( 'should include both color and style in label', async () => { const props = createProps( { value: undefined } ); - render( ); + await render( ); expect( screen.getByLabelText( 'Border color and style picker.' ) ).toBeInTheDocument(); } ); - it( 'should correctly describe named color selection', () => { + it( 'should correctly describe named color selection', async () => { const props = createProps( { value: { color: '#72aee6' } } ); - render( ); + await render( ); expect( screen.getByLabelText( @@ -201,9 +202,9 @@ describe( 'BorderControl', () => { ).toBeInTheDocument(); } ); - it( 'should correctly describe custom color selection', () => { + it( 'should correctly describe custom color selection', async () => { const props = createProps( { value: { color: '#4b1d80' } } ); - render( ); + await render( ); expect( screen.getByLabelText( @@ -212,11 +213,11 @@ describe( 'BorderControl', () => { ).toBeInTheDocument(); } ); - it( 'should correctly describe named color and style selections', () => { + it( 'should correctly describe named color and style selections', async () => { const props = createProps( { value: { color: '#72aee6', style: 'dotted' }, } ); - render( ); + await render( ); expect( screen.getByLabelText( @@ -225,11 +226,11 @@ describe( 'BorderControl', () => { ).toBeInTheDocument(); } ); - it( 'should correctly describe custom color and style selections', () => { + it( 'should correctly describe custom color and style selections', async () => { const props = createProps( { value: { color: '#4b1d80', style: 'dashed' }, } ); - render( ); + await render( ); expect( screen.getByLabelText( @@ -240,24 +241,24 @@ describe( 'BorderControl', () => { } ); describe( 'with style selection disabled', () => { - it( 'should only include color in the label', () => { + it( 'should only include color in the label', async () => { const props = createProps( { value: undefined, enableStyle: false, } ); - render( ); + await render( ); expect( screen.getByLabelText( 'Border color picker.' ) ).toBeInTheDocument(); } ); - it( 'should correctly describe named color selection', () => { + it( 'should correctly describe named color selection', async () => { const props = createProps( { value: { color: '#72aee6' }, enableStyle: false, } ); - render( ); + await render( ); expect( screen.getByLabelText( @@ -266,12 +267,12 @@ describe( 'BorderControl', () => { ).toBeInTheDocument(); } ); - it( 'should correctly describe custom color selection', () => { + it( 'should correctly describe custom color selection', async () => { const props = createProps( { value: { color: '#4b1d80' }, enableStyle: false, } ); - render( ); + await render( ); expect( screen.getByLabelText( @@ -283,9 +284,9 @@ describe( 'BorderControl', () => { } ); describe( 'onChange handling', () => { - it( 'should update width with slider value', () => { + it( 'should update width with slider value', async () => { const props = createProps( { withSlider: true } ); - const { rerender } = render( ); + const { rerender } = await render( ); const slider = getSliderInput(); // As per [1], it is not currently possible to reasonably @@ -299,7 +300,7 @@ describe( 'BorderControl', () => { width: '5px', } ); - rerender( ); + await rerender( ); const widthInput = getWidthInput(); expect( widthInput.value ).toEqual( '5' ); @@ -308,7 +309,7 @@ describe( 'BorderControl', () => { it( 'should update color selection', async () => { const user = userEvent.setup(); const props = createProps(); - render( ); + await render( ); await openPopover( user ); await user.click( getColorOption( 'Green' ) ); @@ -321,7 +322,7 @@ describe( 'BorderControl', () => { it( 'should clear color selection when toggling swatch off', async () => { const user = userEvent.setup(); const props = createProps(); - render( ); + await render( ); await openPopover( user ); await user.click( getColorOption( 'Blue' ) ); @@ -334,7 +335,7 @@ describe( 'BorderControl', () => { it( 'should update style selection', async () => { const user = userEvent.setup(); const props = createProps(); - render( ); + await render( ); await openPopover( user ); await user.click( getButton( 'Dashed' ) ); @@ -347,7 +348,7 @@ describe( 'BorderControl', () => { it( 'should take no action when color and style popover is closed', async () => { const user = userEvent.setup(); const props = createProps( { showDropdownHeader: true } ); - render( ); + await render( ); await openPopover( user ); await user.click( getButton( 'Close border color' ) ); @@ -357,7 +358,7 @@ describe( 'BorderControl', () => { it( 'should reset color and style only when popover reset button clicked', async () => { const user = userEvent.setup(); const props = createProps(); - render( ); + await render( ); await openPopover( user ); await user.click( getButton( 'Reset' ) ); @@ -371,9 +372,9 @@ describe( 'BorderControl', () => { it( 'should sanitize border when width and color are undefined', async () => { const user = userEvent.setup(); const props = createProps(); - const { rerender } = render( ); + const { rerender } = await render( ); await user.clear( getWidthInput() ); - rerender( ); + await rerender( ); await openPopover( user ); await user.click( getColorOption( 'Blue' ) ); @@ -385,9 +386,9 @@ describe( 'BorderControl', () => { const props = createProps( { shouldSanitizeBorder: false, } ); - const { rerender } = render( ); + const { rerender } = await render( ); await user.clear( getWidthInput() ); - rerender( ); + await rerender( ); await openPopover( user ); await user.click( getColorOption( 'Blue' ) ); @@ -401,7 +402,7 @@ describe( 'BorderControl', () => { it( 'should clear color and set style to `none` when setting zero width', async () => { const user = userEvent.setup(); const props = createProps(); - render( ); + await render( ); await openPopover( user ); await user.click( getColorOption( 'Green' ) ); await user.click( getButton( 'Dotted' ) ); @@ -420,12 +421,12 @@ describe( 'BorderControl', () => { it( 'should reselect color and style selections when changing to non-zero width', async () => { const user = userEvent.setup(); const props = createProps(); - const { rerender } = render( ); + const { rerender } = await render( ); await openPopover( user ); await user.click( getColorOption( 'Green' ) ); - rerender( ); + await rerender( ); await user.click( getButton( 'Dotted' ) ); - rerender( ); + await rerender( ); const widthInput = getWidthInput(); await user.type( widthInput, '0', { initialSelectionStart: 0, @@ -446,7 +447,7 @@ describe( 'BorderControl', () => { it( 'should set a non-zero width when applying color to zero width border', async () => { const user = userEvent.setup(); const props = createProps( { value: undefined } ); - const { rerender } = render( ); + const { rerender } = await render( ); await openPopover( user ); await user.click( getColorOption( 'Yellow' ) ); @@ -458,7 +459,7 @@ describe( 'BorderControl', () => { await user.type( getWidthInput(), '0' ); - rerender( ); + await rerender( ); await openPopover( user ); await user.click( getColorOption( 'Green' ) ); @@ -475,7 +476,7 @@ describe( 'BorderControl', () => { value: undefined, shouldSanitizeBorder: false, } ); - const { rerender } = render( ); + const { rerender } = await render( ); await openPopover( user ); await user.click( getButton( 'Dashed' ) ); @@ -487,7 +488,7 @@ describe( 'BorderControl', () => { await user.type( getWidthInput(), '0' ); - rerender( ); + await rerender( ); await openPopover( user ); await user.click( getButton( 'Dotted' ) ); diff --git a/packages/components/src/box-control/test/index.tsx b/packages/components/src/box-control/test/index.tsx index 681e7721d0c13..6475c068e86b5 100644 --- a/packages/components/src/box-control/test/index.tsx +++ b/packages/components/src/box-control/test/index.tsx @@ -1,7 +1,8 @@ /** * External dependencies */ -import { fireEvent, render, screen } from '@testing-library/react'; +import { fireEvent, screen } from '@testing-library/react'; +import { render } from '@ariakit/test/react'; import userEvent from '@testing-library/user-event'; /** @@ -29,8 +30,8 @@ const Example = ( extraProps: Omit< BoxControlProps, 'onChange' > ) => { describe( 'BoxControl', () => { describe( 'Basic rendering', () => { - it( 'should render a box control input', () => { - render( {} } /> ); + it( 'should render a box control input', async () => { + await render( {} } /> ); expect( screen.getByRole( 'group', { name: 'Box Control' } ) @@ -43,7 +44,7 @@ describe( 'BoxControl', () => { it( 'should update values when interacting with input', async () => { const user = userEvent.setup(); - render( {} } /> ); + await render( {} } /> ); const input = screen.getByRole( 'textbox', { name: 'All sides' } ); @@ -53,8 +54,8 @@ describe( 'BoxControl', () => { expect( input ).toHaveValue( '100' ); } ); - it( 'should update input values when interacting with slider', () => { - render( {} } /> ); + it( 'should update input values when interacting with slider', async () => { + await render( {} } /> ); const slider = screen.getByRole( 'slider' ); @@ -68,7 +69,7 @@ describe( 'BoxControl', () => { it( 'should update slider values when interacting with input', async () => { const user = userEvent.setup(); - render( {} } /> ); + await render( {} } /> ); const input = screen.getByRole( 'textbox', { name: 'All sides', @@ -81,16 +82,16 @@ describe( 'BoxControl', () => { expect( screen.getByRole( 'slider' ) ).toHaveValue( '50' ); } ); - it( 'should render the number input with a default min value of 0', () => { - render( {} } /> ); + it( 'should render the number input with a default min value of 0', async () => { + await render( {} } /> ); const input = screen.getByRole( 'textbox', { name: 'All sides' } ); expect( input ).toHaveAttribute( 'min', '0' ); } ); - it( 'should pass down `inputProps` to the underlying number input', () => { - render( + it( 'should pass down `inputProps` to the underlying number input', async () => { + await render( {} } inputProps={ { min: 10, max: 50 } } @@ -108,7 +109,7 @@ describe( 'BoxControl', () => { it( 'should reset values when clicking Reset', async () => { const user = userEvent.setup(); - render( {} } /> ); + await render( {} } /> ); const input = screen.getByRole( 'textbox', { name: 'All sides', @@ -127,7 +128,7 @@ describe( 'BoxControl', () => { it( 'should reset values when clicking Reset, if controlled', async () => { const user = userEvent.setup(); - render( ); + await render( ); const input = screen.getByRole( 'textbox', { name: 'All sides', @@ -146,7 +147,7 @@ describe( 'BoxControl', () => { it( 'should reset values when clicking Reset, if controlled <-> uncontrolled state changes', async () => { const user = userEvent.setup(); - render( ); + await render( ); const input = screen.getByRole( 'textbox', { name: 'All sides', @@ -166,7 +167,7 @@ describe( 'BoxControl', () => { const user = userEvent.setup(); const spyChange = jest.fn(); - render( spyChange( v ) } /> ); + await render( spyChange( v ) } /> ); const input = screen.getByRole( 'textbox', { name: 'All sides', @@ -196,7 +197,7 @@ describe( 'BoxControl', () => { it( 'should update a single side value when unlinked', async () => { const user = userEvent.setup(); - render( ); + await render( ); await user.click( screen.getByRole( 'button', { name: 'Unlink sides' } ) @@ -224,7 +225,7 @@ describe( 'BoxControl', () => { it( 'should update a single side value when using slider unlinked', async () => { const user = userEvent.setup(); - render( ); + await render( ); await user.click( screen.getByRole( 'button', { name: 'Unlink sides' } ) @@ -252,7 +253,7 @@ describe( 'BoxControl', () => { it( 'should update a whole axis when value is changed when unlinked', async () => { const user = userEvent.setup(); - render( ); + await render( ); await user.click( screen.getByRole( 'button', { name: 'Unlink sides' } ) @@ -276,7 +277,7 @@ describe( 'BoxControl', () => { it( 'should update a whole axis using a slider when value is changed when unlinked', async () => { const user = userEvent.setup(); - render( ); + await render( ); await user.click( screen.getByRole( 'button', { name: 'Unlink sides' } ) @@ -300,7 +301,7 @@ describe( 'BoxControl', () => { it( 'should show "Mixed" label when sides have different values but are linked', async () => { const user = userEvent.setup(); - render( ); + await render( ); const unlinkButton = screen.getByRole( 'button', { name: 'Unlink sides', @@ -330,7 +331,7 @@ describe( 'BoxControl', () => { const user = userEvent.setup(); // Render control. - render( {} } /> ); + await render( {} } /> ); // Make unit selection on all input control. await user.selectOptions( @@ -362,7 +363,9 @@ describe( 'BoxControl', () => { const user = userEvent.setup(); // Render control. - const { rerender } = render( {} } /> ); + const { rerender } = await render( + {} } /> + ); // Make unit selection on all input control. await user.selectOptions( @@ -390,7 +393,7 @@ describe( 'BoxControl', () => { } ); // Rerender with individual side value & confirm unit is selected. - rerender( + await rerender( {} } /> ); @@ -414,7 +417,7 @@ describe( 'BoxControl', () => { const user = userEvent.setup(); const onChangeSpy = jest.fn(); - render( ); + await render( ); const valueInput = screen.getByRole( 'textbox', { name: 'All sides', @@ -443,7 +446,7 @@ describe( 'BoxControl', () => { const user = userEvent.setup(); const setState = jest.fn(); - render( ); + await render( ); await user.selectOptions( screen.getByRole( 'combobox', { diff --git a/packages/components/src/button/test/index.tsx b/packages/components/src/button/test/index.tsx index 8161e68c4e21b..091468e65a4c0 100644 --- a/packages/components/src/button/test/index.tsx +++ b/packages/components/src/button/test/index.tsx @@ -1,7 +1,8 @@ /** * External dependencies */ -import { render, screen } from '@testing-library/react'; +import { screen } from '@testing-library/react'; +import { render } from '@ariakit/test/react'; /** * WordPress dependencies @@ -21,8 +22,8 @@ jest.mock( '../../icon', () => () =>
); describe( 'Button', () => { describe( 'basic rendering', () => { - it( 'should render a button element with only one class', () => { - render( ); + await render( ); // Move focus to the button await press.Tab(); @@ -81,15 +82,15 @@ describe( 'Button', () => { expect( screen.getByRole( 'button' ) ).toHaveClass( 'has-text' ); } ); - it( 'should render a button element without has-text when children are not passed', () => { - render( ); + it( 'should render a button element without has-text when children are not passed', async () => { + await render( ); expect( screen.getByRole( 'button' ) ).not.toHaveClass( 'has-text' ); } ); - it( 'should render a button element without has-text when children are empty fragment', () => { - render( + it( 'should render a button element without has-text when children are empty fragment', async () => { + await render( @@ -99,8 +100,8 @@ describe( 'Button', () => { ); } ); - it( 'should render a button element without has-text when a button wrapped in Tooltip', () => { - render( + it( 'should render a button element without has-text when a button wrapped in Tooltip', async () => { + await render( ); @@ -208,7 +209,7 @@ describe( 'Button', () => { // Re-render the button, but this time change the settings so that it // shows a tooltip. - rerender( + await rerender( @@ -219,45 +220,45 @@ describe( 'Button', () => { expect( button ).toHaveFocus(); // Re-render the button, but stop showing a tooltip. - rerender( ); + await rerender( ); // The same button element that we referenced before should still be // in the document and have focus. expect( button ).toHaveFocus(); } ); - it( 'should add a disabled prop to the button', () => { + it( 'should add a disabled prop to the button', async () => { // eslint-disable-next-line no-restricted-syntax - render( @@ -427,7 +428,7 @@ describe( 'Button', () => { } ); it( 'should force showing the tooltip even if icon and children defined', async () => { - render( + await render( @@ -444,48 +445,48 @@ describe( 'Button', () => { } ); describe( 'using `aria-pressed` prop', () => { - it( 'should render a button element with is-pressed when `true`', () => { - render( }> Dropdown menu item @@ -94,7 +95,7 @@ describe( 'DropdownMenu', () => { describe( 'pointer and keyboard interactions', () => { it( 'should open and focus the menu when clicking the trigger', async () => { - render( + await render( Open dropdown }> Dropdown menu item @@ -115,7 +116,7 @@ describe( 'DropdownMenu', () => { } ); it( 'should open and focus the first item when pressing the arrow down key on the trigger', async () => { - render( + await render( Open dropdown }> First item Second item @@ -146,7 +147,7 @@ describe( 'DropdownMenu', () => { } ); it( 'should open and focus the first item when pressing the space key on the trigger', async () => { - render( + await render( Open dropdown }> First item Second item @@ -177,7 +178,7 @@ describe( 'DropdownMenu', () => { } ); it( 'should close when pressing the escape key', async () => { - render( + await render( Open dropdown }> Dropdown menu item @@ -206,7 +207,7 @@ describe( 'DropdownMenu', () => { } ); it( 'should close when clicking outside of the content', async () => { - render( + await render( Open dropdown } @@ -224,7 +225,7 @@ describe( 'DropdownMenu', () => { } ); it( 'should close when clicking on a menu item', async () => { - render( + await render( Open dropdown } @@ -242,7 +243,7 @@ describe( 'DropdownMenu', () => { } ); it( 'should not close when clicking on a menu item when the `hideOnClick` prop is set to `false`', async () => { - render( + await render( Open dropdown } @@ -262,7 +263,7 @@ describe( 'DropdownMenu', () => { } ); it( 'should not close when clicking on a disabled menu item', async () => { - render( + await render( Open dropdown } @@ -282,7 +283,7 @@ describe( 'DropdownMenu', () => { } ); it( 'should reveal submenu content when hovering over the submenu trigger', async () => { - render( + await render( Open dropdown } @@ -327,7 +328,7 @@ describe( 'DropdownMenu', () => { } ); it( 'should navigate menu items and subitems using the arrow, spacebar and enter keys', async () => { - render( + await render( Open dropdown } @@ -481,7 +482,7 @@ describe( 'DropdownMenu', () => { ); }; - render( ); + await render( ); // Open dropdown await click( @@ -534,7 +535,7 @@ describe( 'DropdownMenu', () => { it( 'should check radio items and keep the menu open when clicking (uncontrolled)', async () => { const onRadioValueChangeSpy = jest.fn(); - render( + await render( Open dropdown }> { ); }; - render( ); + await render( ); // Open dropdown await click( @@ -741,7 +742,7 @@ describe( 'DropdownMenu', () => { it( 'should check checkbox items and keep the menu open when clicking (uncontrolled)', async () => { const onCheckboxValueChangeSpy = jest.fn(); - render( + await render( Open dropdown }> { describe( 'modality', () => { it( 'should be modal by default', async () => { - render( + await render( <> Open dropdown }> Dropdown menu item @@ -885,7 +886,7 @@ describe( 'DropdownMenu', () => { } ); it( 'should not be modal when the `modal` prop is set to `false`', async () => { - render( + await render( <> Open dropdown } @@ -924,7 +925,7 @@ describe( 'DropdownMenu', () => { describe( 'items prefix and suffix', () => { it( 'should display a prefix on regular items', async () => { - render( + await render( Open dropdown }> Item prefix }> Dropdown menu item @@ -948,7 +949,7 @@ describe( 'DropdownMenu', () => { } ); it( 'should display a suffix on regular items', async () => { - render( + await render( Open dropdown }> Item suffix }> Dropdown menu item @@ -972,7 +973,7 @@ describe( 'DropdownMenu', () => { } ); it( 'should display a suffix on radio items', async () => { - render( + await render( Open dropdown }> { } ); it( 'should display a suffix on checkbox items', async () => { - render( + await render( Open dropdown }> { describe( 'typeahead', () => { it( 'should highlight matching item', async () => { - render( + await render( Open dropdown }> One Two @@ -1063,7 +1064,7 @@ describe( 'DropdownMenu', () => { } ); it( 'should keep previous focus when no matches are found', async () => { - render( + await render( Open dropdown }> One Two diff --git a/packages/components/src/dropdown-menu/test/index.tsx b/packages/components/src/dropdown-menu/test/index.tsx index 9bee9f2660508..65f950b0c43e1 100644 --- a/packages/components/src/dropdown-menu/test/index.tsx +++ b/packages/components/src/dropdown-menu/test/index.tsx @@ -1,7 +1,8 @@ /** * External dependencies */ -import { render, screen, waitFor, within } from '@testing-library/react'; +import { screen, waitFor, within } from '@testing-library/react'; +import { render } from '@ariakit/test/react'; import userEvent from '@testing-library/user-event'; /** @@ -16,15 +17,15 @@ import DropdownMenu from '..'; import MenuItem from '../../menu-item'; describe( 'DropdownMenu', () => { - it( 'should not render when neither controls nor children are assigned', () => { - render( ); + it( 'should not render when neither controls nor children are assigned', async () => { + await render( ); // The button toggle should not even be rendered expect( screen.queryByRole( 'button' ) ).not.toBeInTheDocument(); } ); - it( 'should not render when controls are empty and children is not specified', () => { - render( ); + it( 'should not render when controls are empty and children is not specified', async () => { + await render( ); // The button toggle should not even be rendered expect( screen.queryByRole( 'button' ) ).not.toBeInTheDocument(); @@ -56,7 +57,9 @@ describe( 'DropdownMenu', () => { }, ]; - render( ); + await render( + + ); // Move focus on the toggle button await user.tab(); @@ -76,7 +79,7 @@ describe( 'DropdownMenu', () => { it( 'should open menu when pressing arrow down on the toggle and the children prop is used to define menu items', async () => { const user = userEvent.setup(); - render( + await render( } diff --git a/packages/components/src/dropdown/test/index.tsx b/packages/components/src/dropdown/test/index.tsx index c737499c7fb28..99396546bf702 100644 --- a/packages/components/src/dropdown/test/index.tsx +++ b/packages/components/src/dropdown/test/index.tsx @@ -1,7 +1,8 @@ /** * External dependencies */ -import { render, screen, waitFor } from '@testing-library/react'; +import { screen, waitFor } from '@testing-library/react'; +import { render } from '@ariakit/test/react'; import userEvent from '@testing-library/user-event'; /** @@ -12,7 +13,7 @@ import Dropdown from '..'; describe( 'Dropdown', () => { it( 'should toggle the dropdown properly', async () => { const user = userEvent.setup(); - const { unmount } = render( + const { unmount } = await render( { it( 'should close the dropdown when calling onClose', async () => { const user = userEvent.setup(); - render( + await render( { const mockOnChange = jest.fn(); - render( ); + await render( ); const draggableArea = screen.getByRole( 'button' ); @@ -38,12 +39,12 @@ describe( 'FocalPointPicker', () => { expect( draggableArea ).toHaveFocus(); } ); - it( 'should stop a drag operation when focus is lost', () => { + it( 'should stop a drag operation when focus is lost', async () => { const mockOnDrag = jest.fn(); const mockOnDragEnd = jest.fn(); const mockOnChange = jest.fn(); - render( + await render( { } ); describe( 'drag gestures', () => { - it( 'should call onDragStart, onDrag, onDragEnd and onChange in that order', () => { + it( 'should call onDragStart, onDrag, onDragEnd and onChange in that order', async () => { const logs: Log[] = []; const eventLogger: EventLogger = ( name, args ) => logs.push( { name, args } ); @@ -80,7 +81,7 @@ describe( 'FocalPointPicker', () => { handlers[ name ] = ( ...all ) => eventLogger( name, all ); } ); - render( ); + await render( ); const dragArea = screen.getByRole( 'button' ); @@ -105,7 +106,7 @@ describe( 'FocalPointPicker', () => { const spyChange = jest.fn(); const spy = jest.fn(); - render( + await render( { } ); describe( 'controllability', () => { - it( 'should update value from props', () => { - const { rerender } = render( + it( 'should update value from props', async () => { + const { rerender } = await render( ); const xInput = screen.getByRole( 'spinbutton', { name: 'Focal point left position', } ) as HTMLButtonElement; - rerender( ); + await rerender( + + ); expect( xInput.value ).toBe( '93' ); } ); it( 'call onChange with the expected values', async () => { const user = userEvent.setup(); const spyChange = jest.fn(); - render( + await render( { } ); describe( 'value handling', () => { - it( 'should handle legacy string values', () => { + it( 'should handle legacy string values', async () => { const onChangeSpy = jest.fn(); - render( + await render( { describe( 'Basic rendering', () => { - it( 'should render', () => { - render( ); + it( 'should render', async () => { + await render( ); expect( screen.getByTestId( 'media' ) ).toBeVisible(); } ); } ); describe( 'Media types', () => { - it( 'should render a placeholder by default', () => { - render( ); + it( 'should render a placeholder by default', async () => { + await render( ); expect( screen.getByTestId( 'media' ) ).toHaveClass( 'components-focal-point-picker__media--placeholder' ); } ); - it( 'should render an video if src is a video file', () => { - const { rerender } = render( + it( 'should render an video if src is a video file', async () => { + const { rerender } = await render( ); expect( screen.getByTestId( 'media' ).tagName ).toBe( 'VIDEO' ); - rerender( ); + await rerender( + + ); expect( screen.getByTestId( 'media' ).tagName ).toBe( 'VIDEO' ); - rerender( ); + await rerender( + + ); expect( screen.getByTestId( 'media' ).tagName ).toBe( 'VIDEO' ); } ); - it( 'should render an image file, if not video', () => { - const { rerender } = render( + it( 'should render an image file, if not video', async () => { + const { rerender } = await render( ); expect( screen.getByTestId( 'media' ).tagName ).toBe( 'IMG' ); - rerender( ); + await rerender( + + ); expect( screen.getByTestId( 'media' ).tagName ).toBe( 'IMG' ); } ); diff --git a/packages/components/src/font-size-picker/test/index.tsx b/packages/components/src/font-size-picker/test/index.tsx index e7205e57eefaa..ed5dffd23247b 100644 --- a/packages/components/src/font-size-picker/test/index.tsx +++ b/packages/components/src/font-size-picker/test/index.tsx @@ -551,7 +551,7 @@ describe( 'FontSizePicker', () => { ); expect( screen.getByLabelText( 'Custom' ) ).toBeVisible(); - rerender( + await rerender( { ); expect( screen.getByLabelText( 'Custom' ) ).toBeVisible(); - rerender( + await rerender( { - it( 'should show an Icon Button and a hidden input', () => { - render( + it( 'should show an Icon Button and a hidden input', async () => { + await render( {} }> My Upload Button @@ -40,7 +41,7 @@ describe( 'FormFileUpload', () => { const onChange = jest.fn(); - render( + await render( My Upload Button @@ -65,7 +66,7 @@ describe( 'FormFileUpload', () => { const onChange = jest.fn(); - render( + await render( ( e.currentTarget.value = '' ) ) } onChange={ onChange } diff --git a/packages/components/src/form-toggle/test/index.tsx b/packages/components/src/form-toggle/test/index.tsx index b843ecc27c74b..cb31e36d04f9b 100644 --- a/packages/components/src/form-toggle/test/index.tsx +++ b/packages/components/src/form-toggle/test/index.tsx @@ -1,7 +1,8 @@ /** * External dependencies */ -import { render, screen } from '@testing-library/react'; +import { screen } from '@testing-library/react'; +import { render } from '@ariakit/test/react'; import userEvent from '@testing-library/user-event'; /** @@ -32,25 +33,27 @@ const ControlledFormToggle = ( { onChange }: FormToggleProps ) => { describe( 'FormToggle', () => { describe( 'basic rendering', () => { - it( 'should render a span element with an unchecked checkbox', () => { - const { container } = render( ); + it( 'should render a span element with an unchecked checkbox', async () => { + const { container } = await render( + + ); expect( getInput() ).not.toBeChecked(); expect( container ).toMatchSnapshot(); } ); - it( 'should render a checked checkbox when providing checked prop', () => { - render( ); + it( 'should render a checked checkbox when providing checked prop', async () => { + await render( ); expect( getInput() ).toBeChecked(); } ); - it( 'should render with an additional className', () => { - const { container: containerDefault } = render( + it( 'should render with an additional className', async () => { + const { container: containerDefault } = await render( ); - const { container: containerWithClassName } = render( + const { container: containerWithClassName } = await render( ); @@ -60,12 +63,12 @@ describe( 'FormToggle', () => { ); } ); - it( 'should render an id prop for the input checkbox', () => { - const { container: containerDefault } = render( + it( 'should render an id prop for the input checkbox', async () => { + const { container: containerDefault } = await render( ); - const { container: containerWithID } = render( + const { container: containerWithID } = await render( // Disabled because of our rule restricting literal IDs, preferring // `withInstanceId`. In this case, it's fine to use literal IDs. // eslint-disable-next-line no-restricted-syntax @@ -82,7 +85,7 @@ describe( 'FormToggle', () => { const user = userEvent.setup(); const onChange = jest.fn(); - render( ); + await render( ); const input = getInput(); diff --git a/packages/components/src/form-token-field/test/index.tsx b/packages/components/src/form-token-field/test/index.tsx index 961214a574c90..9eedcc979a319 100644 --- a/packages/components/src/form-token-field/test/index.tsx +++ b/packages/components/src/form-token-field/test/index.tsx @@ -4,12 +4,12 @@ * External dependencies */ import { - render, screen, within, getDefaultNormalizer, waitFor, } from '@testing-library/react'; +import { render } from '@ariakit/test/react'; import userEvent from '@testing-library/user-event'; import type { ComponentProps } from 'react'; @@ -125,7 +125,9 @@ describe( 'FormTokenField', () => { const onChangeSpy = jest.fn(); - render( ); + await render( + + ); const input = screen.getByRole( 'combobox' ); @@ -150,7 +152,9 @@ describe( 'FormTokenField', () => { const onChangeSpy = jest.fn(); - render( ); + await render( + + ); const input = screen.getByRole( 'combobox' ); @@ -166,7 +170,7 @@ describe( 'FormTokenField', () => { const onChangeSpy = jest.fn(); - const { rerender } = render( + const { rerender } = await render( ); @@ -178,7 +182,7 @@ describe( 'FormTokenField', () => { expect( onChangeSpy ).toHaveBeenCalledWith( [ 'dragon fruit' ] ); expectTokensToBeInTheDocument( [ 'dragon fruit' ] ); - rerender( + await rerender( { const onChangeSpy = jest.fn(); - const { rerender } = render( + const { rerender } = await render( ); @@ -222,7 +226,7 @@ describe( 'FormTokenField', () => { expect( onChangeSpy ).toHaveBeenCalledTimes( 0 ); expectTokensNotToBeInTheDocument( [ 'grapefruit' ] ); - rerender( + await rerender( { const onChangeSpy = jest.fn(); - render( ); + await render( + + ); const input = screen.getByRole( 'combobox' ); @@ -261,7 +267,7 @@ describe( 'FormTokenField', () => { const onChangeSpy = jest.fn(); - render( + await render( { const onChangeSpy = jest.fn(); - render( + await render( { const onChangeSpy = jest.fn(); - render( + await render( { const onChangeSpy = jest.fn(); - render( + await render( { const onChangeSpy = jest.fn(); - render( + await render( { const onChangeSpy = jest.fn(); - render( + await render( { ] ); } ); - it( "should add additional classnames passed via the `className` prop to the input element's 2nd level wrapper", () => { - render( ); + it( "should add additional classnames passed via the `className` prop to the input element's 2nd level wrapper", async () => { + await render( + + ); const input = screen.getByRole( 'combobox' ); @@ -521,14 +529,14 @@ describe( 'FormTokenField', () => { ); } ); - it( 'should label the input correctly via the `label` prop', () => { - const { rerender } = render( ); + it( 'should label the input correctly via the `label` prop', async () => { + const { rerender } = await render( ); expect( screen.getByRole( 'combobox', { name: 'Add item' } ) ).toBeVisible(); - rerender( ); + await rerender( ); expect( screen.getByRole( 'combobox', { name: 'Test label' } ) @@ -540,7 +548,7 @@ describe( 'FormTokenField', () => { const onFocusSpy = jest.fn(); - render( ); + await render( ); const input = screen.getByRole( 'combobox' ); @@ -562,7 +570,7 @@ describe( 'FormTokenField', () => { const onInputChangeSpy = jest.fn(); - render( + await render( ); @@ -579,14 +587,14 @@ describe( 'FormTokenField', () => { ); } ); - it( 'should show extra instructions when the `__experimentalShowHowTo` prop is set to `true`', () => { + it( 'should show extra instructions when the `__experimentalShowHowTo` prop is set to `true`', async () => { const instructionsTokenizeSpace = 'Separate with commas, spaces, or the Enter key.'; const instructionsDefault = 'Separate with commas or the Enter key.'; // The __experimentalShowHowTo prop is `true` by default - const { rerender } = render( ); + const { rerender } = await render( ); expect( screen.getByText( instructionsDefault ) ).toBeVisible(); @@ -595,7 +603,7 @@ describe( 'FormTokenField', () => { screen.getByRole( 'combobox' ) ).toHaveAccessibleDescription( instructionsDefault ); - rerender( ); + await rerender( ); expect( screen.getByText( instructionsTokenizeSpace ) @@ -606,7 +614,7 @@ describe( 'FormTokenField', () => { screen.getByRole( 'combobox' ) ).toHaveAccessibleDescription( instructionsTokenizeSpace ); - rerender( + await rerender( { const onChangeSpy = jest.fn(); - render( + await render( { const onChangeSpy = jest.fn(); - render( + await render( { } ); describe( 'suggestions', () => { - it( 'should not render suggestions in its default state', () => { - render( + it( 'should not render suggestions in its default state', async () => { + await render( @@ -705,7 +713,7 @@ describe( 'FormTokenField', () => { const suggestions = [ 'Cobalt', 'Blue', 'Octane' ]; - render( + await render( <> { const suggestions = [ 'Green', 'Emerald', 'Seaweed' ]; - render( + await render( <> { const suggestions = [ 'Green', 'Emerald', 'Seaweed' ]; - render( + await render( <> { const suggestions = [ 'Green', 'Emerald', 'Seaweed' ]; - render( + await render( <> { const suggestions = [ 'White', 'Pearl', 'Alabaster' ]; - render( ); + await render( + + ); const input = screen.getByRole( 'combobox' ); @@ -858,7 +868,9 @@ describe( 'FormTokenField', () => { const suggestions = [ 'Yellow', 'Canary', 'Gold', 'Blonde' ]; - render( ); + await render( + + ); const input = screen.getByRole( 'combobox' ); @@ -883,7 +895,7 @@ describe( 'FormTokenField', () => { const suggestions = [ 'Green', 'Emerald', 'Seaweed' ]; - render( + await render( { 'Neon', ]; - render( + await render( { const suggestions = [ 'Tiger', 'Tangerine', 'Orange' ]; - render( + await render( { const suggestions = [ 'Black', 'Ash', 'Onyx', 'Ebony' ]; - render( + await render( { const suggestions = [ 'One', 'Two', 'Three' ]; - render( ); + await render( + + ); const input = screen.getByRole( 'combobox' ); @@ -1110,7 +1124,7 @@ describe( 'FormTokenField', () => { const suggestions = [ 'One', 'Two', 'Three' ]; - render( + await render( @@ -1139,7 +1153,7 @@ describe( 'FormTokenField', () => { const suggestions = [ 'One', 'Two', 'Three' ]; - render( + await render( @@ -1168,7 +1182,9 @@ describe( 'FormTokenField', () => { const suggestions = [ 'Cinnamon', 'Tawny', 'Mocha' ]; - render( ); + await render( + + ); const input = screen.getByRole( 'combobox' ); @@ -1200,7 +1216,7 @@ describe( 'FormTokenField', () => { 'Abnormality', ]; - const { rerender } = render( + const { rerender } = await render( ); @@ -1216,7 +1232,7 @@ describe( 'FormTokenField', () => { suggestions ); - rerender( + await rerender( { it( 'should match the search text against the unescaped values of suggestions with special characters (including spaces)', async () => { const user = userEvent.setup(); - render( + await render( { const suggestions = [ 'Aluminum', 'Silver', 'Bronze' ]; - const { rerender } = render( ); + const { rerender } = await render( ); // Type "sil", but there are no suggestions. await user.type( screen.getByRole( 'combobox' ), 'sil' ); @@ -1285,7 +1301,9 @@ describe( 'FormTokenField', () => { // When suggestions change, the "sil" text is matched against the new // suggestions, which results in the "Silver" suggestion being shown. - rerender( ); + await rerender( + + ); expectVisibleSuggestionsToBe( screen.getByRole( 'listbox' ), [ 'Silver', @@ -1297,7 +1315,7 @@ describe( 'FormTokenField', () => { const suggestions = [ 'Walnut', 'Hazelnut', 'Pecan' ]; - const { rerender } = render( + const { rerender } = await render( ); @@ -1319,7 +1337,7 @@ describe( 'FormTokenField', () => { } ) ).not.toBeInTheDocument(); - rerender( + await rerender( { const suggestions = [ 'Wood', 'Stone', 'Metal' ]; - render( + await render( ( @@ -1369,7 +1387,7 @@ describe( 'FormTokenField', () => { const onChangeSpy = jest.fn(); - const { rerender } = render( + const { rerender } = await render( { expect( onChangeSpy ).not.toHaveBeenCalled(); - rerender( + await rerender( { const onMouseEnterSpy = jest.fn(); const onMouseLeaveSpy = jest.fn(); - render( + await render( { expect( onMouseLeaveSpy ).toHaveBeenCalledTimes( 1 ); } ); - it( 'should add an accessible `title` to a token when specified', () => { - render( + it( 'should add an accessible `title` to a token when specified', async () => { + await render( { it( 'should be still used to filter out duplicate suggestions', async () => { const user = userEvent.setup(); - render( + await render( { const onChangeSpy = jest.fn(); - const { rerender } = render( + const { rerender } = await render( { expect( onChangeSpy ).toHaveBeenCalledTimes( 1 ); expectTokensToBeInTheDocument( [ 'potato', 'carrot' ] ); - rerender( + await rerender( { const onChangeSpy = jest.fn(); - const { rerender } = render( + const { rerender } = await render( { 'small shirt', ] ); - rerender( + await rerender( { const suggestions = [ 'Expensive food', 'Free food' ]; - render( + await render( { const onChangeSpy = jest.fn(); - const { rerender } = render( + const { rerender } = await render( { expectTokensToBeInTheDocument( [ 'dark blue', 'dark green' ] ); - rerender( + await rerender( { const suggestions = [ 'Hot coffee', 'Hot tea' ]; - render( + await render( { } ); it( 'should allow to pass a function that renders tokens with escaped special characters correctly', async () => { - render( + await render( { // worth testing, so we can be sure that token values with // dangerous characters in them don't have these characters carried // through unescaped to the HTML. - render( + await render( { const startsWithCapitalLetter = ( tokenText: string ) => /^[A-Z]/.test( tokenText ); - const { rerender } = render( + const { rerender } = await render( ); @@ -1804,7 +1822,7 @@ describe( 'FormTokenField', () => { expect( onChangeSpy ).toHaveBeenCalledWith( [ 'cherry' ] ); expectTokensToBeInTheDocument( [ 'cherry' ] ); - rerender( + await rerender( { const onChangeSpy = jest.fn(); - render( + await render( { ] ); } ); - it( "should not affect the number of tokens set via the `value` prop (ie. not caused by tokenizing the user's input)", () => { - render( + it( "should not affect the number of tokens set via the `value` prop (ie. not caused by tokenizing the user's input)", async () => { + await render( { const onChangeSpy = jest.fn(); - const { rerender } = render( + const { rerender } = await render( ); @@ -1919,7 +1937,7 @@ describe( 'FormTokenField', () => { expectTokensToBeInTheDocument( [ 'cube', 'sphere', 'cylinder' ] ); // Add a `maxLength` after some tokens have already been added. - rerender( + await rerender( { const onChangeSpy = jest.fn(); - const { rerender } = render( + const { rerender } = await render( ); @@ -1958,7 +1976,7 @@ describe( 'FormTokenField', () => { expect( onChangeSpy ).toHaveBeenCalledWith( [ 'sun' ] ); expectTokensToBeInTheDocument( [ 'sun' ] ); - rerender( + await rerender( ); @@ -1974,7 +1992,7 @@ describe( 'FormTokenField', () => { const onChangeSpy = jest.fn(); - render( + await render( { it( 'should announce to assistive technology the addition of a new token', async () => { const user = userEvent.setup(); - render( ); + await render( ); const input = screen.getByRole( 'combobox' ); @@ -2034,7 +2052,9 @@ describe( 'FormTokenField', () => { it( 'should announce to assistive technology the addition of a new token with a custom message', async () => { const user = userEvent.setup(); - render( ); + await render( + + ); const input = screen.getByRole( 'combobox' ); @@ -2050,7 +2070,9 @@ describe( 'FormTokenField', () => { it( 'should announce to assistive technology the removal of a token', async () => { const user = userEvent.setup(); - render( ); + await render( + + ); const input = screen.getByRole( 'combobox' ); @@ -2065,7 +2087,7 @@ describe( 'FormTokenField', () => { it( 'should announce to assistive technology the removal of a token with a custom message', async () => { const user = userEvent.setup(); - render( + await render( { it( 'should announce to assistive technology the failure of a potential token to pass validation', async () => { const user = userEvent.setup(); - render( + await render( false } /> @@ -2105,7 +2127,7 @@ describe( 'FormTokenField', () => { it( 'should announce to assistive technology the failure of a potential token to pass validation with a custom message', async () => { const user = userEvent.setup(); - render( + await render( false } messages={ customMessages } @@ -2126,7 +2148,7 @@ describe( 'FormTokenField', () => { it( 'should announce to assistive technology the result of the matching of the search text against the list of suggestions', async () => { const user = userEvent.setup(); - render( + await render( @@ -2169,7 +2191,7 @@ describe( 'FormTokenField', () => { } ); it( 'should update the label for the "delete" button of a token', async () => { - render( + await render( { const suggestions = [ 'Pine', 'Pistachio', 'Sage' ]; - render( + await render( <> diff --git a/packages/components/src/grid/test/grid.tsx b/packages/components/src/grid/test/grid.tsx index 150dac578c80a..e9d0f47db9c20 100644 --- a/packages/components/src/grid/test/grid.tsx +++ b/packages/components/src/grid/test/grid.tsx @@ -1,7 +1,8 @@ /** * External dependencies */ -import { render, screen } from '@testing-library/react'; +import { screen } from '@testing-library/react'; +import { render } from '@ariakit/test/react'; /** * Internal dependencies diff --git a/packages/components/src/guide/test/index.tsx b/packages/components/src/guide/test/index.tsx index eff2886cb038b..febf0da0fc08b 100644 --- a/packages/components/src/guide/test/index.tsx +++ b/packages/components/src/guide/test/index.tsx @@ -1,7 +1,8 @@ /** * External dependencies */ -import { render, screen, within } from '@testing-library/react'; +import { screen, within } from '@testing-library/react'; +import { render } from '@ariakit/test/react'; import userEvent from '@testing-library/user-event'; /** @@ -15,13 +16,13 @@ const defaultProps = { }; describe( 'Guide', () => { - it( 'renders nothing when there are no pages', () => { - render( ); + it( 'renders nothing when there are no pages', async () => { + await render( ); expect( screen.queryByRole( 'dialog' ) ).not.toBeInTheDocument(); } ); - it( 'renders one page at a time', () => { - render( + it( 'renders one page at a time', async () => { + await render( { expect( screen.queryByText( 'Page 2' ) ).not.toBeInTheDocument(); } ); - it( 'hides back button and shows forward button on the first page', () => { - render( + it( 'hides back button and shows forward button on the first page', async () => { + await render( { it( 'shows back button and shows finish button on the last page', async () => { const user = userEvent.setup(); - render( + await render( { ).toBeVisible(); } ); - it( "doesn't display the page control if there is only one page", () => { - render( + it( "doesn't display the page control if there is only one page", async () => { + await render( Page 1

} ] } @@ -100,7 +101,7 @@ describe( 'Guide', () => { it( 'calls onFinish when the finish button is clicked', async () => { const user = userEvent.setup(); const onFinish = jest.fn(); - render( + await render( { it( 'calls onFinish when the modal is closed', async () => { const user = userEvent.setup(); const onFinish = jest.fn(); - render( + await render( { } ); describe( 'page navigation', () => { - it( 'renders an empty list when there are no pages', () => { - render( ); + it( 'renders an empty list when there are no pages', async () => { + await render( ); expect( screen.queryByRole( 'list', { name: 'Guide controls', @@ -143,8 +144,8 @@ describe( 'Guide', () => { ).not.toBeInTheDocument(); } ); - it( 'renders a button for each page', () => { - render( + it( 'renders a button for each page', async () => { + await render( { it( 'sets the current page when a button is clicked', async () => { const user = userEvent.setup(); - render( + await render( { it( 'allows navigating through the pages with the left and right arrows', async () => { const user = userEvent.setup(); - render( + await render( { removeAllFilters( hookName, 'test/enhanced-component-spy-2' ); } ); - it( 'should display original component when no filters applied', () => { + it( 'should display original component when no filters applied', async () => { const EnhancedComponent = withFilters( hookName )( MyComponent ); - const { container } = render( ); + const { container } = await render( ); expect( container ).toMatchSnapshot(); } ); - it( 'should display a component overridden by the filter', () => { + it( 'should display a component overridden by the filter', async () => { const OverriddenComponent = () =>
Overridden component
; addFilter( 'EnhancedComponent', @@ -42,12 +43,12 @@ describe( 'withFilters', () => { ); const EnhancedComponent = withFilters( hookName )( MyComponent ); - const { container } = render( ); + const { container } = await render( ); expect( container ).toMatchSnapshot(); } ); - it( 'should display two components composed by the filter', () => { + it( 'should display two components composed by the filter', async () => { const ComposedComponent = () =>
Composed component
; addFilter( hookName, @@ -61,7 +62,7 @@ describe( 'withFilters', () => { ); const EnhancedComponent = withFilters( hookName )( MyComponent ); - const { container } = render( ); + const { container } = await render( ); expect( container ).toMatchSnapshot(); } ); @@ -79,7 +80,7 @@ describe( 'withFilters', () => { ); const EnhancedComponent = withFilters( hookName )( SpiedComponent ); - const { container } = render( ); + const { container } = await render( ); await waitFor( () => expect( SpiedComponent ).toHaveBeenCalledTimes( 1 ) @@ -91,7 +92,7 @@ describe( 'withFilters', () => { const SpiedComponent = jest.fn( () =>
Spied component
); const EnhancedComponent = withFilters( hookName )( SpiedComponent ); - const { container } = render( ); + const { container } = await render( ); SpiedComponent.mockClear(); @@ -115,7 +116,7 @@ describe( 'withFilters', () => { const SpiedComponent = jest.fn( () =>
Spied component
); const EnhancedComponent = withFilters( hookName )( SpiedComponent ); - const { container } = render( ); + const { container } = await render( ); SpiedComponent.mockClear(); @@ -147,7 +148,7 @@ describe( 'withFilters', () => { it( 'should re-render component twice when new filter added and removed in two different animation frames', async () => { const SpiedComponent = jest.fn( () =>
Spied component
); const EnhancedComponent = withFilters( hookName )( SpiedComponent ); - const { container } = render( ); + const { container } = await render( ); SpiedComponent.mockClear(); @@ -183,7 +184,7 @@ describe( 'withFilters', () => { ); - const { container } = render( ); + const { container } = await render( ); SpiedComponent.mockClear(); diff --git a/packages/components/src/higher-order/with-focus-outside/test/index.tsx b/packages/components/src/higher-order/with-focus-outside/test/index.tsx index a53a1cf11298d..e4a50e4c9dbad 100644 --- a/packages/components/src/higher-order/with-focus-outside/test/index.tsx +++ b/packages/components/src/higher-order/with-focus-outside/test/index.tsx @@ -1,7 +1,8 @@ /** * External dependencies */ -import { render, screen, waitFor } from '@testing-library/react'; +import { screen, waitFor } from '@testing-library/react'; +import { render } from '@ariakit/test/react'; import userEvent from '@testing-library/user-event'; /** @@ -58,7 +59,7 @@ describe( 'withFocusOutside', () => { } ); it( 'should not call handler if focus shifts to element within component', async () => { - render( ); + await render( ); const input = screen.getByRole( 'textbox' ); const button = screen.getByRole( 'button' ); @@ -72,7 +73,7 @@ describe( 'withFocusOutside', () => { it( 'should not call handler if focus transitions via click to button', async () => { const user = userEvent.setup(); - render( ); + await render( ); const input = screen.getByRole( 'textbox' ); const button = screen.getByRole( 'button' ); @@ -84,7 +85,7 @@ describe( 'withFocusOutside', () => { } ); it( 'should call handler if focus doesn’t shift to element within component', async () => { - render( ); + await render( ); const input = screen.getByRole( 'textbox' ); input.focus(); @@ -94,7 +95,7 @@ describe( 'withFocusOutside', () => { } ); it( 'should not call handler if focus shifts outside the component when the document does not have focus', async () => { - render( ); + await render( ); // Force document.hasFocus() to return false to simulate the window/document losing focus // See https://developer.mozilla.org/en-US/docs/Web/API/Document/hasFocus. @@ -108,7 +109,7 @@ describe( 'withFocusOutside', () => { } ); it( 'should cancel check when unmounting while queued', async () => { - const { rerender } = render( + const { rerender } = await render( ); @@ -116,7 +117,7 @@ describe( 'withFocusOutside', () => { input.focus(); input.blur(); - rerender(
); + await rerender(
); await waitFor( () => expect( onFocusOutside ).not.toHaveBeenCalled() ); } ); diff --git a/packages/components/src/higher-order/with-focus-return/test/index.tsx b/packages/components/src/higher-order/with-focus-return/test/index.tsx index 74e7b58b8de18..694a6adf3c0cc 100644 --- a/packages/components/src/higher-order/with-focus-return/test/index.tsx +++ b/packages/components/src/higher-order/with-focus-return/test/index.tsx @@ -1,7 +1,8 @@ /** * External dependencies */ -import { render, screen } from '@testing-library/react'; +import { screen } from '@testing-library/react'; +import { render } from '@ariakit/test/react'; import userEvent from '@testing-library/user-event'; /** @@ -45,30 +46,30 @@ describe( 'withFocusReturn()', () => { activeElement.blur(); } ); - it( 'should render a basic Test component inside the HOC', () => { - render( ); + it( 'should render a basic Test component inside the HOC', async () => { + await render( ); expect( screen.getByTestId( 'test-element' ) ).toBeVisible(); } ); - it( 'should pass own props through to the wrapped element', () => { - render( ); + it( 'should pass own props through to the wrapped element', async () => { + await render( ); expect( screen.getByTestId( 'test-element' ) ).toHaveClass( 'test' ); } ); - it( 'should not pass any withFocusReturn context props through to the wrapped element', () => { - render( ); + it( 'should not pass any withFocusReturn context props through to the wrapped element', async () => { + await render( ); expect( screen.getByTestId( 'test-element' ) ).not.toHaveAttribute( 'data-focus-history' ); } ); - it( 'should not switch focus back to the bound focus element', () => { - const { unmount } = render( , { + it( 'should not switch focus back to the bound focus element', async () => { + const { unmount } = await render( , { container: document.body.appendChild( document.createElement( 'div' ) ), @@ -86,7 +87,7 @@ describe( 'withFocusReturn()', () => { it( 'should switch focus back when unmounted while having focus', async () => { const user = userEvent.setup(); - const { unmount } = render( , { + const { unmount } = await render( , { container: document.body.appendChild( document.createElement( 'div' ) ), diff --git a/packages/components/src/higher-order/with-notices/test/index.tsx b/packages/components/src/higher-order/with-notices/test/index.tsx index 4b34da40838ee..c254cc61dd7a0 100644 --- a/packages/components/src/higher-order/with-notices/test/index.tsx +++ b/packages/components/src/higher-order/with-notices/test/index.tsx @@ -3,12 +3,12 @@ */ import { act, - render, fireEvent, screen, waitForElementToBeRemoved, within, } from '@testing-library/react'; +import { render } from '@ariakit/test/react'; /** * WordPress dependencies @@ -89,9 +89,9 @@ describe( 'withNotices operations', () => { return ; }; - it( 'should create notices with createNotice', () => { + it( 'should create notices with createNotice', async () => { const message = 'Aló!'; - const { container } = render( ); + const { container } = await render( ); const { getByText } = within( container ); act( () => { handle.current.createNotice( { content: message } ); @@ -99,9 +99,9 @@ describe( 'withNotices operations', () => { expect( getByText( message ) ).toBeInTheDocument(); } ); - it( 'should create notices of error status with createErrorNotice', () => { + it( 'should create notices of error status with createErrorNotice', async () => { const message = 'can’t touch this'; - const { container } = render( ); + const { container } = await render( ); const { getByText } = within( container ); act( () => { handle.current.createErrorNotice( message ); @@ -112,7 +112,7 @@ describe( 'withNotices operations', () => { it( 'should remove a notice with removeNotice', async () => { const notice = { id: 'so real', content: 'so why can’t I touch it?' }; - const { container } = render( ); + const { container } = await render( ); const { getByText } = within( container ); act( () => { handle.current.createNotice( notice ); @@ -129,7 +129,9 @@ describe( 'withNotices operations', () => { it( 'should remove all notices with removeAllNotices', async () => { const messages = [ 'Aló!', 'hu dis?', 'Otis' ]; const notices = noticesFrom( messages ); - const { container } = render( ); + const { container } = await render( + + ); const { getByText } = within( container ); expect( await waitForElementToBeRemoved( () => { @@ -144,15 +146,15 @@ describe( 'withNotices operations', () => { } ); describe( 'withNotices rendering', () => { - it( 'should display the original component given no notices', () => { - const { container } = render( ); + it( 'should display the original component given no notices', async () => { + const { container } = await render( ); expect( container.innerHTML ).toBe( `
${ content }
` ); } ); it( 'should display notices with functioning dismissal triggers', async () => { const messages = [ 'Aló!', 'hu dis?', 'Otis' ]; const notices = noticesFrom( messages ); - const { container } = render( + const { container } = await render( ); const [ buttonRemoveFirst ] = diff --git a/packages/components/src/higher-order/with-spoken-messages/test/index.tsx b/packages/components/src/higher-order/with-spoken-messages/test/index.tsx index b4d37eaa84096..d9b3fe0d839b0 100644 --- a/packages/components/src/higher-order/with-spoken-messages/test/index.tsx +++ b/packages/components/src/higher-order/with-spoken-messages/test/index.tsx @@ -1,7 +1,8 @@ /** * External dependencies */ -import { render } from '@testing-library/react'; + +import { render } from '@ariakit/test/react'; /** * Internal dependencies @@ -9,7 +10,7 @@ import { render } from '@testing-library/react'; import withSpokenMessages from '../'; describe( 'withSpokenMessages', () => { - it( 'should generate speak and debouncedSpeak props', () => { + it( 'should generate speak and debouncedSpeak props', async () => { const testSpeak = jest.fn(); const testDebouncedSpeak = jest.fn(); const isFunction = ( maybeFunc: any ) => @@ -21,7 +22,7 @@ describe( 'withSpokenMessages', () => { return
; } ); - render( ); + await render( ); // Unrendered element. expect( testSpeak ).toHaveBeenCalledWith( true ); diff --git a/packages/components/src/icon/test/index.tsx b/packages/components/src/icon/test/index.tsx index fd9c1650fb3b5..cf179faa6e91f 100644 --- a/packages/components/src/icon/test/index.tsx +++ b/packages/components/src/icon/test/index.tsx @@ -1,7 +1,8 @@ /** * External dependencies */ -import { render, screen } from '@testing-library/react'; +import { screen } from '@testing-library/react'; +import { render } from '@ariakit/test/react'; /** * WordPress dependencies @@ -22,22 +23,22 @@ describe( 'Icon', () => { ); - it( 'renders nothing when icon omitted', () => { - render( ); + it( 'renders nothing when icon omitted', async () => { + await render( ); expect( screen.queryByTestId( testId ) ).not.toBeInTheDocument(); } ); - it( 'renders a dashicon by slug', () => { - render( ); + it( 'renders a dashicon by slug', async () => { + await render( ); expect( screen.getByTestId( testId ) ).toHaveClass( 'dashicons-format-image' ); } ); - it( 'renders a dashicon with custom size', () => { - render( + it( 'renders a dashicon with custom size', async () => { + await render( ); @@ -46,34 +47,34 @@ describe( 'Icon', () => { expect( screen.getByTestId( testId ) ).toHaveStyle( 'font-size:10px' ); } ); - it( 'renders a function', () => { - render( } /> ); + it( 'renders a function', async () => { + await render( } /> ); expect( screen.getByTestId( testId ) ).toBeVisible(); } ); - it( 'renders an element', () => { - render( } /> ); + it( 'renders an element', async () => { + await render( } /> ); expect( screen.getByTestId( testId ) ).toBeVisible(); } ); - it( 'renders an svg element', () => { - render( ); + it( 'renders an svg element', async () => { + await render( ); expect( screen.getByTestId( testId ) ).toBeVisible(); } ); - it( 'renders an svg element with a default width and height of 24', () => { - render( ); + it( 'renders an svg element with a default width and height of 24', async () => { + await render( ); const icon = screen.getByTestId( testId ); expect( icon ).toHaveAttribute( 'width', '24' ); expect( icon ).toHaveAttribute( 'height', '24' ); } ); - it( 'renders an svg element and override its width and height', () => { - render( + it( 'renders an svg element and override its width and height', async () => { + await render( { expect( icon ).toHaveAttribute( 'height', '32' ); } ); - it( 'renders an svg element and does not override width and height if already specified', () => { - render( ); + it( 'renders an svg element and does not override width and height if already specified', async () => { + await render( + + ); const icon = screen.getByTestId( testId ); expect( icon ).toHaveAttribute( 'width', '32' ); expect( icon ).toHaveAttribute( 'height', '32' ); } ); - it( 'renders a component', () => { + it( 'renders a component', async () => { const MyComponent = () => ( ); - render( ); + await render( ); expect( screen.getByTestId( testId ) ).toHaveClass( className ); } ); diff --git a/packages/components/src/input-control/test/index.js b/packages/components/src/input-control/test/index.js index ace3086c388c8..8a33c459a2861 100644 --- a/packages/components/src/input-control/test/index.js +++ b/packages/components/src/input-control/test/index.js @@ -1,7 +1,8 @@ /** * External dependencies */ -import { render, screen } from '@testing-library/react'; +import { screen } from '@testing-library/react'; +import { render } from '@ariakit/test/react'; import userEvent from '@testing-library/user-event'; /** @@ -22,39 +23,41 @@ describe( 'InputControl', () => { ); describe( 'Basic rendering', () => { - it( 'should render', () => { - render( ); + it( 'should render', async () => { + await render( ); const input = getInput(); expect( input ).toBeTruthy(); } ); - it( 'should render with specified type', () => { - render( ); + it( 'should render with specified type', async () => { + await render( ); const input = getInput(); expect( input ).toHaveAttribute( 'type', 'number' ); } ); - it( 'should render label', () => { - render( ); + it( 'should render label', async () => { + await render( ); const input = screen.getByText( 'Hello' ); expect( input ).toBeInTheDocument(); } ); - it( 'should render help text as description', () => { - render( ); + it( 'should render help text as description', async () => { + await render( ); expect( screen.getByRole( 'textbox', { description: 'My help text' } ) ).toBeInTheDocument(); } ); - it( 'should still render help as aria-describedby when not plain text', () => { - render( My help text } /> ); + it( 'should still render help as aria-describedby when not plain text', async () => { + await render( + My help text } /> + ); const input = screen.getByRole( 'textbox' ); const help = screen.getByRole( 'link', { name: 'My help text' } ); @@ -70,7 +73,7 @@ describe( 'InputControl', () => { it( 'should focus its input on mousedown events', async () => { const user = await userEvent.setup(); const spy = jest.fn(); - render( ); + await render( ); const target = getInput(); // Hovers the input and presses (without releasing) primary button. @@ -87,7 +90,7 @@ describe( 'InputControl', () => { it( 'should update value onChange', async () => { const user = await userEvent.setup(); const spy = jest.fn(); - render( + await render( spy( v ) } /> ); const input = getInput(); @@ -131,7 +134,7 @@ describe( 'InputControl', () => { /> ); }; - render( ); + await render( ); const input = getInput(); await user.type( input, '2' ); @@ -154,20 +157,22 @@ describe( 'InputControl', () => { expect( spy ).toHaveBeenCalledTimes( 1 ); } ); - it( 'should change back to initial value prop, if controlled', () => { + it( 'should change back to initial value prop, if controlled', async () => { const spy = jest.fn(); - const { rerender } = render( + const { rerender } = await render( ); const input = getInput(); // Updating the value. - rerender( ); + await rerender( ); expect( input ).toHaveValue( 'New' ); // Change it back to the original value. - rerender( ); + await rerender( + + ); expect( input ).toHaveValue( 'Original' ); expect( spy ).toHaveBeenCalledTimes( 0 ); @@ -176,7 +181,7 @@ describe( 'InputControl', () => { it( 'should not commit value until blurred when isPressEnterToChange is true', async () => { const user = await userEvent.setup(); const spy = jest.fn(); - render( + await render( spy( v ) } @@ -196,7 +201,7 @@ describe( 'InputControl', () => { it( 'should commit value when blurred if value is invalid', async () => { const user = await userEvent.setup(); const spyChange = jest.fn(); - render( + await render( spyChange( v ) } diff --git a/packages/components/src/isolated-event-container/test/index.tsx b/packages/components/src/isolated-event-container/test/index.tsx index a914527b937ff..ae3f1e5bd1aad 100644 --- a/packages/components/src/isolated-event-container/test/index.tsx +++ b/packages/components/src/isolated-event-container/test/index.tsx @@ -1,7 +1,8 @@ /** * External dependencies */ -import { render, screen, within } from '@testing-library/react'; +import { screen, within } from '@testing-library/react'; +import { render } from '@ariakit/test/react'; import userEvent from '@testing-library/user-event'; /** @@ -13,7 +14,7 @@ describe( 'IsolatedEventContainer', () => { it( 'should pass props to container', async () => { const user = userEvent.setup(); const clickHandler = jest.fn(); - render( + await render( { } ); it( 'should render children', async () => { - render( + await render(

Child

@@ -47,7 +48,7 @@ describe( 'IsolatedEventContainer', () => { const mousedownHandler = jest.fn(); const keydownHandler = jest.fn(); - render( + await render( } onRequestClose={ noop } @@ -323,7 +324,7 @@ describe( 'Modal', () => { it( 'should focus the Modal dialog by default when `focusOnMount` prop is not provided', async () => { const user = userEvent.setup(); - render( ); + await render( ); const opener = screen.getByRole( 'button', { name: 'Toggle Modal', @@ -337,7 +338,7 @@ describe( 'Modal', () => { it( 'should focus the Modal dialog when `true` passed as value for `focusOnMount` prop', async () => { const user = userEvent.setup(); - render( ); + await render( ); const opener = screen.getByRole( 'button', { name: 'Toggle Modal', @@ -351,7 +352,9 @@ describe( 'Modal', () => { it( 'should focus the first focusable element in the contents (if found) when `firstContentElement` passed as value for `focusOnMount` prop', async () => { const user = userEvent.setup(); - render( ); + await render( + + ); const opener = screen.getByRole( 'button' ); @@ -365,7 +368,7 @@ describe( 'Modal', () => { it( 'should focus the first element anywhere within the Modal when `firstElement` passed as value for `focusOnMount` prop', async () => { const user = userEvent.setup(); - render( ); + await render( ); const opener = screen.getByRole( 'button' ); @@ -379,7 +382,7 @@ describe( 'Modal', () => { it( 'should not move focus when `false` passed as value for `focusOnMount` prop', async () => { const user = userEvent.setup(); - render( ); + await render( ); const opener = screen.getByRole( 'button', { name: 'Toggle Modal', @@ -459,7 +462,7 @@ describe( 'Modal', () => { it( 'is added and removed when modal opens and closes including when closed due to another modal opening', async () => { const user = userEvent.setup(); - const { baseElement } = render( ); + const { baseElement } = await render( ); await user.keyboard( 'a' ); // Opens modal A. expect( baseElement ).toHaveClass( 'is-A-open' ); @@ -475,7 +478,7 @@ describe( 'Modal', () => { it( 'is removed even when prop changes while nested modal is open', async () => { const user = userEvent.setup(); - const { baseElement } = render( ); + const { baseElement } = await render( ); await user.keyboard( 'a' ); // Opens modal A. await user.keyboard( '{Meta>}a{/Meta}' ); // Opens nested modal. diff --git a/packages/components/src/navigable-container/test/navigable-menu.tsx b/packages/components/src/navigable-container/test/navigable-menu.tsx index a5ab228b0c2b2..e7807baed10c6 100644 --- a/packages/components/src/navigable-container/test/navigable-menu.tsx +++ b/packages/components/src/navigable-container/test/navigable-menu.tsx @@ -1,7 +1,8 @@ /** * External dependencies */ -import { render, screen } from '@testing-library/react'; +import { screen } from '@testing-library/react'; +import { render } from '@ariakit/test/react'; import userEvent from '@testing-library/user-event'; /** @@ -50,7 +51,7 @@ describe( 'NavigableMenu', () => { const onNavigateSpy = jest.fn(); - render( ); + await render( ); const focusables = getNavigableMenuFocusables(); @@ -89,7 +90,7 @@ describe( 'NavigableMenu', () => { const onNavigateSpy = jest.fn(); - render( + await render( { const onNavigateSpy = jest.fn(); - const { rerender } = render( + const { rerender } = await render( ); @@ -160,7 +161,7 @@ describe( 'NavigableMenu', () => { expect( onNavigateSpy ).toHaveBeenCalledTimes( 2 ); expect( onNavigateSpy ).toHaveBeenLastCalledWith( 0, firstFocusable ); - rerender( + await rerender( { const externalWrapperOnKeyDownSpy = jest.fn(); - render( + await render( // Disable reason: this is only for test purposes. // eslint-disable-next-line jsx-a11y/no-static-element-interactions
@@ -218,7 +219,7 @@ describe( 'NavigableMenu', () => { it( 'skips its internal logic when the tab key is pressed', async () => { const user = userEvent.setup(); - render( + await render( <> diff --git a/packages/components/src/navigable-container/test/tababble-container.tsx b/packages/components/src/navigable-container/test/tababble-container.tsx index eb14842025bec..d3c4d04eb80ca 100644 --- a/packages/components/src/navigable-container/test/tababble-container.tsx +++ b/packages/components/src/navigable-container/test/tababble-container.tsx @@ -1,7 +1,8 @@ /** * External dependencies */ -import { render, screen } from '@testing-library/react'; +import { screen } from '@testing-library/react'; +import { render } from '@ariakit/test/react'; import userEvent from '@testing-library/user-event'; /** @@ -57,7 +58,9 @@ describe( 'TabbableContainer', () => { const onNavigateSpy = jest.fn(); - render( ); + await render( + + ); const tabbables = getTabbableContainerTabbables(); @@ -90,7 +93,7 @@ describe( 'TabbableContainer', () => { const onNavigateSpy = jest.fn(); - const { rerender } = render( + const { rerender } = await render( ); @@ -121,7 +124,7 @@ describe( 'TabbableContainer', () => { expect( onNavigateSpy ).toHaveBeenCalledTimes( 2 ); expect( onNavigateSpy ).toHaveBeenLastCalledWith( 0, firstTabbable ); - rerender( + await rerender( { const externalWrapperOnKeyDownSpy = jest.fn(); - render( + await render( // Disable reason: this is only for test purposes. // eslint-disable-next-line jsx-a11y/no-static-element-interactions
diff --git a/packages/components/src/navigation/test/index.tsx b/packages/components/src/navigation/test/index.tsx index 20646a6c809bf..a23b0faffce2b 100644 --- a/packages/components/src/navigation/test/index.tsx +++ b/packages/components/src/navigation/test/index.tsx @@ -1,7 +1,8 @@ /** * External dependencies */ -import { render, screen } from '@testing-library/react'; +import { screen } from '@testing-library/react'; +import { render } from '@ariakit/test/react'; import userEvent from '@testing-library/user-event'; /** @@ -172,7 +173,7 @@ const TestNavigationControlled = () => { describe( 'Navigation', () => { it( 'should render the panes and active item', async () => { - render( ); + await render( ); const menuItems = screen.getAllByRole( 'listitem' ); @@ -187,8 +188,8 @@ describe( 'Navigation', () => { ).toHaveTextContent( 'Item 2' ); } ); - it( 'should render anchor links when menu item supplies an href', () => { - render( ); + it( 'should render anchor links when menu item supplies an href', async () => { + await render( ); const linkItem = screen.getByRole( 'link', { name: 'Item 2' } ); @@ -196,8 +197,8 @@ describe( 'Navigation', () => { expect( linkItem ).toHaveAttribute( 'target', '_blank' ); } ); - it( 'should render a custom component when menu item supplies one', () => { - render( ); + it( 'should render a custom component when menu item supplies one', async () => { + await render( ); expect( screen.getByText( 'customize me' ) ).toBeInTheDocument(); } ); @@ -205,7 +206,7 @@ describe( 'Navigation', () => { it( 'should set an active category on click', async () => { const user = userEvent.setup(); - render( ); + await render( ); await user.click( screen.getByRole( 'button', { name: 'Category' } ) ); @@ -216,30 +217,30 @@ describe( 'Navigation', () => { expect( menuItems[ 1 ] ).toHaveTextContent( 'Child 2' ); } ); - it( 'should render the root title', () => { - const { rerender } = render( ); + it( 'should render the root title', async () => { + const { rerender } = await render( ); expect( screen.queryByRole( 'heading' ) ).not.toBeInTheDocument(); - rerender( ); + await rerender( ); expect( screen.getByRole( 'heading' ) ).toBeInTheDocument(); expect( screen.getByRole( 'heading' ) ).toHaveTextContent( 'Home' ); } ); - it( 'should render badges', () => { - render( ); + it( 'should render badges', async () => { + await render( ); const menuItem = screen.getAllByRole( 'listitem' ); expect( menuItem[ 0 ] ).toHaveTextContent( 'Item 1' + '21' ); } ); - it( 'should render menu titles when items exist', () => { - const { rerender } = render( ); + it( 'should render menu titles when items exist', async () => { + const { rerender } = await render( ); expect( screen.queryByText( 'Menu title' ) ).not.toBeInTheDocument(); - rerender( ); + await rerender( ); expect( screen.getByText( 'Menu title' ) ).toBeInTheDocument(); } ); @@ -247,7 +248,7 @@ describe( 'Navigation', () => { it( 'should navigate up a level when clicking the back button', async () => { const user = userEvent.setup(); - render( ); + await render( ); await user.click( screen.getByRole( 'button', { name: 'Category' } ) ); @@ -261,7 +262,7 @@ describe( 'Navigation', () => { it( 'should navigate correctly when controlled', async () => { const user = userEvent.setup(); - render( ); + await render( ); // check root menu is shown and item 1 is selected expect( diff --git a/packages/components/src/navigator/test/index.tsx b/packages/components/src/navigator/test/index.tsx index b83bd70d9d744..083c4aa446b14 100644 --- a/packages/components/src/navigator/test/index.tsx +++ b/packages/components/src/navigator/test/index.tsx @@ -2,7 +2,8 @@ * External dependencies */ import type { ComponentPropsWithoutRef } from 'react'; -import { render, screen } from '@testing-library/react'; +import { screen } from '@testing-library/react'; +import { render } from '@ariakit/test/react'; import userEvent from '@testing-library/user-event'; /** @@ -408,38 +409,38 @@ describe( 'Navigator', () => { window.Element.prototype.getClientRects = originalGetClientRects; } ); - it( 'should render', () => { - render( ); + it( 'should render', async () => { + await render( ); expect( getScreen( 'home' ) ).toBeInTheDocument(); expect( queryScreen( 'child' ) ).not.toBeInTheDocument(); expect( queryScreen( 'nested' ) ).not.toBeInTheDocument(); } ); - it( 'should show a different screen on the first render depending on the value of `initialPath`', () => { - render( ); + it( 'should show a different screen on the first render depending on the value of `initialPath`', async () => { + await render( ); expect( queryScreen( 'home' ) ).not.toBeInTheDocument(); expect( getScreen( 'child' ) ).toBeInTheDocument(); expect( queryScreen( 'nested' ) ).not.toBeInTheDocument(); } ); - it( 'should ignore changes to `initialPath` after the first render', () => { - const { rerender } = render( ); + it( 'should ignore changes to `initialPath` after the first render', async () => { + const { rerender } = await render( ); expect( getScreen( 'home' ) ).toBeInTheDocument(); expect( queryScreen( 'child' ) ).not.toBeInTheDocument(); expect( queryScreen( 'nested' ) ).not.toBeInTheDocument(); - rerender( ); + await rerender( ); expect( getScreen( 'home' ) ).toBeInTheDocument(); expect( queryScreen( 'child' ) ).not.toBeInTheDocument(); expect( queryScreen( 'nested' ) ).not.toBeInTheDocument(); } ); - it( 'should not rended anything if the `initialPath` does not match any available screen', () => { - render( ); + it( 'should not rended anything if the `initialPath` does not match any available screen', async () => { + await render( ); expect( queryScreen( 'home' ) ).not.toBeInTheDocument(); expect( queryScreen( 'child' ) ).not.toBeInTheDocument(); @@ -451,7 +452,7 @@ describe( 'Navigator', () => { const user = userEvent.setup(); - render( ); + await render( ); expect( getScreen( 'home' ) ).toBeInTheDocument(); expect( getNavigationButton( 'toChildScreen' ) ).toBeInTheDocument(); @@ -521,7 +522,7 @@ describe( 'Navigator', () => { const user = userEvent.setup(); - render( ); + await render( ); expect( getNavigationButton( 'toNonExistingScreen' ) @@ -543,7 +544,7 @@ describe( 'Navigator', () => { } ); it( 'should escape the value of the `path` prop', async () => { - render( ); + await render( ); expect( getScreen( 'home' ) ).toBeInTheDocument(); expect( @@ -564,7 +565,7 @@ describe( 'Navigator', () => { it( 'should match correctly paths with named arguments', async () => { const user = userEvent.setup(); - render( ); + await render( ); expect( getScreen( 'home' ) ).toBeInTheDocument(); @@ -594,7 +595,7 @@ describe( 'Navigator', () => { it( 'should restore focus correctly', async () => { const user = userEvent.setup(); - render( ); + await render( ); // Navigate to child screen. await user.click( getNavigationButton( 'toChildScreen' ) ); @@ -643,7 +644,7 @@ describe( 'Navigator', () => { it( 'should keep focus on an active element inside navigator, while re-rendering', async () => { const user = userEvent.setup(); - render( ); + await render( ); // Navigate to child screen. await user.click( getNavigationButton( 'toChildScreen' ) ); @@ -665,7 +666,7 @@ describe( 'Navigator', () => { it( 'should keep focus on an active element outside navigator, while re-rendering', async () => { const user = userEvent.setup(); - render( ); + await render( ); // Navigate to child screen. await user.click( getNavigationButton( 'toChildScreen' ) ); @@ -687,7 +688,7 @@ describe( 'Navigator', () => { it( 'should restore focus correctly even when the `path` needs to be escaped', async () => { const user = userEvent.setup(); - render( ); + await render( ); expect( getScreen( 'home' ) ).toBeInTheDocument(); @@ -711,7 +712,7 @@ describe( 'Navigator', () => { it( 'should restore focus while using goTo and goToParent', async () => { const user = userEvent.setup(); - render( ); + await render( ); expect( getScreen( 'home' ) ).toBeInTheDocument(); @@ -748,7 +749,7 @@ describe( 'Navigator', () => { it( 'should skip focus based on location `skipFocus` option', async () => { const user = userEvent.setup(); - render( ); + await render( ); // Navigate to child screen with skipFocus. await user.click( getNavigationButton( 'goToWithSkipFocus' ) ); diff --git a/packages/components/src/notice/test/index.tsx b/packages/components/src/notice/test/index.tsx index b601e8717a1d3..bc5ecf0fb2c7b 100644 --- a/packages/components/src/notice/test/index.tsx +++ b/packages/components/src/notice/test/index.tsx @@ -1,7 +1,8 @@ /** * External dependencies */ -import { render } from '@testing-library/react'; + +import { render } from '@ariakit/test/react'; /** * WordPress dependencies @@ -25,8 +26,8 @@ describe( 'Notice', () => { mockedSpeak.mockReset(); } ); - it( 'should match snapshot', () => { - const { container } = render( + it( 'should match snapshot', async () => { + const { container } = await render( { expect( container ).toMatchSnapshot(); } ); - it( 'should not have is-dismissible class when isDismissible prop is false', () => { - const { container } = render( + it( 'should not have is-dismissible class when isDismissible prop is false', async () => { + const { container } = await render( I cannot be dismissed! ); const wrapper = getNoticeWrapper( container ); @@ -52,33 +53,33 @@ describe( 'Notice', () => { expect( wrapper ).not.toHaveClass( 'is-dismissible' ); } ); - it( 'should default to info status', () => { - const { container } = render( FYI ); + it( 'should default to info status', async () => { + const { container } = await render( FYI ); expect( getNoticeWrapper( container ) ).toHaveClass( 'is-info' ); } ); describe( 'useSpokenMessage', () => { - it( 'should speak the given message', () => { - render( FYI ); + it( 'should speak the given message', async () => { + await render( FYI ); expect( speak ).toHaveBeenCalledWith( 'FYI', 'polite' ); } ); - it( 'should speak the given message by explicit politeness', () => { - render( Uh oh! ); + it( 'should speak the given message by explicit politeness', async () => { + await render( Uh oh! ); expect( speak ).toHaveBeenCalledWith( 'Uh oh!', 'assertive' ); } ); - it( 'should speak the given message by implicit politeness by status', () => { - render( Uh oh! ); + it( 'should speak the given message by implicit politeness by status', async () => { + await render( Uh oh! ); expect( speak ).toHaveBeenCalledWith( 'Uh oh!', 'assertive' ); } ); - it( 'should speak the given message, preferring explicit to implicit politeness', () => { - render( + it( 'should speak the given message, preferring explicit to implicit politeness', async () => { + await render( No need to panic @@ -90,10 +91,10 @@ describe( 'Notice', () => { ); } ); - it( 'should coerce a message to a string', () => { + it( 'should coerce a message to a string', async () => { // This test assumes that `@wordpress/a11y` is capable of handling // markup strings appropriately. - render( + await render( With emphasis this time. @@ -105,13 +106,13 @@ describe( 'Notice', () => { ); } ); - it( 'should not re-speak an effectively equivalent element message', () => { - const { rerender } = render( + it( 'should not re-speak an effectively equivalent element message', async () => { + const { rerender } = await render( With emphasis this time. ); - rerender( + await rerender( With emphasis this time. diff --git a/packages/components/src/notice/test/list.tsx b/packages/components/src/notice/test/list.tsx index 65d896e1eb492..3e81ccca26fc4 100644 --- a/packages/components/src/notice/test/list.tsx +++ b/packages/components/src/notice/test/list.tsx @@ -1,7 +1,8 @@ /** * External dependencies */ -import { render, screen } from '@testing-library/react'; +import { screen } from '@testing-library/react'; +import { render } from '@ariakit/test/react'; /** * Internal dependencies @@ -9,8 +10,8 @@ import { render, screen } from '@testing-library/react'; import NoticeList from '../list'; describe( 'NoticeList', () => { - it( 'should merge className', () => { - render( + it( 'should merge className', async () => { + await render( List of notices diff --git a/packages/components/src/number-control/test/index.tsx b/packages/components/src/number-control/test/index.tsx index 3cf3368f1636b..025308b35bf20 100644 --- a/packages/components/src/number-control/test/index.tsx +++ b/packages/components/src/number-control/test/index.tsx @@ -1,7 +1,8 @@ /** * External dependencies */ -import { render, screen } from '@testing-library/react'; +import { screen } from '@testing-library/react'; +import { render } from '@ariakit/test/react'; import userEvent from '@testing-library/user-event'; /** @@ -30,13 +31,13 @@ function StatefulNumberControl( props: NumberControlProps ) { describe( 'NumberControl', () => { describe( 'Basic rendering', () => { - it( 'should render', () => { - render( ); + it( 'should render', async () => { + await render( ); expect( screen.getByRole( 'spinbutton' ) ).toBeVisible(); } ); - it( 'should render custom className', () => { - render( ); + it( 'should render custom className', async () => { + await render( ); expect( screen.getByRole( 'spinbutton' ) ).toBeVisible(); } ); } ); @@ -46,7 +47,7 @@ describe( 'NumberControl', () => { const user = userEvent.setup(); const spy = jest.fn(); - render( + await render( spy( v ) } /> ); @@ -61,7 +62,7 @@ describe( 'NumberControl', () => { const user = userEvent.setup(); const onChangeSpy = jest.fn(); - render( + await render( { const user = userEvent.setup(); const onChangeSpy = jest.fn(); - render( + await render( { it( 'should clamp value within range on ENTER keypress', async () => { const user = userEvent.setup(); - render( ); + await render( ); const input = screen.getByRole( 'spinbutton' ); @@ -165,7 +166,7 @@ describe( 'NumberControl', () => { it( 'should clamp value within range on blur', async () => { const user = userEvent.setup(); - render( ); + await render( ); const input = screen.getByRole( 'spinbutton' ); await user.clear( input ); @@ -184,7 +185,7 @@ describe( 'NumberControl', () => { it( 'should parse non-numeric values to a number on ENTER keypress when required', async () => { const user = userEvent.setup(); - render( ); + await render( ); const input = screen.getByRole( 'spinbutton' ); await user.clear( input ); @@ -197,7 +198,7 @@ describe( 'NumberControl', () => { it( 'should parse non-numeric values to empty string on ENTER keypress when not required', async () => { const user = userEvent.setup(); - render( ); + await render( ); const input = screen.getByRole( 'spinbutton' ); await user.clear( input ); @@ -216,7 +217,7 @@ describe( 'NumberControl', () => { it( 'should not enforce numerical value for empty string when required is omitted', async () => { const user = userEvent.setup(); - render( ); + await render( ); const input = screen.getByRole( 'spinbutton' ); await user.clear( input ); @@ -231,7 +232,7 @@ describe( 'NumberControl', () => { it( 'should enforce numerical value for empty string when required', async () => { const user = userEvent.setup(); - render( ); + await render( ); const input = screen.getByRole( 'spinbutton' ); await user.clear( input ); @@ -247,7 +248,9 @@ describe( 'NumberControl', () => { const spy = jest.fn(); - render( ); + await render( + + ); const input = screen.getByRole( 'spinbutton' ); await user.click( input ); @@ -259,7 +262,7 @@ describe( 'NumberControl', () => { it( 'should increment by step on key UP press', async () => { const user = userEvent.setup(); - render( ); + await render( ); const input = screen.getByRole( 'spinbutton' ); await user.click( input ); @@ -271,7 +274,7 @@ describe( 'NumberControl', () => { it( 'should increment from a negative value', async () => { const user = userEvent.setup(); - render( ); + await render( ); const input = screen.getByRole( 'spinbutton' ); await user.click( input ); @@ -283,7 +286,9 @@ describe( 'NumberControl', () => { it( 'should increment while preserving the decimal value when `step` is “any”', async () => { const user = userEvent.setup(); - render( ); + await render( + + ); const input = screen.getByRole( 'spinbutton' ); await user.click( input ); @@ -295,7 +300,7 @@ describe( 'NumberControl', () => { it( 'should increment by step multiplied by spinFactor when spinFactor is provided', async () => { const user = userEvent.setup(); - render( + await render( { it( 'should increment by shiftStep on key UP + shift press', async () => { const user = userEvent.setup(); - render( ); + await render( + + ); const input = screen.getByRole( 'spinbutton' ); await user.click( input ); @@ -325,7 +332,9 @@ describe( 'NumberControl', () => { it( 'should increment by shiftStep multiplied by spinFactor on key UP + shift press', async () => { const user = userEvent.setup(); - render( ); + await render( + + ); const input = screen.getByRole( 'spinbutton' ); await user.click( input ); @@ -337,7 +346,9 @@ describe( 'NumberControl', () => { it( 'should increment by shiftStep while preserving the decimal value when `step` is “any”', async () => { const user = userEvent.setup(); - render( ); + await render( + + ); const input = screen.getByRole( 'spinbutton' ); await user.click( input ); @@ -349,7 +360,9 @@ describe( 'NumberControl', () => { it( 'should increment by custom shiftStep on key UP + shift press', async () => { const user = userEvent.setup(); - render( ); + await render( + + ); const input = screen.getByRole( 'spinbutton' ); await user.click( input ); @@ -361,7 +374,7 @@ describe( 'NumberControl', () => { it( 'should increment but be limited by max on shiftStep', async () => { const user = userEvent.setup(); - render( + await render( { it( 'should not increment by shiftStep if disabled', async () => { const user = userEvent.setup(); - render( + await render( { const user = userEvent.setup(); const spy = jest.fn(); - render( ); + await render( + + ); const input = screen.getByRole( 'spinbutton' ); await user.click( input ); @@ -412,7 +427,7 @@ describe( 'NumberControl', () => { it( 'should decrement by step on key DOWN press', async () => { const user = userEvent.setup(); - render( ); + await render( ); const input = screen.getByRole( 'spinbutton' ); await user.click( input ); @@ -424,7 +439,7 @@ describe( 'NumberControl', () => { it( 'should decrement from a negative value', async () => { const user = userEvent.setup(); - render( ); + await render( ); const input = screen.getByRole( 'spinbutton' ); await user.click( input ); @@ -436,7 +451,9 @@ describe( 'NumberControl', () => { it( 'should decrement while preserving the decimal value when `step` is “any”', async () => { const user = userEvent.setup(); - render( ); + await render( + + ); const input = screen.getByRole( 'spinbutton' ); await user.click( input ); @@ -448,7 +465,7 @@ describe( 'NumberControl', () => { it( 'should decrement by step multiplied by spinFactor when spinFactor is provided', async () => { const user = userEvent.setup(); - render( + await render( { it( 'should decrement by shiftStep on key DOWN + shift press', async () => { const user = userEvent.setup(); - render( ); + await render( ); const input = screen.getByRole( 'spinbutton' ); await user.click( input ); @@ -478,7 +495,9 @@ describe( 'NumberControl', () => { it( 'should decrement by shiftStep multiplied by spinFactor on key DOWN + shift press', async () => { const user = userEvent.setup(); - render( ); + await render( + + ); const input = screen.getByRole( 'spinbutton' ); await user.click( input ); @@ -490,7 +509,9 @@ describe( 'NumberControl', () => { it( 'should decrement by shiftStep while preserving the decimal value when `step` is “any”', async () => { const user = userEvent.setup(); - render( ); + await render( + + ); const input = screen.getByRole( 'spinbutton' ); await user.click( input ); @@ -502,7 +523,9 @@ describe( 'NumberControl', () => { it( 'should decrement by custom shiftStep on key DOWN + shift press', async () => { const user = userEvent.setup(); - render( ); + await render( + + ); const input = screen.getByRole( 'spinbutton' ); await user.click( input ); @@ -514,7 +537,7 @@ describe( 'NumberControl', () => { it( 'should decrement but be limited by min on shiftStep', async () => { const user = userEvent.setup(); - render( + await render( { it( 'should not decrement by shiftStep if disabled', async () => { const user = userEvent.setup(); - render( + await render( { }, ]; - it( 'shows heading label', () => { - render( ); + it( 'shows heading label', async () => { + await render( ); const paletteLabel = screen.getByRole( 'heading', { level: 2, @@ -134,8 +135,8 @@ describe( 'PaletteEdit', () => { expect( paletteLabel ).toBeVisible(); } ); - it( 'shows heading label with custom heading level', () => { - render( + it( 'shows heading label with custom heading level', async () => { + await render( { ).toBeVisible(); } ); - it( 'shows empty message', () => { - render( + it( 'shows empty message', async () => { + await render( { } ); it( 'shows an option to remove all colors', async () => { - render( ); + await render( ); await click( screen.getByRole( 'button', { @@ -181,7 +182,7 @@ describe( 'PaletteEdit', () => { } ); it( 'shows a reset option when the `canReset` prop is enabled', async () => { - render( + await render( ); @@ -200,7 +201,7 @@ describe( 'PaletteEdit', () => { } ); it( 'does not show a reset colors option when `canReset` is disabled', async () => { - render( ); + await render( ); await click( screen.getByRole( 'button', { @@ -217,7 +218,7 @@ describe( 'PaletteEdit', () => { it( 'calls the `onChange` with the new color appended', async () => { const onChange = jest.fn(); - render( + await render( { it( 'calls the `onChange` with the new gradient appended', async () => { const onChange = jest.fn(); - render( + await render( { } ); } ); - it( 'can not add new colors when `canOnlyChangeValues` is enabled', () => { - render( ); + it( 'can not add new colors when `canOnlyChangeValues` is enabled', async () => { + await render( ); expect( screen.queryByRole( 'button', { @@ -286,7 +287,7 @@ describe( 'PaletteEdit', () => { it( 'can remove a color', async () => { const onChange = jest.fn(); - render( + await render( { it( 'can update palette name', async () => { const onChange = jest.fn(); - render( + await render( { it( 'can update color palette value', async () => { const onChange = jest.fn(); - render( + await render( { it( 'can update gradient palette value', async () => { const onChange = jest.fn(); - render( + await render( { describe( 'basic rendering', () => { - it( 'should render an empty div with the matching className', () => { - const { container } = render( ); + it( 'should render an empty div with the matching className', async () => { + const { container } = await render( ); expect( container ).toMatchSnapshot(); } ); - it( 'should render inner content, if opened', () => { - render( + it( 'should render inner content, if opened', async () => { + await render(
Content
@@ -27,8 +28,8 @@ describe( 'PanelBody', () => { expect( screen.getByTestId( 'inner-content' ) ).toBeVisible(); } ); - it( 'should be opened by default', () => { - render( + it( 'should be opened by default', async () => { + await render(
Content
@@ -37,8 +38,8 @@ describe( 'PanelBody', () => { expect( screen.getByTestId( 'inner-content' ) ).toBeVisible(); } ); - it( 'should render as initially opened, if specified', () => { - render( + it( 'should render as initially opened, if specified', async () => { + await render(
Content
@@ -47,8 +48,8 @@ describe( 'PanelBody', () => { expect( screen.getByTestId( 'inner-content' ) ).toBeVisible(); } ); - it( 'should call the children function, if specified', () => { - const { rerender } = render( + it( 'should call the children function, if specified', async () => { + const { rerender } = await render( { ( { opened } ) => (