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 }