| OLD | NEW |
| 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 /** @fileoverview Suite of tests for cr-shared-menu. */ | 5 /** @fileoverview Suite of tests for cr-shared-menu. */ |
| 6 suite('cr-shared-menu', function() { | 6 suite('cr-shared-menu', function() { |
| 7 var menu; | 7 var menu; |
| 8 | 8 |
| 9 var button; | 9 var button; |
| 10 var button2; | 10 var button2; |
| 11 | 11 |
| 12 var items = []; | 12 var items = []; |
| 13 | 13 |
| 14 function afterOpen(callback) { | 14 function afterOpen(callback) { |
| 15 menu.addEventListener('iron-overlay-opened', function f() { | 15 listenOnce(menu, 'iron-overlay-opened', function () { |
| 16 menu.removeEventListener('iron-overlay-opened', f); | 16 // paper-listbox applies focus after opening with microtask timing. |
| 17 callback(); | 17 // Delay until that has happened: |
| 18 setTimeout(callback, 0); |
| 18 }); | 19 }); |
| 19 } | 20 } |
| 20 | 21 |
| 21 function afterClose(callback) { | 22 function afterClose(callback) { |
| 22 menu.addEventListener('iron-overlay-closed', function f() { | 23 listenOnce(menu, 'iron-overlay-closed', () => callback()); |
| 23 menu.removeEventListener('iron-overlay-closed', f); | |
| 24 callback(); | |
| 25 }); | |
| 26 } | 24 } |
| 27 | 25 |
| 28 suiteSetup(function() { | 26 suiteSetup(function() { |
| 29 return PolymerTest.importHtml( | 27 return PolymerTest.importHtml( |
| 30 'chrome://resources/polymer/v1_0/paper-item/paper-item.html'); | 28 'chrome://resources/polymer/v1_0/paper-item/paper-item.html'); |
| 31 }); | 29 }); |
| 32 | 30 |
| 33 setup(function() { | 31 setup(function() { |
| 34 PolymerTest.clearBody(); | 32 PolymerTest.clearBody(); |
| 35 // Basic wiring to set up an empty menu that opens when a button is pressed. | 33 // Basic wiring to set up an empty menu that opens when a button is pressed. |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 input.focus(); | 137 input.focus(); |
| 140 menu.closeMenu(); | 138 menu.closeMenu(); |
| 141 | 139 |
| 142 afterClose(function() { | 140 afterClose(function() { |
| 143 assertEquals(input, document.activeElement); | 141 assertEquals(input, document.activeElement); |
| 144 done(); | 142 done(); |
| 145 }); | 143 }); |
| 146 }); | 144 }); |
| 147 }); | 145 }); |
| 148 | 146 |
| 149 test('focus is trapped inside the menu', function(done) { | 147 test('tab closes menu', function(done) { |
| 150 button.focus(); | 148 button.focus(); |
| 151 MockInteractions.tap(button); | 149 MockInteractions.tap(button); |
| 152 | 150 |
| 153 afterOpen(function() { | 151 afterOpen(function() { |
| 154 // Simulate shift-tab on first element. | 152 MockInteractions.pressAndReleaseKeyOn(items[0], 9); |
| 155 assertEquals(items[0], menu.shadowRoot.activeElement); | 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() { |
| 156 MockInteractions.pressAndReleaseKeyOn(items[0], 9, ['shift']); | 166 MockInteractions.pressAndReleaseKeyOn(items[0], 9, ['shift']); |
| 157 assertEquals(items[2], menu.shadowRoot.activeElement); | 167 afterClose(done); |
| 168 }); |
| 169 }); |
| 158 | 170 |
| 159 // Simulate tab on last element. | 171 test('up and down change focus', function(done) { |
| 160 MockInteractions.pressAndReleaseKeyOn(items[2], 9); | 172 button.focus(); |
| 161 assertEquals(items[0], menu.shadowRoot.activeElement); | 173 MockInteractions.tap(button); |
| 162 | 174 |
| 163 // Simulate shift-tab on first element. | 175 afterOpen(function() { |
| 164 assertEquals(items[0], menu.shadowRoot.activeElement); | 176 // Pressing down on first item goes to second item. |
| 165 MockInteractions.pressAndReleaseKeyOn(items[0], 9, ['shift']); | 177 assertEquals(items[0], document.activeElement); |
| 166 assertEquals(items[2], menu.shadowRoot.activeElement); | 178 MockInteractions.pressAndReleaseKeyOn(items[0], 40); |
| 179 assertEquals(items[1], document.activeElement); |
| 167 | 180 |
| 168 // Simulate shift-tab on last element. This should simply cause the | 181 // Pressing down twice more cycles back to first item. |
| 169 // browser to focus the previous item in the tab order, since | 182 MockInteractions.pressAndReleaseKeyOn(items[1], 40); |
| 170 // cr-shared-menu should not wrap in this case. However, we can't mimic | 183 MockInteractions.pressAndReleaseKeyOn(items[2], 40); |
| 171 // native events from JS, so the focus won't actually move unless | 184 assertEquals(items[0], document.activeElement); |
| 172 // cr-shared--menu misbehaves. | 185 |
| 173 MockInteractions.pressAndReleaseKeyOn(items[2], 9, ['shift']); | 186 // Pressing up cycles to last item. |
| 174 assertEquals(items[2], menu.shadowRoot.activeElement); | 187 MockInteractions.pressAndReleaseKeyOn(items[0], 38); |
| 188 assertEquals(items[2], document.activeElement); |
| 175 | 189 |
| 176 done(); | 190 done(); |
| 177 }); | 191 }); |
| 178 }); | 192 }); |
| 179 }); | 193 }); |
| 180 | 194 |
| 181 suite('different item types', function() { | 195 suite('different item types', function() { |
| 182 setup(function() { | 196 setup(function() { |
| 183 // Populate the menu with tabbable and untabbable items. | 197 // Populate the menu with tabbable and untabbable items. |
| 184 items[0] = document.createElement('paper-item'); | 198 items[0] = document.createElement('paper-item'); |
| 185 items[0].disabled = true; | 199 items[0].disabled = true; |
| 186 menu.appendChild(items[0]); | 200 menu.appendChild(items[0]); |
| 187 | 201 |
| 188 items[1] = document.createElement('paper-item'); | 202 items[1] = document.createElement('paper-item'); |
| 189 menu.appendChild(items[1]); | 203 menu.appendChild(items[1]); |
| 190 | 204 |
| 191 items[2] = document.createElement('button'); | 205 items[2] = document.createElement('button'); |
| 192 menu.appendChild(items[2]); | 206 menu.appendChild(items[2]); |
| 193 | 207 |
| 194 items[3] = document.createElement('button'); | 208 items[3] = document.createElement('button'); |
| 195 items[3].disabled = true; | 209 items[3].disabled = true; |
| 210 menu.appendChild(items[3]); |
| 196 | 211 |
| 197 items[4] = document.createElement('paper-item'); | 212 items[4] = document.createElement('paper-item'); |
| 198 items[4].hidden = true; | 213 items[4].hidden = true; |
| 199 menu.appendChild(items[4]); | 214 menu.appendChild(items[4]); |
| 200 }); | 215 }); |
| 201 | 216 |
| 202 test('focus does not start/end with untabbable elements', function(done) { | 217 test('focus does not start/end with untabbable elements', function(done) { |
| 203 button.focus(); | 218 button.focus(); |
| 204 MockInteractions.tap(button); | 219 MockInteractions.tap(button); |
| 205 | 220 |
| 206 afterOpen(function() { | 221 afterOpen(function() { |
| 207 // The first item is disabled, so the second item is the first tabbable | 222 // The first item is disabled, so the second item is the first tabbable |
| 208 // item and should be focusced. | 223 // item and should be focusced. |
| 209 assertEquals(items[1], menu.shadowRoot.activeElement); | 224 assertEquals(items[1], menu.shadowRoot.activeElement); |
| 210 | 225 |
| 211 // The last two items are disabled or hidden, so they should be skipped | 226 // The last two items are disabled or hidden, so they should be skipped |
| 212 // too. | 227 // when pressing up. |
| 213 MockInteractions.pressAndReleaseKeyOn(items[1], 9, ['shift']); | 228 MockInteractions.pressAndReleaseKeyOn(items[1], 38); |
| 214 assertEquals(items[2], menu.shadowRoot.activeElement); | 229 assertEquals(items[2], menu.shadowRoot.activeElement); |
| 215 | 230 |
| 216 // Simulate tab on last tabbable element to wrap to the first tabbable | 231 // Simulate pressing down on last focusable element to wrap to first |
| 217 // element again. | 232 // focusable element. |
| 218 MockInteractions.pressAndReleaseKeyOn(items[2], 9); | 233 MockInteractions.pressAndReleaseKeyOn(items[2], 40); |
| 219 assertEquals(items[1], menu.shadowRoot.activeElement); | 234 assertEquals(items[1], menu.shadowRoot.activeElement); |
| 220 | 235 |
| 221 done(); | 236 done(); |
| 222 }); | 237 }); |
| 223 }); | 238 }); |
| 224 }); | 239 }); |
| 225 }); | 240 }); |
| OLD | NEW |