tor-browser

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

browser_914138_widget_API_overflowable_toolbar.js (13906B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 "use strict";
      6 
      7 var navbar = document.getElementById(CustomizableUI.AREA_NAVBAR);
      8 var overflowList = document.getElementById(
      9  navbar.getAttribute("default-overflowtarget")
     10 );
     11 
     12 const kTestBtn1 = "test-addWidgetToArea-overflow";
     13 const kTestBtn2 = "test-removeWidgetFromArea-overflow";
     14 const kTestBtn3 = "test-createWidget-overflow";
     15 const kTestBtn4 = "test-createWidget-overflow-first-item";
     16 const kTestBtn5 = "test-addWidgetToArea-overflow-first-item";
     17 const kSidebarBtn = "sidebar-button";
     18 const kLibraryButton = "library-button";
     19 const kDownloadsBtn = "downloads-button";
     20 const kSearchBox = "search-container";
     21 
     22 var originalWindowWidth;
     23 
     24 // Adding a widget should add it next to the widget it's being inserted next to.
     25 add_task(async function subsequent_widget() {
     26  let sidebarRevampEnabled = Services.prefs.getBoolPref(
     27    "sidebar.revamp",
     28    false
     29  );
     30  createDummyXULButton(kTestBtn1, "Test");
     31  if (sidebarRevampEnabled) {
     32    createDummyXULButton(kTestBtn2, "Test2");
     33  }
     34  ok(
     35    !navbar.hasAttribute("overflowing"),
     36    "Should start subsequent_widget with a non-overflowing toolbar."
     37  );
     38  ok(
     39    CustomizableUI.inDefaultState,
     40    "Should start subsequent_widget in default state."
     41  );
     42  CustomizableUI.addWidgetToArea(
     43    !sidebarRevampEnabled ? kSidebarBtn : kTestBtn2,
     44    "nav-bar"
     45  );
     46  await waitForElementShown(
     47    document.getElementById(!sidebarRevampEnabled ? kSidebarBtn : kTestBtn2)
     48  );
     49 
     50  originalWindowWidth = ensureToolbarOverflow(window, false);
     51  await TestUtils.waitForCondition(() => {
     52    return (
     53      navbar.hasAttribute("overflowing") &&
     54      document
     55        .getElementById(!sidebarRevampEnabled ? kSidebarBtn : kTestBtn2)
     56        .getAttribute("overflowedItem") == "true"
     57    );
     58  });
     59  ok(navbar.hasAttribute("overflowing"), "Should have an overflowing toolbar.");
     60  ok(
     61    !navbar.querySelector(
     62      `#${!sidebarRevampEnabled ? kSidebarBtn : kTestBtn2}`
     63    ),
     64    `${
     65      !sidebarRevampEnabled ? "Sidebar" : "Test 2"
     66    } button should no longer be in the navbar`
     67  );
     68 
     69  let overflowBtnNode = overflowList.querySelector(
     70    `#${!sidebarRevampEnabled ? kSidebarBtn : kTestBtn2}`
     71  );
     72  ok(
     73    overflowBtnNode,
     74    `${
     75      !sidebarRevampEnabled ? "Sidebar" : "Test 2"
     76    } button should be overflowing`
     77  );
     78  ok(
     79    overflowBtnNode && overflowBtnNode.getAttribute("overflowedItem") == "true",
     80    `${
     81      !sidebarRevampEnabled ? "Sidebar" : "Test 2"
     82    } button should have overflowedItem attribute`
     83  );
     84 
     85  let placementOfOverflowButton = CustomizableUI.getWidgetIdsInArea(
     86    navbar.id
     87  ).indexOf(!sidebarRevampEnabled ? kSidebarBtn : kTestBtn2);
     88  CustomizableUI.addWidgetToArea(
     89    kTestBtn1,
     90    navbar.id,
     91    placementOfOverflowButton
     92  );
     93  ok(
     94    !navbar.querySelector("#" + kTestBtn1),
     95    "New button should not be in the navbar"
     96  );
     97  let newButtonNode = overflowList.querySelector("#" + kTestBtn1);
     98  ok(newButtonNode, "New button should be overflowing");
     99  ok(
    100    newButtonNode && newButtonNode.getAttribute("overflowedItem") == "true",
    101    "New button should have overflowedItem attribute"
    102  );
    103  let nextEl = newButtonNode && newButtonNode.nextElementSibling;
    104  is(
    105    nextEl && nextEl.id,
    106    !sidebarRevampEnabled ? kSidebarBtn : kTestBtn2,
    107    `Test button should be next to ${
    108      !sidebarRevampEnabled ? "sidebar" : "test 2"
    109    } button.`
    110  );
    111 
    112  unensureToolbarOverflow(window, originalWindowWidth);
    113  await TestUtils.waitForCondition(() => !navbar.hasAttribute("overflowing"));
    114  ok(
    115    !navbar.hasAttribute("overflowing"),
    116    "Should not have an overflowing toolbar."
    117  );
    118  ok(
    119    navbar.querySelector(`#${!sidebarRevampEnabled ? kSidebarBtn : kTestBtn2}`),
    120    `${
    121      !sidebarRevampEnabled ? "Sidebar" : "Test 2"
    122    } button should be in the navbar`
    123  );
    124  ok(
    125    overflowBtnNode && overflowBtnNode.getAttribute("overflowedItem") != "true",
    126    `${
    127      !sidebarRevampEnabled ? "Sidebar" : "Test 2"
    128    } button should no longer have overflowedItem attribute`
    129  );
    130  ok(
    131    !overflowList.querySelector(
    132      `#${!sidebarRevampEnabled ? kSidebarBtn : kTestBtn2}`
    133    ),
    134    `${
    135      !sidebarRevampEnabled ? "Sidebar" : "Test 2"
    136    } button should no longer be overflowing`
    137  );
    138  ok(
    139    navbar.querySelector("#" + kTestBtn1),
    140    "Test button should be in the navbar"
    141  );
    142  ok(
    143    !overflowList.querySelector("#" + kTestBtn1),
    144    "Test button should no longer be overflowing"
    145  );
    146  ok(
    147    newButtonNode && newButtonNode.getAttribute("overflowedItem") != "true",
    148    "New button should no longer have overflowedItem attribute"
    149  );
    150  let el = document.getElementById(kTestBtn1);
    151  if (el) {
    152    CustomizableUI.removeWidgetFromArea(kTestBtn1);
    153    el.remove();
    154  }
    155  CustomizableUI.removeWidgetFromArea(
    156    !sidebarRevampEnabled ? kSidebarBtn : kTestBtn2
    157  );
    158  unensureToolbarOverflow(window, originalWindowWidth);
    159  await TestUtils.waitForCondition(() => !navbar.hasAttribute("overflowing"));
    160 });
    161 
    162 // Removing a widget should remove it from the overflow list if that is where it is, and update it accordingly.
    163 add_task(async function remove_widget() {
    164  createDummyXULButton(kTestBtn2, "Test");
    165  ok(
    166    !navbar.hasAttribute("overflowing"),
    167    "Should start remove_widget with a non-overflowing toolbar."
    168  );
    169  ok(
    170    CustomizableUI.inDefaultState,
    171    "Should start remove_widget in default state."
    172  );
    173  CustomizableUI.addWidgetToArea(kTestBtn2, navbar.id);
    174  ok(
    175    !navbar.hasAttribute("overflowing"),
    176    "Should still have a non-overflowing toolbar."
    177  );
    178 
    179  originalWindowWidth = ensureToolbarOverflow(window, false);
    180  await TestUtils.waitForCondition(() => navbar.hasAttribute("overflowing"));
    181  ok(navbar.hasAttribute("overflowing"), "Should have an overflowing toolbar.");
    182  ok(
    183    !navbar.querySelector("#" + kTestBtn2),
    184    "Test button should not be in the navbar"
    185  );
    186  ok(
    187    overflowList.querySelector("#" + kTestBtn2),
    188    "Test button should be overflowing"
    189  );
    190 
    191  CustomizableUI.removeWidgetFromArea(kTestBtn2);
    192 
    193  ok(
    194    !overflowList.querySelector("#" + kTestBtn2),
    195    "Test button should not be overflowing."
    196  );
    197  ok(
    198    !navbar.querySelector("#" + kTestBtn2),
    199    "Test button should not be in the navbar"
    200  );
    201  ok(
    202    gNavToolbox.palette.querySelector("#" + kTestBtn2),
    203    "Test button should be in the palette"
    204  );
    205 
    206  unensureToolbarOverflow(window, originalWindowWidth);
    207  await TestUtils.waitForCondition(() => !navbar.hasAttribute("overflowing"));
    208  ok(
    209    !navbar.hasAttribute("overflowing"),
    210    "Should not have an overflowing toolbar."
    211  );
    212  let el = document.getElementById(kTestBtn2);
    213  if (el) {
    214    CustomizableUI.removeWidgetFromArea(kTestBtn2);
    215    el.remove();
    216  }
    217  unensureToolbarOverflow(window, originalWindowWidth);
    218  await TestUtils.waitForCondition(() => !navbar.hasAttribute("overflowing"));
    219 });
    220 
    221 // Constructing a widget while overflown should set the right class on it.
    222 add_task(async function construct_widget() {
    223  let sidebarRevampEnabled = Services.prefs.getBoolPref(
    224    "sidebar.revamp",
    225    false
    226  );
    227  ok(
    228    !navbar.hasAttribute("overflowing"),
    229    "Should start construct_widget with a non-overflowing toolbar."
    230  );
    231  ok(
    232    CustomizableUI.inDefaultState,
    233    "Should start construct_widget in default state."
    234  );
    235 
    236  CustomizableUI.addWidgetToArea(
    237    !sidebarRevampEnabled ? kSidebarBtn : kTestBtn2,
    238    "nav-bar"
    239  );
    240  await waitForElementShown(
    241    document.getElementById(!sidebarRevampEnabled ? kSidebarBtn : kTestBtn2)
    242  );
    243 
    244  originalWindowWidth = ensureToolbarOverflow(window, false);
    245  await TestUtils.waitForCondition(() => {
    246    return (
    247      navbar.hasAttribute("overflowing") &&
    248      document
    249        .getElementById(!sidebarRevampEnabled ? kSidebarBtn : kTestBtn2)
    250        .getAttribute("overflowedItem") == "true"
    251    );
    252  });
    253  ok(navbar.hasAttribute("overflowing"), "Should have an overflowing toolbar.");
    254  ok(
    255    !navbar.querySelector(
    256      `#${!sidebarRevampEnabled ? kSidebarBtn : kTestBtn2}`
    257    ),
    258    `${
    259      !sidebarRevampEnabled ? "Sidebar" : "Test 2"
    260    } button should no longer be in the navbar`
    261  );
    262  let overflowBtnNode = overflowList.querySelector(
    263    `#${!sidebarRevampEnabled ? kSidebarBtn : kTestBtn2}`
    264  );
    265  ok(
    266    overflowBtnNode,
    267    `${
    268      !sidebarRevampEnabled ? "Sidebar" : "Test 2"
    269    } button should be overflowing`
    270  );
    271  ok(
    272    overflowBtnNode && overflowBtnNode.getAttribute("overflowedItem") == "true",
    273    `${
    274      !sidebarRevampEnabled ? "Sidebar" : "Test 2"
    275    } button should have overflowedItem class`
    276  );
    277 
    278  let testBtnSpec = {
    279    id: kTestBtn3,
    280    label: "Overflowable widget test",
    281    defaultArea: "nav-bar",
    282  };
    283  CustomizableUI.createWidget(testBtnSpec);
    284  let testNode = overflowList.querySelector("#" + kTestBtn3);
    285  ok(testNode, "Test button should be overflowing");
    286  ok(
    287    testNode && testNode.getAttribute("overflowedItem") == "true",
    288    "Test button should have overflowedItem class"
    289  );
    290 
    291  CustomizableUI.destroyWidget(kTestBtn3);
    292  testNode = document.getElementById(kTestBtn3);
    293  ok(!testNode, "Test button should be gone");
    294 
    295  CustomizableUI.createWidget(testBtnSpec);
    296  testNode = overflowList.querySelector("#" + kTestBtn3);
    297  ok(testNode, "Test button should be overflowing");
    298  ok(
    299    testNode && testNode.getAttribute("overflowedItem") == "true",
    300    "Test button should have overflowedItem class"
    301  );
    302 
    303  CustomizableUI.removeWidgetFromArea(kTestBtn3);
    304  testNode = document.getElementById(kTestBtn3);
    305  ok(!testNode, "Test button should be gone");
    306  CustomizableUI.destroyWidget(kTestBtn3);
    307  CustomizableUI.removeWidgetFromArea(
    308    !sidebarRevampEnabled ? kSidebarBtn : kTestBtn2
    309  );
    310  unensureToolbarOverflow(window, originalWindowWidth);
    311  await TestUtils.waitForCondition(() => !navbar.hasAttribute("overflowing"));
    312 });
    313 
    314 add_task(async function insertBeforeFirstItemInOverflow() {
    315  originalWindowWidth = window.outerWidth;
    316  ok(
    317    !navbar.hasAttribute("overflowing"),
    318    "Should start insertBeforeFirstItemInOverflow with a non-overflowing toolbar."
    319  );
    320  ok(
    321    CustomizableUI.inDefaultState,
    322    "Should start insertBeforeFirstItemInOverflow in default state."
    323  );
    324 
    325  // Remove sidebar button if present
    326  CustomizableUI.removeWidgetFromArea("sidebar-button");
    327 
    328  CustomizableUI.addWidgetToArea(
    329    "fullscreen-button",
    330    "nav-bar",
    331    CustomizableUI.getWidgetIdsInArea("nav-bar").indexOf(
    332      "fxa-toolbar-menu-button"
    333    )
    334  );
    335  let fullscreenButton = document.getElementById("fullscreen-button");
    336  await waitForElementShown(fullscreenButton);
    337 
    338  CustomizableUI.addWidgetToArea(
    339    kLibraryButton,
    340    "nav-bar",
    341    CustomizableUI.getWidgetIdsInArea("nav-bar").indexOf("fullscreen-button")
    342  );
    343  let libraryButton = document.getElementById(kLibraryButton);
    344  await waitForElementShown(libraryButton);
    345  // Ensure nothing flexes to make the resize predictable:
    346  navbar
    347    .querySelectorAll("toolbarspring")
    348    .forEach(s => CustomizableUI.removeWidgetFromArea(s.id));
    349  let urlbar = document.getElementById("urlbar-container");
    350  urlbar.style.minWidth = urlbar.getBoundingClientRect().width + "px";
    351  // Negative number to make the window smaller by the difference between the left side of
    352  // the item next to the library button and left side of the hamburger one.
    353  // The width of the overflow button that needs to appear will then be enough to
    354  // also hide the library button.
    355  let resizeWidthToMakeLibraryLast =
    356    libraryButton.nextElementSibling.getBoundingClientRect().left -
    357    PanelUI.menuButton.parentNode.getBoundingClientRect().left +
    358    10; // Leave some margin for the margins between buttons etc.;
    359  info(
    360    "Resizing to " +
    361      resizeWidthToMakeLibraryLast +
    362      " , waiting for library to overflow."
    363  );
    364  window.resizeBy(resizeWidthToMakeLibraryLast, 0);
    365  await TestUtils.waitForCondition(() => {
    366    return (
    367      libraryButton.getAttribute("overflowedItem") == "true" &&
    368      !libraryButton.previousElementSibling
    369    );
    370  }, "Library button is overflowed");
    371 
    372  let testBtnSpec = { id: kTestBtn4, label: "Overflowable widget test" };
    373  let placementOfLibraryButton = CustomizableUI.getWidgetIdsInArea(
    374    navbar.id
    375  ).indexOf(kLibraryButton);
    376  CustomizableUI.createWidget(testBtnSpec);
    377  CustomizableUI.addWidgetToArea(
    378    kTestBtn4,
    379    "nav-bar",
    380    placementOfLibraryButton
    381  );
    382  let testNode = overflowList.querySelector("#" + kTestBtn4);
    383  ok(testNode, "Test button should be overflowing");
    384  ok(
    385    testNode && testNode.getAttribute("overflowedItem") == "true",
    386    "Test button should have overflowedItem class"
    387  );
    388  CustomizableUI.destroyWidget(kTestBtn4);
    389  testNode = document.getElementById(kTestBtn4);
    390  ok(!testNode, "Test button should be gone");
    391 
    392  createDummyXULButton(kTestBtn5, "Test");
    393  CustomizableUI.addWidgetToArea(
    394    kTestBtn5,
    395    "nav-bar",
    396    placementOfLibraryButton
    397  );
    398  testNode = overflowList.querySelector("#" + kTestBtn5);
    399  ok(testNode, "Test button should be overflowing");
    400  ok(
    401    testNode && testNode.getAttribute("overflowedItem") == "true",
    402    "Test button should have overflowedItem class"
    403  );
    404  CustomizableUI.removeWidgetFromArea(kTestBtn5);
    405  testNode && testNode.remove();
    406 
    407  urlbar.style.removeProperty("min-width");
    408  CustomizableUI.removeWidgetFromArea(kLibraryButton);
    409  unensureToolbarOverflow(window, originalWindowWidth);
    410  await TestUtils.waitForCondition(() => !navbar.hasAttribute("overflowing"));
    411  await resetCustomization();
    412 });
    413 
    414 registerCleanupFunction(async function asyncCleanup() {
    415  document.getElementById("urlbar-container").style.removeProperty("min-width");
    416  window.resizeTo(originalWindowWidth, window.outerHeight);
    417  await TestUtils.waitForCondition(() => !navbar.hasAttribute("overflowing"));
    418  await resetCustomization();
    419 });