From af2817e2f356f6eb22c4036a4b72539a0cf9edaa Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Mon, 27 Apr 2026 11:54:20 -0700 Subject: [PATCH 01/31] add proper keyboard navigation to combobox --- .../@react-aria/test-utils/src/combobox.ts | 43 ++++++++++++++++--- .../test/ComboBox.test.js | 28 +++++++++++- 2 files changed, 64 insertions(+), 7 deletions(-) diff --git a/packages/@react-aria/test-utils/src/combobox.ts b/packages/@react-aria/test-utils/src/combobox.ts index d95ac6f5711..71c2fbbcbe8 100644 --- a/packages/@react-aria/test-utils/src/combobox.ts +++ b/packages/@react-aria/test-utils/src/combobox.ts @@ -91,8 +91,8 @@ export class ComboBoxTester { } else { await this.user.click(trigger); } - } else if (interactionType === 'keyboard' && this._trigger != null) { - act(() => this._trigger!.focus()); + } else if (interactionType === 'keyboard') { + act(() => combobox.focus()); if (triggerBehavior !== 'focus') { await this.user.keyboard('{ArrowDown}'); } @@ -142,6 +142,38 @@ export class ComboBoxTester { return option; } + private async keyboardNavigateToOption(opts: {option: HTMLElement}) { + let {option} = opts; + let combobox = this.combobox; + let options = this.options(); + let targetIndex = options.findIndex(opt => (opt === option) || opt.contains(option)); + if (targetIndex === -1) { + throw new Error('Option provided is not in the combobox listbox.'); + } + + let getCurrentIndex = () => { + let id = combobox.getAttribute('aria-activedescendant'); + if (!id) { + return -1; + } + return options.findIndex(opt => opt.id === id); + }; + + if (getCurrentIndex() === -1) { + await this.user.keyboard('[ArrowDown]'); + } + + let currIndex = getCurrentIndex(); + if (currIndex === -1) { + throw new Error('Could not determine the current option in the combobox listbox.'); + } + + let direction = targetIndex > currIndex ? 'down' : 'up'; + for (let i = 0; i < Math.abs(targetIndex - currIndex); i++) { + await this.user.keyboard(`[${direction === 'down' ? 'ArrowDown' : 'ArrowUp'}]`); + } + } + /** * Selects the desired combobox option. Defaults to using the interaction type set on the combobox tester. If necessary, will open the combobox dropdown beforehand. * The desired option can be targeted via the option's node, the option's text, or the option's index. @@ -166,9 +198,10 @@ export class ComboBoxTester { throw new Error('Target option not found in the listbox.'); } - // TODO: keyboard method of selecting the the option is a bit tricky unless I simply simulate the user pressing the down arrow - // the required amount of times to reach the option. For now just click the option even in keyboard mode - if (interactionType === 'mouse' || interactionType === 'keyboard') { + if (interactionType === 'keyboard') { + await this.keyboardNavigateToOption({option}); + await this.user.keyboard('[Enter]'); + } else if (interactionType === 'mouse') { await this.user.click(option); } else { await this.user.pointer({target: option, keys: '[TouchA]'}); diff --git a/packages/react-aria-components/test/ComboBox.test.js b/packages/react-aria-components/test/ComboBox.test.js index af75cba5644..48719ed321c 100644 --- a/packages/react-aria-components/test/ComboBox.test.js +++ b/packages/react-aria-components/test/ComboBox.test.js @@ -274,6 +274,30 @@ describe('ComboBox', () => { expect(document.querySelector('input[type=hidden]')).toBeNull(); }); + it('should support selecting an option via keyboard', async () => { + let onSelectionChange = jest.fn(); + let tree = render( + + + + + + + Open + + Share… + + + SMS + Email + + + + Delete… + + + ) } }); diff --git a/packages/react-aria-components/test/Table.test.js b/packages/react-aria-components/test/Table.test.js index 31296172ff2..a3bea8ec57a 100644 --- a/packages/react-aria-components/test/Table.test.js +++ b/packages/react-aria-components/test/Table.test.js @@ -675,22 +675,23 @@ describe('Table', () => { }); it('should support disabled state', async () => { - let {getAllByRole} = renderTable({ + let {getByRole} = renderTable({ tableProps: {selectionMode: 'multiple', disabledKeys: ['2'], disabledBehavior: 'all'}, rowProps: {className: ({isDisabled}) => isDisabled ? 'disabled' : ''} }); - let rows = getAllByRole('row'); - let row = rows[2]; - - expect(row).toHaveAttribute('aria-disabled', 'true'); - expect(row).toHaveClass('disabled'); - expect(within(row).getByRole('checkbox')).toBeDisabled(); + let tableTester = testUtilUser.createTester('Table', {root: getByRole('grid')}); + let disabledRow = tableTester.rows()[1]; + expect(disabledRow).toHaveAttribute('aria-disabled', 'true'); + expect(disabledRow).toHaveClass('disabled'); + expect(within(disabledRow).getByRole('checkbox')).toBeDisabled(); await user.tab(); - expect(document.activeElement).toBe(rows[1]); + expect(document.activeElement).toBe(tableTester.rows()[0]); fireEvent.keyDown(document.activeElement, {key: 'ArrowDown'}); fireEvent.keyUp(document.activeElement, {key: 'ArrowDown'}); - expect(document.activeElement).toBe(rows[3]); + expect(document.activeElement).toBe(tableTester.rows()[2]); + await expect(tableTester.toggleRowSelection({row: 1})).rejects.toThrow(); + await expect(tableTester.triggerRowAction({row: 1})).rejects.toThrow(); }); it('should support isDisabled prop on rows', async () => { @@ -3051,7 +3052,7 @@ describe('Table', () => { )} - + ))} ); From 348c5f7fe2cf9a5dc240fc6863155abf678851c4 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Wed, 29 Apr 2026 10:19:38 -0700 Subject: [PATCH 15/31] cleanup todos that we are punting on/not doing --- packages/@react-aria/test-utils/src/gridlist.ts | 2 -- packages/@react-aria/test-utils/src/listbox.ts | 2 -- packages/@react-aria/test-utils/src/menu.ts | 3 --- packages/@react-aria/test-utils/src/select.ts | 1 - packages/@react-aria/test-utils/src/table.ts | 7 +------ packages/@react-aria/test-utils/src/tabs.ts | 2 -- packages/@react-aria/test-utils/src/tree.ts | 6 ------ packages/@react-aria/test-utils/src/utils.ts | 6 ------ 8 files changed, 1 insertion(+), 28 deletions(-) diff --git a/packages/@react-aria/test-utils/src/gridlist.ts b/packages/@react-aria/test-utils/src/gridlist.ts index 744a67ce6f3..2d4bf8d24b8 100644 --- a/packages/@react-aria/test-utils/src/gridlist.ts +++ b/packages/@react-aria/test-utils/src/gridlist.ts @@ -165,8 +165,6 @@ export class GridListTester { } } - // TODO: There is a more difficult use case where the row has/behaves as link, don't think we have a good way to determine that unless the - // user specificlly tells us /** * Triggers the action for the specified gridlist row. Defaults to using the interaction type set on the gridlist tester. */ diff --git a/packages/@react-aria/test-utils/src/listbox.ts b/packages/@react-aria/test-utils/src/listbox.ts index a3aa6581f70..0d3974ad851 100644 --- a/packages/@react-aria/test-utils/src/listbox.ts +++ b/packages/@react-aria/test-utils/src/listbox.ts @@ -78,7 +78,6 @@ export class ListBoxTester { this._interactionType = type; } - // TODO: now that we have listbox, perhaps select can make use of this tester internally /** * Returns a option matching the specified index or text content. */ @@ -99,7 +98,6 @@ export class ListBoxTester { return option; } - // TODO: this is basically the same as menu except for the error message, refactor later so that they share // TODO: this also doesn't support grid layout yet private async keyboardNavigateToOption(opts: {option: HTMLElement, selectionOnNav?: 'default' | 'none'}) { let {option, selectionOnNav = 'default'} = opts; diff --git a/packages/@react-aria/test-utils/src/menu.ts b/packages/@react-aria/test-utils/src/menu.ts index 128f3a23d3b..d0fc2e22007 100644 --- a/packages/@react-aria/test-utils/src/menu.ts +++ b/packages/@react-aria/test-utils/src/menu.ts @@ -97,8 +97,6 @@ export class MenuTester { this._interactionType = type; } - // TODO: this has been common to select as well, maybe make select use it? Or make a generic method. Will need to make error messages generic - // One difference will be that it supports long press as well /** * Opens the menu. Defaults to using the interaction type set on the menu tester. */ @@ -280,7 +278,6 @@ export class MenuTester { } } - // TODO: update this to remove needsLongPress if we wanna make the user call open first always /** * Opens the submenu. Defaults to using the interaction type set on the menu tester. The submenu trigger can be targeted via the trigger's node or the trigger's text. */ diff --git a/packages/@react-aria/test-utils/src/select.ts b/packages/@react-aria/test-utils/src/select.ts index 17c74a00b30..7f2cec20097 100644 --- a/packages/@react-aria/test-utils/src/select.ts +++ b/packages/@react-aria/test-utils/src/select.ts @@ -206,7 +206,6 @@ export class SelectTester { await this.keyboardNavigateToOption({option}); await this.user.keyboard('[Enter]'); } else { - // TODO: what if the user needs to scroll the list to find the option? What if there are multiple matches for text (hopefully the picker options are pretty unique) if (interactionType === 'mouse') { await this.user.click(option); } else { diff --git a/packages/@react-aria/test-utils/src/table.ts b/packages/@react-aria/test-utils/src/table.ts index cfb84b345ae..c68a20c48f1 100644 --- a/packages/@react-aria/test-utils/src/table.ts +++ b/packages/@react-aria/test-utils/src/table.ts @@ -206,9 +206,7 @@ export class TableTester { let rowExpander = within(row).getAllByRole('button')[0]; // what happens if the button is not first? how can we differentiate? await pressElement(this.user, rowExpander, interactionType); } else if (interactionType === 'keyboard') { - // TODO: We always Use Option/Ctrl when keyboard navigating so selection isn't changed - // in selectionmode="replace"/highlight selection when navigating to the row that the user wants - // to expand. Discuss if this is useful or not + // note that our keyboard navigation makes sure selection isn't changes await this.keyboardNavigateToRow({row}); let collapseKey = this._direction === 'rtl' ? 'ArrowRight' : 'ArrowLeft'; let expandKey = this._direction === 'rtl' ? 'ArrowLeft' : 'ArrowRight'; @@ -420,9 +418,6 @@ export class TableTester { } } - // TODO: should there be utils for drag and drop and column resizing? For column resizing, I'm not entirely convinced that users will be doing that in their tests. - // For DnD, it might be tricky to do for keyboard DnD since we wouldn't know what valid drop zones there are... Similarly, for simulating mouse drag and drop the coordinates depend - // on the mocks the user sets up for their row height/etc. // Additionally, should we also support keyboard navigation/typeahead? Those felt like they could be very easily replicated by the user via user.keyboard already and don't really // add much value if we provide that to them /** diff --git a/packages/@react-aria/test-utils/src/tabs.ts b/packages/@react-aria/test-utils/src/tabs.ts index 184e7a70ae6..eb83c61cbef 100644 --- a/packages/@react-aria/test-utils/src/tabs.ts +++ b/packages/@react-aria/test-utils/src/tabs.ts @@ -56,7 +56,6 @@ export class TabsTester { this._interactionType = type; } - // TODO: This is pretty similar across most the utils, refactor to make it generic? /** * Returns a tab matching the specified index or text content. */ @@ -76,7 +75,6 @@ export class TabsTester { return tab; } - // TODO: also quite similar across more utils albeit with orientation, refactor to make generic private async keyboardNavigateToTab(opts: {tab: HTMLElement, orientation?: Orientation}) { let {tab, orientation = 'vertical'} = opts; let tabs = this.tabs(); diff --git a/packages/@react-aria/test-utils/src/tree.ts b/packages/@react-aria/test-utils/src/tree.ts index eb8f9c6e2a1..6df52215274 100644 --- a/packages/@react-aria/test-utils/src/tree.ts +++ b/packages/@react-aria/test-utils/src/tree.ts @@ -155,7 +155,6 @@ export class TreeTester { // Note that long press interactions with rows is strictly touch only for grid rows await triggerLongPress({element: cell, advanceTimer: this._advanceTimer!, pointerOpts: {pointerType: 'touch'}}); } else { - // TODO add modifiers here? Maybe move into pressElement if we get more cases for different types of modifier keys if (selectionBehavior === 'replace' && interactionType !== 'touch') { await this.user.keyboard(`[${metaKey}>]`); } @@ -197,9 +196,6 @@ export class TreeTester { let rowExpander = within(row).getAllByRole('button')[0]; // what happens if the button is not first? how can we differentiate? await pressElement(this.user, rowExpander, interactionType); } else if (interactionType === 'keyboard') { - // TODO: We always Use Option/Ctrl when keyboard navigating so selection isn't changed - // in selectionmode="replace"/highlight selection when navigating to the row that the user wants - // to expand. Discuss if this is useful or not await this.keyboardNavigateToRow({row}); let collapseKey = this._direction === 'rtl' ? 'ArrowRight' : 'ArrowLeft'; let expandKey = this._direction === 'rtl' ? 'ArrowLeft' : 'ArrowRight'; @@ -236,8 +232,6 @@ export class TreeTester { if (needsDoubleClick) { await this.user.dblClick(row); } else if (interactionType === 'keyboard') { - // TODO: same as above, uses the modifier key to make sure we don't modify selection state on row focus - // as we keyboard navigate to the row we want activate await this.keyboardNavigateToRow({row}); await this.user.keyboard('[Enter]'); } else { diff --git a/packages/@react-aria/test-utils/src/utils.ts b/packages/@react-aria/test-utils/src/utils.ts index edff2eea690..df34de5eda4 100644 --- a/packages/@react-aria/test-utils/src/utils.ts +++ b/packages/@react-aria/test-utils/src/utils.ts @@ -62,9 +62,6 @@ export function formatTargetNode(value: number | string | HTMLElement): string { * @param opts.pointeropts - Options to pass to the simulated event. Defaults to mouse. See https://testing-library.com/docs/dom-testing-library/api-events/#fireevent for more info. */ export async function triggerLongPress(opts: {element: HTMLElement, advanceTimer: (time: number) => unknown | Promise, pointerOpts?: Record}): Promise { - // TODO: note that this only works if the code from installPointerEvent is called somewhere in the test BEFORE the - // render. Perhaps we should rely on the user setting that up since I'm not sure there is a great way to set that up here in the - // util before first render. Will need to document it well let {element, advanceTimer, pointerOpts = {}} = opts; let pointerType = pointerOpts.pointerType ?? 'mouse'; let shouldFireCompatibilityEvents = false; @@ -119,9 +116,6 @@ export async function pressElement(user: {click: (element: Element) => Promise element.focus()); await user.keyboard('[Space]'); } else if (interactionType === 'touch') { From 3c4d45e0113e18e72e9d01388bd7d96dc2c34476 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Wed, 29 Apr 2026 13:31:35 -0700 Subject: [PATCH 16/31] add grid navigation to listbox test util and fix browser tests --- packages/@react-aria/test-utils/src/act.ts | 9 +++- .../@react-aria/test-utils/src/listbox.ts | 31 +++++++++-- packages/@react-aria/test-utils/src/types.ts | 8 ++- .../test/ListBox.browser.test.tsx | 50 ++++++++++++++++++ .../test/ListBox.test.js | 51 +++++++++++++++++++ vitest.browser.config.ts | 4 +- 6 files changed, 144 insertions(+), 9 deletions(-) create mode 100644 packages/react-aria-components/test/ListBox.browser.test.tsx diff --git a/packages/@react-aria/test-utils/src/act.ts b/packages/@react-aria/test-utils/src/act.ts index e5335aa6496..f034af349de 100644 --- a/packages/@react-aria/test-utils/src/act.ts +++ b/packages/@react-aria/test-utils/src/act.ts @@ -20,4 +20,11 @@ if (typeof React.act === 'function') { actImpl = ReactDOMTestUtils.act; } -export const act = actImpl; +export const act: typeof actImpl = ((fn: any) => { + // only wrap in act if in test environment, breaks vite browser test if test utils are used otherwise + // @ts-ignore + if (typeof IS_REACT_ACT_ENVIRONMENT === 'boolean' ? IS_REACT_ACT_ENVIRONMENT : typeof jest !== 'undefined') { + return actImpl(fn); + } + return fn(); +}) as typeof actImpl; diff --git a/packages/@react-aria/test-utils/src/listbox.ts b/packages/@react-aria/test-utils/src/listbox.ts index 0d3974ad851..f3102eaeb71 100644 --- a/packages/@react-aria/test-utils/src/listbox.ts +++ b/packages/@react-aria/test-utils/src/listbox.ts @@ -56,12 +56,14 @@ export class ListBoxTester { private _interactionType: UserOpts['interactionType']; private _advanceTimer: UserOpts['advanceTimer']; private _listbox: HTMLElement; + private _layout: ListBoxTesterOpts['layout']; constructor(opts: ListBoxTesterOpts) { - let {root, user, interactionType, advanceTimer} = opts; + let {root, user, interactionType, advanceTimer, layout} = opts; this.user = user; this._interactionType = interactionType || 'mouse'; this._advanceTimer = advanceTimer; + this._layout = layout || 'stack'; this._listbox = root; if (root.getAttribute('role') !== 'listbox') { let listbox = within(root).queryByRole('listbox'); @@ -98,7 +100,6 @@ export class ListBoxTester { return option; } - // TODO: this also doesn't support grid layout yet private async keyboardNavigateToOption(opts: {option: HTMLElement, selectionOnNav?: 'default' | 'none'}) { let {option, selectionOnNav = 'default'} = opts; let altKey = getAltKey(); @@ -118,12 +119,32 @@ export class ListBoxTester { throw new Error('ActiveElement is not in the listbox'); } - let direction = targetIndex > currIndex ? 'down' : 'up'; if (selectionOnNav === 'none') { await this.user.keyboard(`[${altKey}>]`); } - for (let i = 0; i < Math.abs(targetIndex - currIndex); i++) { - await this.user.keyboard(`[${direction === 'down' ? 'ArrowDown' : 'ArrowUp'}]`); + if (this._layout === 'grid') { + while (document.activeElement !== option) { + let curr = (document.activeElement as HTMLElement).getBoundingClientRect(); + let target = option.getBoundingClientRect(); + let key: string; + // basically compare current position with desired position to determine if we need to go up/down/left/right + // use 1 in the comparison here for subpixels since getBoundingClientRect returns subpixels precision + if (Math.abs(curr.top - target.top) > 1) { + key = curr.top < target.top ? 'ArrowDown' : 'ArrowUp'; + } else if (Math.abs(curr.left - target.left) > 1) { + key = curr.left < target.left ? 'ArrowRight' : 'ArrowLeft'; + } else { + // if the diff in current vs desired is < 1 but it is claiming we arent focused on the target + // then we might be in a case where getBoundingClientRect isnt mocked + throw new Error('Could not navigate to target option in grid layout. Did the test mock getBoundingClientRect?'); + } + await this.user.keyboard(`[${key}]`); + } + } else { + let direction = targetIndex > currIndex ? 'down' : 'up'; + for (let i = 0; i < Math.abs(targetIndex - currIndex); i++) { + await this.user.keyboard(`[${direction === 'down' ? 'ArrowDown' : 'ArrowUp'}]`); + } } if (selectionOnNav === 'none') { await this.user.keyboard(`[/${altKey}]`); diff --git a/packages/@react-aria/test-utils/src/types.ts b/packages/@react-aria/test-utils/src/types.ts index 607af3780cb..2bf5fda32e3 100644 --- a/packages/@react-aria/test-utils/src/types.ts +++ b/packages/@react-aria/test-utils/src/types.ts @@ -72,7 +72,13 @@ export interface DialogTesterOpts extends BaseTesterOpts { export interface GridListTesterOpts extends BaseTesterOpts {} -export interface ListBoxTesterOpts extends BaseTesterOpts {} +export interface ListBoxTesterOpts extends BaseTesterOpts { + /** + * The layout of the listbox. + * @default 'stack' + */ + layout?: 'stack' | 'grid' +} export interface MenuTesterOpts extends BaseTesterOpts { /** diff --git a/packages/react-aria-components/test/ListBox.browser.test.tsx b/packages/react-aria-components/test/ListBox.browser.test.tsx new file mode 100644 index 00000000000..1f2fdcdf1db --- /dev/null +++ b/packages/react-aria-components/test/ListBox.browser.test.tsx @@ -0,0 +1,50 @@ +/* + * Copyright 2026 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +import {expect, it} from 'vitest'; +import {ListBox, ListBoxItem} from '../src/ListBox'; +import React from 'react'; +import {render} from 'vitest-browser-react'; +import {User} from '@react-aria/test-utils'; + +it('can do grid navigation in browser test', async () => { + let testUtilUser = new User({interactionType: 'keyboard'}); + + let {container} = await render( + + 0,0 + 0,1 + 0,2 + 1,0 + 1,1 + 1,2 + 2,0 + 2,1 + 2,2 + + ); + + let listbox = container.querySelector('[role=listbox]') as HTMLElement; + let tester = testUtilUser.createTester('ListBox', {root: listbox, interactionType: 'keyboard', layout: 'grid'}); + + let options = tester.options(); + expect(options).toHaveLength(9); + + await tester.toggleOptionSelection({option: options[5]}); + + expect(options[5].getAttribute('aria-selected')).toBe('true'); + expect(document.activeElement).toBe(options[5]); +}); diff --git a/packages/react-aria-components/test/ListBox.test.js b/packages/react-aria-components/test/ListBox.test.js index bd4656c685b..a23013f6bfd 100644 --- a/packages/react-aria-components/test/ListBox.test.js +++ b/packages/react-aria-components/test/ListBox.test.js @@ -1029,6 +1029,57 @@ describe('ListBox', () => { expect(document.activeElement).toBe(options[0]); // 1,1 }); + it('should support keyboard navigation across grid layout via the test util', async () => { + /** + * The following ListBox is roughly in this shape: + * + * ------------------- + * | 1,1 | 2,1 | 3,1 | + * ------------------- + * | 1,2 | 2,2 | 3,2 | + * ------------------- + * | 1,3 | 3,2 | 3,3 | + * ------------------- + */ + let {getByRole} = render( + + 1,1 + 1,2 + 1,3 + 2,1 + 2,2 + 2,3 + 3,1 + 3,2 + 3,3 + + ); + + jest.spyOn(HTMLElement.prototype, 'getBoundingClientRect').mockImplementation(function () { + if (this.getAttribute('role') === 'listbox') { + return {top: 0, left: 0, bottom: 200, right: 300, width: 300, height: 200}; + } else { + let index = [...this.parentElement.children].indexOf(this); + return {top: (index % 3) * 40, left: Math.floor(index / 3) * 100, bottom: (index % 3) * 40 + 40, right: Math.floor(index / 3) * 100 + 100, width: 100, height: 40}; + } + }); + + let listboxTester = testUtilUser.createTester('ListBox', {root: getByRole('listbox'), interactionType: 'keyboard', layout: 'grid'}); + let options = listboxTester.options(); + + await listboxTester.toggleOptionSelection({option: options[5]}); + expect(options[5]).toHaveAttribute('aria-selected', 'true'); + expect(document.activeElement).toBe(options[5]); + + await listboxTester.toggleOptionSelection({option: '1,1'}); + expect(options[0]).toHaveAttribute('aria-selected', 'true'); + expect(document.activeElement).toBe(options[0]); + + await listboxTester.toggleOptionSelection({option: 8}); + expect(options[8]).toHaveAttribute('aria-selected', 'true'); + expect(document.activeElement).toBe(options[8]); + }); + it('should support onScroll', () => { let onScroll = jest.fn(); let {getByRole} = renderListbox({onScroll}); diff --git a/vitest.browser.config.ts b/vitest.browser.config.ts index 1b89e68fde5..784361923c1 100644 --- a/vitest.browser.config.ts +++ b/vitest.browser.config.ts @@ -21,12 +21,12 @@ import svgr from 'vite-plugin-svgr'; const s2Dir = path.resolve(__dirname, 'packages/@react-spectrum/s2'); -// Handles ../intl/*.json imports +// Handles ../intl/*.json and ../intl//*.json imports. function intlJsonPlugin(): Plugin { return { name: 'intl-json-loader', async resolveId(source, importer) { - if (source.includes('/intl/*.json') && importer) { + if (/\/intl\/.*\*\.json$/.test(source) && importer) { const dir = path.dirname(importer); const intlDir = path.resolve(dir, source.replace('*.json', '')); return `virtual:intl-messages:${intlDir}`; From b1ca6f4e8826ef19dbde9e2785f7acbf6f15c94f Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Wed, 29 Apr 2026 13:42:45 -0700 Subject: [PATCH 17/31] add grid nav to gridlist too --- .../@react-aria/test-utils/src/gridlist.ts | 30 +++++++++-- packages/@react-aria/test-utils/src/types.ts | 8 ++- .../test/GridList.browser.test.tsx | 52 +++++++++++++++++++ .../test/ListBox.browser.test.tsx | 9 +++- 4 files changed, 93 insertions(+), 6 deletions(-) create mode 100644 packages/react-aria-components/test/GridList.browser.test.tsx diff --git a/packages/@react-aria/test-utils/src/gridlist.ts b/packages/@react-aria/test-utils/src/gridlist.ts index 2d4bf8d24b8..33dd74dfb45 100644 --- a/packages/@react-aria/test-utils/src/gridlist.ts +++ b/packages/@react-aria/test-utils/src/gridlist.ts @@ -24,13 +24,15 @@ export class GridListTester { private _advanceTimer: UserOpts['advanceTimer']; private _direction: Direction; private _gridlist: HTMLElement; + private _layout: GridListTesterOpts['layout']; constructor(opts: GridListTesterOpts) { - let {root, user, interactionType, advanceTimer, direction} = opts; + let {root, user, interactionType, advanceTimer, direction, layout} = opts; this.user = user; this._interactionType = interactionType || 'mouse'; this._advanceTimer = advanceTimer; this._direction = direction || 'ltr'; + this._layout = layout || 'stack'; this._gridlist = root; if (root.getAttribute('role') !== 'grid') { let gridlist = within(root).queryByRole('grid'); @@ -90,13 +92,33 @@ export class GridListTester { if (currIndex === -1) { throw new Error('ActiveElement is not in the gridlist'); } - let direction = targetIndex > currIndex ? 'down' : 'up'; if (selectionOnNav === 'none') { await this.user.keyboard(`[${altKey}>]`); } - for (let i = 0; i < Math.abs(targetIndex - currIndex); i++) { - await this.user.keyboard(`[${direction === 'down' ? 'ArrowDown' : 'ArrowUp'}]`); + if (this._layout === 'grid') { + while (document.activeElement !== row) { + let curr = (document.activeElement as HTMLElement).getBoundingClientRect(); + let target = row.getBoundingClientRect(); + let key: string; + // basically compare current position with desired position to determine if we need to go up/down/left/right + // use 1 in the comparison here for subpixels since getBoundingClientRect returns subpixels precision + if (Math.abs(curr.top - target.top) > 1) { + key = curr.top < target.top ? 'ArrowDown' : 'ArrowUp'; + } else if (Math.abs(curr.left - target.left) > 1) { + key = curr.left < target.left ? 'ArrowRight' : 'ArrowLeft'; + } else { + // if the diff in current vs desired is < 1 but it is claiming we arent focused on the target + // then we might be in a case where getBoundingClientRect isnt mocked + throw new Error('Could not navigate to target row in grid layout. Did the test mock getBoundingClientRect?'); + } + await this.user.keyboard(`[${key}]`); + } + } else { + let direction = targetIndex > currIndex ? 'down' : 'up'; + for (let i = 0; i < Math.abs(targetIndex - currIndex); i++) { + await this.user.keyboard(`[${direction === 'down' ? 'ArrowDown' : 'ArrowUp'}]`); + } } if (selectionOnNav === 'none') { await this.user.keyboard(`[/${altKey}]`); diff --git a/packages/@react-aria/test-utils/src/types.ts b/packages/@react-aria/test-utils/src/types.ts index 2bf5fda32e3..348054f1cd9 100644 --- a/packages/@react-aria/test-utils/src/types.ts +++ b/packages/@react-aria/test-utils/src/types.ts @@ -70,7 +70,13 @@ export interface DialogTesterOpts extends BaseTesterOpts { overlayType?: 'modal' | 'popover' } -export interface GridListTesterOpts extends BaseTesterOpts {} +export interface GridListTesterOpts extends BaseTesterOpts { + /** + * The layout of the gridlist. + * @default 'stack' + */ + layout?: 'stack' | 'grid' +} export interface ListBoxTesterOpts extends BaseTesterOpts { /** diff --git a/packages/react-aria-components/test/GridList.browser.test.tsx b/packages/react-aria-components/test/GridList.browser.test.tsx new file mode 100644 index 00000000000..3091a59d038 --- /dev/null +++ b/packages/react-aria-components/test/GridList.browser.test.tsx @@ -0,0 +1,52 @@ +/* + * Copyright 2026 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +import {describe, expect, it} from 'vitest'; +import {GridList, GridListItem} from '../src/GridList'; +import React from 'react'; +import {render} from 'vitest-browser-react'; +import {User} from '@react-aria/test-utils'; + +describe('GridList grid keyboard navigation in real browser', () => { + it('navigates to a target row using real CSS grid layout', async () => { + let testUtilUser = new User({interactionType: 'keyboard'}); + + let {container} = await render( + + 0,0 + 0,1 + 0,2 + 1,0 + 1,1 + 1,2 + 2,0 + 2,1 + 2,2 + + ); + + let gridlist = container.querySelector('[role=grid]') as HTMLElement; + let tester = testUtilUser.createTester('GridList', {root: gridlist, interactionType: 'keyboard', layout: 'grid'}); + + let rows = tester.rows(); + expect(rows).toHaveLength(9); + + await tester.toggleRowSelection({row: rows[5], checkboxSelection: false}); + + expect(rows[5].getAttribute('aria-selected')).toBe('true'); + expect(document.activeElement).toBe(rows[5]); + }); +}); diff --git a/packages/react-aria-components/test/ListBox.browser.test.tsx b/packages/react-aria-components/test/ListBox.browser.test.tsx index 1f2fdcdf1db..1692f63d720 100644 --- a/packages/react-aria-components/test/ListBox.browser.test.tsx +++ b/packages/react-aria-components/test/ListBox.browser.test.tsx @@ -44,7 +44,14 @@ it('can do grid navigation in browser test', async () => { expect(options).toHaveLength(9); await tester.toggleOptionSelection({option: options[5]}); - expect(options[5].getAttribute('aria-selected')).toBe('true'); expect(document.activeElement).toBe(options[5]); + + await tester.toggleOptionSelection({option: options[0]}); + expect(options[0].getAttribute('aria-selected')).toBe('true'); + expect(document.activeElement).toBe(options[0]); + + await tester.toggleOptionSelection({option: options[8]}); + expect(options[8].getAttribute('aria-selected')).toBe('true'); + expect(document.activeElement).toBe(options[8]); }); From 226f5d99b698e349c67fd534eb17fde36c489fa7 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Thu, 30 Apr 2026 11:02:36 -0700 Subject: [PATCH 18/31] add browser tests for each pattern to make sure utils work with it --- packages/@react-aria/test-utils/src/menu.ts | 2 +- .../s2/test/CheckboxGroup.browser.test.tsx | 54 +++++++++++++++ .../s2/test/Combobox.browser.test.tsx | 50 ++++++++++++++ .../s2/test/Menu.browser.test.tsx | 56 +++++++++++++++ .../s2/test/Picker.browser.test.tsx | 50 ++++++++++++++ .../s2/test/RadioGroup.browser.test.tsx | 53 +++++++++++++++ .../s2/test/TableView.browser.test.tsx | 62 +++++++++++++++++ .../s2/test/TreeView.browser.test.tsx | 68 +++++++++++++++++++ .../test/Dialog.browser.test.tsx | 52 ++++++++++++++ .../test/GridList.browser.test.tsx | 68 +++++++++++-------- .../test/ListBox.browser.test.tsx | 19 ++++-- .../test/Tabs.browser.test.tsx | 46 +++++++++++++ 12 files changed, 543 insertions(+), 37 deletions(-) create mode 100644 packages/@react-spectrum/s2/test/CheckboxGroup.browser.test.tsx create mode 100644 packages/@react-spectrum/s2/test/Combobox.browser.test.tsx create mode 100644 packages/@react-spectrum/s2/test/Menu.browser.test.tsx create mode 100644 packages/@react-spectrum/s2/test/Picker.browser.test.tsx create mode 100644 packages/@react-spectrum/s2/test/RadioGroup.browser.test.tsx create mode 100644 packages/@react-spectrum/s2/test/TableView.browser.test.tsx create mode 100644 packages/@react-spectrum/s2/test/TreeView.browser.test.tsx create mode 100644 packages/react-aria-components/test/Dialog.browser.test.tsx create mode 100644 packages/react-aria-components/test/Tabs.browser.test.tsx diff --git a/packages/@react-aria/test-utils/src/menu.ts b/packages/@react-aria/test-utils/src/menu.ts index d0fc2e22007..ffbae2c7eb8 100644 --- a/packages/@react-aria/test-utils/src/menu.ts +++ b/packages/@react-aria/test-utils/src/menu.ts @@ -11,8 +11,8 @@ */ import {act} from './act'; -import {MenuTesterOpts, UserOpts} from './types'; import {formatTargetNode, triggerLongPress} from './utils'; +import {MenuTesterOpts, UserOpts} from './types'; import {waitFor, within} from '@testing-library/dom'; interface MenuOpenOpts { diff --git a/packages/@react-spectrum/s2/test/CheckboxGroup.browser.test.tsx b/packages/@react-spectrum/s2/test/CheckboxGroup.browser.test.tsx new file mode 100644 index 00000000000..baa972110a5 --- /dev/null +++ b/packages/@react-spectrum/s2/test/CheckboxGroup.browser.test.tsx @@ -0,0 +1,54 @@ +/* + * Copyright 2026 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +import {Checkbox} from '../src/Checkbox'; +import {CheckboxGroup} from '../src/CheckboxGroup'; +import {expect, it} from 'vitest'; +import React from 'react'; +import {render} from './utils/render'; +import {User} from '@react-aria/test-utils'; + +function CheckboxGroupExample() { + return ( + + + Product Updates + + + Security Alerts + + + Marketing Emails + + + ); +} + +it.each` + interactionType + ${'mouse'} + ${'keyboard'} +`('toggles a checkbox via $interactionType', async ({interactionType}) => { + let testUtilUser = new User(); + let {container} = await render(); + + let tester = testUtilUser.createTester('CheckboxGroup', {root: container.querySelector('[role=group]') as HTMLElement, interactionType}); + let checkboxes = tester.checkboxes(); + await tester.toggleCheckbox({checkbox: checkboxes[2]}); + expect(tester.selectedCheckboxes()).toContain(checkboxes[2]); +}); diff --git a/packages/@react-spectrum/s2/test/Combobox.browser.test.tsx b/packages/@react-spectrum/s2/test/Combobox.browser.test.tsx new file mode 100644 index 00000000000..42aae0a31ba --- /dev/null +++ b/packages/@react-spectrum/s2/test/Combobox.browser.test.tsx @@ -0,0 +1,50 @@ +/* + * Copyright 2026 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +import {ComboBox, ComboBoxItem} from '../src/ComboBox'; +import {expect, it} from 'vitest'; +import React from 'react'; +import {render} from './utils/render'; +import {User} from '@react-aria/test-utils'; + +let items = [ + {id: 1, name: 'Aardvark'}, + {id: 2, name: 'Cat'}, + {id: 3, name: 'Dog'}, + {id: 4, name: 'Kangaroo'}, + {id: 5, name: 'Koala'}, + {id: 6, name: 'Penguin'}, + {id: 7, name: 'Snake'}, + {id: 8, name: 'Turtle'}, + {id: 9, name: 'Wombat'} +]; + +function ComboBoxExample() { + return ( + + {(item) => {item.name}} + + ); +} + +it.each` + interactionType + ${'mouse'} + ${'keyboard'} +`('selects an option via $interactionType', async ({interactionType}) => { + let testUtilUser = new User(); + let {container} = await render(); + + let tester = testUtilUser.createTester('ComboBox', {root: container, interactionType}); + await tester.toggleOptionSelection({option: 2}); + expect(tester.combobox()).toHaveValue('Dog'); +}); diff --git a/packages/@react-spectrum/s2/test/Menu.browser.test.tsx b/packages/@react-spectrum/s2/test/Menu.browser.test.tsx new file mode 100644 index 00000000000..cc6bc1f208d --- /dev/null +++ b/packages/@react-spectrum/s2/test/Menu.browser.test.tsx @@ -0,0 +1,56 @@ +/* + * Copyright 2026 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +import {Button} from '../src/Button'; +import {expect, it, vi} from 'vitest'; +import {Menu, MenuItem, MenuTrigger} from '../src/Menu'; +import React from 'react'; +import {render} from './utils/render'; +import {User} from '@react-aria/test-utils'; + +let items = [ + {id: 1, name: 'Aardvark'}, + {id: 2, name: 'Cat'}, + {id: 3, name: 'Dog'}, + {id: 4, name: 'Kangaroo'}, + {id: 5, name: 'Koala'}, + {id: 6, name: 'Penguin'}, + {id: 7, name: 'Snake'}, + {id: 8, name: 'Turtle'}, + {id: 9, name: 'Wombat'} +]; + +function MenuExample({onAction}) { + return ( + + + + {(item) => {item.name}} + + + ); +} + +it.each` + interactionType + ${'mouse'} + ${'keyboard'} +`('triggers a menu item via $interactionType', async ({interactionType}) => { + let onAction = vi.fn(); + let testUtilUser = new User(); + let {container} = await render(); + + let tester = testUtilUser.createTester('Menu', {root: container.querySelector('button') as HTMLElement, interactionType}); + await tester.open(); + await tester.toggleOptionSelection({option: 2}); + expect(onAction).toHaveBeenCalledWith(3); +}); diff --git a/packages/@react-spectrum/s2/test/Picker.browser.test.tsx b/packages/@react-spectrum/s2/test/Picker.browser.test.tsx new file mode 100644 index 00000000000..1ecb93eac85 --- /dev/null +++ b/packages/@react-spectrum/s2/test/Picker.browser.test.tsx @@ -0,0 +1,50 @@ +/* + * Copyright 2026 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +import {expect, it} from 'vitest'; +import {Picker, PickerItem} from '../src/Picker'; +import React from 'react'; +import {render} from './utils/render'; +import {User} from '@react-aria/test-utils'; + +let items = [ + {id: 1, name: 'Aardvark'}, + {id: 2, name: 'Cat'}, + {id: 3, name: 'Dog'}, + {id: 4, name: 'Kangaroo'}, + {id: 5, name: 'Koala'}, + {id: 6, name: 'Penguin'}, + {id: 7, name: 'Snake'}, + {id: 8, name: 'Turtle'}, + {id: 9, name: 'Wombat'} +]; + +function PickerExample() { + return ( + + {(item: typeof items[number]) => {item.name}} + + ); +} + +it.each` + interactionType + ${'mouse'} + ${'keyboard'} +`('selects an option via $interactionType', async ({interactionType}) => { + let testUtilUser = new User(); + let {container} = await render(); + + let tester = testUtilUser.createTester('Select', {root: container, interactionType}); + await tester.toggleOptionSelection({option: 2}); + expect(tester.trigger()).toHaveTextContent('Dog'); +}); diff --git a/packages/@react-spectrum/s2/test/RadioGroup.browser.test.tsx b/packages/@react-spectrum/s2/test/RadioGroup.browser.test.tsx new file mode 100644 index 00000000000..6b684dea170 --- /dev/null +++ b/packages/@react-spectrum/s2/test/RadioGroup.browser.test.tsx @@ -0,0 +1,53 @@ +/* + * Copyright 2026 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +import {expect, it} from 'vitest'; +import {Radio, RadioGroup} from '../src/RadioGroup'; +import React from 'react'; +import {render} from './utils/render'; +import {User} from '@react-aria/test-utils'; + +function RadioGroupExample() { + return ( + + + Standard Shipping (Free) + + + Expedited Shipping ($9.99) + + + Overnight Shipping ($19.99) + + + ); +} + +it.each` + interactionType + ${'mouse'} + ${'keyboard'} +`('triggers a radio via $interactionType', async ({interactionType}) => { + let testUtilUser = new User(); + let {container} = await render(); + + let tester = testUtilUser.createTester('RadioGroup', {root: container.querySelector('[role=radiogroup]') as HTMLElement, interactionType}); + let radios = tester.radios(); + await tester.triggerRadio({radio: radios[1]}); + expect(tester.selectedRadio()).toBe(radios[1]); +}); diff --git a/packages/@react-spectrum/s2/test/TableView.browser.test.tsx b/packages/@react-spectrum/s2/test/TableView.browser.test.tsx new file mode 100644 index 00000000000..8452c40b675 --- /dev/null +++ b/packages/@react-spectrum/s2/test/TableView.browser.test.tsx @@ -0,0 +1,62 @@ +/* + * Copyright 2026 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +import {Cell, Column, Row, TableBody, TableHeader, TableView} from '../src/TableView'; +import {expect, it} from 'vitest'; +import React from 'react'; +import {render} from './utils/render'; +import {User} from '@react-aria/test-utils'; + +let columns = [ + {name: 'Title', id: 'title', isRowHeader: true}, + {name: 'Status', id: 'status'}, + {name: 'Payment Method', id: 'paymentMethod'}, + {name: 'Price', id: 'price'} +]; + +const items = [ + {id: 1, title: 'Website Design', status: 'Paid', paymentMethod: 'Credit Card', price: 1200}, + {id: 2, title: 'Logo Creation', status: 'Pending', paymentMethod: 'PayPal', price: 350}, + {id: 3, title: 'SEO Optimization', status: 'Overdue', paymentMethod: 'Bank Transfer', price: 800}, + {id: 4, title: 'Social Media Setup', status: 'Paid', paymentMethod: 'Debit Card', price: 450}, + {id: 5, title: 'Content Writing', status: 'Pending', paymentMethod: 'Credit Card', price: 600} +]; + +function TableExample() { + return ( + + + {(column) => {column.name}} + + + {(item) => ( + + {(column) => {item[column.id]}} + + )} + + + ); +} + +it.each` + interactionType + ${'mouse'} + ${'keyboard'} +`('selects a row via $interactionType', async ({interactionType}) => { + let testUtilUser = new User(); + let {container} = await render(); + + let tester = testUtilUser.createTester('Table', {root: container.querySelector('[role=grid]') as HTMLElement, interactionType}); + await tester.toggleRowSelection({row: 2}); + expect(tester.rows()[2].getAttribute('aria-selected')).toBe('true'); +}); diff --git a/packages/@react-spectrum/s2/test/TreeView.browser.test.tsx b/packages/@react-spectrum/s2/test/TreeView.browser.test.tsx new file mode 100644 index 00000000000..8b57ed38a2d --- /dev/null +++ b/packages/@react-spectrum/s2/test/TreeView.browser.test.tsx @@ -0,0 +1,68 @@ +/* + * Copyright 2026 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +import {Collection} from 'react-aria/Collection'; +import {expect, it} from 'vitest'; +import React from 'react'; +import {render} from './utils/render'; +import {style} from '@react-spectrum/s2/style' with {type: 'macro'}; +import {TreeView, TreeViewItem, TreeViewItemContent} from '../src/TreeView'; +import {User} from '@react-aria/test-utils'; + +let items = [ + {id: 1, title: 'Documents', type: 'directory', children: [ + {id: 2, title: 'Project', type: 'directory', children: [ + {id: 3, title: 'Weekly Report', type: 'file', children: []}, + {id: 4, title: 'Budget', type: 'file', children: []} + ]} + ]}, + {id: 5, title: 'Photos', type: 'directory', children: [ + {id: 6, title: 'Image 1', type: 'file', children: []}, + {id: 7, title: 'Image 2', type: 'file', children: []} + ]} +]; + +function TreeViewExample() { + return ( + + {function renderItem(item) { + return ( + + {item.title} + + {renderItem} + + + ); + }} + + ); +} + +it.each` + interactionType + ${'mouse'} + ${'keyboard'} +`('expands and selects a row via $interactionType', async ({interactionType}) => { + let testUtilUser = new User(); + let {container} = await render(); + + let tester = testUtilUser.createTester('Tree', {root: container.querySelector('[role=treegrid]') as HTMLElement, interactionType}); + await tester.toggleRowExpansion({row: 'Photos'}); + await tester.toggleRowSelection({row: 'Image 2'}); + let selectedRow = tester.findRow({indexOrText: 'Image 2'}); + expect(selectedRow!.getAttribute('aria-selected')).toBe('true'); +}); diff --git a/packages/react-aria-components/test/Dialog.browser.test.tsx b/packages/react-aria-components/test/Dialog.browser.test.tsx new file mode 100644 index 00000000000..1d86e5353e6 --- /dev/null +++ b/packages/react-aria-components/test/Dialog.browser.test.tsx @@ -0,0 +1,52 @@ +/* + * Copyright 2026 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +import {Button} from '../src/Button'; +import {Dialog, DialogTrigger} from '../src/Dialog'; +import {expect, it} from 'vitest'; +import {Heading} from '../src/Heading'; +import {Modal} from '../src/Modal'; +import React from 'react'; +import {render} from 'vitest-browser-react'; +import {User} from '@react-aria/test-utils'; + +function DialogExample() { + return ( + + + + + Hello + + + + + ); +} + +it.each` + interactionType + ${'mouse'} + ${'keyboard'} +`('opens via $interactionType and closes', async ({interactionType}) => { + let testUtilUser = new User(); + let {container} = await render(); + + let tester = testUtilUser.createTester('Dialog', {root: container.querySelector('button') as HTMLElement, interactionType}); + + await tester.open(); + expect(tester.dialog()).not.toBeNull(); + expect(tester.dialog()!.contains(document.activeElement)).toBe(true); + + await tester.close(); + expect(tester.dialog()).toBeNull(); +}); diff --git a/packages/react-aria-components/test/GridList.browser.test.tsx b/packages/react-aria-components/test/GridList.browser.test.tsx index 3091a59d038..f19bf219da0 100644 --- a/packages/react-aria-components/test/GridList.browser.test.tsx +++ b/packages/react-aria-components/test/GridList.browser.test.tsx @@ -10,43 +10,53 @@ * governing permissions and limitations under the License. */ -import {describe, expect, it} from 'vitest'; +import {expect, it} from 'vitest'; import {GridList, GridListItem} from '../src/GridList'; import React from 'react'; import {render} from 'vitest-browser-react'; import {User} from '@react-aria/test-utils'; -describe('GridList grid keyboard navigation in real browser', () => { - it('navigates to a target row using real CSS grid layout', async () => { - let testUtilUser = new User({interactionType: 'keyboard'}); +function Grid() { + return ( + + 0,0 + 0,1 + 0,2 + 1,0 + 1,1 + 1,2 + 2,0 + 2,1 + 2,2 + + ); +} - let {container} = await render( - - 0,0 - 0,1 - 0,2 - 1,0 - 1,1 - 1,2 - 2,0 - 2,1 - 2,2 - - ); +it.each` + interactionType + ${'mouse'} + ${'keyboard'} +`('selects a row via $interactionType in real browser grid layout', async ({interactionType}) => { + let testUtilUser = new User(); + let {container} = await render(); - let gridlist = container.querySelector('[role=grid]') as HTMLElement; - let tester = testUtilUser.createTester('GridList', {root: gridlist, interactionType: 'keyboard', layout: 'grid'}); + let gridlist = container.querySelector('[role=grid]') as HTMLElement; + let tester = testUtilUser.createTester('GridList', {root: gridlist, layout: 'grid', interactionType}); - let rows = tester.rows(); - expect(rows).toHaveLength(9); + let rows = tester.rows(); + await tester.toggleRowSelection({row: rows[5]}); + expect(rows[5].getAttribute('aria-selected')).toBe('true'); + expect(document.activeElement).toBe(rows[5]); - await tester.toggleRowSelection({row: rows[5], checkboxSelection: false}); + await tester.toggleRowSelection({row: rows[0]}); + expect(rows[0].getAttribute('aria-selected')).toBe('true'); + expect(document.activeElement).toBe(rows[0]); - expect(rows[5].getAttribute('aria-selected')).toBe('true'); - expect(document.activeElement).toBe(rows[5]); - }); + await tester.toggleRowSelection({row: rows[8]}); + expect(rows[8].getAttribute('aria-selected')).toBe('true'); + expect(document.activeElement).toBe(rows[8]); }); diff --git a/packages/react-aria-components/test/ListBox.browser.test.tsx b/packages/react-aria-components/test/ListBox.browser.test.tsx index 1692f63d720..ef296b2192b 100644 --- a/packages/react-aria-components/test/ListBox.browser.test.tsx +++ b/packages/react-aria-components/test/ListBox.browser.test.tsx @@ -16,10 +16,8 @@ import React from 'react'; import {render} from 'vitest-browser-react'; import {User} from '@react-aria/test-utils'; -it('can do grid navigation in browser test', async () => { - let testUtilUser = new User({interactionType: 'keyboard'}); - - let {container} = await render( +function GridListBox() { + return ( { 2,2 ); +} + +it.each` + interactionType + ${'mouse'} + ${'keyboard'} +`('selects an option via $interactionType in real browser grid layout', async ({interactionType}) => { + let testUtilUser = new User(); + let {container} = await render(); let listbox = container.querySelector('[role=listbox]') as HTMLElement; - let tester = testUtilUser.createTester('ListBox', {root: listbox, interactionType: 'keyboard', layout: 'grid'}); + let tester = testUtilUser.createTester('ListBox', {root: listbox, layout: 'grid', interactionType}); let options = tester.options(); - expect(options).toHaveLength(9); - await tester.toggleOptionSelection({option: options[5]}); expect(options[5].getAttribute('aria-selected')).toBe('true'); expect(document.activeElement).toBe(options[5]); diff --git a/packages/react-aria-components/test/Tabs.browser.test.tsx b/packages/react-aria-components/test/Tabs.browser.test.tsx new file mode 100644 index 00000000000..2199b7deb6e --- /dev/null +++ b/packages/react-aria-components/test/Tabs.browser.test.tsx @@ -0,0 +1,46 @@ +/* + * Copyright 2026 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +import {expect, it} from 'vitest'; +import React from 'react'; +import {render} from 'vitest-browser-react'; +import {Tab, TabList, TabPanel, Tabs} from '../src/Tabs'; +import {User} from '@react-aria/test-utils'; + +function TabsExample() { + return ( + + + One + Two + Three + + Panel One + Panel Two + Panel Three + + ); +} + +it.each` + interactionType + ${'mouse'} + ${'keyboard'} +`('triggers a tab via $interactionType', async ({interactionType}) => { + let testUtilUser = new User(); + let {container} = await render(); + + let tester = testUtilUser.createTester('Tabs', {root: container.querySelector('[role=tablist]') as HTMLElement, interactionType}); + let tabs = tester.tabs(); + await tester.triggerTab({tab: tabs[1]}); + expect(tester.selectedTab()).toBe(tabs[1]); +}); From 3e45ed4805dd4b7f7b3863ba74b2cf453e29abd4 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Thu, 30 Apr 2026 11:55:03 -0700 Subject: [PATCH 19/31] adding midding dialog testing pages to RAC --- packages/@react-aria/test-utils/README.md | 1 + .../pages/react-aria/Modal/testing.mdx | 75 +++++++++++++++++++ .../pages/react-aria/Popover/testing.mdx | 75 +++++++++++++++++++ .../dev/s2-docs/pages/react-aria/testing.mdx | 1 + 4 files changed, 152 insertions(+) create mode 100644 packages/dev/s2-docs/pages/react-aria/Modal/testing.mdx create mode 100644 packages/dev/s2-docs/pages/react-aria/Popover/testing.mdx diff --git a/packages/@react-aria/test-utils/README.md b/packages/@react-aria/test-utils/README.md index 46443c16e40..fbeb3e7fab9 100644 --- a/packages/@react-aria/test-utils/README.md +++ b/packages/@react-aria/test-utils/README.md @@ -62,6 +62,7 @@ Below is a list of the ARIA patterns supported by `createTester`. See the accomp - [CheckboxGroup](https://react-aria.adobe.com/CheckboxGroup/testing) - [ComboBox](https://react-aria.adobe.com/ComboBox/testing) +- Dialog via [Modal](https://react-aria.adobe.com/Modal/testing) / [Popover](https://react-aria.adobe.com/Popover/testing) - [GridList](https://react-aria.adobe.com/GridList/testing) - [ListBox](https://react-aria.adobe.com/ListBox/testing) - [Menu](https://react-aria.adobe.com/Menu/testing) diff --git a/packages/dev/s2-docs/pages/react-aria/Modal/testing.mdx b/packages/dev/s2-docs/pages/react-aria/Modal/testing.mdx new file mode 100644 index 00000000000..ab0ed857995 --- /dev/null +++ b/packages/dev/s2-docs/pages/react-aria/Modal/testing.mdx @@ -0,0 +1,75 @@ +import {Layout} from '../../../src/Layout'; +export default Layout; + +import {InlineAlert, Heading, Content} from '@react-spectrum/s2'; +import testUtilDocs from 'docs:@react-aria/test-utils'; +import {InstallCommand} from '../../../src/InstallCommand'; +import {PatternTestingFAQ} from '../../../src/PatternTestingFAQ'; + +export const isSubpage = true; +export const hideFromSearch = true; +export const tags = ['testing', 'modal', 'dialog', 'test-utils']; +export const description = 'Testing Modal with React Aria test utils'; + +# Testing Modal + +## Test utils + +`@react-aria/test-utils` offers common dialog interaction testing utilities. Install it with your preferred package manager. + + + + + Requirements + Please note that this library uses [@testing-library/react@16](https://www.npmjs.com/package/@testing-library/react) and [@testing-library/user-event@14](https://www.npmjs.com/package/@testing-library/user-event). This means that you need to be on React 18+ in order for these utilities to work. + + +Initialize a `User` object at the top of your test file, and use it to create a `Dialog` pattern tester in your test cases. Pass `overlayType: 'modal'` to indicate the dialog is rendered inside a `Modal`. The tester has methods that you can call within your test to query for the dialog or simulate common interactions. + +```ts +// Modal.test.ts +import {render} from '@testing-library/react'; +import {User} from '@react-aria/test-utils'; + +let testUtilUser = new User({ + interactionType: 'mouse' +}); +// ... + +it('Modal can be opened and closed', async function () { + // Render your test component/app and initialize the dialog tester + let {getByRole} = render( + + + + + ... + + + + ); + let button = getByRole('button'); + let dialogTester = testUtilUser.createTester('Dialog', {root: button, overlayType: 'modal'}); + + await dialogTester.open(); + let dialog = dialogTester.dialog(); + expect(dialog).toBeVisible(); + + await dialogTester.close(); + expect(dialog).not.toBeInTheDocument(); +}); +``` + +## API + +### User + + + +### DialogTester + + + +## Testing FAQ + + diff --git a/packages/dev/s2-docs/pages/react-aria/Popover/testing.mdx b/packages/dev/s2-docs/pages/react-aria/Popover/testing.mdx new file mode 100644 index 00000000000..07c5c9ccdb0 --- /dev/null +++ b/packages/dev/s2-docs/pages/react-aria/Popover/testing.mdx @@ -0,0 +1,75 @@ +import {Layout} from '../../../src/Layout'; +export default Layout; + +import {InlineAlert, Heading, Content} from '@react-spectrum/s2'; +import testUtilDocs from 'docs:@react-aria/test-utils'; +import {InstallCommand} from '../../../src/InstallCommand'; +import {PatternTestingFAQ} from '../../../src/PatternTestingFAQ'; + +export const isSubpage = true; +export const hideFromSearch = true; +export const tags = ['testing', 'popover', 'dialog', 'test-utils']; +export const description = 'Testing Popover with React Aria test utils'; + +# Testing Popover + +## Test utils + +`@react-aria/test-utils` offers common dialog interaction testing utilities. Install it with your preferred package manager. + + + + + Requirements + Please note that this library uses [@testing-library/react@16](https://www.npmjs.com/package/@testing-library/react) and [@testing-library/user-event@14](https://www.npmjs.com/package/@testing-library/user-event). This means that you need to be on React 18+ in order for these utilities to work. + + +Initialize a `User` object at the top of your test file, and use it to create a `Dialog` pattern tester in your test cases. Pass `overlayType: 'popover'` to indicate the dialog is rendered inside a `Popover`. The tester has methods that you can call within your test to query for the dialog or simulate common interactions. + +```ts +// Popover.test.ts +import {render} from '@testing-library/react'; +import {User} from '@react-aria/test-utils'; + +let testUtilUser = new User({ + interactionType: 'mouse' +}); +// ... + +it('Popover can be opened and closed', async function () { + // Render your test component/app and initialize the dialog tester + let {getByRole} = render( + + + + + ... + + + + ); + let button = getByRole('button'); + let dialogTester = testUtilUser.createTester('Dialog', {root: button, overlayType: 'popover'}); + + await dialogTester.open(); + let dialog = dialogTester.dialog(); + expect(dialog).toBeVisible(); + + await dialogTester.close(); + expect(dialog).not.toBeInTheDocument(); +}); +``` + +## API + +### User + + + +### DialogTester + + + +## Testing FAQ + + diff --git a/packages/dev/s2-docs/pages/react-aria/testing.mdx b/packages/dev/s2-docs/pages/react-aria/testing.mdx index 2bf5b3cdee3..39c67238b08 100644 --- a/packages/dev/s2-docs/pages/react-aria/testing.mdx +++ b/packages/dev/s2-docs/pages/react-aria/testing.mdx @@ -216,6 +216,7 @@ the testers in your test suite. - [CheckboxGroup](./CheckboxGroup/testing) - [ComboBox](./ComboBox/testing) +- Dialog via [Modal](./Modal/testing) / [Popover](./Popover/testing) - [GridList](./GridList/testing) - [ListBox](./ListBox/testing) - [Menu](./Menu/testing) From 1687d0d420b08a96774a3f3d26f5d16fff6594e9 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Thu, 30 Apr 2026 13:36:23 -0700 Subject: [PATCH 20/31] add rough skills for the test utils --- .../s2-docs/scripts/generateAgentSkills.mjs | 15 ++- .../skills/react-aria/test-utils-guidance.md | 97 +++++++++++++++++++ .../react-spectrum-s2/test-utils-guidance.md | 97 +++++++++++++++++++ 3 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 packages/dev/s2-docs/skills/react-aria/test-utils-guidance.md create mode 100644 packages/dev/s2-docs/skills/react-spectrum-s2/test-utils-guidance.md diff --git a/packages/dev/s2-docs/scripts/generateAgentSkills.mjs b/packages/dev/s2-docs/scripts/generateAgentSkills.mjs index ac572c307a2..fb97922f5e0 100644 --- a/packages/dev/s2-docs/scripts/generateAgentSkills.mjs +++ b/packages/dev/s2-docs/scripts/generateAgentSkills.mjs @@ -83,6 +83,10 @@ const CUSTOM_SKILL_CONTENT = { path.join( REPO_ROOT, 'packages/dev/s2-docs/skills/react-spectrum-s2/implementation-guidance.md' + ), + path.join( + REPO_ROOT, + 'packages/dev/s2-docs/skills/react-spectrum-s2/test-utils-guidance.md' ) ], guideEntries: [ @@ -97,6 +101,14 @@ const CUSTOM_SKILL_CONTENT = { 'How to choose the right S2 component when requirements do not name one explicitly.' } ] + }, + 'react-aria': { + embeddedMarkdownPaths: [ + path.join( + REPO_ROOT, + 'packages/dev/s2-docs/skills/react-aria/test-utils-guidance.md' + ) + ] } }; @@ -384,7 +396,8 @@ function generateDocsSkillMd(skillConfig, categories, isS2) { const customSkillNotesMarkdown = getCustomSkillNotesMarkdown(skillConfig.name); const embeddedCustomMarkdown = readCustomEmbeddedMarkdown(skillConfig.name, { '{{guidesBase}}': 'references/guides/', - '{{componentsBase}}': 'references/components/' + '{{componentsBase}}': 'references/components/', + '{{testingBase}}': 'references/testing/' }); let content = generateFrontmatter(skillConfig); diff --git a/packages/dev/s2-docs/skills/react-aria/test-utils-guidance.md b/packages/dev/s2-docs/skills/react-aria/test-utils-guidance.md new file mode 100644 index 00000000000..a5065f34528 --- /dev/null +++ b/packages/dev/s2-docs/skills/react-aria/test-utils-guidance.md @@ -0,0 +1,97 @@ +## Test utilities + +`@react-aria/test-utils` provides ARIA pattern testers that simulate mouse, keyboard, and touch interactions for components built with React Aria Components. + +### Installation + +```bash +npm install @react-aria/test-utils --save-dev +``` + +### Core pattern + +Initialize a `User` once per test file. Call `createTester` to get a tester for a specific ARIA pattern, then call tester methods to simulate interactions. + +```ts +import {User} from '@react-aria/test-utils'; + +// Provide whatever method of advancing timers you use in your test, this example assumes Jest with fake timers. +// 'interactionType' specifies what mode of interaction should be simulated by the tester +// 'advanceTimer' is used by the tester to advance the timers in the tests for specific interactions (e.g. long press) +let testUtilUser = new User({interactionType: 'mouse', advanceTimer: jest.advanceTimersByTime}); + +it('my test case', async function () { + // Render your test component/app + let {getByTestId} = render(); + // Initialize the table tester via providing the 'Table' pattern name and the root element of said table + let tableTester = testUtilUser.createTester('Table', {root: getByTestId('test_table')}); + expect(tableTester.selectedRows()).toHaveLength(0); + + await tableTester.toggleSelectAll(); + expect(tableTester.selectedRows()).toHaveLength(10); + ... +}); +``` + +Set `interactionType` to `'mouse'`, `'keyboard'`, or `'touch'`. Override per tester via `createTester(..., {interactionType})` or per method call. + +When using fake timers, pass `advanceTimer: jest.advanceTimersByTime` and flush timers after each test: + +```ts +afterEach(() => { + act(() => jest.runAllTimers()); +}); +``` + +### Tips and Tricks +- You can still simulate interactions manually in your test alongside the utilities provided by the tester. This can come in handy if you find that the tester doesn't cover a specific user flow or if one of its utilities isn't quite working as expected. After simulating your interaction, you can still +use the tester to query for the component's state or trigger a different interaction utility. +- Mouse drag interactions, simulated scrolling, and other mock reliant interactions are not available in these test utils since they depend heavily on how the user mocks things like clientHeight/Width/etc in their tests. These interactions need to be simulated manually by the user. +- Some testers may support the notion of "long press" for certain interactions (e.g. long pressing a button to trigger its menu). To simulate this, you will need mock PointerEvent globally (see the installPointerEvent util) and provide a way to advance timers to the User via `advanceTimer`. +- These test utils are compatible with not only JSDOM unit tests but browser tests as well (e.g. vitest-browser-react) + +### Draggable handle components + +Components with draggable handles (Slider, ColorArea, ColorSlider, ColorWheel) need `getBoundingClientRect` mocked so move calculations work: + +```ts +import {installMouseEvent} from '@react-spectrum/test-utils'; +installMouseEvent(); + +beforeAll(() => { + jest.spyOn(window.HTMLElement.prototype, 'getBoundingClientRect').mockImplementation( + () => ({top: 0, left: 0, width: 100, height: 10, bottom: 10, right: 100}) + ); +}); +``` + +### Available testers + +| Pattern name | Component | Key methods | +|---|---|---| +| `'CheckboxGroup'` | CheckboxGroup | `checkboxGroup()`, `checkboxes()`, `selectedCheckboxes()`, `toggleCheckbox({checkbox})` | +| `'ComboBox'` | ComboBox | `combobox()`, `listbox()`, `options()`, `open()`, `toggleOptionSelection({option})` | +| `'Dialog'` | Modal, Popover | `trigger()`, `dialog()`, `open()`, `close()` — pass `overlayType: 'modal'` or `'popover'` to `createTester` | +| `'GridList'` | GridList | `gridlist()`, `rows()`, `selectedRows()`, `toggleRowSelection({row})`, `triggerRowAction({row})` | +| `'ListBox'` | ListBox | `listbox()`, `options()`, `selectedOptions()`, `toggleOptionSelection({option})`, `triggerOptionAction({option})` | +| `'Menu'` | Menu | `trigger()`, `menu()`, `options()`, `open()`, `toggleOptionSelection({option})`, `openSubmenu({submenuTrigger})`, `close()` | +| `'RadioGroup'` | RadioGroup | `radiogroup()`, `radios()`, `selectedRadio()`, `triggerRadio({radio})` | +| `'Select'` | Select | `trigger()`, `listbox()`, `options()`, `toggleOptionSelection({option})` | +| `'Table'` | Table | `table()`, `rows()`, `columns()`, `selectedRows()`, `toggleRowSelection({row})`, `toggleSort({column})`, `triggerRowAction({row})` | +| `'Tabs'` | Tabs | `tablist()`, `tabs()`, `tabpanels()`, `selectedTab()`, `triggerTab({tab})` | +| `'Tree'` | Tree | `tree()`, `rows()`, `selectedRows()`, `toggleRowSelection({row})`, `toggleRowExpansion({row})`, `triggerRowAction({row})` | + +### Per-component reference + +- [CheckboxGroup]({{testingBase}}CheckboxGroup/testing.md) +- [ComboBox]({{testingBase}}ComboBox/testing.md) +- [GridList]({{testingBase}}GridList/testing.md) +- [ListBox]({{testingBase}}ListBox/testing.md) +- [Menu]({{testingBase}}Menu/testing.md) +- [Modal]({{testingBase}}Modal/testing.md) +- [Popover]({{testingBase}}Popover/testing.md) +- [RadioGroup]({{testingBase}}RadioGroup/testing.md) +- [Select]({{testingBase}}Select/testing.md) +- [Table]({{testingBase}}Table/testing.md) +- [Tabs]({{testingBase}}Tabs/testing.md) +- [Tree]({{testingBase}}Tree/testing.md) diff --git a/packages/dev/s2-docs/skills/react-spectrum-s2/test-utils-guidance.md b/packages/dev/s2-docs/skills/react-spectrum-s2/test-utils-guidance.md new file mode 100644 index 00000000000..c5d58b7a376 --- /dev/null +++ b/packages/dev/s2-docs/skills/react-spectrum-s2/test-utils-guidance.md @@ -0,0 +1,97 @@ +## Test utilities + +`@react-spectrum/test-utils` provides ARIA pattern testers that simulate mouse, keyboard, and touch interactions for components built with React Spectrum S2. + +### Installation + +```bash +npm install @react-spectrum/test-utils --save-dev +``` + +### Core pattern + +Initialize a `User` once per test file. Call `createTester` to get a tester for a specific ARIA pattern, then call tester methods to simulate interactions. + +```ts +import {User} from '@react-spectrum/test-utils'; + +// Provide whatever method of advancing timers you use in your test, this example assumes Jest with fake timers. +// 'interactionType' specifies what mode of interaction should be simulated by the tester +// 'advanceTimer' is used by the tester to advance the timers in the tests for specific interactions (e.g. long press) +let testUtilUser = new User({interactionType: 'mouse', advanceTimer: jest.advanceTimersByTime}); + +it('my test case', async function () { + // Render your test component/app + let {getByTestId} = render(); + // Initialize the table tester via providing the 'Table' pattern name and the root element of said table + let tableTester = testUtilUser.createTester('Table', {root: getByTestId('test_table')}); + expect(tableTester.selectedRows()).toHaveLength(0); + + await tableTester.toggleSelectAll(); + expect(tableTester.selectedRows()).toHaveLength(10); + ... +}); +``` + +Set `interactionType` to `'mouse'`, `'keyboard'`, or `'touch'`. Override per tester via `createTester(..., {interactionType})` or per method call. + +When using fake timers, pass `advanceTimer: jest.advanceTimersByTime` and flush timers after each test: + +```ts +afterEach(() => { + act(() => jest.runAllTimers()); +}); +``` + +### Tips and Tricks +- The testers typically offers these things: a way to simulate common user interactions for the given component, a way to get the various common elements that make up the component (e.g. the rows in a table), and a way to query the state of the component (e.g. get the selected rows in a table). Prefer using the testers for these use cases so that the user doesn't need to know what specific roles/elements/etc to target in their tests. +- You can still simulate interactions manually in your test alongside the utilities provided by the tester. This can come in handy if you find that the tester doesn't cover a specific user flow or if one of its utilities isn't quite working as expected. After simulating your interaction, you can still use the tester to query for the component's state or trigger a different interaction utility. +- Mouse drag interactions and other mock reliant interactions are not available in these test utils since they depended heavily on how the user mocked various things in their test. These must still be simulated manually by the user. +- Some testers may support the notion of "long press" for certain interactions (e.g. long pressing a button to trigger its menu). To simulate this, you will need to mock PointerEvent globally (see the `installPointerEvent` util) and provide a way to advance timers to the User via `advanceTimer`. +- These test utils are compatible with not only JSDOM unit tests but browser tests as well (e.g. vitest-browser-react). + +### Draggable handle components + +Components with draggable handles (Slider, ColorArea, ColorSlider, ColorWheel) need `getBoundingClientRect` mocked so move calculations work: + +```ts +import {installMouseEvent} from '@react-spectrum/test-utils'; +installMouseEvent(); + +beforeAll(() => { + jest.spyOn(window.HTMLElement.prototype, 'getBoundingClientRect').mockImplementation( + () => ({top: 0, left: 0, width: 100, height: 10, bottom: 10, right: 100}) + ); +}); +``` + +### Available testers + +The pattern name passed to `createTester` is the ARIA pattern name — not the S2 component name. + +| Pattern name | S2 component | Key methods | +|---|---|---| +| `'CheckboxGroup'` | CheckboxGroup | `checkboxGroup()`, `checkboxes()`, `selectedCheckboxes()`, `toggleCheckbox({checkbox})` | +| `'ComboBox'` | ComboBox | `combobox()`, `listbox()`, `options()`, `open()`, `toggleOptionSelection({option})` | +| `'Dialog'` | Dialog | `trigger()`, `dialog()`, `open()`, `close()` | +| `'GridList'` | ListView | `gridlist()`, `rows()`, `selectedRows()`, `toggleRowSelection({row})`, `triggerRowAction({row})` | +| `'Menu'` | Menu | `trigger()`, `menu()`, `options()`, `open()`, `toggleOptionSelection({option})`, `openSubmenu({submenuTrigger})`, `close()` | +| `'RadioGroup'` | RadioGroup | `radiogroup()`, `radios()`, `selectedRadio()`, `triggerRadio({radio})` | +| `'Select'` | Picker | `trigger()`, `listbox()`, `options()`, `toggleOptionSelection({option})` | +| `'Table'` | TableView | `table()`, `rows()`, `columns()`, `selectedRows()`, `toggleRowSelection({row})`, `toggleSort({column})`, `triggerRowAction({row})` | +| `'Tabs'` | Tabs | `tablist()`, `tabs()`, `tabpanels()`, `selectedTab()`, `triggerTab({tab})` | +| `'Tree'` | TreeView | `tree()`, `rows()`, `selectedRows()`, `toggleRowSelection({row})`, `toggleRowExpansion({row})`, `triggerRowAction({row})` | + + +### Per-component reference + +- [CheckboxGroup]({{testingBase}}CheckboxGroup/testing.md) +- [ComboBox]({{testingBase}}ComboBox/testing.md) +- [Dialog]({{testingBase}}Dialog/testing.md) +- [ListView]({{testingBase}}ListView/testing.md) +- [Menu]({{testingBase}}Menu/testing.md) +- [Picker]({{testingBase}}Picker/testing.md) +- [RadioGroup]({{testingBase}}RadioGroup/testing.md) +- [TableView]({{testingBase}}TableView/testing.md) +- [Tabs]({{testingBase}}Tabs/testing.md) +- [TreeView]({{testingBase}}TreeView/testing.md) From 3e6d64a46404de9907f957119ff94e862a19579b Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Thu, 30 Apr 2026 13:50:54 -0700 Subject: [PATCH 21/31] forgot to save --- packages/dev/s2-docs/skills/react-aria/test-utils-guidance.md | 3 ++- .../s2-docs/skills/react-spectrum-s2/test-utils-guidance.md | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/dev/s2-docs/skills/react-aria/test-utils-guidance.md b/packages/dev/s2-docs/skills/react-aria/test-utils-guidance.md index a5065f34528..2124f27ace8 100644 --- a/packages/dev/s2-docs/skills/react-aria/test-utils-guidance.md +++ b/packages/dev/s2-docs/skills/react-aria/test-utils-guidance.md @@ -44,11 +44,12 @@ afterEach(() => { ``` ### Tips and Tricks +- The testers typically offers these things: a way to simulate common user interactions for the given component via a specified user modality (e.g. using mouse vs keyboard to toggle a menu), a way to get the various common elements that make up the component (e.g. the rows in a table), and a way to query the state of the component (e.g. get the selected rows in a table). Prefer using the testers for these use cases so that the user doesn't need to know what specific roles/elements/etc to target in their tests. - You can still simulate interactions manually in your test alongside the utilities provided by the tester. This can come in handy if you find that the tester doesn't cover a specific user flow or if one of its utilities isn't quite working as expected. After simulating your interaction, you can still use the tester to query for the component's state or trigger a different interaction utility. - Mouse drag interactions, simulated scrolling, and other mock reliant interactions are not available in these test utils since they depend heavily on how the user mocks things like clientHeight/Width/etc in their tests. These interactions need to be simulated manually by the user. - Some testers may support the notion of "long press" for certain interactions (e.g. long pressing a button to trigger its menu). To simulate this, you will need mock PointerEvent globally (see the installPointerEvent util) and provide a way to advance timers to the User via `advanceTimer`. -- These test utils are compatible with not only JSDOM unit tests but browser tests as well (e.g. vitest-browser-react) +- These test utils are compatible with not only JSDOM unit tests but browser tests as well (e.g. vitest-browser-react). ### Draggable handle components diff --git a/packages/dev/s2-docs/skills/react-spectrum-s2/test-utils-guidance.md b/packages/dev/s2-docs/skills/react-spectrum-s2/test-utils-guidance.md index c5d58b7a376..ce4898c20d5 100644 --- a/packages/dev/s2-docs/skills/react-spectrum-s2/test-utils-guidance.md +++ b/packages/dev/s2-docs/skills/react-spectrum-s2/test-utils-guidance.md @@ -44,7 +44,7 @@ afterEach(() => { ``` ### Tips and Tricks -- The testers typically offers these things: a way to simulate common user interactions for the given component, a way to get the various common elements that make up the component (e.g. the rows in a table), and a way to query the state of the component (e.g. get the selected rows in a table). Prefer using the testers for these use cases so that the user doesn't need to know what specific roles/elements/etc to target in their tests. +- The testers typically offers these things: a way to simulate common user interactions for the given component via a specified user modality (e.g. using mouse vs keyboard to toggle a menu), a way to get the various common elements that make up the component (e.g. the rows in a table), and a way to query the state of the component (e.g. get the selected rows in a table). Prefer using the testers for these use cases so that the user doesn't need to know what specific roles/elements/etc to target in their tests. - You can still simulate interactions manually in your test alongside the utilities provided by the tester. This can come in handy if you find that the tester doesn't cover a specific user flow or if one of its utilities isn't quite working as expected. After simulating your interaction, you can still use the tester to query for the component's state or trigger a different interaction utility. - Mouse drag interactions and other mock reliant interactions are not available in these test utils since they depended heavily on how the user mocked various things in their test. These must still be simulated manually by the user. - Some testers may support the notion of "long press" for certain interactions (e.g. long pressing a button to trigger its menu). To simulate this, you will need to mock PointerEvent globally (see the `installPointerEvent` util) and provide a way to advance timers to the User via `advanceTimer`. From 1dc99d128426f30a4e6be955c28d9691e5c16d80 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Thu, 30 Apr 2026 16:36:51 -0700 Subject: [PATCH 22/31] improvements to skill guidence and utils from attempt to use skill to convert tests --- packages/@react-aria/test-utils/src/dialog.ts | 14 +++++--- packages/@react-aria/test-utils/src/menu.ts | 29 ++++++++--------- .../skills/react-aria/test-utils-guidance.md | 14 ++++++++ .../react-spectrum-s2/test-utils-guidance.md | 32 ++++++++++++++++++- 4 files changed, 68 insertions(+), 21 deletions(-) diff --git a/packages/@react-aria/test-utils/src/dialog.ts b/packages/@react-aria/test-utils/src/dialog.ts index 30167bae767..8e68bdd985c 100644 --- a/packages/@react-aria/test-utils/src/dialog.ts +++ b/packages/@react-aria/test-utils/src/dialog.ts @@ -34,13 +34,17 @@ export class DialogTester { this._interactionType = interactionType || 'mouse'; this._overlayType = overlayType || 'modal'; - // Handle case where element provided is a wrapper of the trigger button - let trigger = within(root).queryByRole('button'); - if (trigger) { - this._trigger = trigger; + // Handle case where element provided is a wrapper of the trigger button. + let buttons = within(root).queryAllByRole('button'); + let triggerButton: HTMLElement | undefined; + if (buttons.length === 0) { + triggerButton = root; + } else if (buttons.length === 1) { + triggerButton = buttons[0]; } else { - this._trigger = root; + triggerButton = buttons.find(button => button.hasAttribute('aria-haspopup')); } + this._trigger = triggerButton ?? root; } /** diff --git a/packages/@react-aria/test-utils/src/menu.ts b/packages/@react-aria/test-utils/src/menu.ts index ffbae2c7eb8..19e2b76fa8a 100644 --- a/packages/@react-aria/test-utils/src/menu.ts +++ b/packages/@react-aria/test-utils/src/menu.ts @@ -77,13 +77,17 @@ export class MenuTester { if (root.getAttribute('role') === 'menuitem') { this._trigger = root; } else { - // Handle case where element provided is a wrapper of the trigger button - let trigger = within(root).queryByRole('button'); - if (trigger) { - this._trigger = trigger; + // Handle case where element provided is a wrapper of the trigger button. + let buttons = within(root).queryAllByRole('button'); + let triggerButton: HTMLElement | undefined; + if (buttons.length === 0) { + triggerButton = root; + } else if (buttons.length === 1) { + triggerButton = buttons[0]; } else { - this._trigger = root; + triggerButton = buttons.find(button => button.hasAttribute('aria-haspopup')); } + this._trigger = triggerButton ?? root; } this._isSubmenu = isSubmenu || false; @@ -413,18 +417,13 @@ export class MenuTester { */ options(opts: {element?: HTMLElement} = {}): HTMLElement[] { let {element = this.menu()} = opts; - let options: HTMLElement[] = []; - if (element) { - options = within(element).queryAllByRole('menuitem'); - if (options.length === 0) { - options = within(element).queryAllByRole('menuitemradio'); - if (options.length === 0) { - options = within(element).queryAllByRole('menuitemcheckbox'); - } - } + if (!element) { + return []; } - return options; + return Array.from( + element.querySelectorAll('[role=menuitem], [role=menuitemradio], [role=menuitemcheckbox]') + ) as HTMLElement[]; } /** diff --git a/packages/dev/s2-docs/skills/react-aria/test-utils-guidance.md b/packages/dev/s2-docs/skills/react-aria/test-utils-guidance.md index 2124f27ace8..901b22fc5b2 100644 --- a/packages/dev/s2-docs/skills/react-aria/test-utils-guidance.md +++ b/packages/dev/s2-docs/skills/react-aria/test-utils-guidance.md @@ -10,6 +10,11 @@ npm install @react-aria/test-utils --save-dev ### Core pattern +External consumers should import from `@react-aria/test-utils`. Tests inside the `packages/` monorepo should import everything from `@react-spectrum/test-utils-internal`, which re-exports `User` and all other test utilities: +```ts +import {act, render, User} from '@react-spectrum/test-utils-internal'; +``` + Initialize a `User` once per test file. Call `createTester` to get a tester for a specific ARIA pattern, then call tester methods to simulate interactions. ```ts @@ -51,6 +56,15 @@ use the tester to query for the component's state or trigger a different interac - Some testers may support the notion of "long press" for certain interactions (e.g. long pressing a button to trigger its menu). To simulate this, you will need mock PointerEvent globally (see the installPointerEvent util) and provide a way to advance timers to the User via `advanceTimer`. - These test utils are compatible with not only JSDOM unit tests but browser tests as well (e.g. vitest-browser-react). +### When not to use the testers + +Skip the testers and write manual interactions for the following cases: + +- When testing a Menu or Dialog rendered without a trigger. The testers assumes a trigger exists. +- tests that verify exact focus order, arrow key cycling, or specific modifier key behavior. Use `fireEvent.keyDown` or `userEvent.keyboard` directly so the test is actually testing the desired keyboard flow. +- when `isOpen` or `defaultOpen` is set, `open()` will no-op but the tester's `root` must still resolve to the trigger element. Use `getByLabelText` or `getByTestId` rather than `getByRole('button')` to avoid ambiguity when multiple buttons are in the DOM. +- testing `isDismissible`, `isKeyboardDismissDisabled`, or outside-click behavior. Use `userEvent.click(document.body)` or `user.keyboard('[Escape]')` directly and assert the expected state afterwards. + ### Draggable handle components Components with draggable handles (Slider, ColorArea, ColorSlider, ColorWheel) need `getBoundingClientRect` mocked so move calculations work: diff --git a/packages/dev/s2-docs/skills/react-spectrum-s2/test-utils-guidance.md b/packages/dev/s2-docs/skills/react-spectrum-s2/test-utils-guidance.md index ce4898c20d5..4c27bd64a1b 100644 --- a/packages/dev/s2-docs/skills/react-spectrum-s2/test-utils-guidance.md +++ b/packages/dev/s2-docs/skills/react-spectrum-s2/test-utils-guidance.md @@ -10,6 +10,11 @@ npm install @react-spectrum/test-utils --save-dev ### Core pattern +External consumers import from `@react-spectrum/test-utils`. Tests inside the `packages/` monorepo should import everything from `@react-spectrum/test-utils-internal`, which re-exports `User` and all other test utilities: + ```ts +import {act, render, User} from '@react-spectrum/test-utils-internal'; +``` + Initialize a `User` once per test file. Call `createTester` to get a tester for a specific ARIA pattern, then call tester methods to simulate interactions. ```ts @@ -50,6 +55,15 @@ afterEach(() => { - Some testers may support the notion of "long press" for certain interactions (e.g. long pressing a button to trigger its menu). To simulate this, you will need to mock PointerEvent globally (see the `installPointerEvent` util) and provide a way to advance timers to the User via `advanceTimer`. - These test utils are compatible with not only JSDOM unit tests but browser tests as well (e.g. vitest-browser-react). +### When not to use the testers + +Skip the testers and write manual interactions for the following cases: + +- When testing a Menu or Dialog rendered without a trigger. The testers assumes a trigger exists. +- tests that verify exact focus order, arrow key cycling, or specific modifier key behavior. Use `fireEvent.keyDown` or `userEvent.keyboard` directly so the test is actually testing the desired keyboard flow. +- when `isOpen` or `defaultOpen` is set, `open()` will no-op but the tester's `root` must still resolve to the trigger element. Use `getByLabelText` or `getByTestId` rather than `getByRole('button')` to avoid ambiguity when multiple buttons are in the DOM. +- testing `isDismissible`, `isKeyboardDismissDisabled`, or outside-click behavior. Use `userEvent.click(document.body)` or `user.keyboard('[Escape]')` directly and assert the expected state afterwards. + ### Draggable handle components Components with draggable handles (Slider, ColorArea, ColorSlider, ColorWheel) need `getBoundingClientRect` mocked so move calculations work: @@ -73,7 +87,7 @@ The pattern name passed to `createTester` is the ARIA pattern name — not the S |---|---|---| | `'CheckboxGroup'` | CheckboxGroup | `checkboxGroup()`, `checkboxes()`, `selectedCheckboxes()`, `toggleCheckbox({checkbox})` | | `'ComboBox'` | ComboBox | `combobox()`, `listbox()`, `options()`, `open()`, `toggleOptionSelection({option})` | -| `'Dialog'` | Dialog | `trigger()`, `dialog()`, `open()`, `close()` | +| `'Dialog'` | Dialog | `trigger()`, `dialog()`, `open()`, `close()` — pass `overlayType: 'modal'` or `'popover'` to `createTester` | | `'GridList'` | ListView | `gridlist()`, `rows()`, `selectedRows()`, `toggleRowSelection({row})`, `triggerRowAction({row})` | | `'Menu'` | Menu | `trigger()`, `menu()`, `options()`, `open()`, `toggleOptionSelection({option})`, `openSubmenu({submenuTrigger})`, `close()` | | `'RadioGroup'` | RadioGroup | `radiogroup()`, `radios()`, `selectedRadio()`, `triggerRadio({radio})` | @@ -82,6 +96,22 @@ The pattern name passed to `createTester` is the ARIA pattern name — not the S | `'Tabs'` | Tabs | `tablist()`, `tabs()`, `tabpanels()`, `selectedTab()`, `triggerTab({tab})` | | `'Tree'` | TreeView | `tree()`, `rows()`, `selectedRows()`, `toggleRowSelection({row})`, `toggleRowExpansion({row})`, `triggerRowAction({row})` | +#### Dialog `overlayType` reference + +Pass `overlayType` to `createTester` so the tester knows how the overlay is mounted: + +| S2 component | `overlayType` | +|---|---| +| `Dialog` | `'modal'` | +| `AlertDialog` | `'modal'` | +| `CustomDialog` | `'modal'` | +| Popover-based dialogs | `'popover'` | + +```ts +let dialogTester = testUtilUser.createTester('Dialog', {root: tree.getByRole('button'), overlayType: 'modal'}); +await dialogTester.open(); +expect(dialogTester.dialog()).toBeVisible(); +``` ### Per-component reference From 3fac945d822f661631491842c0b03c7edbcc90c2 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Thu, 30 Apr 2026 17:05:19 -0700 Subject: [PATCH 23/31] more improvements from second pass --- .../dev/s2-docs/skills/react-aria/test-utils-guidance.md | 5 ++++- .../s2-docs/skills/react-spectrum-s2/test-utils-guidance.md | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/dev/s2-docs/skills/react-aria/test-utils-guidance.md b/packages/dev/s2-docs/skills/react-aria/test-utils-guidance.md index 901b22fc5b2..b0b301c004d 100644 --- a/packages/dev/s2-docs/skills/react-aria/test-utils-guidance.md +++ b/packages/dev/s2-docs/skills/react-aria/test-utils-guidance.md @@ -55,15 +55,18 @@ use the tester to query for the component's state or trigger a different interac - Mouse drag interactions, simulated scrolling, and other mock reliant interactions are not available in these test utils since they depend heavily on how the user mocks things like clientHeight/Width/etc in their tests. These interactions need to be simulated manually by the user. - Some testers may support the notion of "long press" for certain interactions (e.g. long pressing a button to trigger its menu). To simulate this, you will need mock PointerEvent globally (see the installPointerEvent util) and provide a way to advance timers to the User via `advanceTimer`. - These test utils are compatible with not only JSDOM unit tests but browser tests as well (e.g. vitest-browser-react). +- Methods that accept a target (`option`, `row`, `column`, `checkbox`, `radio`, `tab`) take a `number` (index), `string` (text content), or `HTMLElement`. Use the tester's own query methods (e.g. `rows()`, `options()`) to obtain an `HTMLElement` when you need one. +- Link navigation assertions must be simulated manually. The testers do not assert navigation side effects. ### When not to use the testers Skip the testers and write manual interactions for the following cases: -- When testing a Menu or Dialog rendered without a trigger. The testers assumes a trigger exists. +- When testing a Menu or Dialog rendered without a trigger, or when testing interactive elements embedded inside rows or cells (e.g. an ActionMenu inside a TreeView row). The testers assume a trigger exists and do not reach into row/cell content. - tests that verify exact focus order, arrow key cycling, or specific modifier key behavior. Use `fireEvent.keyDown` or `userEvent.keyboard` directly so the test is actually testing the desired keyboard flow. - when `isOpen` or `defaultOpen` is set, `open()` will no-op but the tester's `root` must still resolve to the trigger element. Use `getByLabelText` or `getByTestId` rather than `getByRole('button')` to avoid ambiguity when multiple buttons are in the DOM. - testing `isDismissible`, `isKeyboardDismissDisabled`, or outside-click behavior. Use `userEvent.click(document.body)` or `user.keyboard('[Escape]')` directly and assert the expected state afterwards. +- when a Dialog closes via an action button (not the explicit close/dismiss button) you should instead click that button manually, then use `dialogTester.dialog()` to assert whether the dialog is still present. ### Draggable handle components diff --git a/packages/dev/s2-docs/skills/react-spectrum-s2/test-utils-guidance.md b/packages/dev/s2-docs/skills/react-spectrum-s2/test-utils-guidance.md index 4c27bd64a1b..3f9a65b544a 100644 --- a/packages/dev/s2-docs/skills/react-spectrum-s2/test-utils-guidance.md +++ b/packages/dev/s2-docs/skills/react-spectrum-s2/test-utils-guidance.md @@ -54,15 +54,18 @@ afterEach(() => { - Mouse drag interactions and other mock reliant interactions are not available in these test utils since they depended heavily on how the user mocked various things in their test. These must still be simulated manually by the user. - Some testers may support the notion of "long press" for certain interactions (e.g. long pressing a button to trigger its menu). To simulate this, you will need to mock PointerEvent globally (see the `installPointerEvent` util) and provide a way to advance timers to the User via `advanceTimer`. - These test utils are compatible with not only JSDOM unit tests but browser tests as well (e.g. vitest-browser-react). +- Methods that accept a target (`option`, `row`, `column`, `checkbox`, `radio`, `tab`) take a `number` (index), `string` (text content), or `HTMLElement`. Use the tester's own query methods (e.g. `rows()`, `options()`) to obtain an `HTMLElement` when you need one. +- Link navigation assertions must be simulated manually. The testers do not assert navigation side effects. ### When not to use the testers Skip the testers and write manual interactions for the following cases: -- When testing a Menu or Dialog rendered without a trigger. The testers assumes a trigger exists. +- When testing a Menu or Dialog rendered without a trigger, or when testing interactive elements embedded inside rows or cells (e.g. an ActionMenu inside a TreeView row). The testers assume a trigger exists and do not reach into row/cell content. - tests that verify exact focus order, arrow key cycling, or specific modifier key behavior. Use `fireEvent.keyDown` or `userEvent.keyboard` directly so the test is actually testing the desired keyboard flow. - when `isOpen` or `defaultOpen` is set, `open()` will no-op but the tester's `root` must still resolve to the trigger element. Use `getByLabelText` or `getByTestId` rather than `getByRole('button')` to avoid ambiguity when multiple buttons are in the DOM. - testing `isDismissible`, `isKeyboardDismissDisabled`, or outside-click behavior. Use `userEvent.click(document.body)` or `user.keyboard('[Escape]')` directly and assert the expected state afterwards. +- when a Dialog closes via an action button (not the explicit close/dismiss button) you should instead click that button manually, then use `dialogTester.dialog()` to assert whether the dialog is still present. ### Draggable handle components From bc32b8540b759d60390509d70b574ae58cd91ebf Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Fri, 1 May 2026 10:44:42 -0700 Subject: [PATCH 24/31] add getter for table footer --- packages/@react-aria/test-utils/src/table.ts | 8 ++++++++ .../dev/s2-docs/skills/react-aria/test-utils-guidance.md | 2 +- .../skills/react-spectrum-s2/test-utils-guidance.md | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/@react-aria/test-utils/src/table.ts b/packages/@react-aria/test-utils/src/table.ts index c68a20c48f1..b61288d303e 100644 --- a/packages/@react-aria/test-utils/src/table.ts +++ b/packages/@react-aria/test-utils/src/table.ts @@ -522,6 +522,14 @@ export class TableTester { return this.rows().filter(row => row.getAttribute('aria-selected') === 'true'); } + /** + * Returns the footer rows within the table if any. + */ + footerRows(): HTMLElement[] { + let footerRowGroup = this.rowGroups()[2]; + return footerRowGroup ? within(footerRowGroup).queryAllByRole('row') : []; + } + /** * Returns the row headers within the table if any. */ diff --git a/packages/dev/s2-docs/skills/react-aria/test-utils-guidance.md b/packages/dev/s2-docs/skills/react-aria/test-utils-guidance.md index b0b301c004d..37cc79b8484 100644 --- a/packages/dev/s2-docs/skills/react-aria/test-utils-guidance.md +++ b/packages/dev/s2-docs/skills/react-aria/test-utils-guidance.md @@ -95,7 +95,7 @@ beforeAll(() => { | `'Menu'` | Menu | `trigger()`, `menu()`, `options()`, `open()`, `toggleOptionSelection({option})`, `openSubmenu({submenuTrigger})`, `close()` | | `'RadioGroup'` | RadioGroup | `radiogroup()`, `radios()`, `selectedRadio()`, `triggerRadio({radio})` | | `'Select'` | Select | `trigger()`, `listbox()`, `options()`, `toggleOptionSelection({option})` | -| `'Table'` | Table | `table()`, `rows()`, `columns()`, `selectedRows()`, `toggleRowSelection({row})`, `toggleSort({column})`, `triggerRowAction({row})` | +| `'Table'` | Table | `table()`, `rows()`, `footerRows()`, `columns()`, `selectedRows()`, `toggleRowSelection({row})`, `toggleSort({column})`, `triggerRowAction({row})` | | `'Tabs'` | Tabs | `tablist()`, `tabs()`, `tabpanels()`, `selectedTab()`, `triggerTab({tab})` | | `'Tree'` | Tree | `tree()`, `rows()`, `selectedRows()`, `toggleRowSelection({row})`, `toggleRowExpansion({row})`, `triggerRowAction({row})` | diff --git a/packages/dev/s2-docs/skills/react-spectrum-s2/test-utils-guidance.md b/packages/dev/s2-docs/skills/react-spectrum-s2/test-utils-guidance.md index 3f9a65b544a..1be6cc86411 100644 --- a/packages/dev/s2-docs/skills/react-spectrum-s2/test-utils-guidance.md +++ b/packages/dev/s2-docs/skills/react-spectrum-s2/test-utils-guidance.md @@ -95,7 +95,7 @@ The pattern name passed to `createTester` is the ARIA pattern name — not the S | `'Menu'` | Menu | `trigger()`, `menu()`, `options()`, `open()`, `toggleOptionSelection({option})`, `openSubmenu({submenuTrigger})`, `close()` | | `'RadioGroup'` | RadioGroup | `radiogroup()`, `radios()`, `selectedRadio()`, `triggerRadio({radio})` | | `'Select'` | Picker | `trigger()`, `listbox()`, `options()`, `toggleOptionSelection({option})` | -| `'Table'` | TableView | `table()`, `rows()`, `columns()`, `selectedRows()`, `toggleRowSelection({row})`, `toggleSort({column})`, `triggerRowAction({row})` | +| `'Table'` | TableView | `table()`, `rows()`, `footerRows()`, `columns()`, `selectedRows()`, `toggleRowSelection({row})`, `toggleSort({column})`, `triggerRowAction({row})` | | `'Tabs'` | Tabs | `tablist()`, `tabs()`, `tabpanels()`, `selectedTab()`, `triggerTab({tab})` | | `'Tree'` | TreeView | `tree()`, `rows()`, `selectedRows()`, `toggleRowSelection({row})`, `toggleRowExpansion({row})`, `triggerRowAction({row})` | From ed0919b467d5247d89b088a584e1e15f5aa4486a Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Fri, 8 May 2026 15:23:26 -0700 Subject: [PATCH 25/31] formatting --- .../test/menu/MenuTrigger.test.js | 86 +++++++----- packages/@react-aria/test-utils/src/act.ts | 6 +- .../s2/test/CheckboxGroup.browser.test.tsx | 17 +-- .../s2/test/Combobox.browser.test.tsx | 6 +- .../s2/test/Menu.browser.test.tsx | 7 +- .../s2/test/Picker.browser.test.tsx | 2 +- .../s2/test/RadioGroup.browser.test.tsx | 17 +-- .../s2/test/RadioGroup.test.tsx | 86 ++++++------ .../s2/test/TableView.browser.test.tsx | 11 +- .../s2/test/TreeView.browser.test.tsx | 44 ++++-- .../s2-docs/scripts/generateAgentSkills.mjs | 10 +- .../test/Dialog.browser.test.tsx | 9 +- .../test/GridList.browser.test.tsx | 6 +- .../test/ListBox.browser.test.tsx | 39 +++--- .../react-aria-components/test/Menu.test.tsx | 129 ++++++++++-------- .../test/Tabs.browser.test.tsx | 5 +- 16 files changed, 279 insertions(+), 201 deletions(-) diff --git a/packages/@adobe/react-spectrum/test/menu/MenuTrigger.test.js b/packages/@adobe/react-spectrum/test/menu/MenuTrigger.test.js index 29bab188fa0..53d15532447 100644 --- a/packages/@adobe/react-spectrum/test/menu/MenuTrigger.test.js +++ b/packages/@adobe/react-spectrum/test/menu/MenuTrigger.test.js @@ -277,27 +277,31 @@ describe('MenuTrigger', function () { expect(onOpen).toBeCalledTimes(1); expect(onClose).toBeCalledTimes(0); } - } - await menuTester.toggleOptionSelection({option: 'Foo', menuSelectionMode: 'single', closesOnSelect: false}); + await menuTester.toggleOptionSelection({ + option: 'Foo', + menuSelectionMode: 'single', + closesOnSelect: false + }); - if (Component === MenuTrigger) { - expect(onSelectionChange).toBeCalledTimes(1); - } else { - expect(onSelect).toBeCalledTimes(1); - } + if (Component === MenuTrigger) { + expect(onSelectionChange).toBeCalledTimes(1); + } else { + expect(onSelect).toBeCalledTimes(1); + } - expect(menuTester.menu()).toBeInTheDocument(); + expect(menuTester.menu()).toBeInTheDocument(); - if (Component === MenuTrigger) { - expect(menuTester.trigger()).toHaveAttribute('aria-expanded', 'true'); - expect(onOpenChange).toBeCalledTimes(1); - } else { - expect(menuTester.trigger()).toHaveAttribute('aria-expanded'); - expect(onOpen).toBeCalledTimes(1); - expect(onClose).toBeCalledTimes(0); + if (Component === MenuTrigger) { + expect(menuTester.trigger()).toHaveAttribute('aria-expanded', 'true'); + expect(onOpenChange).toBeCalledTimes(1); + } else { + expect(menuTester.trigger()).toHaveAttribute('aria-expanded'); + expect(onOpen).toBeCalledTimes(1); + expect(onClose).toBeCalledTimes(0); + } } - }); + ); it.each` Name | Component | props @@ -310,15 +314,20 @@ describe('MenuTrigger', function () { expect(onOpenChange).toBeCalledTimes(0); await menuTester.open(); - expect(onOpenChange).toBeCalledTimes(1); - expect(onSelectionChange).toBeCalledTimes(0); - menuTester.setInteractionType('keyboard'); - await menuTester.toggleOptionSelection({option: 'Foo', menuSelectionMode: 'single', closesOnSelect: false}); + expect(onOpenChange).toBeCalledTimes(1); + expect(onSelectionChange).toBeCalledTimes(0); + menuTester.setInteractionType('keyboard'); + await menuTester.toggleOptionSelection({ + option: 'Foo', + menuSelectionMode: 'single', + closesOnSelect: false + }); - expect(menuTester.menu()).toBeInTheDocument(); - expect(menuTester.trigger()).toHaveAttribute('aria-expanded', 'true'); - expect(onOpenChange).toBeCalledTimes(1); - }); + expect(menuTester.menu()).toBeInTheDocument(); + expect(menuTester.trigger()).toHaveAttribute('aria-expanded', 'true'); + expect(onOpenChange).toBeCalledTimes(1); + } + ); it.each` Name | Component | props @@ -341,17 +350,26 @@ describe('MenuTrigger', function () { expect(onOpenChange).toBeCalledTimes(1); expect(onSelectionChange).toBeCalledTimes(0); - await menuTester.toggleOptionSelection({option: 'Foo', menuSelectionMode: 'multiple', keyboardActivation: 'Space'}); - expect(onSelectionChange).toBeCalledTimes(1); - expect(onSelectionChange.mock.calls[0][0].has('Foo')).toBeTruthy(); - await menuTester.toggleOptionSelection({option: 'Bar', menuSelectionMode: 'multiple', keyboardActivation: 'Space'}); - expect(onSelectionChange).toBeCalledTimes(2); - expect(onSelectionChange.mock.calls[1][0].has('Bar')).toBeTruthy(); + await menuTester.toggleOptionSelection({ + option: 'Foo', + menuSelectionMode: 'multiple', + keyboardActivation: 'Space' + }); + expect(onSelectionChange).toBeCalledTimes(1); + expect(onSelectionChange.mock.calls[0][0].has('Foo')).toBeTruthy(); + await menuTester.toggleOptionSelection({ + option: 'Bar', + menuSelectionMode: 'multiple', + keyboardActivation: 'Space' + }); + expect(onSelectionChange).toBeCalledTimes(2); + expect(onSelectionChange.mock.calls[1][0].has('Bar')).toBeTruthy(); - await menuTester.close(); - expect(menuTester.menu()).not.toBeInTheDocument(); - expect(onOpenChange).toBeCalledTimes(2); - }); + await menuTester.close(); + expect(menuTester.menu()).not.toBeInTheDocument(); + expect(onOpenChange).toBeCalledTimes(2); + } + ); it.each` Name | Component | props | menuProps diff --git a/packages/@react-aria/test-utils/src/act.ts b/packages/@react-aria/test-utils/src/act.ts index f034af349de..b8ecf325d31 100644 --- a/packages/@react-aria/test-utils/src/act.ts +++ b/packages/@react-aria/test-utils/src/act.ts @@ -23,7 +23,11 @@ if (typeof React.act === 'function') { export const act: typeof actImpl = ((fn: any) => { // only wrap in act if in test environment, breaks vite browser test if test utils are used otherwise // @ts-ignore - if (typeof IS_REACT_ACT_ENVIRONMENT === 'boolean' ? IS_REACT_ACT_ENVIRONMENT : typeof jest !== 'undefined') { + if ( + typeof IS_REACT_ACT_ENVIRONMENT === 'boolean' + ? IS_REACT_ACT_ENVIRONMENT + : typeof jest !== 'undefined' + ) { return actImpl(fn); } return fn(); diff --git a/packages/@react-spectrum/s2/test/CheckboxGroup.browser.test.tsx b/packages/@react-spectrum/s2/test/CheckboxGroup.browser.test.tsx index baa972110a5..c31bb0882b9 100644 --- a/packages/@react-spectrum/s2/test/CheckboxGroup.browser.test.tsx +++ b/packages/@react-spectrum/s2/test/CheckboxGroup.browser.test.tsx @@ -20,19 +20,13 @@ import {User} from '@react-aria/test-utils'; function CheckboxGroupExample() { return ( - + Product Updates - + Security Alerts - + Marketing Emails @@ -47,7 +41,10 @@ it.each` let testUtilUser = new User(); let {container} = await render(); - let tester = testUtilUser.createTester('CheckboxGroup', {root: container.querySelector('[role=group]') as HTMLElement, interactionType}); + let tester = testUtilUser.createTester('CheckboxGroup', { + root: container.querySelector('[role=group]') as HTMLElement, + interactionType + }); let checkboxes = tester.checkboxes(); await tester.toggleCheckbox({checkbox: checkboxes[2]}); expect(tester.selectedCheckboxes()).toContain(checkboxes[2]); diff --git a/packages/@react-spectrum/s2/test/Combobox.browser.test.tsx b/packages/@react-spectrum/s2/test/Combobox.browser.test.tsx index 42aae0a31ba..4777219650d 100644 --- a/packages/@react-spectrum/s2/test/Combobox.browser.test.tsx +++ b/packages/@react-spectrum/s2/test/Combobox.browser.test.tsx @@ -31,7 +31,11 @@ let items = [ function ComboBoxExample() { return ( - {(item) => {item.name}} + {item => ( + + {item.name} + + )} ); } diff --git a/packages/@react-spectrum/s2/test/Menu.browser.test.tsx b/packages/@react-spectrum/s2/test/Menu.browser.test.tsx index cc6bc1f208d..dd15f6d7442 100644 --- a/packages/@react-spectrum/s2/test/Menu.browser.test.tsx +++ b/packages/@react-spectrum/s2/test/Menu.browser.test.tsx @@ -34,7 +34,7 @@ function MenuExample({onAction}) { - {(item) => {item.name}} + {item => {item.name}} ); @@ -49,7 +49,10 @@ it.each` let testUtilUser = new User(); let {container} = await render(); - let tester = testUtilUser.createTester('Menu', {root: container.querySelector('button') as HTMLElement, interactionType}); + let tester = testUtilUser.createTester('Menu', { + root: container.querySelector('button') as HTMLElement, + interactionType + }); await tester.open(); await tester.toggleOptionSelection({option: 2}); expect(onAction).toHaveBeenCalledWith(3); diff --git a/packages/@react-spectrum/s2/test/Picker.browser.test.tsx b/packages/@react-spectrum/s2/test/Picker.browser.test.tsx index 1ecb93eac85..fda4b5ba325 100644 --- a/packages/@react-spectrum/s2/test/Picker.browser.test.tsx +++ b/packages/@react-spectrum/s2/test/Picker.browser.test.tsx @@ -31,7 +31,7 @@ let items = [ function PickerExample() { return ( - {(item: typeof items[number]) => {item.name}} + {(item: (typeof items)[number]) => {item.name}} ); } diff --git a/packages/@react-spectrum/s2/test/RadioGroup.browser.test.tsx b/packages/@react-spectrum/s2/test/RadioGroup.browser.test.tsx index 6b684dea170..8f0a5e88b89 100644 --- a/packages/@react-spectrum/s2/test/RadioGroup.browser.test.tsx +++ b/packages/@react-spectrum/s2/test/RadioGroup.browser.test.tsx @@ -19,19 +19,13 @@ import {User} from '@react-aria/test-utils'; function RadioGroupExample() { return ( - + Standard Shipping (Free) - + Expedited Shipping ($9.99) - + Overnight Shipping ($19.99) @@ -46,7 +40,10 @@ it.each` let testUtilUser = new User(); let {container} = await render(); - let tester = testUtilUser.createTester('RadioGroup', {root: container.querySelector('[role=radiogroup]') as HTMLElement, interactionType}); + let tester = testUtilUser.createTester('RadioGroup', { + root: container.querySelector('[role=radiogroup]') as HTMLElement, + interactionType + }); let radios = tester.radios(); await tester.triggerRadio({radio: radios[1]}); expect(tester.selectedRadio()).toBe(radios[1]); diff --git a/packages/@react-spectrum/s2/test/RadioGroup.test.tsx b/packages/@react-spectrum/s2/test/RadioGroup.test.tsx index b6509a2757a..121e681ffd5 100644 --- a/packages/@react-spectrum/s2/test/RadioGroup.test.tsx +++ b/packages/@react-spectrum/s2/test/RadioGroup.test.tsx @@ -26,53 +26,63 @@ describe('RadioGroup', () => { }); it.each` - Name | props - ${'ltr + vertical'} | ${{locale: 'de-DE', orientation: 'vertical'}} - ${'rtl + verfical'} | ${{locale: 'ar-AE', orientation: 'vertical'}} - ${'ltr + horizontal'} | ${{locale: 'de-DE', orientation: 'horizontal'}} - ${'rtl + horizontal'} | ${{locale: 'ar-AE', orientation: 'horizontal'}} - `('$Name should select the correct radio via keyboard regardless of orientation and disabled radios', async function ({props}) { - let {getByRole} = render( - - - Dogs - Cats - Dragons - Unicorns - Chocobo - - - ); - let direction = props.locale === 'ar-AE' ? 'rtl' : 'ltr' as Direction; - let radioGroupTester = testUtilUser.createTester('RadioGroup', {root: getByRole('radiogroup'), direction}); - expect(radioGroupTester.radiogroup()).toHaveAttribute('aria-orientation', props.orientation); - let radios = radioGroupTester.radios(); - await radioGroupTester.triggerRadio({radio: radios[0]}); - expect(radios[0]).toBeChecked(); + Name | props + ${'ltr + vertical'} | ${{locale: 'de-DE', orientation: 'vertical'}} + ${'rtl + verfical'} | ${{locale: 'ar-AE', orientation: 'vertical'}} + ${'ltr + horizontal'} | ${{locale: 'de-DE', orientation: 'horizontal'}} + ${'rtl + horizontal'} | ${{locale: 'ar-AE', orientation: 'horizontal'}} + `( + '$Name should select the correct radio via keyboard regardless of orientation and disabled radios', + async function ({props}) { + let {getByRole} = render( + + + Dogs + + Cats + + + Dragons + + Unicorns + Chocobo + + + ); + let direction = props.locale === 'ar-AE' ? 'rtl' : ('ltr' as Direction); + let radioGroupTester = testUtilUser.createTester('RadioGroup', { + root: getByRole('radiogroup'), + direction + }); + expect(radioGroupTester.radiogroup()).toHaveAttribute('aria-orientation', props.orientation); + let radios = radioGroupTester.radios(); + await radioGroupTester.triggerRadio({radio: radios[0]}); + expect(radios[0]).toBeChecked(); await radioGroupTester.triggerRadio({radio: 4, interactionType: 'keyboard'}); expect(radios[4]).toBeChecked(); - let radio4 = radioGroupTester.findRadio({indexOrText: 3}); - await radioGroupTester.triggerRadio({radio: radio4, interactionType: 'keyboard'}); - expect(radios[3]).toBeChecked(); + let radio4 = radioGroupTester.findRadio({indexOrText: 3}); + await radioGroupTester.triggerRadio({radio: radio4, interactionType: 'keyboard'}); + expect(radios[3]).toBeChecked(); await radioGroupTester.triggerRadio({radio: 'Dogs', interactionType: 'mouse'}); expect(radios[0]).toBeChecked(); - let radio5 = radioGroupTester.findRadio({indexOrText: 'Chocobo'}); - await radioGroupTester.triggerRadio({radio: radio5, interactionType: 'mouse'}); - expect(radios[4]).toBeChecked(); + let radio5 = radioGroupTester.findRadio({indexOrText: 'Chocobo'}); + await radioGroupTester.triggerRadio({radio: radio5, interactionType: 'mouse'}); + expect(radios[4]).toBeChecked(); - // This isn't using the radioGroup tester because the tester uses the attached aria-orientation to determine - // what arrow to press, which won't reproduce the original bug where we forgot to pass the orientation to the RadioGroup. - // The tester ends up still pressing the correct keys (ArrowUp/ArrowDown) to navigate properly even in the horizontal orientation - // instead of using ArrowLeft/ArrowRight - await user.keyboard('[ArrowLeft]'); - if (props.locale === 'ar-AE' && props.orientation === 'horizontal') { - expect(radioGroupTester.selectedRadio()).toBe(radios[0]); - } else { - expect(radioGroupTester.selectedRadio()).toBe(radios[3]); + // This isn't using the radioGroup tester because the tester uses the attached aria-orientation to determine + // what arrow to press, which won't reproduce the original bug where we forgot to pass the orientation to the RadioGroup. + // The tester ends up still pressing the correct keys (ArrowUp/ArrowDown) to navigate properly even in the horizontal orientation + // instead of using ArrowLeft/ArrowRight + await user.keyboard('[ArrowLeft]'); + if (props.locale === 'ar-AE' && props.orientation === 'horizontal') { + expect(radioGroupTester.selectedRadio()).toBe(radios[0]); + } else { + expect(radioGroupTester.selectedRadio()).toBe(radios[3]); + } } ); }); diff --git a/packages/@react-spectrum/s2/test/TableView.browser.test.tsx b/packages/@react-spectrum/s2/test/TableView.browser.test.tsx index 8452c40b675..444f010f400 100644 --- a/packages/@react-spectrum/s2/test/TableView.browser.test.tsx +++ b/packages/@react-spectrum/s2/test/TableView.browser.test.tsx @@ -35,12 +35,12 @@ function TableExample() { return ( - {(column) => {column.name}} + {column => {column.name}} - {(item) => ( + {item => ( - {(column) => {item[column.id]}} + {column => {item[column.id]}} )} @@ -56,7 +56,10 @@ it.each` let testUtilUser = new User(); let {container} = await render(); - let tester = testUtilUser.createTester('Table', {root: container.querySelector('[role=grid]') as HTMLElement, interactionType}); + let tester = testUtilUser.createTester('Table', { + root: container.querySelector('[role=grid]') as HTMLElement, + interactionType + }); await tester.toggleRowSelection({row: 2}); expect(tester.rows()[2].getAttribute('aria-selected')).toBe('true'); }); diff --git a/packages/@react-spectrum/s2/test/TreeView.browser.test.tsx b/packages/@react-spectrum/s2/test/TreeView.browser.test.tsx index 8b57ed38a2d..fa3de611c1d 100644 --- a/packages/@react-spectrum/s2/test/TreeView.browser.test.tsx +++ b/packages/@react-spectrum/s2/test/TreeView.browser.test.tsx @@ -19,16 +19,31 @@ import {TreeView, TreeViewItem, TreeViewItemContent} from '../src/TreeView'; import {User} from '@react-aria/test-utils'; let items = [ - {id: 1, title: 'Documents', type: 'directory', children: [ - {id: 2, title: 'Project', type: 'directory', children: [ - {id: 3, title: 'Weekly Report', type: 'file', children: []}, - {id: 4, title: 'Budget', type: 'file', children: []} - ]} - ]}, - {id: 5, title: 'Photos', type: 'directory', children: [ - {id: 6, title: 'Image 1', type: 'file', children: []}, - {id: 7, title: 'Image 2', type: 'file', children: []} - ]} + { + id: 1, + title: 'Documents', + type: 'directory', + children: [ + { + id: 2, + title: 'Project', + type: 'directory', + children: [ + {id: 3, title: 'Weekly Report', type: 'file', children: []}, + {id: 4, title: 'Budget', type: 'file', children: []} + ] + } + ] + }, + { + id: 5, + title: 'Photos', + type: 'directory', + children: [ + {id: 6, title: 'Image 1', type: 'file', children: []}, + {id: 7, title: 'Image 2', type: 'file', children: []} + ] + } ]; function TreeViewExample() { @@ -42,9 +57,7 @@ function TreeViewExample() { return ( {item.title} - - {renderItem} - + {renderItem} ); }} @@ -60,7 +73,10 @@ it.each` let testUtilUser = new User(); let {container} = await render(); - let tester = testUtilUser.createTester('Tree', {root: container.querySelector('[role=treegrid]') as HTMLElement, interactionType}); + let tester = testUtilUser.createTester('Tree', { + root: container.querySelector('[role=treegrid]') as HTMLElement, + interactionType + }); await tester.toggleRowExpansion({row: 'Photos'}); await tester.toggleRowSelection({row: 'Image 2'}); let selectedRow = tester.findRow({indexOrText: 'Image 2'}); diff --git a/packages/dev/s2-docs/scripts/generateAgentSkills.mjs b/packages/dev/s2-docs/scripts/generateAgentSkills.mjs index dc1a0893563..69f70ec4ef5 100644 --- a/packages/dev/s2-docs/scripts/generateAgentSkills.mjs +++ b/packages/dev/s2-docs/scripts/generateAgentSkills.mjs @@ -82,10 +82,7 @@ const CUSTOM_SKILL_CONTENT = { REPO_ROOT, 'packages/dev/s2-docs/skills/react-spectrum-s2/implementation-guidance.md' ), - path.join( - REPO_ROOT, - 'packages/dev/s2-docs/skills/react-spectrum-s2/test-utils-guidance.md' - ) + path.join(REPO_ROOT, 'packages/dev/s2-docs/skills/react-spectrum-s2/test-utils-guidance.md') ], guideEntries: [ { @@ -102,10 +99,7 @@ const CUSTOM_SKILL_CONTENT = { }, 'react-aria': { embeddedMarkdownPaths: [ - path.join( - REPO_ROOT, - 'packages/dev/s2-docs/skills/react-aria/test-utils-guidance.md' - ) + path.join(REPO_ROOT, 'packages/dev/s2-docs/skills/react-aria/test-utils-guidance.md') ] } }; diff --git a/packages/react-aria-components/test/Dialog.browser.test.tsx b/packages/react-aria-components/test/Dialog.browser.test.tsx index 1d86e5353e6..7d215d0bff9 100644 --- a/packages/react-aria-components/test/Dialog.browser.test.tsx +++ b/packages/react-aria-components/test/Dialog.browser.test.tsx @@ -26,7 +26,9 @@ function DialogExample() { Hello - + @@ -41,7 +43,10 @@ it.each` let testUtilUser = new User(); let {container} = await render(); - let tester = testUtilUser.createTester('Dialog', {root: container.querySelector('button') as HTMLElement, interactionType}); + let tester = testUtilUser.createTester('Dialog', { + root: container.querySelector('button') as HTMLElement, + interactionType + }); await tester.open(); expect(tester.dialog()).not.toBeNull(); diff --git a/packages/react-aria-components/test/GridList.browser.test.tsx b/packages/react-aria-components/test/GridList.browser.test.tsx index f19bf219da0..e0912e0ecf4 100644 --- a/packages/react-aria-components/test/GridList.browser.test.tsx +++ b/packages/react-aria-components/test/GridList.browser.test.tsx @@ -45,7 +45,11 @@ it.each` let {container} = await render(); let gridlist = container.querySelector('[role=grid]') as HTMLElement; - let tester = testUtilUser.createTester('GridList', {root: gridlist, layout: 'grid', interactionType}); + let tester = testUtilUser.createTester('GridList', { + root: gridlist, + layout: 'grid', + interactionType + }); let rows = tester.rows(); await tester.toggleRowSelection({row: rows[5]}); diff --git a/packages/react-aria-components/test/ListBox.browser.test.tsx b/packages/react-aria-components/test/ListBox.browser.test.tsx index ef296b2192b..2956d17777d 100644 --- a/packages/react-aria-components/test/ListBox.browser.test.tsx +++ b/packages/react-aria-components/test/ListBox.browser.test.tsx @@ -40,23 +40,30 @@ it.each` interactionType ${'mouse'} ${'keyboard'} -`('selects an option via $interactionType in real browser grid layout', async ({interactionType}) => { - let testUtilUser = new User(); - let {container} = await render(); +`( + 'selects an option via $interactionType in real browser grid layout', + async ({interactionType}) => { + let testUtilUser = new User(); + let {container} = await render(); - let listbox = container.querySelector('[role=listbox]') as HTMLElement; - let tester = testUtilUser.createTester('ListBox', {root: listbox, layout: 'grid', interactionType}); + let listbox = container.querySelector('[role=listbox]') as HTMLElement; + let tester = testUtilUser.createTester('ListBox', { + root: listbox, + layout: 'grid', + interactionType + }); - let options = tester.options(); - await tester.toggleOptionSelection({option: options[5]}); - expect(options[5].getAttribute('aria-selected')).toBe('true'); - expect(document.activeElement).toBe(options[5]); + let options = tester.options(); + await tester.toggleOptionSelection({option: options[5]}); + expect(options[5].getAttribute('aria-selected')).toBe('true'); + expect(document.activeElement).toBe(options[5]); - await tester.toggleOptionSelection({option: options[0]}); - expect(options[0].getAttribute('aria-selected')).toBe('true'); - expect(document.activeElement).toBe(options[0]); + await tester.toggleOptionSelection({option: options[0]}); + expect(options[0].getAttribute('aria-selected')).toBe('true'); + expect(document.activeElement).toBe(options[0]); - await tester.toggleOptionSelection({option: options[8]}); - expect(options[8].getAttribute('aria-selected')).toBe('true'); - expect(document.activeElement).toBe(options[8]); -}); + await tester.toggleOptionSelection({option: options[8]}); + expect(options[8].getAttribute('aria-selected')).toBe('true'); + expect(document.activeElement).toBe(options[8]); + } +); diff --git a/packages/react-aria-components/test/Menu.test.tsx b/packages/react-aria-components/test/Menu.test.tsx index be243658b39..b54487ed42e 100644 --- a/packages/react-aria-components/test/Menu.test.tsx +++ b/packages/react-aria-components/test/Menu.test.tsx @@ -1239,7 +1239,9 @@ describe('Menu', () => { // Open the nested submenu let nestedSubmenu = await submenuTester?.openSubmenu({submenuTrigger: 'Email…'}); - act(() => {jest.runAllTimers();}); + act(() => { + jest.runAllTimers(); + }); expect(nestedSubmenu?.menu()).toBeInTheDocument(); expect(document.activeElement).toBe(nestedSubmenu?.options()[0]); @@ -1565,7 +1567,9 @@ describe('Menu', () => { // Open the subdialog let subDialogTester = await menuTester.openSubmenu({submenuTrigger: triggerItem}); - act(() => {jest.runAllTimers();}); + act(() => { + jest.runAllTimers(); + }); expect(subDialogTester?.menu()).toBeInTheDocument(); let subDialogTriggerItem = subDialogTester?.submenuTriggers()[0]; @@ -1647,7 +1651,9 @@ describe('Menu', () => { let triggerItem = menuTester.submenuTriggers()[0]; let subDialogTester = await menuTester.openSubmenu({submenuTrigger: triggerItem}); - act(() => {jest.runAllTimers();}); + act(() => { + jest.runAllTimers(); + }); expect(subDialogTester?.menu()).toBeInTheDocument(); // Open the nested subdialog @@ -1905,7 +1911,11 @@ describe('Menu', () => { let menuTester = testUtilUser.createTester('Menu', {user, root: tree.container}); await menuTester.open(); - await menuTester.toggleOptionSelection({option: 'Cat', interactionType: 'keyboard', closesOnSelect: false}); + await menuTester.toggleOptionSelection({ + option: 'Cat', + interactionType: 'keyboard', + closesOnSelect: false + }); expect(onAction).toHaveBeenCalledTimes(1); expect(onPressStart).toHaveBeenCalledTimes(1); @@ -1976,7 +1986,9 @@ describe('Menu', () => { await menuTester.open(); await findByRole('menu'); await menuTester.toggleOptionSelection({option: 0}); - expect(await findByText('Contact your administrator for permissions to delete.')).toBeInTheDocument(); + expect( + await findByText('Contact your administrator for permissions to delete.') + ).toBeInTheDocument(); expect(onAction).not.toHaveBeenCalled(); let dialogs = getAllByRole('dialog'); expect(dialogs).toHaveLength(2); @@ -2092,59 +2104,60 @@ AriaMenuTests({ - - ), - submenus: () => render( - - - - - Open - Rename… - Duplicate - - Share… - - - - Email… - - - Work - Personal - - - - SMS - X - - - - Delete… - - - - ), - disabledSubmenuTrigger: () => render( - - - - - Open - - Share… - - - SMS - Email - - - - Delete… - - - - ) + ), + submenus: () => + render( + + + + + Open + Rename… + Duplicate + + Share… + + + + Email… + + + Work + Personal + + + + SMS + X + + + + Delete… + + + + ), + disabledSubmenuTrigger: () => + render( + + + + + Open + + Share… + + + SMS + Email + + + + Delete… + + + + ) } }); diff --git a/packages/react-aria-components/test/Tabs.browser.test.tsx b/packages/react-aria-components/test/Tabs.browser.test.tsx index 2199b7deb6e..05230490f78 100644 --- a/packages/react-aria-components/test/Tabs.browser.test.tsx +++ b/packages/react-aria-components/test/Tabs.browser.test.tsx @@ -39,7 +39,10 @@ it.each` let testUtilUser = new User(); let {container} = await render(); - let tester = testUtilUser.createTester('Tabs', {root: container.querySelector('[role=tablist]') as HTMLElement, interactionType}); + let tester = testUtilUser.createTester('Tabs', { + root: container.querySelector('[role=tablist]') as HTMLElement, + interactionType + }); let tabs = tester.tabs(); await tester.triggerTab({tab: tabs[1]}); expect(tester.selectedTab()).toBe(tabs[1]); From ed6c99cc887b528a33545cf932e67ec59b12b2d7 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Fri, 8 May 2026 16:04:21 -0700 Subject: [PATCH 26/31] update getter naming --- .../react-spectrum/docs/combobox/ComboBox.mdx | 8 +- .../react-spectrum/docs/list/ListView.mdx | 8 +- .../react-spectrum/docs/listbox/ListBox.mdx | 2 +- .../react-spectrum/docs/menu/MenuTrigger.mdx | 12 +- .../react-spectrum/docs/picker/Picker.mdx | 2 +- .../react-spectrum/docs/table/TableView.mdx | 12 +- .../@adobe/react-spectrum/docs/tabs/Tabs.mdx | 6 +- .../react-spectrum/docs/tree/TreeView.mdx | 12 +- .../test/checkbox/CheckboxGroup.test.js | 14 +- .../test/combobox/ComboBox.test.js | 72 +-- .../test/dialog/DialogTrigger.test.js | 6 +- .../react-spectrum/test/list/ListView.test.js | 12 +- .../test/listbox/ListBox.test.js | 20 +- .../test/menu/MenuTrigger.test.js | 28 +- .../react-spectrum/test/picker/Picker.test.js | 72 +-- .../test/picker/TempUtilTest.test.js | 10 +- .../react-spectrum/test/radio/Radio.test.js | 2 +- .../react-spectrum/test/table/TableTests.js | 14 +- .../react-spectrum/test/tabs/Tabs.test.js | 26 +- .../test/tree/TreeView.test.tsx | 112 ++-- .../test-utils/src/checkboxgroup.ts | 18 +- .../@react-aria/test-utils/src/combobox.ts | 42 +- packages/@react-aria/test-utils/src/dialog.ts | 6 +- .../@react-aria/test-utils/src/gridlist.ts | 20 +- .../@react-aria/test-utils/src/listbox.ts | 18 +- packages/@react-aria/test-utils/src/menu.ts | 50 +- .../@react-aria/test-utils/src/radiogroup.ts | 20 +- packages/@react-aria/test-utils/src/select.ts | 32 +- packages/@react-aria/test-utils/src/table.ts | 54 +- packages/@react-aria/test-utils/src/tabs.ts | 24 +- packages/@react-aria/test-utils/src/tree.ts | 26 +- .../s2/test/CheckboxGroup.browser.test.tsx | 4 +- .../s2/test/CheckboxGroup.test.tsx | 14 +- .../s2/test/Combobox.browser.test.tsx | 2 +- .../@react-spectrum/s2/test/Combobox.test.tsx | 30 +- .../s2/test/EditableTableView.test.tsx | 12 +- .../s2/test/Picker.browser.test.tsx | 2 +- .../@react-spectrum/s2/test/Picker.test.tsx | 10 +- .../s2/test/RadioGroup.browser.test.tsx | 4 +- .../s2/test/RadioGroup.test.tsx | 8 +- .../s2/test/SelectBoxGroup.test.tsx | 18 +- .../s2/test/TableView.browser.test.tsx | 2 +- .../s2/test/TableView.test.tsx | 8 +- .../react-aria/CheckboxGroup/testing.mdx | 10 +- .../pages/react-aria/ComboBox/testing.mdx | 8 +- .../pages/react-aria/GridList/testing.mdx | 8 +- .../pages/react-aria/ListBox/testing.mdx | 2 +- .../s2-docs/pages/react-aria/Menu/testing.mdx | 12 +- .../pages/react-aria/Modal/testing.mdx | 2 +- .../pages/react-aria/Popover/testing.mdx | 2 +- .../pages/react-aria/RadioGroup/testing.mdx | 8 +- .../pages/react-aria/Select/testing.mdx | 2 +- .../pages/react-aria/Table/testing.mdx | 12 +- .../s2-docs/pages/react-aria/Tabs/testing.mdx | 6 +- .../s2-docs/pages/react-aria/Tree/testing.mdx | 14 +- .../pages/s2/CheckboxGroup/testing.mdx | 10 +- .../dev/s2-docs/pages/s2/ComboBox/testing.mdx | 8 +- .../dev/s2-docs/pages/s2/Dialog/testing.mdx | 2 +- .../dev/s2-docs/pages/s2/ListView/testing.mdx | 8 +- .../dev/s2-docs/pages/s2/Menu/testing.mdx | 12 +- .../dev/s2-docs/pages/s2/Picker/testing.mdx | 2 +- .../s2-docs/pages/s2/RadioGroup/testing.mdx | 8 +- .../s2-docs/pages/s2/TableView/testing.mdx | 12 +- .../dev/s2-docs/pages/s2/Tabs/testing.mdx | 6 +- .../dev/s2-docs/pages/s2/TreeView/testing.mdx | 14 +- .../skills/react-aria/test-utils-guidance.md | 30 +- .../react-spectrum-s2/test-utils-guidance.md | 30 +- .../react-aria-components/docs/ComboBox.mdx | 8 +- .../react-aria-components/docs/GridList.mdx | 8 +- .../react-aria-components/docs/ListBox.mdx | 2 +- packages/react-aria-components/docs/Menu.mdx | 12 +- .../react-aria-components/docs/Select.mdx | 2 +- packages/react-aria-components/docs/Table.mdx | 12 +- packages/react-aria-components/docs/Tabs.mdx | 6 +- packages/react-aria-components/docs/Tree.mdx | 12 +- .../test/AriaMenu.test-util.tsx | 168 +++--- .../test/AriaTree.test-util.tsx | 30 +- .../test/ComboBox.test.js | 169 +++---- .../test/Dialog.browser.test.tsx | 6 +- .../react-aria-components/test/Dialog.test.js | 4 +- .../test/GridList.browser.test.tsx | 2 +- .../test/GridList.test.js | 118 ++--- .../test/ListBox.browser.test.tsx | 2 +- .../test/ListBox.test.js | 124 ++--- .../react-aria-components/test/Menu.test.tsx | 70 +-- .../test/RadioGroup.test.js | 14 +- .../react-aria-components/test/Select.test.js | 68 +-- .../react-aria-components/test/Table.test.js | 162 +++--- .../test/Tabs.browser.test.tsx | 4 +- .../react-aria-components/test/Tabs.test.js | 50 +- .../react-aria-components/test/Tree.test.tsx | 52 +- .../test/Treeble.test.js | 478 +++++++++--------- .../test/VirtualizedMenu.test.tsx | 2 +- 93 files changed, 1340 insertions(+), 1347 deletions(-) diff --git a/packages/@adobe/react-spectrum/docs/combobox/ComboBox.mdx b/packages/@adobe/react-spectrum/docs/combobox/ComboBox.mdx index c2abb6b8429..4bb9373b6ad 100644 --- a/packages/@adobe/react-spectrum/docs/combobox/ComboBox.mdx +++ b/packages/@adobe/react-spectrum/docs/combobox/ComboBox.mdx @@ -1020,12 +1020,12 @@ it('ComboBox can select an option via keyboard', async function () { let comboboxTester = testUtilUser.createTester('ComboBox', {root: getByTestId('test-combobox'), interactionType: 'keyboard'}); await comboboxTester.open(); - expect(comboboxTester.listbox()).toBeInTheDocument(); + expect(comboboxTester.getListbox()).toBeInTheDocument(); - let options = comboboxTester.options(); + let options = comboboxTester.getOptions(); await comboboxTester.toggleOptionSelection({option: options[0]}); - expect(comboboxTester.combobox().value).toBe('One'); - expect(comboboxTester.listbox()).not.toBeInTheDocument(); + expect(comboboxTester.getCombobox().value).toBe('One'); + expect(comboboxTester.getListbox()).not.toBeInTheDocument(); }); ``` diff --git a/packages/@adobe/react-spectrum/docs/list/ListView.mdx b/packages/@adobe/react-spectrum/docs/list/ListView.mdx index 50d0a6258c0..84a2a7d386f 100644 --- a/packages/@adobe/react-spectrum/docs/list/ListView.mdx +++ b/packages/@adobe/react-spectrum/docs/list/ListView.mdx @@ -1218,17 +1218,17 @@ it('ListView can select a row via keyboard', async function () { ); let gridListTester = testUtilUser.createTester('GridList', {root: getByTestId('test-gridlist'), interactionType: 'keyboard'}); - let row = gridListTester.rows()[0]; + let row = gridListTester.getRows()[0]; expect(within(row).getByRole('checkbox')).not.toBeChecked(); - expect(gridListTester.selectedRows()).toHaveLength(0); + expect(gridListTester.getSelectedRows()).toHaveLength(0); await gridListTester.toggleRowSelection({row: 0}); expect(within(row).getByRole('checkbox')).toBeChecked(); - expect(gridListTester.selectedRows()).toHaveLength(1); + expect(gridListTester.getSelectedRows()).toHaveLength(1); await gridListTester.toggleRowSelection({row: 0}); expect(within(row).getByRole('checkbox')).not.toBeChecked(); - expect(gridListTester.selectedRows()).toHaveLength(0); + expect(gridListTester.getSelectedRows()).toHaveLength(0); }); ``` diff --git a/packages/@adobe/react-spectrum/docs/listbox/ListBox.mdx b/packages/@adobe/react-spectrum/docs/listbox/ListBox.mdx index 28bb88b9c72..97cb8e5922a 100644 --- a/packages/@adobe/react-spectrum/docs/listbox/ListBox.mdx +++ b/packages/@adobe/react-spectrum/docs/listbox/ListBox.mdx @@ -437,7 +437,7 @@ it('ListBox can select an option via keyboard', async function () { let listboxTester = testUtilUser.createTester('ListBox', {root: getByTestId('test-listbox'), interactionType: 'keyboard'}); await listboxTester.toggleOptionSelection({option: 4}); - expect(listboxTester.options()[4]).toHaveAttribute('aria-selected', 'true'); + expect(listboxTester.getOptions()[4]).toHaveAttribute('aria-selected', 'true'); }); ``` diff --git a/packages/@adobe/react-spectrum/docs/menu/MenuTrigger.mdx b/packages/@adobe/react-spectrum/docs/menu/MenuTrigger.mdx index 7cf702ba1c8..8435e7a24bc 100644 --- a/packages/@adobe/react-spectrum/docs/menu/MenuTrigger.mdx +++ b/packages/@adobe/react-spectrum/docs/menu/MenuTrigger.mdx @@ -285,16 +285,16 @@ it('Menu can open its submenu via keyboard', async function () { let menuTester = testUtilUser.createTester('Menu', {root: getByTestId('test-menutrigger'), interactionType: 'keyboard'}); await menuTester.open(); - expect(menuTester.menu()).toBeInTheDocument(); - let submenuTriggers = menuTester.submenuTriggers(); + expect(menuTester.getMenu()).toBeInTheDocument(); + let submenuTriggers = menuTester.getSubmenuTriggers(); expect(submenuTriggers).toHaveLength(1); let submenuTester = await menuTester.openSubmenu({submenuTrigger: 'Share…'}); - expect(submenuTester.menu()).toBeInTheDocument(); + expect(submenuTester.getMenu()).toBeInTheDocument(); - await submenuTester.toggleOptionSelection({option: submenuTester.options()[0]}); - expect(submenuTester.menu()).not.toBeInTheDocument(); - expect(menuTester.menu()).not.toBeInTheDocument(); + await submenuTester.toggleOptionSelection({option: submenuTester.getOptions()[0]}); + expect(submenuTester.getMenu()).not.toBeInTheDocument(); + expect(menuTester.getMenu()).not.toBeInTheDocument(); }); ``` diff --git a/packages/@adobe/react-spectrum/docs/picker/Picker.mdx b/packages/@adobe/react-spectrum/docs/picker/Picker.mdx index 14a2b0a06c2..1213254c8e7 100644 --- a/packages/@adobe/react-spectrum/docs/picker/Picker.mdx +++ b/packages/@adobe/react-spectrum/docs/picker/Picker.mdx @@ -600,7 +600,7 @@ it('Picker can select an option via keyboard', async function () { ); let selectTester = testUtilUser.createTester('Select', {root: getByTestId('test-select'), interactionType: 'keyboard'}); - let trigger = selectTester.trigger(); + let trigger = selectTester.getTrigger(); expect(trigger).toHaveTextContent('Select…'); await selectTester.toggleOptionSelection({option: 'Cat'}); diff --git a/packages/@adobe/react-spectrum/docs/table/TableView.mdx b/packages/@adobe/react-spectrum/docs/table/TableView.mdx index 43bc410349d..718d6d52638 100644 --- a/packages/@adobe/react-spectrum/docs/table/TableView.mdx +++ b/packages/@adobe/react-spectrum/docs/table/TableView.mdx @@ -1986,22 +1986,22 @@ it('TableView can toggle row selection', async function () { ); let tableTester = testUtilUser.createTester('Table', {root: getByTestId('test-table')}); - expect(tableTester.selectedRows()).toHaveLength(0); + expect(tableTester.getSelectedRows()).toHaveLength(0); await tableTester.toggleSelectAll(); - expect(tableTester.selectedRows()).toHaveLength(10); + expect(tableTester.getSelectedRows()).toHaveLength(10); await tableTester.toggleRowSelection({row: 2}); - expect(tableTester.selectedRows()).toHaveLength(9); - let checkbox = within(tableTester.rows()[2]).getByRole('checkbox'); + expect(tableTester.getSelectedRows()).toHaveLength(9); + let checkbox = within(tableTester.getRows()[2]).getByRole('checkbox'); expect(checkbox).not.toBeChecked(); await tableTester.toggleSelectAll(); - expect(tableTester.selectedRows()).toHaveLength(10); + expect(tableTester.getSelectedRows()).toHaveLength(10); expect(checkbox).toBeChecked(); await tableTester.toggleSelectAll(); - expect(tableTester.selectedRows()).toHaveLength(0); + expect(tableTester.getSelectedRows()).toHaveLength(0); }); ``` diff --git a/packages/@adobe/react-spectrum/docs/tabs/Tabs.mdx b/packages/@adobe/react-spectrum/docs/tabs/Tabs.mdx index a0916431483..a6e779f3627 100644 --- a/packages/@adobe/react-spectrum/docs/tabs/Tabs.mdx +++ b/packages/@adobe/react-spectrum/docs/tabs/Tabs.mdx @@ -662,11 +662,11 @@ it('Tabs can change selection via keyboard', async function () { ); let tabsTester = testUtilUser.createTester('Tabs', {root: getByTestId('test-tabs'), interactionType: 'keyboard'}); - let tabs = tabsTester.tabs(); - expect(tabsTester.selectedTab()).toBe(tabs[0]); + let tabs = tabsTester.getTabs(); + expect(tabsTester.getSelectedTab()).toBe(tabs[0]); await tabsTester.triggerTab({tab: 1}); - expect(tabsTester.selectedTab()).toBe(tabs[1]); + expect(tabsTester.getSelectedTab()).toBe(tabs[1]); }); ``` diff --git a/packages/@adobe/react-spectrum/docs/tree/TreeView.mdx b/packages/@adobe/react-spectrum/docs/tree/TreeView.mdx index 07df8cd8b9d..ed582c03a9a 100644 --- a/packages/@adobe/react-spectrum/docs/tree/TreeView.mdx +++ b/packages/@adobe/react-spectrum/docs/tree/TreeView.mdx @@ -557,16 +557,16 @@ it('TreeView can select a row via keyboard', async function () { let treeTester = testUtilUser.createTester('Tree', {root: getByTestId('test-tree'), interactionType: 'keyboard'}); await treeTester.toggleRowSelection({row: 0}); - expect(treeTester.selectedRows()).toHaveLength(1); - expect(within(treeTester.rows()[0]).getByRole('checkbox')).toBeChecked(); + expect(treeTester.getSelectedRows()).toHaveLength(1); + expect(within(treeTester.getRows()[0]).getByRole('checkbox')).toBeChecked(); await treeTester.toggleRowSelection({row: 1}); - expect(treeTester.selectedRows()).toHaveLength(2); - expect(within(treeTester.rows()[1]).getByRole('checkbox')).toBeChecked(); + expect(treeTester.getSelectedRows()).toHaveLength(2); + expect(within(treeTester.getRows()[1]).getByRole('checkbox')).toBeChecked(); await treeTester.toggleRowSelection({row: 0}); - expect(treeTester.selectedRows()).toHaveLength(1); - expect(within(treeTester.rows()[0]).getByRole('checkbox')).not.toBeChecked(); + expect(treeTester.getSelectedRows()).toHaveLength(1); + expect(within(treeTester.getRows()[0]).getByRole('checkbox')).not.toBeChecked(); }); ``` diff --git a/packages/@adobe/react-spectrum/test/checkbox/CheckboxGroup.test.js b/packages/@adobe/react-spectrum/test/checkbox/CheckboxGroup.test.js index e2277025a64..e991000c009 100644 --- a/packages/@adobe/react-spectrum/test/checkbox/CheckboxGroup.test.js +++ b/packages/@adobe/react-spectrum/test/checkbox/CheckboxGroup.test.js @@ -889,15 +889,15 @@ describe('CheckboxGroup', () => { let checkboxGroupTester = testUtilUser.createTester('CheckboxGroup', { root: getByRole('group') }); - expect(checkboxGroupTester.checkboxgroup()).toHaveAttribute('role'); - let checkboxes = checkboxGroupTester.checkboxes(); + expect(checkboxGroupTester.getCheckboxGroup()).toHaveAttribute('role'); + let checkboxes = checkboxGroupTester.getCheckboxes(); await checkboxGroupTester.toggleCheckbox({checkbox: checkboxes[0]}); expect(checkboxes[0]).toBeChecked(); - expect(checkboxGroupTester.selectedCheckboxes()).toHaveLength(1); + expect(checkboxGroupTester.getSelectedCheckboxes()).toHaveLength(1); await checkboxGroupTester.toggleCheckbox({checkbox: 4, interactionType: 'keyboard'}); expect(checkboxes[4]).toBeChecked(); - expect(checkboxGroupTester.selectedCheckboxes()).toHaveLength(2); + expect(checkboxGroupTester.getSelectedCheckboxes()).toHaveLength(2); let checkbox4 = checkboxGroupTester.findCheckbox({indexOrText: 3}); await checkboxGroupTester.toggleCheckbox({ @@ -905,16 +905,16 @@ describe('CheckboxGroup', () => { interactionType: 'keyboard' }); expect(checkboxes[3]).toBeChecked(); - expect(checkboxGroupTester.selectedCheckboxes()).toHaveLength(3); + expect(checkboxGroupTester.getSelectedCheckboxes()).toHaveLength(3); await checkboxGroupTester.toggleCheckbox({checkbox: 'Soccer', interactionType: 'keyboard'}); expect(checkboxes[0]).not.toBeChecked(); - expect(checkboxGroupTester.selectedCheckboxes()).toHaveLength(2); + expect(checkboxGroupTester.getSelectedCheckboxes()).toHaveLength(2); let checkbox5 = checkboxGroupTester.findCheckbox({indexOrText: 'Rugby'}); await checkboxGroupTester.toggleCheckbox({checkbox: checkbox5, interactionType: 'mouse'}); expect(checkboxes[4]).not.toBeChecked(); - expect(checkboxGroupTester.selectedCheckboxes()).toHaveLength(1); + expect(checkboxGroupTester.getSelectedCheckboxes()).toHaveLength(1); } ); }); diff --git a/packages/@adobe/react-spectrum/test/combobox/ComboBox.test.js b/packages/@adobe/react-spectrum/test/combobox/ComboBox.test.js index 9fe7858c995..cf5386714b1 100644 --- a/packages/@adobe/react-spectrum/test/combobox/ComboBox.test.js +++ b/packages/@adobe/react-spectrum/test/combobox/ComboBox.test.js @@ -352,23 +352,23 @@ describe('ComboBox', function () { let comboboxTester = testUtilUser.createTester('ComboBox', {root: tree.container}); act(() => { - comboboxTester.combobox().focus(); + comboboxTester.getCombobox().focus(); }); await user.keyboard('One'); - expect(comboboxTester.listbox()).toBeFalsy(); + expect(comboboxTester.getListbox()).toBeFalsy(); expect(onOpenChange).not.toHaveBeenCalled(); expect(onFocus).not.toHaveBeenCalled(); comboboxTester.setInteractionType('keyboard'); await comboboxTester.open(); - expect(comboboxTester.listbox()).toBeFalsy(); + expect(comboboxTester.getListbox()).toBeFalsy(); expect(onOpenChange).not.toHaveBeenCalled(); comboboxTester.setInteractionType('mouse'); await comboboxTester.open(); - expect(comboboxTester.listbox()).toBeFalsy(); + expect(comboboxTester.getListbox()).toBeFalsy(); expect(onOpenChange).not.toHaveBeenCalled(); expect(onInputChange).not.toHaveBeenCalled(); }); @@ -378,11 +378,11 @@ describe('ComboBox', function () { let comboboxTester = testUtilUser.createTester('ComboBox', {root: tree.container}); act(() => { - comboboxTester.combobox().focus(); + comboboxTester.getCombobox().focus(); }); await user.keyboard('One'); - expect(comboboxTester.listbox()).toBeFalsy(); - expect(comboboxTester.combobox().value).toBe('Blargh'); + expect(comboboxTester.getListbox()).toBeFalsy(); + expect(comboboxTester.getCombobox().value).toBe('Blargh'); expect(onOpenChange).not.toHaveBeenCalled(); expect(onFocus).toHaveBeenCalled(); expect(onInputChange).not.toHaveBeenCalled(); @@ -390,14 +390,14 @@ describe('ComboBox', function () { comboboxTester.setInteractionType('keyboard'); await comboboxTester.open(); - expect(comboboxTester.listbox()).toBeFalsy(); + expect(comboboxTester.getListbox()).toBeFalsy(); expect(onOpenChange).not.toHaveBeenCalled(); expect(onInputChange).not.toHaveBeenCalled(); comboboxTester.setInteractionType('mouse'); await comboboxTester.open(); - expect(comboboxTester.listbox()).toBeFalsy(); + expect(comboboxTester.getListbox()).toBeFalsy(); expect(onOpenChange).not.toHaveBeenCalled(); }); @@ -405,7 +405,7 @@ describe('ComboBox', function () { let tree = renderComboBox(); let comboboxTester = testUtilUser.createTester('ComboBox', {root: tree.container}); - let combobox = comboboxTester.combobox(); + let combobox = comboboxTester.getCombobox(); expect(combobox).not.toHaveAttribute('aria-controls'); expect(combobox).not.toHaveAttribute('aria-activedescendant'); expect(combobox).toHaveAttribute('aria-autocomplete', 'list'); @@ -418,12 +418,12 @@ describe('ComboBox', function () { jest.runAllTimers(); }); - let items = comboboxTester.options(); + let items = comboboxTester.getOptions(); expect(items).toHaveLength(1); expect(combobox.value).toBe('On'); expect(items[0]).toHaveTextContent('One'); - expect(combobox).toHaveAttribute('aria-controls', comboboxTester.listbox().id); + expect(combobox).toHaveAttribute('aria-controls', comboboxTester.getListbox().id); expect(combobox).not.toHaveAttribute('aria-activedescendant'); await user.keyboard('{ArrowDown}'); @@ -431,7 +431,7 @@ describe('ComboBox', function () { jest.runAllTimers(); }); - expect(combobox).toHaveAttribute('aria-activedescendant', comboboxTester.focusedOption().id); + expect(combobox).toHaveAttribute('aria-activedescendant', comboboxTester.getFocusedOption().id); }); describe('refs', function () { @@ -467,11 +467,11 @@ describe('ComboBox', function () { let tree = renderComboBox({menuTrigger: 'focus'}); let comboboxTester = testUtilUser.createTester('ComboBox', {root: tree.container}); - let button = comboboxTester.trigger(); - let combobox = comboboxTester.combobox(); + let button = comboboxTester.getTrigger(); + let combobox = comboboxTester.getCombobox(); await comboboxTester.open({triggerBehavior: 'focus'}); - let listbox = comboboxTester.listbox(); + let listbox = comboboxTester.getListbox(); expect(onOpenChange).toBeCalledTimes(1); expect(onOpenChange).toHaveBeenCalledWith(true, 'focus'); await testComboBoxOpen(combobox, button, listbox); @@ -481,11 +481,11 @@ describe('ComboBox', function () { let tree = renderComboBox({menuTrigger: 'focus'}); let comboboxTester = testUtilUser.createTester('ComboBox', {root: tree.container}); - let button = comboboxTester.trigger(); - let combobox = comboboxTester.combobox(); + let button = comboboxTester.getTrigger(); + let combobox = comboboxTester.getCombobox(); await comboboxTester.open({triggerBehavior: 'manual'}); - let listbox = comboboxTester.listbox(); + let listbox = comboboxTester.getListbox(); expect(onOpenChange).toBeCalledTimes(1); expect(onOpenChange).toHaveBeenCalledWith(true, 'focus'); await testComboBoxOpen(combobox, button, listbox); @@ -502,18 +502,18 @@ describe('ComboBox', function () { trigger: button }); - expect(comboboxTester.listbox()).toBeFalsy(); + expect(comboboxTester.getListbox()).toBeFalsy(); await comboboxTester.open(); - expect(comboboxTester.listbox()).toBeInTheDocument(); - expect(document.activeElement).toBe(comboboxTester.combobox()); + expect(comboboxTester.getListbox()).toBeInTheDocument(); + expect(document.activeElement).toBe(comboboxTester.getCombobox()); - await user.click(comboboxTester.trigger()); + await user.click(comboboxTester.getTrigger()); act(() => { jest.runAllTimers(); }); - expect(comboboxTester.listbox()).toBeFalsy(); + expect(comboboxTester.getListbox()).toBeFalsy(); }); it("doesn't focus first item if there are items loaded", async function () { @@ -536,21 +536,21 @@ describe('ComboBox', function () { let tree = renderComboBox({}); let comboboxTester = testUtilUser.createTester('ComboBox', {root: tree.container}); - let combobox = comboboxTester.combobox(); + let combobox = comboboxTester.getCombobox(); expect(document.activeElement).not.toBe(combobox); comboboxTester.setInteractionType('touch'); await comboboxTester.open(); - expect(document.activeElement).toBe(comboboxTester.combobox()); - expect(comboboxTester.listbox()).toBeInTheDocument(); + expect(document.activeElement).toBe(comboboxTester.getCombobox()); + expect(comboboxTester.getListbox()).toBeInTheDocument(); - let button = comboboxTester.trigger(); + let button = comboboxTester.getTrigger(); fireEvent.touchStart(button, {targetTouches: [{identifier: 1}]}); fireEvent.touchEnd(button, {changedTouches: [{identifier: 1, clientX: 0, clientY: 0}]}); act(() => { jest.runAllTimers(); }); - expect(comboboxTester.listbox()).toBeFalsy(); + expect(comboboxTester.getListbox()).toBeFalsy(); }); it("it doesn't reset the focused item when re-opening the menu", async function () { @@ -558,15 +558,15 @@ describe('ComboBox', function () { let comboboxTester = testUtilUser.createTester('ComboBox', {root: tree.container}); await comboboxTester.open(); - expect(comboboxTester.combobox()).not.toHaveAttribute('aria-activedescendant'); + expect(comboboxTester.getCombobox()).not.toHaveAttribute('aria-activedescendant'); - let options = comboboxTester.options(); + let options = comboboxTester.getOptions(); await comboboxTester.toggleOptionSelection({option: options[0]}); - expect(comboboxTester.combobox().value).toBe('One'); + expect(comboboxTester.getCombobox().value).toBe('One'); await comboboxTester.open(); - expect(comboboxTester.combobox()).toHaveAttribute('aria-activedescendant', options[0].id); + expect(comboboxTester.getCombobox()).toHaveAttribute('aria-activedescendant', options[0].id); }); it('shows all items', async function () { @@ -920,7 +920,7 @@ describe('ComboBox', function () { let tree = renderComboBox({defaultSelectedKey: '2'}); let comboboxTester = testUtilUser.createTester('ComboBox', {root: tree.container}); - let combobox = comboboxTester.combobox(); + let combobox = comboboxTester.getCombobox(); expect(combobox.value).toBe('Two'); act(() => combobox.focus()); @@ -929,10 +929,10 @@ describe('ComboBox', function () { expect(onInputChange).toHaveBeenCalledTimes(1); expect(onInputChange).toHaveBeenLastCalledWith('Tw'); expect(combobox.value).toBe('Tw'); - expect(comboboxTester.options().length).toBe(1); + expect(comboboxTester.getOptions().length).toBe(1); await comboboxTester.toggleOptionSelection({option: 'Two'}); - expect(comboboxTester.listbox()).toBeFalsy(); + expect(comboboxTester.getListbox()).toBeFalsy(); expect(combobox.value).toBe('Two'); // selectionManager.select from useSingleSelectListState always calls onSelectionChange even if the key is the same expect(onSelectionChange).toHaveBeenCalledTimes(1); diff --git a/packages/@adobe/react-spectrum/test/dialog/DialogTrigger.test.js b/packages/@adobe/react-spectrum/test/dialog/DialogTrigger.test.js index ecf80f60780..f1ed8c07288 100644 --- a/packages/@adobe/react-spectrum/test/dialog/DialogTrigger.test.js +++ b/packages/@adobe/react-spectrum/test/dialog/DialogTrigger.test.js @@ -89,7 +89,7 @@ describe('DialogTrigger', function () { let button = getByRole('button'); let dialogTester = testUtilUser.createTester('Dialog', {root: button, overlayType: 'modal'}); await dialogTester.open(); - let dialog = dialogTester.dialog(); + let dialog = dialogTester.getDialog(); expect(dialog).toBeVisible(); let modal = getByTestId('modal'); @@ -137,7 +137,7 @@ describe('DialogTrigger', function () { let button = getByRole('button'); let dialogTester = testUtilUser.createTester('Dialog', {root: button, overlayType: 'popover'}); await dialogTester.open(); - let dialog = dialogTester.dialog(); + let dialog = dialogTester.getDialog(); expect(dialog).toBeVisible(); let popover = getByTestId('popover'); @@ -290,7 +290,7 @@ describe('DialogTrigger', function () { let button = getByRole('button'); let dialogTester = testUtilUser.createTester('Dialog', {root: button, overlayType: 'modal'}); await dialogTester.open(); - let dialog = dialogTester.dialog(); + let dialog = dialogTester.getDialog(); expect(document.activeElement).toBe(dialog); await dialogTester.close(); // now that it's been unmounted, run the raf callback diff --git a/packages/@adobe/react-spectrum/test/list/ListView.test.js b/packages/@adobe/react-spectrum/test/list/ListView.test.js index e41510504af..24d01bffc29 100644 --- a/packages/@adobe/react-spectrum/test/list/ListView.test.js +++ b/packages/@adobe/react-spectrum/test/list/ListView.test.js @@ -187,13 +187,13 @@ describe('ListView', function () { expect(grid).toHaveAttribute('aria-rowcount', '3'); expect(grid).toHaveAttribute('aria-colcount', '1'); - let rows = gridListTester.rows(); + let rows = gridListTester.getRows(); expect(rows).toHaveLength(3); expect(rows[0]).toHaveAttribute('aria-rowindex', '1'); expect(rows[1]).toHaveAttribute('aria-rowindex', '2'); expect(rows[2]).toHaveAttribute('aria-rowindex', '3'); - let gridCells = gridListTester.cells({element: rows[0]}); + let gridCells = gridListTester.getCells({element: rows[0]}); expect(gridCells).toHaveLength(1); expect(gridCells[0]).toHaveTextContent('Foo'); expect(gridCells[0]).toHaveAttribute('aria-colindex', '1'); @@ -897,14 +897,14 @@ describe('ListView', function () { let tree = renderSelectionList({onSelectionChange, selectionMode: 'multiple'}); let grid = tree.getByRole('grid'); let gridListTester = testUtilUser.createTester('GridList', {root: grid}); - let rows = gridListTester.rows(); + let rows = gridListTester.getRows(); await gridListTester.toggleRowSelection({row: 0}); checkSelection(onSelectionChange, ['foo']); onSelectionChange.mockClear(); expect(announce).toHaveBeenLastCalledWith('Foo selected.'); expect(announce).toHaveBeenCalledTimes(1); - expect(gridListTester.selectedRows()).toHaveLength(1); + expect(gridListTester.getSelectedRows()).toHaveLength(1); await user.keyboard('{Control>}a{/Control}'); act(() => jest.runAllTimers()); @@ -912,7 +912,7 @@ describe('ListView', function () { onSelectionChange.mockClear(); expect(announce).toHaveBeenLastCalledWith('All items selected.'); expect(announce).toHaveBeenCalledTimes(2); - expect(gridListTester.selectedRows()).toHaveLength(3); + expect(gridListTester.getSelectedRows()).toHaveLength(3); fireEvent.keyDown(rows[0], {key: 'Escape'}); fireEvent.keyUp(rows[0], {key: 'Escape'}); @@ -920,7 +920,7 @@ describe('ListView', function () { onSelectionChange.mockClear(); expect(announce).toHaveBeenLastCalledWith('No items selected.'); expect(announce).toHaveBeenCalledTimes(3); - expect(gridListTester.selectedRows()).toHaveLength(0); + expect(gridListTester.getSelectedRows()).toHaveLength(0); }); describe('onAction', function () { diff --git a/packages/@adobe/react-spectrum/test/listbox/ListBox.test.js b/packages/@adobe/react-spectrum/test/listbox/ListBox.test.js index 943e2980335..7821cacdb08 100644 --- a/packages/@adobe/react-spectrum/test/listbox/ListBox.test.js +++ b/packages/@adobe/react-spectrum/test/listbox/ListBox.test.js @@ -109,11 +109,11 @@ describe('ListBox', function () { it('renders properly', function () { let tree = renderComponent(); let listboxTester = testUtilUser.createTester('ListBox', {root: tree.getByRole('listbox')}); - let listbox = listboxTester.listbox(); + let listbox = listboxTester.getListbox(); expect(listbox).toBeTruthy(); expect(listbox).toHaveAttribute('aria-labelledby', 'label'); - let sections = listboxTester.sections(); + let sections = listboxTester.getSections(); expect(sections.length).toBe(withSection.length); for (let section of sections) { @@ -130,7 +130,7 @@ describe('ListBox', function () { } } - let options = listboxTester.options(); + let options = listboxTester.getOptions(); expect(options.length).toBe(withSection.reduce((acc, curr) => acc + curr.children.length, 0)); let i = 1; for (let option of options) { @@ -214,7 +214,7 @@ describe('ListBox', function () { }); let listboxTester = testUtilUser.createTester('ListBox', {root: tree.getByRole('listbox')}); - let selectedOptions = listboxTester.selectedOptions(); + let selectedOptions = listboxTester.getSelectedOptions(); expect(selectedOptions).toHaveLength(1); expect(selectedOptions[0]).toBe(document.activeElement); expect(selectedOptions[0]).toHaveAttribute('aria-selected', 'true'); @@ -226,7 +226,7 @@ describe('ListBox', function () { // Select a different listbox item via enter await listboxTester.toggleOptionSelection({option: 4, interactionType: 'keyboard'}); - selectedOptions = listboxTester.selectedOptions(); + selectedOptions = listboxTester.getSelectedOptions(); expect(selectedOptions[0]).toHaveAttribute('aria-selected', 'true'); itemText = within(selectedOptions[0]).getByText('Bleh'); expect(itemText).toBeTruthy(); @@ -282,7 +282,7 @@ describe('ListBox', function () { let listboxTester = testUtilUser.createTester('ListBox', {root: tree.getByRole('listbox')}); // Trigger a menu item via space - let options = listboxTester.options(); + let options = listboxTester.getOptions(); await listboxTester.toggleOptionSelection({ option: 4, keyboardActivation: 'Space', @@ -891,8 +891,8 @@ describe('ListBox', function () { let {rerender, getByRole, getByLabelText} = render(); let listboxTester = testUtilUser.createTester('ListBox', {root: getByRole('listbox')}); let item = listboxTester.findOption({indexOrText: 'Foo 1'}); - let listboxSections = listboxTester.sections(); - expect(listboxTester.options({element: listboxSections[0]})).toContain(item); + let listboxSections = listboxTester.getSections(); + expect(listboxTester.getOptions({element: listboxSections[0]})).toContain(item); expect(listboxSections[0]).toBe(getByLabelText('Section 1')); let sections2 = [ @@ -909,8 +909,8 @@ describe('ListBox', function () { rerender(); listboxTester = testUtilUser.createTester('ListBox', {root: getByRole('listbox')}); item = listboxTester.findOption({indexOrText: 'Foo 1'}); - listboxSections = listboxTester.sections(); - expect(listboxTester.options({element: listboxSections[1]})).toContain(item); + listboxSections = listboxTester.getSections(); + expect(listboxTester.getOptions({element: listboxSections[1]})).toContain(item); expect(listboxSections[1]).toBe(getByLabelText('Section 2')); }); diff --git a/packages/@adobe/react-spectrum/test/menu/MenuTrigger.test.js b/packages/@adobe/react-spectrum/test/menu/MenuTrigger.test.js index 53d15532447..043bf3d7807 100644 --- a/packages/@adobe/react-spectrum/test/menu/MenuTrigger.test.js +++ b/packages/@adobe/react-spectrum/test/menu/MenuTrigger.test.js @@ -126,7 +126,7 @@ describe('MenuTrigger', function () { jest.runAllTimers(); }); - let menu = menuTester.menu(); + let menu = menuTester.getMenu(); expect(menu).toBeInTheDocument(); expect(menu).toHaveAttribute('aria-labelledby', triggerButton.id); @@ -223,7 +223,7 @@ describe('MenuTrigger', function () { async function openAndTriggerMenuItem(tree, role, selectionMode, triggerEvent) { let menuTester = testUtilUser.createTester('Menu', {root: tree.container}); await menuTester.open(); - let menuItems = menuTester.options(); + let menuItems = menuTester.getOptions(); let itemToAction = menuItems[1]; await triggerEvent(itemToAction); act(() => { @@ -255,7 +255,7 @@ describe('MenuTrigger', function () { expect(onSelect).toBeCalledTimes(0); } - await menuTester.selectOption({ + await menuTester.toggleOptionSelection({ option: 'Foo', menuSelectionMode: 'single', closesOnSelect: false @@ -267,13 +267,13 @@ describe('MenuTrigger', function () { expect(onSelect).toBeCalledTimes(1); } - expect(menuTester.menu).toBeInTheDocument(); + expect(menuTester.getMenu()).toBeInTheDocument(); if (Component === MenuTrigger) { - expect(menuTester.trigger).toHaveAttribute('aria-expanded', 'true'); + expect(menuTester.getTrigger()).toHaveAttribute('aria-expanded', 'true'); expect(onOpenChange).toBeCalledTimes(1); } else { - expect(menuTester.trigger).toHaveAttribute('aria-expanded'); + expect(menuTester.getTrigger()).toHaveAttribute('aria-expanded'); expect(onOpen).toBeCalledTimes(1); expect(onClose).toBeCalledTimes(0); } @@ -290,13 +290,13 @@ describe('MenuTrigger', function () { expect(onSelect).toBeCalledTimes(1); } - expect(menuTester.menu()).toBeInTheDocument(); + expect(menuTester.getMenu()).toBeInTheDocument(); if (Component === MenuTrigger) { - expect(menuTester.trigger()).toHaveAttribute('aria-expanded', 'true'); + expect(menuTester.getTrigger()).toHaveAttribute('aria-expanded', 'true'); expect(onOpenChange).toBeCalledTimes(1); } else { - expect(menuTester.trigger()).toHaveAttribute('aria-expanded'); + expect(menuTester.getTrigger()).toHaveAttribute('aria-expanded'); expect(onOpen).toBeCalledTimes(1); expect(onClose).toBeCalledTimes(0); } @@ -323,8 +323,8 @@ describe('MenuTrigger', function () { closesOnSelect: false }); - expect(menuTester.menu()).toBeInTheDocument(); - expect(menuTester.trigger()).toHaveAttribute('aria-expanded', 'true'); + expect(menuTester.getMenu()).toBeInTheDocument(); + expect(menuTester.getTrigger()).toHaveAttribute('aria-expanded', 'true'); expect(onOpenChange).toBeCalledTimes(1); } ); @@ -366,7 +366,7 @@ describe('MenuTrigger', function () { expect(onSelectionChange.mock.calls[1][0].has('Bar')).toBeTruthy(); await menuTester.close(); - expect(menuTester.menu()).not.toBeInTheDocument(); + expect(menuTester.getMenu()).not.toBeInTheDocument(); expect(onOpenChange).toBeCalledTimes(2); } ); @@ -1014,7 +1014,7 @@ describe('MenuTrigger', function () { jest.runAllTimers(); }); - let menu = menuTester.menu(); + let menu = menuTester.getMenu(); await user.tab(); act(() => { @@ -1024,7 +1024,7 @@ describe('MenuTrigger', function () { jest.runAllTimers(); }); expect(menu).toBeInTheDocument(); - expect(document.activeElement).toBe(menuTester.options()[0]); + expect(document.activeElement).toBe(menuTester.getOptions()[0]); }); }); diff --git a/packages/@adobe/react-spectrum/test/picker/Picker.test.js b/packages/@adobe/react-spectrum/test/picker/Picker.test.js index dfe3fb80daf..92c6d270563 100644 --- a/packages/@adobe/react-spectrum/test/picker/Picker.test.js +++ b/packages/@adobe/react-spectrum/test/picker/Picker.test.js @@ -108,17 +108,17 @@ describe('Picker', function () { let selectTester = testUtilUser.createTester('Select', {root: getByRole('button')}); expect(queryByRole('listbox')).toBeNull(); - let picker = selectTester.trigger(); + let picker = selectTester.getTrigger(); await selectTester.open(); - let listbox = selectTester.listbox(); + let listbox = selectTester.getListbox(); expect(listbox).toBeVisible(); expect(onOpenChange).toBeCalledTimes(1); expect(onOpenChange).toHaveBeenCalledWith(true); expect(picker).toHaveAttribute('aria-expanded', 'true'); expect(picker).toHaveAttribute('aria-controls', listbox.id); - let items = selectTester.options(); + let items = selectTester.getOptions(); expect(items.length).toBe(3); expect(items[0]).toHaveTextContent('One'); expect(items[1]).toHaveTextContent('Two'); @@ -218,18 +218,18 @@ describe('Picker', function () { expect(queryByRole('listbox')).toBeNull(); let selectTester = testUtilUser.createTester('Select', {root: getByRole('button')}); selectTester.setInteractionType('keyboard'); - let picker = selectTester.trigger(); + let picker = selectTester.getTrigger(); await selectTester.open(); - let listbox = selectTester.listbox(); + let listbox = selectTester.getListbox(); expect(listbox).toBeVisible(); expect(onOpenChange).toBeCalledTimes(1); expect(onOpenChange).toHaveBeenCalledWith(true); expect(picker).toHaveAttribute('aria-expanded', 'true'); expect(picker).toHaveAttribute('aria-controls', listbox.id); - let items = selectTester.options(); + let items = selectTester.getOptions(); expect(items.length).toBe(3); expect(items[0]).toHaveTextContent('One'); expect(items[1]).toHaveTextContent('Two'); @@ -252,7 +252,7 @@ describe('Picker', function () { expect(queryByRole('listbox')).toBeNull(); let selectTester = testUtilUser.createTester('Select', {root: getByRole('button')}); - let picker = selectTester.trigger(); + let picker = selectTester.getTrigger(); // TODO: for these keyboard event, IMO we don't have to include in the test utils since the user can pretty // easily define what specific keyboard interactions they want to do. We can handle firing the various intermediate interactions // for basic flows (aka we will handle firing Enter in selectTester.open()) @@ -260,14 +260,14 @@ describe('Picker', function () { fireEvent.keyUp(picker, {key: 'ArrowDown'}); act(() => jest.runAllTimers()); - let listbox = selectTester.listbox(); + let listbox = selectTester.getListbox(); expect(listbox).toBeVisible(); expect(onOpenChange).toBeCalledTimes(1); expect(onOpenChange).toHaveBeenCalledWith(true); expect(picker).toHaveAttribute('aria-expanded', 'true'); expect(picker).toHaveAttribute('aria-controls', listbox.id); - let items = selectTester.options(); + let items = selectTester.getOptions(); expect(items.length).toBe(3); expect(items[0]).toHaveTextContent('One'); expect(items[1]).toHaveTextContent('Two'); @@ -541,10 +541,10 @@ describe('Picker', function () { expect(queryByRole('listbox')).toBeNull(); let selectTester = testUtilUser.createTester('Select', {root: getByRole('button')}); - let picker = selectTester.trigger(); + let picker = selectTester.getTrigger(); await selectTester.open(); - let listbox = selectTester.listbox(); + let listbox = selectTester.getListbox(); expect(listbox).toBeVisible(); expect(onOpenChange).toBeCalledTimes(1); expect(onOpenChange).toHaveBeenCalledWith(true); @@ -963,12 +963,12 @@ describe('Picker', function () { ); let selectTester = testUtilUser.createTester('Select', {root: getByRole('button')}); - let picker = selectTester.trigger(); + let picker = selectTester.getTrigger(); expect(picker).toHaveTextContent('Select…'); await selectTester.open(); - let listbox = selectTester.listbox(); - let items = selectTester.options(); + let listbox = selectTester.getListbox(); + let items = selectTester.getOptions(); expect(items.length).toBe(3); expect(items[0]).toHaveTextContent('One'); expect(items[1]).toHaveTextContent('Two'); @@ -995,12 +995,12 @@ describe('Picker', function () { ); let selectTester = testUtilUser.createTester('Select', {root: getByRole('button')}); - let picker = selectTester.trigger(); + let picker = selectTester.getTrigger(); expect(picker).toHaveTextContent('Select…'); await selectTester.open(); - let listbox = selectTester.listbox(); - let items = selectTester.options(); + let listbox = selectTester.getListbox(); + let items = selectTester.getOptions(); expect(items.length).toBe(3); expect(items[0]).toHaveTextContent('Empty'); expect(items[1]).toHaveTextContent('Zero'); @@ -1085,12 +1085,12 @@ describe('Picker', function () { ); let selectTester = testUtilUser.createTester('Select', {root: getByRole('button')}); selectTester.setInteractionType('keyboard'); - let picker = selectTester.trigger(); + let picker = selectTester.getTrigger(); expect(picker).toHaveTextContent('Select…'); await selectTester.open(); - let items = selectTester.options(); + let items = selectTester.getOptions(); expect(items.length).toBe(3); expect(items[0]).toHaveTextContent('One'); expect(items[1]).toHaveTextContent('Two'); @@ -1161,18 +1161,18 @@ describe('Picker', function () { ); let selectTester = testUtilUser.createTester('Select', {root: getByRole('button')}); - let picker = selectTester.trigger(); + let picker = selectTester.getTrigger(); expect(picker).toHaveTextContent('Select…'); expect(onOpenChangeSpy).toHaveBeenCalledTimes(0); await selectTester.open(); expect(onOpenChangeSpy).toHaveBeenCalledTimes(1); - let listbox = selectTester.listbox(); + let listbox = selectTester.getListbox(); let label = getAllByText('Test')[0]; expect(listbox).toBeVisible(); expect(listbox).toHaveAttribute('aria-labelledby', label.id); - let items = selectTester.options(); + let items = selectTester.getOptions(); expect(items[0]).toHaveTextContent('One'); expect(items[1]).toHaveTextContent('Two'); expect(items[2]).toHaveTextContent('Three'); @@ -1365,15 +1365,15 @@ describe('Picker', function () { ); let selectTester = testUtilUser.createTester('Select', {root: getByRole('button')}); - let picker = selectTester.trigger(); + let picker = selectTester.getTrigger(); expect(picker).toHaveTextContent('Select…'); await selectTester.open(); - let listbox = selectTester.listbox(); - let items = selectTester.options(); + let listbox = selectTester.getListbox(); + let items = selectTester.getOptions(); expect(items.length).toBe(6); - let groups = selectTester.sections(); + let groups = selectTester.getSections(); expect(groups).toHaveLength(2); expect(groups[0]).toHaveAttribute('aria-labelledby', getByText('Section 1').id); @@ -1427,8 +1427,8 @@ describe('Picker', function () { // Open again await selectTester.open(); - listbox = selectTester.listbox(); - items = selectTester.options(); + listbox = selectTester.getListbox(); + items = selectTester.getOptions(); expect(items.length).toBe(6); expect(document.activeElement).toBe(items[1]); @@ -1535,11 +1535,11 @@ describe('Picker', function () { ); let selectTester = testUtilUser.createTester('Select', {root: getByRole('button')}); - let picker = selectTester.trigger(); + let picker = selectTester.getTrigger(); expect(picker).toHaveTextContent('Two'); await selectTester.open(); - let items = selectTester.options(); + let items = selectTester.getOptions(); expect(document.activeElement).toBe(items[1]); await selectTester.toggleOptionSelection({option: 'Two'}); @@ -2138,7 +2138,7 @@ describe('Picker', function () { ); let selectTester = testUtilUser.createTester('Select', {root: getByRole('button')}); - let picker = selectTester.trigger(); + let picker = selectTester.getTrigger(); let input = document.querySelector('[name=picker]'); expect(input).toHaveAttribute('required'); expect(picker).not.toHaveAttribute('aria-describedby'); @@ -2177,7 +2177,7 @@ describe('Picker', function () { ); let selectTester = testUtilUser.createTester('Select', {root: getByRole('button')}); - let picker = selectTester.trigger(); + let picker = selectTester.getTrigger(); let input = document.querySelector('[name=picker]'); expect(picker).not.toHaveAttribute('aria-describedby'); expect(input.validity.valid).toBe(false); @@ -2228,7 +2228,7 @@ describe('Picker', function () { let {getByTestId} = render(); let selectTester = testUtilUser.createTester('Select', {root: getByTestId('picker')}); - let picker = selectTester.trigger(); + let picker = selectTester.getTrigger(); let input = document.querySelector('[name=picker]'); expect(picker).not.toHaveAttribute('aria-describedby'); @@ -2299,7 +2299,7 @@ describe('Picker', function () { ); let selectTester = testUtilUser.createTester('Select', {root: getByTestId('picker')}); - let picker = selectTester.trigger(); + let picker = selectTester.getTrigger(); let input = document.querySelector('[name=picker]'); expect(input).toHaveAttribute('required'); expect(picker).not.toHaveAttribute('aria-describedby'); @@ -2341,7 +2341,7 @@ describe('Picker', function () { ); let selectTester = testUtilUser.createTester('Select', {root: getByTestId('picker')}); - let picker = selectTester.trigger(); + let picker = selectTester.getTrigger(); let input = document.querySelector('[name=picker]'); expect(picker).toHaveAttribute('aria-describedby'); expect( @@ -2366,7 +2366,7 @@ describe('Picker', function () { ); let selectTester = testUtilUser.createTester('Select', {root: getByTestId('picker')}); - let picker = selectTester.trigger(); + let picker = selectTester.getTrigger(); expect(picker).toHaveAttribute('aria-describedby'); expect( document.getElementById(picker.getAttribute('aria-describedby')) diff --git a/packages/@adobe/react-spectrum/test/picker/TempUtilTest.test.js b/packages/@adobe/react-spectrum/test/picker/TempUtilTest.test.js index db179246772..943441ac6b9 100644 --- a/packages/@adobe/react-spectrum/test/picker/TempUtilTest.test.js +++ b/packages/@adobe/react-spectrum/test/picker/TempUtilTest.test.js @@ -135,7 +135,7 @@ describe('Picker/Select ', function () { let selectTester = testUtilUser.createTester('Select', {root: screen.getByTestId('test')}); await selectTester.toggleOptionSelection({option: 'Three'}); - expect(selectTester.trigger()).toHaveTextContent('Three'); + expect(selectTester.getTrigger()).toHaveTextContent('Three'); expect(onSelectionChange).toHaveBeenCalledTimes(1); expect(onSelectionChange).toHaveBeenLastCalledWith('three'); }); @@ -161,7 +161,7 @@ describe('Picker/Select ', function () { let selectTester = testUtilUser.createTester('Select', {root: screen.getByTestId('test')}); await selectTester.toggleOptionSelection({option: 'Cat'}); - expect(selectTester.trigger()).toHaveTextContent('Cat'); + expect(selectTester.getTrigger()).toHaveTextContent('Cat'); expect(onSelectionChange).toHaveBeenCalledTimes(1); expect(onSelectionChange).toHaveBeenLastCalledWith('cat'); }); @@ -248,7 +248,7 @@ describe('Picker/Select ', function () { let selectTester = testUtilUser.createTester('Select', {root: screen.getByTestId('test')}); await selectTester.toggleOptionSelection({option: 'Three'}); - expect(selectTester.trigger()).toHaveTextContent('Three'); + expect(selectTester.getTrigger()).toHaveTextContent('Three'); expect(onSelectionChange).toHaveBeenCalledTimes(1); expect(onSelectionChange).toHaveBeenLastCalledWith('three'); }); @@ -276,7 +276,7 @@ describe('Picker/Select ', function () { root: screen.getAllByTestId('test')[0] }); await selectTester.toggleOptionSelection({option: 'Cat'}); - expect(selectTester.trigger()).toHaveTextContent('Cat'); + expect(selectTester.getTrigger()).toHaveTextContent('Cat'); expect(onSelectionChange).toHaveBeenCalledTimes(1); expect(onSelectionChange).toHaveBeenLastCalledWith('cat'); }); @@ -306,7 +306,7 @@ describe('Picker/Select ', function () { let selectTester = testUtilUser.createTester('Select', {root: screen.getByTestId('test')}); await selectTester.open(); - expect(await screen.findByTestId('tray')).toContainElement(selectTester.listbox()); + expect(await screen.findByTestId('tray')).toContainElement(selectTester.getListbox()); }); }); }); diff --git a/packages/@adobe/react-spectrum/test/radio/Radio.test.js b/packages/@adobe/react-spectrum/test/radio/Radio.test.js index b25b848bd6d..6a668365f13 100644 --- a/packages/@adobe/react-spectrum/test/radio/Radio.test.js +++ b/packages/@adobe/react-spectrum/test/radio/Radio.test.js @@ -1152,7 +1152,7 @@ describe('Radios', function () { root: getByRole('radiogroup'), direction }); - let radios = radioGroupTester.radios(); + let radios = radioGroupTester.getRadios(); await radioGroupTester.triggerRadio({radio: radios[0]}); expect(radios[0]).toBeChecked(); diff --git a/packages/@adobe/react-spectrum/test/table/TableTests.js b/packages/@adobe/react-spectrum/test/table/TableTests.js index d1d1333aca7..741796f395f 100644 --- a/packages/@adobe/react-spectrum/test/table/TableTests.js +++ b/packages/@adobe/react-spectrum/test/table/TableTests.js @@ -2327,15 +2327,15 @@ export let tableTests = () => { tableTester.setInteractionType('keyboard'); await tableTester.toggleRowSelection({row: 0}); - expect(tableTester.selectedRows()).toHaveLength(1); + expect(tableTester.getSelectedRows()).toHaveLength(1); expect(onSelectionChange).toHaveBeenCalledTimes(1); await tableTester.toggleRowSelection({row: 1}); - expect(tableTester.selectedRows()).toHaveLength(2); + expect(tableTester.getSelectedRows()).toHaveLength(2); expect(onSelectionChange).toHaveBeenCalledTimes(2); await user.keyboard('{Escape}'); - expect(tableTester.selectedRows()).toHaveLength(2); + expect(tableTester.getSelectedRows()).toHaveLength(2); expect(onSelectionChange).toHaveBeenCalledTimes(2); }); @@ -2751,12 +2751,12 @@ export let tableTests = () => { checkSelectAll(tree, 'unchecked'); - let rows = tableTester.rows(); + let rows = tableTester.getRows(); checkRowSelection(rows.slice(1), false); - expect(tableTester.selectedRows()).toHaveLength(0); + expect(tableTester.getSelectedRows()).toHaveLength(0); await tableTester.toggleSelectAll(); - expect(tableTester.selectedRows()).toHaveLength(tableTester.rows().length); + expect(tableTester.getSelectedRows()).toHaveLength(tableTester.getRows().length); expect(onSelectionChange).toHaveBeenCalledTimes(1); expect(onSelectionChange.mock.calls[0][0]).toEqual('all'); checkRowSelection(rows.slice(1), true); @@ -4897,7 +4897,7 @@ export let tableTests = () => { let tree = render(); let tableTester = testUtilUser.createTester('Table', {root: tree.getByRole('grid')}); tableTester.setInteractionType('keyboard'); - let columnheaders = tableTester.columns(); + let columnheaders = tableTester.getColumns(); expect(columnheaders).toHaveLength(3); expect(columnheaders[0]).not.toHaveAttribute('aria-sort'); expect(columnheaders[1]).not.toHaveAttribute('aria-sort'); diff --git a/packages/@adobe/react-spectrum/test/tabs/Tabs.test.js b/packages/@adobe/react-spectrum/test/tabs/Tabs.test.js index 3ecc0f3837a..5ec0fcf4d2e 100644 --- a/packages/@adobe/react-spectrum/test/tabs/Tabs.test.js +++ b/packages/@adobe/react-spectrum/test/tabs/Tabs.test.js @@ -86,11 +86,11 @@ describe('Tabs', function () { let container = renderComponent(); let tabsTester = testUtilUser.createTester('Tabs', {root: container.getByRole('tablist')}); - let tablist = tabsTester.tablist(); + let tablist = tabsTester.getTablist(); expect(tablist).toBeTruthy(); expect(tablist).toHaveAttribute('aria-orientation', 'horizontal'); - let tabs = tabsTester.tabs(); + let tabs = tabsTester.getTabs(); expect(tabs.length).toBe(3); for (let tab of tabs) { @@ -98,15 +98,15 @@ describe('Tabs', function () { expect(tab).toHaveAttribute('aria-selected'); let isSelected = tab.getAttribute('aria-selected') === 'true'; if (isSelected) { - expect(tab).toBe(tabsTester.selectedTab()); + expect(tab).toBe(tabsTester.getSelectedTab()); expect(tab).toHaveAttribute('aria-controls'); let tabpanel = document.getElementById(tab.getAttribute('aria-controls')); expect(tabpanel).toBeTruthy(); expect(tabpanel).toHaveAttribute('aria-labelledby', tab.id); expect(tabpanel).toHaveAttribute('role', 'tabpanel'); expect(tabpanel).toHaveTextContent(defaultItems[0].children); - expect(tabpanel).toBe(tabsTester.activeTabpanel()); - expect(tabsTester.tabpanels()).toHaveLength(1); + expect(tabpanel).toBe(tabsTester.getActiveTabpanel()); + expect(tabsTester.getTabpanels()).toHaveLength(1); } } }); @@ -163,7 +163,7 @@ describe('Tabs', function () { interactionType: 'keyboard', direction: 'rtl' }); - let tabs = tabsTester.tabs(); + let tabs = tabsTester.getTabs(); window.addEventListener('keydown', onKeyDown); expect(tabs[0]).toHaveAttribute('aria-selected', 'true'); @@ -1330,23 +1330,23 @@ describe('Tabs', function () { let direction = props.locale === 'ar-AE' ? 'rtl' : 'ltr'; let tabsTester = testUtilUser.createTester('Tabs', {root: getByRole('tablist'), direction}); - expect(tabsTester.tablist()).toHaveAttribute('aria-orientation', props.orientation); - let tabs = tabsTester.tabs(); + expect(tabsTester.getTablist()).toHaveAttribute('aria-orientation', props.orientation); + let tabs = tabsTester.getTabs(); await tabsTester.triggerTab({tab: tabs[0]}); - expect(tabsTester.selectedTab()).toBe(tabs[0]); + expect(tabsTester.getSelectedTab()).toBe(tabs[0]); await tabsTester.triggerTab({tab: 4, interactionType: 'keyboard'}); - expect(tabsTester.selectedTab()).toBe(tabs[4]); + expect(tabsTester.getSelectedTab()).toBe(tabs[4]); let tab4 = tabsTester.findTab({indexOrText: 3}); await tabsTester.triggerTab({tab: tab4, interactionType: 'keyboard'}); - expect(tabsTester.selectedTab()).toBe(tabs[3]); + expect(tabsTester.getSelectedTab()).toBe(tabs[3]); await tabsTester.triggerTab({tab: 'Tab 1', interactionType: 'mouse'}); - expect(tabsTester.selectedTab()).toBe(tabs[0]); + expect(tabsTester.getSelectedTab()).toBe(tabs[0]); let tab5 = tabsTester.findTab({indexOrText: 'Tab 5'}); await tabsTester.triggerTab({tab: tab5, interactionType: 'mouse'}); - expect(tabsTester.selectedTab()).toBe(tabs[4]); + expect(tabsTester.getSelectedTab()).toBe(tabs[4]); } ); }); diff --git a/packages/@adobe/react-spectrum/test/tree/TreeView.test.tsx b/packages/@adobe/react-spectrum/test/tree/TreeView.test.tsx index 1e647dbbcce..a255deb0b26 100644 --- a/packages/@adobe/react-spectrum/test/tree/TreeView.test.tsx +++ b/packages/@adobe/react-spectrum/test/tree/TreeView.test.tsx @@ -428,7 +428,7 @@ describe('Tree', () => { it('should support dynamic trees', () => { let {getByRole} = render(); let treeTester = testUtilUser.createTester('Tree', {user, root: getByRole('treegrid')}); - let rows = treeTester.rows(); + let rows = treeTester.getRows(); expect(rows).toHaveLength(20); // Check the rough structure to make sure dynamic rows are rendering as expected (just checks the expandable rows and their attributes) @@ -498,10 +498,10 @@ describe('Tree', () => { ); let treeTester = testUtilUser.createTester('Tree', {user, root: getByRole('treegrid')}); - expect(treeTester.tree()).toHaveAttribute('aria-multiselectable', 'true'); - let rows = treeTester.rows(); + expect(treeTester.getTree()).toHaveAttribute('aria-multiselectable', 'true'); + let rows = treeTester.getRows(); - for (let row of treeTester.rows()) { + for (let row of treeTester.getRows()) { let checkbox = within(row).queryByRole('checkbox'); expect(checkbox).toBeNull(); expect(row).toHaveAttribute('aria-selected', 'false'); @@ -515,8 +515,8 @@ describe('Tree', () => { expect(row2).toHaveAttribute('data-selected', 'true'); expect(onSelectionChange).toHaveBeenCalledTimes(1); expect(new Set(onSelectionChange.mock.calls[0][0])).toEqual(new Set(['Projects-1'])); - expect(treeTester.selectedRows()).toHaveLength(1); - expect(treeTester.selectedRows()[0]).toBe(row2); + expect(treeTester.getSelectedRows()).toHaveLength(1); + expect(treeTester.getSelectedRows()[0]).toBe(row2); let row1 = rows[1]; await treeTester.toggleRowSelection({row: row1}); @@ -526,8 +526,8 @@ describe('Tree', () => { expect(row2).not.toHaveAttribute('data-selected'); expect(onSelectionChange).toHaveBeenCalledTimes(2); expect(new Set(onSelectionChange.mock.calls[1][0])).toEqual(new Set(['Projects'])); - expect(treeTester.selectedRows()).toHaveLength(1); - expect(treeTester.selectedRows()[0]).toBe(row1); + expect(treeTester.getSelectedRows()).toHaveLength(1); + expect(treeTester.getSelectedRows()[0]).toBe(row1); }); it('should prevent Esc from clearing selection if escapeKeyBehavior is "none"', async () => { @@ -535,12 +535,12 @@ describe('Tree', () => { ); let treeTester = testUtilUser.createTester('Tree', {user, root: getByRole('treegrid')}); - let rows = treeTester.rows(); + let rows = treeTester.getRows(); let row1 = rows[1]; await treeTester.toggleRowSelection({row: row1}); expect(onSelectionChange).toHaveBeenCalledTimes(1); expect(new Set(onSelectionChange.mock.calls[0][0])).toEqual(new Set(['Projects'])); - expect(treeTester.selectedRows()).toHaveLength(1); + expect(treeTester.getSelectedRows()).toHaveLength(1); let row2 = rows[2]; await treeTester.toggleRowSelection({row: row2}); @@ -548,11 +548,11 @@ describe('Tree', () => { expect(new Set(onSelectionChange.mock.calls[1][0])).toEqual( new Set(['Projects', 'Projects-1']) ); - expect(treeTester.selectedRows()).toHaveLength(2); + expect(treeTester.getSelectedRows()).toHaveLength(2); await user.keyboard('{Escape}'); expect(onSelectionChange).toHaveBeenCalledTimes(2); - expect(treeTester.selectedRows()).toHaveLength(2); + expect(treeTester.getSelectedRows()).toHaveLength(2); }); it('should render a chevron for an expandable row marked with hasChildItems', () => { @@ -763,7 +763,7 @@ describe('Tree', () => { ); let treeTester = testUtilUser.createTester('Tree', {user, root: getByRole('treegrid')}); - let rows = treeTester.rows(); + let rows = treeTester.getRows(); await treeTester.triggerRowAction({row: rows[0]}); expect(onAction).toHaveBeenCalledTimes(1); expect(onAction).toHaveBeenLastCalledWith('Photos'); @@ -809,9 +809,9 @@ describe('Tree', () => { root: getByRole('treegrid'), interactionType: type as 'keyboard' | 'mouse' | 'touch' }); - let rows = treeTester.rows(); + let rows = treeTester.getRows(); - for (let row of treeTester.rows()) { + for (let row of treeTester.getRows()) { let checkbox = within(row).queryByRole('checkbox'); expect(checkbox).toBeNull(); expect(row).toHaveAttribute('aria-selected', 'false'); @@ -830,8 +830,8 @@ describe('Tree', () => { expect(onSelectionChange).toHaveBeenCalledTimes(1); } expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual(new Set(['Projects-1'])); - expect(treeTester.selectedRows()).toHaveLength(1); - expect(treeTester.selectedRows()[0]).toBe(row2); + expect(treeTester.getSelectedRows()).toHaveLength(1); + expect(treeTester.getSelectedRows()[0]).toBe(row2); let row1 = rows[1]; await treeTester.toggleRowSelection({row: row1, selectionBehavior: 'replace'}); @@ -845,8 +845,8 @@ describe('Tree', () => { expect(onSelectionChange).toHaveBeenCalledTimes(2); } expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual(new Set(['Projects'])); - expect(treeTester.selectedRows()).toHaveLength(1); - expect(treeTester.selectedRows()[0]).toBe(row1); + expect(treeTester.getSelectedRows()).toHaveLength(1); + expect(treeTester.getSelectedRows()[0]).toBe(row1); await treeTester.toggleRowSelection({row: row1, selectionBehavior: 'replace'}); expect(row1).toHaveAttribute('aria-selected', 'false'); @@ -859,7 +859,7 @@ describe('Tree', () => { expect(onSelectionChange).toHaveBeenCalledTimes(3); } expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual(new Set([])); - expect(treeTester.selectedRows()).toHaveLength(0); + expect(treeTester.getSelectedRows()).toHaveLength(0); }); it('should perform toggle selection in highlight mode when using modifier keys', async () => { @@ -871,9 +871,9 @@ describe('Tree', () => { root: getByRole('treegrid'), interactionType: type as 'keyboard' | 'mouse' | 'touch' }); - let rows = treeTester.rows(); + let rows = treeTester.getRows(); - for (let row of treeTester.rows()) { + for (let row of treeTester.getRows()) { let checkbox = within(row).queryByRole('checkbox'); expect(checkbox).toBeNull(); expect(row).toHaveAttribute('aria-selected', 'false'); @@ -891,15 +891,15 @@ describe('Tree', () => { expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual( new Set(['Photos', 'Projects-1']) ); - expect(treeTester.selectedRows()).toHaveLength(2); - expect(treeTester.selectedRows()[1]).toBe(row2); + expect(treeTester.getSelectedRows()).toHaveLength(2); + expect(treeTester.getSelectedRows()[1]).toBe(row2); } else { expect(onSelectionChange).toHaveBeenCalledTimes(1); expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual( new Set(['Projects-1']) ); - expect(treeTester.selectedRows()).toHaveLength(1); - expect(treeTester.selectedRows()[0]).toBe(row2); + expect(treeTester.getSelectedRows()).toHaveLength(1); + expect(treeTester.getSelectedRows()[0]).toBe(row2); } let row1 = rows[1]; @@ -913,17 +913,17 @@ describe('Tree', () => { expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual( new Set(['Photos', 'Projects-1', 'Projects']) ); - expect(treeTester.selectedRows()).toHaveLength(3); - expect(treeTester.selectedRows()[1]).toBe(row1); - expect(treeTester.selectedRows()[2]).toBe(row2); + expect(treeTester.getSelectedRows()).toHaveLength(3); + expect(treeTester.getSelectedRows()[1]).toBe(row1); + expect(treeTester.getSelectedRows()[2]).toBe(row2); } else { expect(onSelectionChange).toHaveBeenCalledTimes(2); expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual( new Set(['Projects-1', 'Projects']) ); - expect(treeTester.selectedRows()).toHaveLength(2); - expect(treeTester.selectedRows()[0]).toBe(row1); - expect(treeTester.selectedRows()[1]).toBe(row2); + expect(treeTester.getSelectedRows()).toHaveLength(2); + expect(treeTester.getSelectedRows()[0]).toBe(row1); + expect(treeTester.getSelectedRows()[1]).toBe(row2); } // With modifier key, you should be able to deselect on press of the same row @@ -937,15 +937,15 @@ describe('Tree', () => { expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual( new Set(['Photos', 'Projects-1']) ); - expect(treeTester.selectedRows()).toHaveLength(2); - expect(treeTester.selectedRows()[1]).toBe(row2); + expect(treeTester.getSelectedRows()).toHaveLength(2); + expect(treeTester.getSelectedRows()[1]).toBe(row2); } else { expect(onSelectionChange).toHaveBeenCalledTimes(3); expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual( new Set(['Projects-1']) ); - expect(treeTester.selectedRows()).toHaveLength(1); - expect(treeTester.selectedRows()[0]).toBe(row2); + expect(treeTester.getSelectedRows()).toHaveLength(1); + expect(treeTester.getSelectedRows()[0]).toBe(row2); } }); @@ -958,9 +958,9 @@ describe('Tree', () => { root: getByRole('treegrid'), interactionType: type as 'keyboard' | 'mouse' | 'touch' }); - let rows = treeTester.rows(); + let rows = treeTester.getRows(); - for (let row of treeTester.rows()) { + for (let row of treeTester.getRows()) { let checkbox = within(row).queryByRole('checkbox'); expect(checkbox).toBeNull(); expect(row).toHaveAttribute('aria-selected', 'false'); @@ -979,8 +979,8 @@ describe('Tree', () => { expect(onSelectionChange).toHaveBeenCalledTimes(1); } expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual(new Set(['Projects-1'])); - expect(treeTester.selectedRows()).toHaveLength(1); - expect(treeTester.selectedRows()[0]).toBe(row2); + expect(treeTester.getSelectedRows()).toHaveLength(1); + expect(treeTester.getSelectedRows()[0]).toBe(row2); let row1 = rows[1]; await treeTester.toggleRowSelection({row: row1}); @@ -995,8 +995,8 @@ describe('Tree', () => { expect(onSelectionChange).toHaveBeenCalledTimes(2); } expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual(new Set(['Projects'])); - expect(treeTester.selectedRows()).toHaveLength(1); - expect(treeTester.selectedRows()[0]).toBe(row1); + expect(treeTester.getSelectedRows()).toHaveLength(1); + expect(treeTester.getSelectedRows()[0]).toBe(row1); // pressing without modifier keys won't deselect the row await treeTester.toggleRowSelection({row: row1}); @@ -1007,7 +1007,7 @@ describe('Tree', () => { } else { expect(onSelectionChange).toHaveBeenCalledTimes(2); } - expect(treeTester.selectedRows()).toHaveLength(1); + expect(treeTester.getSelectedRows()).toHaveLength(1); } else { // touch always behaves as toggle expect(row1).toHaveAttribute('aria-selected', 'true'); @@ -1018,16 +1018,16 @@ describe('Tree', () => { expect(new Set(onSelectionChange.mock.calls[1][0])).toEqual( new Set(['Projects', 'Projects-1']) ); - expect(treeTester.selectedRows()).toHaveLength(2); - expect(treeTester.selectedRows()[0]).toBe(row1); + expect(treeTester.getSelectedRows()).toHaveLength(2); + expect(treeTester.getSelectedRows()[0]).toBe(row1); await treeTester.toggleRowSelection({row: row1}); expect(row1).toHaveAttribute('aria-selected', 'false'); expect(row1).not.toHaveAttribute('data-selected'); expect(onSelectionChange).toHaveBeenCalledTimes(3); expect(new Set(onSelectionChange.mock.calls[2][0])).toEqual(new Set(['Projects-1'])); - expect(treeTester.selectedRows()).toHaveLength(1); - expect(treeTester.selectedRows()[0]).toBe(row2); + expect(treeTester.getSelectedRows()).toHaveLength(1); + expect(treeTester.getSelectedRows()[0]).toBe(row2); } }); }); @@ -1262,7 +1262,7 @@ describe('Tree', () => { it('should expand/collapse a row when clicking/using Enter on the row itself and there arent any other primary actions', async () => { let {getByRole} = render(); let treeTester = testUtilUser.createTester('Tree', {user, root: getByRole('treegrid')}); - let rows = treeTester.rows(); + let rows = treeTester.getRows(); expect(rows).toHaveLength(20); await user.tab(); @@ -1292,7 +1292,7 @@ describe('Tree', () => { expect(new Set(onExpandedChange.mock.calls[0][0])).toEqual( new Set(['Project-2', 'Project-5', 'Reports', 'Reports-1', 'Reports-1A', 'Reports-1AB']) ); - rows = treeTester.rows(); + rows = treeTester.getRows(); expect(rows).toHaveLength(9); await treeTester.toggleRowExpansion({ @@ -1318,7 +1318,7 @@ describe('Tree', () => { 'Reports-1AB' ]) ); - rows = treeTester.rows(); + rows = treeTester.getRows(); expect(rows).toHaveLength(20); await user.keyboard('{ArrowDown}'); @@ -1353,7 +1353,7 @@ describe('Tree', () => { expect(new Set(onExpandedChange.mock.calls[2][0])).toEqual( new Set(['Projects', 'Project-5', 'Reports', 'Reports-1', 'Reports-1A', 'Reports-1AB']) ); - rows = treeTester.rows(); + rows = treeTester.getRows(); expect(rows).toHaveLength(17); // Check behavior of onExpandedChange when a nested row is already closed and the parent is collapsed @@ -1368,7 +1368,7 @@ describe('Tree', () => { expect(new Set(onExpandedChange.mock.calls[3][0])).toEqual( new Set(['Project-5', 'Reports', 'Reports-1', 'Reports-1A', 'Reports-1AB']) ); - rows = treeTester.rows(); + rows = treeTester.getRows(); expect(rows).toHaveLength(9); // Check that the nested collapsed row is still closed when the parent is reexpanded @@ -1381,7 +1381,7 @@ describe('Tree', () => { expect(new Set(onExpandedChange.mock.calls[4][0])).toEqual( new Set(['Projects', 'Project-5', 'Reports', 'Reports-1', 'Reports-1A', 'Reports-1AB']) ); - rows = treeTester.rows(); + rows = treeTester.getRows(); expect(rows).toHaveLength(17); }); @@ -1661,16 +1661,16 @@ describe('Tree', () => { ); let treeTester = testUtilUser.createTester('Tree', {user, root: getByRole('treegrid')}); - let tree = treeTester.tree(); + let tree = treeTester.getTree(); expect(tree).toHaveAttribute('data-empty', 'true'); expect(tree).not.toHaveAttribute('data-focused'); expect(tree).not.toHaveAttribute('data-focus-visible'); - let row = treeTester.rows()[0]; + let row = treeTester.getRows()[0]; expect(row).toHaveAttribute('aria-level', '1'); expect(row).not.toHaveAttribute('aria-posinset'); expect(row).not.toHaveAttribute('aria-setsize'); - let gridCell = treeTester.cells({element: row})[0]; + let gridCell = treeTester.getCells({element: row})[0]; expect(gridCell).toHaveTextContent('No resultsNo results found.'); await user.tab(); diff --git a/packages/@react-aria/test-utils/src/checkboxgroup.ts b/packages/@react-aria/test-utils/src/checkboxgroup.ts index 96f457ddf9d..e33eae09a55 100644 --- a/packages/@react-aria/test-utils/src/checkboxgroup.ts +++ b/packages/@react-aria/test-utils/src/checkboxgroup.ts @@ -58,9 +58,9 @@ export class CheckboxGroupTester { let checkbox; if (typeof indexOrText === 'number') { - checkbox = this.checkboxes()[indexOrText]; + checkbox = this.getCheckboxes()[indexOrText]; } else if (typeof indexOrText === 'string') { - let label = within(this.checkboxgroup()).getByText(indexOrText); + let label = within(this.getCheckboxGroup()).getByText(indexOrText); // Label may wrap the checkbox, or the actual label may be a sibling span, or the checkbox div could have the label within it if (label) { @@ -81,7 +81,7 @@ export class CheckboxGroupTester { private async keyboardNavigateToCheckbox(opts: {checkbox: HTMLElement}) { let {checkbox} = opts; - let checkboxes = this.checkboxes(); + let checkboxes = this.getCheckboxes(); checkboxes = checkboxes.filter( checkbox => !(checkbox.hasAttribute('disabled') || checkbox.getAttribute('aria-disabled') === 'true') @@ -97,7 +97,7 @@ export class CheckboxGroupTester { throw new Error('Checkbox provided is not in the checkbox group.'); } - if (!this.checkboxgroup().contains(document.activeElement)) { + if (!this.getCheckboxGroup().contains(document.activeElement)) { act(() => checkboxes[0].focus()); } @@ -140,22 +140,22 @@ export class CheckboxGroupTester { /** * Returns the checkboxgroup. */ - checkboxgroup(): HTMLElement { + getCheckboxGroup(): HTMLElement { return this._checkboxgroup; } /** * Returns the checkboxes. */ - checkboxes(): HTMLElement[] { - return within(this.checkboxgroup()).queryAllByRole('checkbox'); + getCheckboxes(): HTMLElement[] { + return within(this.getCheckboxGroup()).queryAllByRole('checkbox'); } /** * Returns the currently selected checkboxes in the checkboxgroup if any. */ - selectedCheckboxes(): HTMLElement[] { - return this.checkboxes().filter( + getSelectedCheckboxes(): HTMLElement[] { + return this.getCheckboxes().filter( checkbox => (checkbox as HTMLInputElement).checked || checkbox.getAttribute('aria-checked') === 'true' ); diff --git a/packages/@react-aria/test-utils/src/combobox.ts b/packages/@react-aria/test-utils/src/combobox.ts index 30467187389..11e35442041 100644 --- a/packages/@react-aria/test-utils/src/combobox.ts +++ b/packages/@react-aria/test-utils/src/combobox.ts @@ -29,7 +29,7 @@ interface ComboBoxOpenOpts { interface ComboBoxSelectOpts extends ComboBoxOpenOpts { /** - * The index, text, or node of the option to select. Option nodes can be sourced via `options()`. + * The index, text, or node of the option to select. Option nodes can be sourced via `getOptions()`. */ option: number | string | HTMLElement; /** @@ -88,8 +88,8 @@ export class ComboBoxTester { */ async open(opts: ComboBoxOpenOpts = {}): Promise { let {triggerBehavior = 'manual', interactionType = this._interactionType} = opts; - let trigger = this.trigger(); - let combobox = this.combobox(); + let trigger = this.getTrigger(); + let combobox = this.getCombobox(); let isDisabled = trigger!.hasAttribute('disabled'); if (interactionType === 'mouse') { @@ -135,8 +135,8 @@ export class ComboBoxTester { let {indexOrText} = opts; let option; - let options = this.options(); - let listbox = this.listbox(); + let options = this.getOptions(); + let listbox = this.getListbox(); if (typeof indexOrText === 'number') { option = options[indexOrText]; @@ -149,8 +149,8 @@ export class ComboBoxTester { private async keyboardNavigateToOption(opts: {option: HTMLElement}) { let {option} = opts; - let combobox = this.combobox(); - let options = this.options(); + let combobox = this.getCombobox(); + let options = this.getOptions(); let targetIndex = options.findIndex(opt => opt === option || opt.contains(option)); if (targetIndex === -1) { throw new Error('Option provided is not in the combobox listbox.'); @@ -185,11 +185,11 @@ export class ComboBoxTester { */ async toggleOptionSelection(opts: ComboBoxSelectOpts): Promise { let {option, triggerBehavior, interactionType = this._interactionType, closesOnSelect} = opts; - if (!this.combobox().getAttribute('aria-controls')) { + if (!this.getCombobox().getAttribute('aria-controls')) { await this.open({triggerBehavior}); } - let listbox = this.listbox(); + let listbox = this.getListbox(); if (!listbox) { throw new Error("Combobox's listbox not found."); } @@ -231,9 +231,9 @@ export class ComboBoxTester { * Closes the combobox dropdown. */ async close(): Promise { - let listbox = this.listbox(); + let listbox = this.getListbox(); if (listbox) { - act(() => this.combobox().focus()); + act(() => this.getCombobox().focus()); await this.user.keyboard('[Escape]'); await waitFor(() => { @@ -251,38 +251,38 @@ export class ComboBoxTester { /** * Returns the combobox. */ - combobox(): HTMLElement { + getCombobox(): HTMLElement { return this._combobox; } /** * Returns the combobox trigger button. */ - trigger(): HTMLElement { + getTrigger(): HTMLElement { return this._trigger; } /** * Returns the combobox's listbox if present. */ - listbox(): HTMLElement | null { - let listBoxId = this.combobox().getAttribute('aria-controls'); + getListbox(): HTMLElement | null { + let listBoxId = this.getCombobox().getAttribute('aria-controls'); return listBoxId ? document.getElementById(listBoxId) || null : null; } /** * Returns the combobox's sections if present. */ - sections(): HTMLElement[] { - let listbox = this.listbox(); + getSections(): HTMLElement[] { + let listbox = this.getListbox(); return listbox ? within(listbox).queryAllByRole('group') : []; } /** * Returns the combobox's options if present. Can be filtered to a subsection of the listbox if provided via `element`. */ - options(opts: {element?: HTMLElement} = {}): HTMLElement[] { - let {element = this.listbox()} = opts; + getOptions(opts: {element?: HTMLElement} = {}): HTMLElement[] { + let {element = this.getListbox()} = opts; let options = []; if (element) { options = within(element).queryAllByRole('option'); @@ -294,8 +294,8 @@ export class ComboBoxTester { /** * Returns the currently focused option in the combobox's dropdown if any. */ - focusedOption(): HTMLElement | null { - let focusedOptionId = this.combobox().getAttribute('aria-activedescendant'); + getFocusedOption(): HTMLElement | null { + let focusedOptionId = this.getCombobox().getAttribute('aria-activedescendant'); return focusedOptionId ? document.getElementById(focusedOptionId) : null; } } diff --git a/packages/@react-aria/test-utils/src/dialog.ts b/packages/@react-aria/test-utils/src/dialog.ts index 93410260f52..bdf48071271 100644 --- a/packages/@react-aria/test-utils/src/dialog.ts +++ b/packages/@react-aria/test-utils/src/dialog.ts @@ -59,7 +59,7 @@ export class DialogTester { */ async open(opts: DialogOpenOpts = {}): Promise { let {interactionType = this._interactionType} = opts; - let trigger = this.trigger(); + let trigger = this.getTrigger(); if (!trigger.hasAttribute('disabled')) { if (interactionType === 'mouse') { await this.user.click(trigger); @@ -137,7 +137,7 @@ export class DialogTester { /** * Returns the dialog's trigger. */ - trigger(): HTMLElement { + getTrigger(): HTMLElement { if (!this._trigger) { throw new Error('No trigger element found for dialog.'); } @@ -148,7 +148,7 @@ export class DialogTester { /** * Returns the dialog if present. */ - dialog(): HTMLElement | null { + getDialog(): HTMLElement | null { return this._dialog && document.contains(this._dialog) ? this._dialog : null; } } diff --git a/packages/@react-aria/test-utils/src/gridlist.ts b/packages/@react-aria/test-utils/src/gridlist.ts index 994015a9372..2567f1b8abd 100644 --- a/packages/@react-aria/test-utils/src/gridlist.ts +++ b/packages/@react-aria/test-utils/src/gridlist.ts @@ -63,9 +63,9 @@ export class GridListTester { let row; if (typeof indexOrText === 'number') { - row = this.rows()[indexOrText]; + row = this.getRows()[indexOrText]; } else if (typeof indexOrText === 'string') { - row = within(this.gridlist()!).getByText(indexOrText).closest('[role=row]')! as HTMLElement; + row = within(this.getGridlist()!).getByText(indexOrText).closest('[role=row]')! as HTMLElement; } return row; @@ -77,7 +77,7 @@ export class GridListTester { }) { let {row, selectionOnNav = 'default'} = opts; let altKey = getAltKey(); - let rows = this.rows(); + let rows = this.getRows(); let targetIndex = rows.indexOf(row); if (targetIndex === -1) { throw new Error('Row provided is not in the gridlist'); @@ -245,29 +245,29 @@ export class GridListTester { /** * Returns the gridlist. */ - gridlist(): HTMLElement { + getGridlist(): HTMLElement { return this._gridlist; } /** * Returns the gridlist's rows if any. */ - rows(): HTMLElement[] { - return within(this.gridlist()).queryAllByRole('row'); + getRows(): HTMLElement[] { + return within(this.getGridlist()).queryAllByRole('row'); } /** * Returns the gridlist's selected rows if any. */ - selectedRows(): HTMLElement[] { - return this.rows().filter(row => row.getAttribute('aria-selected') === 'true'); + getSelectedRows(): HTMLElement[] { + return this.getRows().filter(row => row.getAttribute('aria-selected') === 'true'); } /** * Returns the gridlist's cells if any. Can be filtered against a specific row if provided via `element`. */ - cells(opts: {element?: HTMLElement} = {}): HTMLElement[] { - let {element = this.gridlist()} = opts; + getCells(opts: {element?: HTMLElement} = {}): HTMLElement[] { + let {element = this.getGridlist()} = opts; return within(element).queryAllByRole('gridcell'); } } diff --git a/packages/@react-aria/test-utils/src/listbox.ts b/packages/@react-aria/test-utils/src/listbox.ts index 16a138e56d5..87d5c6e4b62 100644 --- a/packages/@react-aria/test-utils/src/listbox.ts +++ b/packages/@react-aria/test-utils/src/listbox.ts @@ -90,12 +90,12 @@ export class ListBoxTester { let {indexOrText} = opts; let option; - let options = this.options(); + let options = this.getOptions(); if (typeof indexOrText === 'number') { option = options[indexOrText]; } else if (typeof indexOrText === 'string') { - option = within(this.listbox()!) + option = within(this.getListbox()!) .getByText(indexOrText) .closest('[role=option]')! as HTMLElement; } @@ -109,7 +109,7 @@ export class ListBoxTester { }) { let {option, selectionOnNav = 'default'} = opts; let altKey = getAltKey(); - let options = this.options(); + let options = this.getOptions(); let targetIndex = options.indexOf(option); if (targetIndex === -1) { throw new Error('Option provided is not in the listbox'); @@ -138,7 +138,7 @@ export class ListBoxTester { let curr = (document.activeElement as HTMLElement).getBoundingClientRect(); let target = option.getBoundingClientRect(); let key: string; - // basically compare current position with desired position to determine if we need to go up/down/left/right + // compare current position with desired position to determine if we need to go up/down/left/right // use 1 in the comparison here for subpixels since getBoundingClientRect returns subpixels precision if (Math.abs(curr.top - target.top) > 1) { key = curr.top < target.top ? 'ArrowDown' : 'ArrowUp'; @@ -253,14 +253,14 @@ export class ListBoxTester { /** * Returns the listbox. */ - listbox(): HTMLElement { + getListbox(): HTMLElement { return this._listbox; } /** * Returns the listbox options. Can be filtered to a subsection of the listbox if provided via `element`. */ - options(opts: {element?: HTMLElement} = {}): HTMLElement[] { + getOptions(opts: {element?: HTMLElement} = {}): HTMLElement[] { let {element = this._listbox} = opts; let options = []; if (element) { @@ -273,14 +273,14 @@ export class ListBoxTester { /** * Returns the listbox's selected options if any. */ - selectedOptions(): HTMLElement[] { - return this.options().filter(row => row.getAttribute('aria-selected') === 'true'); + getSelectedOptions(): HTMLElement[] { + return this.getOptions().filter(row => row.getAttribute('aria-selected') === 'true'); } /** * Returns the listbox's sections if any. */ - sections(): HTMLElement[] { + getSections(): HTMLElement[] { return within(this._listbox).queryAllByRole('group'); } } diff --git a/packages/@react-aria/test-utils/src/menu.ts b/packages/@react-aria/test-utils/src/menu.ts index a19d9a0f2fa..222dd27bb0b 100644 --- a/packages/@react-aria/test-utils/src/menu.ts +++ b/packages/@react-aria/test-utils/src/menu.ts @@ -32,7 +32,7 @@ interface MenuOpenOpts { interface MenuSelectOpts extends MenuOpenOpts { /** - * The index, text, or node of the option to select. Option nodes can be sourced via `options()`. + * The index, text, or node of the option to select. Option nodes can be sourced via `getOptions()`. */ option: number | string | HTMLElement; /** @@ -54,7 +54,7 @@ interface MenuSelectOpts extends MenuOpenOpts { interface MenuOpenSubmenuOpts extends MenuOpenOpts { /** - * The text or node of the submenu trigger to open. Available submenu trigger nodes can be sourced via `submenuTriggers`. + * The text or node of the submenu trigger to open. Available submenu trigger nodes can be sourced via `getSubmenuTriggers()`. */ submenuTrigger: string | HTMLElement; } @@ -106,7 +106,7 @@ export class MenuTester { */ async open(opts: MenuOpenOpts = {}): Promise { let {needsLongPress, interactionType = this._interactionType, direction} = opts; - let trigger = this.trigger(); + let trigger = this.getTrigger(); let isDisabled = trigger.hasAttribute('disabled'); if (interactionType === 'mouse' || interactionType === 'touch') { if (needsLongPress) { @@ -160,8 +160,8 @@ export class MenuTester { let {indexOrText} = opts; let option; - let options = this.options(); - let menu = this.menu(); + let options = this.getOptions(); + let menu = this.getMenu(); if (typeof indexOrText === 'number') { option = options[indexOrText]; @@ -187,13 +187,13 @@ export class MenuTester { interactionType = this._interactionType, keyboardActivation = 'Enter' } = opts; - let trigger = this.trigger(); + let trigger = this.getTrigger(); if (!trigger.getAttribute('aria-controls') && !trigger.hasAttribute('aria-expanded')) { await this.open({needsLongPress}); } - let menu = this.menu(); + let menu = this.getMenu(); if (!menu) { throw new Error('Menu not found.'); @@ -268,7 +268,7 @@ export class MenuTester { if (this._isSubmenu) { await waitFor(() => { if ( - document.activeElement === this.trigger() || + document.activeElement === this.getTrigger() || this._rootMenu?.contains(document.activeElement) ) { throw new Error( @@ -302,7 +302,7 @@ export class MenuTester { async openSubmenu(opts: MenuOpenSubmenuOpts): Promise { let {submenuTrigger, needsLongPress, interactionType = this._interactionType} = opts; - let trigger = this.trigger(); + let trigger = this.getTrigger(); let isDisabled = trigger.hasAttribute('disabled'); if (isDisabled) { throw new Error( @@ -312,10 +312,10 @@ export class MenuTester { if (!trigger.getAttribute('aria-controls')) { await this.open({needsLongPress}); } - let menu = this.menu(); + let menu = this.getMenu(); if (!menu) { throw new Error( - 'Cannot open submenu, parent menu didn\'t open on trigger "${formatTargetNode(trigger)}" press.' + `Cannot open submenu, parent menu didn't open on trigger "${formatTargetNode(trigger)}" press.` ); } if (typeof submenuTrigger === 'string') { @@ -330,7 +330,7 @@ export class MenuTester { root: submenuTrigger, isSubmenu: true, advanceTimer: this._advanceTimer, - rootMenu: (this._isSubmenu ? this._rootMenu : this.menu()) || undefined + rootMenu: (this._isSubmenu ? this._rootMenu : this.getMenu()) || undefined }); if (interactionType === 'mouse') { await this.user.pointer({target: submenuTrigger}); @@ -356,13 +356,13 @@ export class MenuTester { private async keyboardNavigateToOption(opts: {option: HTMLElement}) { let {option} = opts; - let options = this.options(); + let options = this.getOptions(); let targetIndex = options.findIndex(opt => opt === option || opt.contains(option)); if (targetIndex === -1) { throw new Error('Option provided is not in the menu'); } - if (document.activeElement === this.menu()) { + if (document.activeElement === this.getMenu()) { await this.user.keyboard('[ArrowDown]'); } let currIndex = options.indexOf(document.activeElement as HTMLElement); @@ -380,13 +380,13 @@ export class MenuTester { * Closes the menu. */ async close(): Promise { - let menu = this.menu(); + let menu = this.getMenu(); if (menu) { act(() => menu.focus()); await this.user.keyboard('[Escape]'); await waitFor(() => { - if (document.activeElement !== this.trigger()) { + if (document.activeElement !== this.getTrigger()) { throw new Error( `Expected the document.activeElement after closing the menu to be the menu trigger but got ${document.activeElement}` ); @@ -404,7 +404,7 @@ export class MenuTester { /** * Returns the menu's trigger. */ - trigger(): HTMLElement { + getTrigger(): HTMLElement { if (!this._trigger) { throw new Error('No trigger element found for menu.'); } @@ -415,16 +415,16 @@ export class MenuTester { /** * Returns the menu if present. */ - menu(): HTMLElement | null { - let menuId = this.trigger().getAttribute('aria-controls'); + getMenu(): HTMLElement | null { + let menuId = this.getTrigger().getAttribute('aria-controls'); return menuId ? document.getElementById(menuId) : null; } /** * Returns the menu's sections if any. */ - sections(): HTMLElement[] { - let menu = this.menu(); + getSections(): HTMLElement[] { + let menu = this.getMenu(); if (menu) { return within(menu).queryAllByRole('group'); } else { @@ -435,8 +435,8 @@ export class MenuTester { /** * Returns the menu's options if present. Can be filtered to a subsection of the menu if provided via `element`. */ - options(opts: {element?: HTMLElement} = {}): HTMLElement[] { - let {element = this.menu()} = opts; + getOptions(opts: {element?: HTMLElement} = {}): HTMLElement[] { + let {element = this.getMenu()} = opts; if (!element) { return []; } @@ -449,8 +449,8 @@ export class MenuTester { /** * Returns the menu's submenu triggers if any. */ - submenuTriggers(): HTMLElement[] { - let options = this.options(); + getSubmenuTriggers(): HTMLElement[] { + let options = this.getOptions(); if (options.length > 0) { return options.filter(item => item.getAttribute('aria-haspopup') != null); } diff --git a/packages/@react-aria/test-utils/src/radiogroup.ts b/packages/@react-aria/test-utils/src/radiogroup.ts index 3e579559896..0cf60c0b253 100644 --- a/packages/@react-aria/test-utils/src/radiogroup.ts +++ b/packages/@react-aria/test-utils/src/radiogroup.ts @@ -60,9 +60,9 @@ export class RadioGroupTester { let radio; if (typeof indexOrText === 'number') { - radio = this.radios()[indexOrText]; + radio = this.getRadios()[indexOrText]; } else if (typeof indexOrText === 'string') { - let label = within(this.radiogroup()).getByText(indexOrText); + let label = within(this.getRadioGroup()).getByText(indexOrText); // Label may wrap the radio, or the actual label may be a sibling span, or the radio div could have the label within it if (label) { radio = within(label).queryByRole('radio'); @@ -82,7 +82,7 @@ export class RadioGroupTester { private async keyboardNavigateToRadio(opts: {radio: HTMLElement; orientation?: Orientation}) { let {radio, orientation = 'vertical'} = opts; - let radios = this.radios(); + let radios = this.getRadios(); radios = radios.filter( radio => !(radio.hasAttribute('disabled') || radio.getAttribute('aria-disabled') === 'true') ); @@ -97,8 +97,8 @@ export class RadioGroupTester { throw new Error('Radio provided is not in the radio group.'); } - if (!this.radiogroup().contains(document.activeElement)) { - let selectedRadio = this.selectedRadio(); + if (!this.getRadioGroup().contains(document.activeElement)) { + let selectedRadio = this.getSelectedRadio(); if (selectedRadio != null) { act(() => selectedRadio.focus()); } else { @@ -158,21 +158,21 @@ export class RadioGroupTester { /** * Returns the radiogroup. */ - radiogroup(): HTMLElement { + getRadioGroup(): HTMLElement { return this._radiogroup; } /** * Returns the radios. */ - radios(): HTMLElement[] { - return within(this.radiogroup()).queryAllByRole('radio'); + getRadios(): HTMLElement[] { + return within(this.getRadioGroup()).queryAllByRole('radio'); } /** * Returns the currently selected radio in the radiogroup if any. */ - selectedRadio(): HTMLElement | null { - return this.radios().find(radio => (radio as HTMLInputElement).checked) || null; + getSelectedRadio(): HTMLElement | null { + return this.getRadios().find(radio => (radio as HTMLInputElement).checked) || null; } } diff --git a/packages/@react-aria/test-utils/src/select.ts b/packages/@react-aria/test-utils/src/select.ts index 3f48bf0bf51..6dcb2da9c24 100644 --- a/packages/@react-aria/test-utils/src/select.ts +++ b/packages/@react-aria/test-utils/src/select.ts @@ -24,7 +24,7 @@ interface SelectOpenOpts { interface SelectTriggerOptionOpts extends SelectOpenOpts { /** - * The index, text, or node of the option to select. Option nodes can be sourced via `options()`. + * The index, text, or node of the option to select. Option nodes can be sourced via `getOptions()`. */ option: number | string | HTMLElement; /** @@ -68,7 +68,7 @@ export class SelectTester { */ async open(opts: SelectOpenOpts = {}): Promise { let {interactionType = this._interactionType} = opts; - let trigger = this.trigger(); + let trigger = this.getTrigger(); let isDisabled = trigger.hasAttribute('disabled'); if (interactionType === 'mouse') { @@ -101,7 +101,7 @@ export class SelectTester { * Closes the select. */ async close(): Promise { - let listbox = this.listbox(); + let listbox = this.getListbox(); if (listbox) { act(() => listbox.focus()); await this.user.keyboard('[Escape]'); @@ -131,8 +131,8 @@ export class SelectTester { let {indexOrText} = opts; let option; - let options = this.options(); - let listbox = this.listbox(); + let options = this.getOptions(); + let listbox = this.getListbox(); if (typeof indexOrText === 'number') { option = options[indexOrText]; @@ -145,12 +145,12 @@ export class SelectTester { private async keyboardNavigateToOption(opts: {option: HTMLElement}) { let {option} = opts; - let options = this.options(); + let options = this.getOptions(); let targetIndex = options.indexOf(option); if (targetIndex === -1) { throw new Error('Option provided is not in the listbox'); } - if (document.activeElement === this.listbox()) { + if (document.activeElement === this.getListbox()) { await this.user.keyboard('[ArrowDown]'); } let currIndex = options.indexOf(document.activeElement as HTMLElement); @@ -170,11 +170,11 @@ export class SelectTester { */ async toggleOptionSelection(opts: SelectTriggerOptionOpts): Promise { let {option, closesOnSelect, interactionType = this._interactionType} = opts || {}; - let trigger = this.trigger(); + let trigger = this.getTrigger(); if (!trigger.getAttribute('aria-controls')) { await this.open(); } - let listbox = this.listbox(); + let listbox = this.getListbox(); if (!listbox) { throw new Error("Select's listbox not found."); } @@ -231,8 +231,8 @@ export class SelectTester { /** * Returns the select's options if present. Can be filtered to a subsection of the listbox if provided via `element`. */ - options(opts: {element?: HTMLElement} = {}): HTMLElement[] { - let {element = this.listbox()} = opts; + getOptions(opts: {element?: HTMLElement} = {}): HTMLElement[] { + let {element = this.getListbox()} = opts; let options = []; if (element) { options = within(element).queryAllByRole('option'); @@ -244,23 +244,23 @@ export class SelectTester { /** * Returns the select's trigger. */ - trigger(): HTMLElement { + getTrigger(): HTMLElement { return this._trigger; } /** * Returns the select's listbox if present. */ - listbox(): HTMLElement | null { - let listBoxId = this.trigger().getAttribute('aria-controls'); + getListbox(): HTMLElement | null { + let listBoxId = this.getTrigger().getAttribute('aria-controls'); return listBoxId ? document.getElementById(listBoxId) : null; } /** * Returns the select's sections if present. */ - sections(): HTMLElement[] { - let listbox = this.listbox(); + getSections(): HTMLElement[] { + let listbox = this.getListbox(); return listbox ? within(listbox).queryAllByRole('group') : []; } } diff --git a/packages/@react-aria/test-utils/src/table.ts b/packages/@react-aria/test-utils/src/table.ts index ac2b51e9fe7..2281fbb181d 100644 --- a/packages/@react-aria/test-utils/src/table.ts +++ b/packages/@react-aria/test-utils/src/table.ts @@ -78,7 +78,7 @@ export class TableTester { }) { let {row, selectionOnNav = 'default'} = opts; let altKey = getAltKey(); - let rows = this.rows(); + let rows = this.getRows(); let targetIndex = rows.indexOf(row); if (targetIndex === -1) { throw new Error('Row provided is not in the table'); @@ -93,7 +93,7 @@ export class TableTester { await this.user.keyboard('[ArrowDown]'); } - let rowGroups = this.rowGroups(); + let rowGroups = this.getRowGroups(); // If focus is currently somewhere in the first row group (aka on a column), we want to keyboard navigate downwards till we reach the rows if (rowGroups[0].contains(document.activeElement)) { do { @@ -202,9 +202,9 @@ export class TableTester { */ async toggleRowExpansion(opts: TableToggleExpansionOpts): Promise { let {row, interactionType = this._interactionType} = opts; - if (!this.table().contains(document.activeElement)) { + if (!this.getTable().contains(document.activeElement)) { await act(async () => { - this.table().focus(); + this.getTable().focus(); }); } @@ -246,9 +246,9 @@ export class TableTester { let columnheader; if (typeof column === 'number') { - columnheader = this.columns()[column]; + columnheader = this.getColumns()[column]; } else if (typeof column === 'string') { - columnheader = within(this.rowGroups()[0]).getByText(column); + columnheader = within(this.getRowGroups()[0]).getByText(column); while (columnheader && !/columnheader/.test(columnheader.getAttribute('role'))) { columnheader = columnheader.parentElement; } @@ -341,9 +341,9 @@ export class TableTester { let columnheader; if (typeof column === 'number') { - columnheader = this.columns()[column]; + columnheader = this.getColumns()[column]; } else if (typeof column === 'string') { - columnheader = within(this.rowGroups()[0]).getByText(column); + columnheader = within(this.getRowGroups()[0]).getByText(column); while (columnheader && !/columnheader/.test(columnheader.getAttribute('role'))) { columnheader = columnheader.parentElement; } @@ -456,13 +456,13 @@ export class TableTester { let {interactionType = this._interactionType} = opts; if (interactionType === 'keyboard') { let metaKey = getMetaKey(); - let table = this.table(); + let table = this.getTable(); if (document.activeElement !== table && !table.contains(document.activeElement)) { act(() => table.focus()); } await this.user.keyboard(`[${metaKey}>]a[/${metaKey}]`); } else { - let checkbox = within(this.table()).getByLabelText('Select All'); + let checkbox = within(this.getTable()).getByLabelText('Select All'); await pressElement(this.user, checkbox, interactionType); } } @@ -474,8 +474,8 @@ export class TableTester { let {indexOrText} = opts; let row; - let rows = this.rows(); - let bodyRowGroup = this.rowGroups()[1]; + let rows = this.getRows(); + let bodyRowGroup = this.getRowGroups()[1]; if (typeof indexOrText === 'number') { row = rows[indexOrText]; } else if (typeof indexOrText === 'string') { @@ -494,7 +494,7 @@ export class TableTester { findCell(opts: {text: string}): HTMLElement { let {text} = opts; - let cell = within(this.table()).getByText(text); + let cell = within(this.getTable()).getByText(text); if (cell) { while (cell && !/gridcell|rowheader|columnheader/.test(cell.getAttribute('role') || '')) { if (cell.parentElement) { @@ -511,14 +511,14 @@ export class TableTester { /** * Returns the table. */ - table(): HTMLElement { + getTable(): HTMLElement { return this._table; } /** * Returns the row groups within the table. */ - rowGroups(): HTMLElement[] { + getRowGroups(): HTMLElement[] { let table = this._table; return table ? within(table).queryAllByRole('rowgroup') : []; } @@ -526,16 +526,16 @@ export class TableTester { /** * Returns the columns within the table. */ - columns(): HTMLElement[] { - let headerRowGroup = this.rowGroups()[0]; + getColumns(): HTMLElement[] { + let headerRowGroup = this.getRowGroups()[0]; return headerRowGroup ? within(headerRowGroup).queryAllByRole('columnheader') : []; } /** * Returns the rows within the table if any. */ - rows(): HTMLElement[] { - return this.rowGroups() + getRows(): HTMLElement[] { + return this.getRowGroups() .slice(1) .flatMap(rowGroup => within(rowGroup).queryAllByRole('row')); } @@ -543,30 +543,30 @@ export class TableTester { /** * Returns the currently selected rows within the table if any. */ - selectedRows(): HTMLElement[] { - return this.rows().filter(row => row.getAttribute('aria-selected') === 'true'); + getSelectedRows(): HTMLElement[] { + return this.getRows().filter(row => row.getAttribute('aria-selected') === 'true'); } /** * Returns the footer rows within the table if any. */ - footerRows(): HTMLElement[] { - let footerRowGroup = this.rowGroups()[2]; + getFooterRows(): HTMLElement[] { + let footerRowGroup = this.getRowGroups()[2]; return footerRowGroup ? within(footerRowGroup).queryAllByRole('row') : []; } /** * Returns the row headers within the table if any. */ - rowHeaders(): HTMLElement[] { - return within(this.table()).queryAllByRole('rowheader'); + getRowHeaders(): HTMLElement[] { + return within(this.getTable()).queryAllByRole('rowheader'); } /** * Returns the cells within the table if any. Can be filtered against a specific row if provided via `element`. */ - cells(opts: {element?: HTMLElement} = {}): HTMLElement[] { - let {element = this.table()} = opts; + getCells(opts: {element?: HTMLElement} = {}): HTMLElement[] { + let {element = this.getTable()} = opts; return within(element).queryAllByRole('gridcell'); } } diff --git a/packages/@react-aria/test-utils/src/tabs.ts b/packages/@react-aria/test-utils/src/tabs.ts index 301f3756e4c..f47ac7d8ca3 100644 --- a/packages/@react-aria/test-utils/src/tabs.ts +++ b/packages/@react-aria/test-utils/src/tabs.ts @@ -63,7 +63,7 @@ export class TabsTester { let {indexOrText} = opts; let tab; - let tabs = this.tabs(); + let tabs = this.getTabs(); if (typeof indexOrText === 'number') { tab = tabs[indexOrText]; } else if (typeof indexOrText === 'string') { @@ -75,7 +75,7 @@ export class TabsTester { private async keyboardNavigateToTab(opts: {tab: HTMLElement; orientation?: Orientation}) { let {tab, orientation = 'vertical'} = opts; - let tabs = this.tabs(); + let tabs = this.getTabs(); tabs = tabs.filter( tab => !(tab.hasAttribute('disabled') || tab.getAttribute('aria-disabled') === 'true') ); @@ -91,7 +91,7 @@ export class TabsTester { } if (!this._tablist.contains(document.activeElement)) { - let selectedTab = this.selectedTab(); + let selectedTab = this.getSelectedTab(); if (selectedTab != null) { act(() => selectedTab.focus()); } else { @@ -159,16 +159,16 @@ export class TabsTester { /** * Returns the tablist. */ - tablist(): HTMLElement { + getTablist(): HTMLElement { return this._tablist; } /** * Returns the tabpanels. */ - tabpanels(): HTMLElement[] { + getTabpanels(): HTMLElement[] { let tabpanels = [] as HTMLElement[]; - for (let tab of this.tabs()) { + for (let tab of this.getTabs()) { let controlId = tab.getAttribute('aria-controls'); let panel = controlId != null ? document.getElementById(controlId) : null; if (panel != null) { @@ -182,22 +182,22 @@ export class TabsTester { /** * Returns the tabs in the tablist. */ - tabs(): HTMLElement[] { - return within(this.tablist()).queryAllByRole('tab'); + getTabs(): HTMLElement[] { + return within(this.getTablist()).queryAllByRole('tab'); } /** * Returns the currently selected tab in the tablist if any. */ - selectedTab(): HTMLElement | null { - return this.tabs().find(tab => tab.getAttribute('aria-selected') === 'true') || null; + getSelectedTab(): HTMLElement | null { + return this.getTabs().find(tab => tab.getAttribute('aria-selected') === 'true') || null; } /** * Returns the currently active tabpanel if any. */ - activeTabpanel(): HTMLElement | null { - let activeTabpanelId = this.selectedTab()?.getAttribute('aria-controls'); + getActiveTabpanel(): HTMLElement | null { + let activeTabpanelId = this.getSelectedTab()?.getAttribute('aria-controls'); return activeTabpanelId ? document.getElementById(activeTabpanelId) : null; } } diff --git a/packages/@react-aria/test-utils/src/tree.ts b/packages/@react-aria/test-utils/src/tree.ts index 045ac518c2a..fdf6cba2fe7 100644 --- a/packages/@react-aria/test-utils/src/tree.ts +++ b/packages/@react-aria/test-utils/src/tree.ts @@ -63,9 +63,9 @@ export class TreeTester { let row; if (typeof indexOrText === 'number') { - row = this.rows()[indexOrText]; + row = this.getRows()[indexOrText]; } else if (typeof indexOrText === 'string') { - row = within(this.tree()!).getByText(indexOrText).closest('[role=row]')! as HTMLElement; + row = within(this.getTree()!).getByText(indexOrText).closest('[role=row]')! as HTMLElement; } return row; @@ -77,7 +77,7 @@ export class TreeTester { }) { let {row, selectionOnNav = 'default'} = opts; let altKey = getAltKey(); - let rows = this.rows(); + let rows = this.getRows(); let targetIndex = rows.indexOf(row); if (targetIndex === -1) { throw new Error('Row provided is not in the tree'); @@ -88,7 +88,7 @@ export class TreeTester { } let focusPrevKey = this._direction === 'rtl' ? 'ArrowRight' : 'ArrowLeft'; - if (document.activeElement === this.tree()) { + if (document.activeElement === this.getTree()) { await this.user.keyboard( `${selectionOnNav === 'none' ? `[${altKey}>]` : ''}[ArrowDown]${selectionOnNav === 'none' ? `[/${altKey}]` : ''}` ); @@ -194,8 +194,8 @@ export class TreeTester { */ async toggleRowExpansion(opts: TreeToggleExpansionOpts): Promise { let {row, interactionType = this._interactionType} = opts; - if (!this.tree().contains(document.activeElement)) { - act(() => this.tree().focus()); + if (!this.getTree().contains(document.activeElement)) { + act(() => this.getTree().focus()); } if (typeof row === 'string' || typeof row === 'number') { @@ -258,29 +258,29 @@ export class TreeTester { /** * Returns the tree. */ - tree(): HTMLElement { + getTree(): HTMLElement { return this._tree; } /** * Returns the tree's rows if any. */ - rows(): HTMLElement[] { - return within(this.tree()).queryAllByRole('row'); + getRows(): HTMLElement[] { + return within(this.getTree()).queryAllByRole('row'); } /** * Returns the tree's selected rows if any. */ - selectedRows(): HTMLElement[] { - return this.rows().filter(row => row.getAttribute('aria-selected') === 'true'); + getSelectedRows(): HTMLElement[] { + return this.getRows().filter(row => row.getAttribute('aria-selected') === 'true'); } /** * Returns the tree's cells if any. Can be filtered against a specific row if provided via `element`. */ - cells(opts: {element?: HTMLElement} = {}): HTMLElement[] { - let {element = this.tree()} = opts; + getCells(opts: {element?: HTMLElement} = {}): HTMLElement[] { + let {element = this.getTree()} = opts; return within(element).queryAllByRole('gridcell'); } } diff --git a/packages/@react-spectrum/s2/test/CheckboxGroup.browser.test.tsx b/packages/@react-spectrum/s2/test/CheckboxGroup.browser.test.tsx index c31bb0882b9..c64d8dcfeb9 100644 --- a/packages/@react-spectrum/s2/test/CheckboxGroup.browser.test.tsx +++ b/packages/@react-spectrum/s2/test/CheckboxGroup.browser.test.tsx @@ -45,7 +45,7 @@ it.each` root: container.querySelector('[role=group]') as HTMLElement, interactionType }); - let checkboxes = tester.checkboxes(); + let checkboxes = tester.getCheckboxes(); await tester.toggleCheckbox({checkbox: checkboxes[2]}); - expect(tester.selectedCheckboxes()).toContain(checkboxes[2]); + expect(tester.getSelectedCheckboxes()).toContain(checkboxes[2]); }); diff --git a/packages/@react-spectrum/s2/test/CheckboxGroup.test.tsx b/packages/@react-spectrum/s2/test/CheckboxGroup.test.tsx index 2976b268d2c..6f3158174cd 100644 --- a/packages/@react-spectrum/s2/test/CheckboxGroup.test.tsx +++ b/packages/@react-spectrum/s2/test/CheckboxGroup.test.tsx @@ -84,29 +84,29 @@ describe('CheckboxGroup', () => { let checkboxGroupTester = testUtilUser.createTester('CheckboxGroup', { root: getByRole('group') }); - expect(checkboxGroupTester.checkboxgroup()).toHaveAttribute('role'); - let checkboxes = checkboxGroupTester.checkboxes(); + expect(checkboxGroupTester.getCheckboxGroup()).toHaveAttribute('role'); + let checkboxes = checkboxGroupTester.getCheckboxes(); await checkboxGroupTester.toggleCheckbox({checkbox: checkboxes[0]}); expect(checkboxes[0]).toBeChecked(); - expect(checkboxGroupTester.selectedCheckboxes()).toHaveLength(1); + expect(checkboxGroupTester.getSelectedCheckboxes()).toHaveLength(1); await checkboxGroupTester.toggleCheckbox({checkbox: 4, interactionType: 'keyboard'}); expect(checkboxes[4]).toBeChecked(); - expect(checkboxGroupTester.selectedCheckboxes()).toHaveLength(2); + expect(checkboxGroupTester.getSelectedCheckboxes()).toHaveLength(2); let checkbox4 = checkboxGroupTester.findCheckbox({indexOrText: 3}); await checkboxGroupTester.toggleCheckbox({checkbox: checkbox4, interactionType: 'keyboard'}); expect(checkboxes[3]).toBeChecked(); - expect(checkboxGroupTester.selectedCheckboxes()).toHaveLength(3); + expect(checkboxGroupTester.getSelectedCheckboxes()).toHaveLength(3); await checkboxGroupTester.toggleCheckbox({checkbox: 'Soccer', interactionType: 'keyboard'}); expect(checkboxes[0]).not.toBeChecked(); - expect(checkboxGroupTester.selectedCheckboxes()).toHaveLength(2); + expect(checkboxGroupTester.getSelectedCheckboxes()).toHaveLength(2); let checkbox5 = checkboxGroupTester.findCheckbox({indexOrText: 'Rugby'}); await checkboxGroupTester.toggleCheckbox({checkbox: checkbox5, interactionType: 'mouse'}); expect(checkboxes[4]).not.toBeChecked(); - expect(checkboxGroupTester.selectedCheckboxes()).toHaveLength(1); + expect(checkboxGroupTester.getSelectedCheckboxes()).toHaveLength(1); } ); }); diff --git a/packages/@react-spectrum/s2/test/Combobox.browser.test.tsx b/packages/@react-spectrum/s2/test/Combobox.browser.test.tsx index 4777219650d..c8e5c99201d 100644 --- a/packages/@react-spectrum/s2/test/Combobox.browser.test.tsx +++ b/packages/@react-spectrum/s2/test/Combobox.browser.test.tsx @@ -50,5 +50,5 @@ it.each` let tester = testUtilUser.createTester('ComboBox', {root: container, interactionType}); await tester.toggleOptionSelection({option: 2}); - expect(tester.combobox()).toHaveValue('Dog'); + expect(tester.getCombobox()).toHaveValue('Dog'); }); diff --git a/packages/@react-spectrum/s2/test/Combobox.test.tsx b/packages/@react-spectrum/s2/test/Combobox.test.tsx index 7eedc34c772..54affd53d4a 100644 --- a/packages/@react-spectrum/s2/test/Combobox.test.tsx +++ b/packages/@react-spectrum/s2/test/Combobox.test.tsx @@ -73,15 +73,15 @@ describe('Combobox', () => { let tree = render({[]}); let comboboxTester = testUtilUser.createTester('ComboBox', {root: tree.container}); - expect(comboboxTester.listbox()).toBeFalsy(); + expect(comboboxTester.getListbox()).toBeFalsy(); comboboxTester.setInteractionType('mouse'); await comboboxTester.open(); - let options = comboboxTester.options(); + let options = comboboxTester.getOptions(); expect(options).toHaveLength(1); - expect(comboboxTester.listbox()).toBeTruthy(); + expect(comboboxTester.getListbox()).toBeTruthy(); expect(options[0]).toHaveTextContent('No results'); - expect(within(comboboxTester.listbox()!).getByTestId('loadMoreSentinel')).toBeInTheDocument(); + expect(within(comboboxTester.getListbox()!).getByTestId('loadMoreSentinel')).toBeInTheDocument(); }); it('should only call loadMore whenever intersection is detected', async () => { @@ -102,7 +102,7 @@ describe('Combobox', () => { ); let comboboxTester = testUtilUser.createTester('ComboBox', {root: tree.container}); - expect(comboboxTester.listbox()).toBeFalsy(); + expect(comboboxTester.getListbox()).toBeFalsy(); comboboxTester.setInteractionType('mouse'); await comboboxTester.open(); @@ -158,7 +158,7 @@ describe('Combobox', () => { expect(announce).toHaveBeenLastCalledWith('5 options available.'); expect( - within(comboboxTester.listbox()!).getByRole('progressbar', {hidden: true}) + within(comboboxTester.getListbox()!).getByRole('progressbar', {hidden: true}) ).toBeInTheDocument(); await user.keyboard('C'); @@ -174,13 +174,13 @@ describe('Combobox', () => { interactionType: 'mouse' }); await comboboxTester.open(); - let options = comboboxTester.options(); + let options = comboboxTester.getOptions(); for (let [index, option] of options.entries()) { expect(option).toHaveAttribute('aria-posinset', `${index + 1}`); } tree.rerender(); - options = comboboxTester.options(); + options = comboboxTester.getOptions(); for (let [index, option] of options.entries()) { expect(option).toHaveAttribute('aria-posinset', `${index + 1}`); } @@ -194,7 +194,7 @@ describe('Combobox', () => { ]; tree.rerender(); - options = comboboxTester.options(); + options = comboboxTester.getOptions(); for (let [index, option] of options.entries()) { expect(option).toHaveAttribute('aria-posinset', `${index + 1}`); } @@ -229,7 +229,7 @@ describe('Combobox', () => { }); let buttons = tree.getAllByRole('button'); expect(buttons).toHaveLength(2); - expect(buttons[1]).toBe(comboboxTester.trigger()); + expect(buttons[1]).toBe(comboboxTester.getTrigger()); await user.click(buttons[0]); @@ -271,25 +271,25 @@ describe('Combobox', () => { interactionType: 'mouse' }); await dialogTester.open(); - expect(dialogTester.dialog()).toBeVisible(); + expect(dialogTester.getDialog()).toBeVisible(); act(() => { jest.runAllTimers(); }); let comboboxTester = testUtilUser.createTester('ComboBox', { - root: dialogTester.dialog()!, + root: dialogTester.getDialog()!, interactionType: 'mouse' }); await comboboxTester.open(); - expect(comboboxTester.listbox()).toBeVisible(); + expect(comboboxTester.getListbox()).toBeVisible(); act(() => { jest.runAllTimers(); }); let backdrop = document.querySelector('[style*="--visual-viewport-height"]'); await user.click(backdrop!); - await waitFor(() => expect(comboboxTester.listbox()).toBeNull()); + await waitFor(() => expect(comboboxTester.getListbox()).toBeNull()); await user.click(backdrop!); - expect(dialogTester.dialog()).toBeNull(); + expect(dialogTester.getDialog()).toBeNull(); }); }); diff --git a/packages/@react-spectrum/s2/test/EditableTableView.test.tsx b/packages/@react-spectrum/s2/test/EditableTableView.test.tsx index 806ff3096e4..3cd6a142b83 100644 --- a/packages/@react-spectrum/s2/test/EditableTableView.test.tsx +++ b/packages/@react-spectrum/s2/test/EditableTableView.test.tsx @@ -292,7 +292,7 @@ describe('TableView', () => { overlayType: 'modal' }); await dialogTester.open(); - let dialog = dialogTester.dialog(); + let dialog = dialogTester.getDialog(); expect(dialog).toBeVisible(); let input = within(dialog!).getByRole('textbox'); @@ -320,12 +320,12 @@ describe('TableView', () => { overlayType: 'modal' }); await dialogTester.open(); - dialog = dialogTester.dialog(); + dialog = dialogTester.getDialog(); // TODO: also weird that it is dialog.dialog? expect(dialog).toBeVisible(); let selectTester = testUtilUser.createTester('Select', {root: dialog!}); - expect(selectTester.trigger()).toHaveFocus(); + expect(selectTester.getTrigger()).toHaveFocus(); await selectTester.toggleOptionSelection({option: 'Steven'}); act(() => { jest.runAllTimers(); @@ -737,7 +737,7 @@ describe('TableView', () => { overlayType: 'modal' }); await dialogTester.open(); - let dialog = dialogTester.dialog(); + let dialog = dialogTester.getDialog(); expect(dialog).toBeVisible(); let input = within(dialog!).getByRole('textbox'); @@ -765,12 +765,12 @@ describe('TableView', () => { overlayType: 'modal' }); await dialogTester.open(); - dialog = dialogTester.dialog(); + dialog = dialogTester.getDialog(); // TODO: also weird that it is dialog.dialog? expect(dialog).toBeVisible(); let selectTester = testUtilUser.createTester('Select', {root: dialog!}); - expect(selectTester.trigger()).toHaveFocus(); + expect(selectTester.getTrigger()).toHaveFocus(); await selectTester.toggleOptionSelection({option: 'Steven'}); act(() => { jest.runAllTimers(); diff --git a/packages/@react-spectrum/s2/test/Picker.browser.test.tsx b/packages/@react-spectrum/s2/test/Picker.browser.test.tsx index fda4b5ba325..1ce29a20769 100644 --- a/packages/@react-spectrum/s2/test/Picker.browser.test.tsx +++ b/packages/@react-spectrum/s2/test/Picker.browser.test.tsx @@ -46,5 +46,5 @@ it.each` let tester = testUtilUser.createTester('Select', {root: container, interactionType}); await tester.toggleOptionSelection({option: 2}); - expect(tester.trigger()).toHaveTextContent('Dog'); + expect(tester.getTrigger()).toHaveTextContent('Dog'); }); diff --git a/packages/@react-spectrum/s2/test/Picker.test.tsx b/packages/@react-spectrum/s2/test/Picker.test.tsx index 995831acb95..e111ed0a90d 100644 --- a/packages/@react-spectrum/s2/test/Picker.test.tsx +++ b/packages/@react-spectrum/s2/test/Picker.test.tsx @@ -72,7 +72,7 @@ describe('Picker', () => { ); let selectTester = testUtilUser.createTester('Select', {root: tree.container}); - expect(selectTester.listbox()).toBeFalsy(); + expect(selectTester.getListbox()).toBeFalsy(); selectTester.setInteractionType('mouse'); await selectTester.open(); @@ -114,14 +114,14 @@ describe('Picker', () => { let selectTester = testUtilUser.createTester('Select', {root: tree.container}); await selectTester.open(); - let options = selectTester.options(); + let options = selectTester.getOptions(); for (let [index, option] of options.entries()) { expect(option).toHaveAttribute('aria-posinset', `${index + 1}`); expect(option).toHaveAttribute('aria-setsize', `${items.length}`); } tree.rerender(); - options = selectTester.options(); + options = selectTester.getOptions(); for (let [index, option] of options.entries()) { if (index === options.length - 1) { // The last row is the loader here which shouldn't have posinset @@ -136,7 +136,7 @@ describe('Picker', () => { let newItems = [...items, {name: 'Chocolate Mint'}, {name: 'Chocolate Chip Cookie Dough'}]; tree.rerender(); - options = selectTester.options(); + options = selectTester.getOptions(); for (let [index, option] of options.entries()) { expect(option).toHaveAttribute('aria-posinset', `${index + 1}`); expect(option).toHaveAttribute('aria-setsize', `${newItems.length}`); @@ -246,7 +246,7 @@ describe('Picker', () => { let selectTester = testUtilUser.createTester('Select', {root: tree.getByTestId('testpicker')}); let buttons = tree.getAllByRole('button'); expect(buttons).toHaveLength(2); - expect(buttons[1]).toBe(selectTester.trigger()); + expect(buttons[1]).toBe(selectTester.getTrigger()); await user.click(buttons[0]); diff --git a/packages/@react-spectrum/s2/test/RadioGroup.browser.test.tsx b/packages/@react-spectrum/s2/test/RadioGroup.browser.test.tsx index 8f0a5e88b89..8534e235a91 100644 --- a/packages/@react-spectrum/s2/test/RadioGroup.browser.test.tsx +++ b/packages/@react-spectrum/s2/test/RadioGroup.browser.test.tsx @@ -44,7 +44,7 @@ it.each` root: container.querySelector('[role=radiogroup]') as HTMLElement, interactionType }); - let radios = tester.radios(); + let radios = tester.getRadios(); await tester.triggerRadio({radio: radios[1]}); - expect(tester.selectedRadio()).toBe(radios[1]); + expect(tester.getSelectedRadio()).toBe(radios[1]); }); diff --git a/packages/@react-spectrum/s2/test/RadioGroup.test.tsx b/packages/@react-spectrum/s2/test/RadioGroup.test.tsx index 121e681ffd5..5f633df9748 100644 --- a/packages/@react-spectrum/s2/test/RadioGroup.test.tsx +++ b/packages/@react-spectrum/s2/test/RadioGroup.test.tsx @@ -54,8 +54,8 @@ describe('RadioGroup', () => { root: getByRole('radiogroup'), direction }); - expect(radioGroupTester.radiogroup()).toHaveAttribute('aria-orientation', props.orientation); - let radios = radioGroupTester.radios(); + expect(radioGroupTester.getRadioGroup()).toHaveAttribute('aria-orientation', props.orientation); + let radios = radioGroupTester.getRadios(); await radioGroupTester.triggerRadio({radio: radios[0]}); expect(radios[0]).toBeChecked(); @@ -79,9 +79,9 @@ describe('RadioGroup', () => { // instead of using ArrowLeft/ArrowRight await user.keyboard('[ArrowLeft]'); if (props.locale === 'ar-AE' && props.orientation === 'horizontal') { - expect(radioGroupTester.selectedRadio()).toBe(radios[0]); + expect(radioGroupTester.getSelectedRadio()).toBe(radios[0]); } else { - expect(radioGroupTester.selectedRadio()).toBe(radios[3]); + expect(radioGroupTester.getSelectedRadio()).toBe(radios[3]); } } ); diff --git a/packages/@react-spectrum/s2/test/SelectBoxGroup.test.tsx b/packages/@react-spectrum/s2/test/SelectBoxGroup.test.tsx index d43995a4cc5..c2a89f122fb 100644 --- a/packages/@react-spectrum/s2/test/SelectBoxGroup.test.tsx +++ b/packages/@react-spectrum/s2/test/SelectBoxGroup.test.tsx @@ -127,7 +127,7 @@ describe('SelectBoxGroup', () => { let listboxTester = testUtilUser.createTester('ListBox', {root: screen.getByRole('listbox')}); await listboxTester.toggleOptionSelection({option: 0}); - expect(listboxTester.options()[0]).toHaveAttribute('aria-selected', 'true'); + expect(listboxTester.getOptions()[0]).toHaveAttribute('aria-selected', 'true'); }); it('handles uncontrolled click selection in multiple mode', async () => { @@ -137,8 +137,8 @@ describe('SelectBoxGroup', () => { await listboxTester.toggleOptionSelection({option: 0}); await listboxTester.toggleOptionSelection({option: 1}); - expect(listboxTester.options()[0]).toHaveAttribute('aria-selected', 'true'); - expect(listboxTester.options()[1]).toHaveAttribute('aria-selected', 'true'); + expect(listboxTester.getOptions()[0]).toHaveAttribute('aria-selected', 'true'); + expect(listboxTester.getOptions()[1]).toHaveAttribute('aria-selected', 'true'); }); it('handles uncontrolled selection toggle', async () => { @@ -146,12 +146,12 @@ describe('SelectBoxGroup', () => { let listboxTester = testUtilUser.createTester('ListBox', {root: screen.getByRole('listbox')}); await listboxTester.toggleOptionSelection({option: 0}); - expect(listboxTester.options()[0]).toHaveAttribute('aria-selected', 'true'); + expect(listboxTester.getOptions()[0]).toHaveAttribute('aria-selected', 'true'); // Toggle off in single mode by selecting another await listboxTester.toggleOptionSelection({option: 1}); - expect(listboxTester.options()[0]).toHaveAttribute('aria-selected', 'false'); - expect(listboxTester.options()[1]).toHaveAttribute('aria-selected', 'true'); + expect(listboxTester.getOptions()[0]).toHaveAttribute('aria-selected', 'false'); + expect(listboxTester.getOptions()[1]).toHaveAttribute('aria-selected', 'true'); }); it('handles uncontrolled keyboard selection', async () => { @@ -173,7 +173,7 @@ describe('SelectBoxGroup', () => { let listboxTester = testUtilUser.createTester('ListBox', {root: screen.getByRole('listbox')}); await listboxTester.toggleOptionSelection({option: 0}); - expect(listboxTester.options()[0]).toHaveAttribute('aria-selected', 'true'); + expect(listboxTester.getOptions()[0]).toHaveAttribute('aria-selected', 'true'); }); it('handles controlled multiple selection', async () => { @@ -183,8 +183,8 @@ describe('SelectBoxGroup', () => { await listboxTester.toggleOptionSelection({option: 0}); await listboxTester.toggleOptionSelection({option: 1}); - expect(listboxTester.options()[0]).toHaveAttribute('aria-selected', 'true'); - expect(listboxTester.options()[1]).toHaveAttribute('aria-selected', 'true'); + expect(listboxTester.getOptions()[0]).toHaveAttribute('aria-selected', 'true'); + expect(listboxTester.getOptions()[1]).toHaveAttribute('aria-selected', 'true'); }); it('calls onSelectionChange when selection changes in controlled mode', async () => { diff --git a/packages/@react-spectrum/s2/test/TableView.browser.test.tsx b/packages/@react-spectrum/s2/test/TableView.browser.test.tsx index 444f010f400..cb64439d332 100644 --- a/packages/@react-spectrum/s2/test/TableView.browser.test.tsx +++ b/packages/@react-spectrum/s2/test/TableView.browser.test.tsx @@ -61,5 +61,5 @@ it.each` interactionType }); await tester.toggleRowSelection({row: 2}); - expect(tester.rows()[2].getAttribute('aria-selected')).toBe('true'); + expect(tester.getRows()[2].getAttribute('aria-selected')).toBe('true'); }); diff --git a/packages/@react-spectrum/s2/test/TableView.test.tsx b/packages/@react-spectrum/s2/test/TableView.test.tsx index 55c3a96b65d..c217b1648ea 100644 --- a/packages/@react-spectrum/s2/test/TableView.test.tsx +++ b/packages/@react-spectrum/s2/test/TableView.test.tsx @@ -271,16 +271,16 @@ describe('TableView', () => { let tableTester = testUtilUser.createTester('Table', {root}); - let groups = tableTester.rowGroups(); + let groups = tableTester.getRowGroups(); expect(groups).toHaveLength(3); await user.tab(); - for (let row of tableTester.rows()) { + for (let row of tableTester.getRows()) { expect(document.activeElement).toBe(row); await user.keyboard('{ArrowDown}'); } - for (let row of tableTester.rows().toReversed().slice(1)) { + for (let row of tableTester.getRows().toReversed().slice(1)) { await user.keyboard('{ArrowUp}'); expect(document.activeElement).toBe(row); } @@ -289,7 +289,7 @@ describe('TableView', () => { await user.click(footerRows[0]); expect(onSelectionChange).not.toHaveBeenCalled(); - await user.click(tableTester.rows()[0]); + await user.click(tableTester.getRows()[0]); expect(onSelectionChange).toHaveBeenCalled(); }); }); diff --git a/packages/dev/s2-docs/pages/react-aria/CheckboxGroup/testing.mdx b/packages/dev/s2-docs/pages/react-aria/CheckboxGroup/testing.mdx index c37a7a86775..175453e3c51 100644 --- a/packages/dev/s2-docs/pages/react-aria/CheckboxGroup/testing.mdx +++ b/packages/dev/s2-docs/pages/react-aria/CheckboxGroup/testing.mdx @@ -45,15 +45,15 @@ it('CheckboxGroup can select multiple checkboxes', async function () { ); let checkboxGroupTester = testUtilUser.createTester('CheckboxGroup', {root: getByTestId('test-checkboxgroup')}); - expect(checkboxGroupTester.selectedCheckboxes()).toHaveLength(0); + expect(checkboxGroupTester.getSelectedCheckboxes()).toHaveLength(0); await checkboxGroupTester.toggleCheckbox({checkbox: 0}); - expect(checkboxGroupTester.checkboxes()[0]).toBeChecked(); - expect(checkboxGroupTester.selectedCheckboxes()).toHaveLength(1); + expect(checkboxGroupTester.getCheckboxes()[0]).toBeChecked(); + expect(checkboxGroupTester.getSelectedCheckboxes()).toHaveLength(1); await checkboxGroupTester.toggleCheckbox({checkbox: 4}); - expect(checkboxGroupTester.checkboxes()[4]).toBeChecked(); - expect(checkboxGroupTester.selectedCheckboxes()).toHaveLength(2); + expect(checkboxGroupTester.getCheckboxes()[4]).toBeChecked(); + expect(checkboxGroupTester.getSelectedCheckboxes()).toHaveLength(2); }); ``` diff --git a/packages/dev/s2-docs/pages/react-aria/ComboBox/testing.mdx b/packages/dev/s2-docs/pages/react-aria/ComboBox/testing.mdx index 69ce7b771dd..a965e8d2d22 100644 --- a/packages/dev/s2-docs/pages/react-aria/ComboBox/testing.mdx +++ b/packages/dev/s2-docs/pages/react-aria/ComboBox/testing.mdx @@ -46,12 +46,12 @@ it('ComboBox can select an option via keyboard', async function () { let comboboxTester = testUtilUser.createTester('ComboBox', {root: getByTestId('test-combobox'), interactionType: 'keyboard'}); await comboboxTester.open(); - expect(comboboxTester.listbox()).toBeInTheDocument(); + expect(comboboxTester.getListbox()).toBeInTheDocument(); - let options = comboboxTester.options(); + let options = comboboxTester.getOptions(); await comboboxTester.toggleOptionSelection({option: options[0]}); - expect(comboboxTester.combobox().value).toBe('One'); - expect(comboboxTester.listbox()).not.toBeInTheDocument(); + expect(comboboxTester.getCombobox().value).toBe('One'); + expect(comboboxTester.getListbox()).not.toBeInTheDocument(); }); ``` diff --git a/packages/dev/s2-docs/pages/react-aria/GridList/testing.mdx b/packages/dev/s2-docs/pages/react-aria/GridList/testing.mdx index eb52db3db08..946809f2d97 100644 --- a/packages/dev/s2-docs/pages/react-aria/GridList/testing.mdx +++ b/packages/dev/s2-docs/pages/react-aria/GridList/testing.mdx @@ -52,17 +52,17 @@ it('GridList can select a row via keyboard', async function () { ); let gridListTester = testUtilUser.createTester('GridList', {root: getByTestId('test-gridlist'), interactionType: 'keyboard'}); - let row = gridListTester.rows()[0]; + let row = gridListTester.getRows()[0]; expect(within(row).getByRole('checkbox')).not.toBeChecked(); - expect(gridListTester.selectedRows()).toHaveLength(0); + expect(gridListTester.getSelectedRows()).toHaveLength(0); await gridListTester.toggleRowSelection({row: 0}); expect(within(row).getByRole('checkbox')).toBeChecked(); - expect(gridListTester.selectedRows()).toHaveLength(1); + expect(gridListTester.getSelectedRows()).toHaveLength(1); await gridListTester.toggleRowSelection({row: 0}); expect(within(row).getByRole('checkbox')).not.toBeChecked(); - expect(gridListTester.selectedRows()).toHaveLength(0); + expect(gridListTester.getSelectedRows()).toHaveLength(0); }); ``` diff --git a/packages/dev/s2-docs/pages/react-aria/ListBox/testing.mdx b/packages/dev/s2-docs/pages/react-aria/ListBox/testing.mdx index 175da6f0d2b..b3ebdcce962 100644 --- a/packages/dev/s2-docs/pages/react-aria/ListBox/testing.mdx +++ b/packages/dev/s2-docs/pages/react-aria/ListBox/testing.mdx @@ -53,7 +53,7 @@ it('ListBox can select an option via keyboard', async function () { let listboxTester = testUtilUser.createTester('ListBox', {root: getByTestId('test-listbox'), interactionType: 'keyboard'}); await listboxTester.toggleOptionSelection({option: 4}); - expect(listboxTester.options()[4]).toHaveAttribute('aria-selected', 'true'); + expect(listboxTester.getOptions()[4]).toHaveAttribute('aria-selected', 'true'); }); ``` diff --git a/packages/dev/s2-docs/pages/react-aria/Menu/testing.mdx b/packages/dev/s2-docs/pages/react-aria/Menu/testing.mdx index d8c7808ce2c..fe0db81924e 100644 --- a/packages/dev/s2-docs/pages/react-aria/Menu/testing.mdx +++ b/packages/dev/s2-docs/pages/react-aria/Menu/testing.mdx @@ -54,16 +54,16 @@ it('Menu can open its submenu via keyboard', async function () { let menuTester = testUtilUser.createTester('Menu', {root: getByTestId('test-menutrigger'), interactionType: 'keyboard'}); await menuTester.open(); - expect(menuTester.menu()).toBeInTheDocument(); - let submenuTriggers = menuTester.submenuTriggers(); + expect(menuTester.getMenu()).toBeInTheDocument(); + let submenuTriggers = menuTester.getSubmenuTriggers(); expect(submenuTriggers).toHaveLength(1); let submenuTester = await menuTester.openSubmenu({submenuTrigger: 'Share…'}); - expect(submenuTester.menu()).toBeInTheDocument(); + expect(submenuTester.getMenu()).toBeInTheDocument(); - await submenuTester.toggleOptionSelection({option: submenuTester.options()[0]}); - expect(submenuTester.menu()).not.toBeInTheDocument(); - expect(menuTester.menu()).not.toBeInTheDocument(); + await submenuTester.toggleOptionSelection({option: submenuTester.getOptions()[0]}); + expect(submenuTester.getMenu()).not.toBeInTheDocument(); + expect(menuTester.getMenu()).not.toBeInTheDocument(); }); ``` diff --git a/packages/dev/s2-docs/pages/react-aria/Modal/testing.mdx b/packages/dev/s2-docs/pages/react-aria/Modal/testing.mdx index ab0ed857995..895d46b6eb3 100644 --- a/packages/dev/s2-docs/pages/react-aria/Modal/testing.mdx +++ b/packages/dev/s2-docs/pages/react-aria/Modal/testing.mdx @@ -52,7 +52,7 @@ it('Modal can be opened and closed', async function () { let dialogTester = testUtilUser.createTester('Dialog', {root: button, overlayType: 'modal'}); await dialogTester.open(); - let dialog = dialogTester.dialog(); + let dialog = dialogTester.getDialog(); expect(dialog).toBeVisible(); await dialogTester.close(); diff --git a/packages/dev/s2-docs/pages/react-aria/Popover/testing.mdx b/packages/dev/s2-docs/pages/react-aria/Popover/testing.mdx index 07c5c9ccdb0..d44d20b4d0c 100644 --- a/packages/dev/s2-docs/pages/react-aria/Popover/testing.mdx +++ b/packages/dev/s2-docs/pages/react-aria/Popover/testing.mdx @@ -52,7 +52,7 @@ it('Popover can be opened and closed', async function () { let dialogTester = testUtilUser.createTester('Dialog', {root: button, overlayType: 'popover'}); await dialogTester.open(); - let dialog = dialogTester.dialog(); + let dialog = dialogTester.getDialog(); expect(dialog).toBeVisible(); await dialogTester.close(); diff --git a/packages/dev/s2-docs/pages/react-aria/RadioGroup/testing.mdx b/packages/dev/s2-docs/pages/react-aria/RadioGroup/testing.mdx index 9a24afffb5d..59b50fe4e2e 100644 --- a/packages/dev/s2-docs/pages/react-aria/RadioGroup/testing.mdx +++ b/packages/dev/s2-docs/pages/react-aria/RadioGroup/testing.mdx @@ -46,14 +46,14 @@ it('RadioGroup can switch the selected radio', async function () { ); let radioGroupTester = testUtilUser.createTester('RadioGroup', {root: getByRole('radiogroup')}); - let radios = radioGroupTester.radios(); - expect(radioGroupTester.selectedRadio()).toBeFalsy(); + let radios = radioGroupTester.getRadios(); + expect(radioGroupTester.getSelectedRadio()).toBeFalsy(); await radioGroupTester.triggerRadio({radio: radios[0]}); - expect(radioGroupTester.selectedRadio()).toBe(radios[0]); + expect(radioGroupTester.getSelectedRadio()).toBe(radios[0]); await radioGroupTester.triggerRadio({radio: radios[1]}); - expect(radioGroupTester.selectedRadio()).toBe(radios[1]); + expect(radioGroupTester.getSelectedRadio()).toBe(radios[1]); }); ``` diff --git a/packages/dev/s2-docs/pages/react-aria/Select/testing.mdx b/packages/dev/s2-docs/pages/react-aria/Select/testing.mdx index 22c3dd8d13a..35ce936504f 100644 --- a/packages/dev/s2-docs/pages/react-aria/Select/testing.mdx +++ b/packages/dev/s2-docs/pages/react-aria/Select/testing.mdx @@ -44,7 +44,7 @@ it('Select can select an option via keyboard', async function () { ); let selectTester = testUtilUser.createTester('Select', {root: getByTestId('test-select'), interactionType: 'keyboard'}); - let trigger = selectTester.trigger(); + let trigger = selectTester.getTrigger(); expect(trigger).toHaveTextContent('Select an item'); await selectTester.toggleOptionSelection({option: 'Cat'}); diff --git a/packages/dev/s2-docs/pages/react-aria/Table/testing.mdx b/packages/dev/s2-docs/pages/react-aria/Table/testing.mdx index 27134d2a2dc..14fd3601a63 100644 --- a/packages/dev/s2-docs/pages/react-aria/Table/testing.mdx +++ b/packages/dev/s2-docs/pages/react-aria/Table/testing.mdx @@ -52,22 +52,22 @@ it('Table can toggle row selection', async function () { ); let tableTester = testUtilUser.createTester('Table', {root: getByTestId('test-table')}); - expect(tableTester.selectedRows()).toHaveLength(0); + expect(tableTester.getSelectedRows()).toHaveLength(0); await tableTester.toggleSelectAll(); - expect(tableTester.selectedRows()).toHaveLength(10); + expect(tableTester.getSelectedRows()).toHaveLength(10); await tableTester.toggleRowSelection({row: 2}); - expect(tableTester.selectedRows()).toHaveLength(9); - let checkbox = within(tableTester.rows()[2]).getByRole('checkbox'); + expect(tableTester.getSelectedRows()).toHaveLength(9); + let checkbox = within(tableTester.getRows()[2]).getByRole('checkbox'); expect(checkbox).not.toBeChecked(); await tableTester.toggleSelectAll(); - expect(tableTester.selectedRows()).toHaveLength(10); + expect(tableTester.getSelectedRows()).toHaveLength(10); expect(checkbox).toBeChecked(); await tableTester.toggleSelectAll(); - expect(tableTester.selectedRows()).toHaveLength(0); + expect(tableTester.getSelectedRows()).toHaveLength(0); }); ``` diff --git a/packages/dev/s2-docs/pages/react-aria/Tabs/testing.mdx b/packages/dev/s2-docs/pages/react-aria/Tabs/testing.mdx index 4e42e640982..1c151a49ddc 100644 --- a/packages/dev/s2-docs/pages/react-aria/Tabs/testing.mdx +++ b/packages/dev/s2-docs/pages/react-aria/Tabs/testing.mdx @@ -45,11 +45,11 @@ it('Tabs can change selection via keyboard', async function () { ); let tabsTester = testUtilUser.createTester('Tabs', {root: getByTestId('test-tabs'), interactionType: 'keyboard'}); - let tabs = tabsTester.tabs(); - expect(tabsTester.selectedTab()).toBe(tabs[0]); + let tabs = tabsTester.getTabs(); + expect(tabsTester.getSelectedTab()).toBe(tabs[0]); await tabsTester.triggerTab({tab: 1}); - expect(tabsTester.selectedTab()).toBe(tabs[1]); + expect(tabsTester.getSelectedTab()).toBe(tabs[1]); }); ``` diff --git a/packages/dev/s2-docs/pages/react-aria/Tree/testing.mdx b/packages/dev/s2-docs/pages/react-aria/Tree/testing.mdx index fe522e43e08..9206b279d40 100644 --- a/packages/dev/s2-docs/pages/react-aria/Tree/testing.mdx +++ b/packages/dev/s2-docs/pages/react-aria/Tree/testing.mdx @@ -53,19 +53,19 @@ it('Tree can select and expand an item via keyboard', async function () { let treeTester = testUtilUser.createTester('Tree', {root: getByTestId('test-tree'), interactionType: 'keyboard'}); await treeTester.toggleRowSelection({row: 0}); - expect(treeTester.selectedRows()).toHaveLength(1); - expect(within(treeTester.rows()[0]).getByRole('checkbox')).toBeChecked(); + expect(treeTester.getSelectedRows()).toHaveLength(1); + expect(within(treeTester.getRows()[0]).getByRole('checkbox')).toBeChecked(); await treeTester.toggleRowSelection({row: 1}); - expect(treeTester.selectedRows()).toHaveLength(2); - expect(within(treeTester.rows()[1]).getByRole('checkbox')).toBeChecked(); + expect(treeTester.getSelectedRows()).toHaveLength(2); + expect(within(treeTester.getRows()[1]).getByRole('checkbox')).toBeChecked(); await treeTester.toggleRowSelection({row: 0}); - expect(treeTester.selectedRows()).toHaveLength(1); - expect(within(treeTester.rows()[0]).getByRole('checkbox')).not.toBeChecked(); + expect(treeTester.getSelectedRows()).toHaveLength(1); + expect(within(treeTester.getRows()[0]).getByRole('checkbox')).not.toBeChecked(); await treeTester.toggleRowExpansion({index: 0}); - expect(treeTester.rows()[0]).toHaveAttribute('aria-expanded', 'true'); + expect(treeTester.getRows()[0]).toHaveAttribute('aria-expanded', 'true'); }); ``` diff --git a/packages/dev/s2-docs/pages/s2/CheckboxGroup/testing.mdx b/packages/dev/s2-docs/pages/s2/CheckboxGroup/testing.mdx index f51c8ff79ce..481152081df 100644 --- a/packages/dev/s2-docs/pages/s2/CheckboxGroup/testing.mdx +++ b/packages/dev/s2-docs/pages/s2/CheckboxGroup/testing.mdx @@ -45,15 +45,15 @@ it('CheckboxGroup can select multiple checkboxes', async function () { ); let checkboxGroupTester = testUtilUser.createTester('CheckboxGroup', {root: getByTestId('test-checkboxgroup')}); - expect(checkboxGroupTester.selectedCheckboxes()).toHaveLength(0); + expect(checkboxGroupTester.getSelectedCheckboxes()).toHaveLength(0); await checkboxGroupTester.toggleCheckbox({checkbox: 0}); - expect(checkboxGroupTester.checkboxes()[0]).toBeChecked(); - expect(checkboxGroupTester.selectedCheckboxes()).toHaveLength(1); + expect(checkboxGroupTester.getCheckboxes()[0]).toBeChecked(); + expect(checkboxGroupTester.getSelectedCheckboxes()).toHaveLength(1); await checkboxGroupTester.toggleCheckbox({checkbox: 4}); - expect(checkboxGroupTester.checkboxes()[4]).toBeChecked(); - expect(checkboxGroupTester.selectedCheckboxes()).toHaveLength(2); + expect(checkboxGroupTester.getCheckboxes()[4]).toBeChecked(); + expect(checkboxGroupTester.getSelectedCheckboxes()).toHaveLength(2); }); ``` diff --git a/packages/dev/s2-docs/pages/s2/ComboBox/testing.mdx b/packages/dev/s2-docs/pages/s2/ComboBox/testing.mdx index 169ac21bb31..3826774b821 100644 --- a/packages/dev/s2-docs/pages/s2/ComboBox/testing.mdx +++ b/packages/dev/s2-docs/pages/s2/ComboBox/testing.mdx @@ -46,12 +46,12 @@ it('ComboBox can select an option via keyboard', async function () { let comboboxTester = testUtilUser.createTester('ComboBox', {root: getByTestId('test-combobox'), interactionType: 'keyboard'}); await comboboxTester.open(); - expect(comboboxTester.listbox()).toBeInTheDocument(); + expect(comboboxTester.getListbox()).toBeInTheDocument(); - let options = comboboxTester.options(); + let options = comboboxTester.getOptions(); await comboboxTester.toggleOptionSelection({option: options[0]}); - expect(comboboxTester.combobox().value).toBe('One'); - expect(comboboxTester.listbox()).not.toBeInTheDocument(); + expect(comboboxTester.getCombobox().value).toBe('One'); + expect(comboboxTester.getListbox()).not.toBeInTheDocument(); }); ``` diff --git a/packages/dev/s2-docs/pages/s2/Dialog/testing.mdx b/packages/dev/s2-docs/pages/s2/Dialog/testing.mdx index 0937be15176..a6c1852c2e2 100644 --- a/packages/dev/s2-docs/pages/s2/Dialog/testing.mdx +++ b/packages/dev/s2-docs/pages/s2/Dialog/testing.mdx @@ -50,7 +50,7 @@ it('Dialog can be opened and closed', async function () { let button = getByRole('button'); let dialogTester = testUtilUser.createTester('Dialog', {root: button, overlayType: 'modal'}); await dialogTester.open(); - let dialog = dialogTester.dialog(); + let dialog = dialogTester.getDialog(); expect(dialog).toBeVisible(); await dialogTester.close(); expect(dialog).not.toBeInTheDocument(); diff --git a/packages/dev/s2-docs/pages/s2/ListView/testing.mdx b/packages/dev/s2-docs/pages/s2/ListView/testing.mdx index bd17ca71bc7..2b9bd52f38f 100644 --- a/packages/dev/s2-docs/pages/s2/ListView/testing.mdx +++ b/packages/dev/s2-docs/pages/s2/ListView/testing.mdx @@ -52,17 +52,17 @@ it('ListView can toggle row selection', async function () { ); let gridListTester = testUtilUser.createTester('GridList', {root: getByTestId('test-listview'), interactionType: 'keyboard'}); - let row = gridListTester.rows()[0]; + let row = gridListTester.getRows()[0]; expect(within(row).getByRole('checkbox')).not.toBeChecked(); - expect(gridListTester.selectedRows()).toHaveLength(0); + expect(gridListTester.getSelectedRows()).toHaveLength(0); await gridListTester.toggleRowSelection({row: 0}); expect(within(row).getByRole('checkbox')).toBeChecked(); - expect(gridListTester.selectedRows()).toHaveLength(1); + expect(gridListTester.getSelectedRows()).toHaveLength(1); await gridListTester.toggleRowSelection({row: 0}); expect(within(row).getByRole('checkbox')).not.toBeChecked(); - expect(gridListTester.selectedRows()).toHaveLength(0); + expect(gridListTester.getSelectedRows()).toHaveLength(0); }); ``` diff --git a/packages/dev/s2-docs/pages/s2/Menu/testing.mdx b/packages/dev/s2-docs/pages/s2/Menu/testing.mdx index 267565de0dd..489352c5952 100644 --- a/packages/dev/s2-docs/pages/s2/Menu/testing.mdx +++ b/packages/dev/s2-docs/pages/s2/Menu/testing.mdx @@ -54,16 +54,16 @@ it('Menu can open its submenu via keyboard', async function () { let menuTester = testUtilUser.createTester('Menu', {root: getByTestId('test-menutrigger'), interactionType: 'keyboard'}); await menuTester.open(); - expect(menuTester.menu()).toBeInTheDocument(); - let submenuTriggers = menuTester.submenuTriggers(); + expect(menuTester.getMenu()).toBeInTheDocument(); + let submenuTriggers = menuTester.getSubmenuTriggers(); expect(submenuTriggers).toHaveLength(1); let submenuTester = await menuTester.openSubmenu({submenuTrigger: 'Share…'}); - expect(submenuTester.menu()).toBeInTheDocument(); + expect(submenuTester.getMenu()).toBeInTheDocument(); - await submenuTester.toggleOptionSelection({option: submenuTester.options()[0]}); - expect(submenuTester.menu()).not.toBeInTheDocument(); - expect(menuTester.menu()).not.toBeInTheDocument(); + await submenuTester.toggleOptionSelection({option: submenuTester.getOptions()[0]}); + expect(submenuTester.getMenu()).not.toBeInTheDocument(); + expect(menuTester.getMenu()).not.toBeInTheDocument(); }); ``` diff --git a/packages/dev/s2-docs/pages/s2/Picker/testing.mdx b/packages/dev/s2-docs/pages/s2/Picker/testing.mdx index 3724fd49e3f..9cca881136a 100644 --- a/packages/dev/s2-docs/pages/s2/Picker/testing.mdx +++ b/packages/dev/s2-docs/pages/s2/Picker/testing.mdx @@ -44,7 +44,7 @@ it('Picker can select an option via keyboard', async function () { ); let selectTester = testUtilUser.createTester('Select', {root: getByTestId('test-select'), interactionType: 'keyboard'}); - let trigger = selectTester.trigger(); + let trigger = selectTester.getTrigger(); expect(trigger).toHaveTextContent('Select an item'); await selectTester.toggleOptionSelection({option: 'Cat'}); diff --git a/packages/dev/s2-docs/pages/s2/RadioGroup/testing.mdx b/packages/dev/s2-docs/pages/s2/RadioGroup/testing.mdx index 9967cd8b74f..4b962514204 100644 --- a/packages/dev/s2-docs/pages/s2/RadioGroup/testing.mdx +++ b/packages/dev/s2-docs/pages/s2/RadioGroup/testing.mdx @@ -46,14 +46,14 @@ it('RadioGroup can switch the selected radio', async function () { ); let radioGroupTester = testUtilUser.createTester('RadioGroup', {root: getByRole('radiogroup')}); - let radios = radioGroupTester.radios(); - expect(radioGroupTester.selectedRadio()).toBeFalsy(); + let radios = radioGroupTester.getRadios(); + expect(radioGroupTester.getSelectedRadio()).toBeFalsy(); await radioGroupTester.triggerRadio({radio: radios[0]}); - expect(radioGroupTester.selectedRadio()).toBe(radios[0]); + expect(radioGroupTester.getSelectedRadio()).toBe(radios[0]); await radioGroupTester.triggerRadio({radio: radios[1]}); - expect(radioGroupTester.selectedRadio()).toBe(radios[1]); + expect(radioGroupTester.getSelectedRadio()).toBe(radios[1]); }); ``` diff --git a/packages/dev/s2-docs/pages/s2/TableView/testing.mdx b/packages/dev/s2-docs/pages/s2/TableView/testing.mdx index 069779e7c8c..38b7aa1a84f 100644 --- a/packages/dev/s2-docs/pages/s2/TableView/testing.mdx +++ b/packages/dev/s2-docs/pages/s2/TableView/testing.mdx @@ -52,22 +52,22 @@ it('TableView can toggle row selection', async function () { ); let tableTester = testUtilUser.createTester('Table', {root: getByTestId('test-table')}); - expect(tableTester.selectedRows()).toHaveLength(0); + expect(tableTester.getSelectedRows()).toHaveLength(0); await tableTester.toggleSelectAll(); - expect(tableTester.selectedRows()).toHaveLength(10); + expect(tableTester.getSelectedRows()).toHaveLength(10); await tableTester.toggleRowSelection({row: 2}); - expect(tableTester.selectedRows()).toHaveLength(9); - let checkbox = within(tableTester.rows()[2]).getByRole('checkbox'); + expect(tableTester.getSelectedRows()).toHaveLength(9); + let checkbox = within(tableTester.getRows()[2]).getByRole('checkbox'); expect(checkbox).not.toBeChecked(); await tableTester.toggleSelectAll(); - expect(tableTester.selectedRows()).toHaveLength(10); + expect(tableTester.getSelectedRows()).toHaveLength(10); expect(checkbox).toBeChecked(); await tableTester.toggleSelectAll(); - expect(tableTester.selectedRows()).toHaveLength(0); + expect(tableTester.getSelectedRows()).toHaveLength(0); }); ``` diff --git a/packages/dev/s2-docs/pages/s2/Tabs/testing.mdx b/packages/dev/s2-docs/pages/s2/Tabs/testing.mdx index 5a866e7c206..4590c50ad11 100644 --- a/packages/dev/s2-docs/pages/s2/Tabs/testing.mdx +++ b/packages/dev/s2-docs/pages/s2/Tabs/testing.mdx @@ -45,11 +45,11 @@ it('Tabs can change selection via keyboard', async function () { ); let tabsTester = testUtilUser.createTester('Tabs', {root: getByTestId('test-tabs'), interactionType: 'keyboard'}); - let tabs = tabsTester.tabs(); - expect(tabsTester.selectedTab()).toBe(tabs[0]); + let tabs = tabsTester.getTabs(); + expect(tabsTester.getSelectedTab()).toBe(tabs[0]); await tabsTester.triggerTab({tab: 1}); - expect(tabsTester.selectedTab()).toBe(tabs[1]); + expect(tabsTester.getSelectedTab()).toBe(tabs[1]); }); ``` diff --git a/packages/dev/s2-docs/pages/s2/TreeView/testing.mdx b/packages/dev/s2-docs/pages/s2/TreeView/testing.mdx index ac999c52d94..2ab1fbf725f 100644 --- a/packages/dev/s2-docs/pages/s2/TreeView/testing.mdx +++ b/packages/dev/s2-docs/pages/s2/TreeView/testing.mdx @@ -53,19 +53,19 @@ it('TreeView can select an item via keyboard', async function () { let treeTester = testUtilUser.createTester('Tree', {root: getByTestId('test-tree'), interactionType: 'keyboard'}); await treeTester.toggleRowSelection({row: 0}); - expect(treeTester.selectedRows()).toHaveLength(1); - expect(within(treeTester.rows()[0]).getByRole('checkbox')).toBeChecked(); + expect(treeTester.getSelectedRows()).toHaveLength(1); + expect(within(treeTester.getRows()[0]).getByRole('checkbox')).toBeChecked(); await treeTester.toggleRowSelection({row: 1}); - expect(treeTester.selectedRows()).toHaveLength(2); - expect(within(treeTester.rows()[1]).getByRole('checkbox')).toBeChecked(); + expect(treeTester.getSelectedRows()).toHaveLength(2); + expect(within(treeTester.getRows()[1]).getByRole('checkbox')).toBeChecked(); await treeTester.toggleRowSelection({row: 0}); - expect(treeTester.selectedRows()).toHaveLength(1); - expect(within(treeTester.rows()[0]).getByRole('checkbox')).not.toBeChecked(); + expect(treeTester.getSelectedRows()).toHaveLength(1); + expect(within(treeTester.getRows()[0]).getByRole('checkbox')).not.toBeChecked(); await treeTester.toggleRowExpansion({index: 0}); - expect(treeTester.rows()[0]).toHaveAttribute('aria-expanded', 'true'); + expect(treeTester.getRows()[0]).toHaveAttribute('aria-expanded', 'true'); }); ``` diff --git a/packages/dev/s2-docs/skills/react-aria/test-utils-guidance.md b/packages/dev/s2-docs/skills/react-aria/test-utils-guidance.md index 37cc79b8484..db6575b713b 100644 --- a/packages/dev/s2-docs/skills/react-aria/test-utils-guidance.md +++ b/packages/dev/s2-docs/skills/react-aria/test-utils-guidance.md @@ -30,10 +30,10 @@ it('my test case', async function () { let {getByTestId} = render(); // Initialize the table tester via providing the 'Table' pattern name and the root element of said table let tableTester = testUtilUser.createTester('Table', {root: getByTestId('test_table')}); - expect(tableTester.selectedRows()).toHaveLength(0); + expect(tableTester.getSelectedRows()).toHaveLength(0); await tableTester.toggleSelectAll(); - expect(tableTester.selectedRows()).toHaveLength(10); + expect(tableTester.getSelectedRows()).toHaveLength(10); ... }); ``` @@ -55,7 +55,7 @@ use the tester to query for the component's state or trigger a different interac - Mouse drag interactions, simulated scrolling, and other mock reliant interactions are not available in these test utils since they depend heavily on how the user mocks things like clientHeight/Width/etc in their tests. These interactions need to be simulated manually by the user. - Some testers may support the notion of "long press" for certain interactions (e.g. long pressing a button to trigger its menu). To simulate this, you will need mock PointerEvent globally (see the installPointerEvent util) and provide a way to advance timers to the User via `advanceTimer`. - These test utils are compatible with not only JSDOM unit tests but browser tests as well (e.g. vitest-browser-react). -- Methods that accept a target (`option`, `row`, `column`, `checkbox`, `radio`, `tab`) take a `number` (index), `string` (text content), or `HTMLElement`. Use the tester's own query methods (e.g. `rows()`, `options()`) to obtain an `HTMLElement` when you need one. +- Methods that accept a target (`option`, `row`, `column`, `checkbox`, `radio`, `tab`) take a `number` (index), `string` (text content), or `HTMLElement`. Use the tester's own query methods (e.g. `getRows()`, `getOptions()`) to obtain an `HTMLElement` when you need one. - Link navigation assertions must be simulated manually. The testers do not assert navigation side effects. ### When not to use the testers @@ -66,7 +66,7 @@ Skip the testers and write manual interactions for the following cases: - tests that verify exact focus order, arrow key cycling, or specific modifier key behavior. Use `fireEvent.keyDown` or `userEvent.keyboard` directly so the test is actually testing the desired keyboard flow. - when `isOpen` or `defaultOpen` is set, `open()` will no-op but the tester's `root` must still resolve to the trigger element. Use `getByLabelText` or `getByTestId` rather than `getByRole('button')` to avoid ambiguity when multiple buttons are in the DOM. - testing `isDismissible`, `isKeyboardDismissDisabled`, or outside-click behavior. Use `userEvent.click(document.body)` or `user.keyboard('[Escape]')` directly and assert the expected state afterwards. -- when a Dialog closes via an action button (not the explicit close/dismiss button) you should instead click that button manually, then use `dialogTester.dialog()` to assert whether the dialog is still present. +- when a Dialog closes via an action button (not the explicit close/dismiss button) you should instead click that button manually, then use `dialogTester.getDialog()` to assert whether the dialog is still present. ### Draggable handle components @@ -87,17 +87,17 @@ beforeAll(() => { | Pattern name | Component | Key methods | |---|---|---| -| `'CheckboxGroup'` | CheckboxGroup | `checkboxGroup()`, `checkboxes()`, `selectedCheckboxes()`, `toggleCheckbox({checkbox})` | -| `'ComboBox'` | ComboBox | `combobox()`, `listbox()`, `options()`, `open()`, `toggleOptionSelection({option})` | -| `'Dialog'` | Modal, Popover | `trigger()`, `dialog()`, `open()`, `close()` — pass `overlayType: 'modal'` or `'popover'` to `createTester` | -| `'GridList'` | GridList | `gridlist()`, `rows()`, `selectedRows()`, `toggleRowSelection({row})`, `triggerRowAction({row})` | -| `'ListBox'` | ListBox | `listbox()`, `options()`, `selectedOptions()`, `toggleOptionSelection({option})`, `triggerOptionAction({option})` | -| `'Menu'` | Menu | `trigger()`, `menu()`, `options()`, `open()`, `toggleOptionSelection({option})`, `openSubmenu({submenuTrigger})`, `close()` | -| `'RadioGroup'` | RadioGroup | `radiogroup()`, `radios()`, `selectedRadio()`, `triggerRadio({radio})` | -| `'Select'` | Select | `trigger()`, `listbox()`, `options()`, `toggleOptionSelection({option})` | -| `'Table'` | Table | `table()`, `rows()`, `footerRows()`, `columns()`, `selectedRows()`, `toggleRowSelection({row})`, `toggleSort({column})`, `triggerRowAction({row})` | -| `'Tabs'` | Tabs | `tablist()`, `tabs()`, `tabpanels()`, `selectedTab()`, `triggerTab({tab})` | -| `'Tree'` | Tree | `tree()`, `rows()`, `selectedRows()`, `toggleRowSelection({row})`, `toggleRowExpansion({row})`, `triggerRowAction({row})` | +| `'CheckboxGroup'` | CheckboxGroup | `getCheckboxGroup()`, `getCheckboxes()`, `getSelectedCheckboxes()`, `toggleCheckbox({checkbox})` | +| `'ComboBox'` | ComboBox | `getCombobox()`, `getListbox()`, `getOptions()`, `open()`, `toggleOptionSelection({option})` | +| `'Dialog'` | Modal, Popover | `getTrigger()`, `getDialog()`, `open()`, `close()` — pass `overlayType: 'modal'` or `'popover'` to `createTester` | +| `'GridList'` | GridList | `getGridlist()`, `getRows()`, `getSelectedRows()`, `toggleRowSelection({row})`, `triggerRowAction({row})` | +| `'ListBox'` | ListBox | `getListbox()`, `getOptions()`, `getSelectedOptions()`, `toggleOptionSelection({option})`, `triggerOptionAction({option})` | +| `'Menu'` | Menu | `getTrigger()`, `getMenu()`, `getOptions()`, `open()`, `toggleOptionSelection({option})`, `openSubmenu({submenuTrigger})`, `close()` | +| `'RadioGroup'` | RadioGroup | `getRadioGroup()`, `getRadios()`, `getSelectedRadio()`, `triggerRadio({radio})` | +| `'Select'` | Select | `getTrigger()`, `getListbox()`, `getOptions()`, `toggleOptionSelection({option})` | +| `'Table'` | Table | `getTable()`, `getRows()`, `getFooterRows()`, `getColumns()`, `getSelectedRows()`, `toggleRowSelection({row})`, `toggleSort({column})`, `triggerRowAction({row})` | +| `'Tabs'` | Tabs | `getTablist()`, `getTabs()`, `getTabpanels()`, `getSelectedTab()`, `triggerTab({tab})` | +| `'Tree'` | Tree | `getTree()`, `getRows()`, `getSelectedRows()`, `toggleRowSelection({row})`, `toggleRowExpansion({row})`, `triggerRowAction({row})` | ### Per-component reference diff --git a/packages/dev/s2-docs/skills/react-spectrum-s2/test-utils-guidance.md b/packages/dev/s2-docs/skills/react-spectrum-s2/test-utils-guidance.md index 1be6cc86411..74dad90b995 100644 --- a/packages/dev/s2-docs/skills/react-spectrum-s2/test-utils-guidance.md +++ b/packages/dev/s2-docs/skills/react-spectrum-s2/test-utils-guidance.md @@ -30,10 +30,10 @@ it('my test case', async function () { let {getByTestId} = render(); // Initialize the table tester via providing the 'Table' pattern name and the root element of said table let tableTester = testUtilUser.createTester('Table', {root: getByTestId('test_table')}); - expect(tableTester.selectedRows()).toHaveLength(0); + expect(tableTester.getSelectedRows()).toHaveLength(0); await tableTester.toggleSelectAll(); - expect(tableTester.selectedRows()).toHaveLength(10); + expect(tableTester.getSelectedRows()).toHaveLength(10); ... }); ``` @@ -54,7 +54,7 @@ afterEach(() => { - Mouse drag interactions and other mock reliant interactions are not available in these test utils since they depended heavily on how the user mocked various things in their test. These must still be simulated manually by the user. - Some testers may support the notion of "long press" for certain interactions (e.g. long pressing a button to trigger its menu). To simulate this, you will need to mock PointerEvent globally (see the `installPointerEvent` util) and provide a way to advance timers to the User via `advanceTimer`. - These test utils are compatible with not only JSDOM unit tests but browser tests as well (e.g. vitest-browser-react). -- Methods that accept a target (`option`, `row`, `column`, `checkbox`, `radio`, `tab`) take a `number` (index), `string` (text content), or `HTMLElement`. Use the tester's own query methods (e.g. `rows()`, `options()`) to obtain an `HTMLElement` when you need one. +- Methods that accept a target (`option`, `row`, `column`, `checkbox`, `radio`, `tab`) take a `number` (index), `string` (text content), or `HTMLElement`. Use the tester's own query methods (e.g. `getRows()`, `getOptions()`) to obtain an `HTMLElement` when you need one. - Link navigation assertions must be simulated manually. The testers do not assert navigation side effects. ### When not to use the testers @@ -65,7 +65,7 @@ Skip the testers and write manual interactions for the following cases: - tests that verify exact focus order, arrow key cycling, or specific modifier key behavior. Use `fireEvent.keyDown` or `userEvent.keyboard` directly so the test is actually testing the desired keyboard flow. - when `isOpen` or `defaultOpen` is set, `open()` will no-op but the tester's `root` must still resolve to the trigger element. Use `getByLabelText` or `getByTestId` rather than `getByRole('button')` to avoid ambiguity when multiple buttons are in the DOM. - testing `isDismissible`, `isKeyboardDismissDisabled`, or outside-click behavior. Use `userEvent.click(document.body)` or `user.keyboard('[Escape]')` directly and assert the expected state afterwards. -- when a Dialog closes via an action button (not the explicit close/dismiss button) you should instead click that button manually, then use `dialogTester.dialog()` to assert whether the dialog is still present. +- when a Dialog closes via an action button (not the explicit close/dismiss button) you should instead click that button manually, then use `dialogTester.getDialog()` to assert whether the dialog is still present. ### Draggable handle components @@ -88,16 +88,16 @@ The pattern name passed to `createTester` is the ARIA pattern name — not the S | Pattern name | S2 component | Key methods | |---|---|---| -| `'CheckboxGroup'` | CheckboxGroup | `checkboxGroup()`, `checkboxes()`, `selectedCheckboxes()`, `toggleCheckbox({checkbox})` | -| `'ComboBox'` | ComboBox | `combobox()`, `listbox()`, `options()`, `open()`, `toggleOptionSelection({option})` | -| `'Dialog'` | Dialog | `trigger()`, `dialog()`, `open()`, `close()` — pass `overlayType: 'modal'` or `'popover'` to `createTester` | -| `'GridList'` | ListView | `gridlist()`, `rows()`, `selectedRows()`, `toggleRowSelection({row})`, `triggerRowAction({row})` | -| `'Menu'` | Menu | `trigger()`, `menu()`, `options()`, `open()`, `toggleOptionSelection({option})`, `openSubmenu({submenuTrigger})`, `close()` | -| `'RadioGroup'` | RadioGroup | `radiogroup()`, `radios()`, `selectedRadio()`, `triggerRadio({radio})` | -| `'Select'` | Picker | `trigger()`, `listbox()`, `options()`, `toggleOptionSelection({option})` | -| `'Table'` | TableView | `table()`, `rows()`, `footerRows()`, `columns()`, `selectedRows()`, `toggleRowSelection({row})`, `toggleSort({column})`, `triggerRowAction({row})` | -| `'Tabs'` | Tabs | `tablist()`, `tabs()`, `tabpanels()`, `selectedTab()`, `triggerTab({tab})` | -| `'Tree'` | TreeView | `tree()`, `rows()`, `selectedRows()`, `toggleRowSelection({row})`, `toggleRowExpansion({row})`, `triggerRowAction({row})` | +| `'CheckboxGroup'` | CheckboxGroup | `getCheckboxGroup()`, `getCheckboxes()`, `getSelectedCheckboxes()`, `toggleCheckbox({checkbox})` | +| `'ComboBox'` | ComboBox | `getCombobox()`, `getListbox()`, `getOptions()`, `open()`, `toggleOptionSelection({option})` | +| `'Dialog'` | Dialog | `getTrigger()`, `getDialog()`, `open()`, `close()` — pass `overlayType: 'modal'` or `'popover'` to `createTester` | +| `'GridList'` | ListView | `getGridlist()`, `getRows()`, `getSelectedRows()`, `toggleRowSelection({row})`, `triggerRowAction({row})` | +| `'Menu'` | Menu | `getTrigger()`, `getMenu()`, `getOptions()`, `open()`, `toggleOptionSelection({option})`, `openSubmenu({submenuTrigger})`, `close()` | +| `'RadioGroup'` | RadioGroup | `getRadioGroup()`, `getRadios()`, `getSelectedRadio()`, `triggerRadio({radio})` | +| `'Select'` | Picker | `getTrigger()`, `getListbox()`, `getOptions()`, `toggleOptionSelection({option})` | +| `'Table'` | TableView | `getTable()`, `getRows()`, `getFooterRows()`, `getColumns()`, `getSelectedRows()`, `toggleRowSelection({row})`, `toggleSort({column})`, `triggerRowAction({row})` | +| `'Tabs'` | Tabs | `getTablist()`, `getTabs()`, `getTabpanels()`, `getSelectedTab()`, `triggerTab({tab})` | +| `'Tree'` | TreeView | `getTree()`, `getRows()`, `getSelectedRows()`, `toggleRowSelection({row})`, `toggleRowExpansion({row})`, `triggerRowAction({row})` | #### Dialog `overlayType` reference @@ -113,7 +113,7 @@ Pass `overlayType` to `createTester` so the tester knows how the overlay is moun ```ts let dialogTester = testUtilUser.createTester('Dialog', {root: tree.getByRole('button'), overlayType: 'modal'}); await dialogTester.open(); -expect(dialogTester.dialog()).toBeVisible(); +expect(dialogTester.getDialog()).toBeVisible(); ``` ### Per-component reference diff --git a/packages/react-aria-components/docs/ComboBox.mdx b/packages/react-aria-components/docs/ComboBox.mdx index cc1bdda1654..0751df477b3 100644 --- a/packages/react-aria-components/docs/ComboBox.mdx +++ b/packages/react-aria-components/docs/ComboBox.mdx @@ -1599,12 +1599,12 @@ it('ComboBox can select an option via keyboard', async function () { let comboboxTester = testUtilUser.createTester('ComboBox', {root: getByTestId('test-combobox'), interactionType: 'keyboard'}); await comboboxTester.open(); - expect(comboboxTester.listbox()).toBeInTheDocument(); + expect(comboboxTester.getListbox()).toBeInTheDocument(); - let options = comboboxTester.options(); + let options = comboboxTester.getOptions(); await comboboxTester.toggleOptionSelection({option: options[0]}); - expect(comboboxTester.combobox().value).toBe('One'); - expect(comboboxTester.listbox()).not.toBeInTheDocument(); + expect(comboboxTester.getCombobox().value).toBe('One'); + expect(comboboxTester.getListbox()).not.toBeInTheDocument(); }); ``` diff --git a/packages/react-aria-components/docs/GridList.mdx b/packages/react-aria-components/docs/GridList.mdx index 075023ebe67..debf6d418ab 100644 --- a/packages/react-aria-components/docs/GridList.mdx +++ b/packages/react-aria-components/docs/GridList.mdx @@ -2107,17 +2107,17 @@ it('GridList can select a row via keyboard', async function () { ); let gridListTester = testUtilUser.createTester('GridList', {root: getByTestId('test-gridlist'), interactionType: 'keyboard'}); - let row = gridListTester.rows()[0]; + let row = gridListTester.getRows()[0]; expect(within(row).getByRole('checkbox')).not.toBeChecked(); - expect(gridListTester.selectedRows()).toHaveLength(0); + expect(gridListTester.getSelectedRows()).toHaveLength(0); await gridListTester.toggleRowSelection({row: 0}); expect(within(row).getByRole('checkbox')).toBeChecked(); - expect(gridListTester.selectedRows()).toHaveLength(1); + expect(gridListTester.getSelectedRows()).toHaveLength(1); await gridListTester.toggleRowSelection({row: 0}); expect(within(row).getByRole('checkbox')).not.toBeChecked(); - expect(gridListTester.selectedRows()).toHaveLength(0); + expect(gridListTester.getSelectedRows()).toHaveLength(0); }); ``` diff --git a/packages/react-aria-components/docs/ListBox.mdx b/packages/react-aria-components/docs/ListBox.mdx index 2467be7be0c..8537fbae916 100644 --- a/packages/react-aria-components/docs/ListBox.mdx +++ b/packages/react-aria-components/docs/ListBox.mdx @@ -2206,7 +2206,7 @@ it('ListBox can select an option via keyboard', async function () { let listboxTester = testUtilUser.createTester('ListBox', {root: getByTestId('test-listbox'), interactionType: 'keyboard'}); await listboxTester.toggleOptionSelection({option: 4}); - expect(listboxTester.options()[4]).toHaveAttribute('aria-selected', 'true'); + expect(listboxTester.getOptions()[4]).toHaveAttribute('aria-selected', 'true'); }); ``` diff --git a/packages/react-aria-components/docs/Menu.mdx b/packages/react-aria-components/docs/Menu.mdx index f588e7d940e..98e0cc5232b 100644 --- a/packages/react-aria-components/docs/Menu.mdx +++ b/packages/react-aria-components/docs/Menu.mdx @@ -1247,16 +1247,16 @@ it('Menu can open its submenu via keyboard', async function () { let menuTester = testUtilUser.createTester('Menu', {root: getByTestId('test-menutrigger'), interactionType: 'keyboard'}); await menuTester.open(); - expect(menuTester.menu()).toBeInTheDocument(); - let submenuTriggers = menuTester.submenuTriggers(); + expect(menuTester.getMenu()).toBeInTheDocument(); + let submenuTriggers = menuTester.getSubmenuTriggers(); expect(submenuTriggers).toHaveLength(1); let submenuTester = await menuTester.openSubmenu({submenuTrigger: 'Share…'}); - expect(submenuTester.menu()).toBeInTheDocument(); + expect(submenuTester.getMenu()).toBeInTheDocument(); - await submenuTester.toggleOptionSelection({option: submenuTester.options()[0]}); - expect(submenuTester.menu()).not.toBeInTheDocument(); - expect(menuTester.menu()).not.toBeInTheDocument(); + await submenuTester.toggleOptionSelection({option: submenuTester.getOptions()[0]}); + expect(submenuTester.getMenu()).not.toBeInTheDocument(); + expect(menuTester.getMenu()).not.toBeInTheDocument(); }); ``` diff --git a/packages/react-aria-components/docs/Select.mdx b/packages/react-aria-components/docs/Select.mdx index d1eb5b7012c..921e113a509 100644 --- a/packages/react-aria-components/docs/Select.mdx +++ b/packages/react-aria-components/docs/Select.mdx @@ -1364,7 +1364,7 @@ it('Select can select an option via keyboard', async function () { ); let selectTester = testUtilUser.createTester('Select', {root: getByTestId('test-select'), interactionType: 'keyboard'}); - let trigger = selectTester.trigger(); + let trigger = selectTester.getTrigger(); expect(trigger).toHaveTextContent('Select an item'); await selectTester.toggleOptionSelection({option: 'Cat'}); diff --git a/packages/react-aria-components/docs/Table.mdx b/packages/react-aria-components/docs/Table.mdx index 4acbd1d7371..6d96b08ae72 100644 --- a/packages/react-aria-components/docs/Table.mdx +++ b/packages/react-aria-components/docs/Table.mdx @@ -2695,22 +2695,22 @@ it('Table can toggle row selection', async function () { ); let tableTester = testUtilUser.createTester('Table', {root: getByTestId('test-table')}); - expect(tableTester.selectedRows()).toHaveLength(0); + expect(tableTester.getSelectedRows()).toHaveLength(0); await tableTester.toggleSelectAll(); - expect(tableTester.selectedRows()).toHaveLength(10); + expect(tableTester.getSelectedRows()).toHaveLength(10); await tableTester.toggleRowSelection({row: 2}); - expect(tableTester.selectedRows()).toHaveLength(9); - let checkbox = within(tableTester.rows()[2]).getByRole('checkbox'); + expect(tableTester.getSelectedRows()).toHaveLength(9); + let checkbox = within(tableTester.getRows()[2]).getByRole('checkbox'); expect(checkbox).not.toBeChecked(); await tableTester.toggleSelectAll(); - expect(tableTester.selectedRows()).toHaveLength(10); + expect(tableTester.getSelectedRows()).toHaveLength(10); expect(checkbox).toBeChecked(); await tableTester.toggleSelectAll(); - expect(tableTester.selectedRows()).toHaveLength(0); + expect(tableTester.getSelectedRows()).toHaveLength(0); }); ``` diff --git a/packages/react-aria-components/docs/Tabs.mdx b/packages/react-aria-components/docs/Tabs.mdx index 12d1a4f1765..b77ec14d504 100644 --- a/packages/react-aria-components/docs/Tabs.mdx +++ b/packages/react-aria-components/docs/Tabs.mdx @@ -835,11 +835,11 @@ it('Tabs can change selection via keyboard', async function () { ); let tabsTester = testUtilUser.createTester('Tabs', {root: getByTestId('test-tabs'), interactionType: 'keyboard'}); - let tabs = tabsTester.tabs(); - expect(tabsTester.selectedTab()).toBe(tabs[0]); + let tabs = tabsTester.getTabs(); + expect(tabsTester.getSelectedTab()).toBe(tabs[0]); await tabsTester.triggerTab({tab: 1}); - expect(tabsTester.selectedTab()).toBe(tabs[1]); + expect(tabsTester.getSelectedTab()).toBe(tabs[1]); }); ``` diff --git a/packages/react-aria-components/docs/Tree.mdx b/packages/react-aria-components/docs/Tree.mdx index a8d12f9dde3..9ac5198ade1 100644 --- a/packages/react-aria-components/docs/Tree.mdx +++ b/packages/react-aria-components/docs/Tree.mdx @@ -2193,16 +2193,16 @@ it('Tree can select a item via keyboard', async function () { let treeTester = testUtilUser.createTester('Tree', {root: getByTestId('test-tree'), interactionType: 'keyboard'}); await treeTester.toggleRowSelection({row: 0}); - expect(treeTester.selectedRows()).toHaveLength(1); - expect(within(treeTester.rows()[0]).getByRole('checkbox')).toBeChecked(); + expect(treeTester.getSelectedRows()).toHaveLength(1); + expect(within(treeTester.getRows()[0]).getByRole('checkbox')).toBeChecked(); await treeTester.toggleRowSelection({row: 1}); - expect(treeTester.selectedRows()).toHaveLength(2); - expect(within(treeTester.rows()[1]).getByRole('checkbox')).toBeChecked(); + expect(treeTester.getSelectedRows()).toHaveLength(2); + expect(within(treeTester.getRows()[1]).getByRole('checkbox')).toBeChecked(); await treeTester.toggleRowSelection({row: 0}); - expect(treeTester.selectedRows()).toHaveLength(1); - expect(within(treeTester.rows()[0]).getByRole('checkbox')).not.toBeChecked(); + expect(treeTester.getSelectedRows()).toHaveLength(1); + expect(within(treeTester.getRows()[0]).getByRole('checkbox')).not.toBeChecked(); }); ``` diff --git a/packages/react-aria-components/test/AriaMenu.test-util.tsx b/packages/react-aria-components/test/AriaMenu.test-util.tsx index 41a72658dd2..2500c7dde4e 100644 --- a/packages/react-aria-components/test/AriaMenu.test-util.tsx +++ b/packages/react-aria-components/test/AriaMenu.test-util.tsx @@ -99,7 +99,7 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo it('has default behavior (button renders, menu is closed)', function () { let tree = renderers.standard(); let menuTester = testUtilUser.createTester('Menu', {user, root: tree.container}); - let triggerButton = menuTester.trigger()!; + let triggerButton = menuTester.getTrigger()!; expect(triggerButton).toBeTruthy(); expect(triggerButton).toHaveAttribute('aria-haspopup', 'true'); @@ -107,7 +107,7 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo let buttonText = within(triggerButton).getByText(triggerText); expect(buttonText).toBeTruthy(); - expect(menuTester.menu()).toBeFalsy(); + expect(menuTester.getMenu()).toBeFalsy(); expect(triggerButton).toHaveAttribute('aria-expanded', 'false'); expect(triggerButton).toHaveAttribute('type', 'button'); @@ -116,14 +116,14 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo it('toggles the menu display on button click', async function () { let tree = renderers.standard(); let menuTester = testUtilUser.createTester('Menu', {user, root: tree.container}); - let triggerButton = menuTester.trigger()!; + let triggerButton = menuTester.getTrigger()!; await menuTester.open(); act(() => { jest.runAllTimers(); }); - let menu = menuTester.menu()!; + let menu = menuTester.getMenu()!; expect(menu).toBeTruthy(); expect(menu).toHaveAttribute('aria-labelledby', triggerButton.id); expect(menu).toHaveFocus(); @@ -142,7 +142,7 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo it('will not close the menu when mousing over the trigger again without lifting press', function () { let tree = renderers.standard(); let menuTester = testUtilUser.createTester('Menu', {user, root: tree.container}); - let triggerButton = menuTester.trigger()!; + let triggerButton = menuTester.getTrigger()!; fireEvent.mouseEnter(triggerButton); fireEvent.mouseDown(triggerButton, {detail: 1}); @@ -157,14 +157,14 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo it('closes the menu on click outside', async function () { let tree = renderers.standard(); let menuTester = testUtilUser.createTester('Menu', {user, root: tree.container}); - let triggerButton = menuTester.trigger()!; + let triggerButton = menuTester.getTrigger()!; await menuTester.open(); act(() => { jest.runAllTimers(); }); - let menu = menuTester.menu()!; + let menu = menuTester.getMenu()!; expect(menu).toBeTruthy(); expect(menu).toHaveAttribute('aria-labelledby', triggerButton.id); expect(menu).toHaveFocus(); @@ -189,16 +189,16 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo let tree = renderers.standard(); let menuTester = testUtilUser.createTester('Menu', {user, root: tree.container}); menuTester.setInteractionType('keyboard'); - let triggerButton = menuTester.trigger(); + let triggerButton = menuTester.getTrigger(); await menuTester.open(); act(() => { jest.runAllTimers(); }); - let menu = menuTester.menu(); + let menu = menuTester.getMenu(); expect(menu).toBeTruthy(); - let options = menuTester.options(); + let options = menuTester.getOptions(); expect(options[0]).toHaveFocus(); await menuTester.close(); @@ -214,16 +214,16 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo let tree = renderers.standard(); let menuTester = testUtilUser.createTester('Menu', {user, root: tree.container}); menuTester.setInteractionType('keyboard'); - let triggerButton = menuTester.trigger(); + let triggerButton = menuTester.getTrigger(); await menuTester.open({direction: 'down'}); act(() => { jest.runAllTimers(); }); - let menu = menuTester.menu(); + let menu = menuTester.getMenu(); expect(menu).toBeTruthy(); - let options = menuTester.options(); + let options = menuTester.getOptions(); expect(options[0]).toHaveFocus(); await menuTester.close(); @@ -239,16 +239,16 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo let tree = renderers.standard(); let menuTester = testUtilUser.createTester('Menu', {user, root: tree.container}); menuTester.setInteractionType('keyboard'); - let triggerButton = menuTester.trigger(); + let triggerButton = menuTester.getTrigger(); await menuTester.open({direction: 'up'}); act(() => { jest.runAllTimers(); }); - let menu = menuTester.menu(); + let menu = menuTester.getMenu(); expect(menu).toBeTruthy(); - let options = menuTester.options(); + let options = menuTester.getOptions(); expect(options[options.length - 1]).toHaveFocus(); await menuTester.close(); @@ -264,18 +264,18 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo let tree = renderers.standard(); let menuTester = testUtilUser.createTester('Menu', {user, root: tree.container}); menuTester.setInteractionType('keyboard'); - let triggerButton = menuTester.trigger()!; + let triggerButton = menuTester.getTrigger()!; await menuTester.open(); act(() => { jest.runAllTimers(); }); - let menu = menuTester.menu(); + let menu = menuTester.getMenu(); expect(menu).toBeTruthy(); expect(menu).toHaveAttribute('aria-labelledby', triggerButton.id); - let options = menuTester.options(); + let options = menuTester.getOptions(); expect(options[0]).toHaveFocus(); await user.keyboard('[ArrowUp]'); @@ -298,7 +298,7 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo jest.runAllTimers(); }); - let menu = menuTester.menu(); + let menu = menuTester.getMenu(); await user.keyboard('[Space]'); act(() => { @@ -310,7 +310,7 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo act(() => { jest.runAllTimers(); }); - menu = menuTester.menu(); + menu = menuTester.getMenu(); await user.keyboard('[Enter]'); act(() => { @@ -329,7 +329,7 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo jest.runAllTimers(); }); - let menu = menuTester.menu(); + let menu = menuTester.getMenu(); let buttons = tree.getAllByLabelText('Dismiss'); expect(buttons.length).toBe(2); @@ -348,18 +348,18 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo it('selects an option via mouse', async function () { let tree = renderers.singleSelection!(); let menuTester = testUtilUser.createTester('Menu', {user, root: tree.container}); - let triggerButton = menuTester.trigger()!; + let triggerButton = menuTester.getTrigger()!; await menuTester.open(); act(() => { jest.runAllTimers(); }); - let menu = menuTester.menu(); + let menu = menuTester.getMenu(); expect(menu).toBeTruthy(); expect(menu).toHaveAttribute('aria-labelledby', triggerButton.id); - let options = menuTester.options(); + let options = menuTester.getOptions(); await menuTester.toggleOptionSelection({option: options[1], menuSelectionMode: 'single'}); @@ -373,7 +373,7 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo jest.runAllTimers(); }); - options = menuTester.options(); + options = menuTester.getOptions(); expect(options[0]).toHaveAttribute('aria-checked', 'false'); expect(options[1]).toHaveAttribute('aria-checked', 'true'); }); @@ -385,18 +385,18 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo root: tree.container, interactionType: 'keyboard' }); - let triggerButton = menuTester.trigger()!; + let triggerButton = menuTester.getTrigger()!; await menuTester.open(); act(() => { jest.runAllTimers(); }); - let menu = menuTester.menu()!; + let menu = menuTester.getMenu()!; expect(menu).toBeTruthy(); expect(menu).toHaveAttribute('aria-labelledby', triggerButton.id); - let options = menuTester.options(); + let options = menuTester.getOptions(); expect(options[0]).toHaveFocus(); await menuTester.toggleOptionSelection({option: options[1], menuSelectionMode: 'single'}); @@ -411,7 +411,7 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo jest.runAllTimers(); }); - options = menuTester.options(); + options = menuTester.getOptions(); expect(options[0]).toHaveAttribute('aria-checked', 'false'); expect(options[1]).toHaveAttribute('aria-checked', 'true'); expect(options[1]).toHaveFocus(); @@ -423,7 +423,7 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo jest.runAllTimers(); }); - options = menuTester.options(); + options = menuTester.getOptions(); expect(options[0]).toHaveAttribute('aria-checked', 'false'); expect(options[1]).toHaveAttribute('aria-checked', 'true'); expect(options[1]).toHaveFocus(); @@ -433,18 +433,18 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo let tree = renderers.singleSelection!(); let menuTester = testUtilUser.createTester('Menu', {user, root: tree.container}); menuTester.setInteractionType('keyboard'); - let triggerButton = menuTester.trigger(); + let triggerButton = menuTester.getTrigger(); await menuTester.open(); act(() => { jest.runAllTimers(); }); - let menu = menuTester.menu(); + let menu = menuTester.getMenu(); expect(menu).toBeTruthy(); expect(menu).toHaveAttribute('aria-labelledby', triggerButton.id); - let options = menuTester.options(); + let options = menuTester.getOptions(); expect(options[0]).toHaveFocus(); await user.keyboard('[ArrowDown]'); @@ -470,11 +470,11 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo jest.runAllTimers(); }); fireEvent.keyDown(document.activeElement!, {key: 'Enter', repeat: true}); - let menu = menuTester.menu(); + let menu = menuTester.getMenu(); expect(menu).toBeInTheDocument(); await user.keyboard('{/Enter}'); expect( - menuTester.options().filter(option => option.getAttribute('aria-checked') === 'true') + menuTester.getOptions().filter(option => option.getAttribute('aria-checked') === 'true') .length ).toBe(0); }); @@ -492,8 +492,8 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo jest.runAllTimers(); }); - let menu = menuTester.menu(); - let options = menuTester.options(); + let menu = menuTester.getMenu(); + let options = menuTester.getOptions(); await menuTester.toggleOptionSelection({ option: options[2], @@ -523,8 +523,8 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo jest.runAllTimers(); }); - menu = menuTester.menu(); - options = menuTester.options(); + menu = menuTester.getMenu(); + options = menuTester.getOptions(); expect(options[1]).toHaveAttribute('aria-checked', 'true'); expect(options[2]).toHaveAttribute('aria-checked', 'true'); expect(options[2]).toHaveFocus(); @@ -540,8 +540,8 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo jest.runAllTimers(); }); - let menu = menuTester.menu(); - let options = menuTester.options(); + let menu = menuTester.getMenu(); + let options = menuTester.getOptions(); expect(options[0]).toHaveFocus(); await user.keyboard('[ArrowDown]'); @@ -568,8 +568,8 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo jest.runAllTimers(); }); - menu = menuTester.menu(); - options = menuTester.options(); + menu = menuTester.getMenu(); + options = menuTester.getOptions(); expect(options[1]).toHaveAttribute('aria-checked', 'true'); expect(options[2]).toHaveAttribute('aria-checked', 'true'); expect(options[1]).toHaveFocus(); @@ -585,8 +585,8 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo jest.runAllTimers(); }); - let menu = menuTester.menu(); - let options = menuTester.options(); + let menu = menuTester.getMenu(); + let options = menuTester.getOptions(); expect(options[0]).toHaveFocus(); await user.keyboard('[ArrowDown]'); @@ -602,8 +602,8 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo jest.runAllTimers(); }); - menu = menuTester.menu(); - options = menuTester.options(); + menu = menuTester.getMenu(); + options = menuTester.getOptions(); expect(options[0]).toHaveAttribute('aria-checked', 'false'); expect(options[1]).toHaveAttribute('aria-checked', 'true'); expect(options[2]).toHaveAttribute('aria-checked', 'false'); @@ -621,11 +621,11 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo jest.runAllTimers(); }); fireEvent.keyDown(document.activeElement!, {key: 'Enter', repeat: true}); - let menu = menuTester.menu(); + let menu = menuTester.getMenu(); expect(menu).toBeInTheDocument(); await user.keyboard('{/Enter}'); expect( - menuTester.options().filter(option => option.getAttribute('aria-checked') === 'true') + menuTester.getOptions().filter(option => option.getAttribute('aria-checked') === 'true') .length ).toBe(0); }); @@ -637,7 +637,7 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo it('does not trigger', async function () { let tree = renderers.disabledTrigger!(); let menuTester = testUtilUser.createTester('Menu', {user, root: tree.container}); - let triggerButton = menuTester.trigger(); + let triggerButton = menuTester.getTrigger(); await menuTester.open(); act(() => { @@ -688,9 +688,9 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo interactionType }); await menuTester.open(); - let menu = menuTester.menu(); + let menu = menuTester.getMenu(); - let submenuTrigger = menuTester.submenuTriggers()[0]!; + let submenuTrigger = menuTester.getSubmenuTriggers()[0]!; expect(submenuTrigger).toHaveAttribute('aria-expanded', 'false'); let submenuUtil = (await menuTester.openSubmenu({submenuTrigger}))!; @@ -698,17 +698,17 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo jest.runAllTimers(); }); expect(submenuTrigger).toHaveAttribute('aria-expanded', 'true'); - let submenu = submenuUtil.menu(); + let submenu = submenuUtil.getMenu(); expect(submenu).toBeInTheDocument(); await submenuUtil.toggleOptionSelection({ option: submenuUtil - .options() + .getOptions() .filter(item => item.getAttribute('aria-haspopup') == null)[0] }); expect(menu).not.toBeInTheDocument(); expect(submenu).not.toBeInTheDocument(); - expect(document.activeElement).toBe(menuTester.trigger()); + expect(document.activeElement).toBe(menuTester.getTrigger()); }); it('should support nested submenu triggers', async () => { @@ -720,35 +720,35 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo interactionType }); await menuTester.open(); - let menu = menuTester.menu(); + let menu = menuTester.getMenu(); - let submenuTrigger = menuTester.submenuTriggers()[0]; + let submenuTrigger = menuTester.getSubmenuTriggers()[0]; expect(submenuTrigger).toHaveAttribute('aria-expanded', 'false'); let submenuUtil = (await menuTester.openSubmenu({submenuTrigger}))!; expect(submenuTrigger).toHaveAttribute('aria-expanded', 'true'); - let submenu = submenuUtil.menu(); + let submenu = submenuUtil.getMenu(); expect(submenu).toBeInTheDocument(); - let nestedSubmenuTrigger = submenuUtil.submenuTriggers()[0]; + let nestedSubmenuTrigger = submenuUtil.getSubmenuTriggers()[0]; expect(nestedSubmenuTrigger).toHaveAttribute('aria-expanded', 'false'); let nestedSubmenuUtil = (await submenuUtil.openSubmenu({ submenuTrigger: nestedSubmenuTrigger }))!; expect(nestedSubmenuTrigger).toHaveAttribute('aria-expanded', 'true'); - let nestedSubmenu = nestedSubmenuUtil.menu(); + let nestedSubmenu = nestedSubmenuUtil.getMenu(); expect(nestedSubmenu).toBeInTheDocument(); await nestedSubmenuUtil.toggleOptionSelection({ option: nestedSubmenuUtil - .options() + .getOptions() .filter(item => item.getAttribute('aria-haspopup') == null)[0] }); expect(menu).not.toBeInTheDocument(); expect(submenu).not.toBeInTheDocument(); expect(nestedSubmenu).not.toBeInTheDocument(); - expect(document.activeElement).toBe(menuTester.trigger()); + expect(document.activeElement).toBe(menuTester.getTrigger()); }); if (renderers.disabledSubmenuTrigger) { @@ -760,8 +760,8 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo interactionType }); await expect(menuTester.openSubmenu({submenuTrigger: 'Share…'})).rejects.toThrow(); - expect(menuTester.menu()).toBeInTheDocument(); - expect(menuTester.submenuTriggers()[0]).toHaveAttribute('aria-disabled'); + expect(menuTester.getMenu()).toBeInTheDocument(); + expect(menuTester.getSubmenuTriggers()[0]).toHaveAttribute('aria-disabled'); expect(tree.getAllByRole('menu', {hidden: true})).toHaveLength(1); }); } @@ -773,9 +773,9 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo let menuTester = testUtilUser.createTester('Menu', {user, root: tree.container}); await menuTester.open(); - let menu = menuTester.menu(); + let menu = menuTester.getMenu(); - let submenuTrigger = menuTester.submenuTriggers()[0]; + let submenuTrigger = menuTester.getSubmenuTriggers()[0]; expect(submenuTrigger).toHaveAttribute('aria-expanded', 'false'); let submenuUtil = (await menuTester.openSubmenu({submenuTrigger}))!; @@ -783,10 +783,10 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo jest.runAllTimers(); }); expect(submenuTrigger).toHaveAttribute('aria-expanded', 'true'); - let submenu = submenuUtil.menu(); + let submenu = submenuUtil.getMenu(); expect(submenu).toBeInTheDocument(); - let nestedSubmenuTrigger = submenuUtil.submenuTriggers()[0]; + let nestedSubmenuTrigger = submenuUtil.getSubmenuTriggers()[0]; expect(nestedSubmenuTrigger).toHaveAttribute('aria-expanded', 'false'); let nestedSubmenuUtil = (await submenuUtil.openSubmenu({ @@ -796,7 +796,7 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo jest.runAllTimers(); }); expect(nestedSubmenuTrigger).toHaveAttribute('aria-expanded', 'true'); - let nestedSubmenu = nestedSubmenuUtil.menu(); + let nestedSubmenu = nestedSubmenuUtil.getMenu(); expect(submenu).toBeInTheDocument(); await user.click(document.body); @@ -817,23 +817,23 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo interactionType: 'keyboard' }); await menuTester.open(); - let menu = menuTester.menu(); + let menu = menuTester.getMenu(); - let submenuTrigger = menuTester.submenuTriggers()[0]; + let submenuTrigger = menuTester.getSubmenuTriggers()[0]; let submenuUtil = (await menuTester.openSubmenu({submenuTrigger}))!; act(() => { jest.runAllTimers(); }); - let submenu = submenuUtil.menu(); + let submenu = submenuUtil.getMenu(); - let nestedSubmenuTrigger = submenuUtil.submenuTriggers()[0]; + let nestedSubmenuTrigger = submenuUtil.getSubmenuTriggers()[0]; let nestedSubmenuUtil = (await submenuUtil.openSubmenu({ submenuTrigger: nestedSubmenuTrigger }))!; act(() => { jest.runAllTimers(); }); - let nestedSubmenu = nestedSubmenuUtil.menu(); + let nestedSubmenu = nestedSubmenuUtil.getMenu(); await user.keyboard('[Escape]'); act(() => { @@ -852,24 +852,24 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo let tree = renderers.submenus!(); let menuTester = testUtilUser.createTester('Menu', {user, root: tree.container}); await menuTester.open(); - let menu = menuTester.menu(); - let submenuTrigger = menuTester.submenuTriggers()[0]; + let menu = menuTester.getMenu(); + let submenuTrigger = menuTester.getSubmenuTriggers()[0]; let submenuUtil = (await menuTester.openSubmenu({submenuTrigger}))!; act(() => { jest.runAllTimers(); }); - let submenu = submenuUtil.menu(); + let submenu = submenuUtil.getMenu(); expect(submenu).toBeInTheDocument(); - let nestedSubmenuTrigger = submenuUtil.submenuTriggers()[0]; + let nestedSubmenuTrigger = submenuUtil.getSubmenuTriggers()[0]; let nestedSubmenuUtil = (await submenuUtil.openSubmenu({ submenuTrigger: nestedSubmenuTrigger }))!; act(() => { jest.runAllTimers(); }); - let nestedSubmenu = nestedSubmenuUtil.menu(); + let nestedSubmenu = nestedSubmenuUtil.getMenu(); expect(submenu).toBeInTheDocument(); - await user.hover(menuTester.options()[0]); + await user.hover(menuTester.getOptions()[0]); act(() => { jest.runAllTimers(); }); @@ -882,12 +882,12 @@ export const AriaMenuTests = ({renderers, setup, prefix}: AriaMenuTestProps): vo let tree = renderers.submenus!(); let menuTester = testUtilUser.createTester('Menu', {user, root: tree.container}); await menuTester.open(); - await user.hover(menuTester.submenuTriggers()[0]); + await user.hover(menuTester.getSubmenuTriggers()[0]); act(() => { jest.runAllTimers(); }); - expect(menuTester.submenuTriggers()[0]).toHaveAttribute('aria-expanded', 'true'); - expect(document.activeElement).toBe(menuTester.submenuTriggers()[0]); + expect(menuTester.getSubmenuTriggers()[0]).toHaveAttribute('aria-expanded', 'true'); + expect(document.activeElement).toBe(menuTester.getSubmenuTriggers()[0]); // It should also allow the user to move focus into the submenu via ArrowRight await user.keyboard('{ArrowRight}'); diff --git a/packages/react-aria-components/test/AriaTree.test-util.tsx b/packages/react-aria-components/test/AriaTree.test-util.tsx index fe5e72ed0b1..46dba784d11 100644 --- a/packages/react-aria-components/test/AriaTree.test-util.tsx +++ b/packages/react-aria-components/test/AriaTree.test-util.tsx @@ -76,16 +76,16 @@ export const AriaTreeTests = ({renderers, setup, prefix}: AriaTreeTestProps): vo it('should have the base set of aria and data attributes', () => { let root = renderers.standard!(); let treeTester = testUtilUser.createTester('Tree', {user, root: root.container}); - let tree = treeTester.tree(); + let tree = treeTester.getTree(); expect(tree).toHaveAttribute('aria-label'); - for (let row of treeTester.rows()) { + for (let row of treeTester.getRows()) { expect(row).toHaveAttribute('aria-level'); expect(row).toHaveAttribute('aria-posinset'); expect(row).toHaveAttribute('aria-setsize'); } - expect(treeTester.rows()[0]).not.toHaveAttribute('aria-expanded'); - expect(treeTester.rows()[1]).toHaveAttribute('aria-expanded', 'false'); + expect(treeTester.getRows()[0]).not.toHaveAttribute('aria-expanded'); + expect(treeTester.getRows()[1]).toHaveAttribute('aria-expanded', 'false'); }); describeInteractions('interaction', function ({interactionType}) { @@ -99,7 +99,7 @@ export const AriaTreeTests = ({renderers, setup, prefix}: AriaTreeTestProps): vo await treeTester.toggleRowExpansion({row: 1}); await treeTester.toggleRowExpansion({row: 2}); - let rows = treeTester.rows(); + let rows = treeTester.getRows(); let rowNoChild = rows[0]; expect(rowNoChild).toHaveAttribute('aria-label'); expect(rowNoChild).not.toHaveAttribute('aria-expanded'); @@ -158,7 +158,7 @@ export const AriaTreeTests = ({renderers, setup, prefix}: AriaTreeTestProps): vo interactionType }); - let rows = treeTester.rows(); + let rows = treeTester.getRows(); expect(rows[0]).toHaveAttribute('aria-selected', 'false'); expect(rows[1]).toHaveAttribute('aria-selected', 'false'); // disabled rows should not be selectable @@ -168,15 +168,15 @@ export const AriaTreeTests = ({renderers, setup, prefix}: AriaTreeTestProps): vo await treeTester.toggleRowSelection({row: 0}); expect(rows[0]).toHaveAttribute('aria-selected', 'true'); expect(rows[1]).toHaveAttribute('aria-selected', 'false'); - expect(treeTester.selectedRows()).toHaveLength(1); - expect(within(treeTester.rows()[0]).getByRole('checkbox')).toBeChecked(); + expect(treeTester.getSelectedRows()).toHaveLength(1); + expect(within(treeTester.getRows()[0]).getByRole('checkbox')).toBeChecked(); await treeTester.toggleRowSelection({row: 1}); expect(rows[0]).toHaveAttribute('aria-selected', 'false'); expect(rows[1]).toHaveAttribute('aria-selected', 'true'); - expect(treeTester.selectedRows()).toHaveLength(1); - expect(within(treeTester.rows()[0]).getByRole('checkbox')).not.toBeChecked(); - expect(within(treeTester.rows()[1]).getByRole('checkbox')).toBeChecked(); + expect(treeTester.getSelectedRows()).toHaveLength(1); + expect(within(treeTester.getRows()[0]).getByRole('checkbox')).not.toBeChecked(); + expect(within(treeTester.getRows()[1]).getByRole('checkbox')).toBeChecked(); await expect(treeTester.toggleRowSelection({row: 2})).rejects.toThrow(); expect(rows[0]).toHaveAttribute('aria-selected', 'false'); @@ -184,7 +184,7 @@ export const AriaTreeTests = ({renderers, setup, prefix}: AriaTreeTestProps): vo expect(rows[2]).not.toHaveAttribute('aria-selected'); await treeTester.toggleRowExpansion({row: 1}); - rows = treeTester.rows(); + rows = treeTester.getRows(); // row 2 is now the subrow of row 1 because we expanded it expect(rows[2]).toHaveAttribute('aria-selected', 'false'); @@ -196,7 +196,7 @@ export const AriaTreeTests = ({renderers, setup, prefix}: AriaTreeTestProps): vo // collapse and re-expand to make sure the selection persists await treeTester.toggleRowExpansion({row: 1}); await treeTester.toggleRowExpansion({row: 1}); - rows = treeTester.rows(); + rows = treeTester.getRows(); expect(rows[2]).toHaveAttribute('aria-selected', 'true'); await treeTester.toggleRowSelection({row: 2}); @@ -207,7 +207,7 @@ export const AriaTreeTests = ({renderers, setup, prefix}: AriaTreeTestProps): vo await treeTester.toggleRowExpansion({row: 1}); // items inside a disabled item can be selected await treeTester.toggleRowExpansion({row: 2}); - rows = treeTester.rows(); + rows = treeTester.getRows(); await treeTester.toggleRowSelection({row: 3}); expect(rows[3]).toHaveAttribute('aria-selected', 'true'); @@ -227,7 +227,7 @@ export const AriaTreeTests = ({renderers, setup, prefix}: AriaTreeTestProps): vo interactionType }); - let rows = treeTester.rows(); + let rows = treeTester.getRows(); expect(rows[2]).toHaveAttribute('aria-expanded', 'false'); await expect(treeTester.toggleRowExpansion({row: 2})).rejects.toThrow(); diff --git a/packages/react-aria-components/test/ComboBox.test.js b/packages/react-aria-components/test/ComboBox.test.js index b2fe02ed1cb..dfa993ecef8 100644 --- a/packages/react-aria-components/test/ComboBox.test.js +++ b/packages/react-aria-components/test/ComboBox.test.js @@ -156,11 +156,11 @@ describe('ComboBox', () => { let comboboxTester = testUtilUser.createTester('ComboBox', {root: tree.container}); act(() => { - comboboxTester.combobox().focus(); + comboboxTester.getCombobox().focus(); }); await user.keyboard('p'); - let groups = comboboxTester.sections(); + let groups = comboboxTester.getSections(); expect(groups).toHaveLength(1); expect(groups[0]).toHaveAttribute('aria-labelledby'); expect(document.getElementById(groups[0].getAttribute('aria-labelledby'))).toHaveTextContent( @@ -196,11 +196,11 @@ describe('ComboBox', () => { let comboboxTester = testUtilUser.createTester('ComboBox', {root: tree.container}); act(() => { - comboboxTester.combobox().focus(); + comboboxTester.getCombobox().focus(); }); await user.keyboard('p'); - let groups = comboboxTester.sections(); + let groups = comboboxTester.getSections(); expect(groups).toHaveLength(1); expect(groups[0]).toHaveAttribute('aria-labelledby'); expect(document.getElementById(groups[0].getAttribute('aria-labelledby'))).toHaveTextContent( @@ -232,10 +232,10 @@ describe('ComboBox', () => { let comboboxTester = testUtilUser.createTester('ComboBox', {root: tree.container}); act(() => { - comboboxTester.combobox().focus(); + comboboxTester.getCombobox().focus(); }); await user.keyboard('c'); - let options = comboboxTester.options(); + let options = comboboxTester.getOptions(); expect(options).toHaveLength(1); }); @@ -296,21 +296,26 @@ describe('ComboBox', () => { ); - let comboboxTester = testUtilUser.createTester('ComboBox', {root: tree.container, interactionType: 'keyboard'}); + let comboboxTester = testUtilUser.createTester('ComboBox', { + root: tree.container, + interactionType: 'keyboard' + }); await comboboxTester.toggleOptionSelection({option: 'Dog'}); expect(onSelectionChange).toHaveBeenCalledWith('2'); - expect(comboboxTester.combobox()).toHaveValue('Dog'); - expect(comboboxTester.listbox()).toBeNull(); + expect(comboboxTester.getCombobox()).toHaveValue('Dog'); + expect(comboboxTester.getListbox()).toBeNull(); }); - it.each(['click', 'tab'])('should not fire extra onSelectionChange calls after focus moves away in fully controlled mode via %s', async (focusMove) => { - let onSelectionChange = jest.fn(); - let keyToText = { - '1': 'Cat', - '2': 'Dog', - '3': 'Kangaroo' - }; + it.each(['click', 'tab'])( + 'should not fire extra onSelectionChange calls after focus moves away in fully controlled mode via %s', + async focusMove => { + let onSelectionChange = jest.fn(); + let keyToText = { + 1: 'Cat', + 2: 'Dog', + 3: 'Kangaroo' + }; function ControlledComboBox() { let [selectedKey, setSelectedKey] = useState(null); @@ -346,38 +351,21 @@ describe('ComboBox', () => { let tree = render(); let comboboxTester = testUtilUser.createTester('ComboBox', {root: tree.container}); - await comboboxTester.selectOption({option: 'Dog'}); + await comboboxTester.toggleOptionSelection({option: 'Dog'}); expect(onSelectionChange).toHaveBeenCalledTimes(1); if (focusMove === 'click') { await user.click(tree.getByRole('button', {name: 'Next'})); } else { act(() => { - comboboxTester.combobox.focus(); + comboboxTester.getCombobox().focus(); }); await user.tab(); } expect(onSelectionChange).toHaveBeenCalledTimes(1); } - - let tree = render(); - let comboboxTester = testUtilUser.createTester('ComboBox', {root: tree.container}); - - await comboboxTester.toggleOptionSelection({option: 'Dog'}); - expect(onSelectionChange).toHaveBeenCalledTimes(1); - - if (focusMove === 'click') { - await user.click(tree.getByRole('button', {name: 'Next'})); - } else { - act(() => { - comboboxTester.combobox().focus(); - }); - await user.tab(); - } - - expect(onSelectionChange).toHaveBeenCalledTimes(1); - }); + ); it('should support form reset', async () => { const tree = render( @@ -400,12 +388,12 @@ describe('ComboBox', () => { ); const comboboxTester = testUtilUser.createTester('ComboBox', {root: tree.container}); - const combobox = comboboxTester.combobox(); + const combobox = comboboxTester.getCombobox(); expect(combobox).toHaveValue('Dog'); await comboboxTester.open(); - const options = comboboxTester.options(); + const options = comboboxTester.getOptions(); await user.click(options[0]); expect(combobox).toHaveValue('Cat'); @@ -441,7 +429,7 @@ describe('ComboBox', () => { ); let comboboxTester = testUtilUser.createTester('ComboBox', {root: tree.container}); - let combobox = comboboxTester.combobox(); + let combobox = comboboxTester.getCombobox(); expect(combobox).toHaveAttribute('required'); expect(combobox).not.toHaveAttribute('aria-required'); @@ -462,11 +450,11 @@ describe('ComboBox', () => { expect(comboboxWrapper).toHaveAttribute('data-invalid'); act(() => { - comboboxTester.combobox().focus(); + comboboxTester.getCombobox().focus(); }); await user.keyboard('C'); - let options = comboboxTester.options(); + let options = comboboxTester.getOptions(); await user.click(options[0]); expect(combobox).toHaveAttribute('aria-describedby'); @@ -540,11 +528,11 @@ describe('ComboBox', () => { ); let comboboxTester = testUtilUser.createTester('ComboBox', {root: tree.container}); - expect(comboboxTester.listbox()).toBeFalsy(); + expect(comboboxTester.getListbox()).toBeFalsy(); comboboxTester.setInteractionType('mouse'); await comboboxTester.open(); - expect(comboboxTester.options()).toHaveLength(7); + expect(comboboxTester.getOptions()).toHaveLength(7); }); it('should clear contexts inside popover', async () => { @@ -596,13 +584,13 @@ describe('ComboBox', () => { let comboboxTester = testUtilUser.createTester('ComboBox', {root: tree.container}); act(() => { - comboboxTester.combobox().focus(); + comboboxTester.getCombobox().focus(); }); await user.keyboard('p'); - let options = comboboxTester.options(); + let options = comboboxTester.getOptions(); expect(options).toHaveLength(1); - expect(comboboxTester.listbox()).toBeTruthy(); + expect(comboboxTester.getListbox()).toBeTruthy(); expect(options[0]).toHaveTextContent('No results'); }); @@ -642,12 +630,12 @@ describe('ComboBox', () => { let tree = render(); let comboboxTester = testUtilUser.createTester('ComboBox', {root: tree.container}); act(() => { - comboboxTester.combobox().focus(); + comboboxTester.getCombobox().focus(); }); await user.keyboard('L'); - let options = comboboxTester.options(); + let options = comboboxTester.getOptions(); expect(options).toHaveLength(1); expect(options[0]).toHaveTextContent('Create "L"'); @@ -657,14 +645,14 @@ describe('ComboBox', () => { await user.click(options[0]); } expect(onAction).toHaveBeenCalledTimes(1); - expect(comboboxTester.combobox()).toHaveValue(''); + expect(comboboxTester.getCombobox()).toHaveValue(''); // Repeat with an option selected. await comboboxTester.toggleOptionSelection({option: 'Cat'}); await user.keyboard('s'); - options = comboboxTester.options(); + options = comboboxTester.getOptions(); expect(options).toHaveLength(1); expect(options[0]).toHaveTextContent('Create "Cats"'); @@ -674,7 +662,7 @@ describe('ComboBox', () => { await user.click(options[0]); } expect(onAction).toHaveBeenCalledTimes(2); - expect(comboboxTester.combobox()).toHaveValue('Cat'); + expect(comboboxTester.getCombobox()).toHaveValue('Cat'); }); it('should not close the combobox when clicking on a section header', async () => { @@ -729,7 +717,7 @@ describe('ComboBox', () => { expect(listbox).toBeVisible(); // Verify we can still interact with options - let options = comboboxTester.options(); + let options = comboboxTester.getOptions(); expect(options.length).toBeGreaterThan(0); // Click an option @@ -740,7 +728,7 @@ describe('ComboBox', () => { // Verify the combobox is closed and the value is updated expect(tree.queryByRole('listbox')).toBeNull(); - expect(comboboxTester.combobox()).toHaveValue('Apple'); + expect(comboboxTester.getCombobox()).toHaveValue('Apple'); }); it('should support multiple selection', async () => { @@ -760,26 +748,26 @@ describe('ComboBox', () => { let value = container.querySelector('.react-aria-ComboBoxValue'); expect(value).toHaveTextContent('No items selected'); - expect(comboboxTester.combobox().getAttribute('aria-describedby')).toContain(value.id); + expect(comboboxTester.getCombobox().getAttribute('aria-describedby')).toContain(value.id); - expect(comboboxTester.combobox()).toHaveValue(''); + expect(comboboxTester.getCombobox()).toHaveValue(''); await comboboxTester.open(); - let listbox = comboboxTester.listbox(); + let listbox = comboboxTester.getListbox(); expect(listbox).toHaveAttribute('aria-multiselectable', 'true'); - let options = comboboxTester.options(); + let options = comboboxTester.getOptions(); expect(options).toHaveLength(3); await comboboxTester.toggleOptionSelection({option: options[0]}); expect(options[0]).toHaveAttribute('aria-selected', 'true'); - expect(comboboxTester.combobox()).toHaveValue(''); - expect(comboboxTester.listbox()).toBeInTheDocument(); + expect(comboboxTester.getCombobox()).toHaveValue(''); + expect(comboboxTester.getListbox()).toBeInTheDocument(); expect(value).toHaveTextContent('Cat'); await comboboxTester.toggleOptionSelection({option: options[1]}); expect(options[1]).toHaveAttribute('aria-selected', 'true'); - expect(comboboxTester.combobox()).toHaveValue(''); - expect(comboboxTester.listbox()).toBeInTheDocument(); + expect(comboboxTester.getCombobox()).toHaveValue(''); + expect(comboboxTester.getListbox()).toBeInTheDocument(); expect(value).toHaveTextContent('Cat and Dog'); await comboboxTester.close(); @@ -790,7 +778,7 @@ describe('ComboBox', () => { expect(formData.getAll('combobox')).toEqual(['1', '2']); await user.click(document.querySelector('input[type="reset"]')); - expect(comboboxTester.combobox()).toHaveValue(''); + expect(comboboxTester.getCombobox()).toHaveValue(''); formData = new FormData(getByTestId('form')); expect(formData.getAll('combobox')).toEqual(['']); }); @@ -798,24 +786,29 @@ describe('ComboBox', () => { it('should support deselection if multiple selection is enabled', async () => { let onChange = jest.fn(); let {container} = render( - + ); let comboboxTester = testUtilUser.createTester('ComboBox', {root: container}); await comboboxTester.toggleOptionSelection({option: 'Cat'}); await comboboxTester.toggleOptionSelection({option: 'Dog'}); - expect(comboboxTester.options()[0]).toHaveAttribute('aria-selected', 'true'); - expect(comboboxTester.options()[1]).toHaveAttribute('aria-selected', 'true'); + expect(comboboxTester.getOptions()[0]).toHaveAttribute('aria-selected', 'true'); + expect(comboboxTester.getOptions()[1]).toHaveAttribute('aria-selected', 'true'); expect(onChange).toHaveBeenLastCalledWith(['1', '2']); await comboboxTester.toggleOptionSelection({option: 'Cat'}); - expect(comboboxTester.options()[0]).toHaveAttribute('aria-selected', 'false'); - expect(comboboxTester.options()[1]).toHaveAttribute('aria-selected', 'true'); + expect(comboboxTester.getOptions()[0]).toHaveAttribute('aria-selected', 'false'); + expect(comboboxTester.getOptions()[1]).toHaveAttribute('aria-selected', 'true'); expect(onChange).toHaveBeenLastCalledWith(['2']); await comboboxTester.toggleOptionSelection({option: 'Dog'}); - expect(comboboxTester.options()[0]).toHaveAttribute('aria-selected', 'false'); - expect(comboboxTester.options()[1]).toHaveAttribute('aria-selected', 'false'); + expect(comboboxTester.getOptions()[0]).toHaveAttribute('aria-selected', 'false'); + expect(comboboxTester.getOptions()[1]).toHaveAttribute('aria-selected', 'false'); expect(onChange).toHaveBeenLastCalledWith([]); await comboboxTester.close(); @@ -827,10 +820,10 @@ describe('ComboBox', () => { ); let comboboxTester = testUtilUser.createTester('ComboBox', {root: container}); - expect(comboboxTester.combobox()).toHaveValue(''); + expect(comboboxTester.getCombobox()).toHaveValue(''); await comboboxTester.open(); - let options = comboboxTester.options(); + let options = comboboxTester.getOptions(); expect(options[0]).toHaveAttribute('aria-selected', 'false'); expect(options[1]).toHaveAttribute('aria-selected', 'true'); expect(options[2]).toHaveAttribute('aria-selected', 'true'); @@ -851,7 +844,7 @@ describe('ComboBox', () => { ); let comboboxTester = testUtilUser.createTester('ComboBox', {root: container}); - let combobox = comboboxTester.combobox(); + let combobox = comboboxTester.getCombobox(); expect(combobox).toHaveValue('C'); await comboboxTester.open(); @@ -880,10 +873,10 @@ describe('ComboBox', () => { await user.tab(); await user.keyboard('Test'); - expect(comboboxTester.combobox()).toHaveValue('Test'); + expect(comboboxTester.getCombobox()).toHaveValue('Test'); await user.tab(); - expect(comboboxTester.combobox()).toHaveValue('Test'); + expect(comboboxTester.getCombobox()).toHaveValue('Test'); }); it.each(['{Escape}', '{Enter}', '{Tab}'])( @@ -904,12 +897,12 @@ describe('ComboBox', () => { await user.tab(); await user.keyboard('Den'); - expect(comboboxTester.combobox).toHaveValue('Den'); + expect(comboboxTester.getCombobox()).toHaveValue('Den'); await user.keyboard(key); expect(queryByRole('listbox')).toBeNull(); - expect(comboboxTester.combobox).toHaveValue('Den'); + expect(comboboxTester.getCombobox()).toHaveValue('Den'); expect(value).toHaveTextContent('Cat and Dog'); } ); @@ -969,7 +962,7 @@ describe('ComboBox', () => { ); let comboboxTester = testUtilUser.createTester('ComboBox', {root: container}); - let combobox = comboboxTester.combobox(); + let combobox = comboboxTester.getCombobox(); expect(combobox).toHaveAttribute('required'); expect(combobox.validity.valid).toBe(false); @@ -981,7 +974,7 @@ describe('ComboBox', () => { expect(container.querySelector('.react-aria-ComboBox')).toHaveAttribute('data-invalid'); await comboboxTester.open(); - let options = comboboxTester.options(); + let options = comboboxTester.getOptions(); await user.click(options[0]); act(() => combobox.blur()); @@ -995,7 +988,7 @@ describe('ComboBox', () => { expect(hiddenInputs[0]).toHaveAttribute('value', '1'); await comboboxTester.open(); - options = comboboxTester.options(); + options = comboboxTester.getOptions(); await user.click(options[0]); act(() => combobox.blur()); expect(combobox).toHaveAttribute('required'); @@ -1016,8 +1009,8 @@ describe('ComboBox', () => { act(() => { jest.runAllTimers(); }); - expect(comboboxTester.listbox()).toBeVisible(); - expect(comboboxTester.combobox()).toHaveFocus(); + expect(comboboxTester.getListbox()).toBeVisible(); + expect(comboboxTester.getCombobox()).toHaveFocus(); expect(onOpenChange).toHaveBeenCalledTimes(1); onOpenChange.mockClear(); @@ -1025,8 +1018,8 @@ describe('ComboBox', () => { act(() => { jest.runAllTimers(); }); - expect(comboboxTester.listbox()).toBeVisible(); - expect(comboboxTester.combobox()).toHaveFocus(); + expect(comboboxTester.getListbox()).toBeVisible(); + expect(comboboxTester.getCombobox()).toHaveFocus(); expect(onOpenChange).toHaveBeenCalledTimes(0); }); @@ -1038,7 +1031,7 @@ describe('ComboBox', () => { act(() => { jest.runAllTimers(); }); - expect(comboboxTester.listbox()).toBeVisible(); + expect(comboboxTester.getListbox()).toBeVisible(); expect(onOpenChange).toHaveBeenCalledTimes(1); onOpenChange.mockClear(); @@ -1046,8 +1039,8 @@ describe('ComboBox', () => { act(() => { jest.runAllTimers(); }); - expect(comboboxTester.listbox()).toBeNull(); - expect(comboboxTester.combobox()).toHaveFocus(); + expect(comboboxTester.getListbox()).toBeNull(); + expect(comboboxTester.getCombobox()).toHaveFocus(); expect(onOpenChange).toHaveBeenCalledTimes(1); onOpenChange.mockClear(); @@ -1055,8 +1048,8 @@ describe('ComboBox', () => { act(() => { jest.runAllTimers(); }); - expect(comboboxTester.listbox()).toBeVisible(); - expect(comboboxTester.combobox()).toHaveFocus(); + expect(comboboxTester.getListbox()).toBeVisible(); + expect(comboboxTester.getCombobox()).toHaveFocus(); expect(onOpenChange).toHaveBeenCalledTimes(1); }); diff --git a/packages/react-aria-components/test/Dialog.browser.test.tsx b/packages/react-aria-components/test/Dialog.browser.test.tsx index 7d215d0bff9..5b5b622accd 100644 --- a/packages/react-aria-components/test/Dialog.browser.test.tsx +++ b/packages/react-aria-components/test/Dialog.browser.test.tsx @@ -49,9 +49,9 @@ it.each` }); await tester.open(); - expect(tester.dialog()).not.toBeNull(); - expect(tester.dialog()!.contains(document.activeElement)).toBe(true); + expect(tester.getDialog()).not.toBeNull(); + expect(tester.getDialog()!.contains(document.activeElement)).toBe(true); await tester.close(); - expect(tester.dialog()).toBeNull(); + expect(tester.getDialog()).toBeNull(); }); diff --git a/packages/react-aria-components/test/Dialog.test.js b/packages/react-aria-components/test/Dialog.test.js index f0ee9f49479..9621e7c90d8 100644 --- a/packages/react-aria-components/test/Dialog.test.js +++ b/packages/react-aria-components/test/Dialog.test.js @@ -70,7 +70,7 @@ describe('Dialog', () => { let button = getByRole('button'); let dialogTester = testUtilUser.createTester('Dialog', {root: button, overlayType: 'modal'}); await dialogTester.open(); - let dialog = dialogTester.dialog(); + let dialog = dialogTester.getDialog(); expect(dialog).toHaveAttribute('role', 'alertdialog'); let heading = getByRole('heading'); expect(dialog).toHaveAttribute('aria-labelledby', heading.id); @@ -174,7 +174,7 @@ describe('Dialog', () => { await dialogTester.open(); expect(button).toHaveAttribute('data-pressed'); - let dialog = dialogTester.dialog(); + let dialog = dialogTester.getDialog(); let heading = getByRole('heading'); expect(dialog).toHaveAttribute('aria-labelledby', heading.id); expect(dialog).toHaveAttribute('data-test', 'dialog'); diff --git a/packages/react-aria-components/test/GridList.browser.test.tsx b/packages/react-aria-components/test/GridList.browser.test.tsx index e0912e0ecf4..d7b944e1f73 100644 --- a/packages/react-aria-components/test/GridList.browser.test.tsx +++ b/packages/react-aria-components/test/GridList.browser.test.tsx @@ -51,7 +51,7 @@ it.each` interactionType }); - let rows = tester.rows(); + let rows = tester.getRows(); await tester.toggleRowSelection({row: rows[5]}); expect(rows[5].getAttribute('aria-selected')).toBe('true'); expect(document.activeElement).toBe(rows[5]); diff --git a/packages/react-aria-components/test/GridList.test.js b/packages/react-aria-components/test/GridList.test.js index 39ab2d9cd2c..e9b99905cd2 100644 --- a/packages/react-aria-components/test/GridList.test.js +++ b/packages/react-aria-components/test/GridList.test.js @@ -145,9 +145,9 @@ describe('GridList', () => { let {getByRole} = renderGridList(); let gridListTester = testUtilUser.createTester('GridList', {root: getByRole('grid')}); - expect(gridListTester.gridlist()).toHaveAttribute('class', 'react-aria-GridList'); + expect(gridListTester.getGridlist()).toHaveAttribute('class', 'react-aria-GridList'); - for (let row of gridListTester.rows()) { + for (let row of gridListTester.getRows()) { expect(row).toHaveAttribute('class', 'react-aria-GridListItem'); } }); @@ -341,7 +341,7 @@ describe('GridList', () => { ); let gridListTester = testUtilUser.createTester('GridList', {root: getByRole('grid')}); - let row = gridListTester.rows()[0]; + let row = gridListTester.getRows()[0]; expect(row).not.toHaveAttribute('aria-selected', 'true'); expect(row).not.toHaveClass('selected'); expect(within(row).getByRole('checkbox')).not.toBeChecked(); @@ -361,17 +361,17 @@ describe('GridList', () => { let {getByRole} = renderGridList({selectionMode: 'multiple', escapeKeyBehavior: 'none'}); let gridListTester = testUtilUser.createTester('GridList', {root: getByRole('grid')}); - let row = gridListTester.rows()[0]; + let row = gridListTester.getRows()[0]; expect(within(row).getByRole('checkbox')).not.toBeChecked(); await gridListTester.toggleRowSelection({row: 0}); - expect(gridListTester.selectedRows()).toHaveLength(1); + expect(gridListTester.getSelectedRows()).toHaveLength(1); await gridListTester.toggleRowSelection({row: 1}); - expect(gridListTester.selectedRows()).toHaveLength(2); + expect(gridListTester.getSelectedRows()).toHaveLength(2); await user.keyboard('{Escape}'); - expect(gridListTester.selectedRows()).toHaveLength(2); + expect(gridListTester.getSelectedRows()).toHaveLength(2); }); it('should support disabled state', async () => { @@ -403,7 +403,7 @@ describe('GridList', () => { ); let gridListTester = testUtilUser.createTester('GridList', {root: getByRole('grid')}); - let rows = gridListTester.rows(); + let rows = gridListTester.getRows(); expect(rows[1]).toHaveAttribute('aria-disabled', 'true'); expect(within(rows[1]).getByRole('button')).toBeDisabled(); @@ -724,9 +724,9 @@ describe('GridList', () => { root: getByRole('grid'), interactionType: type }); - let rows = gridListTester.rows(); + let rows = gridListTester.getRows(); - for (let row of gridListTester.rows()) { + for (let row of gridListTester.getRows()) { let checkbox = within(row).queryByRole('checkbox'); expect(checkbox).toBeNull(); expect(row).toHaveAttribute('aria-selected', 'false'); @@ -746,8 +746,8 @@ describe('GridList', () => { expect(onSelectionChange).toHaveBeenCalledTimes(1); } expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual(new Set(['kangaroo'])); - expect(gridListTester.selectedRows()).toHaveLength(1); - expect(gridListTester.selectedRows()[0]).toBe(row2); + expect(gridListTester.getSelectedRows()).toHaveLength(1); + expect(gridListTester.getSelectedRows()[0]).toBe(row2); let row1 = rows[1]; await gridListTester.toggleRowSelection({row: row1, selectionBehavior: 'replace'}); @@ -761,8 +761,8 @@ describe('GridList', () => { expect(onSelectionChange).toHaveBeenCalledTimes(2); } expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual(new Set(['dog'])); - expect(gridListTester.selectedRows()).toHaveLength(1); - expect(gridListTester.selectedRows()[0]).toBe(row1); + expect(gridListTester.getSelectedRows()).toHaveLength(1); + expect(gridListTester.getSelectedRows()[0]).toBe(row1); await gridListTester.toggleRowSelection({row: row1, selectionBehavior: 'replace'}); expect(row1).toHaveAttribute('aria-selected', 'false'); @@ -775,7 +775,7 @@ describe('GridList', () => { expect(onSelectionChange).toHaveBeenCalledTimes(3); } expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual(new Set([])); - expect(gridListTester.selectedRows()).toHaveLength(0); + expect(gridListTester.getSelectedRows()).toHaveLength(0); }); it('should perform toggle selection in highlight mode when using modifier keys', async () => { @@ -793,9 +793,9 @@ describe('GridList', () => { root: getByRole('grid'), interactionType: type }); - let rows = gridListTester.rows(); + let rows = gridListTester.getRows(); - for (let row of gridListTester.rows()) { + for (let row of gridListTester.getRows()) { let checkbox = within(row).queryByRole('checkbox'); expect(checkbox).toBeNull(); expect(row).toHaveAttribute('aria-selected', 'false'); @@ -813,13 +813,13 @@ describe('GridList', () => { expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual( new Set(['cat', 'kangaroo']) ); - expect(gridListTester.selectedRows()).toHaveLength(2); - expect(gridListTester.selectedRows()[1]).toBe(row2); + expect(gridListTester.getSelectedRows()).toHaveLength(2); + expect(gridListTester.getSelectedRows()[1]).toBe(row2); } else { expect(onSelectionChange).toHaveBeenCalledTimes(1); expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual(new Set(['kangaroo'])); - expect(gridListTester.selectedRows()).toHaveLength(1); - expect(gridListTester.selectedRows()[0]).toBe(row2); + expect(gridListTester.getSelectedRows()).toHaveLength(1); + expect(gridListTester.getSelectedRows()[0]).toBe(row2); } let row1 = rows[1]; @@ -833,17 +833,17 @@ describe('GridList', () => { expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual( new Set(['cat', 'dog', 'kangaroo']) ); - expect(gridListTester.selectedRows()).toHaveLength(3); - expect(gridListTester.selectedRows()[1]).toBe(row1); - expect(gridListTester.selectedRows()[2]).toBe(row2); + expect(gridListTester.getSelectedRows()).toHaveLength(3); + expect(gridListTester.getSelectedRows()[1]).toBe(row1); + expect(gridListTester.getSelectedRows()[2]).toBe(row2); } else { expect(onSelectionChange).toHaveBeenCalledTimes(2); expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual( new Set(['dog', 'kangaroo']) ); - expect(gridListTester.selectedRows()).toHaveLength(2); - expect(gridListTester.selectedRows()[0]).toBe(row1); - expect(gridListTester.selectedRows()[1]).toBe(row2); + expect(gridListTester.getSelectedRows()).toHaveLength(2); + expect(gridListTester.getSelectedRows()[0]).toBe(row1); + expect(gridListTester.getSelectedRows()[1]).toBe(row2); } // With modifier key, you should be able to deselect on press of the same row @@ -857,13 +857,13 @@ describe('GridList', () => { expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual( new Set(['cat', 'kangaroo']) ); - expect(gridListTester.selectedRows()).toHaveLength(2); - expect(gridListTester.selectedRows()[1]).toBe(row2); + expect(gridListTester.getSelectedRows()).toHaveLength(2); + expect(gridListTester.getSelectedRows()[1]).toBe(row2); } else { expect(onSelectionChange).toHaveBeenCalledTimes(3); expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual(new Set(['kangaroo'])); - expect(gridListTester.selectedRows()).toHaveLength(1); - expect(gridListTester.selectedRows()[0]).toBe(row2); + expect(gridListTester.getSelectedRows()).toHaveLength(1); + expect(gridListTester.getSelectedRows()[0]).toBe(row2); } }); @@ -882,9 +882,9 @@ describe('GridList', () => { root: getByRole('grid'), interactionType: type }); - let rows = gridListTester.rows(); + let rows = gridListTester.getRows(); - for (let row of gridListTester.rows()) { + for (let row of gridListTester.getRows()) { let checkbox = within(row).queryByRole('checkbox'); expect(checkbox).toBeNull(); expect(row).toHaveAttribute('aria-selected', 'false'); @@ -903,8 +903,8 @@ describe('GridList', () => { expect(onSelectionChange).toHaveBeenCalledTimes(1); } expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual(new Set(['kangaroo'])); - expect(gridListTester.selectedRows()).toHaveLength(1); - expect(gridListTester.selectedRows()[0]).toBe(row2); + expect(gridListTester.getSelectedRows()).toHaveLength(1); + expect(gridListTester.getSelectedRows()[0]).toBe(row2); let row1 = rows[1]; await gridListTester.toggleRowSelection({row: row1}); @@ -919,8 +919,8 @@ describe('GridList', () => { expect(onSelectionChange).toHaveBeenCalledTimes(2); } expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual(new Set(['dog'])); - expect(gridListTester.selectedRows()).toHaveLength(1); - expect(gridListTester.selectedRows()[0]).toBe(row1); + expect(gridListTester.getSelectedRows()).toHaveLength(1); + expect(gridListTester.getSelectedRows()[0]).toBe(row1); // pressing without modifier keys won't deselect the row await gridListTester.toggleRowSelection({row: row1}); @@ -931,7 +931,7 @@ describe('GridList', () => { } else { expect(onSelectionChange).toHaveBeenCalledTimes(2); } - expect(gridListTester.selectedRows()).toHaveLength(1); + expect(gridListTester.getSelectedRows()).toHaveLength(1); } else { // touch always behaves as toggle expect(row1).toHaveAttribute('aria-selected', 'true'); @@ -940,16 +940,16 @@ describe('GridList', () => { expect(row2).toHaveAttribute('data-selected', 'true'); expect(onSelectionChange).toHaveBeenCalledTimes(2); expect(new Set(onSelectionChange.mock.calls[1][0])).toEqual(new Set(['dog', 'kangaroo'])); - expect(gridListTester.selectedRows()).toHaveLength(2); - expect(gridListTester.selectedRows()[0]).toBe(row1); + expect(gridListTester.getSelectedRows()).toHaveLength(2); + expect(gridListTester.getSelectedRows()[0]).toBe(row1); await gridListTester.toggleRowSelection({row: row1}); expect(row1).toHaveAttribute('aria-selected', 'false'); expect(row1).not.toHaveAttribute('data-selected'); expect(onSelectionChange).toHaveBeenCalledTimes(3); expect(new Set(onSelectionChange.mock.calls[2][0])).toEqual(new Set(['kangaroo'])); - expect(gridListTester.selectedRows()).toHaveLength(1); - expect(gridListTester.selectedRows()[0]).toBe(row2); + expect(gridListTester.getSelectedRows()).toHaveLength(1); + expect(gridListTester.getSelectedRows()[0]).toBe(row2); } }); }); @@ -1566,7 +1566,7 @@ describe('GridList', () => { let tree = render(); let gridListTester = testUtilUser.createTester('GridList', {root: tree.getByRole('grid')}); - let rows = gridListTester.rows(); + let rows = gridListTester.getRows(); expect(rows).toHaveLength(4); let loaderRow = rows[3]; expect(loaderRow).toHaveTextContent('Loading...'); @@ -1579,7 +1579,7 @@ describe('GridList', () => { let tree = render(); let gridListTester = testUtilUser.createTester('GridList', {root: tree.getByRole('grid')}); - let rows = gridListTester.rows(); + let rows = gridListTester.getRows(); expect(rows).toHaveLength(3); expect(tree.queryByText('Loading...')).toBeFalsy(); expect(tree.getByTestId('loadMoreSentinel')).toBeInTheDocument(); @@ -1589,7 +1589,7 @@ describe('GridList', () => { let tree = render(); let gridListTester = testUtilUser.createTester('GridList', {root: tree.getByRole('grid')}); - let rows = gridListTester.rows(); + let rows = gridListTester.getRows(); expect(rows).toHaveLength(1); expect(rows[0]).toHaveTextContent('empty state'); expect(tree.queryByText('Loading...')).toBeFalsy(); @@ -1597,7 +1597,7 @@ describe('GridList', () => { // Even if the gridlist is empty, providing isLoading will render the loader tree.rerender(); - rows = gridListTester.rows(); + rows = gridListTester.getRows(); expect(rows).toHaveLength(2); expect(rows[1]).toHaveTextContent('empty state'); expect(tree.queryByText('Loading...')).toBeTruthy(); @@ -1681,7 +1681,7 @@ describe('GridList', () => { let tree = render(); let gridListTester = testUtilUser.createTester('GridList', {root: tree.getByRole('grid')}); - let rows = gridListTester.rows(); + let rows = gridListTester.getRows(); expect(rows).toHaveLength(8); let loaderRow = rows[7]; expect(loaderRow).toHaveTextContent('Loading...'); @@ -1700,35 +1700,35 @@ describe('GridList', () => { let tree = render(); let gridListTester = testUtilUser.createTester('GridList', {root: tree.getByRole('grid')}); - let rows = gridListTester.rows(); + let rows = gridListTester.getRows(); expect(rows).toHaveLength(7); - expect(within(gridListTester.gridlist()).queryByText('Loading...')).toBeFalsy(); + expect(within(gridListTester.getGridlist()).queryByText('Loading...')).toBeFalsy(); - let sentinel = within(gridListTester.gridlist()).getByTestId('loadMoreSentinel'); + let sentinel = within(gridListTester.getGridlist()).getByTestId('loadMoreSentinel'); let sentinelParentStyles = sentinel.parentElement.parentElement.style; expect(sentinelParentStyles.top).toBe('1250px'); expect(sentinelParentStyles.height).toBe('0px'); expect(sentinel.parentElement).toHaveAttribute('inert'); tree.rerender(); - rows = gridListTester.rows(); + rows = gridListTester.getRows(); expect(rows).toHaveLength(1); let emptyStateRow = rows[0]; expect(emptyStateRow).toHaveTextContent('empty state'); - expect(within(gridListTester.gridlist()).queryByText('Loading...')).toBeFalsy(); + expect(within(gridListTester.getGridlist()).queryByText('Loading...')).toBeFalsy(); - sentinel = within(gridListTester.gridlist()).getByTestId('loadMoreSentinel'); + sentinel = within(gridListTester.getGridlist()).getByTestId('loadMoreSentinel'); sentinelParentStyles = sentinel.parentElement.parentElement.style; expect(sentinelParentStyles.top).toBe('0px'); expect(sentinelParentStyles.height).toBe('0px'); tree.rerender(); - rows = gridListTester.rows(); + rows = gridListTester.getRows(); expect(rows).toHaveLength(1); emptyStateRow = rows[0]; expect(emptyStateRow).toHaveTextContent('loading'); - sentinel = within(gridListTester.gridlist()).getByTestId('loadMoreSentinel'); + sentinel = within(gridListTester.getGridlist()).getByTestId('loadMoreSentinel'); sentinelParentStyles = sentinel.parentElement.parentElement.style; expect(sentinelParentStyles.top).toBe('0px'); expect(sentinelParentStyles.height).toBe('0px'); @@ -1738,7 +1738,7 @@ describe('GridList', () => { let tree = render(); let gridListTester = testUtilUser.createTester('GridList', {root: tree.getByRole('grid')}); - let rows = gridListTester.rows(); + let rows = gridListTester.getRows(); expect(rows).toHaveLength(1); let loaderRow = rows[0]; @@ -1749,15 +1749,15 @@ describe('GridList', () => { } tree.rerender(); - rows = gridListTester.rows(); + rows = gridListTester.getRows(); expect(rows).toHaveLength(7); - expect(within(gridListTester.gridlist()).queryByText('loading')).toBeFalsy(); + expect(within(gridListTester.getGridlist()).queryByText('loading')).toBeFalsy(); for (let [index, row] of rows.entries()) { expect(row).toHaveAttribute('aria-rowindex', `${index + 1}`); } tree.rerender(); - rows = gridListTester.rows(); + rows = gridListTester.getRows(); expect(rows).toHaveLength(8); loaderRow = rows[7]; expect(loaderRow).not.toHaveAttribute('aria-rowindex'); diff --git a/packages/react-aria-components/test/ListBox.browser.test.tsx b/packages/react-aria-components/test/ListBox.browser.test.tsx index 2956d17777d..f8b99c311c9 100644 --- a/packages/react-aria-components/test/ListBox.browser.test.tsx +++ b/packages/react-aria-components/test/ListBox.browser.test.tsx @@ -53,7 +53,7 @@ it.each` interactionType }); - let options = tester.options(); + let options = tester.getOptions(); await tester.toggleOptionSelection({option: options[5]}); expect(options[5].getAttribute('aria-selected')).toBe('true'); expect(document.activeElement).toBe(options[5]); diff --git a/packages/react-aria-components/test/ListBox.test.js b/packages/react-aria-components/test/ListBox.test.js index c42836920b7..8f9bcf937e7 100644 --- a/packages/react-aria-components/test/ListBox.test.js +++ b/packages/react-aria-components/test/ListBox.test.js @@ -111,13 +111,13 @@ describe('ListBox', () => { ); let listboxTester = testUtilUser.createTester('ListBox', {root: getByRole('listbox')}); - expect(listboxTester.listbox()).toHaveAttribute('data-rac'); - let sections = listboxTester.sections(); + expect(listboxTester.getListbox()).toHaveAttribute('data-rac'); + let sections = listboxTester.getSections(); for (let section of sections) { expect(section).toHaveAttribute('data-rac'); } - let options = listboxTester.options(); + let options = listboxTester.getOptions(); for (let option of options) { expect(option).toHaveAttribute('data-rac'); } @@ -587,7 +587,7 @@ describe('ListBox', () => { ); let listboxTester = testUtilUser.createTester('ListBox', {root: getByRole('listbox')}); - let option = listboxTester.options()[0]; + let option = listboxTester.getOptions()[0]; expect(option).not.toHaveAttribute('aria-selected', 'true'); expect(option).not.toHaveClass('selected'); @@ -649,7 +649,7 @@ describe('ListBox', () => { ); let listboxTester = testUtilUser.createTester('ListBox', {root: getByRole('listbox')}); - let options = listboxTester.options(); + let options = listboxTester.getOptions(); await listboxTester.triggerOptionAction({option: options[0], interactionType}); expect(onAction).toHaveBeenCalledTimes(1); }); @@ -669,14 +669,14 @@ describe('ListBox', () => { ); let listboxTester = testUtilUser.createTester('ListBox', {root: getByRole('listbox')}); - let options = listboxTester.options(); + let options = listboxTester.getOptions(); await listboxTester.triggerOptionAction({option: options[0]}); - let selectedOptions = listboxTester.selectedOptions(); + let selectedOptions = listboxTester.getSelectedOptions(); expect(selectedOptions).toHaveLength(1); expect(onAction).not.toHaveBeenCalled(); await listboxTester.triggerOptionAction({option: options[1], needsDoubleClick: true}); - selectedOptions = listboxTester.selectedOptions(); + selectedOptions = listboxTester.getSelectedOptions(); expect(selectedOptions).toHaveLength(1); expect(onAction).toHaveBeenCalledTimes(1); }); @@ -695,7 +695,7 @@ describe('ListBox', () => { root: getByRole('listbox'), interactionType: type }); - let options = listboxTester.options(); + let options = listboxTester.getOptions(); expect(onSelectionChange).toHaveBeenCalledTimes(0); let option2 = options[2]; @@ -712,8 +712,8 @@ describe('ListBox', () => { expect(onSelectionChange).toHaveBeenCalledTimes(1); } expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual(new Set(['kangaroo'])); - expect(listboxTester.selectedOptions()).toHaveLength(1); - expect(listboxTester.selectedOptions()[0]).toBe(option2); + expect(listboxTester.getSelectedOptions()).toHaveLength(1); + expect(listboxTester.getSelectedOptions()[0]).toBe(option2); let option1 = options[1]; await listboxTester.toggleOptionSelection({option: option1, selectionBehavior: 'replace'}); @@ -727,8 +727,8 @@ describe('ListBox', () => { expect(onSelectionChange).toHaveBeenCalledTimes(2); } expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual(new Set(['dog'])); - expect(listboxTester.selectedOptions()).toHaveLength(1); - expect(listboxTester.selectedOptions()[0]).toBe(option1); + expect(listboxTester.getSelectedOptions()).toHaveLength(1); + expect(listboxTester.getSelectedOptions()[0]).toBe(option1); await listboxTester.toggleOptionSelection({option: option1, selectionBehavior: 'replace'}); expect(option1).toHaveAttribute('aria-selected', 'false'); @@ -741,7 +741,7 @@ describe('ListBox', () => { expect(onSelectionChange).toHaveBeenCalledTimes(3); } expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual(new Set([])); - expect(listboxTester.selectedOptions()).toHaveLength(0); + expect(listboxTester.getSelectedOptions()).toHaveLength(0); }); it('should perform toggle selection in highlight mode when using modifier keys', async () => { @@ -754,7 +754,7 @@ describe('ListBox', () => { root: getByRole('listbox'), interactionType: type }); - let options = listboxTester.options(); + let options = listboxTester.getOptions(); let option2 = options[2]; await listboxTester.toggleOptionSelection({ @@ -769,13 +769,13 @@ describe('ListBox', () => { expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual( new Set(['cat', 'kangaroo']) ); - expect(listboxTester.selectedOptions()).toHaveLength(2); - expect(listboxTester.selectedOptions()[1]).toBe(option2); + expect(listboxTester.getSelectedOptions()).toHaveLength(2); + expect(listboxTester.getSelectedOptions()[1]).toBe(option2); } else { expect(onSelectionChange).toHaveBeenCalledTimes(1); expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual(new Set(['kangaroo'])); - expect(listboxTester.selectedOptions()).toHaveLength(1); - expect(listboxTester.selectedOptions()[0]).toBe(option2); + expect(listboxTester.getSelectedOptions()).toHaveLength(1); + expect(listboxTester.getSelectedOptions()[0]).toBe(option2); } let option1 = options[1]; @@ -789,17 +789,17 @@ describe('ListBox', () => { expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual( new Set(['cat', 'dog', 'kangaroo']) ); - expect(listboxTester.selectedOptions()).toHaveLength(3); - expect(listboxTester.selectedOptions()[1]).toBe(option1); - expect(listboxTester.selectedOptions()[2]).toBe(option2); + expect(listboxTester.getSelectedOptions()).toHaveLength(3); + expect(listboxTester.getSelectedOptions()[1]).toBe(option1); + expect(listboxTester.getSelectedOptions()[2]).toBe(option2); } else { expect(onSelectionChange).toHaveBeenCalledTimes(2); expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual( new Set(['dog', 'kangaroo']) ); - expect(listboxTester.selectedOptions()).toHaveLength(2); - expect(listboxTester.selectedOptions()[0]).toBe(option1); - expect(listboxTester.selectedOptions()[1]).toBe(option2); + expect(listboxTester.getSelectedOptions()).toHaveLength(2); + expect(listboxTester.getSelectedOptions()[0]).toBe(option1); + expect(listboxTester.getSelectedOptions()[1]).toBe(option2); } // With modifier key, you should be able to deselect on press of the same row @@ -813,13 +813,13 @@ describe('ListBox', () => { expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual( new Set(['cat', 'kangaroo']) ); - expect(listboxTester.selectedOptions()).toHaveLength(2); - expect(listboxTester.selectedOptions()[1]).toBe(option2); + expect(listboxTester.getSelectedOptions()).toHaveLength(2); + expect(listboxTester.getSelectedOptions()[1]).toBe(option2); } else { expect(onSelectionChange).toHaveBeenCalledTimes(3); expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual(new Set(['kangaroo'])); - expect(listboxTester.selectedOptions()).toHaveLength(1); - expect(listboxTester.selectedOptions()[0]).toBe(option2); + expect(listboxTester.getSelectedOptions()).toHaveLength(1); + expect(listboxTester.getSelectedOptions()[0]).toBe(option2); } }); @@ -833,7 +833,7 @@ describe('ListBox', () => { root: getByRole('listbox'), interactionType: type }); - let options = listboxTester.options(); + let options = listboxTester.getOptions(); let option2 = options[2]; await listboxTester.toggleOptionSelection({option: 'Kangaroo'}); @@ -846,8 +846,8 @@ describe('ListBox', () => { expect(onSelectionChange).toHaveBeenCalledTimes(1); } expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual(new Set(['kangaroo'])); - expect(listboxTester.selectedOptions()).toHaveLength(1); - expect(listboxTester.selectedOptions()[0]).toBe(option2); + expect(listboxTester.getSelectedOptions()).toHaveLength(1); + expect(listboxTester.getSelectedOptions()[0]).toBe(option2); let option1 = options[1]; await listboxTester.toggleOptionSelection({option: option1}); @@ -862,8 +862,8 @@ describe('ListBox', () => { expect(onSelectionChange).toHaveBeenCalledTimes(2); } expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual(new Set(['dog'])); - expect(listboxTester.selectedOptions()).toHaveLength(1); - expect(listboxTester.selectedOptions()[0]).toBe(option1); + expect(listboxTester.getSelectedOptions()).toHaveLength(1); + expect(listboxTester.getSelectedOptions()[0]).toBe(option1); // pressing without modifier keys won't deselect the row await listboxTester.toggleOptionSelection({option: option1}); expect(option1).toHaveAttribute('aria-selected', 'true'); @@ -873,7 +873,7 @@ describe('ListBox', () => { } else { expect(onSelectionChange).toHaveBeenCalledTimes(2); } - expect(listboxTester.selectedOptions()).toHaveLength(1); + expect(listboxTester.getSelectedOptions()).toHaveLength(1); } else { // touch always behaves as toggle expect(option1).toHaveAttribute('aria-selected', 'true'); @@ -882,16 +882,16 @@ describe('ListBox', () => { expect(option2).toHaveAttribute('data-selected', 'true'); expect(onSelectionChange).toHaveBeenCalledTimes(2); expect(new Set(onSelectionChange.mock.calls[1][0])).toEqual(new Set(['dog', 'kangaroo'])); - expect(listboxTester.selectedOptions()).toHaveLength(2); - expect(listboxTester.selectedOptions()[0]).toBe(option1); + expect(listboxTester.getSelectedOptions()).toHaveLength(2); + expect(listboxTester.getSelectedOptions()[0]).toBe(option1); await listboxTester.toggleOptionSelection({option: option1}); expect(option1).toHaveAttribute('aria-selected', 'false'); expect(option1).not.toHaveAttribute('data-selected'); expect(onSelectionChange).toHaveBeenCalledTimes(3); expect(new Set(onSelectionChange.mock.calls[2][0])).toEqual(new Set(['kangaroo'])); - expect(listboxTester.selectedOptions()).toHaveLength(1); - expect(listboxTester.selectedOptions()[0]).toBe(option2); + expect(listboxTester.getSelectedOptions()).toHaveLength(1); + expect(listboxTester.getSelectedOptions()[0]).toBe(option2); } }); }); @@ -918,21 +918,21 @@ describe('ListBox', () => { interactionType: 'touch' }); - await listboxTester.toggleOptionSelection({option: listboxTester.options()[0]}); - expect(listboxTester.selectedOptions()).toHaveLength(0); + await listboxTester.toggleOptionSelection({option: listboxTester.getOptions()[0]}); + expect(listboxTester.getSelectedOptions()).toHaveLength(0); expect(onAction).toHaveBeenCalledTimes(1); await listboxTester.toggleOptionSelection({ - option: listboxTester.options()[0], + option: listboxTester.getOptions()[0], needsLongPress: true }); - expect(listboxTester.selectedOptions()).toHaveLength(1); - expect(listboxTester.selectedOptions()[0]).toBe(listboxTester.options()[0]); + expect(listboxTester.getSelectedOptions()).toHaveLength(1); + expect(listboxTester.getSelectedOptions()[0]).toBe(listboxTester.getOptions()[0]); expect(onAction).toHaveBeenCalledTimes(1); - await listboxTester.toggleOptionSelection({option: listboxTester.options()[1]}); - expect(listboxTester.selectedOptions()).toHaveLength(2); - expect(listboxTester.selectedOptions()[1]).toBe(listboxTester.options()[1]); + await listboxTester.toggleOptionSelection({option: listboxTester.getOptions()[1]}); + expect(listboxTester.getSelectedOptions()).toHaveLength(2); + expect(listboxTester.getSelectedOptions()[1]).toBe(listboxTester.getOptions()[1]); }); }); @@ -1233,7 +1233,7 @@ describe('ListBox', () => { interactionType: 'keyboard', layout: 'grid' }); - let options = listboxTester.options(); + let options = listboxTester.getOptions(); await listboxTester.toggleOptionSelection({option: options[5]}); expect(options[5]).toHaveAttribute('aria-selected', 'true'); @@ -1329,7 +1329,7 @@ describe('ListBox', () => { let {getByRole} = renderListbox({selectionMode: 'multiple', escapeKeyBehavior: 'none'}); let listboxTester = testUtilUser.createTester('ListBox', {root: getByRole('listbox')}); - let option = listboxTester.options()[0]; + let option = listboxTester.getOptions()[0]; expect(option).not.toHaveAttribute('aria-selected', 'true'); expect(option).not.toHaveClass('selected'); @@ -2044,7 +2044,7 @@ describe('ListBox', () => { let tree = render(); let listboxTester = testUtilUser.createTester('ListBox', {root: tree.getByRole('listbox')}); - let options = listboxTester.options(); + let options = listboxTester.getOptions(); expect(options).toHaveLength(4); let loaderRow = options[3]; expect(loaderRow).toHaveTextContent('Loading...'); @@ -2057,7 +2057,7 @@ describe('ListBox', () => { let tree = render(); let listboxTester = testUtilUser.createTester('ListBox', {root: tree.getByRole('listbox')}); - let options = listboxTester.options(); + let options = listboxTester.getOptions(); expect(options).toHaveLength(3); expect(tree.queryByText('Loading...')).toBeFalsy(); expect(tree.getByTestId('loadMoreSentinel')).toBeInTheDocument(); @@ -2067,7 +2067,7 @@ describe('ListBox', () => { let tree = render(); let listboxTester = testUtilUser.createTester('ListBox', {root: tree.getByRole('listbox')}); - let options = listboxTester.options(); + let options = listboxTester.getOptions(); expect(options).toHaveLength(1); expect(options[0]).toHaveTextContent('empty state'); expect(tree.queryByText('Loading...')).toBeFalsy(); @@ -2075,7 +2075,7 @@ describe('ListBox', () => { // Even if the listbox is empty, providing isLoading will render the loader tree.rerender(); - options = listboxTester.options(); + options = listboxTester.getOptions(); expect(options).toHaveLength(2); expect(options[1]).toHaveTextContent('empty state'); expect(tree.queryByText('Loading...')).toBeTruthy(); @@ -2162,7 +2162,7 @@ describe('ListBox', () => { it('should always render the sentinel even when virtualized', () => { let tree = render(); let listboxTester = testUtilUser.createTester('ListBox', {root: tree.getByRole('listbox')}); - let options = listboxTester.options(); + let options = listboxTester.getOptions(); expect(options).toHaveLength(8); let loaderRow = options[7]; expect(loaderRow).toHaveTextContent('Loading...'); @@ -2185,31 +2185,31 @@ describe('ListBox', () => { it.skip('should not reserve room for the loader if isLoading is false', () => { let tree = render(); let listboxTester = testUtilUser.createTester('ListBox', {root: tree.getByRole('listbox')}); - let options = listboxTester.options(); + let options = listboxTester.getOptions(); expect(options).toHaveLength(7); - expect(within(listboxTester.listbox()).queryByText('Loading...')).toBeFalsy(); + expect(within(listboxTester.getListbox()).queryByText('Loading...')).toBeFalsy(); - let sentinel = within(listboxTester.listbox()).getByTestId('loadMoreSentinel'); + let sentinel = within(listboxTester.getListbox()).getByTestId('loadMoreSentinel'); let sentinelParentStyles = sentinel.parentElement.parentElement.style; expect(sentinelParentStyles.top).toBe('1250px'); expect(sentinelParentStyles.height).toBe('0px'); expect(sentinel.parentElement).toHaveAttribute('inert'); tree.rerender(); - options = listboxTester.options(); + options = listboxTester.getOptions(); expect(options).toHaveLength(1); let emptyStateRow = options[0]; expect(emptyStateRow).toHaveTextContent('empty state'); - expect(within(listboxTester.listbox()).queryByText('Loading...')).toBeFalsy(); + expect(within(listboxTester.getListbox()).queryByText('Loading...')).toBeFalsy(); - sentinel = within(listboxTester.listbox()).getByTestId('loadMoreSentinel'); + sentinel = within(listboxTester.getListbox()).getByTestId('loadMoreSentinel'); sentinelParentStyles = sentinel.parentElement.parentElement.style; expect(sentinelParentStyles.top).toBe('0px'); expect(sentinelParentStyles.height).toBe('0px'); // Setting isLoading will render the loader even if the list is empty. tree.rerender(); - options = listboxTester.options(); + options = listboxTester.getOptions(); expect(options).toHaveLength(2); emptyStateRow = options[1]; expect(emptyStateRow).toHaveTextContent('empty state'); @@ -2217,7 +2217,7 @@ describe('ListBox', () => { let loadingRow = options[0]; expect(loadingRow).toHaveTextContent('Loading...'); - sentinel = within(listboxTester.listbox()).getByTestId('loadMoreSentinel'); + sentinel = within(listboxTester.getListbox()).getByTestId('loadMoreSentinel'); sentinelParentStyles = sentinel.parentElement.parentElement.style; expect(sentinelParentStyles.top).toBe('0px'); expect(sentinelParentStyles.height).toBe('30px'); diff --git a/packages/react-aria-components/test/Menu.test.tsx b/packages/react-aria-components/test/Menu.test.tsx index b54487ed42e..938dec20a83 100644 --- a/packages/react-aria-components/test/Menu.test.tsx +++ b/packages/react-aria-components/test/Menu.test.tsx @@ -1207,18 +1207,18 @@ describe('Menu', () => { interactionType: 'keyboard' }); - expect(menuTester.trigger()).not.toHaveAttribute('data-pressed'); + expect(menuTester.getTrigger()).not.toHaveAttribute('data-pressed'); await menuTester.open(); - expect(menuTester.trigger()).toHaveAttribute('data-pressed'); + expect(menuTester.getTrigger()).toHaveAttribute('data-pressed'); - expect(menuTester.options()).toHaveLength(5); - expect(menuTester.menu()).toBeInTheDocument(); + expect(menuTester.getOptions()).toHaveLength(5); + expect(menuTester.getMenu()).toBeInTheDocument(); - let popover = menuTester.menu()?.closest('.react-aria-Popover'); + let popover = menuTester.getMenu()?.closest('.react-aria-Popover'); expect(popover).toBeInTheDocument(); expect(popover).toHaveAttribute('data-trigger', 'MenuTrigger'); - let triggerItem = menuTester.submenuTriggers()[0]; + let triggerItem = menuTester.getSubmenuTriggers()[0]; expect(triggerItem).toHaveTextContent('Share…'); expect(triggerItem).toHaveAttribute('aria-haspopup', 'menu'); expect(triggerItem).toHaveAttribute('aria-expanded', 'false'); @@ -1234,26 +1234,26 @@ describe('Menu', () => { expect(triggerItem).toHaveAttribute('data-hovered', 'true'); expect(triggerItem).toHaveAttribute('aria-expanded', 'true'); expect(triggerItem).toHaveAttribute('data-open', 'true'); - expect(submenuTester?.menu()).toBeInTheDocument(); - expect(submenuTester?.options()).toHaveLength(3); + expect(submenuTester?.getMenu()).toBeInTheDocument(); + expect(submenuTester?.getOptions()).toHaveLength(3); // Open the nested submenu let nestedSubmenu = await submenuTester?.openSubmenu({submenuTrigger: 'Email…'}); act(() => { jest.runAllTimers(); }); - expect(nestedSubmenu?.menu()).toBeInTheDocument(); - expect(document.activeElement).toBe(nestedSubmenu?.options()[0]); + expect(nestedSubmenu?.getMenu()).toBeInTheDocument(); + expect(document.activeElement).toBe(nestedSubmenu?.getOptions()[0]); await user.keyboard('{Escape}'); act(() => { jest.runAllTimers(); }); - expect(nestedSubmenu?.menu()).not.toBeInTheDocument(); - expect(submenuTester?.menu()).toBeInTheDocument(); - expect(menuTester.menu()).toBeInTheDocument(); - expect(document.activeElement).toBe(nestedSubmenu?.trigger()); + expect(nestedSubmenu?.getMenu()).not.toBeInTheDocument(); + expect(submenuTester?.getMenu()).toBeInTheDocument(); + expect(menuTester.getMenu()).toBeInTheDocument(); + expect(document.activeElement).toBe(nestedSubmenu?.getTrigger()); }); it('should not close the menu when clicking on a element within the submenu tree', async () => { let onAction = jest.fn(); @@ -1378,7 +1378,7 @@ describe('Menu', () => { await menuTester.open(); expect(button).toHaveAttribute('data-pressed'); - let groups = menuTester.sections(); + let groups = menuTester.getSections(); expect(groups).toHaveLength(2); expect(groups[0]).toHaveClass('react-aria-MenuSection'); @@ -1394,24 +1394,24 @@ describe('Menu', () => { 'Settings' ); - let menu = menuTester.menu()!; + let menu = menuTester.getMenu()!; expect(getAllByRole('menuitem')).toHaveLength(7); let popover = menu.closest('.react-aria-Popover'); expect(popover).toBeInTheDocument(); expect(popover).toHaveAttribute('data-trigger', 'MenuTrigger'); - let submenuTriggers = menuTester.submenuTriggers(); + let submenuTriggers = menuTester.getSubmenuTriggers(); expect(submenuTriggers).toHaveLength(1); // Open the submenu let submenuUtil = (await menuTester.openSubmenu({submenuTrigger: 'Share…'}))!; - let submenu = submenuUtil.menu(); + let submenu = submenuUtil.getMenu(); expect(submenu).toBeInTheDocument(); - let submenuItems = submenuUtil.options(); + let submenuItems = submenuUtil.getOptions(); expect(submenuItems).toHaveLength(6); - let groupsInSubmenu = submenuUtil.sections(); + let groupsInSubmenu = submenuUtil.getSections(); expect(groupsInSubmenu).toHaveLength(2); expect(groupsInSubmenu[0]).toHaveClass('react-aria-MenuSection'); @@ -1474,17 +1474,17 @@ describe('Menu', () => { ); let menuTester = testUtilUser.createTester('Menu', {root: getByRole('button')}); - expect(menuTester.trigger()).not.toHaveAttribute('data-pressed'); + expect(menuTester.getTrigger()).not.toHaveAttribute('data-pressed'); await menuTester.open(); - expect(menuTester.trigger()).toHaveAttribute('data-pressed'); - expect(menuTester.options()).toHaveLength(5); + expect(menuTester.getTrigger()).toHaveAttribute('data-pressed'); + expect(menuTester.getOptions()).toHaveLength(5); - let popover = menuTester.menu()?.closest('.react-aria-Popover'); + let popover = menuTester.getMenu()?.closest('.react-aria-Popover'); expect(popover).toBeInTheDocument(); expect(popover).toHaveAttribute('data-trigger', 'MenuTrigger'); - let triggerItem = menuTester.submenuTriggers()[0]; + let triggerItem = menuTester.getSubmenuTriggers()[0]; expect(triggerItem).toHaveTextContent('Share…'); expect(triggerItem).toHaveAttribute('aria-haspopup', 'menu'); expect(triggerItem).toHaveAttribute('aria-expanded', 'false'); @@ -1561,7 +1561,7 @@ describe('Menu', () => { let menuTester = testUtilUser.createTester('Menu', {root: getByRole('button')}); await menuTester.open(); - let triggerItem = menuTester.submenuTriggers()[0]; + let triggerItem = menuTester.getSubmenuTriggers()[0]; expect(triggerItem).toHaveTextContent('Share…'); expect(triggerItem).toHaveAttribute('aria-haspopup', 'menu'); @@ -1570,9 +1570,9 @@ describe('Menu', () => { act(() => { jest.runAllTimers(); }); - expect(subDialogTester?.menu()).toBeInTheDocument(); + expect(subDialogTester?.getMenu()).toBeInTheDocument(); - let subDialogTriggerItem = subDialogTester?.submenuTriggers()[0]; + let subDialogTriggerItem = subDialogTester?.getSubmenuTriggers()[0]; expect(subDialogTriggerItem).toHaveTextContent('Nested Subdialog'); expect(subDialogTriggerItem).toHaveAttribute('aria-haspopup', 'menu'); @@ -1648,16 +1648,16 @@ describe('Menu', () => { await menuTester.open(); // Open the subdialog - let triggerItem = menuTester.submenuTriggers()[0]; + let triggerItem = menuTester.getSubmenuTriggers()[0]; let subDialogTester = await menuTester.openSubmenu({submenuTrigger: triggerItem}); act(() => { jest.runAllTimers(); }); - expect(subDialogTester?.menu()).toBeInTheDocument(); + expect(subDialogTester?.getMenu()).toBeInTheDocument(); // Open the nested subdialog - let subDialogTriggerItem = subDialogTester?.submenuTriggers()[0]; + let subDialogTriggerItem = subDialogTester?.getSubmenuTriggers()[0]; await subDialogTester?.openSubmenu({submenuTrigger: subDialogTriggerItem!}); act(() => { jest.runAllTimers(); @@ -1671,7 +1671,7 @@ describe('Menu', () => { }); subdialogs = queryAllByRole('dialog'); expect(subdialogs).toHaveLength(0); - expect(menuTester.menu()).not.toBeInTheDocument(); + expect(menuTester.getMenu()).not.toBeInTheDocument(); }); // TODO: add test where clicking in a parent subdialog should close the nested subdialog when we fix that use case @@ -1765,7 +1765,7 @@ describe('Menu', () => { jest.runAllTimers(); }); - let menu = menuTester.menu(); + let menu = menuTester.getMenu(); let activeElement = document.activeElement; await user.tab(); @@ -1853,7 +1853,7 @@ describe('Menu', () => { ); let menuTester = testUtilUser.createTester('Menu', {user, root: tree.container}); - await user.pointer({target: menuTester.trigger(), keys: '[MouseLeft>]'}); + await user.pointer({target: menuTester.getTrigger(), keys: '[MouseLeft>]'}); await user.pointer({target: menuTester.findOption({indexOrText: 'Cat'}), keys: '[/MouseLeft]'}); expect(onAction).toHaveBeenCalledTimes(1); @@ -1997,7 +1997,7 @@ describe('Menu', () => { act(() => { jest.runAllTimers(); }); - expect(document.activeElement).toBe(menuTester.options()[0]); + expect(document.activeElement).toBe(menuTester.getOptions()[0]); }); }); }); diff --git a/packages/react-aria-components/test/RadioGroup.test.js b/packages/react-aria-components/test/RadioGroup.test.js index a4bec9f06f3..357564454ca 100644 --- a/packages/react-aria-components/test/RadioGroup.test.js +++ b/packages/react-aria-components/test/RadioGroup.test.js @@ -356,17 +356,17 @@ describe.each(['RadioGroup', 'RadioField'])('%s', comp => { {buttonClassName: ({isSelected}) => (isSelected ? 'selected' : '')} ); let radioGroupTester = testUtilUser.createTester('RadioGroup', {root: getByRole('radiogroup')}); - let radios = radioGroupTester.radios(); + let radios = radioGroupTester.getRadios(); let label = radios[0].closest('label'); - expect(radioGroupTester.selectedRadio()).toBeFalsy(); + expect(radioGroupTester.getSelectedRadio()).toBeFalsy(); expect(label).not.toHaveAttribute('data-selected'); expect(findRoot(label)).not.toHaveAttribute('data-selected'); expect(label).not.toHaveClass('selected'); await radioGroupTester.triggerRadio({radio: radios[0]}); expect(onChange).toHaveBeenLastCalledWith('a'); - expect(radioGroupTester.selectedRadio()).toBe(radios[0]); + expect(radioGroupTester.getSelectedRadio()).toBe(radios[0]); expect(label).toHaveAttribute('data-selected', 'true'); expect(findRoot(label)).toHaveAttribute('data-selected', 'true'); expect(label).toHaveClass('selected'); @@ -374,7 +374,7 @@ describe.each(['RadioGroup', 'RadioField'])('%s', comp => { await radioGroupTester.triggerRadio({radio: radios[1]}); expect(onChange).toHaveBeenLastCalledWith('b'); expect(radios[0]).not.toBeChecked(); - expect(radioGroupTester.selectedRadio()).toBe(radios[1]); + expect(radioGroupTester.getSelectedRadio()).toBe(radios[1]); expect(label).not.toHaveAttribute('data-selected'); expect(findRoot(label)).not.toHaveAttribute('data-selected'); expect(label).not.toHaveClass('selected'); @@ -433,9 +433,9 @@ describe.each(['RadioGroup', 'RadioField'])('%s', comp => { }); let radioGroupTester = testUtilUser.createTester('RadioGroup', {root: getByRole('radiogroup')}); - expect(radioGroupTester.radiogroup()).toHaveAttribute('aria-orientation', 'horizontal'); - expect(radioGroupTester.radiogroup()).toHaveClass('horizontal'); - let radios = radioGroupTester.radios(); + expect(radioGroupTester.getRadioGroup()).toHaveAttribute('aria-orientation', 'horizontal'); + expect(radioGroupTester.getRadioGroup()).toHaveClass('horizontal'); + let radios = radioGroupTester.getRadios(); await radioGroupTester.triggerRadio({radio: radios[0]}); expect(radios[0]).toBeChecked(); diff --git a/packages/react-aria-components/test/Select.test.js b/packages/react-aria-components/test/Select.test.js index 3be5ffea99f..df4906037d2 100644 --- a/packages/react-aria-components/test/Select.test.js +++ b/packages/react-aria-components/test/Select.test.js @@ -54,7 +54,7 @@ describe('Select', () => { let wrapper = getByTestId('select'); let selectTester = testUtilUser.createTester('Select', {root: wrapper}); - let trigger = selectTester.trigger(); + let trigger = selectTester.getTrigger(); expect(trigger).toHaveTextContent('Select an item'); expect(trigger).not.toHaveAttribute('data-pressed'); @@ -83,12 +83,12 @@ describe('Select', () => { await selectTester.open(); expect(trigger).toHaveAttribute('data-pressed', 'true'); - let listbox = selectTester.listbox(); + let listbox = selectTester.getListbox(); expect(listbox).toHaveAttribute('class', 'react-aria-ListBox'); expect(listbox.closest('.react-aria-Popover')).toBeInTheDocument(); expect(listbox.closest('.react-aria-Popover')).toHaveAttribute('data-trigger', 'Select'); - let options = selectTester.options(); + let options = selectTester.getOptions(); expect(options).toHaveLength(3); await user.click(options[1]); @@ -103,7 +103,7 @@ describe('Select', () => { ); let selectTester = testUtilUser.createTester('Select', {root: getByTestId('select')}); - let trigger = selectTester.trigger(); + let trigger = selectTester.getTrigger(); expect(trigger.closest('.react-aria-Select')).toHaveAttribute('slot', 'test'); expect(trigger).toHaveAttribute('aria-label', 'test'); }); @@ -145,7 +145,7 @@ describe('Select', () => { ); let selectTester = testUtilUser.createTester('Select', {root: getByTestId('select')}); - let trigger = selectTester.trigger(); + let trigger = selectTester.getTrigger(); expect(trigger).toHaveTextContent('Cat'); }); @@ -172,14 +172,14 @@ describe('Select', () => { ); let selectTester = testUtilUser.createTester('Select', {root: getByTestId('select')}); - let trigger = selectTester.trigger(); + let trigger = selectTester.getTrigger(); expect(trigger).toHaveTextContent('1 - Cat'); }); it('supports placeholder', () => { let {getByTestId} = render(); let selectTester = testUtilUser.createTester('Select', {root: getByTestId('select')}); - let trigger = selectTester.trigger(); + let trigger = selectTester.getTrigger(); expect(trigger).toHaveTextContent('Select an animal'); }); @@ -230,7 +230,7 @@ describe('Select', () => { ); let selectTester = testUtilUser.createTester('Select', {root: getByTestId('select')}); - let trigger = selectTester.trigger(); + let trigger = selectTester.getTrigger(); expect(trigger).toHaveTextContent('open'); await selectTester.open(); @@ -255,7 +255,7 @@ describe('Select', () => { ); let selectTester = testUtilUser.createTester('Select', {root: getByTestId('select')}); - let trigger = selectTester.trigger(); + let trigger = selectTester.getTrigger(); await selectTester.open(); expect(trigger).toHaveAttribute('data-pressed', 'true'); @@ -283,7 +283,7 @@ describe('Select', () => { ); let selectTester = testUtilUser.createTester('Select', {root: getByTestId('select')}); - let trigger = selectTester.trigger(); + let trigger = selectTester.getTrigger(); await selectTester.open(); expect(trigger).toHaveAttribute('data-pressed', 'true'); @@ -329,7 +329,7 @@ describe('Select', () => { let wrapper = getByTestId('test-select'); let selectTester = testUtilUser.createTester('Select', {root: wrapper}); - let trigger = selectTester.trigger(); + let trigger = selectTester.getTrigger(); let select = wrapper; let input = document.querySelector('[name=select]'); expect(input).toHaveAttribute('required'); @@ -349,7 +349,7 @@ describe('Select', () => { expect(document.activeElement).toBe(trigger); await selectTester.toggleOptionSelection({option: 'Cat'}); - expect(selectTester.trigger()).not.toHaveAttribute('aria-describedby'); + expect(selectTester.getTrigger()).not.toHaveAttribute('aria-describedby'); expect(select).not.toHaveAttribute('data-invalid'); }); @@ -461,7 +461,7 @@ describe('Select', () => { await user.tab(); await user.tab(); - expect(document.activeElement).toBe(selectTester.trigger()); + expect(document.activeElement).toBe(selectTester.getTrigger()); await user.tab(); expect(document.activeElement).toBe(clearButton); @@ -473,7 +473,7 @@ describe('Select', () => { expect(document.activeElement).toBe(clearButton); await user.tab({shift: true}); - expect(document.activeElement).toBe(selectTester.trigger()); + expect(document.activeElement).toBe(selectTester.getTrigger()); await user.tab({shift: true}); expect(document.activeElement).toBe(beforeInput); @@ -497,7 +497,7 @@ describe('Select', () => { root: wrapper, interactionType: 'keyboard' }); - let trigger = selectTester.trigger(); + let trigger = selectTester.getTrigger(); expect(trigger).toHaveTextContent('Select an item'); expect(trigger).not.toHaveAttribute('data-pressed'); @@ -545,7 +545,7 @@ describe('Select', () => { root: wrapper, interactionType: 'keyboard' }); - let trigger = selectTester.trigger(); + let trigger = selectTester.getTrigger(); expect(trigger).toHaveTextContent('Northern Territory'); expect(trigger).not.toHaveAttribute('data-pressed'); }); @@ -556,7 +556,7 @@ describe('Select', () => { let selectTester = testUtilUser.createTester('Select', { root: getByTestId('select') }); - let trigger = selectTester.trigger(); + let trigger = selectTester.getTrigger(); expect(document.activeElement).toBe(trigger); }); @@ -614,7 +614,7 @@ describe('Select', () => { let wrapper = getByTestId('select'); let selectTester = testUtilUser.createTester('Select', {root: wrapper}); - await user.click(selectTester.trigger()); + await user.click(selectTester.getTrigger()); let popover = queryByTestId('popover'); expect(popover).toBeFalsy(); @@ -636,7 +636,7 @@ describe('Select', () => { ); - await user.click(selectTester.trigger()); + await user.click(selectTester.getTrigger()); popover = queryByTestId('popover'); expect(popover).toBeFalsy(); }); @@ -674,7 +674,7 @@ describe('Select', () => { const {getByTestId} = render(); const wrapper = getByTestId('select'); const selectTester = testUtilUser.createTester('Select', {root: wrapper}); - const trigger = selectTester.trigger(); + const trigger = selectTester.getTrigger(); const submit = getByTestId('submit'); expect(trigger).toHaveTextContent('Select an item'); @@ -699,15 +699,15 @@ describe('Select', () => { let wrapper = getByTestId('select'); let selectTester = testUtilUser.createTester('Select', {root: wrapper}); - let trigger = selectTester.trigger(); + let trigger = selectTester.getTrigger(); expect(trigger).toHaveTextContent('Select an item'); await selectTester.open(); - let listbox = selectTester.listbox(); + let listbox = selectTester.getListbox(); expect(listbox).toHaveAttribute('aria-multiselectable', 'true'); - let options = selectTester.options(); + let options = selectTester.getOptions(); expect(options).toHaveLength(3); await selectTester.toggleOptionSelection({option: options[0]}); @@ -729,18 +729,18 @@ describe('Select', () => { await selectTester.toggleOptionSelection({option: 'Cat'}); await selectTester.toggleOptionSelection({option: 'Dog'}); - expect(selectTester.options()[0]).toHaveAttribute('aria-selected', 'true'); - expect(selectTester.options()[1]).toHaveAttribute('aria-selected', 'true'); + expect(selectTester.getOptions()[0]).toHaveAttribute('aria-selected', 'true'); + expect(selectTester.getOptions()[1]).toHaveAttribute('aria-selected', 'true'); expect(onChange).toHaveBeenLastCalledWith(['cat', 'dog']); await selectTester.toggleOptionSelection({option: 'Cat'}); - expect(selectTester.options()[0]).toHaveAttribute('aria-selected', 'false'); - expect(selectTester.options()[1]).toHaveAttribute('aria-selected', 'true'); + expect(selectTester.getOptions()[0]).toHaveAttribute('aria-selected', 'false'); + expect(selectTester.getOptions()[1]).toHaveAttribute('aria-selected', 'true'); expect(onChange).toHaveBeenLastCalledWith(['dog']); await selectTester.toggleOptionSelection({option: 'Dog'}); - expect(selectTester.options()[0]).toHaveAttribute('aria-selected', 'false'); - expect(selectTester.options()[1]).toHaveAttribute('aria-selected', 'false'); + expect(selectTester.getOptions()[0]).toHaveAttribute('aria-selected', 'false'); + expect(selectTester.getOptions()[1]).toHaveAttribute('aria-selected', 'false'); expect(onChange).toHaveBeenLastCalledWith([]); await selectTester.close(); @@ -772,7 +772,7 @@ describe('Select', () => { let wrapper = getByTestId('select'); let selectTester = testUtilUser.createTester('Select', {root: wrapper}); - let trigger = selectTester.trigger(); + let trigger = selectTester.getTrigger(); expect(trigger).toHaveTextContent('Select an item'); let submit = getByTestId('submit'); @@ -783,7 +783,7 @@ describe('Select', () => { await selectTester.open(); - let options = selectTester.options(); + let options = selectTester.getOptions(); await user.click(options[0]); await user.click(options[1]); await selectTester.close(); @@ -803,12 +803,12 @@ describe('Select', () => { let wrapper = getByTestId('select'); let selectTester = testUtilUser.createTester('Select', {root: wrapper}); - let trigger = selectTester.trigger(); + let trigger = selectTester.getTrigger(); expect(trigger).toHaveTextContent('Dog and Kangaroo'); await selectTester.open(); - let options = selectTester.options(); + let options = selectTester.getOptions(); expect(options[0]).toHaveAttribute('aria-selected', 'false'); expect(options[1]).toHaveAttribute('aria-selected', 'true'); expect(options[2]).toHaveAttribute('aria-selected', 'true'); @@ -839,7 +839,7 @@ describe('Select', () => { ); let selectTester = testUtilUser.createTester('Select', {root: getByTestId('select')}); - let trigger = selectTester.trigger(); + let trigger = selectTester.getTrigger(); expect(trigger).toHaveTextContent('Cat'); await selectTester.toggleOptionSelection({option: 'Dog'}); diff --git a/packages/react-aria-components/test/Table.test.js b/packages/react-aria-components/test/Table.test.js index 9359b7e67e7..203032ae997 100644 --- a/packages/react-aria-components/test/Table.test.js +++ b/packages/react-aria-components/test/Table.test.js @@ -304,27 +304,27 @@ describe('Table', () => { it('should render with default classes', () => { let {getByRole} = renderTable(); let tableTester = testUtilUser.createTester('Table', {root: getByRole('grid')}); - let table = tableTester.table(); + let table = tableTester.getTable(); expect(table).toHaveAttribute('class', 'react-aria-Table'); - for (let row of tableTester.rows()) { + for (let row of tableTester.getRows()) { expect(row).toHaveAttribute('class', 'react-aria-Row'); } - let rowGroups = tableTester.rowGroups(); + let rowGroups = tableTester.getRowGroups(); expect(rowGroups).toHaveLength(2); expect(rowGroups[0]).toHaveAttribute('class', 'react-aria-TableHeader'); expect(rowGroups[1]).toHaveAttribute('class', 'react-aria-TableBody'); - for (let cell of tableTester.columns()) { + for (let cell of tableTester.getColumns()) { expect(cell).toHaveAttribute('class', 'react-aria-Column'); } - for (let cell of tableTester.rowHeaders()) { + for (let cell of tableTester.getRowHeaders()) { expect(cell).toHaveAttribute('class', 'react-aria-Cell'); } - for (let cell of tableTester.cells()) { + for (let cell of tableTester.getCells()) { expect(cell).toHaveAttribute('class', 'react-aria-Cell'); } }); @@ -758,16 +758,16 @@ describe('Table', () => { rowProps: {className: ({isDisabled}) => (isDisabled ? 'disabled' : '')} }); let tableTester = testUtilUser.createTester('Table', {root: getByRole('grid')}); - let disabledRow = tableTester.rows()[1]; + let disabledRow = tableTester.getRows()[1]; expect(disabledRow).toHaveAttribute('aria-disabled', 'true'); expect(disabledRow).toHaveClass('disabled'); expect(within(disabledRow).getByRole('checkbox')).toBeDisabled(); await user.tab(); - expect(document.activeElement).toBe(tableTester.rows()[0]); + expect(document.activeElement).toBe(tableTester.getRows()[0]); fireEvent.keyDown(document.activeElement, {key: 'ArrowDown'}); fireEvent.keyUp(document.activeElement, {key: 'ArrowDown'}); - expect(document.activeElement).toBe(tableTester.rows()[2]); + expect(document.activeElement).toBe(tableTester.getRows()[2]); await expect(tableTester.toggleRowSelection({row: 1})).rejects.toThrow(); await expect(tableTester.triggerRowAction({row: 1})).rejects.toThrow(); }); @@ -846,7 +846,7 @@ describe('Table', () => { let tableTester = testUtilUser.createTester('Table', {root: getByRole('grid')}); - let columns = tableTester.columns(); + let columns = tableTester.getColumns(); expect(columns[0]).toHaveAttribute('aria-sort', 'ascending'); expect(columns[0]).toHaveTextContent('▲'); expect(columns[1]).toHaveAttribute('aria-sort', 'none'); @@ -884,7 +884,7 @@ describe('Table', () => { await user.keyboard('{ArrowDown}'); await user.keyboard('{ArrowRight}'); - let gridRows = tableTester.rows(); + let gridRows = tableTester.getRows(); expect(gridRows).toHaveLength(4); let cell = within(gridRows[1]).getAllByRole('rowheader')[0]; expect(cell).toHaveTextContent('Program Files'); @@ -892,7 +892,7 @@ describe('Table', () => { rerender(); - gridRows = tableTester.rows(); + gridRows = tableTester.getRows(); expect(gridRows).toHaveLength(3); cell = within(gridRows[1]).getAllByRole('rowheader')[0]; expect(cell).toHaveTextContent('bootmgr'); @@ -1697,8 +1697,8 @@ describe('Table', () => { const DndTableExample = stories.DndTableExample; let {getAllByRole} = render(); let tableTester = testUtilUser.createTester('Table', {root: getAllByRole('grid')[1]}); - expect(tableTester.rows()).toHaveLength(7); - expect(tableTester.selectedRows()).toHaveLength(0); + expect(tableTester.getRows()).toHaveLength(7); + expect(tableTester.getSelectedRows()).toHaveLength(0); await user.tab(); await user.keyboard('{ArrowRight}'); await user.keyboard('{Enter}'); @@ -1716,8 +1716,8 @@ describe('Table', () => { // run onInsert promise in DnDTableExample first, otherwise updateFocusAfterDrop doesn't run properly await act(async () => {}); act(() => jest.runAllTimers()); - expect(tableTester.rows()).toHaveLength(8); - expect(tableTester.selectedRows()).toHaveLength(1); + expect(tableTester.getRows()).toHaveLength(8); + expect(tableTester.getSelectedRows()).toHaveLength(1); }); }); @@ -2363,7 +2363,7 @@ describe('Table', () => { it('should render the loading element when loading', async () => { let tree = render(); let tableTester = testUtilUser.createTester('Table', {root: tree.getByRole('grid')}); - let rows = tableTester.rows(); + let rows = tableTester.getRows(); expect(rows).toHaveLength(12); let loaderRow = rows[11]; expect(loaderRow).toHaveTextContent('spinner'); @@ -2375,7 +2375,7 @@ describe('Table', () => { it('should render the sentinel but not the loading indicator when not loading', async () => { let tree = render(); let tableTester = testUtilUser.createTester('Table', {root: tree.getByRole('grid')}); - let rows = tableTester.rows(); + let rows = tableTester.getRows(); expect(rows).toHaveLength(11); expect(tree.queryByText('spinner')).toBeFalsy(); expect(tree.getByTestId('loadMoreSentinel')).toBeInTheDocument(); @@ -2384,24 +2384,24 @@ describe('Table', () => { it('should properly render the renderEmptyState if table is empty', async () => { let tree = render(); let tableTester = testUtilUser.createTester('Table', {root: tree.getByRole('grid')}); - let rows = tableTester.rows(); + let rows = tableTester.getRows(); expect(rows).toHaveLength(2); expect(rows[1]).toHaveTextContent('No results'); expect(tree.queryByText('spinner')).toBeFalsy(); expect(tree.getByTestId('loadMoreSentinel')).toBeInTheDocument(); - let body = tableTester.rowGroups()[1]; + let body = tableTester.getRowGroups()[1]; expect(body).toHaveAttribute('data-empty', 'true'); let selectAll = tree.getAllByRole('checkbox')[0]; expect(selectAll).toBeDisabled(); // Even if the table is empty, providing isLoading will render the loader tree.rerender(); - rows = tableTester.rows(); + rows = tableTester.getRows(); expect(rows).toHaveLength(3); expect(rows[2]).toHaveTextContent('No results'); expect(tree.queryByText('spinner')).toBeTruthy(); expect(tree.getByTestId('loadMoreSentinel')).toBeInTheDocument(); - body = tableTester.rowGroups()[1]; + body = tableTester.getRowGroups()[1]; expect(body).toHaveAttribute('data-empty', 'true'); selectAll = tree.getAllByRole('checkbox')[0]; expect(selectAll).toBeDisabled(); @@ -2588,7 +2588,7 @@ describe('Table', () => { it('should always render the sentinel even when virtualized', () => { let tree = render(); let tableTester = testUtilUser.createTester('Table', {root: tree.getByRole('grid')}); - let rows = tableTester.rows(); + let rows = tableTester.getRows(); expect(rows).toHaveLength(7); let loaderRow = rows[6]; expect(loaderRow).toHaveTextContent('spinner'); @@ -2606,34 +2606,34 @@ describe('Table', () => { it('should not reserve room for the loader if isLoading is false', () => { let tree = render(); let tableTester = testUtilUser.createTester('Table', {root: tree.getByRole('grid')}); - let rows = tableTester.rows(); + let rows = tableTester.getRows(); expect(rows).toHaveLength(6); - expect(within(tableTester.table()).queryByText('spinner')).toBeFalsy(); + expect(within(tableTester.getTable()).queryByText('spinner')).toBeFalsy(); - let sentinel = within(tableTester.table()).getByTestId('loadMoreSentinel'); + let sentinel = within(tableTester.getTable()).getByTestId('loadMoreSentinel'); let sentinelVirtWrapperStyles = sentinel.closest('[role="presentation"]').style; expect(sentinelVirtWrapperStyles.top).toBe('1250px'); expect(sentinelVirtWrapperStyles.height).toBe('0px'); expect(sentinel.closest('[inert]')).toBeTruthy(); tree.rerender(); - rows = tableTester.rows(); + rows = tableTester.getRows(); expect(rows).toHaveLength(1); let emptyStateRow = rows[0]; expect(emptyStateRow).toHaveTextContent('No results'); - expect(within(tableTester.table()).queryByText('spinner')).toBeFalsy(); - sentinel = within(tableTester.table()).getByTestId('loadMoreSentinel', {hidden: true}); + expect(within(tableTester.getTable()).queryByText('spinner')).toBeFalsy(); + sentinel = within(tableTester.getTable()).getByTestId('loadMoreSentinel', {hidden: true}); sentinelVirtWrapperStyles = sentinel.closest('[role="presentation"]').style; expect(sentinelVirtWrapperStyles.top).toBe('0px'); expect(sentinelVirtWrapperStyles.height).toBe('0px'); tree.rerender(); - rows = tableTester.rows(); + rows = tableTester.getRows(); expect(rows).toHaveLength(1); emptyStateRow = rows[0]; expect(emptyStateRow).toHaveTextContent('loading'); - sentinel = within(tableTester.table()).getByTestId('loadMoreSentinel', {hidden: true}); + sentinel = within(tableTester.getTable()).getByTestId('loadMoreSentinel', {hidden: true}); sentinelVirtWrapperStyles = sentinel.closest('[role="presentation"]').style; expect(sentinelVirtWrapperStyles.top).toBe('0px'); expect(sentinelVirtWrapperStyles.height).toBe('0px'); @@ -2642,7 +2642,7 @@ describe('Table', () => { it('should have the correct row indicies after loading more items', async () => { let tree = render(); let tableTester = testUtilUser.createTester('Table', {root: tree.getByRole('grid')}); - let rows = tableTester.rows(); + let rows = tableTester.getRows(); expect(rows).toHaveLength(1); let loaderRow = rows[0]; @@ -2651,15 +2651,15 @@ describe('Table', () => { expect(loaderRow).not.toHaveAttribute('aria-rowindex'); tree.rerender(); - rows = tableTester.rows(); + rows = tableTester.getRows(); expect(rows).toHaveLength(6); - expect(within(tableTester.table()).queryByText('spinner')).toBeFalsy(); + expect(within(tableTester.getTable()).queryByText('spinner')).toBeFalsy(); for (let [index, row] of rows.entries()) { expect(row).toHaveAttribute('aria-rowindex', `${index + 2}`); } tree.rerender(); - rows = tableTester.rows(); + rows = tableTester.getRows(); expect(rows).toHaveLength(7); loaderRow = rows[6]; expect(loaderRow).not.toHaveAttribute('aria-rowindex'); @@ -2873,9 +2873,9 @@ describe('Table', () => { root: getByRole('grid'), interactionType: type }); - let rows = tableTester.rows(); + let rows = tableTester.getRows(); - for (let row of tableTester.rows()) { + for (let row of tableTester.getRows()) { let checkbox = within(row).queryByRole('checkbox'); expect(checkbox).toBeNull(); expect(row).toHaveAttribute('aria-selected', 'false'); @@ -2895,8 +2895,8 @@ describe('Table', () => { expect(onSelectionChange).toHaveBeenCalledTimes(1); } expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual(new Set(['3'])); - expect(tableTester.selectedRows()).toHaveLength(1); - expect(tableTester.selectedRows()[0]).toBe(row2); + expect(tableTester.getSelectedRows()).toHaveLength(1); + expect(tableTester.getSelectedRows()[0]).toBe(row2); let row1 = rows[1]; await tableTester.toggleRowSelection({row: row1, selectionBehavior: 'replace'}); @@ -2910,8 +2910,8 @@ describe('Table', () => { expect(onSelectionChange).toHaveBeenCalledTimes(2); } expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual(new Set(['2'])); - expect(tableTester.selectedRows()).toHaveLength(1); - expect(tableTester.selectedRows()[0]).toBe(row1); + expect(tableTester.getSelectedRows()).toHaveLength(1); + expect(tableTester.getSelectedRows()[0]).toBe(row1); await tableTester.toggleRowSelection({row: row1, selectionBehavior: 'replace'}); expect(row1).toHaveAttribute('aria-selected', 'false'); @@ -2924,7 +2924,7 @@ describe('Table', () => { expect(onSelectionChange).toHaveBeenCalledTimes(3); } expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual(new Set([])); - expect(tableTester.selectedRows()).toHaveLength(0); + expect(tableTester.getSelectedRows()).toHaveLength(0); }); it('should perform toggle selection in highlight mode when using modifier keys', async () => { @@ -2940,9 +2940,9 @@ describe('Table', () => { root: getByRole('grid'), interactionType: type }); - let rows = tableTester.rows(); + let rows = tableTester.getRows(); - for (let row of tableTester.rows()) { + for (let row of tableTester.getRows()) { let checkbox = within(row).queryByRole('checkbox'); expect(checkbox).toBeNull(); expect(row).toHaveAttribute('aria-selected', 'false'); @@ -2958,13 +2958,13 @@ describe('Table', () => { // Called twice because initial focus will select the first keyboard focused row, meaning we have two items selected expect(onSelectionChange).toHaveBeenCalledTimes(2); expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual(new Set(['1', '3'])); - expect(tableTester.selectedRows()).toHaveLength(2); - expect(tableTester.selectedRows()[1]).toBe(row2); + expect(tableTester.getSelectedRows()).toHaveLength(2); + expect(tableTester.getSelectedRows()[1]).toBe(row2); } else { expect(onSelectionChange).toHaveBeenCalledTimes(1); expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual(new Set(['3'])); - expect(tableTester.selectedRows()).toHaveLength(1); - expect(tableTester.selectedRows()[0]).toBe(row2); + expect(tableTester.getSelectedRows()).toHaveLength(1); + expect(tableTester.getSelectedRows()[0]).toBe(row2); } let row1 = rows[1]; @@ -2976,15 +2976,15 @@ describe('Table', () => { if (type === 'keyboard') { expect(onSelectionChange).toHaveBeenCalledTimes(3); expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual(new Set(['1', '2', '3'])); - expect(tableTester.selectedRows()).toHaveLength(3); - expect(tableTester.selectedRows()[1]).toBe(row1); - expect(tableTester.selectedRows()[2]).toBe(row2); + expect(tableTester.getSelectedRows()).toHaveLength(3); + expect(tableTester.getSelectedRows()[1]).toBe(row1); + expect(tableTester.getSelectedRows()[2]).toBe(row2); } else { expect(onSelectionChange).toHaveBeenCalledTimes(2); expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual(new Set(['2', '3'])); - expect(tableTester.selectedRows()).toHaveLength(2); - expect(tableTester.selectedRows()[0]).toBe(row1); - expect(tableTester.selectedRows()[1]).toBe(row2); + expect(tableTester.getSelectedRows()).toHaveLength(2); + expect(tableTester.getSelectedRows()[0]).toBe(row1); + expect(tableTester.getSelectedRows()[1]).toBe(row2); } // With modifier key, you should be able to deselect on press of the same row @@ -2996,13 +2996,13 @@ describe('Table', () => { if (type === 'keyboard') { expect(onSelectionChange).toHaveBeenCalledTimes(4); expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual(new Set(['1', '3'])); - expect(tableTester.selectedRows()).toHaveLength(2); - expect(tableTester.selectedRows()[1]).toBe(row2); + expect(tableTester.getSelectedRows()).toHaveLength(2); + expect(tableTester.getSelectedRows()[1]).toBe(row2); } else { expect(onSelectionChange).toHaveBeenCalledTimes(3); expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual(new Set(['3'])); - expect(tableTester.selectedRows()).toHaveLength(1); - expect(tableTester.selectedRows()[0]).toBe(row2); + expect(tableTester.getSelectedRows()).toHaveLength(1); + expect(tableTester.getSelectedRows()[0]).toBe(row2); } }); @@ -3019,9 +3019,9 @@ describe('Table', () => { root: getByRole('grid'), interactionType: type }); - let rows = tableTester.rows(); + let rows = tableTester.getRows(); - for (let row of tableTester.rows()) { + for (let row of tableTester.getRows()) { let checkbox = within(row).queryByRole('checkbox'); expect(checkbox).toBeNull(); expect(row).toHaveAttribute('aria-selected', 'false'); @@ -3040,8 +3040,8 @@ describe('Table', () => { expect(onSelectionChange).toHaveBeenCalledTimes(1); } expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual(new Set(['3'])); - expect(tableTester.selectedRows()).toHaveLength(1); - expect(tableTester.selectedRows()[0]).toBe(row2); + expect(tableTester.getSelectedRows()).toHaveLength(1); + expect(tableTester.getSelectedRows()[0]).toBe(row2); let row1 = rows[1]; await tableTester.toggleRowSelection({row: row1}); @@ -3056,8 +3056,8 @@ describe('Table', () => { expect(onSelectionChange).toHaveBeenCalledTimes(2); } expect(new Set(onSelectionChange.mock.calls.at(-1)[0])).toEqual(new Set(['2'])); - expect(tableTester.selectedRows()).toHaveLength(1); - expect(tableTester.selectedRows()[0]).toBe(row1); + expect(tableTester.getSelectedRows()).toHaveLength(1); + expect(tableTester.getSelectedRows()[0]).toBe(row1); // pressing without modifier keys won't deselect the row await tableTester.toggleRowSelection({row: row1}); @@ -3068,7 +3068,7 @@ describe('Table', () => { } else { expect(onSelectionChange).toHaveBeenCalledTimes(2); } - expect(tableTester.selectedRows()).toHaveLength(1); + expect(tableTester.getSelectedRows()).toHaveLength(1); } else { // touch always behaves as toggle expect(row1).toHaveAttribute('aria-selected', 'true'); @@ -3077,16 +3077,16 @@ describe('Table', () => { expect(row2).toHaveAttribute('data-selected', 'true'); expect(onSelectionChange).toHaveBeenCalledTimes(2); expect(new Set(onSelectionChange.mock.calls[1][0])).toEqual(new Set(['2', '3'])); - expect(tableTester.selectedRows()).toHaveLength(2); - expect(tableTester.selectedRows()[0]).toBe(row1); + expect(tableTester.getSelectedRows()).toHaveLength(2); + expect(tableTester.getSelectedRows()[0]).toBe(row1); await tableTester.toggleRowSelection({row: row1}); expect(row1).toHaveAttribute('aria-selected', 'false'); expect(row1).not.toHaveAttribute('data-selected'); expect(onSelectionChange).toHaveBeenCalledTimes(3); expect(new Set(onSelectionChange.mock.calls[2][0])).toEqual(new Set(['3'])); - expect(tableTester.selectedRows()).toHaveLength(1); - expect(tableTester.selectedRows()[0]).toBe(row2); + expect(tableTester.getSelectedRows()).toHaveLength(1); + expect(tableTester.getSelectedRows()[0]).toBe(row2); } }); }); @@ -3236,20 +3236,20 @@ describe('Table', () => { let tableTester = testUtilUser.createTester('Table', {root}); - let groups = tableTester.rowGroups(); + let groups = tableTester.getRowGroups(); expect(groups).toHaveLength(3); expect(groups[0].tagName).toBe('THEAD'); expect(groups[1].tagName).toBe('TBODY'); expect(groups[2].tagName).toBe('TFOOT'); - expect(tableTester.rows()).toHaveLength(8); + expect(tableTester.getRows()).toHaveLength(8); await user.tab(); - for (let row of tableTester.rows()) { + for (let row of tableTester.getRows()) { expect(document.activeElement).toBe(row); await user.keyboard('{ArrowDown}'); } - for (let row of tableTester.rows().toReversed().slice(1)) { + for (let row of tableTester.getRows().toReversed().slice(1)) { await user.keyboard('{ArrowUp}'); expect(document.activeElement).toBe(row); } @@ -3314,17 +3314,17 @@ describe('Table', () => { let tableTester = testUtilUser.createTester('Table', {root}); - let groups = tableTester.rowGroups(); + let groups = tableTester.getRowGroups(); expect(groups).toHaveLength(3); - expect(tableTester.rows()).toHaveLength(8); + expect(tableTester.getRows()).toHaveLength(8); await user.tab(); - for (let row of tableTester.rows()) { + for (let row of tableTester.getRows()) { expect(document.activeElement).toBe(row); await user.keyboard('{ArrowDown}'); } - for (let row of tableTester.rows().toReversed().slice(1)) { + for (let row of tableTester.getRows().toReversed().slice(1)) { await user.keyboard('{ArrowUp}'); expect(document.activeElement).toBe(row); } @@ -3373,21 +3373,21 @@ describe('Table', () => { let tableTester = testUtilUser.createTester('Table', {root}); - let groups = tableTester.rowGroups(); + let groups = tableTester.getRowGroups(); expect(groups).toHaveLength(4); expect(groups[0].tagName).toBe('THEAD'); expect(groups[1].tagName).toBe('TBODY'); expect(groups[2].tagName).toBe('TBODY'); expect(groups[3].tagName).toBe('TBODY'); - expect(tableTester.rows()).toHaveLength(10); + expect(tableTester.getRows()).toHaveLength(10); await user.tab(); - for (let row of tableTester.rows()) { + for (let row of tableTester.getRows()) { expect(document.activeElement).toBe(row); await user.keyboard('{ArrowDown}'); } - for (let row of tableTester.rows().toReversed().slice(1)) { + for (let row of tableTester.getRows().toReversed().slice(1)) { await user.keyboard('{ArrowUp}'); expect(document.activeElement).toBe(row); } diff --git a/packages/react-aria-components/test/Tabs.browser.test.tsx b/packages/react-aria-components/test/Tabs.browser.test.tsx index 05230490f78..8a778b0f008 100644 --- a/packages/react-aria-components/test/Tabs.browser.test.tsx +++ b/packages/react-aria-components/test/Tabs.browser.test.tsx @@ -43,7 +43,7 @@ it.each` root: container.querySelector('[role=tablist]') as HTMLElement, interactionType }); - let tabs = tester.tabs(); + let tabs = tester.getTabs(); await tester.triggerTab({tab: tabs[1]}); - expect(tester.selectedTab()).toBe(tabs[1]); + expect(tester.getSelectedTab()).toBe(tabs[1]); }); diff --git a/packages/react-aria-components/test/Tabs.test.js b/packages/react-aria-components/test/Tabs.test.js index 50545229c02..881b7b2b14b 100644 --- a/packages/react-aria-components/test/Tabs.test.js +++ b/packages/react-aria-components/test/Tabs.test.js @@ -73,16 +73,16 @@ describe('Tabs', () => { let {getByTestId} = renderTabs(); let tabs = getByTestId('tabs-wrapper'); let tabsTester = testUtilUser.createTester('Tabs', {root: tabs}); - let tablist = tabsTester.tablist(); + let tablist = tabsTester.getTablist(); expect(tabs).toBeInTheDocument(); expect(tablist).toHaveAttribute('class', 'react-aria-TabList'); expect(tablist).toHaveAttribute('aria-label', 'Test'); - for (let tab of tabsTester.tabs()) { + for (let tab of tabsTester.getTabs()) { expect(tab).toHaveAttribute('class', 'react-aria-Tab'); } - expect(tabsTester.tabpanels()[0]).toHaveAttribute('class', 'react-aria-TabPanel'); + expect(tabsTester.getTabpanels()[0]).toHaveAttribute('class', 'react-aria-TabPanel'); }); it('should render tabs with custom classes', () => { @@ -399,8 +399,8 @@ describe('Tabs', () => { let tabsTester = testUtilUser.createTester('Tabs', {root: getByRole('tablist')}); await user.tab(); - expect(tabsTester.selectedTab()).toBe(tabsTester.tabs()[0]); - expect(document.activeElement).toBe(tabsTester.tabpanels()[0]); + expect(tabsTester.getSelectedTab()).toBe(tabsTester.getTabs()[0]); + expect(document.activeElement).toBe(tabsTester.getTabpanels()[0]); }); it('should support selected state', async () => { @@ -411,7 +411,7 @@ describe('Tabs', () => { {className: ({isSelected}) => (isSelected ? 'selected' : '')} ); let tabsTester = testUtilUser.createTester('Tabs', {root: getByRole('tablist')}); - let tabs = tabsTester.tabs(); + let tabs = tabsTester.getTabs(); expect(tabs[0]).toHaveAttribute('aria-selected', 'true'); expect(tabs[0]).toHaveClass('selected'); @@ -445,15 +445,15 @@ describe('Tabs', () => { ); let tabsTester = testUtilUser.createTester('Tabs', {root: getByRole('tablist')}); - expect(tabsTester.activeTabpanel().getAttribute('id')).toContain('first-element'); + expect(tabsTester.getActiveTabpanel().getAttribute('id')).toContain('first-element'); await tabsTester.triggerTab({tab: 1}); expect(onSelectionChange).toHaveBeenCalled(); - expect(tabsTester.activeTabpanel().getAttribute('id')).toContain('second-element'); + expect(tabsTester.getActiveTabpanel().getAttribute('id')).toContain('second-element'); await tabsTester.triggerTab({tab: 2}); expect(onSelectionChange).toHaveBeenCalled(); - expect(tabsTester.activeTabpanel().getAttribute('id')).toContain('third-element'); + expect(tabsTester.getActiveTabpanel().getAttribute('id')).toContain('third-element'); }); it('should support orientation', () => { @@ -482,23 +482,23 @@ describe('Tabs', () => { root: getByRole('tablist'), interactionType }); - let tabs = tabsTester.tabs(); + let tabs = tabsTester.getTabs(); await tabsTester.triggerTab({tab: 0}); - expect(tabsTester.selectedTab()).toBe(tabs[0]); - expect(tabsTester.activeTabpanel().getAttribute('aria-labelledby')).toBe(tabs[0].id); + expect(tabsTester.getSelectedTab()).toBe(tabs[0]); + expect(tabsTester.getActiveTabpanel().getAttribute('aria-labelledby')).toBe(tabs[0].id); await tabsTester.triggerTab({tab: 1}); - expect(tabsTester.selectedTab()).toBe(tabs[1]); - expect(tabsTester.activeTabpanel().getAttribute('aria-labelledby')).toBe(tabs[1].id); + expect(tabsTester.getSelectedTab()).toBe(tabs[1]); + expect(tabsTester.getActiveTabpanel().getAttribute('aria-labelledby')).toBe(tabs[1].id); await tabsTester.triggerTab({tab: 2}); - expect(tabsTester.selectedTab()).toBe(tabs[2]); - expect(tabsTester.activeTabpanel().getAttribute('aria-labelledby')).toBe(tabs[2].id); + expect(tabsTester.getSelectedTab()).toBe(tabs[2]); + expect(tabsTester.getActiveTabpanel().getAttribute('aria-labelledby')).toBe(tabs[2].id); await tabsTester.triggerTab({tab: 1}); - expect(tabsTester.selectedTab()).toBe(tabs[1]); - expect(tabsTester.activeTabpanel().getAttribute('aria-labelledby')).toBe(tabs[1].id); + expect(tabsTester.getSelectedTab()).toBe(tabs[1]); + expect(tabsTester.getActiveTabpanel().getAttribute('aria-labelledby')).toBe(tabs[1].id); } ); @@ -563,7 +563,7 @@ describe('Tabs', () => { interactionType: 'keyboard' }); - let tabs = tabsTester.tabs(); + let tabs = tabsTester.getTabs(); await tabsTester.triggerTab({tab: 0}); expect(tabs[0]).toHaveAttribute('aria-selected', 'true'); @@ -997,12 +997,12 @@ describe('Tabs', () => { ); let tester = testUtilUser.createTester('Tabs', {root: tree.getByRole('tablist')}); - expect(tester.tabs.length).toBe(2); + expect(tester.getTabs().length).toBe(2); let trigger = tree.getByRole('button'); let menu = testUtilUser.createTester('Menu', {root: trigger}); await menu.open(); - expect(menu.options()).toHaveLength(2); + expect(menu.getOptions()).toHaveLength(2); await menu.close(); }); @@ -1034,12 +1034,12 @@ describe('Tabs', () => { ); let tester = testUtilUser.createTester('Tabs', {root: tree.getByRole('tablist')}); - expect(tester.tabs.length).toBe(2); + expect(tester.getTabs().length).toBe(2); let trigger = tree.getByRole('button'); let menu = testUtilUser.createTester('Select', {root: trigger}); await menu.open(); - expect(menu.options()).toHaveLength(3); + expect(menu.getOptions()).toHaveLength(3); await menu.close(); }); @@ -1069,14 +1069,14 @@ describe('Tabs', () => { ); let tester = testUtilUser.createTester('Tabs', {root: tree.getByRole('tablist')}); - expect(tester.tabs.length).toBe(2); + expect(tester.getTabs().length).toBe(2); let menu = testUtilUser.createTester('ComboBox', { interactionType: 'keyboard', root: tree.container.querySelector('.react-aria-ComboBox') }); await menu.open(); - expect(menu.options()).toHaveLength(3); + expect(menu.getOptions()).toHaveLength(3); await menu.close(); }); }); diff --git a/packages/react-aria-components/test/Tree.test.tsx b/packages/react-aria-components/test/Tree.test.tsx index f89354fbdb1..f0c922c1013 100644 --- a/packages/react-aria-components/test/Tree.test.tsx +++ b/packages/react-aria-components/test/Tree.test.tsx @@ -1782,7 +1782,7 @@ describe('Tree', () => { let tree = render(); let treeTester = testUtilUser.createTester('Tree', {root: tree.getByRole('treegrid')}); - let rows = treeTester.rows(); + let rows = treeTester.getRows(); expect(rows).toHaveLength(3); let loaderRow = rows[2]; expect(loaderRow).toHaveTextContent('Loading...'); @@ -1794,7 +1794,7 @@ describe('Tree', () => { tree.rerender( ); - rows = treeTester.rows(); + rows = treeTester.getRows(); expect(rows).toHaveLength(8); let newLoaderRow = rows[4]; expect(newLoaderRow).toHaveTextContent('Loading...'); @@ -1809,7 +1809,7 @@ describe('Tree', () => { let tree = render(); let treeTester = testUtilUser.createTester('Tree', {root: tree.getByRole('treegrid')}); - let rows = treeTester.rows(); + let rows = treeTester.getRows(); expect(rows).toHaveLength(2); expect(tree.queryByText('Loading...')).toBeFalsy(); expect(tree.getByTestId('loadMoreSentinel')).toBeInTheDocument(); @@ -1967,7 +1967,7 @@ describe('Tree', () => { /> ); let treeTester = testUtilUser.createTester('Tree', {root: tree.getByRole('treegrid')}); - let rows = treeTester.rows(); + let rows = treeTester.getRows(); expect(rows).toHaveLength(8); let rootLoaderRow = rows[7]; expect(rootLoaderRow).toHaveTextContent('Loading...'); @@ -1993,7 +1993,7 @@ describe('Tree', () => { /> ); - rows = treeTester.rows(); + rows = treeTester.getRows(); expect(rows).toHaveLength(9); rootLoaderRow = rows[8]; rootLoaderParentStyles = rootLoaderRow.parentElement!.style; @@ -2024,7 +2024,7 @@ describe('Tree', () => { /> ); - rows = treeTester.rows(); + rows = treeTester.getRows(); expect(rows).toHaveLength(10); rootLoaderRow = rows[9]; rootLoaderParentStyles = rootLoaderRow.parentElement!.style; @@ -2062,7 +2062,7 @@ describe('Tree', () => { /> ); - rows = treeTester.rows(); + rows = treeTester.getRows(); expect(rows).toHaveLength(11); rootLoaderRow = rows[10]; rootLoaderParentStyles = rootLoaderRow.parentElement!.style; @@ -2107,7 +2107,7 @@ describe('Tree', () => { ); let treeTester = testUtilUser.createTester('Tree', {root: tree.getByRole('treegrid')}); - let rows = treeTester.rows(); + let rows = treeTester.getRows(); expect(rows).toHaveLength(9); let rootLoaderRow = rows[8]; let rootLoaderParentStyles = rootLoaderRow.parentElement!.style; @@ -2141,7 +2141,7 @@ describe('Tree', () => { it.skip('should restore focus to the tree if the loader is keyboard focused when loading finishes', async () => { let tree = render(); let treeTester = testUtilUser.createTester('Tree', {root: tree.getByRole('treegrid')}); - let rows = treeTester.rows(); + let rows = treeTester.getRows(); expect(rows).toHaveLength(8); let rootLoaderRow = rows[7]; expect(rootLoaderRow).toHaveTextContent('Loading...'); @@ -2152,7 +2152,7 @@ describe('Tree', () => { tree.rerender(); - expect(document.activeElement).toBe(treeTester.tree()); + expect(document.activeElement).toBe(treeTester.getTree()); }); }); }); @@ -2510,9 +2510,9 @@ describe('Tree', () => { let firstTreeTester = testUtilUser.createTester('Tree', {root: trees[0]}); let secondTreeTester = testUtilUser.createTester('Tree', {root: trees[1]}); - expect(firstTreeTester.rows()).toHaveLength(2); + expect(firstTreeTester.getRows()).toHaveLength(2); // has the empty state row - expect(secondTreeTester.rows()).toHaveLength(1); + expect(secondTreeTester.getRows()).toHaveLength(1); await user.tab(); // selects and drops first row onto second tree await user.keyboard('{ArrowRight}'); @@ -2527,13 +2527,13 @@ describe('Tree', () => { fireEvent.keyUp(document.activeElement as Element, {key: 'Enter'}); }); act(() => jest.runAllTimers()); - expect(secondTreeTester.rows()).toHaveLength(1); + expect(secondTreeTester.getRows()).toHaveLength(1); // expands tree row children await user.keyboard('{ArrowRight}'); await user.keyboard('{ArrowDown}'); await user.keyboard('{ArrowDown}'); await user.keyboard('{ArrowRight}'); - expect(secondTreeTester.selectedRows()).toHaveLength(9); + expect(secondTreeTester.getSelectedRows()).toHaveLength(9); }); it('should focus the parent row when dropped on if it isnt expanded', async () => { @@ -2542,9 +2542,9 @@ describe('Tree', () => { let firstTreeTester = testUtilUser.createTester('Tree', {root: trees[0]}); let secondTreeTester = testUtilUser.createTester('Tree', {root: trees[1]}); - expect(firstTreeTester.rows()).toHaveLength(2); + expect(firstTreeTester.getRows()).toHaveLength(2); // has the empty state row - expect(secondTreeTester.rows()).toHaveLength(1); + expect(secondTreeTester.getRows()).toHaveLength(1); await user.tab(); // selects and drops first row onto second tree await user.keyboard('{ArrowRight}'); @@ -2558,12 +2558,12 @@ describe('Tree', () => { fireEvent.keyUp(document.activeElement as Element, {key: 'Enter'}); }); act(() => jest.runAllTimers()); - expect(secondTreeTester.rows()).toHaveLength(1); + expect(secondTreeTester.getRows()).toHaveLength(1); await user.keyboard('{ArrowRight}'); - expect(secondTreeTester.rows()).toHaveLength(6); + expect(secondTreeTester.getRows()).toHaveLength(6); // tab back to the first tree and drop a new row onto one of the 2nd tree's child rows as it is expanded await user.tab({shift: true}); - expect(document.activeElement).toBe(firstTreeTester.rows()[0]); + expect(document.activeElement).toBe(firstTreeTester.getRows()[0]); await user.keyboard('{ArrowRight}'); await user.keyboard('{Enter}'); act(() => jest.runAllTimers()); @@ -2577,7 +2577,7 @@ describe('Tree', () => { fireEvent.keyUp(document.activeElement as Element, {key: 'Enter'}); }); act(() => jest.runAllTimers()); - expect(document.activeElement).toBe(secondTreeTester.rows()[2]); + expect(document.activeElement).toBe(secondTreeTester.getRows()[2]); }); it('should focus the dropped row when dropped on a parent that is expanded', async () => { @@ -2586,9 +2586,9 @@ describe('Tree', () => { let firstTreeTester = testUtilUser.createTester('Tree', {root: trees[0]}); let secondTreeTester = testUtilUser.createTester('Tree', {root: trees[1]}); - expect(firstTreeTester.rows()).toHaveLength(2); + expect(firstTreeTester.getRows()).toHaveLength(2); // has the empty state row - expect(secondTreeTester.rows()).toHaveLength(1); + expect(secondTreeTester.getRows()).toHaveLength(1); await user.tab(); // selects and drops first row onto second tree await user.keyboard('{ArrowRight}'); @@ -2603,16 +2603,16 @@ describe('Tree', () => { fireEvent.keyUp(document.activeElement as Element, {key: 'Enter'}); }); act(() => jest.runAllTimers()); - expect(secondTreeTester.rows()).toHaveLength(1); + expect(secondTreeTester.getRows()).toHaveLength(1); // expands tree row children await user.keyboard('{ArrowRight}'); await user.keyboard('{ArrowDown}'); await user.keyboard('{ArrowDown}'); await user.keyboard('{ArrowRight}'); - expect(secondTreeTester.rows()).toHaveLength(9); + expect(secondTreeTester.getRows()).toHaveLength(9); // tab back to the first tree and drop a new row onto one of the 2nd tree's child rows as it is expanded await user.tab({shift: true}); - expect(document.activeElement).toBe(firstTreeTester.rows()[0]); + expect(document.activeElement).toBe(firstTreeTester.getRows()[0]); await user.keyboard('{ArrowRight}'); await user.keyboard('{Enter}'); @@ -2628,7 +2628,7 @@ describe('Tree', () => { }); act(() => jest.runAllTimers()); expect(document.activeElement).toHaveTextContent('Projects'); - expect(document.activeElement).toBe(secondTreeTester.rows()[3]); + expect(document.activeElement).toBe(secondTreeTester.getRows()[3]); }); }); diff --git a/packages/react-aria-components/test/Treeble.test.js b/packages/react-aria-components/test/Treeble.test.js index 9159270f15d..e3517551bb4 100644 --- a/packages/react-aria-components/test/Treeble.test.js +++ b/packages/react-aria-components/test/Treeble.test.js @@ -204,62 +204,62 @@ describe('Treeble', () => { let tree = render(); let tester = utils.createTester('Table', {root: tree.getByTestId('treeble')}); - expect(tester.table()).toHaveAttribute('role', 'treegrid'); - - expect(tester.rows()).toHaveLength(4); - expect(tester.rows()[0]).toHaveAttribute('aria-expanded', 'false'); - expect(tester.rows()[0]).toHaveAttribute('aria-level', '1'); - expect(tester.rows()[0]).toHaveAttribute('aria-posinset', '1'); - expect(tester.rows()[0]).toHaveAttribute('aria-setsize', '4'); - expect(tester.rows()[0]).not.toHaveAttribute('data-expanded'); - expect(tester.rows()[0]).toHaveAttribute('data-has-child-items', 'true'); - expect(tester.rows()[0]).toHaveAttribute('data-level', '1'); - expect(tester.rows()[0]).toHaveAttribute('style', '--table-row-level: 1;'); - expect(tester.rowHeaders()[0]).toHaveTextContent('Games'); - expect(tester.rowHeaders()[0]).toHaveAttribute('data-tree-column'); - for (let cell of tester.cells()) { + expect(tester.getTable()).toHaveAttribute('role', 'treegrid'); + + expect(tester.getRows()).toHaveLength(4); + expect(tester.getRows()[0]).toHaveAttribute('aria-expanded', 'false'); + expect(tester.getRows()[0]).toHaveAttribute('aria-level', '1'); + expect(tester.getRows()[0]).toHaveAttribute('aria-posinset', '1'); + expect(tester.getRows()[0]).toHaveAttribute('aria-setsize', '4'); + expect(tester.getRows()[0]).not.toHaveAttribute('data-expanded'); + expect(tester.getRows()[0]).toHaveAttribute('data-has-child-items', 'true'); + expect(tester.getRows()[0]).toHaveAttribute('data-level', '1'); + expect(tester.getRows()[0]).toHaveAttribute('style', '--table-row-level: 1;'); + expect(tester.getRowHeaders()[0]).toHaveTextContent('Games'); + expect(tester.getRowHeaders()[0]).toHaveAttribute('data-tree-column'); + for (let cell of tester.getCells()) { expect(cell).not.toHaveAttribute('data-tree-column'); } - for (let cell of tester.cells({element: tester.rows()[0]})) { + for (let cell of tester.getCells({element: tester.getRows()[0]})) { expect(cell).not.toHaveAttribute('data-expanded'); expect(cell).toHaveAttribute('data-has-child-items', 'true'); expect(cell).toHaveAttribute('data-level', '1'); } - let button = within(tester.rowHeaders()[0]).getByRole('button'); + let button = within(tester.getRowHeaders()[0]).getByRole('button'); expect(button).toHaveAttribute('aria-label', 'Expand'); - expect(button).toHaveAttribute('aria-labelledby', `${button.id} ${tester.rowHeaders()[0].id}`); + expect(button).toHaveAttribute('aria-labelledby', `${button.id} ${tester.getRowHeaders()[0].id}`); expect(button).toHaveAttribute('tabindex', '-1'); - expect(tester.rows()[1]).toHaveAttribute('aria-expanded', 'false'); - expect(tester.rows()[1]).toHaveAttribute('aria-level', '1'); - expect(tester.rows()[1]).toHaveAttribute('aria-posinset', '2'); - expect(tester.rows()[1]).toHaveAttribute('aria-setsize', '4'); - expect(tester.rows()[1]).not.toHaveAttribute('data-expanded'); - expect(tester.rows()[1]).toHaveAttribute('data-has-child-items', 'true'); - expect(tester.rows()[1]).toHaveAttribute('data-level', '1'); - expect(tester.rows()[1]).toHaveAttribute('style', '--table-row-level: 1;'); - expect(tester.rowHeaders()[1]).toHaveTextContent('Applications'); - - expect(tester.rows()[2]).not.toHaveAttribute('aria-expanded'); - expect(tester.rows()[2]).toHaveAttribute('aria-level', '1'); - expect(tester.rows()[2]).toHaveAttribute('aria-posinset', '3'); - expect(tester.rows()[2]).toHaveAttribute('aria-setsize', '4'); - expect(tester.rows()[2]).not.toHaveAttribute('data-expanded'); - expect(tester.rows()[2]).not.toHaveAttribute('data-has-child-items'); - expect(tester.rows()[2]).toHaveAttribute('data-level', '1'); - expect(tester.rows()[2]).toHaveAttribute('style', '--table-row-level: 1;'); - expect(tester.rowHeaders()[2]).toHaveTextContent('2024 Financial Report'); - - expect(tester.rows()[3]).not.toHaveAttribute('aria-expanded'); - expect(tester.rows()[3]).toHaveAttribute('aria-level', '1'); - expect(tester.rows()[3]).toHaveAttribute('aria-posinset', '4'); - expect(tester.rows()[3]).toHaveAttribute('aria-setsize', '4'); - expect(tester.rows()[3]).not.toHaveAttribute('data-expanded'); - expect(tester.rows()[3]).not.toHaveAttribute('data-has-child-items'); - expect(tester.rows()[3]).toHaveAttribute('data-level', '1'); - expect(tester.rows()[3]).toHaveAttribute('style', '--table-row-level: 1;'); - expect(tester.rowHeaders()[3]).toHaveTextContent('Job Posting'); + expect(tester.getRows()[1]).toHaveAttribute('aria-expanded', 'false'); + expect(tester.getRows()[1]).toHaveAttribute('aria-level', '1'); + expect(tester.getRows()[1]).toHaveAttribute('aria-posinset', '2'); + expect(tester.getRows()[1]).toHaveAttribute('aria-setsize', '4'); + expect(tester.getRows()[1]).not.toHaveAttribute('data-expanded'); + expect(tester.getRows()[1]).toHaveAttribute('data-has-child-items', 'true'); + expect(tester.getRows()[1]).toHaveAttribute('data-level', '1'); + expect(tester.getRows()[1]).toHaveAttribute('style', '--table-row-level: 1;'); + expect(tester.getRowHeaders()[1]).toHaveTextContent('Applications'); + + expect(tester.getRows()[2]).not.toHaveAttribute('aria-expanded'); + expect(tester.getRows()[2]).toHaveAttribute('aria-level', '1'); + expect(tester.getRows()[2]).toHaveAttribute('aria-posinset', '3'); + expect(tester.getRows()[2]).toHaveAttribute('aria-setsize', '4'); + expect(tester.getRows()[2]).not.toHaveAttribute('data-expanded'); + expect(tester.getRows()[2]).not.toHaveAttribute('data-has-child-items'); + expect(tester.getRows()[2]).toHaveAttribute('data-level', '1'); + expect(tester.getRows()[2]).toHaveAttribute('style', '--table-row-level: 1;'); + expect(tester.getRowHeaders()[2]).toHaveTextContent('2024 Financial Report'); + + expect(tester.getRows()[3]).not.toHaveAttribute('aria-expanded'); + expect(tester.getRows()[3]).toHaveAttribute('aria-level', '1'); + expect(tester.getRows()[3]).toHaveAttribute('aria-posinset', '4'); + expect(tester.getRows()[3]).toHaveAttribute('aria-setsize', '4'); + expect(tester.getRows()[3]).not.toHaveAttribute('data-expanded'); + expect(tester.getRows()[3]).not.toHaveAttribute('data-has-child-items'); + expect(tester.getRows()[3]).toHaveAttribute('data-level', '1'); + expect(tester.getRows()[3]).toHaveAttribute('style', '--table-row-level: 1;'); + expect(tester.getRowHeaders()[3]).toHaveTextContent('Job Posting'); }); it.each` @@ -282,59 +282,59 @@ describe('Treeble', () => { await tester.toggleRowExpansion({row: 0, interactionType}); - expect(tester.rows()).toHaveLength(7); - expect(tester.rows()[0]).toHaveAttribute('aria-expanded', 'true'); - expect(tester.rows()[0]).toHaveAttribute('aria-level', '1'); - expect(tester.rows()[0]).toHaveAttribute('aria-posinset', '1'); - expect(tester.rows()[0]).toHaveAttribute('aria-setsize', '4'); - expect(tester.rows()[0]).toHaveAttribute('data-expanded', 'true'); - expect(tester.rows()[0]).toHaveAttribute('data-has-child-items', 'true'); - expect(tester.rows()[0]).toHaveAttribute('data-level', '1'); - expect(tester.rows()[0]).toHaveAttribute('style', '--table-row-level: 1;'); - expect(tester.rowHeaders()[0]).toHaveTextContent('Games'); - for (let cell of tester.cells({element: tester.rows()[0]})) { + expect(tester.getRows()).toHaveLength(7); + expect(tester.getRows()[0]).toHaveAttribute('aria-expanded', 'true'); + expect(tester.getRows()[0]).toHaveAttribute('aria-level', '1'); + expect(tester.getRows()[0]).toHaveAttribute('aria-posinset', '1'); + expect(tester.getRows()[0]).toHaveAttribute('aria-setsize', '4'); + expect(tester.getRows()[0]).toHaveAttribute('data-expanded', 'true'); + expect(tester.getRows()[0]).toHaveAttribute('data-has-child-items', 'true'); + expect(tester.getRows()[0]).toHaveAttribute('data-level', '1'); + expect(tester.getRows()[0]).toHaveAttribute('style', '--table-row-level: 1;'); + expect(tester.getRowHeaders()[0]).toHaveTextContent('Games'); + for (let cell of tester.getCells({element: tester.getRows()[0]})) { expect(cell).toHaveAttribute('data-expanded'); expect(cell).toHaveAttribute('data-has-child-items', 'true'); expect(cell).toHaveAttribute('data-level', '1'); } - expect(tester.rows()[1]).not.toHaveAttribute('aria-expanded'); - expect(tester.rows()[1]).toHaveAttribute('aria-level', '2'); - expect(tester.rows()[1]).toHaveAttribute('aria-posinset', '1'); - expect(tester.rows()[1]).toHaveAttribute('aria-setsize', '3'); - expect(tester.rows()[1]).toHaveAttribute('style', '--table-row-level: 2;'); - expect(tester.rowHeaders()[1]).toHaveTextContent('Mario Kart'); - - expect(tester.rows()[2]).not.toHaveAttribute('aria-expanded'); - expect(tester.rows()[2]).toHaveAttribute('aria-level', '2'); - expect(tester.rows()[2]).toHaveAttribute('aria-posinset', '2'); - expect(tester.rows()[2]).toHaveAttribute('aria-setsize', '3'); - expect(tester.rows()[2]).toHaveAttribute('style', '--table-row-level: 2;'); - expect(tester.rowHeaders()[2]).toHaveTextContent('Tetris'); - - expect(tester.rows()[3]).not.toHaveAttribute('aria-expanded'); - expect(tester.rows()[3]).toHaveAttribute('aria-level', '2'); - expect(tester.rows()[3]).toHaveAttribute('aria-posinset', '3'); - expect(tester.rows()[3]).toHaveAttribute('aria-setsize', '3'); - expect(tester.rows()[3]).toHaveAttribute('style', '--table-row-level: 2;'); - expect(tester.rowHeaders()[3]).toHaveTextContent('Pac-Man'); - - expect(tester.rows()[4]).toHaveAttribute('aria-expanded', 'false'); - expect(tester.rows()[4]).toHaveAttribute('aria-level', '1'); - expect(tester.rows()[4]).toHaveAttribute('aria-posinset', '2'); - expect(tester.rows()[4]).toHaveAttribute('aria-setsize', '4'); - expect(tester.rows()[4]).toHaveAttribute('style', '--table-row-level: 1;'); - expect(tester.rowHeaders()[4]).toHaveTextContent('Applications'); - - expect(tester.rows()[5]).not.toHaveAttribute('aria-expanded'); - expect(tester.rows()[5]).toHaveAttribute('aria-level', '1'); - expect(tester.rows()[5]).toHaveAttribute('aria-posinset', '3'); - expect(tester.rows()[5]).toHaveAttribute('aria-setsize', '4'); - expect(tester.rows()[5]).toHaveAttribute('style', '--table-row-level: 1;'); - expect(tester.rowHeaders()[5]).toHaveTextContent('2024 Financial Report'); + expect(tester.getRows()[1]).not.toHaveAttribute('aria-expanded'); + expect(tester.getRows()[1]).toHaveAttribute('aria-level', '2'); + expect(tester.getRows()[1]).toHaveAttribute('aria-posinset', '1'); + expect(tester.getRows()[1]).toHaveAttribute('aria-setsize', '3'); + expect(tester.getRows()[1]).toHaveAttribute('style', '--table-row-level: 2;'); + expect(tester.getRowHeaders()[1]).toHaveTextContent('Mario Kart'); + + expect(tester.getRows()[2]).not.toHaveAttribute('aria-expanded'); + expect(tester.getRows()[2]).toHaveAttribute('aria-level', '2'); + expect(tester.getRows()[2]).toHaveAttribute('aria-posinset', '2'); + expect(tester.getRows()[2]).toHaveAttribute('aria-setsize', '3'); + expect(tester.getRows()[2]).toHaveAttribute('style', '--table-row-level: 2;'); + expect(tester.getRowHeaders()[2]).toHaveTextContent('Tetris'); + + expect(tester.getRows()[3]).not.toHaveAttribute('aria-expanded'); + expect(tester.getRows()[3]).toHaveAttribute('aria-level', '2'); + expect(tester.getRows()[3]).toHaveAttribute('aria-posinset', '3'); + expect(tester.getRows()[3]).toHaveAttribute('aria-setsize', '3'); + expect(tester.getRows()[3]).toHaveAttribute('style', '--table-row-level: 2;'); + expect(tester.getRowHeaders()[3]).toHaveTextContent('Pac-Man'); + + expect(tester.getRows()[4]).toHaveAttribute('aria-expanded', 'false'); + expect(tester.getRows()[4]).toHaveAttribute('aria-level', '1'); + expect(tester.getRows()[4]).toHaveAttribute('aria-posinset', '2'); + expect(tester.getRows()[4]).toHaveAttribute('aria-setsize', '4'); + expect(tester.getRows()[4]).toHaveAttribute('style', '--table-row-level: 1;'); + expect(tester.getRowHeaders()[4]).toHaveTextContent('Applications'); + + expect(tester.getRows()[5]).not.toHaveAttribute('aria-expanded'); + expect(tester.getRows()[5]).toHaveAttribute('aria-level', '1'); + expect(tester.getRows()[5]).toHaveAttribute('aria-posinset', '3'); + expect(tester.getRows()[5]).toHaveAttribute('aria-setsize', '4'); + expect(tester.getRows()[5]).toHaveAttribute('style', '--table-row-level: 1;'); + expect(tester.getRowHeaders()[5]).toHaveTextContent('2024 Financial Report'); await tester.toggleRowExpansion({row: 0, interactionType}); - expect(tester.rows()).toHaveLength(4); + expect(tester.getRows()).toHaveLength(4); } ); @@ -345,109 +345,109 @@ describe('Treeble', () => { ); let tester = utils.createTester('Table', {root: tree.getByTestId('treeble')}); - expect(tester.rows()).toHaveLength(7); - expect(tester.rows()[0]).toHaveAttribute('aria-expanded', 'true'); - expect(tester.rows()[0]).toHaveAttribute('aria-level', '1'); - expect(tester.rows()[0]).toHaveAttribute('aria-posinset', '1'); - expect(tester.rows()[0]).toHaveAttribute('aria-setsize', '4'); - - expect(tester.rowHeaders()[0]).toHaveTextContent('Games'); - - expect(tester.rows()[1]).not.toHaveAttribute('aria-expanded'); - expect(tester.rows()[1]).toHaveAttribute('aria-level', '2'); - expect(tester.rows()[1]).toHaveAttribute('aria-posinset', '1'); - expect(tester.rows()[1]).toHaveAttribute('aria-setsize', '3'); - expect(tester.rowHeaders()[1]).toHaveTextContent('Mario Kart'); - - expect(tester.rows()[2]).not.toHaveAttribute('aria-expanded'); - expect(tester.rows()[2]).toHaveAttribute('aria-level', '2'); - expect(tester.rows()[2]).toHaveAttribute('aria-posinset', '2'); - expect(tester.rows()[2]).toHaveAttribute('aria-setsize', '3'); - expect(tester.rowHeaders()[2]).toHaveTextContent('Tetris'); - - expect(tester.rows()[3]).not.toHaveAttribute('aria-expanded'); - expect(tester.rows()[3]).toHaveAttribute('aria-level', '2'); - expect(tester.rows()[3]).toHaveAttribute('aria-posinset', '3'); - expect(tester.rows()[3]).toHaveAttribute('aria-setsize', '3'); - expect(tester.rowHeaders()[3]).toHaveTextContent('Pac-Man'); - - expect(tester.rows()[4]).toHaveAttribute('aria-expanded', 'false'); - expect(tester.rows()[4]).toHaveAttribute('aria-level', '1'); - expect(tester.rows()[4]).toHaveAttribute('aria-posinset', '2'); - expect(tester.rows()[4]).toHaveAttribute('aria-setsize', '4'); - expect(tester.rowHeaders()[4]).toHaveTextContent('Applications'); - - expect(tester.rows()[5]).not.toHaveAttribute('aria-expanded'); - expect(tester.rows()[5]).toHaveAttribute('aria-level', '1'); - expect(tester.rows()[5]).toHaveAttribute('aria-posinset', '3'); - expect(tester.rows()[5]).toHaveAttribute('aria-setsize', '4'); - expect(tester.rowHeaders()[5]).toHaveTextContent('2024 Financial Report'); + expect(tester.getRows()).toHaveLength(7); + expect(tester.getRows()[0]).toHaveAttribute('aria-expanded', 'true'); + expect(tester.getRows()[0]).toHaveAttribute('aria-level', '1'); + expect(tester.getRows()[0]).toHaveAttribute('aria-posinset', '1'); + expect(tester.getRows()[0]).toHaveAttribute('aria-setsize', '4'); + + expect(tester.getRowHeaders()[0]).toHaveTextContent('Games'); + + expect(tester.getRows()[1]).not.toHaveAttribute('aria-expanded'); + expect(tester.getRows()[1]).toHaveAttribute('aria-level', '2'); + expect(tester.getRows()[1]).toHaveAttribute('aria-posinset', '1'); + expect(tester.getRows()[1]).toHaveAttribute('aria-setsize', '3'); + expect(tester.getRowHeaders()[1]).toHaveTextContent('Mario Kart'); + + expect(tester.getRows()[2]).not.toHaveAttribute('aria-expanded'); + expect(tester.getRows()[2]).toHaveAttribute('aria-level', '2'); + expect(tester.getRows()[2]).toHaveAttribute('aria-posinset', '2'); + expect(tester.getRows()[2]).toHaveAttribute('aria-setsize', '3'); + expect(tester.getRowHeaders()[2]).toHaveTextContent('Tetris'); + + expect(tester.getRows()[3]).not.toHaveAttribute('aria-expanded'); + expect(tester.getRows()[3]).toHaveAttribute('aria-level', '2'); + expect(tester.getRows()[3]).toHaveAttribute('aria-posinset', '3'); + expect(tester.getRows()[3]).toHaveAttribute('aria-setsize', '3'); + expect(tester.getRowHeaders()[3]).toHaveTextContent('Pac-Man'); + + expect(tester.getRows()[4]).toHaveAttribute('aria-expanded', 'false'); + expect(tester.getRows()[4]).toHaveAttribute('aria-level', '1'); + expect(tester.getRows()[4]).toHaveAttribute('aria-posinset', '2'); + expect(tester.getRows()[4]).toHaveAttribute('aria-setsize', '4'); + expect(tester.getRowHeaders()[4]).toHaveTextContent('Applications'); + + expect(tester.getRows()[5]).not.toHaveAttribute('aria-expanded'); + expect(tester.getRows()[5]).toHaveAttribute('aria-level', '1'); + expect(tester.getRows()[5]).toHaveAttribute('aria-posinset', '3'); + expect(tester.getRows()[5]).toHaveAttribute('aria-setsize', '4'); + expect(tester.getRowHeaders()[5]).toHaveTextContent('2024 Financial Report'); await tester.toggleRowExpansion({row: 4}); expect(onExpandedChange).toHaveBeenCalledTimes(1); expect(onExpandedChange).toHaveBeenCalledWith(new Set(['games', 'apps'])); - expect(tester.rows()).toHaveLength(10); - expect(tester.rows()[0]).toHaveAttribute('aria-expanded', 'true'); - expect(tester.rows()[0]).toHaveAttribute('aria-level', '1'); - expect(tester.rows()[0]).toHaveAttribute('aria-posinset', '1'); - expect(tester.rows()[0]).toHaveAttribute('aria-setsize', '4'); - expect(tester.rows()[0]).toHaveAttribute('data-expanded', 'true'); - expect(tester.rows()[0]).toHaveAttribute('data-has-child-items', 'true'); - expect(tester.rows()[0]).toHaveAttribute('data-level', '1'); - expect(tester.rowHeaders()[0]).toHaveTextContent('Games'); - - expect(tester.rows()[1]).not.toHaveAttribute('aria-expanded'); - expect(tester.rows()[1]).toHaveAttribute('aria-level', '2'); - expect(tester.rows()[1]).toHaveAttribute('aria-posinset', '1'); - expect(tester.rows()[1]).toHaveAttribute('aria-setsize', '3'); - expect(tester.rowHeaders()[1]).toHaveTextContent('Mario Kart'); - - expect(tester.rows()[2]).not.toHaveAttribute('aria-expanded'); - expect(tester.rows()[2]).toHaveAttribute('aria-level', '2'); - expect(tester.rows()[2]).toHaveAttribute('aria-posinset', '2'); - expect(tester.rows()[2]).toHaveAttribute('aria-setsize', '3'); - expect(tester.rowHeaders()[2]).toHaveTextContent('Tetris'); - - expect(tester.rows()[3]).not.toHaveAttribute('aria-expanded'); - expect(tester.rows()[3]).toHaveAttribute('aria-level', '2'); - expect(tester.rows()[3]).toHaveAttribute('aria-posinset', '3'); - expect(tester.rows()[3]).toHaveAttribute('aria-setsize', '3'); - expect(tester.rowHeaders()[3]).toHaveTextContent('Pac-Man'); - - expect(tester.rows()[4]).toHaveAttribute('aria-expanded', 'true'); - expect(tester.rows()[4]).toHaveAttribute('aria-level', '1'); - expect(tester.rows()[4]).toHaveAttribute('aria-posinset', '2'); - expect(tester.rows()[4]).toHaveAttribute('aria-setsize', '4'); - expect(tester.rowHeaders()[4]).toHaveTextContent('Applications'); - - expect(tester.rows()[5]).not.toHaveAttribute('aria-expanded'); - expect(tester.rows()[5]).toHaveAttribute('aria-level', '2'); - expect(tester.rows()[5]).toHaveAttribute('aria-posinset', '1'); - expect(tester.rows()[5]).toHaveAttribute('aria-setsize', '3'); - expect(tester.rowHeaders()[5]).toHaveTextContent('Photoshop'); - - expect(tester.rows()[6]).not.toHaveAttribute('aria-expanded'); - expect(tester.rows()[6]).toHaveAttribute('aria-level', '2'); - expect(tester.rows()[6]).toHaveAttribute('aria-posinset', '2'); - expect(tester.rows()[6]).toHaveAttribute('aria-setsize', '3'); - expect(tester.rowHeaders()[6]).toHaveTextContent('Premiere'); - - expect(tester.rows()[7]).not.toHaveAttribute('aria-expanded'); - expect(tester.rows()[7]).toHaveAttribute('aria-level', '2'); - expect(tester.rows()[7]).toHaveAttribute('aria-posinset', '3'); - expect(tester.rows()[7]).toHaveAttribute('aria-setsize', '3'); - expect(tester.rowHeaders()[7]).toHaveTextContent('Lightroom'); - - expect(tester.rows()[8]).not.toHaveAttribute('aria-expanded'); - expect(tester.rows()[8]).toHaveAttribute('aria-level', '1'); - expect(tester.rows()[8]).toHaveAttribute('aria-posinset', '3'); - expect(tester.rows()[8]).toHaveAttribute('aria-setsize', '4'); - expect(tester.rowHeaders()[8]).toHaveTextContent('2024 Financial Report'); + expect(tester.getRows()).toHaveLength(10); + expect(tester.getRows()[0]).toHaveAttribute('aria-expanded', 'true'); + expect(tester.getRows()[0]).toHaveAttribute('aria-level', '1'); + expect(tester.getRows()[0]).toHaveAttribute('aria-posinset', '1'); + expect(tester.getRows()[0]).toHaveAttribute('aria-setsize', '4'); + expect(tester.getRows()[0]).toHaveAttribute('data-expanded', 'true'); + expect(tester.getRows()[0]).toHaveAttribute('data-has-child-items', 'true'); + expect(tester.getRows()[0]).toHaveAttribute('data-level', '1'); + expect(tester.getRowHeaders()[0]).toHaveTextContent('Games'); + + expect(tester.getRows()[1]).not.toHaveAttribute('aria-expanded'); + expect(tester.getRows()[1]).toHaveAttribute('aria-level', '2'); + expect(tester.getRows()[1]).toHaveAttribute('aria-posinset', '1'); + expect(tester.getRows()[1]).toHaveAttribute('aria-setsize', '3'); + expect(tester.getRowHeaders()[1]).toHaveTextContent('Mario Kart'); + + expect(tester.getRows()[2]).not.toHaveAttribute('aria-expanded'); + expect(tester.getRows()[2]).toHaveAttribute('aria-level', '2'); + expect(tester.getRows()[2]).toHaveAttribute('aria-posinset', '2'); + expect(tester.getRows()[2]).toHaveAttribute('aria-setsize', '3'); + expect(tester.getRowHeaders()[2]).toHaveTextContent('Tetris'); + + expect(tester.getRows()[3]).not.toHaveAttribute('aria-expanded'); + expect(tester.getRows()[3]).toHaveAttribute('aria-level', '2'); + expect(tester.getRows()[3]).toHaveAttribute('aria-posinset', '3'); + expect(tester.getRows()[3]).toHaveAttribute('aria-setsize', '3'); + expect(tester.getRowHeaders()[3]).toHaveTextContent('Pac-Man'); + + expect(tester.getRows()[4]).toHaveAttribute('aria-expanded', 'true'); + expect(tester.getRows()[4]).toHaveAttribute('aria-level', '1'); + expect(tester.getRows()[4]).toHaveAttribute('aria-posinset', '2'); + expect(tester.getRows()[4]).toHaveAttribute('aria-setsize', '4'); + expect(tester.getRowHeaders()[4]).toHaveTextContent('Applications'); + + expect(tester.getRows()[5]).not.toHaveAttribute('aria-expanded'); + expect(tester.getRows()[5]).toHaveAttribute('aria-level', '2'); + expect(tester.getRows()[5]).toHaveAttribute('aria-posinset', '1'); + expect(tester.getRows()[5]).toHaveAttribute('aria-setsize', '3'); + expect(tester.getRowHeaders()[5]).toHaveTextContent('Photoshop'); + + expect(tester.getRows()[6]).not.toHaveAttribute('aria-expanded'); + expect(tester.getRows()[6]).toHaveAttribute('aria-level', '2'); + expect(tester.getRows()[6]).toHaveAttribute('aria-posinset', '2'); + expect(tester.getRows()[6]).toHaveAttribute('aria-setsize', '3'); + expect(tester.getRowHeaders()[6]).toHaveTextContent('Premiere'); + + expect(tester.getRows()[7]).not.toHaveAttribute('aria-expanded'); + expect(tester.getRows()[7]).toHaveAttribute('aria-level', '2'); + expect(tester.getRows()[7]).toHaveAttribute('aria-posinset', '3'); + expect(tester.getRows()[7]).toHaveAttribute('aria-setsize', '3'); + expect(tester.getRowHeaders()[7]).toHaveTextContent('Lightroom'); + + expect(tester.getRows()[8]).not.toHaveAttribute('aria-expanded'); + expect(tester.getRows()[8]).toHaveAttribute('aria-level', '1'); + expect(tester.getRows()[8]).toHaveAttribute('aria-posinset', '3'); + expect(tester.getRows()[8]).toHaveAttribute('aria-setsize', '4'); + expect(tester.getRowHeaders()[8]).toHaveTextContent('2024 Financial Report'); await tester.toggleRowExpansion({row: 4}); - expect(tester.rows()).toHaveLength(7); + expect(tester.getRows()).toHaveLength(7); expect(onExpandedChange).toHaveBeenCalledTimes(2); expect(onExpandedChange).toHaveBeenLastCalledWith(new Set(['games'])); @@ -458,49 +458,49 @@ describe('Treeble', () => { let tree = render(); let tester = utils.createTester('Table', {root: tree.getByTestId('treeble')}); - expect(tester.rows()).toHaveLength(7); - expect(tester.rows()[0]).toHaveAttribute('aria-expanded', 'true'); - expect(tester.rows()[0]).toHaveAttribute('aria-level', '1'); - expect(tester.rows()[0]).toHaveAttribute('aria-posinset', '1'); - expect(tester.rows()[0]).toHaveAttribute('aria-setsize', '4'); - expect(tester.rowHeaders()[0]).toHaveTextContent('Games'); - - expect(tester.rows()[1]).not.toHaveAttribute('aria-expanded'); - expect(tester.rows()[1]).toHaveAttribute('aria-level', '2'); - expect(tester.rows()[1]).toHaveAttribute('aria-posinset', '1'); - expect(tester.rows()[1]).toHaveAttribute('aria-setsize', '3'); - expect(tester.rowHeaders()[1]).toHaveTextContent('Mario Kart'); - - expect(tester.rows()[2]).not.toHaveAttribute('aria-expanded'); - expect(tester.rows()[2]).toHaveAttribute('aria-level', '2'); - expect(tester.rows()[2]).toHaveAttribute('aria-posinset', '2'); - expect(tester.rows()[2]).toHaveAttribute('aria-setsize', '3'); - expect(tester.rowHeaders()[2]).toHaveTextContent('Tetris'); - - expect(tester.rows()[3]).not.toHaveAttribute('aria-expanded'); - expect(tester.rows()[3]).toHaveAttribute('aria-level', '2'); - expect(tester.rows()[3]).toHaveAttribute('aria-posinset', '3'); - expect(tester.rows()[3]).toHaveAttribute('aria-setsize', '3'); - expect(tester.rowHeaders()[3]).toHaveTextContent('Pac-Man'); - - expect(tester.rows()[4]).toHaveAttribute('aria-expanded', 'false'); - expect(tester.rows()[4]).toHaveAttribute('aria-level', '1'); - expect(tester.rows()[4]).toHaveAttribute('aria-posinset', '2'); - expect(tester.rows()[4]).toHaveAttribute('aria-setsize', '4'); - expect(tester.rowHeaders()[4]).toHaveTextContent('Applications'); - - expect(tester.rows()[5]).not.toHaveAttribute('aria-expanded'); - expect(tester.rows()[5]).toHaveAttribute('aria-level', '1'); - expect(tester.rows()[5]).toHaveAttribute('aria-posinset', '3'); - expect(tester.rows()[5]).toHaveAttribute('aria-setsize', '4'); - expect(tester.rowHeaders()[5]).toHaveTextContent('2024 Financial Report'); + expect(tester.getRows()).toHaveLength(7); + expect(tester.getRows()[0]).toHaveAttribute('aria-expanded', 'true'); + expect(tester.getRows()[0]).toHaveAttribute('aria-level', '1'); + expect(tester.getRows()[0]).toHaveAttribute('aria-posinset', '1'); + expect(tester.getRows()[0]).toHaveAttribute('aria-setsize', '4'); + expect(tester.getRowHeaders()[0]).toHaveTextContent('Games'); + + expect(tester.getRows()[1]).not.toHaveAttribute('aria-expanded'); + expect(tester.getRows()[1]).toHaveAttribute('aria-level', '2'); + expect(tester.getRows()[1]).toHaveAttribute('aria-posinset', '1'); + expect(tester.getRows()[1]).toHaveAttribute('aria-setsize', '3'); + expect(tester.getRowHeaders()[1]).toHaveTextContent('Mario Kart'); + + expect(tester.getRows()[2]).not.toHaveAttribute('aria-expanded'); + expect(tester.getRows()[2]).toHaveAttribute('aria-level', '2'); + expect(tester.getRows()[2]).toHaveAttribute('aria-posinset', '2'); + expect(tester.getRows()[2]).toHaveAttribute('aria-setsize', '3'); + expect(tester.getRowHeaders()[2]).toHaveTextContent('Tetris'); + + expect(tester.getRows()[3]).not.toHaveAttribute('aria-expanded'); + expect(tester.getRows()[3]).toHaveAttribute('aria-level', '2'); + expect(tester.getRows()[3]).toHaveAttribute('aria-posinset', '3'); + expect(tester.getRows()[3]).toHaveAttribute('aria-setsize', '3'); + expect(tester.getRowHeaders()[3]).toHaveTextContent('Pac-Man'); + + expect(tester.getRows()[4]).toHaveAttribute('aria-expanded', 'false'); + expect(tester.getRows()[4]).toHaveAttribute('aria-level', '1'); + expect(tester.getRows()[4]).toHaveAttribute('aria-posinset', '2'); + expect(tester.getRows()[4]).toHaveAttribute('aria-setsize', '4'); + expect(tester.getRowHeaders()[4]).toHaveTextContent('Applications'); + + expect(tester.getRows()[5]).not.toHaveAttribute('aria-expanded'); + expect(tester.getRows()[5]).toHaveAttribute('aria-level', '1'); + expect(tester.getRows()[5]).toHaveAttribute('aria-posinset', '3'); + expect(tester.getRows()[5]).toHaveAttribute('aria-setsize', '4'); + expect(tester.getRowHeaders()[5]).toHaveTextContent('2024 Financial Report'); await tester.toggleRowExpansion({row: 4}); expect(onExpandedChange).toHaveBeenCalledTimes(1); expect(onExpandedChange).toHaveBeenCalledWith(new Set(['games', 'apps'])); - expect(tester.rows()).toHaveLength(7); // controlled + expect(tester.getRows()).toHaveLength(7); // controlled }); it('supports keyboard navigation of flattened rows', async () => { @@ -509,16 +509,16 @@ describe('Treeble', () => { await user.tab(); - for (let i = 0; i < tester.rows().length; i++) { - expect(document.activeElement).toBe(tester.rows()[i]); + for (let i = 0; i < tester.getRows().length; i++) { + expect(document.activeElement).toBe(tester.getRows()[i]); await user.keyboard('{ArrowDown}'); } await user.keyboard('{Home}'); - expect(document.activeElement).toBe(tester.rows()[0]); + expect(document.activeElement).toBe(tester.getRows()[0]); await user.keyboard('{End}'); - expect(document.activeElement).toBe(tester.rows()[tester.rows().length - 1]); + expect(document.activeElement).toBe(tester.getRows()[tester.getRows().length - 1]); }); it('supports keyboard navigation of cells', async () => { @@ -526,25 +526,25 @@ describe('Treeble', () => { let tester = utils.createTester('Table', {root: tree.getByTestId('treeble')}); await user.tab(); - expect(document.activeElement).toBe(tester.rows()[0]); - expect(tester.rows()[0]).toHaveAttribute('aria-expanded', 'false'); + expect(document.activeElement).toBe(tester.getRows()[0]); + expect(tester.getRows()[0]).toHaveAttribute('aria-expanded', 'false'); await user.keyboard('{ArrowRight}'); - expect(document.activeElement).toBe(tester.rows()[0]); - expect(tester.rows()[0]).toHaveAttribute('aria-expanded', 'true'); + expect(document.activeElement).toBe(tester.getRows()[0]); + expect(tester.getRows()[0]).toHaveAttribute('aria-expanded', 'true'); - let cells = [tester.rowHeaders()[0], ...tester.cells({element: tester.rows()[0]})]; + let cells = [tester.getRowHeaders()[0], ...tester.getCells({element: tester.getRows()[0]})]; for (let cell of cells) { await user.keyboard('{ArrowRight}'); expect(document.activeElement).toBe(cell); } await user.keyboard('{ArrowRight}'); - expect(document.activeElement).toBe(tester.rows()[0]); + expect(document.activeElement).toBe(tester.getRows()[0]); await user.keyboard('{ArrowLeft}'); - expect(document.activeElement).toBe(tester.rows()[0]); - expect(tester.rows()[0]).toHaveAttribute('aria-expanded', 'false'); + expect(document.activeElement).toBe(tester.getRows()[0]); + expect(tester.getRows()[0]).toHaveAttribute('aria-expanded', 'false'); for (let cell of cells.reverse()) { await user.keyboard('{ArrowLeft}'); @@ -552,7 +552,7 @@ describe('Treeble', () => { } await user.keyboard('{ArrowLeft}'); - expect(document.activeElement).toBe(tester.rows()[0]); + expect(document.activeElement).toBe(tester.getRows()[0]); }); it('supports selection', async () => { @@ -568,7 +568,7 @@ describe('Treeble', () => { await tester.toggleRowSelection({row: 0}); await user.keyboard('{Shift>}'); - await user.click(tester.rows()[2]); + await user.click(tester.getRows()[2]); await user.keyboard('{/Shift}'); expect(onSelectionChange).toHaveBeenCalledTimes(2); @@ -628,7 +628,7 @@ describe('Treeble', () => { await user.keyboard('{Enter}'); act(() => jest.runAllTimers()); - expect(tester.rowHeaders().map(r => r.textContent)).toEqual([ + expect(tester.getRowHeaders().map(r => r.textContent)).toEqual([ '>Documents', '>Project', 'Image 2', diff --git a/packages/react-aria-components/test/VirtualizedMenu.test.tsx b/packages/react-aria-components/test/VirtualizedMenu.test.tsx index 86654885db0..053469968de 100644 --- a/packages/react-aria-components/test/VirtualizedMenu.test.tsx +++ b/packages/react-aria-components/test/VirtualizedMenu.test.tsx @@ -71,7 +71,7 @@ describe('virtualized menu', () => { tester.setInteractionType('mouse'); await tester.open(); let items = getAllByRole('menuitem'); - let menu = tester.menu(); + let menu = tester.getMenu(); expect(menu).toBeInTheDocument(); expect(items[0]).toHaveAttribute('aria-posinset', '1'); expect(items[0]).toHaveAttribute('aria-setsize', '50'); From 10870bf12a8057e6b109e3ab57d90217a7a7cae8 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Fri, 8 May 2026 16:30:43 -0700 Subject: [PATCH 27/31] update table util for rowgroups and table footer, update formatTargetNode, fix missing menu tests from bad merge --- packages/@react-aria/test-utils/src/table.ts | 14 ++++++-- packages/@react-aria/test-utils/src/utils.ts | 2 +- .../react-aria-components/test/Menu.test.tsx | 33 +++++++++++++++++++ .../react-aria-components/test/Table.test.js | 18 ++++++++-- 4 files changed, 61 insertions(+), 6 deletions(-) diff --git a/packages/@react-aria/test-utils/src/table.ts b/packages/@react-aria/test-utils/src/table.ts index 2281fbb181d..b84d6be7c17 100644 --- a/packages/@react-aria/test-utils/src/table.ts +++ b/packages/@react-aria/test-utils/src/table.ts @@ -532,9 +532,13 @@ export class TableTester { } /** - * Returns the rows within the table if any. + * Returns the rows within the table if any. Can be filtered to a specific row group if provided via `element`. */ - getRows(): HTMLElement[] { + getRows(opts: {element?: HTMLElement} = {}): HTMLElement[] { + let {element} = opts; + if (element != null) { + return within(element).queryAllByRole('row'); + } return this.getRowGroups() .slice(1) .flatMap(rowGroup => within(rowGroup).queryAllByRole('row')); @@ -551,7 +555,11 @@ export class TableTester { * Returns the footer rows within the table if any. */ getFooterRows(): HTMLElement[] { - let footerRowGroup = this.getRowGroups()[2]; + let rowGroups = this.getRowGroups(); + if (rowGroups.length < 3) { + return []; + } + let footerRowGroup = rowGroups.at(-1); return footerRowGroup ? within(footerRowGroup).queryAllByRole('row') : []; } diff --git a/packages/@react-aria/test-utils/src/utils.ts b/packages/@react-aria/test-utils/src/utils.ts index 090453af9cd..2be1a2a947d 100644 --- a/packages/@react-aria/test-utils/src/utils.ts +++ b/packages/@react-aria/test-utils/src/utils.ts @@ -49,7 +49,7 @@ export function getMetaKey(): 'MetaLeft' | 'ControlLeft' { export function formatTargetNode(value: number | string | HTMLElement): string { if (typeof HTMLElement !== 'undefined' && value instanceof HTMLElement) { - return value.outerHTML; + return (value.cloneNode(false) as HTMLElement).outerHTML; } return String(value); } diff --git a/packages/react-aria-components/test/Menu.test.tsx b/packages/react-aria-components/test/Menu.test.tsx index 938dec20a83..3efe8997db2 100644 --- a/packages/react-aria-components/test/Menu.test.tsx +++ b/packages/react-aria-components/test/Menu.test.tsx @@ -2105,6 +2105,39 @@ AriaMenuTests({ ), + singleSelection: () => render(), + multipleSelection: () => render(), + multipleMenus: () => + render( + <> + + + + + +
Heading 1
+ Foo + Bar + Baz +
+
+
+
+ + + + + +
Heading 1
+ Foo + Bar + Baz +
+
+
+
+ + ), submenus: () => render( diff --git a/packages/react-aria-components/test/Table.test.js b/packages/react-aria-components/test/Table.test.js index 203032ae997..e1ce21f42bd 100644 --- a/packages/react-aria-components/test/Table.test.js +++ b/packages/react-aria-components/test/Table.test.js @@ -3368,18 +3368,29 @@ describe('Table', () => { ))} + + + Total + Blah + + ); let tableTester = testUtilUser.createTester('Table', {root}); let groups = tableTester.getRowGroups(); - expect(groups).toHaveLength(4); + expect(groups).toHaveLength(5); expect(groups[0].tagName).toBe('THEAD'); expect(groups[1].tagName).toBe('TBODY'); expect(groups[2].tagName).toBe('TBODY'); expect(groups[3].tagName).toBe('TBODY'); - expect(tableTester.getRows()).toHaveLength(10); + expect(tableTester.getRows()).toHaveLength(11); + + expect(tableTester.getRows({element: 1})).toHaveLength(3); + expect(tableTester.getRows({element: groups[1]})).toHaveLength(3); + expect(tableTester.getRows({element: 2})).toHaveLength(3); + expect(tableTester.getRows({element: 3})).toHaveLength(4); await user.tab(); for (let row of tableTester.getRows()) { @@ -3391,6 +3402,9 @@ describe('Table', () => { await user.keyboard('{ArrowUp}'); expect(document.activeElement).toBe(row); } + + expect(tableTester.getFooterRows()).toHaveLength(1); + expect(tableTester.getFooterRows()).toHaveTextContent('Blah'); }); }); From c109290618d1606218657895238b697808337411 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Fri, 8 May 2026 17:03:48 -0700 Subject: [PATCH 28/31] formatting --- .../@adobe/react-spectrum/test/combobox/ComboBox.test.js | 5 ++++- packages/@react-aria/test-utils/src/act.ts | 3 ++- packages/@react-aria/test-utils/src/gridlist.ts | 4 +++- packages/@react-spectrum/s2/test/Combobox.test.tsx | 4 +++- packages/@react-spectrum/s2/test/RadioGroup.test.tsx | 5 ++++- packages/react-aria-components/test/Table.test.js | 7 +++---- packages/react-aria-components/test/Treeble.test.js | 5 ++++- 7 files changed, 23 insertions(+), 10 deletions(-) diff --git a/packages/@adobe/react-spectrum/test/combobox/ComboBox.test.js b/packages/@adobe/react-spectrum/test/combobox/ComboBox.test.js index cf5386714b1..fc26e484870 100644 --- a/packages/@adobe/react-spectrum/test/combobox/ComboBox.test.js +++ b/packages/@adobe/react-spectrum/test/combobox/ComboBox.test.js @@ -566,7 +566,10 @@ describe('ComboBox', function () { expect(comboboxTester.getCombobox().value).toBe('One'); await comboboxTester.open(); - expect(comboboxTester.getCombobox()).toHaveAttribute('aria-activedescendant', options[0].id); + expect(comboboxTester.getCombobox()).toHaveAttribute( + 'aria-activedescendant', + options[0].id + ); }); it('shows all items', async function () { diff --git a/packages/@react-aria/test-utils/src/act.ts b/packages/@react-aria/test-utils/src/act.ts index b8ecf325d31..a96e58a73f1 100644 --- a/packages/@react-aria/test-utils/src/act.ts +++ b/packages/@react-aria/test-utils/src/act.ts @@ -22,9 +22,10 @@ if (typeof React.act === 'function') { export const act: typeof actImpl = ((fn: any) => { // only wrap in act if in test environment, breaks vite browser test if test utils are used otherwise - // @ts-ignore if ( + // @ts-ignore typeof IS_REACT_ACT_ENVIRONMENT === 'boolean' + // @ts-ignore ? IS_REACT_ACT_ENVIRONMENT : typeof jest !== 'undefined' ) { diff --git a/packages/@react-aria/test-utils/src/gridlist.ts b/packages/@react-aria/test-utils/src/gridlist.ts index 2567f1b8abd..b6090aa02cb 100644 --- a/packages/@react-aria/test-utils/src/gridlist.ts +++ b/packages/@react-aria/test-utils/src/gridlist.ts @@ -65,7 +65,9 @@ export class GridListTester { if (typeof indexOrText === 'number') { row = this.getRows()[indexOrText]; } else if (typeof indexOrText === 'string') { - row = within(this.getGridlist()!).getByText(indexOrText).closest('[role=row]')! as HTMLElement; + row = within(this.getGridlist()!) + .getByText(indexOrText) + .closest('[role=row]')! as HTMLElement; } return row; diff --git a/packages/@react-spectrum/s2/test/Combobox.test.tsx b/packages/@react-spectrum/s2/test/Combobox.test.tsx index 54affd53d4a..d62e7e6e9cb 100644 --- a/packages/@react-spectrum/s2/test/Combobox.test.tsx +++ b/packages/@react-spectrum/s2/test/Combobox.test.tsx @@ -81,7 +81,9 @@ describe('Combobox', () => { expect(options).toHaveLength(1); expect(comboboxTester.getListbox()).toBeTruthy(); expect(options[0]).toHaveTextContent('No results'); - expect(within(comboboxTester.getListbox()!).getByTestId('loadMoreSentinel')).toBeInTheDocument(); + expect( + within(comboboxTester.getListbox()!).getByTestId('loadMoreSentinel') + ).toBeInTheDocument(); }); it('should only call loadMore whenever intersection is detected', async () => { diff --git a/packages/@react-spectrum/s2/test/RadioGroup.test.tsx b/packages/@react-spectrum/s2/test/RadioGroup.test.tsx index 5f633df9748..79d3bb76085 100644 --- a/packages/@react-spectrum/s2/test/RadioGroup.test.tsx +++ b/packages/@react-spectrum/s2/test/RadioGroup.test.tsx @@ -54,7 +54,10 @@ describe('RadioGroup', () => { root: getByRole('radiogroup'), direction }); - expect(radioGroupTester.getRadioGroup()).toHaveAttribute('aria-orientation', props.orientation); + expect(radioGroupTester.getRadioGroup()).toHaveAttribute( + 'aria-orientation', + props.orientation + ); let radios = radioGroupTester.getRadios(); await radioGroupTester.triggerRadio({radio: radios[0]}); expect(radios[0]).toBeChecked(); diff --git a/packages/react-aria-components/test/Table.test.js b/packages/react-aria-components/test/Table.test.js index e1ce21f42bd..6aa69f336cc 100644 --- a/packages/react-aria-components/test/Table.test.js +++ b/packages/react-aria-components/test/Table.test.js @@ -3387,10 +3387,9 @@ describe('Table', () => { expect(groups[3].tagName).toBe('TBODY'); expect(tableTester.getRows()).toHaveLength(11); - expect(tableTester.getRows({element: 1})).toHaveLength(3); expect(tableTester.getRows({element: groups[1]})).toHaveLength(3); - expect(tableTester.getRows({element: 2})).toHaveLength(3); - expect(tableTester.getRows({element: 3})).toHaveLength(4); + expect(tableTester.getRows({element: groups[2]})).toHaveLength(3); + expect(tableTester.getRows({element: groups[3]})).toHaveLength(4); await user.tab(); for (let row of tableTester.getRows()) { @@ -3404,7 +3403,7 @@ describe('Table', () => { } expect(tableTester.getFooterRows()).toHaveLength(1); - expect(tableTester.getFooterRows()).toHaveTextContent('Blah'); + expect(tableTester.getFooterRows()[0]).toHaveTextContent('Blah'); }); }); diff --git a/packages/react-aria-components/test/Treeble.test.js b/packages/react-aria-components/test/Treeble.test.js index e3517551bb4..c551171ab67 100644 --- a/packages/react-aria-components/test/Treeble.test.js +++ b/packages/react-aria-components/test/Treeble.test.js @@ -228,7 +228,10 @@ describe('Treeble', () => { let button = within(tester.getRowHeaders()[0]).getByRole('button'); expect(button).toHaveAttribute('aria-label', 'Expand'); - expect(button).toHaveAttribute('aria-labelledby', `${button.id} ${tester.getRowHeaders()[0].id}`); + expect(button).toHaveAttribute( + 'aria-labelledby', + `${button.id} ${tester.getRowHeaders()[0].id}` + ); expect(button).toHaveAttribute('tabindex', '-1'); expect(tester.getRows()[1]).toHaveAttribute('aria-expanded', 'false'); From 6d01a4cd1281311a69d61fc22c4b5b20ec0b28bd Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Fri, 8 May 2026 17:10:11 -0700 Subject: [PATCH 29/31] fix test from bad merge --- .../@adobe/react-spectrum/test/menu/MenuTrigger.test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/@adobe/react-spectrum/test/menu/MenuTrigger.test.js b/packages/@adobe/react-spectrum/test/menu/MenuTrigger.test.js index 043bf3d7807..0db0865daf5 100644 --- a/packages/@adobe/react-spectrum/test/menu/MenuTrigger.test.js +++ b/packages/@adobe/react-spectrum/test/menu/MenuTrigger.test.js @@ -279,15 +279,15 @@ describe('MenuTrigger', function () { } await menuTester.toggleOptionSelection({ - option: 'Foo', + option: 'Bar', menuSelectionMode: 'single', closesOnSelect: false }); if (Component === MenuTrigger) { - expect(onSelectionChange).toBeCalledTimes(1); + expect(onSelectionChange).toBeCalledTimes(2); } else { - expect(onSelect).toBeCalledTimes(1); + expect(onSelect).toBeCalledTimes(2); } expect(menuTester.getMenu()).toBeInTheDocument(); From 41fb37828eae053cfe7cb633eccb55fb74f56021 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Fri, 8 May 2026 17:12:19 -0700 Subject: [PATCH 30/31] add missing aria labels to browser tests --- packages/@react-spectrum/s2/test/CheckboxGroup.browser.test.tsx | 2 +- packages/@react-spectrum/s2/test/RadioGroup.browser.test.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@react-spectrum/s2/test/CheckboxGroup.browser.test.tsx b/packages/@react-spectrum/s2/test/CheckboxGroup.browser.test.tsx index c64d8dcfeb9..be123bbc927 100644 --- a/packages/@react-spectrum/s2/test/CheckboxGroup.browser.test.tsx +++ b/packages/@react-spectrum/s2/test/CheckboxGroup.browser.test.tsx @@ -19,7 +19,7 @@ import {User} from '@react-aria/test-utils'; function CheckboxGroupExample() { return ( - + Product Updates diff --git a/packages/@react-spectrum/s2/test/RadioGroup.browser.test.tsx b/packages/@react-spectrum/s2/test/RadioGroup.browser.test.tsx index 8534e235a91..b951b8baaeb 100644 --- a/packages/@react-spectrum/s2/test/RadioGroup.browser.test.tsx +++ b/packages/@react-spectrum/s2/test/RadioGroup.browser.test.tsx @@ -18,7 +18,7 @@ import {User} from '@react-aria/test-utils'; function RadioGroupExample() { return ( - + Standard Shipping (Free) From 38ec8e242d3106f6ff0b7077eed263f6be499002 Mon Sep 17 00:00:00 2001 From: Daniel Lu Date: Fri, 8 May 2026 17:13:40 -0700 Subject: [PATCH 31/31] how did this not auto format --- packages/@react-aria/test-utils/src/act.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@react-aria/test-utils/src/act.ts b/packages/@react-aria/test-utils/src/act.ts index a96e58a73f1..e824a2ea56f 100644 --- a/packages/@react-aria/test-utils/src/act.ts +++ b/packages/@react-aria/test-utils/src/act.ts @@ -25,8 +25,8 @@ export const act: typeof actImpl = ((fn: any) => { if ( // @ts-ignore typeof IS_REACT_ACT_ENVIRONMENT === 'boolean' - // @ts-ignore - ? IS_REACT_ACT_ENVIRONMENT + ? // @ts-ignore + IS_REACT_ACT_ENVIRONMENT : typeof jest !== 'undefined' ) { return actImpl(fn);