browser_editcontrols_update.js (9610B)
1 // This test checks that the edit command enabled state (cut/paste) is updated 2 // properly when the edit controls are on the toolbar, popup and not present. 3 // It also verifies that the performance optimiation implemented by 4 // updateEditUIVisibility in browser.js is applied. 5 6 let isMac = navigator.platform.indexOf("Mac") == 0; 7 8 function checkState(allowCut, desc, testWindow = window) { 9 is( 10 testWindow.document.getElementById("cmd_cut").getAttribute("disabled") == 11 "true", 12 !allowCut, 13 desc + " - cut" 14 ); 15 is( 16 testWindow.document.getElementById("cmd_paste").getAttribute("disabled") == 17 "true", 18 false, 19 desc + " - paste" 20 ); 21 } 22 23 // Add a special controller to the urlbar and browser to listen in on when 24 // commands are being updated. Return a promise that resolves when 'count' 25 // updates have occurred. 26 function expectCommandUpdate(count, testWindow = window) { 27 return new Promise((resolve, reject) => { 28 let overrideController = { 29 supportsCommand(cmd) { 30 return cmd == "cmd_delete"; 31 }, 32 isCommandEnabled() { 33 if (!count) { 34 ok(false, "unexpected update"); 35 reject(); 36 } 37 38 if (!--count) { 39 testWindow.gURLBar.inputField.controllers.removeControllerAt( 40 0, 41 overrideController 42 ); 43 testWindow.gBrowser.selectedBrowser.controllers.removeControllerAt( 44 0, 45 overrideController 46 ); 47 resolve(true); 48 } 49 }, 50 }; 51 52 if (!count) { 53 SimpleTest.executeSoon(() => { 54 testWindow.gURLBar.inputField.controllers.removeControllerAt( 55 0, 56 overrideController 57 ); 58 testWindow.gBrowser.selectedBrowser.controllers.removeControllerAt( 59 0, 60 overrideController 61 ); 62 resolve(false); 63 }); 64 } 65 66 testWindow.gURLBar.inputField.controllers.insertControllerAt( 67 0, 68 overrideController 69 ); 70 testWindow.gBrowser.selectedBrowser.controllers.insertControllerAt( 71 0, 72 overrideController 73 ); 74 }); 75 } 76 77 // Call this between `.select()` to make sure the selection actually changes 78 // and thus TextInputListener::UpdateTextInputCommands() is called. 79 function deselectURLBarAndSpin() { 80 gURLBar.inputField.setSelectionRange(0, 0); 81 return new Promise(setTimeout); 82 } 83 84 add_task(async function test_init() { 85 // Put something on the clipboard to verify that the paste button is properly enabled during the test. 86 let clipboardHelper = Cc["@mozilla.org/widget/clipboardhelper;1"].getService( 87 Ci.nsIClipboardHelper 88 ); 89 await new Promise(resolve => { 90 SimpleTest.waitForClipboard( 91 "Sample", 92 function () { 93 clipboardHelper.copyString("Sample"); 94 }, 95 resolve 96 ); 97 }); 98 99 // Open and close the panel first so that it is fully initialized. 100 await gCUITestUtils.openMainMenu(); 101 await gCUITestUtils.hideMainMenu(); 102 }); 103 104 // Test updating when the panel is open with the edit-controls on the panel. 105 // Updates should occur. 106 add_task(async function test_panelui_opened() { 107 document.commandDispatcher.unlock(); 108 gURLBar.focus(); 109 gURLBar.value = "test"; 110 111 await gCUITestUtils.openMainMenu(); 112 113 checkState(false, "Update when edit-controls is on panel and visible"); 114 115 let overridePromise = expectCommandUpdate(1); 116 gURLBar.select(); 117 await overridePromise; 118 119 checkState( 120 true, 121 "Update when edit-controls is on panel and selection changed" 122 ); 123 124 overridePromise = expectCommandUpdate(0); 125 await gCUITestUtils.hideMainMenu(); 126 await overridePromise; 127 128 // Check that updates do not occur after the panel has been closed. 129 checkState(true, "Update when edit-controls is on panel and hidden"); 130 131 // Mac will update the enabled state even when the panel is closed so that 132 // main menubar shortcuts will work properly. 133 await deselectURLBarAndSpin(); 134 overridePromise = expectCommandUpdate(isMac ? 1 : 0); 135 gURLBar.select(); 136 await overridePromise; 137 checkState( 138 true, 139 "Update when edit-controls is on panel, hidden and selection changed" 140 ); 141 }); 142 143 // Test updating when the edit-controls are moved to the toolbar. 144 add_task(async function test_panelui_customize_to_toolbar() { 145 await startCustomizing(); 146 let navbar = document.getElementById("nav-bar"); 147 simulateItemDrag( 148 document.getElementById("edit-controls"), 149 CustomizableUI.getCustomizationTarget(navbar), 150 "end" 151 ); 152 await endCustomizing(); 153 154 // updateEditUIVisibility should be called when customization ends but isn't. See bug 1359790. 155 updateEditUIVisibility(); 156 157 // The URL bar may have been focused to begin with, which means 158 // that subsequent calls to focus it won't result in command 159 // updates, so we'll make sure to blur it. 160 gURLBar.blur(); 161 162 let overridePromise = expectCommandUpdate(1); 163 gURLBar.select(); 164 gURLBar.focus(); 165 gURLBar.value = "other"; 166 await overridePromise; 167 checkState(false, "Update when edit-controls on toolbar and focused"); 168 169 await deselectURLBarAndSpin(); 170 overridePromise = expectCommandUpdate(1); 171 gURLBar.select(); 172 await overridePromise; 173 checkState( 174 true, 175 "Update when edit-controls on toolbar and selection changed" 176 ); 177 178 const kOverflowPanel = document.getElementById("widget-overflow"); 179 180 let originalWidth = window.outerWidth; 181 registerCleanupFunction(async function () { 182 kOverflowPanel.removeAttribute("animate"); 183 window.resizeTo(originalWidth, window.outerHeight); 184 await TestUtils.waitForCondition(() => !navbar.hasAttribute("overflowing")); 185 CustomizableUI.reset(); 186 }); 187 188 window.resizeTo(kForceOverflowWidthPx, window.outerHeight); 189 await TestUtils.waitForCondition( 190 () => 191 navbar.hasAttribute("overflowing") && 192 !navbar.querySelector("edit-controls") 193 ); 194 195 // Mac will update the enabled state even when the buttons are overflowing, 196 // so main menubar shortcuts will work properly. 197 await deselectURLBarAndSpin(); 198 overridePromise = expectCommandUpdate(isMac ? 1 : 0); 199 gURLBar.select(); 200 await overridePromise; 201 checkState( 202 true, 203 "Update when edit-controls is on overflow panel, hidden and selection changed" 204 ); 205 206 // Check that we get an update if we select content while the panel is open. 207 await deselectURLBarAndSpin(); 208 overridePromise = expectCommandUpdate(1); 209 await navbar.overflowable.show(); 210 gURLBar.select(); 211 await overridePromise; 212 213 // And that we don't (except on mac) when the panel is hidden. 214 kOverflowPanel.hidePopup(); 215 await deselectURLBarAndSpin(); 216 overridePromise = expectCommandUpdate(isMac ? 1 : 0); 217 gURLBar.select(); 218 await overridePromise; 219 220 window.resizeTo(originalWidth, window.outerHeight); 221 await TestUtils.waitForCondition(() => !navbar.hasAttribute("overflowing")); 222 223 CustomizableUI.addWidgetToArea( 224 "edit-controls", 225 CustomizableUI.AREA_FIXED_OVERFLOW_PANEL 226 ); 227 // updateEditUIVisibility should be called when customization happens but isn't. See bug 1359790. 228 updateEditUIVisibility(); 229 230 await deselectURLBarAndSpin(); 231 overridePromise = expectCommandUpdate(isMac ? 1 : 0); 232 gURLBar.select(); 233 await overridePromise; 234 235 // Check that we get an update if we select content while the panel is open. 236 await deselectURLBarAndSpin(); 237 overridePromise = expectCommandUpdate(1); 238 await navbar.overflowable.show(); 239 gURLBar.select(); 240 await overridePromise; 241 242 // And that we don't (except on mac) when the panel is hidden. 243 kOverflowPanel.hidePopup(); 244 await deselectURLBarAndSpin(); 245 overridePromise = expectCommandUpdate(isMac ? 1 : 0); 246 gURLBar.select(); 247 await overridePromise; 248 }); 249 250 // Test updating when the edit-controls are moved to the palette. 251 add_task(async function test_panelui_customize_to_palette() { 252 await startCustomizing(); 253 let palette = document.getElementById("customization-palette"); 254 simulateItemDrag(document.getElementById("edit-controls"), palette); 255 await endCustomizing(); 256 257 // updateEditUIVisibility should be called when customization ends but isn't. See bug 1359790. 258 updateEditUIVisibility(); 259 260 let overridePromise = expectCommandUpdate(isMac ? 1 : 0); 261 gURLBar.focus(); 262 gURLBar.value = "other"; 263 gURLBar.select(); 264 await overridePromise; 265 266 // If the UI isn't found, the command is set to be enabled. 267 checkState( 268 true, 269 "Update when edit-controls is on palette, hidden and selection changed" 270 ); 271 }); 272 273 add_task(async function finish() { 274 await resetCustomization(); 275 }); 276 277 // Test updating in the initial state when the edit-controls are on the panel but 278 // have not yet been created. This needs to be done in a new window to ensure that 279 // other tests haven't opened the panel. 280 add_task(async function test_initial_state() { 281 let testWindow = await BrowserTestUtils.openNewBrowserWindow(); 282 await SimpleTest.promiseFocus(testWindow); 283 284 // For focusing the URL bar to have an effect, we need to ensure the URL bar isn't 285 // initially focused: 286 testWindow.gBrowser.selectedTab.focus(); 287 await TestUtils.waitForCondition(() => !testWindow.gURLBar.focused); 288 289 let overridePromise = expectCommandUpdate(isMac, testWindow); 290 291 testWindow.gURLBar.focus(); 292 testWindow.gURLBar.value = "test"; 293 294 await overridePromise; 295 296 // Commands won't update when no edit UI is present. They default to being 297 // enabled so that keyboard shortcuts will work. The real enabled state will 298 // be checked when shortcut is pressed. 299 checkState( 300 !isMac, 301 "No update when edit-controls is on panel and not visible", 302 testWindow 303 ); 304 305 await BrowserTestUtils.closeWindow(testWindow); 306 await SimpleTest.promiseFocus(window); 307 });