Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(401)

Side by Side Diff: chrome/test/data/webui/cr_elements/cr_action_menu_test.js

Issue 2980463002: Revert of [cr-action-menu] Use clientWidth for rtl flipping. (Closed)
Patch Set: Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 /**
6 * @fileoverview Tests for cr-action-menu element. Runs as an interactive UI 6 * @fileoverview Tests for cr-action-menu element. Runs as an interactive UI
7 * test, since many of these tests check focus behavior. 7 * test, since many of these tests check focus behavior.
8 */ 8 */
9 suite('CrActionMenu', function() { 9 suite('CrActionMenu', function() {
10 /** @type {?CrActionMenuElement} */ 10 /** @type {?CrActionMenuElement} */
11 var menu = null; 11 var menu = null;
12 12
13 /** @type {?NodeList<HTMLElement>} */ 13 /** @type {?NodeList<HTMLElement>} */
14 var items = null; 14 var items = null;
15 15
16 /** @type {HTMLElement} */
17 var dots = null;
18
19 setup(function() { 16 setup(function() {
20 PolymerTest.clearBody(); 17 PolymerTest.clearBody();
21 18
22 document.body.innerHTML = ` 19 document.body.innerHTML = `
23 <button id="dots">...</button> 20 <button id="dots">...</button>
24 <dialog is="cr-action-menu"> 21 <dialog is="cr-action-menu">
25 <button class="dropdown-item">Un</button> 22 <button class="dropdown-item">Un</button>
26 <hr> 23 <hr>
27 <button class="dropdown-item">Dos</button> 24 <button class="dropdown-item">Dos</button>
28 <button class="dropdown-item">Tres</button> 25 <button class="dropdown-item">Tres</button>
29 </dialog> 26 </dialog>
30 `; 27 `;
31 28
32 menu = document.querySelector('dialog[is=cr-action-menu]'); 29 menu = document.querySelector('dialog[is=cr-action-menu]');
33 items = menu.querySelectorAll('.dropdown-item'); 30 items = menu.querySelectorAll('.dropdown-item');
34 dots = document.querySelector('#dots');
35 assertEquals(3, items.length); 31 assertEquals(3, items.length);
36 }); 32 });
37 33
38 teardown(function() { 34 teardown(function() {
39 document.body.style.direction = 'ltr';
40
41 if (menu.open) 35 if (menu.open)
42 menu.close(); 36 menu.close();
43 }); 37 });
44 38
45 function down() { 39 function down() {
46 MockInteractions.keyDownOn(menu, 'ArrowDown', [], 'ArrowDown'); 40 MockInteractions.keyDownOn(menu, 'ArrowDown', [], 'ArrowDown');
47 } 41 }
48 42
49 function up() { 43 function up() {
50 MockInteractions.keyDownOn(menu, 'ArrowUp', [], 'ArrowUp'); 44 MockInteractions.keyDownOn(menu, 'ArrowUp', [], 'ArrowUp');
51 } 45 }
52 46
53 test('hidden or disabled items', function() { 47 test('hidden or disabled items', function() {
54 menu.showAt(dots); 48 menu.showAt(document.querySelector('#dots'));
55 down(); 49 down();
56 assertEquals(menu.root.activeElement, items[0]); 50 assertEquals(menu.root.activeElement, items[0]);
57 51
58 menu.close(); 52 menu.close();
59 items[0].hidden = true; 53 items[0].hidden = true;
60 menu.showAt(dots); 54 menu.showAt(document.querySelector('#dots'));
61 down(); 55 down();
62 assertEquals(menu.root.activeElement, items[1]); 56 assertEquals(menu.root.activeElement, items[1]);
63 57
64 menu.close(); 58 menu.close();
65 items[1].disabled = true; 59 items[1].disabled = true;
66 menu.showAt(dots); 60 menu.showAt(document.querySelector('#dots'));
67 down(); 61 down();
68 assertEquals(menu.root.activeElement, items[2]); 62 assertEquals(menu.root.activeElement, items[2]);
69 }); 63 });
70 64
71 test('focus after down/up arrow', function() { 65 test('focus after down/up arrow', function() {
72 menu.showAt(dots); 66 menu.showAt(document.querySelector('#dots'));
73 67
74 // The menu should be focused when shown, but not on any of the items. 68 // The menu should be focused when shown, but not on any of the items.
75 assertEquals(menu, document.activeElement); 69 assertEquals(menu, document.activeElement);
76 assertNotEquals(items[0], menu.root.activeElement); 70 assertNotEquals(items[0], menu.root.activeElement);
77 assertNotEquals(items[1], menu.root.activeElement); 71 assertNotEquals(items[1], menu.root.activeElement);
78 assertNotEquals(items[2], menu.root.activeElement); 72 assertNotEquals(items[2], menu.root.activeElement);
79 73
80 down(); 74 down();
81 assertEquals(items[0], menu.root.activeElement); 75 assertEquals(items[0], menu.root.activeElement);
82 down(); 76 down();
83 assertEquals(items[1], menu.root.activeElement); 77 assertEquals(items[1], menu.root.activeElement);
84 down(); 78 down();
85 assertEquals(items[2], menu.root.activeElement); 79 assertEquals(items[2], menu.root.activeElement);
86 down(); 80 down();
87 assertEquals(items[0], menu.root.activeElement); 81 assertEquals(items[0], menu.root.activeElement);
88 up(); 82 up();
89 assertEquals(items[2], menu.root.activeElement); 83 assertEquals(items[2], menu.root.activeElement);
90 up(); 84 up();
91 assertEquals(items[1], menu.root.activeElement); 85 assertEquals(items[1], menu.root.activeElement);
92 up(); 86 up();
93 assertEquals(items[0], menu.root.activeElement); 87 assertEquals(items[0], menu.root.activeElement);
94 up(); 88 up();
95 assertEquals(items[2], menu.root.activeElement); 89 assertEquals(items[2], menu.root.activeElement);
96 90
97 items[1].disabled = true; 91 items[1].disabled = true;
98 up(); 92 up();
99 assertEquals(items[0], menu.root.activeElement); 93 assertEquals(items[0], menu.root.activeElement);
100 }); 94 });
101 95
102 test('pressing up arrow when no focus will focus last item', function() { 96 test('pressing up arrow when no focus will focus last item', function(){
103 menu.showAt(dots); 97 menu.showAt(document.querySelector('#dots'));
104 assertEquals(menu, document.activeElement); 98 assertEquals(menu, document.activeElement);
105 99
106 up(); 100 up();
107 assertEquals(items[items.length - 1], menu.root.activeElement); 101 assertEquals(items[items.length - 1], menu.root.activeElement);
108 }); 102 });
109 103
110 test('can navigate to dynamically added items', function() { 104 test('can navigate to dynamically added items', function() {
111 // Can modify children after attached() and before showAt(). 105 // Can modify children after attached() and before showAt().
112 var item = document.createElement('button'); 106 var item = document.createElement('button');
113 item.classList.add('dropdown-item'); 107 item.classList.add('dropdown-item');
114 menu.insertBefore(item, items[0]); 108 menu.insertBefore(item, items[0]);
115 menu.showAt(dots); 109 menu.showAt(document.querySelector('#dots'));
116 110
117 down(); 111 down();
118 assertEquals(item, menu.root.activeElement); 112 assertEquals(item, menu.root.activeElement);
119 down(); 113 down();
120 assertEquals(items[0], menu.root.activeElement); 114 assertEquals(items[0], menu.root.activeElement);
121 115
122 // Can modify children while menu is open. 116 // Can modify children while menu is open.
123 menu.removeChild(item); 117 menu.removeChild(item);
124 118
125 up(); 119 up();
126 // Focus should have wrapped around to final item. 120 // Focus should have wrapped around to final item.
127 assertEquals(items[2], menu.root.activeElement); 121 assertEquals(items[2], menu.root.activeElement);
128 }); 122 });
129 123
130 test('close on resize', function() { 124 test('close on resize', function() {
131 menu.showAt(dots); 125 menu.showAt(document.querySelector('#dots'));
132 assertTrue(menu.open); 126 assertTrue(menu.open);
133 127
134 window.dispatchEvent(new CustomEvent('resize')); 128 window.dispatchEvent(new CustomEvent('resize'));
135 assertFalse(menu.open); 129 assertFalse(menu.open);
136 }); 130 });
137 131
138 test('close on popstate', function() { 132 test('close on popstate', function() {
139 menu.showAt(dots); 133 menu.showAt(document.querySelector('#dots'));
140 assertTrue(menu.open); 134 assertTrue(menu.open);
141 135
142 window.dispatchEvent(new CustomEvent('popstate')); 136 window.dispatchEvent(new CustomEvent('popstate'));
143 assertFalse(menu.open); 137 assertFalse(menu.open);
144 }); 138 });
145 139
146 /** @param {string} key The key to use for closing. */ 140 /** @param {string} key The key to use for closing. */
147 function testFocusAfterClosing(key) { 141 function testFocusAfterClosing(key) {
148 return new Promise(function(resolve) { 142 return new Promise(function(resolve) {
143 var dots = document.querySelector('#dots');
149 menu.showAt(dots); 144 menu.showAt(dots);
150 assertTrue(menu.open); 145 assertTrue(menu.open);
151 146
152 // Check that focus returns to the anchor element. 147 // Check that focus returns to the anchor element.
153 dots.addEventListener('focus', resolve); 148 dots.addEventListener('focus', resolve);
154 MockInteractions.keyDownOn(menu, key, [], key); 149 MockInteractions.keyDownOn(menu, key, [], key);
155 assertFalse(menu.open); 150 assertFalse(menu.open);
156 }); 151 });
157 } 152 }
158 153
159 test('close on Tab', function() { 154 test('close on Tab', function() { return testFocusAfterClosing('Tab'); });
160 return testFocusAfterClosing('Tab');
161 });
162 test('close on Escape', function() { 155 test('close on Escape', function() {
163 return testFocusAfterClosing('Escape'); 156 return testFocusAfterClosing('Escape');
164 }); 157 });
165 158
166 test('mouse movement focus options', function() { 159 test('mouse movement focus options', function() {
167 function makeMouseoverEvent(node) { 160 function makeMouseoverEvent(node) {
168 var e = new MouseEvent('mouseover', {bubbles: true}); 161 var e = new MouseEvent('mouseover', {bubbles: true});
169 node.dispatchEvent(e); 162 node.dispatchEvent(e);
170 } 163 }
171 164
172 menu.showAt(dots); 165 menu.showAt(document.querySelector('#dots'));
173 166
174 // Moving mouse on option 1 should focus it. 167 // Moving mouse on option 1 should focus it.
175 assertNotEquals(items[0], menu.root.activeElement); 168 assertNotEquals(items[0], menu.root.activeElement);
176 makeMouseoverEvent(items[0]); 169 makeMouseoverEvent(items[0]);
177 assertEquals(items[0], menu.root.activeElement); 170 assertEquals(items[0], menu.root.activeElement);
178 171
179 // Moving mouse on the menu (not on option) should focus the menu. 172 // Moving mouse on the menu (not on option) should focus the menu.
180 makeMouseoverEvent(menu); 173 makeMouseoverEvent(menu);
181 assertNotEquals(items[0], menu.root.activeElement); 174 assertNotEquals(items[0], menu.root.activeElement);
182 assertEquals(menu, document.activeElement); 175 assertEquals(menu, document.activeElement);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 menu.close(); 252 menu.close();
260 253
261 // If the viewport can't fit the menu, align the menu to the viewport. 254 // If the viewport can't fit the menu, align the menu to the viewport.
262 menu.showAtPosition({ 255 menu.showAtPosition({
263 left: menuWidth - 5, 256 left: menuWidth - 5,
264 top: 0, 257 top: 0,
265 width: 0, 258 width: 0,
266 height: 0, 259 height: 0,
267 maxX: menuWidth * 2 - 10, 260 maxX: menuWidth * 2 - 10,
268 }); 261 });
269 assertEquals(`${menuWidth - 10}px`, menu.style.left); 262 assertEquals(`${menuWidth - 10}px`, menu.style.left);
270 assertEquals(`0px`, menu.style.top); 263 assertEquals(`0px`, menu.style.top);
271 menu.close(); 264 menu.close();
272 265
273 // Alignment is reversed in RTL. 266 // Alignment is reversed in RTL.
274 document.body.style.direction = 'rtl'; 267 document.body.style.direction = 'rtl';
275 menu.showAtPosition(config); 268 menu.showAtPosition(config);
276 assertTrue(menu.open); 269 assertTrue(menu.open);
277 assertEquals(140 - menuWidth, menu.offsetLeft); 270 assertEquals(140 - menuWidth, menu.offsetLeft);
278 assertEquals('250px', menu.style.top); 271 assertEquals('250px', menu.style.top);
279 menu.close(); 272 menu.close();
273 document.body.style.direction = 'ltr';
280 }); 274 });
281 275
282 suite('offscreen scroll positioning', function() { 276 test('offscreen scroll positioning', function() {
283 var bodyHeight = 10000; 277 var bodyHeight = 10000;
284 var bodyWidth = 20000; 278 var bodyWidth = 20000;
285 var containerLeft = 5000; 279 var containerLeft = 5000;
286 var containerTop = 10000; 280 var containerTop = 10000;
287 var containerWidth = 500; 281 var containerWidth = 500;
288 var containerHeight = 500; 282 var containerHeight = 500;
283 document.body.innerHTML = `
284 <style>
285 body {
286 height: ${bodyHeight}px;
287 width: ${bodyWidth}px;
288 }
289 289
290 setup(function() { 290 #container {
291 document.body.scrollTop = 0; 291 overflow: auto;
292 document.body.scrollLeft = 0; 292 position: absolute;
293 document.body.innerHTML = ` 293 top: ${containerTop}px;
294 <style> 294 left: ${containerLeft}px;
295 body { 295 height: ${containerHeight}px;
296 height: ${bodyHeight}px; 296 width: ${containerWidth}px;
297 width: ${bodyWidth}px; 297 }
298 }
299 298
300 #container { 299 #inner-container {
301 overflow: auto; 300 height: 1000px;
302 position: absolute; 301 width: 1000px;
303 top: ${containerTop}px; 302 }
304 left: ${containerLeft}px; 303 </style>
305 right: ${containerLeft}px; 304 <div id="container">
306 height: ${containerHeight}px; 305 <div id="inner-container">
307 width: ${containerWidth}px; 306 <button id="dots">...</button>
308 } 307 <dialog is="cr-action-menu">
309 308 <button class="dropdown-item">Un</button>
310 #inner-container { 309 <hr>
311 height: 1000px; 310 <button class="dropdown-item">Dos</button>
312 width: 1000px; 311 <button class="dropdown-item">Tres</button>
313 } 312 </dialog>
314 </style>
315 <div id="container">
316 <div id="inner-container">
317 <button id="dots">...</button>
318 <dialog is="cr-action-menu">
319 <button class="dropdown-item">Un</button>
320 <hr>
321 <button class="dropdown-item">Dos</button>
322 <button class="dropdown-item">Tres</button>
323 </dialog>
324 </div>
325 </div> 313 </div>
326 `; 314 </div>
327 menu = document.querySelector('dialog[is=cr-action-menu]'); 315 `;
328 dots = document.querySelector('#dots'); 316 menu = document.querySelector('dialog[is=cr-action-menu]');
329 }) 317 var dots = document.querySelector('#dots');
330 318
331 // Show the menu, scrolling the body to the button. 319 // Show the menu, scrolling the body to the button.
332 test('simple offscreen', function() { 320 menu.showAt(
333 menu.showAt(dots, {anchorAlignmentX: AnchorAlignment.AFTER_START}); 321 dots,
334 assertEquals(`${containerLeft}px`, menu.style.left); 322 {anchorAlignmentX: AnchorAlignment.AFTER_START});
335 assertEquals(`${containerTop}px`, menu.style.top); 323 assertEquals(`${containerLeft}px`, menu.style.left);
336 menu.close(); 324 assertEquals(`${containerTop}px`, menu.style.top);
337 }); 325 menu.close();
338 326
339 // Show the menu, scrolling the container to the button, and the body to the 327 // Show the menu, scrolling the container to the button, and the body to the
340 // button. 328 // button.
341 test('offscreen and out of scroll container viewport', function() { 329 document.body.scrollLeft = bodyWidth;
342 document.body.scrollLeft = bodyWidth; 330 document.body.scrollTop = bodyHeight;
343 document.body.scrollTop = bodyHeight;
344 var container = document.querySelector('#container');
345 331
346 container.scrollLeft = containerLeft; 332 document.querySelector('#container').scrollLeft = containerLeft;
347 container.scrollTop = containerTop; 333 document.querySelector('#container').scrollTop = containerTop;
348 334
349 menu.showAt(dots, {anchorAlignmentX: AnchorAlignment.AFTER_START}); 335 menu.showAt(dots, {anchorAlignmentX: AnchorAlignment.AFTER_START});
350 assertEquals(`${containerLeft}px`, menu.style.left); 336 assertEquals(`${containerLeft}px`, menu.style.left);
351 assertEquals(`${containerTop}px`, menu.style.top); 337 assertEquals(`${containerTop}px`, menu.style.top);
352 menu.close(); 338 menu.close();
353 });
354 339
355 // Show the menu for an already onscreen button. The anchor should be 340 // Show the menu for an already onscreen button. The anchor should be
356 // overridden so that no scrolling happens. 341 // overridden so that no scrolling happens.
357 test('onscreen forces anchor change', function() { 342 document.body.scrollLeft = 0;
358 var rect = dots.getBoundingClientRect(); 343 document.body.scrollTop = 0;
359 document.body.scrollLeft = rect.right - document.body.clientWidth;
360 document.body.scrollTop = rect.bottom - document.body.clientHeight;
361 344
362 menu.showAt(dots, {anchorAlignmentX: AnchorAlignment.AFTER_START}); 345 var rect = dots.getBoundingClientRect();
363 var menuWidth = menu.offsetWidth; 346 document.body.scrollLeft = rect.right - document.body.clientWidth;
364 var menuHeight = menu.offsetHeight; 347 document.body.scrollTop = rect.bottom - document.body.clientHeight;
365 var buttonWidth = dots.offsetWidth;
366 var buttonHeight = dots.offsetHeight;
367 assertEquals(containerLeft - menuWidth + buttonWidth, menu.offsetLeft);
368 assertEquals(containerTop - menuHeight + buttonHeight, menu.offsetTop);
369 menu.close();
370 });
371 348
372 test('scroll position maintained for showAtPosition', function() { 349 menu.showAt(dots, {anchorAlignmentX: AnchorAlignment.AFTER_START});
373 document.body.scrollLeft = 500; 350 var menuWidth = menu.offsetWidth;
374 document.body.scrollTop = 1000; 351 var menuHeight = menu.offsetHeight;
375 menu.showAtPosition({top: 50, left: 50}); 352 var buttonWidth = dots.offsetWidth;
376 assertEquals(550, menu.offsetLeft); 353 var buttonHeight = dots.offsetHeight;
377 assertEquals(1050, menu.offsetTop); 354 assertEquals(containerLeft - menuWidth + buttonWidth, menu.offsetLeft);
378 menu.close(); 355 assertEquals(containerTop - menuHeight + buttonHeight, menu.offsetTop);
379 });
380
381 test('rtl', function() {
382 // Anchor to an item in RTL.
383 document.body.style.direction = 'rtl';
384 menu.showAt(dots, {anchorAlignmentX: AnchorAlignment.AFTER_START});
385 assertEquals(
386 container.offsetLeft + containerWidth - menu.offsetWidth,
387 menu.offsetLeft);
388 assertEquals(containerTop, menu.offsetTop);
389 menu.close();
390 });
391 }); 356 });
392 }); 357 });
OLDNEW
« no previous file with comments | « no previous file | ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698