forked from ChromeDevTools/devtools-frontend
-
Notifications
You must be signed in to change notification settings - Fork 24
Expand file tree
/
Copy pathSelectMenu_test.ts
More file actions
318 lines (252 loc) · 11.7 KB
/
Copy pathSelectMenu_test.ts
File metadata and controls
318 lines (252 loc) · 11.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
// Copyright 2023 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import {assert} from 'chai';
import type * as Menus from '../../../../front_end/ui/components/menus/menus.js';
import {loadComponentDocExample} from '../../../../test/interactions/helpers/shared.js';
import {
$,
activeElement,
click,
clickElement,
getBrowserAndPages,
waitFor,
waitForFunction,
waitForNone,
} from '../../../../test/shared/helper.js';
import {
assertElementScreenshotUnchanged,
waitForDialogAnimationEnd,
} from '../../../shared/screenshots.js';
interface GetSelectMenuOptions {
placeholderSelector?: string;
}
async function getFocusedItemValue() {
const focusedItem = await waitFor('devtools-menu-item:focus');
return await focusedItem.evaluate((item: Element) => (item as Menus.Menu.MenuItem).value);
}
async function getSelectMenu(options: GetSelectMenuOptions = {}) {
await loadComponentDocExample('select_menu/basic.html');
if (options.placeholderSelector) {
const placeholder = await waitFor(options.placeholderSelector);
return await waitFor('devtools-select-menu', placeholder);
}
return await waitFor('devtools-select-menu');
}
async function openMenu(options: GetSelectMenuOptions = {}) {
const selectMenu = await getSelectMenu(options);
const animationEndPromise = waitForDialogAnimationEnd();
await click('button', {
root: selectMenu,
});
await animationEndPromise;
return await waitFor('dialog[open]');
}
async function testScreenshotOnPlaceholder(placeholderSelector: string, screenshot: string) {
const dialog = await waitFor(placeholderSelector);
const selectMenu = await waitFor('devtools-select-menu', dialog);
const animationEndPromise = waitForDialogAnimationEnd();
await click('button', {
root: selectMenu,
});
await animationEndPromise;
await assertElementScreenshotUnchanged(dialog, screenshot);
}
describe('SelectMenu', () => {
it('shows the button to open the menu', async () => {
const selectMenu = await getSelectMenu();
const button = await $('button', selectMenu);
assert.isNotNull(button);
});
it('opens the menu when the button is clicked', async () => {
const selectMenu = await getSelectMenu();
const openDialog = await $('dialog[open]', selectMenu);
assert.isNull(openDialog);
await click('button');
await waitFor('dialog[open]');
});
it('changes focus across menu\'s items using keyboard arrows', async () => {
const {frontend} = getBrowserAndPages();
// First, test navigation on a menu without groups.
await openMenu();
await frontend.keyboard.press('ArrowDown');
assert.strictEqual(await getFocusedItemValue(), '1');
await frontend.keyboard.press('ArrowDown');
assert.strictEqual(await getFocusedItemValue(), '2');
await frontend.keyboard.press('ArrowUp');
assert.strictEqual(await getFocusedItemValue(), '1');
await frontend.keyboard.press('Escape');
// Next, test navigation on a menu with groups.
await openMenu({placeholderSelector: '#place-holder-4'});
await frontend.keyboard.press('ArrowDown');
assert.strictEqual(await getFocusedItemValue(), '1');
await frontend.keyboard.press('ArrowUp');
assert.strictEqual(await getFocusedItemValue(), '1');
await frontend.keyboard.press('ArrowDown');
assert.strictEqual(await getFocusedItemValue(), '2');
await frontend.keyboard.press('ArrowUp');
assert.strictEqual(await getFocusedItemValue(), '1');
});
it('focuses the first item when pressing the right arrow key ', async () => {
const {frontend} = getBrowserAndPages();
// First, test navigation on a menu without groups.
await openMenu();
await frontend.keyboard.press('ArrowRight');
assert.strictEqual(await getFocusedItemValue(), '1');
await frontend.keyboard.press('Escape');
// Next, test navigation on a menu with groups.
await openMenu({placeholderSelector: '#place-holder-4'});
await frontend.keyboard.press('ArrowRight');
assert.strictEqual(await getFocusedItemValue(), '1');
});
it('focuses the last item when pressing the up arrow key ', async () => {
const {frontend} = getBrowserAndPages();
// First, test navigation on a menu without groups.
await openMenu();
await frontend.keyboard.press('ArrowUp');
assert.strictEqual(await getFocusedItemValue(), '4');
await frontend.keyboard.press('Escape');
// Next, test navigation on a menu with groups.
await openMenu({placeholderSelector: '#place-holder-4'});
await frontend.keyboard.press('ArrowUp');
assert.strictEqual(await getFocusedItemValue(), '4');
});
it('changes focus across menu\'s items using the HOME and END keys', async () => {
const {frontend} = getBrowserAndPages();
// First, test navigation on a menu without groups.
await openMenu();
await frontend.keyboard.press('ArrowDown');
assert.strictEqual(await getFocusedItemValue(), '1');
await frontend.keyboard.press('End');
assert.strictEqual(await getFocusedItemValue(), '4');
await frontend.keyboard.press('Home');
assert.strictEqual(await getFocusedItemValue(), '1');
await frontend.keyboard.press('Escape');
// Next, test navigation on a menu with groups.
await openMenu({placeholderSelector: '#place-holder-4'});
await frontend.keyboard.press('ArrowDown');
assert.strictEqual(await getFocusedItemValue(), '1');
await frontend.keyboard.press('End');
assert.strictEqual(await getFocusedItemValue(), '4');
await frontend.keyboard.press('Home');
assert.strictEqual(await getFocusedItemValue(), '1');
});
it('opens a menu using the UP and DOWN keys appropriately', async () => {
const {frontend} = getBrowserAndPages();
await loadComponentDocExample('select_menu/basic.html');
// Focus the first select menu, which deploys downwards and open it using the
// down arrow key.
await frontend.keyboard.press('Tab');
await frontend.keyboard.press('ArrowDown');
await waitFor('dialog[open]');
await frontend.keyboard.press('Escape');
const placeHolder1 = await waitFor('#place-holder-1');
await waitFor('dialog:not([open])', placeHolder1);
// Focus the second select menu, which deploys upwards and open it using the
// up arrow key.
await frontend.keyboard.press('Tab');
await frontend.keyboard.press('ArrowUp');
await waitFor('dialog[open]');
});
it('can close a menu with ESC and open it again using the keyboard', async () => {
const {frontend} = getBrowserAndPages();
await loadComponentDocExample('select_menu/basic.html');
// Focus the first select menu, which deploys downwards and open it using the
// down arrow key.
await frontend.keyboard.press('Tab');
await frontend.keyboard.press('ArrowDown');
const placeHolder1 = await waitFor('#place-holder-1');
await waitFor('dialog[open]', placeHolder1);
await frontend.keyboard.press('Escape');
await waitFor('dialog:not([open])', placeHolder1);
// Wait until the focus is set on the button that opens the menu.
await waitForFunction(async () => {
const activeElementHandle = await activeElement();
const activeElementName = await activeElementHandle.evaluate(e => e.tagName);
return activeElementName === 'BUTTON';
});
await frontend.keyboard.press('ArrowDown');
await waitFor('dialog[open]');
});
it('triggers a selectmenuselected event when clicking an item from the menu', async () => {
await openMenu();
const item = await waitFor('devtools-select-menu > devtools-menu-item:nth-child(1)');
const itemText = await item.evaluate((itemText: Element) => (itemText as HTMLElement).innerText.trim());
await clickElement(item);
// Element containing the selected item's text.
const result = await waitFor('#place-holder-1 > div');
const resultText = await result.evaluate((result: Element) => (result as HTMLElement).innerText.trim());
assert.strictEqual(resultText, `Selected option: ${itemText}`);
});
it('triggers a selectmenuselected event using the enter key', async () => {
const {frontend} = getBrowserAndPages();
await openMenu();
await frontend.keyboard.press('ArrowDown');
const focusedItem = await waitFor('devtools-menu-item:focus');
const itemText = await focusedItem.evaluate((item: Element) => (item as HTMLElement).innerText.trim());
await frontend.keyboard.press('Enter');
// Element containing the selected item's text.
const result = await waitFor('#place-holder-1 > div');
const resultText = await result.evaluate((result: Element) => (result as HTMLElement).innerText.trim());
assert.strictEqual(resultText, `Selected option: ${itemText}`);
});
it('closes the dialog by clicking it', async () => {
const dialog = await openMenu();
await clickElement(dialog);
await waitFor('dialog:not([open])');
});
it('closes the dialog using the esc key', async () => {
const {frontend} = getBrowserAndPages();
await openMenu();
await frontend.keyboard.press('Escape');
await waitFor('dialog:not([open])');
});
it('renders a menu in its correct position (top or bottom)', async () => {
await getSelectMenu();
// Open the first (regular) menu
const placeHolder1 = await waitFor('#place-holder-1');
let animationEndPromise = waitForDialogAnimationEnd();
await click('button', {
root: placeHolder1,
});
await animationEndPromise;
const regularMenuWrapper = await waitFor('devtools-select-menu', placeHolder1);
const regularDialog = await waitFor('dialog[open]', placeHolder1);
const regularDialogTopBound = await regularDialog.evaluate((dialog: Element) => dialog.getBoundingClientRect().top);
const regularMenuWrapperBottomBound =
await regularMenuWrapper.evaluate((menu: Element) => menu.getBoundingClientRect().bottom);
assert.strictEqual(regularDialogTopBound, regularMenuWrapperBottomBound);
// Close the first menu
await clickElement(regularDialog);
await waitFor('dialog:not([open])', placeHolder1);
// Open the second (inverted) menu
const placeHolder2 = await waitFor('#place-holder-2');
const invertedButton = await waitFor('button', placeHolder2);
animationEndPromise = waitForDialogAnimationEnd();
await clickElement(invertedButton);
await animationEndPromise;
const invertedMenuWrapper = await waitFor('devtools-select-menu', placeHolder2);
const invertedDialog = await waitFor('dialog[open]', placeHolder2);
const invertedDialogBottomBound =
await invertedDialog.evaluate((dialog: Element) => dialog.getBoundingClientRect().bottom);
const invertedMenuWrapperTopBound =
await invertedMenuWrapper.evaluate((menu: Element) => menu.getBoundingClientRect().top);
assert.strictEqual(invertedDialogBottomBound, invertedMenuWrapperTopBound);
});
it('does not open on click if it\'s disabled', async () => {
await getSelectMenu();
const selectMenuWrapper = await waitFor('#place-holder-6');
const selectMenu = await waitFor('devtools-select-menu', selectMenuWrapper);
const selectMenuButton = await waitFor('devtools-select-menu-button', selectMenu);
await clickElement(selectMenuButton);
await waitForNone('dialog[open]');
});
itScreenshot('renders a menu with a connector', async () => {
await loadComponentDocExample('select_menu/basic.html');
await testScreenshotOnPlaceholder('#place-holder-3', 'select_menu/select_menu.png');
});
itScreenshot('renders a menu with groups', async () => {
await loadComponentDocExample('select_menu/basic.html');
await testScreenshotOnPlaceholder('#place-holder-4', 'select_menu/select_menu_with_groups.png');
});
});