tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 });