| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 /** @fileoverview Suite of tests for cr-shared-menu. */ | |
| 6 suite('cr-shared-menu', function() { | |
| 7 var menu; | |
| 8 | |
| 9 var button; | |
| 10 var button2; | |
| 11 | |
| 12 var items = []; | |
| 13 | |
| 14 function afterOpen(callback) { | |
| 15 listenOnce(menu, 'iron-overlay-opened', function () { | |
| 16 // paper-listbox applies focus after opening with microtask timing. | |
| 17 // Delay until that has happened: | |
| 18 setTimeout(callback, 0); | |
| 19 }); | |
| 20 } | |
| 21 | |
| 22 function afterClose(callback) { | |
| 23 listenOnce(menu, 'iron-overlay-closed', () => callback()); | |
| 24 } | |
| 25 | |
| 26 suiteSetup(function() { | |
| 27 return PolymerTest.importHtml( | |
| 28 'chrome://resources/polymer/v1_0/paper-item/paper-item.html'); | |
| 29 }); | |
| 30 | |
| 31 setup(function() { | |
| 32 PolymerTest.clearBody(); | |
| 33 // Basic wiring to set up an empty menu that opens when a button is pressed. | |
| 34 menu = document.createElement('cr-shared-menu'); | |
| 35 menu.$$('#dropdown').noAnimations = true; | |
| 36 | |
| 37 button = document.createElement('button'); | |
| 38 button.addEventListener('tap', function(e) { | |
| 39 menu.toggleMenu(button, {}); | |
| 40 e.stopPropagation(); // Prevent 'tap' from closing the dialog. | |
| 41 }); | |
| 42 | |
| 43 button2 = document.createElement('button'); | |
| 44 button2.addEventListener('tap', function(e) { | |
| 45 menu.toggleMenu(button2, {}); | |
| 46 e.stopPropagation(); // Prevent 'tap' from closing the dialog. | |
| 47 }); | |
| 48 | |
| 49 document.body.appendChild(menu); | |
| 50 document.body.appendChild(button); | |
| 51 document.body.appendChild(button2); | |
| 52 }); | |
| 53 | |
| 54 suite('basic', function() { | |
| 55 setup(function() { | |
| 56 // Populate the menu with paper-items. | |
| 57 for (var i = 0; i < 3; i++) { | |
| 58 items[i] = document.createElement('paper-item'); | |
| 59 menu.appendChild(items[i]); | |
| 60 } | |
| 61 }); | |
| 62 | |
| 63 test('opening and closing menu', function(done) { | |
| 64 MockInteractions.tap(button); | |
| 65 assertTrue(menu.menuOpen); | |
| 66 | |
| 67 afterOpen(function() { | |
| 68 // Using tap to close the menu requires that the iron-overlay-behavior | |
| 69 // has finished initializing, which happens asynchronously between | |
| 70 // tapping the button and firing iron-overlay-opened. | |
| 71 MockInteractions.tap(document.body); | |
| 72 assertFalse(menu.menuOpen); | |
| 73 | |
| 74 done(); | |
| 75 }); | |
| 76 }); | |
| 77 | |
| 78 test('open and close menu with escape', function(done) { | |
| 79 MockInteractions.tap(button); | |
| 80 assertTrue(menu.menuOpen); | |
| 81 afterOpen(function() { | |
| 82 // Pressing escape should close the menu. | |
| 83 MockInteractions.pressAndReleaseKeyOn(menu, 27); | |
| 84 assertFalse(menu.menuOpen); | |
| 85 done(); | |
| 86 }); | |
| 87 }); | |
| 88 | |
| 89 test('refocus button on close', function(done) { | |
| 90 button.focus(); | |
| 91 MockInteractions.tap(button); | |
| 92 | |
| 93 afterOpen(function() { | |
| 94 assertTrue(menu.menuOpen); | |
| 95 // Focus is applied asynchronously after the menu is opened. | |
| 96 assertEquals(items[0], menu.shadowRoot.activeElement); | |
| 97 | |
| 98 menu.closeMenu(); | |
| 99 | |
| 100 afterClose(function() { | |
| 101 assertFalse(menu.menuOpen); | |
| 102 // Button should regain focus after closing the menu. | |
| 103 assertEquals(button, document.activeElement); | |
| 104 done(); | |
| 105 }); | |
| 106 | |
| 107 }); | |
| 108 }); | |
| 109 | |
| 110 test('refocus latest button on close', function(done) { | |
| 111 // Regression test for crbug.com/628080. | |
| 112 button.focus(); | |
| 113 MockInteractions.tap(button); | |
| 114 | |
| 115 afterOpen(function() { | |
| 116 button2.focus(); | |
| 117 MockInteractions.tap(button2); | |
| 118 | |
| 119 afterOpen(function() { | |
| 120 menu.closeMenu(); | |
| 121 afterClose(function() { | |
| 122 assertEquals(button2, document.activeElement); | |
| 123 done(); | |
| 124 }); | |
| 125 }); | |
| 126 }); | |
| 127 }); | |
| 128 | |
| 129 test('closeMenu does not refocus button when focus moves', function(done) { | |
| 130 var input = document.createElement('input'); | |
| 131 document.body.appendChild(input); | |
| 132 | |
| 133 button.focus(); | |
| 134 MockInteractions.tap(button); | |
| 135 | |
| 136 afterOpen(function() { | |
| 137 input.focus(); | |
| 138 menu.closeMenu(); | |
| 139 | |
| 140 afterClose(function() { | |
| 141 assertEquals(input, document.activeElement); | |
| 142 done(); | |
| 143 }); | |
| 144 }); | |
| 145 }); | |
| 146 | |
| 147 test('tab closes menu', function(done) { | |
| 148 button.focus(); | |
| 149 MockInteractions.tap(button); | |
| 150 | |
| 151 afterOpen(function() { | |
| 152 MockInteractions.pressAndReleaseKeyOn(items[0], 9); | |
| 153 afterClose(function() { | |
| 154 // Focus should move to a different element, but we can't simulate | |
| 155 // the right events to test this. | |
| 156 done(); | |
| 157 }); | |
| 158 }); | |
| 159 }); | |
| 160 | |
| 161 test('shift-tab closes menu', function(done) { | |
| 162 button.focus(); | |
| 163 MockInteractions.tap(button); | |
| 164 | |
| 165 afterOpen(function() { | |
| 166 MockInteractions.pressAndReleaseKeyOn(items[0], 9, ['shift']); | |
| 167 afterClose(done); | |
| 168 }); | |
| 169 }); | |
| 170 | |
| 171 test('up and down change focus', function(done) { | |
| 172 button.focus(); | |
| 173 MockInteractions.tap(button); | |
| 174 | |
| 175 afterOpen(function() { | |
| 176 // Pressing down on first item goes to second item. | |
| 177 assertEquals(items[0], document.activeElement); | |
| 178 MockInteractions.pressAndReleaseKeyOn(items[0], 40); | |
| 179 assertEquals(items[1], document.activeElement); | |
| 180 | |
| 181 // Pressing down twice more cycles back to first item. | |
| 182 MockInteractions.pressAndReleaseKeyOn(items[1], 40); | |
| 183 MockInteractions.pressAndReleaseKeyOn(items[2], 40); | |
| 184 assertEquals(items[0], document.activeElement); | |
| 185 | |
| 186 // Pressing up cycles to last item. | |
| 187 MockInteractions.pressAndReleaseKeyOn(items[0], 38); | |
| 188 assertEquals(items[2], document.activeElement); | |
| 189 | |
| 190 done(); | |
| 191 }); | |
| 192 }); | |
| 193 }); | |
| 194 | |
| 195 suite('different item types', function() { | |
| 196 setup(function() { | |
| 197 // Populate the menu with tabbable and untabbable items. | |
| 198 items[0] = document.createElement('paper-item'); | |
| 199 items[0].disabled = true; | |
| 200 menu.appendChild(items[0]); | |
| 201 | |
| 202 items[1] = document.createElement('paper-item'); | |
| 203 menu.appendChild(items[1]); | |
| 204 | |
| 205 items[2] = document.createElement('button'); | |
| 206 menu.appendChild(items[2]); | |
| 207 | |
| 208 items[3] = document.createElement('button'); | |
| 209 items[3].disabled = true; | |
| 210 menu.appendChild(items[3]); | |
| 211 | |
| 212 items[4] = document.createElement('paper-item'); | |
| 213 items[4].hidden = true; | |
| 214 menu.appendChild(items[4]); | |
| 215 }); | |
| 216 | |
| 217 test('focus does not start/end with untabbable elements', function(done) { | |
| 218 button.focus(); | |
| 219 MockInteractions.tap(button); | |
| 220 | |
| 221 afterOpen(function() { | |
| 222 // The first item is disabled, so the second item is the first tabbable | |
| 223 // item and should be focusced. | |
| 224 assertEquals(items[1], menu.shadowRoot.activeElement); | |
| 225 | |
| 226 // The last two items are disabled or hidden, so they should be skipped | |
| 227 // when pressing up. | |
| 228 MockInteractions.pressAndReleaseKeyOn(items[1], 38); | |
| 229 assertEquals(items[2], menu.shadowRoot.activeElement); | |
| 230 | |
| 231 // Simulate pressing down on last focusable element to wrap to first | |
| 232 // focusable element. | |
| 233 MockInteractions.pressAndReleaseKeyOn(items[2], 40); | |
| 234 assertEquals(items[1], menu.shadowRoot.activeElement); | |
| 235 | |
| 236 done(); | |
| 237 }); | |
| 238 }); | |
| 239 }); | |
| 240 }); | |
| OLD | NEW |