tor-browser

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

browser_search_within_preferences_2.js (8171B)


      1 "use strict";
      2 /**
      3 * This file contains tests for the Preferences search bar.
      4 */
      5 
      6 /**
      7 * Test that we only search the selected child of a XUL deck.
      8 * When we search "Remove Account",
      9 * it should not show the "Remove Account" button if the Firefox account is not logged in yet.
     10 */
     11 add_task(async function () {
     12  await openPreferencesViaOpenPreferencesAPI("paneSync", { leaveOpen: true });
     13 
     14  let weavePrefsDeck =
     15    gBrowser.contentDocument.getElementById("weavePrefsDeck");
     16  is(
     17    weavePrefsDeck.selectedIndex,
     18    0,
     19    "Should select the #noFxaAccount child node"
     20  );
     21 
     22  // Performs search.
     23  let searchInput = gBrowser.contentDocument.getElementById("searchInput");
     24 
     25  is(
     26    searchInput,
     27    gBrowser.contentDocument.activeElement.closest("#searchInput"),
     28    "Search input should be focused when visiting preferences"
     29  );
     30 
     31  let query = "Sync";
     32  let searchCompletedPromise = BrowserTestUtils.waitForEvent(
     33    gBrowser.contentWindow,
     34    "PreferencesSearchCompleted",
     35    evt => evt.detail == query
     36  );
     37  EventUtils.sendString(query);
     38  await searchCompletedPromise;
     39 
     40  let mainPrefTag = gBrowser.contentDocument.getElementById("mainPrefPane");
     41  for (let i = 0; i < mainPrefTag.childElementCount; i++) {
     42    let child = mainPrefTag.children[i];
     43    if (child.id == "header-searchResults" || child.id == "weavePrefsDeck") {
     44      is_element_visible(child, "Should be in search results");
     45    } else if (child.id) {
     46      is_element_hidden(child, "Should not be in search results");
     47    }
     48  }
     49 
     50  // Ensure the "Remove Account" button exists in the hidden child of the <xul:deck>.
     51  let unlinkFxaAccount = weavePrefsDeck.children[1].querySelector(
     52    "#unverifiedUnlinkFxaAccount"
     53  );
     54  is(
     55    unlinkFxaAccount.label,
     56    "Remove Account",
     57    "The Remove Account button should exist"
     58  );
     59 
     60  // Performs search.
     61  searchInput.focus();
     62  query = "Remove Account";
     63  searchCompletedPromise = BrowserTestUtils.waitForEvent(
     64    gBrowser.contentWindow,
     65    "PreferencesSearchCompleted",
     66    evt => evt.detail == query
     67  );
     68  EventUtils.sendString(query);
     69  await searchCompletedPromise;
     70 
     71  let noResultsEl = gBrowser.contentDocument.querySelector(
     72    "#no-results-message"
     73  );
     74  is_element_visible(noResultsEl, "Should be reporting no results");
     75 
     76  BrowserTestUtils.removeTab(gBrowser.selectedTab);
     77 });
     78 
     79 /**
     80 * Test that we search using `search-l10n-ids`.
     81 *
     82 * The test uses element `showUpdateHistory` and
     83 * l10n id `language-and-appearance-header` and expects the element
     84 * to be matched on the first word from the l10n id value ("Language" in en-US).
     85 */
     86 add_task(async function () {
     87  let l10nId = "language-and-appearance-header";
     88 
     89  await openPreferencesViaOpenPreferencesAPI("paneGeneral", {
     90    leaveOpen: true,
     91  });
     92 
     93  // First, lets make sure that the element is not matched without
     94  // `search-l10n-ids`.
     95  {
     96    let searchInput = gBrowser.contentDocument.getElementById("searchInput");
     97    let suhElem = gBrowser.contentDocument.getElementById("showUpdateHistory");
     98 
     99    is(
    100      searchInput,
    101      gBrowser.contentDocument.activeElement.closest("#searchInput"),
    102      "Search input should be focused when visiting preferences"
    103    );
    104 
    105    ok(
    106      !suhElem.getAttribute("search-l10n-ids").includes(l10nId),
    107      "showUpdateHistory element should not contain the l10n id here."
    108    );
    109 
    110    let query = "Language";
    111    let searchCompletedPromise = BrowserTestUtils.waitForEvent(
    112      gBrowser.contentWindow,
    113      "PreferencesSearchCompleted",
    114      evt => evt.detail == query
    115    );
    116    EventUtils.sendString(query);
    117    await searchCompletedPromise;
    118 
    119    is_element_hidden(
    120      suhElem,
    121      "showUpdateHistory should not be in search results"
    122    );
    123  }
    124 
    125  await BrowserTestUtils.removeTab(gBrowser.selectedTab);
    126 
    127  // Now, let's add the l10n id to the element and perform the same search again.
    128 
    129  await openPreferencesViaOpenPreferencesAPI("paneGeneral", {
    130    leaveOpen: true,
    131  });
    132 
    133  {
    134    let searchInput = gBrowser.contentDocument.getElementById("searchInput");
    135 
    136    is(
    137      searchInput,
    138      gBrowser.contentDocument.activeElement.closest("#searchInput"),
    139      "Search input should be focused when visiting preferences"
    140    );
    141 
    142    let suhElem = gBrowser.contentDocument.getElementById("showUpdateHistory");
    143    suhElem.setAttribute("search-l10n-ids", l10nId);
    144 
    145    let query = "Language";
    146    let searchCompletedPromise = BrowserTestUtils.waitForEvent(
    147      gBrowser.contentWindow,
    148      "PreferencesSearchCompleted",
    149      evt => evt.detail == query
    150    );
    151    EventUtils.sendString(query);
    152    await searchCompletedPromise;
    153 
    154    if (
    155      AppConstants.platform === "win" &&
    156      Services.sysinfo.getProperty("hasWinPackageId")
    157    ) {
    158      is_element_hidden(
    159        suhElem,
    160        "showUpdateHistory should not be in search results"
    161      );
    162    } else {
    163      is_element_visible(
    164        suhElem,
    165        "showUpdateHistory should be in search results"
    166      );
    167    }
    168  }
    169 
    170  await BrowserTestUtils.removeTab(gBrowser.selectedTab);
    171 });
    172 
    173 /**
    174 * Test that search works as expected for custom elements that utilize both
    175 * slots and shadow DOM. We should be able to find text the shadow DOM.
    176 */
    177 add_task(async function testSearchShadowDOM() {
    178  await openPreferencesViaOpenPreferencesAPI("paneGeneral", {
    179    leaveOpen: true,
    180  });
    181 
    182  // Create the toggle.
    183  let { mozElements, SHADOW_DOM_TEXT } = createMozCustomElements(gBrowser);
    184 
    185  mozElements.forEach(el => {
    186    ok(
    187      !BrowserTestUtils.isVisible(el),
    188      `${el.localName} is not visible prior to search.`
    189    );
    190  });
    191 
    192  // Perform search with text found in moz-toggle's shadow DOM.
    193  let query = SHADOW_DOM_TEXT;
    194  let searchCompletedPromise = BrowserTestUtils.waitForEvent(
    195    gBrowser.contentWindow,
    196    "PreferencesSearchCompleted",
    197    evt => evt.detail == query
    198  );
    199  EventUtils.sendString(query);
    200  await searchCompletedPromise;
    201  mozElements.forEach(el => {
    202    ok(
    203      BrowserTestUtils.isVisible(el),
    204      `${el.localName} is visible after searching for string in the shadow DOM.`
    205    );
    206  });
    207 
    208  BrowserTestUtils.removeTab(gBrowser.selectedTab);
    209 });
    210 
    211 /**
    212 * Test that search works as expected for custom elements that utilize both
    213 * slots and shadow DOM. We should be able to find text the light DOM.
    214 */
    215 add_task(async function testSearchLightDOM() {
    216  await openPreferencesViaOpenPreferencesAPI("paneGeneral", {
    217    leaveOpen: true,
    218  });
    219 
    220  // Create the toggle.
    221  let { mozElements, LIGHT_DOM_TEXT } = createMozCustomElements(gBrowser, [
    222    "moz-toggle",
    223  ]);
    224  let toggle = mozElements[0];
    225 
    226  // Perform search with text found in moz-toggle's slotted content.
    227  let query = LIGHT_DOM_TEXT;
    228  let searchCompletedPromise = BrowserTestUtils.waitForEvent(
    229    gBrowser.contentWindow,
    230    "PreferencesSearchCompleted",
    231    evt => evt.detail == query
    232  );
    233  EventUtils.sendString(query);
    234  await searchCompletedPromise;
    235  ok(
    236    BrowserTestUtils.isVisible(toggle),
    237    "Toggle is visible again after searching for text found in slotted content."
    238  );
    239 
    240  BrowserTestUtils.removeTab(gBrowser.selectedTab);
    241 });
    242 
    243 const MOZ_CUSTOM_ELEMENTS = [
    244  "moz-toggle",
    245  "moz-radio-group",
    246  "moz-radio",
    247  "moz-checkbox",
    248 ];
    249 
    250 // Create multiple moz- custom elements with the same label.
    251 function createMozCustomElements(gBrowser, elements = MOZ_CUSTOM_ELEMENTS) {
    252  const SHADOW_DOM_TEXT = "This text lives in the shadow DOM";
    253  const LIGHT_DOM_TEXT = "This text lives in the light DOM";
    254 
    255  let doc = gBrowser.contentDocument;
    256  let mozElements = elements.map(tag => {
    257    let el = doc.createElement(tag);
    258    el.label = SHADOW_DOM_TEXT;
    259    return el;
    260  });
    261  let [toggle, radioGroup, radioButton, ...rest] = mozElements;
    262  let protectionsGroup = doc.getElementById("trackingGroup");
    263 
    264  if (toggle) {
    265    let link = doc.createElement("a");
    266    link.href = "https://mozilla.org/";
    267    link.textContent = LIGHT_DOM_TEXT;
    268    toggle.append(link);
    269    link.slot = "support-link";
    270    protectionsGroup.append(toggle);
    271  }
    272 
    273  if (radioGroup && radioButton) {
    274    radioGroup.appendChild(radioButton);
    275    protectionsGroup.append(radioGroup);
    276  }
    277 
    278  protectionsGroup.append(...rest);
    279 
    280  return { SHADOW_DOM_TEXT, LIGHT_DOM_TEXT, mozElements };
    281 }