tor-browser

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

test_search_suggestions_tail.js (10960B)


      1 /* Any copyright is dedicated to the Public Domain.
      2   http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 /**
      5 * Tests that tailed search engine suggestions are returned by
      6 * UrlbarProviderSearchSuggestions when available.
      7 */
      8 
      9 const SUGGEST_ENABLED_PREF = "browser.search.suggest.enabled";
     10 const PRIVATE_SEARCH_PREF = "browser.search.separatePrivateDefault.ui.enabled";
     11 const TAIL_SUGGESTIONS_PREF = "browser.urlbar.richSuggestions.tail";
     12 
     13 var suggestionsFn;
     14 var previousSuggestionsFn;
     15 
     16 /**
     17 * Set the current suggestion funciton.
     18 *
     19 * @param {Function} fn
     20 *   A function that that a search string and returns an array of strings that
     21 *   will be used as search suggestions.
     22 *   Note: `fn` should return > 1 suggestion in most cases. Otherwise, you may
     23 *         encounter unexceptede behaviour with UrlbarProviderSuggestion's
     24 *         _lastLowResultsSearchSuggestion safeguard.
     25 */
     26 function setSuggestionsFn(fn) {
     27  previousSuggestionsFn = suggestionsFn;
     28  suggestionsFn = fn;
     29 }
     30 
     31 async function cleanup() {
     32  await PlacesUtils.bookmarks.eraseEverything();
     33  await PlacesUtils.history.clear();
     34 }
     35 
     36 async function cleanUpSuggestions() {
     37  await cleanup();
     38  if (previousSuggestionsFn) {
     39    suggestionsFn = previousSuggestionsFn;
     40    previousSuggestionsFn = null;
     41  }
     42 }
     43 
     44 add_setup(async function () {
     45  let engine = await addTestTailSuggestionsEngine(searchStr => {
     46    return suggestionsFn(searchStr);
     47  });
     48  setSuggestionsFn(searchStr => {
     49    let suffixes = ["toronto", "tunisia"];
     50    return [
     51      "what time is it in t",
     52      suffixes.map(s => searchStr + s.slice(1)),
     53      [],
     54      {
     55        "google:irrelevantparameter": [],
     56        "google:suggestdetail": suffixes.map(s => ({
     57          mp: "… ",
     58          t: s,
     59        })),
     60      },
     61    ];
     62  });
     63 
     64  // Install the test engine.
     65  let oldDefaultEngine = await Services.search.getDefault();
     66  registerCleanupFunction(async () => {
     67    Services.search.setDefault(
     68      oldDefaultEngine,
     69      Ci.nsISearchService.CHANGE_REASON_UNKNOWN
     70    );
     71    Services.prefs.clearUserPref(PRIVATE_SEARCH_PREF);
     72    Services.prefs.clearUserPref(TAIL_SUGGESTIONS_PREF);
     73    Services.prefs.clearUserPref(SUGGEST_ENABLED_PREF);
     74  });
     75  Services.search.setDefault(engine, Ci.nsISearchService.CHANGE_REASON_UNKNOWN);
     76  Services.prefs.setBoolPref(PRIVATE_SEARCH_PREF, false);
     77  Services.prefs.setBoolPref(TAIL_SUGGESTIONS_PREF, true);
     78  Services.prefs.setBoolPref(SUGGEST_ENABLED_PREF, true);
     79 });
     80 
     81 /**
     82 * Tests that non-tail suggestion providers still return results correctly when
     83 * the tailSuggestions pref is enabled.
     84 */
     85 add_task(async function normal_suggestions_provider() {
     86  let engine = await addTestSuggestionsEngine();
     87  let tailEngine = await Services.search.getDefault();
     88  Services.search.setDefault(engine, Ci.nsISearchService.CHANGE_REASON_UNKNOWN);
     89 
     90  const query = "hello world";
     91  let context = createContext(query, { isPrivate: false });
     92  await check_results({
     93    context,
     94    matches: [
     95      makeSearchResult(context, {
     96        engineName: SUGGESTIONS_ENGINE_NAME,
     97        heuristic: true,
     98      }),
     99      makeSearchResult(context, {
    100        engineName: SUGGESTIONS_ENGINE_NAME,
    101        suggestion: query + " foo",
    102      }),
    103      makeSearchResult(context, {
    104        engineName: SUGGESTIONS_ENGINE_NAME,
    105        suggestion: query + " bar",
    106      }),
    107    ],
    108  });
    109 
    110  Services.search.setDefault(
    111    tailEngine,
    112    Ci.nsISearchService.CHANGE_REASON_UNKNOWN
    113  );
    114  await cleanUpSuggestions();
    115 });
    116 
    117 /**
    118 * Tests a suggestions provider that returns only tail suggestions.
    119 */
    120 add_task(async function basic_tail() {
    121  const query = "what time is it in t";
    122  let context = createContext(query, { isPrivate: false });
    123  await check_results({
    124    context,
    125    matches: [
    126      makeSearchResult(context, {
    127        engineName: TAIL_SUGGESTIONS_ENGINE_NAME,
    128        heuristic: true,
    129      }),
    130      makeSearchResult(context, {
    131        engineName: TAIL_SUGGESTIONS_ENGINE_NAME,
    132        suggestion: query + "oronto",
    133        tail: "toronto",
    134      }),
    135      makeSearchResult(context, {
    136        engineName: TAIL_SUGGESTIONS_ENGINE_NAME,
    137        suggestion: query + "unisia",
    138        tail: "tunisia",
    139      }),
    140    ],
    141  });
    142  await cleanUpSuggestions();
    143 });
    144 
    145 /**
    146 * Tests a suggestions provider that returns both normal and tail suggestions.
    147 * Only normal results should be shown.
    148 */
    149 add_task(async function mixed_suggestions() {
    150  // When normal suggestions are mixed with tail suggestions, they appear at the
    151  // correct position in the google:suggestdetail array as empty objects.
    152  setSuggestionsFn(searchStr => {
    153    let suffixes = ["toronto", "tunisia"];
    154    return [
    155      "what time is it in t",
    156      ["what is the time today texas"].concat(
    157        suffixes.map(s => searchStr + s.slice(1))
    158      ),
    159      [],
    160      {
    161        "google:irrelevantparameter": [],
    162        "google:suggestdetail": [{}].concat(
    163          suffixes.map(s => ({
    164            mp: "… ",
    165            t: s,
    166          }))
    167        ),
    168      },
    169    ];
    170  });
    171 
    172  const query = "what time is it in t";
    173  let context = createContext(query, { isPrivate: false });
    174  await check_results({
    175    context,
    176    matches: [
    177      makeSearchResult(context, {
    178        engineName: TAIL_SUGGESTIONS_ENGINE_NAME,
    179        heuristic: true,
    180      }),
    181      makeSearchResult(context, {
    182        engineName: TAIL_SUGGESTIONS_ENGINE_NAME,
    183        suggestion: "what is the time today texas",
    184        tail: undefined,
    185      }),
    186    ],
    187  });
    188  await cleanUpSuggestions();
    189 });
    190 
    191 /**
    192 * Tests a suggestions provider that returns both normal and tail suggestions,
    193 * with tail suggestions listed before normal suggestions.  In the real world
    194 * we don't expect that to happen, but we should handle it by showing only the
    195 * normal suggestions.
    196 */
    197 add_task(async function mixed_suggestions_tail_first() {
    198  setSuggestionsFn(searchStr => {
    199    let suffixes = ["toronto", "tunisia"];
    200    return [
    201      "what time is it in t",
    202      suffixes
    203        .map(s => searchStr + s.slice(1))
    204        .concat(["what is the time today texas"]),
    205      [],
    206      {
    207        "google:irrelevantparameter": [],
    208        "google:suggestdetail": suffixes
    209          .map(s => ({
    210            mp: "… ",
    211            t: s,
    212          }))
    213          .concat([{}]),
    214      },
    215    ];
    216  });
    217 
    218  const query = "what time is it in t";
    219  let context = createContext(query, { isPrivate: false });
    220  await check_results({
    221    context,
    222    matches: [
    223      makeSearchResult(context, {
    224        engineName: TAIL_SUGGESTIONS_ENGINE_NAME,
    225        heuristic: true,
    226      }),
    227      makeSearchResult(context, {
    228        engineName: TAIL_SUGGESTIONS_ENGINE_NAME,
    229        suggestion: "what is the time today texas",
    230        tail: undefined,
    231      }),
    232    ],
    233  });
    234  await cleanUpSuggestions();
    235 });
    236 
    237 /**
    238 * Tests a search that returns history results, bookmark results and tail
    239 * suggestions. Only the history and bookmark results should be shown.
    240 */
    241 add_task(async function mixed_results() {
    242  await PlacesTestUtils.addVisits([
    243    {
    244      uri: Services.io.newURI("http://example.com/1"),
    245      title: "what time is",
    246    },
    247  ]);
    248 
    249  await PlacesUtils.bookmarks.insert({
    250    parentGuid: PlacesUtils.bookmarks.unfiledGuid,
    251    url: "http://example.com/2",
    252    title: "what time is",
    253  });
    254  await PlacesFrecencyRecalculator.recalculateAnyOutdatedFrecencies();
    255 
    256  // Tail suggestions should not be shown.
    257  const query = "what time is";
    258  let context = createContext(query, { isPrivate: false });
    259  await check_results({
    260    context,
    261    matches: [
    262      makeSearchResult(context, {
    263        engineName: TAIL_SUGGESTIONS_ENGINE_NAME,
    264        heuristic: true,
    265      }),
    266      makeBookmarkResult(context, {
    267        uri: "http://example.com/2",
    268        title: "what time is",
    269      }),
    270      makeVisitResult(context, {
    271        uri: "http://example.com/1",
    272        title: "what time is",
    273      }),
    274    ],
    275  });
    276 
    277  // Once we make the query specific enough to exclude the history and bookmark
    278  // results, we should show tail suggestions.
    279  const tQuery = "what time is it in t";
    280  context = createContext(tQuery, { isPrivate: false });
    281  await check_results({
    282    context,
    283    matches: [
    284      makeSearchResult(context, {
    285        engineName: TAIL_SUGGESTIONS_ENGINE_NAME,
    286        heuristic: true,
    287      }),
    288      makeSearchResult(context, {
    289        engineName: TAIL_SUGGESTIONS_ENGINE_NAME,
    290        suggestion: tQuery + "oronto",
    291        tail: "toronto",
    292      }),
    293      makeSearchResult(context, {
    294        engineName: TAIL_SUGGESTIONS_ENGINE_NAME,
    295        suggestion: tQuery + "unisia",
    296        tail: "tunisia",
    297      }),
    298    ],
    299  });
    300 
    301  await cleanUpSuggestions();
    302 });
    303 
    304 /**
    305 * Tests that tail suggestions are deduped if their full-text form is a dupe of
    306 * a local search suggestion. Remaining tail suggestions should also not be
    307 * shown since we do not mix tail and non-tail suggestions.
    308 */
    309 add_task(async function dedupe_local() {
    310  Services.prefs.setIntPref("browser.urlbar.maxHistoricalSearchSuggestions", 1);
    311  await UrlbarTestUtils.formHistory.add(["what time is it in toronto"]);
    312 
    313  const query = "what time is it in t";
    314  let context = createContext(query, { isPrivate: false });
    315  await check_results({
    316    context,
    317    matches: [
    318      makeSearchResult(context, {
    319        engineName: TAIL_SUGGESTIONS_ENGINE_NAME,
    320        heuristic: true,
    321      }),
    322      makeFormHistoryResult(context, {
    323        engineName: TAIL_SUGGESTIONS_ENGINE_NAME,
    324        suggestion: query + "oronto",
    325      }),
    326    ],
    327  });
    328 
    329  Services.prefs.clearUserPref("browser.urlbar.maxHistoricalSearchSuggestions");
    330  await cleanUpSuggestions();
    331 });
    332 
    333 /**
    334 * Tests that the correct number of suggestion results are displayed if
    335 * maxResults is limited, even when tail suggestions are returned.
    336 */
    337 add_task(async function limit_results() {
    338  await UrlbarTestUtils.formHistory.clear();
    339  const query = "what time is it in t";
    340  let context = createContext(query, { isPrivate: false });
    341  context.maxResults = 2;
    342  await check_results({
    343    context,
    344    matches: [
    345      makeSearchResult(context, {
    346        engineName: TAIL_SUGGESTIONS_ENGINE_NAME,
    347        heuristic: true,
    348      }),
    349      makeSearchResult(context, {
    350        engineName: TAIL_SUGGESTIONS_ENGINE_NAME,
    351        suggestion: query + "oronto",
    352        tail: "toronto",
    353      }),
    354    ],
    355  });
    356  await cleanUpSuggestions();
    357 });
    358 
    359 /**
    360 * Tests that tail suggestions are hidden if the pref is disabled.
    361 */
    362 add_task(async function disable_pref() {
    363  let oldPrefValue = Services.prefs.getBoolPref(TAIL_SUGGESTIONS_PREF);
    364  Services.prefs.setBoolPref(TAIL_SUGGESTIONS_PREF, false);
    365  const query = "what time is it in t";
    366  let context = createContext(query, { isPrivate: false });
    367  await check_results({
    368    context,
    369    matches: [
    370      makeSearchResult(context, {
    371        engineName: TAIL_SUGGESTIONS_ENGINE_NAME,
    372        heuristic: true,
    373      }),
    374    ],
    375  });
    376 
    377  Services.prefs.setBoolPref(TAIL_SUGGESTIONS_PREF, oldPrefValue);
    378  await cleanUpSuggestions();
    379 });