tor-browser

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

test_quicksuggest_merinoSessions.js (5951B)


      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 // Tests Merino session integration with UrlbarProviderQuickSuggest.
      6 
      7 "use strict";
      8 
      9 add_setup(async () => {
     10  await MerinoTestUtils.server.start();
     11  await QuickSuggestTestUtils.ensureQuickSuggestInit({
     12    prefs: [
     13      ["suggest.quicksuggest.sponsored", true],
     14      ["quicksuggest.online.available", true],
     15      ["quicksuggest.online.enabled", true],
     16    ],
     17  });
     18 });
     19 
     20 // In a single engagement, all requests should use the same session ID and the
     21 // sequence number should be incremented.
     22 add_task(async function singleEngagement() {
     23  let controller = UrlbarTestUtils.newMockController();
     24 
     25  for (let i = 0; i < 3; i++) {
     26    let searchString = "search" + i;
     27    await controller.startQuery(
     28      createContext(searchString, {
     29        providers: [UrlbarProviderQuickSuggest.name],
     30        isPrivate: false,
     31      })
     32    );
     33 
     34    MerinoTestUtils.server.checkAndClearRequests([
     35      {
     36        params: {
     37          [MerinoTestUtils.SEARCH_PARAMS.QUERY]: searchString,
     38          [MerinoTestUtils.SEARCH_PARAMS.SEQUENCE_NUMBER]: i,
     39        },
     40      },
     41    ]);
     42  }
     43 
     44  // End the engagement to reset the session for the next test.
     45  endEngagement({ controller });
     46 });
     47 
     48 // New engagements should not use the same session ID as previous engagements
     49 // and the sequence number should be reset. This task completes each engagement
     50 // successfully.
     51 add_task(async function manyEngagements_engagement() {
     52  await doManyEngagementsTest("engagement");
     53 });
     54 
     55 // New engagements should not use the same session ID as previous engagements
     56 // and the sequence number should be reset. This task abandons each engagement.
     57 add_task(async function manyEngagements_abandonment() {
     58  await doManyEngagementsTest("abandonment");
     59 });
     60 
     61 async function doManyEngagementsTest(state) {
     62  let controller = UrlbarTestUtils.newMockController();
     63 
     64  for (let i = 0; i < 3; i++) {
     65    let searchString = "search" + i;
     66    let context = createContext(searchString, {
     67      providers: [UrlbarProviderQuickSuggest.name],
     68      isPrivate: false,
     69    });
     70    await controller.startQuery(context);
     71 
     72    MerinoTestUtils.server.checkAndClearRequests([
     73      {
     74        params: {
     75          [MerinoTestUtils.SEARCH_PARAMS.QUERY]: searchString,
     76          [MerinoTestUtils.SEARCH_PARAMS.SEQUENCE_NUMBER]: 0,
     77        },
     78      },
     79    ]);
     80 
     81    endEngagement({ context, state, controller });
     82  }
     83 }
     84 
     85 // When a search is canceled after the request is sent and before the Merino
     86 // response is received, the sequence number should still be incremented.
     87 add_task(async function canceledQueries() {
     88  let controller = UrlbarTestUtils.newMockController();
     89 
     90  for (let i = 0; i < 3; i++) {
     91    // Send the first response after a delay to make sure the client will not
     92    // receive it before we start the second fetch.
     93    MerinoTestUtils.server.response.delay = UrlbarPrefs.get("merino.timeoutMs");
     94 
     95    // Start the first search.
     96    let requestPromise = MerinoTestUtils.server.waitForNextRequest();
     97    let searchString1 = "search" + i;
     98    controller.startQuery(
     99      createContext(searchString1, {
    100        providers: [UrlbarProviderQuickSuggest.name],
    101        isPrivate: false,
    102      })
    103    );
    104 
    105    // Wait until the first request is received before starting the second
    106    // search. If we started the second search immediately, the first would be
    107    // canceled before the provider is even called due to the urlbar's 50ms
    108    // delay (see `browser.urlbar.delay`) so the sequence number would not be
    109    // incremented for it. Here we want to test the case where the first search
    110    // is canceled after the request is sent and the number is incremented.
    111    await requestPromise;
    112    delete MerinoTestUtils.server.response.delay;
    113 
    114    // Now do a second search that cancels the first.
    115    let searchString2 = searchString1 + "again";
    116    await controller.startQuery(
    117      createContext(searchString2, {
    118        providers: [UrlbarProviderQuickSuggest.name],
    119        isPrivate: false,
    120      })
    121    );
    122 
    123    // The sequence number should have been incremented for each search.
    124    MerinoTestUtils.server.checkAndClearRequests([
    125      {
    126        params: {
    127          [MerinoTestUtils.SEARCH_PARAMS.QUERY]: searchString1,
    128          [MerinoTestUtils.SEARCH_PARAMS.SEQUENCE_NUMBER]: 2 * i,
    129        },
    130      },
    131      {
    132        params: {
    133          [MerinoTestUtils.SEARCH_PARAMS.QUERY]: searchString2,
    134          [MerinoTestUtils.SEARCH_PARAMS.SEQUENCE_NUMBER]: 2 * i + 1,
    135        },
    136      },
    137    ]);
    138  }
    139 
    140  // End the engagement to reset the session for the next test.
    141  endEngagement({ controller });
    142 });
    143 
    144 function endEngagement({ controller, context = null, state = "engagement" }) {
    145  context ||= createContext("endEngagement", {
    146    providers: [UrlbarProviderQuickSuggest.name],
    147    isPrivate: false,
    148  });
    149  let details = { selIndex: -1, result: { payload: {} } };
    150  let quickSuggestProviderInstance = UrlbarProvidersManager.getProvider(
    151    UrlbarProviderQuickSuggest.name
    152  );
    153 
    154  switch (state) {
    155    case "engagement":
    156      quickSuggestProviderInstance.onEngagement(context, controller, details);
    157      quickSuggestProviderInstance.onSearchSessionEnd(
    158        context,
    159        controller,
    160        details
    161      );
    162      break;
    163    case "abandonment":
    164      quickSuggestProviderInstance.onSearchSessionEnd(
    165        context,
    166        controller,
    167        details
    168      );
    169      break;
    170    default:
    171      throw new Error("Unrecognized engagement state: " + state);
    172  }
    173 
    174  Assert.strictEqual(
    175    merinoClient().sessionID,
    176    null,
    177    "sessionID is null after engagement"
    178  );
    179  Assert.strictEqual(
    180    merinoClient()._test_sessionTimer,
    181    null,
    182    "sessionTimer is null after engagement"
    183  );
    184 }
    185 
    186 function merinoClient() {
    187  return QuickSuggest.getFeature("SuggestBackendMerino")?.client;
    188 }