@react-aria/test-utils 1.0.0-alpha.5 → 1.0.0-alpha.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/combobox.main.js.map +1 -1
- package/dist/combobox.module.js.map +1 -1
- package/dist/events.main.js.map +1 -1
- package/dist/events.module.js.map +1 -1
- package/dist/gridlist.main.js +1 -1
- package/dist/gridlist.main.js.map +1 -1
- package/dist/gridlist.mjs +1 -1
- package/dist/gridlist.module.js +1 -1
- package/dist/gridlist.module.js.map +1 -1
- package/dist/listbox.main.js +2 -3
- package/dist/listbox.main.js.map +1 -1
- package/dist/listbox.mjs +2 -3
- package/dist/listbox.module.js +2 -3
- package/dist/listbox.module.js.map +1 -1
- package/dist/menu.main.js +39 -19
- package/dist/menu.main.js.map +1 -1
- package/dist/menu.mjs +39 -19
- package/dist/menu.module.js +39 -19
- package/dist/menu.module.js.map +1 -1
- package/dist/select.main.js.map +1 -1
- package/dist/select.module.js.map +1 -1
- package/dist/table.main.js +48 -0
- package/dist/table.main.js.map +1 -1
- package/dist/table.mjs +48 -0
- package/dist/table.module.js +48 -0
- package/dist/table.module.js.map +1 -1
- package/dist/tabs.main.js.map +1 -1
- package/dist/tabs.module.js.map +1 -1
- package/dist/testSetup.main.js.map +1 -1
- package/dist/testSetup.module.js.map +1 -1
- package/dist/tree.main.js +1 -1
- package/dist/tree.main.js.map +1 -1
- package/dist/tree.mjs +1 -1
- package/dist/tree.module.js +1 -1
- package/dist/tree.module.js.map +1 -1
- package/dist/types.d.ts +16 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/user.main.js +1 -1
- package/dist/user.main.js.map +1 -1
- package/dist/user.mjs +1 -1
- package/dist/user.module.js +1 -1
- package/dist/user.module.js.map +1 -1
- package/package.json +5 -4
- package/src/combobox.ts +4 -4
- package/src/events.ts +3 -3
- package/src/gridlist.ts +8 -7
- package/src/listbox.ts +7 -13
- package/src/menu.ts +64 -14
- package/src/select.ts +4 -4
- package/src/table.ts +98 -6
- package/src/tabs.ts +2 -2
- package/src/testSetup.ts +2 -2
- package/src/tree.ts +9 -8
- package/src/types.ts +8 -4
- package/src/user.ts +1 -1
package/src/menu.ts
CHANGED
|
@@ -64,9 +64,10 @@ export class MenuTester {
|
|
|
64
64
|
private _advanceTimer: UserOpts['advanceTimer'];
|
|
65
65
|
private _trigger: HTMLElement | undefined;
|
|
66
66
|
private _isSubmenu: boolean = false;
|
|
67
|
+
private _rootMenu: HTMLElement | undefined;
|
|
67
68
|
|
|
68
69
|
constructor(opts: MenuTesterOpts) {
|
|
69
|
-
let {root, user, interactionType, advanceTimer, isSubmenu} = opts;
|
|
70
|
+
let {root, user, interactionType, advanceTimer, isSubmenu, rootMenu} = opts;
|
|
70
71
|
this.user = user;
|
|
71
72
|
this._interactionType = interactionType || 'mouse';
|
|
72
73
|
this._advanceTimer = advanceTimer;
|
|
@@ -85,12 +86,13 @@ export class MenuTester {
|
|
|
85
86
|
}
|
|
86
87
|
|
|
87
88
|
this._isSubmenu = isSubmenu || false;
|
|
89
|
+
this._rootMenu = rootMenu;
|
|
88
90
|
}
|
|
89
91
|
|
|
90
92
|
/**
|
|
91
93
|
* Set the interaction type used by the menu tester.
|
|
92
94
|
*/
|
|
93
|
-
setInteractionType(type: UserOpts['interactionType']) {
|
|
95
|
+
setInteractionType(type: UserOpts['interactionType']): void {
|
|
94
96
|
this._interactionType = type;
|
|
95
97
|
}
|
|
96
98
|
|
|
@@ -99,7 +101,7 @@ export class MenuTester {
|
|
|
99
101
|
/**
|
|
100
102
|
* Opens the menu. Defaults to using the interaction type set on the menu tester.
|
|
101
103
|
*/
|
|
102
|
-
async open(opts: MenuOpenOpts = {}) {
|
|
104
|
+
async open(opts: MenuOpenOpts = {}): Promise<void> {
|
|
103
105
|
let {
|
|
104
106
|
needsLongPress,
|
|
105
107
|
interactionType = this._interactionType,
|
|
@@ -178,7 +180,7 @@ export class MenuTester {
|
|
|
178
180
|
* Selects the desired menu option. Defaults to using the interaction type set on the menu tester. If necessary, will open the menu dropdown beforehand.
|
|
179
181
|
* The desired option can be targeted via the option's node, the option's text, or the option's index.
|
|
180
182
|
*/
|
|
181
|
-
async selectOption(opts: MenuSelectOpts) {
|
|
183
|
+
async selectOption(opts: MenuSelectOpts): Promise<void> {
|
|
182
184
|
let {
|
|
183
185
|
menuSelectionMode = 'single',
|
|
184
186
|
needsLongPress,
|
|
@@ -226,20 +228,56 @@ export class MenuTester {
|
|
|
226
228
|
await this.user.pointer({target: option, keys: '[TouchA]'});
|
|
227
229
|
}
|
|
228
230
|
}
|
|
229
|
-
act(() => {jest.runAllTimers();});
|
|
230
231
|
|
|
231
|
-
|
|
232
|
+
// This chain of waitFors is needed in place of running all timers since we don't know how long transitions may take, or what action
|
|
233
|
+
// the menu option select may trigger.
|
|
234
|
+
if (
|
|
235
|
+
!(menuSelectionMode === 'single' && !closesOnSelect) &&
|
|
236
|
+
!(menuSelectionMode === 'multiple' && (keyboardActivation === 'Space' || interactionType === 'mouse'))
|
|
237
|
+
) {
|
|
238
|
+
// For RSP, clicking on a submenu option seems to briefly lose focus to the body before moving to the clicked option in the test so we need to wait
|
|
239
|
+
// for focus to be coerced to somewhere else in place of running all timers.
|
|
240
|
+
if (this._isSubmenu) {
|
|
241
|
+
await waitFor(() => {
|
|
242
|
+
if (document.activeElement === document.body) {
|
|
243
|
+
throw new Error('Expected focus to move to somewhere other than the body after selecting a submenu option.');
|
|
244
|
+
} else {
|
|
245
|
+
return true;
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// If user isn't trying to select multiple menu options or closeOnSelect is true then we can assume that
|
|
251
|
+
// the menu will close or some action is triggered. In cases like that focus should move somewhere after the menu closes
|
|
252
|
+
// but we can't really know where so just make sure it doesn't get lost to the body.
|
|
232
253
|
await waitFor(() => {
|
|
233
|
-
if (document.activeElement
|
|
234
|
-
throw new Error(
|
|
254
|
+
if (document.activeElement === option) {
|
|
255
|
+
throw new Error('Expected focus after selecting an option to move away from the option.');
|
|
235
256
|
} else {
|
|
236
257
|
return true;
|
|
237
258
|
}
|
|
238
259
|
});
|
|
239
260
|
|
|
240
|
-
|
|
241
|
-
|
|
261
|
+
// We'll also want to wait for focus to move away from the original submenu trigger since the entire submenu tree should
|
|
262
|
+
// 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
|
|
263
|
+
if (this._isSubmenu) {
|
|
264
|
+
await waitFor(() => {
|
|
265
|
+
if (document.activeElement === this.trigger || this._rootMenu?.contains(document.activeElement)) {
|
|
266
|
+
throw new Error('Expected focus after selecting an submenu option to move away from the original submenu trigger.');
|
|
267
|
+
} else {
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
});
|
|
242
271
|
}
|
|
272
|
+
|
|
273
|
+
// Finally wait for focus to be coerced somewhere final when the menu tree is removed from the DOM
|
|
274
|
+
await waitFor(() => {
|
|
275
|
+
if (document.activeElement === document.body) {
|
|
276
|
+
throw new Error('Expected focus to move to somewhere other than the body after selecting a menu option.');
|
|
277
|
+
} else {
|
|
278
|
+
return true;
|
|
279
|
+
}
|
|
280
|
+
});
|
|
243
281
|
}
|
|
244
282
|
} else {
|
|
245
283
|
throw new Error("Attempted to select a option in the menu, but menu wasn't found.");
|
|
@@ -269,18 +307,30 @@ export class MenuTester {
|
|
|
269
307
|
submenuTrigger = (within(menu!).getByText(submenuTrigger).closest('[role=menuitem]'))! as HTMLElement;
|
|
270
308
|
}
|
|
271
309
|
|
|
272
|
-
let submenuTriggerTester = new MenuTester({
|
|
310
|
+
let submenuTriggerTester = new MenuTester({
|
|
311
|
+
user: this.user,
|
|
312
|
+
interactionType: this._interactionType,
|
|
313
|
+
root: submenuTrigger,
|
|
314
|
+
isSubmenu: true,
|
|
315
|
+
advanceTimer: this._advanceTimer,
|
|
316
|
+
rootMenu: (this._isSubmenu ? this._rootMenu : this.menu) || undefined
|
|
317
|
+
});
|
|
273
318
|
if (interactionType === 'mouse') {
|
|
274
319
|
await this.user.pointer({target: submenuTrigger});
|
|
275
|
-
act(() => {jest.runAllTimers();});
|
|
276
320
|
} else if (interactionType === 'keyboard') {
|
|
277
321
|
await this.keyboardNavigateToOption({option: submenuTrigger});
|
|
278
322
|
await this.user.keyboard('[ArrowRight]');
|
|
279
|
-
act(() => {jest.runAllTimers();});
|
|
280
323
|
} else {
|
|
281
324
|
await submenuTriggerTester.open();
|
|
282
325
|
}
|
|
283
326
|
|
|
327
|
+
await waitFor(() => {
|
|
328
|
+
if (submenuTriggerTester._trigger?.getAttribute('aria-expanded') !== 'true') {
|
|
329
|
+
throw new Error('aria-expanded for the submenu trigger wasn\'t changed to "true", unable to confirm the existance of the submenu');
|
|
330
|
+
} else {
|
|
331
|
+
return true;
|
|
332
|
+
}
|
|
333
|
+
});
|
|
284
334
|
|
|
285
335
|
return submenuTriggerTester;
|
|
286
336
|
}
|
|
@@ -314,7 +364,7 @@ export class MenuTester {
|
|
|
314
364
|
/**
|
|
315
365
|
* Closes the menu.
|
|
316
366
|
*/
|
|
317
|
-
async close() {
|
|
367
|
+
async close(): Promise<void> {
|
|
318
368
|
let menu = this.menu;
|
|
319
369
|
if (menu) {
|
|
320
370
|
act(() => menu.focus());
|
package/src/select.ts
CHANGED
|
@@ -46,14 +46,14 @@ export class SelectTester {
|
|
|
46
46
|
/**
|
|
47
47
|
* Set the interaction type used by the select tester.
|
|
48
48
|
*/
|
|
49
|
-
setInteractionType(type: UserOpts['interactionType']) {
|
|
49
|
+
setInteractionType(type: UserOpts['interactionType']): void {
|
|
50
50
|
this._interactionType = type;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
/**
|
|
54
54
|
* Opens the select. Defaults to using the interaction type set on the select tester.
|
|
55
55
|
*/
|
|
56
|
-
async open(opts: SelectOpenOpts = {}) {
|
|
56
|
+
async open(opts: SelectOpenOpts = {}): Promise<void> {
|
|
57
57
|
let {
|
|
58
58
|
interactionType = this._interactionType
|
|
59
59
|
} = opts;
|
|
@@ -89,7 +89,7 @@ export class SelectTester {
|
|
|
89
89
|
/**
|
|
90
90
|
* Closes the select.
|
|
91
91
|
*/
|
|
92
|
-
async close() {
|
|
92
|
+
async close(): Promise<void> {
|
|
93
93
|
let listbox = this.listbox;
|
|
94
94
|
if (listbox) {
|
|
95
95
|
act(() => listbox.focus());
|
|
@@ -155,7 +155,7 @@ export class SelectTester {
|
|
|
155
155
|
* Selects the desired select option. Defaults to using the interaction type set on the select tester. If necessary, will open the select dropdown beforehand.
|
|
156
156
|
* The desired option can be targeted via the option's node, the option's text, or the option's index.
|
|
157
157
|
*/
|
|
158
|
-
async selectOption(opts: SelectTriggerOptionOpts) {
|
|
158
|
+
async selectOption(opts: SelectTriggerOptionOpts): Promise<void> {
|
|
159
159
|
let {
|
|
160
160
|
option,
|
|
161
161
|
interactionType = this._interactionType
|
package/src/table.ts
CHANGED
|
@@ -25,6 +25,12 @@ interface TableToggleSortOpts {
|
|
|
25
25
|
*/
|
|
26
26
|
interactionType?: UserOpts['interactionType']
|
|
27
27
|
}
|
|
28
|
+
interface TableColumnHeaderActionOpts extends TableToggleSortOpts {
|
|
29
|
+
/**
|
|
30
|
+
* The index of the column header action to trigger.
|
|
31
|
+
*/
|
|
32
|
+
action: number
|
|
33
|
+
}
|
|
28
34
|
interface TableRowActionOpts extends GridRowActionOpts {}
|
|
29
35
|
|
|
30
36
|
export class TableTester {
|
|
@@ -44,14 +50,14 @@ export class TableTester {
|
|
|
44
50
|
/**
|
|
45
51
|
* Set the interaction type used by the table tester.
|
|
46
52
|
*/
|
|
47
|
-
setInteractionType(type: UserOpts['interactionType']) {
|
|
53
|
+
setInteractionType(type: UserOpts['interactionType']): void {
|
|
48
54
|
this._interactionType = type;
|
|
49
55
|
}
|
|
50
56
|
|
|
51
57
|
/**
|
|
52
58
|
* Toggles the selection for the specified table row. Defaults to using the interaction type set on the table tester.
|
|
53
59
|
*/
|
|
54
|
-
async toggleRowSelection(opts: TableToggleRowOpts) {
|
|
60
|
+
async toggleRowSelection(opts: TableToggleRowOpts): Promise<void> {
|
|
55
61
|
let {
|
|
56
62
|
row,
|
|
57
63
|
needsLongPress,
|
|
@@ -97,7 +103,7 @@ export class TableTester {
|
|
|
97
103
|
/**
|
|
98
104
|
* Toggles the sort order for the specified table column. Defaults to using the interaction type set on the table tester.
|
|
99
105
|
*/
|
|
100
|
-
async toggleSort(opts: TableToggleSortOpts) {
|
|
106
|
+
async toggleSort(opts: TableToggleSortOpts): Promise<void> {
|
|
101
107
|
let {
|
|
102
108
|
column,
|
|
103
109
|
interactionType = this._interactionType
|
|
@@ -184,10 +190,96 @@ export class TableTester {
|
|
|
184
190
|
}
|
|
185
191
|
}
|
|
186
192
|
|
|
193
|
+
/**
|
|
194
|
+
* Triggers an action for the specified table column menu. Defaults to using the interaction type set on the table tester.
|
|
195
|
+
*/
|
|
196
|
+
async triggerColumnHeaderAction(opts: TableColumnHeaderActionOpts): Promise<void> {
|
|
197
|
+
let {
|
|
198
|
+
column,
|
|
199
|
+
interactionType = this._interactionType,
|
|
200
|
+
action
|
|
201
|
+
} = opts;
|
|
202
|
+
|
|
203
|
+
let columnheader;
|
|
204
|
+
if (typeof column === 'number') {
|
|
205
|
+
columnheader = this.columns[column];
|
|
206
|
+
} else if (typeof column === 'string') {
|
|
207
|
+
columnheader = within(this.rowGroups[0]).getByText(column);
|
|
208
|
+
while (columnheader && !/columnheader/.test(columnheader.getAttribute('role'))) {
|
|
209
|
+
columnheader = columnheader.parentElement;
|
|
210
|
+
}
|
|
211
|
+
} else {
|
|
212
|
+
columnheader = column;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
let menuButton = within(columnheader).queryByRole('button');
|
|
216
|
+
if (menuButton) {
|
|
217
|
+
// TODO: Focus management is all kinda of messed up if I just use .focus and Space to open the sort menu. Seems like
|
|
218
|
+
// the focused key doesn't get properly set to the desired column header. Have to do this strange flow where I focus the
|
|
219
|
+
// column header except if the active element is already the menu button within the column header
|
|
220
|
+
if (interactionType === 'keyboard' && document.activeElement !== menuButton) {
|
|
221
|
+
await pressElement(this.user, columnheader, interactionType);
|
|
222
|
+
} else {
|
|
223
|
+
await pressElement(this.user, menuButton, interactionType);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
await waitFor(() => {
|
|
227
|
+
if (menuButton.getAttribute('aria-controls') == null) {
|
|
228
|
+
throw new Error('No aria-controls found on table column dropdown menu trigger element.');
|
|
229
|
+
} else {
|
|
230
|
+
return true;
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
let menuId = menuButton.getAttribute('aria-controls');
|
|
235
|
+
await waitFor(() => {
|
|
236
|
+
if (!menuId || document.getElementById(menuId) == null) {
|
|
237
|
+
throw new Error(`Table column header menu with id of ${menuId} not found in document.`);
|
|
238
|
+
} else {
|
|
239
|
+
return true;
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
if (menuId) {
|
|
244
|
+
let menu = document.getElementById(menuId);
|
|
245
|
+
if (menu) {
|
|
246
|
+
await pressElement(this.user, within(menu).getAllByRole('menuitem')[action], interactionType);
|
|
247
|
+
|
|
248
|
+
await waitFor(() => {
|
|
249
|
+
if (document.contains(menu)) {
|
|
250
|
+
throw new Error('Expected table column menu listbox to not be in the document after selecting an option');
|
|
251
|
+
} else {
|
|
252
|
+
return true;
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Handle cases where the table may transition in response to the row selection/deselection
|
|
259
|
+
if (!this._advanceTimer) {
|
|
260
|
+
throw new Error('No advanceTimers provided for table transition.');
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
await act(async () => {
|
|
264
|
+
await this._advanceTimer?.(200);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
await waitFor(() => {
|
|
268
|
+
if (document.activeElement !== menuButton) {
|
|
269
|
+
throw new Error(`Expected the document.activeElement to be the table column menu button but got ${document.activeElement}`);
|
|
270
|
+
} else {
|
|
271
|
+
return true;
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
} else {
|
|
275
|
+
throw new Error('No menu button found on table column header.');
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
187
279
|
/**
|
|
188
280
|
* Triggers the action for the specified table row. Defaults to using the interaction type set on the table tester.
|
|
189
281
|
*/
|
|
190
|
-
async triggerRowAction(opts: TableRowActionOpts) {
|
|
282
|
+
async triggerRowAction(opts: TableRowActionOpts): Promise<void> {
|
|
191
283
|
let {
|
|
192
284
|
row,
|
|
193
285
|
needsDoubleClick,
|
|
@@ -221,7 +313,7 @@ export class TableTester {
|
|
|
221
313
|
/**
|
|
222
314
|
* Toggle selection for all rows in the table. Defaults to using the interaction type set on the table tester.
|
|
223
315
|
*/
|
|
224
|
-
async toggleSelectAll(opts: {interactionType?: UserOpts['interactionType']} = {}) {
|
|
316
|
+
async toggleSelectAll(opts: {interactionType?: UserOpts['interactionType']} = {}): Promise<void> {
|
|
225
317
|
let {
|
|
226
318
|
interactionType = this._interactionType
|
|
227
319
|
} = opts;
|
|
@@ -260,7 +352,7 @@ export class TableTester {
|
|
|
260
352
|
/**
|
|
261
353
|
* Returns a cell matching the specified text content.
|
|
262
354
|
*/
|
|
263
|
-
findCell(opts: {text: string}) {
|
|
355
|
+
findCell(opts: {text: string}): HTMLElement {
|
|
264
356
|
let {
|
|
265
357
|
text
|
|
266
358
|
} = opts;
|
package/src/tabs.ts
CHANGED
|
@@ -51,7 +51,7 @@ export class TabsTester {
|
|
|
51
51
|
/**
|
|
52
52
|
* Set the interaction type used by the tabs tester.
|
|
53
53
|
*/
|
|
54
|
-
setInteractionType(type: UserOpts['interactionType']) {
|
|
54
|
+
setInteractionType(type: UserOpts['interactionType']): void {
|
|
55
55
|
this._interactionType = type;
|
|
56
56
|
}
|
|
57
57
|
|
|
@@ -119,7 +119,7 @@ export class TabsTester {
|
|
|
119
119
|
/**
|
|
120
120
|
* Triggers the specified tab. Defaults to using the interaction type set on the tabs tester.
|
|
121
121
|
*/
|
|
122
|
-
async triggerTab(opts: TriggerTabOptions) {
|
|
122
|
+
async triggerTab(opts: TriggerTabOptions): Promise<void> {
|
|
123
123
|
let {
|
|
124
124
|
tab,
|
|
125
125
|
interactionType = this._interactionType,
|
package/src/testSetup.ts
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
/**
|
|
14
14
|
* Enables reading pageX/pageY from fireEvent.mouse*(..., {pageX: ..., pageY: ...}).
|
|
15
15
|
*/
|
|
16
|
-
export function installMouseEvent() {
|
|
16
|
+
export function installMouseEvent(): void {
|
|
17
17
|
let oldMouseEvent = MouseEvent;
|
|
18
18
|
beforeAll(() => {
|
|
19
19
|
global.MouseEvent = class FakeMouseEvent extends MouseEvent {
|
|
@@ -35,7 +35,7 @@ export function installMouseEvent() {
|
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
export function installPointerEvent() {
|
|
38
|
+
export function installPointerEvent(): void {
|
|
39
39
|
beforeAll(() => {
|
|
40
40
|
// @ts-ignore
|
|
41
41
|
global.PointerEvent = class FakePointerEvent extends MouseEvent {
|
package/src/tree.ts
CHANGED
|
@@ -41,7 +41,7 @@ export class TreeTester {
|
|
|
41
41
|
/**
|
|
42
42
|
* Set the interaction type used by the tree tester.
|
|
43
43
|
*/
|
|
44
|
-
setInteractionType(type: UserOpts['interactionType']) {
|
|
44
|
+
setInteractionType(type: UserOpts['interactionType']): void {
|
|
45
45
|
this._interactionType = type;
|
|
46
46
|
};
|
|
47
47
|
|
|
@@ -71,6 +71,11 @@ export class TreeTester {
|
|
|
71
71
|
if (targetIndex === -1) {
|
|
72
72
|
throw new Error('Option provided is not in the tree');
|
|
73
73
|
}
|
|
74
|
+
|
|
75
|
+
if (document.activeElement !== this._tree || !this._tree.contains(document.activeElement)) {
|
|
76
|
+
act(() => this._tree.focus());
|
|
77
|
+
}
|
|
78
|
+
|
|
74
79
|
if (document.activeElement === this.tree) {
|
|
75
80
|
await this.user.keyboard('[ArrowDown]');
|
|
76
81
|
} else if (this._tree.contains(document.activeElement) && document.activeElement!.getAttribute('role') !== 'row') {
|
|
@@ -92,7 +97,7 @@ export class TreeTester {
|
|
|
92
97
|
/**
|
|
93
98
|
* Toggles the selection for the specified tree row. Defaults to using the interaction type set on the tree tester.
|
|
94
99
|
*/
|
|
95
|
-
async toggleRowSelection(opts: TreeToggleRowOpts) {
|
|
100
|
+
async toggleRowSelection(opts: TreeToggleRowOpts): Promise<void> {
|
|
96
101
|
let {
|
|
97
102
|
row,
|
|
98
103
|
needsLongPress,
|
|
@@ -143,7 +148,7 @@ export class TreeTester {
|
|
|
143
148
|
/**
|
|
144
149
|
* Toggles the expansion for the specified tree row. Defaults to using the interaction type set on the tree tester.
|
|
145
150
|
*/
|
|
146
|
-
async toggleRowExpansion(opts: TreeToggleExpansionOpts) {
|
|
151
|
+
async toggleRowExpansion(opts: TreeToggleExpansionOpts): Promise<void> {
|
|
147
152
|
let {
|
|
148
153
|
row,
|
|
149
154
|
interactionType = this._interactionType
|
|
@@ -184,7 +189,7 @@ export class TreeTester {
|
|
|
184
189
|
/**
|
|
185
190
|
* Triggers the action for the specified tree row. Defaults to using the interaction type set on the tree tester.
|
|
186
191
|
*/
|
|
187
|
-
async triggerRowAction(opts: TreeRowActionOpts) {
|
|
192
|
+
async triggerRowAction(opts: TreeRowActionOpts): Promise<void> {
|
|
188
193
|
let {
|
|
189
194
|
row,
|
|
190
195
|
needsDoubleClick,
|
|
@@ -206,10 +211,6 @@ export class TreeTester {
|
|
|
206
211
|
return;
|
|
207
212
|
}
|
|
208
213
|
|
|
209
|
-
if (document.activeElement !== this._tree || !this._tree.contains(document.activeElement)) {
|
|
210
|
-
act(() => this._tree.focus());
|
|
211
|
-
}
|
|
212
|
-
|
|
213
214
|
await this.keyboardNavigateToRow({row});
|
|
214
215
|
await this.user.keyboard('[Enter]');
|
|
215
216
|
} else {
|
package/src/types.ts
CHANGED
|
@@ -22,14 +22,14 @@ export interface UserOpts {
|
|
|
22
22
|
* @default mouse
|
|
23
23
|
*/
|
|
24
24
|
interactionType?: 'mouse' | 'touch' | 'keyboard',
|
|
25
|
-
// If using fake timers user should provide something like (time) => jest.advanceTimersByTime(time))}
|
|
26
|
-
// A real timer user would pass
|
|
25
|
+
// If using fake timers user should provide something like (time) => jest.advanceTimersByTime(time))}.
|
|
26
|
+
// A real timer user would pass (waitTime) => new Promise((resolve) => setTimeout(resolve, waitTime))
|
|
27
27
|
// Time is in ms.
|
|
28
28
|
/**
|
|
29
29
|
* A function used by the test utils to advance timers during interactions. Required for certain aria patterns (e.g. table). This can be overridden
|
|
30
30
|
* at the aria pattern tester level if needed.
|
|
31
31
|
*/
|
|
32
|
-
advanceTimer?: (time
|
|
32
|
+
advanceTimer?: (time: number) => unknown | Promise<unknown>
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
export interface BaseTesterOpts extends UserOpts {
|
|
@@ -69,7 +69,11 @@ export interface MenuTesterOpts extends BaseTesterOpts {
|
|
|
69
69
|
/**
|
|
70
70
|
* Whether the current menu is a submenu.
|
|
71
71
|
*/
|
|
72
|
-
isSubmenu?: boolean
|
|
72
|
+
isSubmenu?: boolean,
|
|
73
|
+
/**
|
|
74
|
+
* The root menu of the menu tree. Only available if the menu is a submenu.
|
|
75
|
+
*/
|
|
76
|
+
rootMenu?: HTMLElement
|
|
73
77
|
}
|
|
74
78
|
|
|
75
79
|
export interface SelectTesterOpts extends BaseTesterOpts {
|
package/src/user.ts
CHANGED
|
@@ -67,7 +67,7 @@ type TesterOpts<T> =
|
|
|
67
67
|
T extends 'Tree' ? TreeTesterOpts :
|
|
68
68
|
never;
|
|
69
69
|
|
|
70
|
-
let defaultAdvanceTimer =
|
|
70
|
+
let defaultAdvanceTimer = (waitTime: number | undefined) => new Promise((resolve) => setTimeout(resolve, waitTime));
|
|
71
71
|
|
|
72
72
|
export class User {
|
|
73
73
|
private user;
|