diff --git a/eslint.config.mjs b/eslint.config.mjs index ad336dabaf3..cd41e502778 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -501,6 +501,15 @@ export default [{ message: "Use getOwnerDocument from @react-aria/utils instead.", }], }, +}, { + files: [ + "packages/@react-aria/test-utils/src/**/*.ts", + "packages/@react-aria/test-utils/src/**/*.tsx", + ], + + rules: { + "rsp-rules/no-non-shadow-contains": OFF, + }, }, { files: ["packages/@react-spectrum/s2/**", "packages/dev/s2-docs/**"], diff --git a/packages/@react-aria/test-utils/package.json b/packages/@react-aria/test-utils/package.json index ec18ecb6981..4393a60b129 100644 --- a/packages/@react-aria/test-utils/package.json +++ b/packages/@react-aria/test-utils/package.json @@ -26,7 +26,6 @@ "url": "https://github.com/adobe/react-spectrum" }, "dependencies": { - "@react-aria/utils": "^3.32.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { diff --git a/packages/@react-aria/test-utils/src/checkboxgroup.ts b/packages/@react-aria/test-utils/src/checkboxgroup.ts index 7451b7ec9cb..54e436a5cab 100644 --- a/packages/@react-aria/test-utils/src/checkboxgroup.ts +++ b/packages/@react-aria/test-utils/src/checkboxgroup.ts @@ -12,7 +12,6 @@ import {act, within} from '@testing-library/react'; import {CheckboxGroupTesterOpts, UserOpts} from './types'; -import {nodeContains} from '@react-aria/utils'; import {pressElement} from './events'; interface TriggerCheckboxOptions { @@ -95,7 +94,7 @@ export class CheckboxGroupTester { throw new Error('Checkbox provided is not in the checkbox group.'); } - if (!nodeContains(this.checkboxgroup, document.activeElement)) { + if (!this.checkboxgroup.contains(document.activeElement)) { act(() => checkboxes[0].focus()); } diff --git a/packages/@react-aria/test-utils/src/combobox.ts b/packages/@react-aria/test-utils/src/combobox.ts index 3dfb46c3946..d95ac6f5711 100644 --- a/packages/@react-aria/test-utils/src/combobox.ts +++ b/packages/@react-aria/test-utils/src/combobox.ts @@ -12,7 +12,6 @@ import {act, waitFor, within} from '@testing-library/react'; import {ComboBoxTesterOpts, UserOpts} from './types'; -import {nodeContains} from '@react-aria/utils'; interface ComboBoxOpenOpts { /** @@ -177,7 +176,7 @@ export class ComboBoxTester { if (option.getAttribute('href') == null) { await waitFor(() => { - if (nodeContains(document, listbox)) { + if (document.contains(listbox)) { throw new Error('Expected listbox element to not be in the document after selecting an option'); } else { return true; @@ -199,7 +198,7 @@ export class ComboBoxTester { await this.user.keyboard('[Escape]'); await waitFor(() => { - if (nodeContains(document, listbox)) { + if (document.contains(listbox)) { throw new Error('Expected listbox element to not be in the document after selecting an option'); } else { return true; diff --git a/packages/@react-aria/test-utils/src/dialog.ts b/packages/@react-aria/test-utils/src/dialog.ts index 10e3b22d0f5..213c86c2b1a 100644 --- a/packages/@react-aria/test-utils/src/dialog.ts +++ b/packages/@react-aria/test-utils/src/dialog.ts @@ -12,7 +12,6 @@ import {act, waitFor, within} from '@testing-library/react'; import {DialogTesterOpts, UserOpts} from './types'; -import {nodeContains} from '@react-aria/utils'; interface DialogOpenOpts { /** @@ -97,7 +96,7 @@ export class DialogTester { } }); - if (dialog && document.activeElement !== this._trigger && nodeContains(dialog, document.activeElement)) { + if (dialog && document.activeElement !== this._trigger && dialog.contains(document.activeElement)) { this._dialog = dialog; } else { throw new Error('New modal dialog doesnt contain the active element OR the active element is still the trigger. Uncertain if the proper modal dialog was found'); @@ -114,7 +113,7 @@ export class DialogTester { if (dialog) { await this.user.keyboard('[Escape]'); await waitFor(() => { - if (nodeContains(document, dialog)) { + if (document.contains(dialog)) { throw new Error('Expected the dialog to not be in the document after closing it.'); } else { this._dialog = undefined; @@ -139,6 +138,6 @@ export class DialogTester { * Returns the dialog if present. */ get dialog(): HTMLElement | null { - return this._dialog && nodeContains(document, this._dialog) ? this._dialog : 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 ebf8af799b6..d5d1c21e082 100644 --- a/packages/@react-aria/test-utils/src/gridlist.ts +++ b/packages/@react-aria/test-utils/src/gridlist.ts @@ -13,7 +13,6 @@ import {act, within} from '@testing-library/react'; import {getAltKey, getMetaKey, pressElement, triggerLongPress} from './events'; import {GridListTesterOpts, GridRowActionOpts, ToggleGridRowOpts, UserOpts} from './types'; -import {nodeContains} from '@react-aria/utils'; interface GridListToggleRowOpts extends ToggleGridRowOpts {} interface GridListRowActionOpts extends GridRowActionOpts {} @@ -67,13 +66,13 @@ export class GridListTester { throw new Error('Option provided is not in the gridlist'); } - if (document.activeElement !== this._gridlist && !nodeContains(this._gridlist, document.activeElement)) { + if (document.activeElement !== this._gridlist && !this._gridlist.contains(document.activeElement)) { act(() => this._gridlist.focus()); } if (document.activeElement === this._gridlist) { await this.user.keyboard(`${selectionOnNav === 'none' ? `[${altKey}>]` : ''}[ArrowDown]${selectionOnNav === 'none' ? `[/${altKey}]` : ''}`); - } else if (nodeContains(this._gridlist, document.activeElement) && document.activeElement!.getAttribute('role') !== 'row') { + } else if (this._gridlist.contains(document.activeElement) && document.activeElement!.getAttribute('role') !== 'row') { do { await this.user.keyboard('[ArrowLeft]'); } while (document.activeElement!.getAttribute('role') !== 'row'); diff --git a/packages/@react-aria/test-utils/src/listbox.ts b/packages/@react-aria/test-utils/src/listbox.ts index d8fcab4a772..cac8d9d78bc 100644 --- a/packages/@react-aria/test-utils/src/listbox.ts +++ b/packages/@react-aria/test-utils/src/listbox.ts @@ -13,7 +13,6 @@ import {act, within} from '@testing-library/react'; import {getAltKey, getMetaKey, pressElement, triggerLongPress} from './events'; import {ListBoxTesterOpts, UserOpts} from './types'; -import {nodeContains} from '@react-aria/utils'; interface ListBoxToggleOptionOpts { /** @@ -104,7 +103,7 @@ export class ListBoxTester { throw new Error('Option provided is not in the listbox'); } - if (document.activeElement !== this._listbox && !nodeContains(this._listbox, document.activeElement)) { + if (document.activeElement !== this._listbox && !this._listbox.contains(document.activeElement)) { act(() => this._listbox.focus()); await this.user.keyboard(`${selectionOnNav === 'none' ? `[${altKey}>]` : ''}[ArrowDown]${selectionOnNav === 'none' ? `[/${altKey}]` : ''}`); } diff --git a/packages/@react-aria/test-utils/src/menu.ts b/packages/@react-aria/test-utils/src/menu.ts index f3dcdd3bdd0..87af5c11fd0 100644 --- a/packages/@react-aria/test-utils/src/menu.ts +++ b/packages/@react-aria/test-utils/src/menu.ts @@ -12,7 +12,6 @@ import {act, waitFor, within} from '@testing-library/react'; import {MenuTesterOpts, UserOpts} from './types'; -import {nodeContains} from '@react-aria/utils'; import {triggerLongPress} from './events'; interface MenuOpenOpts { @@ -216,7 +215,7 @@ export class MenuTester { return; } - if (document.activeElement !== menu && !nodeContains(menu, document.activeElement)) { + if (document.activeElement !== menu && !menu.contains(document.activeElement)) { act(() => menu.focus()); } @@ -263,7 +262,7 @@ export class MenuTester { // close. In React 16, focus actually makes it all the way to the root menu's submenu trigger so we need check the root menu if (this._isSubmenu) { await waitFor(() => { - if (document.activeElement === this.trigger || nodeContains(this._rootMenu, document.activeElement)) { + if (document.activeElement === this.trigger || this._rootMenu?.contains(document.activeElement)) { throw new Error('Expected focus after selecting an submenu option to move away from the original submenu trigger.'); } else { return true; @@ -343,7 +342,7 @@ export class MenuTester { private async keyboardNavigateToOption(opts: {option: HTMLElement}) { let {option} = opts; let options = this.options(); - let targetIndex = options.findIndex(opt => (opt === option) || nodeContains(opt, option)); + let targetIndex = options.findIndex(opt => (opt === option) || opt.contains(option)); if (targetIndex === -1) { throw new Error('Option provided is not in the menu'); @@ -379,7 +378,7 @@ export class MenuTester { } }); - if (nodeContains(document, menu)) { + if (document.contains(menu)) { throw new Error('Expected the menu to not be in the document after closing it.'); } } diff --git a/packages/@react-aria/test-utils/src/radiogroup.ts b/packages/@react-aria/test-utils/src/radiogroup.ts index bdcbfce9730..6c1d0e38c9e 100644 --- a/packages/@react-aria/test-utils/src/radiogroup.ts +++ b/packages/@react-aria/test-utils/src/radiogroup.ts @@ -12,7 +12,6 @@ import {act, within} from '@testing-library/react'; import {Direction, Orientation, RadioGroupTesterOpts, UserOpts} from './types'; -import {nodeContains} from '@react-aria/utils'; import {pressElement} from './events'; interface TriggerRadioOptions { @@ -95,7 +94,7 @@ export class RadioGroupTester { throw new Error('Radio provided is not in the radio group.'); } - if (!nodeContains(this.radiogroup, document.activeElement)) { + if (!this.radiogroup.contains(document.activeElement)) { let selectedRadio = this.selectedRadio; if (selectedRadio != null) { act(() => selectedRadio.focus()); diff --git a/packages/@react-aria/test-utils/src/select.ts b/packages/@react-aria/test-utils/src/select.ts index 56a9372dfe5..4cce164f53f 100644 --- a/packages/@react-aria/test-utils/src/select.ts +++ b/packages/@react-aria/test-utils/src/select.ts @@ -11,7 +11,6 @@ */ import {act, waitFor, within} from '@testing-library/react'; -import {nodeContains} from '@react-aria/utils'; import {SelectTesterOpts, UserOpts} from './types'; interface SelectOpenOpts { @@ -111,7 +110,7 @@ export class SelectTester { } }); - if (listbox && nodeContains(document, listbox)) { + if (listbox && document.contains(listbox)) { throw new Error('Expected the select element listbox to not be in the document after closing the dropdown.'); } } @@ -192,7 +191,7 @@ export class SelectTester { return; } - if (document.activeElement !== listbox && !nodeContains(listbox, document.activeElement)) { + if (document.activeElement !== listbox && !listbox.contains(document.activeElement)) { act(() => listbox.focus()); } await this.keyboardNavigateToOption({option}); @@ -215,7 +214,7 @@ export class SelectTester { } }); - if (nodeContains(document, listbox)) { + if (document.contains(listbox)) { throw new Error('Expected select element listbox to not be in the document after selecting an option'); } } diff --git a/packages/@react-aria/test-utils/src/table.ts b/packages/@react-aria/test-utils/src/table.ts index 24071fd3b90..95d4e6fe184 100644 --- a/packages/@react-aria/test-utils/src/table.ts +++ b/packages/@react-aria/test-utils/src/table.ts @@ -13,7 +13,6 @@ import {act, waitFor, within} from '@testing-library/react'; import {getAltKey, getMetaKey, pressElement, triggerLongPress} from './events'; import {GridRowActionOpts, TableTesterOpts, ToggleGridRowOpts, UserOpts} from './types'; -import {nodeContains} from '@react-aria/utils'; interface TableToggleRowOpts extends ToggleGridRowOpts {} interface TableToggleSortOpts { @@ -66,7 +65,7 @@ export class TableTester { } // Move focus into the table - if (document.activeElement !== this._table && !nodeContains(this._table, document.activeElement)) { + if (document.activeElement !== this._table && !this._table.contains(document.activeElement)) { act(() => this._table.focus()); } @@ -75,14 +74,14 @@ export class TableTester { } // 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 (nodeContains(this.rowGroups[0], document.activeElement)) { + if (this.rowGroups[0].contains(document.activeElement)) { do { await this.user.keyboard('[ArrowDown]'); - } while (!nodeContains(this.rowGroups[1], document.activeElement)); + } while (!this.rowGroups[1].contains(document.activeElement)); } // Move focus onto the row itself - if (nodeContains(this.rowGroups[1], document.activeElement) && document.activeElement!.getAttribute('role') !== 'row') { + if (this.rowGroups[1].contains(document.activeElement) && document.activeElement!.getAttribute('role') !== 'row') { do { await this.user.keyboard('[ArrowLeft]'); } while (document.activeElement!.getAttribute('role') !== 'row'); @@ -223,7 +222,7 @@ export class TableTester { } await waitFor(() => { - if (nodeContains(document, menu)) { + if (document.contains(menu)) { throw new Error('Expected table column menu listbox to not be in the document after selecting an option'); } else { return true; @@ -309,7 +308,7 @@ export class TableTester { await pressElement(this.user, within(menu).getAllByRole('menuitem')[action], interactionType); await waitFor(() => { - if (nodeContains(document, menu)) { + if (document.contains(menu)) { throw new Error('Expected table column menu listbox to not be in the document after selecting an option'); } else { return true; diff --git a/packages/@react-aria/test-utils/src/tabs.ts b/packages/@react-aria/test-utils/src/tabs.ts index f87a2d9afd2..c26da3e7656 100644 --- a/packages/@react-aria/test-utils/src/tabs.ts +++ b/packages/@react-aria/test-utils/src/tabs.ts @@ -12,7 +12,6 @@ import {act, within} from '@testing-library/react'; import {Direction, Orientation, TabsTesterOpts, UserOpts} from './types'; -import {nodeContains} from '@react-aria/utils'; import {pressElement} from './events'; interface TriggerTabOptions { @@ -90,7 +89,7 @@ export class TabsTester { throw new Error('Tab provided is not in the tablist'); } - if (!nodeContains(this._tablist, document.activeElement)) { + if (!this._tablist.contains(document.activeElement)) { let selectedTab = this.selectedTab; if (selectedTab != null) { act(() => selectedTab.focus()); @@ -143,7 +142,7 @@ export class TabsTester { } if (interactionType === 'keyboard') { - if (document.activeElement !== this._tablist && !nodeContains(this._tablist, document.activeElement)) { + if (document.activeElement !== this._tablist && !this._tablist.contains(document.activeElement)) { act(() => this._tablist.focus()); } diff --git a/packages/@react-aria/test-utils/src/tree.ts b/packages/@react-aria/test-utils/src/tree.ts index 28a566d59ec..cadcf52b72a 100644 --- a/packages/@react-aria/test-utils/src/tree.ts +++ b/packages/@react-aria/test-utils/src/tree.ts @@ -13,7 +13,6 @@ import {act, within} from '@testing-library/react'; import {BaseGridRowInteractionOpts, GridRowActionOpts, ToggleGridRowOpts, TreeTesterOpts, UserOpts} from './types'; import {getAltKey, getMetaKey, pressElement, triggerLongPress} from './events'; -import {nodeContains} from '@react-aria/utils'; interface TreeToggleExpansionOpts extends BaseGridRowInteractionOpts {} interface TreeToggleRowOpts extends ToggleGridRowOpts {} @@ -74,13 +73,13 @@ export class TreeTester { throw new Error('Option provided is not in the tree'); } - if (document.activeElement !== this._tree && !nodeContains(this._tree, document.activeElement)) { + if (document.activeElement !== this._tree && !this._tree.contains(document.activeElement)) { act(() => this._tree.focus()); } if (document.activeElement === this.tree) { await this.user.keyboard(`${selectionOnNav === 'none' ? `[${altKey}>]` : ''}[ArrowDown]${selectionOnNav === 'none' ? `[/${altKey}]` : ''}`); - } else if (nodeContains(this._tree, document.activeElement) && document.activeElement!.getAttribute('role') !== 'row') { + } else if (this._tree.contains(document.activeElement) && document.activeElement!.getAttribute('role') !== 'row') { do { await this.user.keyboard('[ArrowLeft]'); } while (document.activeElement!.getAttribute('role') !== 'row'); @@ -179,7 +178,7 @@ export class TreeTester { row, interactionType = this._interactionType } = opts; - if (!nodeContains(this.tree, document.activeElement)) { + if (!this.tree.contains(document.activeElement)) { await act(async () => { this.tree.focus(); }); diff --git a/yarn.lock b/yarn.lock index 82f4b7eb377..d716c3117ce 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6179,7 +6179,6 @@ __metadata: version: 0.0.0-use.local resolution: "@react-aria/test-utils@workspace:packages/@react-aria/test-utils" dependencies: - "@react-aria/utils": "npm:^3.32.0" "@swc/helpers": "npm:^0.5.0" peerDependencies: "@testing-library/react": ^16.0.0