Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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/**"],

Expand Down
1 change: 0 additions & 1 deletion packages/@react-aria/test-utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
"url": "https://github.com/adobe/react-spectrum"
},
"dependencies": {
"@react-aria/utils": "^3.32.0",
"@swc/helpers": "^0.5.0"
},
"peerDependencies": {
Expand Down
3 changes: 1 addition & 2 deletions packages/@react-aria/test-utils/src/checkboxgroup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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());
}

Expand Down
5 changes: 2 additions & 3 deletions packages/@react-aria/test-utils/src/combobox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
/**
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down
7 changes: 3 additions & 4 deletions packages/@react-aria/test-utils/src/dialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
/**
Expand Down Expand Up @@ -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');
Expand All @@ -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;
Expand All @@ -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;
}
}
5 changes: 2 additions & 3 deletions packages/@react-aria/test-utils/src/gridlist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}
Expand Down Expand Up @@ -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');
Expand Down
3 changes: 1 addition & 2 deletions packages/@react-aria/test-utils/src/listbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
/**
Expand Down Expand Up @@ -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}]` : ''}`);
}
Expand Down
9 changes: 4 additions & 5 deletions packages/@react-aria/test-utils/src/menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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());
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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');
Expand Down Expand Up @@ -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.');
}
}
Expand Down
3 changes: 1 addition & 2 deletions packages/@react-aria/test-utils/src/radiogroup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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());
Expand Down
7 changes: 3 additions & 4 deletions packages/@react-aria/test-utils/src/select.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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.');
}
}
Expand Down Expand Up @@ -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});
Expand All @@ -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');
}
}
Expand Down
13 changes: 6 additions & 7 deletions packages/@react-aria/test-utils/src/table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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());
}

Expand All @@ -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');
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
5 changes: 2 additions & 3 deletions packages/@react-aria/test-utils/src/tabs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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());
}

Expand Down
7 changes: 3 additions & 4 deletions packages/@react-aria/test-utils/src/tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}
Expand Down Expand Up @@ -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');
Expand Down Expand Up @@ -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();
});
Expand Down
2 changes: 1 addition & 1 deletion packages/@react-aria/utils/src/useResizeObserver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export function useResizeObserver<T extends Element>(options: useResizeObserverO
return;
}

requestAnimationFrame(() => onResizeEvent());
onResizeEvent();
});
resizeObserverInstance.observe(element, {box});

Expand Down
6 changes: 4 additions & 2 deletions packages/@react-spectrum/s2/src/ComboBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export interface ComboboxStyleProps {
size?: 'S' | 'M' | 'L' | 'XL'
}
export interface ComboBoxProps<T extends object> extends
Omit<AriaComboBoxProps<T>, 'children' | 'style' | 'className' | 'render' | 'defaultFilter' | 'allowsEmptyCollection' | 'isTriggerUpWhenOpen' | keyof GlobalDOMAttributes>,
Omit<AriaComboBoxProps<T>, 'children' | 'style' | 'className' | 'render' | 'defaultFilter' | 'allowsEmptyCollection' | keyof GlobalDOMAttributes>,
ComboboxStyleProps,
StyleProps,
SpectrumLabelableProps,
Expand Down Expand Up @@ -354,7 +354,6 @@ export const ComboBox = /*#__PURE__*/ (forwardRef as forwardRefType)(function Co
return (
<AriaComboBox
{...comboBoxProps}
isTriggerUpWhenOpen
allowsEmptyCollection
style={UNSAFE_style}
className={UNSAFE_className + style(field(), getAllowedOverrides())({
Expand Down Expand Up @@ -644,6 +643,9 @@ const ComboboxInner = forwardRef(function ComboboxInner(props: ComboBoxProps<any
)}
<Button
ref={buttonRef}
// Prevent press scale from sticking while ComboBox is open.
// @ts-ignore
isPressed={false}
style={renderProps => pressScale(buttonRef)(renderProps)}
className={renderProps => inputButton({
...renderProps,
Expand Down
Loading
Loading