Skip to content

feat: Test utils API audit, additional feature coverage (RTL, grid nav, etc) in prep for RC/1.0#9998

Merged
LFDanLu merged 38 commits into
mainfrom
test-utils-1.0
May 18, 2026
Merged

feat: Test utils API audit, additional feature coverage (RTL, grid nav, etc) in prep for RC/1.0#9998
LFDanLu merged 38 commits into
mainfrom
test-utils-1.0

Conversation

@LFDanLu
Copy link
Copy Markdown
Member

@LFDanLu LFDanLu commented Apr 29, 2026

See commits for what changed

Some additional pattern support to be opened in a different PR maybe, to discuss if we think they are worth it or not.

✅ Pull Request Checklist:

  • Included link to corresponding React Spectrum GitHub Issue.
  • Added/updated unit tests and storybook for this change (for new code or code which already has tests).
  • Filled out test instructions.
  • Updated documentation (if it already exists for this component).
  • Looked at the Accessibility Practices for this feature - Aria Practices

📝 Test Instructions:

🧢 Your Project:

RSP

@rspbot
Copy link
Copy Markdown

rspbot commented Apr 30, 2026

@rspbot
Copy link
Copy Markdown

rspbot commented Apr 30, 2026

@LFDanLu LFDanLu marked this pull request as ready for review April 30, 2026 22:47
Comment thread packages/@react-aria/test-utils/src/table.ts Outdated
Comment thread packages/@react-aria/test-utils/src/table.ts Outdated
@rspbot
Copy link
Copy Markdown

rspbot commented May 9, 2026

* -------------------
* | 1,3 | 3,2 | 3,3 |
* -------------------
* ## | 1,1 | 2,1 | 3,1 |
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

huh... these would be titles now?

@rspbot
Copy link
Copy Markdown

rspbot commented May 12, 2026

Comment thread packages/dev/s2-docs/pages/s2/testing.mdx
Comment thread packages/@react-aria/test-utils/src/select.ts
Comment thread packages/@react-aria/test-utils/src/gridlist.ts
Comment thread packages/dev/s2-docs/pages/s2/TreeView/testing.mdx Outdated
Comment thread packages/dev/s2-docs/pages/react-aria/Tree/testing.mdx Outdated
Comment thread packages/@react-aria/test-utils/src/menu.ts
@rspbot
Copy link
Copy Markdown

rspbot commented May 15, 2026

@rspbot
Copy link
Copy Markdown

rspbot commented May 15, 2026

@rspbot
Copy link
Copy Markdown

rspbot commented May 15, 2026

## API Changes

@react-aria/test-utils

/@react-aria/test-utils:CheckboxGroupTester

 CheckboxGroupTester {
-  checkboxes: Array<HTMLElement>
-  checkboxgroup: HTMLElement
   constructor: (CheckboxGroupTesterOpts) => void
   findCheckbox: ({
-    checkboxIndexOrText: number | string
+    indexOrText: number | string
 }) => HTMLElement
-  selectedCheckboxes: Array<HTMLElement>
+  getCheckboxGroup: () => HTMLElement
+  getCheckboxes: () => Array<HTMLElement>
+  getSelectedCheckboxes: () => Array<HTMLElement>
   setInteractionType: (UserOpts['interactionType']) => void
   toggleCheckbox: (TriggerCheckboxOptions) => Promise<void>
 }

/@react-aria/test-utils:ComboBoxTester

 ComboBoxTester {
   close: () => Promise<void>
-  combobox: HTMLElement
   constructor: (ComboBoxTesterOpts) => void
   findOption: ({
-    optionIndexOrText: number | string
+    indexOrText: number | string
 }) => HTMLElement
-  focusedOption: HTMLElement | null
-  listbox: HTMLElement | null
-  open: (ComboBoxOpenOpts) => Promise<void>
-  options: ({
+  getCombobox: () => HTMLElement
+  getFocusedOption: () => HTMLElement | null
+  getListbox: () => HTMLElement | null
+  getOptions: ({
     element?: HTMLElement
 }) => Array<HTMLElement>
-  sections: Array<HTMLElement>
-  selectOption: (ComboBoxSelectOpts) => Promise<void>
+  getSections: () => Array<HTMLElement>
+  getTrigger: () => HTMLElement
+  open: (ComboBoxOpenOpts) => Promise<void>
   setInteractionType: (UserOpts['interactionType']) => void
-  trigger: HTMLElement
+  toggleOptionSelection: (ComboBoxSelectOpts) => Promise<void>
 }

/@react-aria/test-utils:DialogTester

 DialogTester {
   close: () => Promise<void>
   constructor: (DialogTesterOpts) => void
-  dialog: HTMLElement | null
+  getDialog: () => HTMLElement | null
+  getTrigger: () => HTMLElement
   open: (DialogOpenOpts) => Promise<void>
   setInteractionType: (UserOpts['interactionType']) => void
-  trigger: HTMLElement
 }

/@react-aria/test-utils:GridListTester

 GridListTester {
-  cells: ({
-    element?: HTMLElement
-}) => Array<HTMLElement>
   constructor: (GridListTesterOpts) => void
   findRow: ({
-    rowIndexOrText: number | string
+    indexOrText: number | string
 }) => HTMLElement
-  gridlist: HTMLElement
-  rows: Array<HTMLElement>
-  selectedRows: Array<HTMLElement>
+  getCells: ({
+    element?: HTMLElement
+}) => Array<HTMLElement>
+  getGridlist: () => HTMLElement
+  getRows: () => Array<HTMLElement>
+  getSelectedRows: () => Array<HTMLElement>
   setInteractionType: (UserOpts['interactionType']) => void
   toggleRowSelection: (GridListToggleRowOpts) => Promise<void>
   triggerRowAction: (GridListRowActionOpts) => Promise<void>
 }

/@react-aria/test-utils:ListBoxTester

 ListBoxTester {
   constructor: (ListBoxTesterOpts) => void
   findOption: ({
-    optionIndexOrText: number | string
+    indexOrText: number | string
 }) => HTMLElement
-  listbox: HTMLElement
-  options: ({
+  getListbox: () => HTMLElement
+  getOptions: ({
     element?: HTMLElement
 }) => Array<HTMLElement>
-  sections: Array<HTMLElement>
-  selectedOptions: Array<HTMLElement>
+  getSections: () => Array<HTMLElement>
+  getSelectedOptions: () => Array<HTMLElement>
   setInteractionType: (UserOpts['interactionType']) => void
   toggleOptionSelection: (ListBoxToggleOptionOpts) => Promise<void>
   triggerOptionAction: (ListBoxOptionActionOpts) => Promise<void>
 }

/@react-aria/test-utils:MenuTester

 MenuTester {
   close: () => Promise<void>
   constructor: (MenuTesterOpts) => void
   findOption: ({
-    optionIndexOrText: number | string
+    indexOrText: number | string
 }) => HTMLElement
-  menu: HTMLElement | null
-  open: (MenuOpenOpts) => Promise<void>
-  openSubmenu: (MenuOpenSubmenuOpts) => Promise<MenuTester | null>
-  options: ({
+  getMenu: () => HTMLElement | null
+  getOptions: ({
     element?: HTMLElement
 }) => Array<HTMLElement>
-  sections: Array<HTMLElement>
-  selectOption: (MenuSelectOpts) => Promise<void>
+  getSections: () => Array<HTMLElement>
+  getSubmenuTriggers: () => Array<HTMLElement>
+  getTrigger: () => HTMLElement
+  open: (MenuOpenOpts) => Promise<void>
+  openSubmenu: (MenuOpenSubmenuOpts) => Promise<MenuTester>
   setInteractionType: (UserOpts['interactionType']) => void
-  submenuTriggers: Array<HTMLElement>
-  trigger: HTMLElement
+  toggleOptionSelection: (MenuSelectOpts) => Promise<void>
 }

/@react-aria/test-utils:RadioGroupTester

 RadioGroupTester {
   constructor: (RadioGroupTesterOpts) => void
   findRadio: ({
-    radioIndexOrText: number | string
+    indexOrText: number | string
 }) => HTMLElement
-  radiogroup: HTMLElement
-  radios: Array<HTMLElement>
-  selectedRadio: HTMLElement | null
+  getRadioGroup: () => HTMLElement
+  getRadios: () => Array<HTMLElement>
+  getSelectedRadio: () => HTMLElement | null
   setInteractionType: (UserOpts['interactionType']) => void
   triggerRadio: (TriggerRadioOptions) => Promise<void>
 }

/@react-aria/test-utils:SelectTester

 SelectTester {
   close: () => Promise<void>
   constructor: (SelectTesterOpts) => void
   findOption: ({
-    optionIndexOrText: number | string
+    indexOrText: number | string
 }) => HTMLElement
-  listbox: HTMLElement | null
-  open: (SelectOpenOpts) => Promise<void>
-  options: ({
+  getListbox: () => HTMLElement | null
+  getOptions: ({
     element?: HTMLElement
 }) => Array<HTMLElement>
-  sections: Array<HTMLElement>
-  selectOption: (SelectTriggerOptionOpts) => Promise<void>
+  getSections: () => Array<HTMLElement>
+  getTrigger: () => HTMLElement
+  open: (SelectOpenOpts) => Promise<void>
   setInteractionType: (UserOpts['interactionType']) => void
-  trigger: HTMLElement
+  toggleOptionSelection: (SelectTriggerOptionOpts) => Promise<void>
 }

/@react-aria/test-utils:TableTester

 TableTester {
-  cells: ({
-    element?: HTMLElement
-}) => Array<HTMLElement>
-  columns: Array<HTMLElement>
   constructor: (TableTesterOpts) => void
   findCell: ({
     text: string
 }) => HTMLElement
   findRow: ({
-    rowIndexOrText: number | string
+    indexOrText: number | string
 }) => HTMLElement
-  rowGroups: Array<HTMLElement>
-  rowHeaders: Array<HTMLElement>
-  rows: Array<HTMLElement>
-  selectedRows: Array<HTMLElement>
+  getCells: ({
+    element?: HTMLElement
+}) => Array<HTMLElement>
+  getColumns: () => Array<HTMLElement>
+  getFooterRows: () => Array<HTMLElement>
+  getRowGroups: () => Array<HTMLElement>
+  getRowHeaders: () => Array<HTMLElement>
+  getRows: ({
+    element?: HTMLElement
+}) => Array<HTMLElement>
+  getSelectedRows: () => Array<HTMLElement>
+  getTable: () => HTMLElement
   setInteractionType: (UserOpts['interactionType']) => void
-  table: HTMLElement
   toggleRowExpansion: (TableToggleExpansionOpts) => Promise<void>
   toggleRowSelection: (TableToggleRowOpts) => Promise<void>
   toggleSelectAll: ({
     interactionType?: UserOpts['interactionType']
   toggleSort: (TableToggleSortOpts) => Promise<void>
   triggerColumnHeaderAction: (TableColumnHeaderActionOpts) => Promise<void>
   triggerRowAction: (TableRowActionOpts) => Promise<void>
 }

/@react-aria/test-utils:TabsTester

 TabsTester {
-  activeTabpanel: HTMLElement | null
   constructor: (TabsTesterOpts) => void
   findTab: ({
-    tabIndexOrText: number | string
+    indexOrText: number | string
 }) => HTMLElement
-  selectedTab: HTMLElement | null
+  getActiveTabpanel: () => HTMLElement | null
+  getSelectedTab: () => HTMLElement | null
+  getTablist: () => HTMLElement
+  getTabpanels: () => Array<HTMLElement>
+  getTabs: () => Array<HTMLElement>
   setInteractionType: (UserOpts['interactionType']) => void
-  tablist: HTMLElement
-  tabpanels: Array<HTMLElement>
-  tabs: Array<HTMLElement>
   triggerTab: (TriggerTabOptions) => Promise<void>
 }

/@react-aria/test-utils:TreeTester

 TreeTester {
-  cells: ({
-    element?: HTMLElement
-}) => Array<HTMLElement>
   constructor: (TreeTesterOpts) => void
   findRow: ({
-    rowIndexOrText: number | string
+    indexOrText: number | string
 }) => HTMLElement
-  rows: Array<HTMLElement>
-  selectedRows: Array<HTMLElement>
+  getCells: ({
+    element?: HTMLElement
+}) => Array<HTMLElement>
+  getRows: () => Array<HTMLElement>
+  getSelectedRows: () => Array<HTMLElement>
+  getTree: () => HTMLElement
   setInteractionType: (UserOpts['interactionType']) => void
   toggleRowExpansion: (TreeToggleExpansionOpts) => Promise<void>
   toggleRowSelection: (TreeToggleRowOpts) => Promise<void>
-  tree: HTMLElement
   triggerRowAction: (TreeRowActionOpts) => Promise<void>
 }

@react-spectrum/test-utils

/@react-spectrum/test-utils:CheckboxGroupTester

 CheckboxGroupTester {
-  checkboxes: Array<HTMLElement>
-  checkboxgroup: HTMLElement
   constructor: (CheckboxGroupTesterOpts) => void
   findCheckbox: ({
-    checkboxIndexOrText: number | string
+    indexOrText: number | string
 }) => HTMLElement
-  selectedCheckboxes: Array<HTMLElement>
+  getCheckboxGroup: () => HTMLElement
+  getCheckboxes: () => Array<HTMLElement>
+  getSelectedCheckboxes: () => Array<HTMLElement>
   setInteractionType: (UserOpts['interactionType']) => void
   toggleCheckbox: (TriggerCheckboxOptions) => Promise<void>
 }

/@react-spectrum/test-utils:ComboBoxTester

 ComboBoxTester {
   close: () => Promise<void>
-  combobox: HTMLElement
   constructor: (ComboBoxTesterOpts) => void
   findOption: ({
-    optionIndexOrText: number | string
+    indexOrText: number | string
 }) => HTMLElement
-  focusedOption: HTMLElement | null
-  listbox: HTMLElement | null
-  open: (ComboBoxOpenOpts) => Promise<void>
-  options: ({
+  getCombobox: () => HTMLElement
+  getFocusedOption: () => HTMLElement | null
+  getListbox: () => HTMLElement | null
+  getOptions: ({
     element?: HTMLElement
 }) => Array<HTMLElement>
-  sections: Array<HTMLElement>
-  selectOption: (ComboBoxSelectOpts) => Promise<void>
+  getSections: () => Array<HTMLElement>
+  getTrigger: () => HTMLElement
+  open: (ComboBoxOpenOpts) => Promise<void>
   setInteractionType: (UserOpts['interactionType']) => void
-  trigger: HTMLElement
+  toggleOptionSelection: (ComboBoxSelectOpts) => Promise<void>
 }

/@react-spectrum/test-utils:DialogTester

 DialogTester {
   close: () => Promise<void>
   constructor: (DialogTesterOpts) => void
-  dialog: HTMLElement | null
+  getDialog: () => HTMLElement | null
+  getTrigger: () => HTMLElement
   open: (DialogOpenOpts) => Promise<void>
   setInteractionType: (UserOpts['interactionType']) => void
-  trigger: HTMLElement
 }

/@react-spectrum/test-utils:GridListTester

 GridListTester {
-  cells: ({
-    element?: HTMLElement
-}) => Array<HTMLElement>
   constructor: (GridListTesterOpts) => void
   findRow: ({
-    rowIndexOrText: number | string
+    indexOrText: number | string
 }) => HTMLElement
-  gridlist: HTMLElement
-  rows: Array<HTMLElement>
-  selectedRows: Array<HTMLElement>
+  getCells: ({
+    element?: HTMLElement
+}) => Array<HTMLElement>
+  getGridlist: () => HTMLElement
+  getRows: () => Array<HTMLElement>
+  getSelectedRows: () => Array<HTMLElement>
   setInteractionType: (UserOpts['interactionType']) => void
   toggleRowSelection: (GridListToggleRowOpts) => Promise<void>
   triggerRowAction: (GridListRowActionOpts) => Promise<void>
 }

/@react-spectrum/test-utils:ListBoxTester

 ListBoxTester {
   constructor: (ListBoxTesterOpts) => void
   findOption: ({
-    optionIndexOrText: number | string
+    indexOrText: number | string
 }) => HTMLElement
-  listbox: HTMLElement
-  options: ({
+  getListbox: () => HTMLElement
+  getOptions: ({
     element?: HTMLElement
 }) => Array<HTMLElement>
-  sections: Array<HTMLElement>
-  selectedOptions: Array<HTMLElement>
+  getSections: () => Array<HTMLElement>
+  getSelectedOptions: () => Array<HTMLElement>
   setInteractionType: (UserOpts['interactionType']) => void
   toggleOptionSelection: (ListBoxToggleOptionOpts) => Promise<void>
   triggerOptionAction: (ListBoxOptionActionOpts) => Promise<void>
 }

/@react-spectrum/test-utils:MenuTester

 MenuTester {
   close: () => Promise<void>
   constructor: (MenuTesterOpts) => void
   findOption: ({
-    optionIndexOrText: number | string
+    indexOrText: number | string
 }) => HTMLElement
-  menu: HTMLElement | null
-  open: (MenuOpenOpts) => Promise<void>
-  openSubmenu: (MenuOpenSubmenuOpts) => Promise<MenuTester | null>
-  options: ({
+  getMenu: () => HTMLElement | null
+  getOptions: ({
     element?: HTMLElement
 }) => Array<HTMLElement>
-  sections: Array<HTMLElement>
-  selectOption: (MenuSelectOpts) => Promise<void>
+  getSections: () => Array<HTMLElement>
+  getSubmenuTriggers: () => Array<HTMLElement>
+  getTrigger: () => HTMLElement
+  open: (MenuOpenOpts) => Promise<void>
+  openSubmenu: (MenuOpenSubmenuOpts) => Promise<MenuTester>
   setInteractionType: (UserOpts['interactionType']) => void
-  submenuTriggers: Array<HTMLElement>
-  trigger: HTMLElement
+  toggleOptionSelection: (MenuSelectOpts) => Promise<void>
 }

/@react-spectrum/test-utils:RadioGroupTester

 RadioGroupTester {
   constructor: (RadioGroupTesterOpts) => void
   findRadio: ({
-    radioIndexOrText: number | string
+    indexOrText: number | string
 }) => HTMLElement
-  radiogroup: HTMLElement
-  radios: Array<HTMLElement>
-  selectedRadio: HTMLElement | null
+  getRadioGroup: () => HTMLElement
+  getRadios: () => Array<HTMLElement>
+  getSelectedRadio: () => HTMLElement | null
   setInteractionType: (UserOpts['interactionType']) => void
   triggerRadio: (TriggerRadioOptions) => Promise<void>
 }

/@react-spectrum/test-utils:SelectTester

 SelectTester {
   close: () => Promise<void>
   constructor: (SelectTesterOpts) => void
   findOption: ({
-    optionIndexOrText: number | string
+    indexOrText: number | string
 }) => HTMLElement
-  listbox: HTMLElement | null
-  open: (SelectOpenOpts) => Promise<void>
-  options: ({
+  getListbox: () => HTMLElement | null
+  getOptions: ({
     element?: HTMLElement
 }) => Array<HTMLElement>
-  sections: Array<HTMLElement>
-  selectOption: (SelectTriggerOptionOpts) => Promise<void>
+  getSections: () => Array<HTMLElement>
+  getTrigger: () => HTMLElement
+  open: (SelectOpenOpts) => Promise<void>
   setInteractionType: (UserOpts['interactionType']) => void
-  trigger: HTMLElement
+  toggleOptionSelection: (SelectTriggerOptionOpts) => Promise<void>
 }

/@react-spectrum/test-utils:TableTester

 TableTester {
-  cells: ({
-    element?: HTMLElement
-}) => Array<HTMLElement>
-  columns: Array<HTMLElement>
   constructor: (TableTesterOpts) => void
   findCell: ({
     text: string
 }) => HTMLElement
   findRow: ({
-    rowIndexOrText: number | string
+    indexOrText: number | string
 }) => HTMLElement
-  rowGroups: Array<HTMLElement>
-  rowHeaders: Array<HTMLElement>
-  rows: Array<HTMLElement>
-  selectedRows: Array<HTMLElement>
+  getCells: ({
+    element?: HTMLElement
+}) => Array<HTMLElement>
+  getColumns: () => Array<HTMLElement>
+  getFooterRows: () => Array<HTMLElement>
+  getRowGroups: () => Array<HTMLElement>
+  getRowHeaders: () => Array<HTMLElement>
+  getRows: ({
+    element?: HTMLElement
+}) => Array<HTMLElement>
+  getSelectedRows: () => Array<HTMLElement>
+  getTable: () => HTMLElement
   setInteractionType: (UserOpts['interactionType']) => void
-  table: HTMLElement
   toggleRowExpansion: (TableToggleExpansionOpts) => Promise<void>
   toggleRowSelection: (TableToggleRowOpts) => Promise<void>
   toggleSelectAll: ({
     interactionType?: UserOpts['interactionType']
   toggleSort: (TableToggleSortOpts) => Promise<void>
   triggerColumnHeaderAction: (TableColumnHeaderActionOpts) => Promise<void>
   triggerRowAction: (TableRowActionOpts) => Promise<void>
 }

/@react-spectrum/test-utils:TabsTester

 TabsTester {
-  activeTabpanel: HTMLElement | null
   constructor: (TabsTesterOpts) => void
   findTab: ({
-    tabIndexOrText: number | string
+    indexOrText: number | string
 }) => HTMLElement
-  selectedTab: HTMLElement | null
+  getActiveTabpanel: () => HTMLElement | null
+  getSelectedTab: () => HTMLElement | null
+  getTablist: () => HTMLElement
+  getTabpanels: () => Array<HTMLElement>
+  getTabs: () => Array<HTMLElement>
   setInteractionType: (UserOpts['interactionType']) => void
-  tablist: HTMLElement
-  tabpanels: Array<HTMLElement>
-  tabs: Array<HTMLElement>
   triggerTab: (TriggerTabOptions) => Promise<void>
 }

/@react-spectrum/test-utils:TreeTester

 TreeTester {
-  cells: ({
-    element?: HTMLElement
-}) => Array<HTMLElement>
   constructor: (TreeTesterOpts) => void
   findRow: ({
-    rowIndexOrText: number | string
+    indexOrText: number | string
 }) => HTMLElement
-  rows: Array<HTMLElement>
-  selectedRows: Array<HTMLElement>
+  getCells: ({
+    element?: HTMLElement
+}) => Array<HTMLElement>
+  getRows: () => Array<HTMLElement>
+  getSelectedRows: () => Array<HTMLElement>
+  getTree: () => HTMLElement
   setInteractionType: (UserOpts['interactionType']) => void
   toggleRowExpansion: (TreeToggleExpansionOpts) => Promise<void>
   toggleRowSelection: (TreeToggleRowOpts) => Promise<void>
-  tree: HTMLElement
   triggerRowAction: (TreeRowActionOpts) => Promise<void>
 }

@LFDanLu
Copy link
Copy Markdown
Member Author

LFDanLu commented May 18, 2026

Merging, will add some follow ups for node version requirement and a global config for setting fireEvent in a followup

@LFDanLu LFDanLu added this pull request to the merge queue May 18, 2026
Merged via the queue into main with commit 9508b15 May 18, 2026
29 checks passed
@LFDanLu LFDanLu deleted the test-utils-1.0 branch May 18, 2026 22:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no testing Does not require manual testing during testing session RAC ready for review release S2

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants