tor-browser

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

browser_appendSpanCount.js (6372B)


      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 // This test makes sure that when the view updates itself and appends new rows,
      6 // the new rows start out hidden when they exceed the current visible result
      7 // span count.  It includes a tip result so that it tests a row with > 1 result
      8 // span.
      9 
     10 "use strict";
     11 
     12 add_setup(async function () {
     13  await SpecialPowers.pushPrefEnv({
     14    set: [["browser.urlbar.scotchBonnet.enableOverride", false]],
     15  });
     16 });
     17 
     18 add_task(async function viewUpdateAppendHidden() {
     19  // We'll use this test provider to test specific results.  We assume that
     20  // history and bookmarks have been cleared (by init() above).
     21  let provider = new DelayingTestProvider();
     22  UrlbarProvidersManager.registerProvider(provider);
     23  registerCleanupFunction(() => {
     24    UrlbarProvidersManager.unregisterProvider(provider);
     25  });
     26 
     27  // We do two searches below without closing the panel.  Use "firefox cach" as
     28  // the first query and "firefox cache" as the second so that (1) an
     29  // intervention tip is triggered both times but also so that (2) the queries
     30  // are different each time.
     31  let baseQuery = "firefox cache";
     32  let queries = [baseQuery.substring(0, baseQuery.length - 1), baseQuery];
     33  let maxResults = UrlbarPrefs.get("maxRichResults");
     34 
     35  let queryStrings = [];
     36  for (let i = 0; i < maxResults; i++) {
     37    queryStrings.push(`${baseQuery} ${i}`);
     38  }
     39 
     40  // First search: Trigger the intervention tip and a view full of search
     41  // suggestions.
     42  provider.results = queryStrings.map(
     43    suggestion =>
     44      new UrlbarResult({
     45        type: UrlbarUtils.RESULT_TYPE.SEARCH,
     46        source: UrlbarUtils.RESULT_SOURCE.SEARCH,
     47        payload: {
     48          query: queries[0],
     49          suggestion,
     50          lowerCaseSuggestion: suggestion.toLocaleLowerCase(),
     51          engine: Services.search.defaultEngine.name,
     52        },
     53      })
     54  );
     55  provider.finishQueryPromise = Promise.resolve();
     56  await UrlbarTestUtils.promiseAutocompleteResultPopup({
     57    window,
     58    value: queries[0],
     59  });
     60 
     61  // Sanity check the tip result and row count.
     62  let tipResult = await UrlbarTestUtils.getDetailsOfResultAt(window, 1);
     63  Assert.equal(
     64    tipResult.type,
     65    UrlbarUtils.RESULT_TYPE.TIP,
     66    "Result at index 1 is a tip"
     67  );
     68  let tipResultSpan = UrlbarUtils.getSpanForResult(
     69    tipResult.element.row.result
     70  );
     71  Assert.greater(tipResultSpan, 1, "Sanity check: Tip has large result span");
     72  let expectedRowCount = maxResults - tipResultSpan + 1;
     73  Assert.equal(
     74    UrlbarTestUtils.getResultCount(window),
     75    expectedRowCount,
     76    "Sanity check: Initial row count takes tip result span into account"
     77  );
     78 
     79  // Second search: Change the provider's results so that it has enough history
     80  // to fill up the view.  Search suggestion rows cannot be updated to history
     81  // results, so the view will append the history results as new rows.
     82  provider.results = queryStrings.map(title => {
     83    let url = "http://example.com/" + title;
     84    return new UrlbarResult({
     85      type: UrlbarUtils.RESULT_TYPE.URL,
     86      source: UrlbarUtils.RESULT_SOURCE.HISTORY,
     87      payload: {
     88        title,
     89        url,
     90      },
     91    });
     92  });
     93 
     94  // Don't allow the search to finish until we check the updated rows.  We'll
     95  // accomplish that by adding a mutation observer on the rows and delaying
     96  // resolving the provider's finishQueryPromise.  When all new rows have been
     97  // added, we expect the new row count to be:
     98  //
     99  //     expectedRowCount       // the original row count
    100  //   + (expectedRowCount - 2) // the newly added history row count (hidden)
    101  //   --------------------------
    102  //   (2 * expectedRowCount) - 2
    103  //
    104  // The `- 2` subtracts the heuristic and tip result.
    105  let newExpectedRowCount = 2 * expectedRowCount - 2;
    106  let mutationPromise = new Promise(resolve => {
    107    let observer = new MutationObserver(() => {
    108      let childCount = UrlbarTestUtils.getResultCount(window);
    109      info(`Rows mutation observer called, childCount now ${childCount}`);
    110      if (newExpectedRowCount <= childCount) {
    111        observer.disconnect();
    112        resolve();
    113      }
    114    });
    115    observer.observe(UrlbarTestUtils.getResultsContainer(window), {
    116      childList: true,
    117    });
    118  });
    119 
    120  // Now do the second search but don't wait for it to finish.
    121  let resolveQuery;
    122  provider.finishQueryPromise = new Promise(
    123    resolve => (resolveQuery = resolve)
    124  );
    125  let queryPromise = UrlbarTestUtils.promiseAutocompleteResultPopup({
    126    window,
    127    value: queries[1],
    128  });
    129 
    130  // Wait for the history rows to be added.
    131  await mutationPromise;
    132 
    133  // Check the rows.  We can't use UrlbarTestUtils.getDetailsOfResultAt() here
    134  // because it waits for the query to finish.
    135  Assert.equal(
    136    UrlbarTestUtils.getResultCount(window),
    137    newExpectedRowCount,
    138    "New expected row count"
    139  );
    140  // stale search rows
    141  let rows = UrlbarTestUtils.getResultsContainer(window).children;
    142  for (let i = 2; i < expectedRowCount; i++) {
    143    let row = rows[i];
    144    Assert.equal(
    145      row.result.type,
    146      UrlbarUtils.RESULT_TYPE.SEARCH,
    147      `Result at index ${i} is a search result`
    148    );
    149    Assert.ok(
    150      BrowserTestUtils.isVisible(row),
    151      `Search result at index ${i} is visible`
    152    );
    153    Assert.equal(
    154      row.getAttribute("stale"),
    155      "true",
    156      `Search result at index ${i} is stale`
    157    );
    158  }
    159  // new hidden history rows
    160  for (let i = expectedRowCount; i < newExpectedRowCount; i++) {
    161    let row = rows[i];
    162    Assert.equal(
    163      row.result.type,
    164      UrlbarUtils.RESULT_TYPE.URL,
    165      `Result at index ${i} is a URL result`
    166    );
    167    Assert.ok(
    168      !BrowserTestUtils.isVisible(row),
    169      `URL result at index ${i} is hidden`
    170    );
    171    Assert.ok(
    172      !row.hasAttribute("stale"),
    173      `URL result at index ${i} is not stale`
    174    );
    175  }
    176 
    177  // Finish the query, and we're done.
    178  resolveQuery();
    179  await queryPromise;
    180 
    181  await UrlbarTestUtils.promisePopupClose(window);
    182  gURLBar.handleRevert();
    183 
    184  // We unregister the provider above in a cleanup function so we don't
    185  // accidentally interfere with later tests, but do it here too in case we add
    186  // more tasks to this test.  It's harmless to call more than once.
    187  UrlbarProvidersManager.unregisterProvider(provider);
    188 });