test_autofill_origins_alt_frecency.js (8270B)
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 is a basic autofill test to ensure enabling the alternative frecency 6 // algorithm doesn't break autofill or tab-to-search. A more comprehensive 7 // testing of the algorithm itself is not included since it's something that 8 // may change frequently according to experimentation results. 9 // Other existing autofill tests will, of course, need to be adapted once an 10 // algorithm is promoted to be the default. 11 12 ChromeUtils.defineLazyGetter(this, "PlacesFrecencyRecalculator", () => { 13 return Cc["@mozilla.org/places/frecency-recalculator;1"].getService( 14 Ci.nsIObserver 15 ).wrappedJSObject; 16 }); 17 18 testEngine_setup(); 19 20 add_task(async function test_autofill() { 21 const origin = "example.com"; 22 let context = createContext(origin.substring(0, 2), { isPrivate: false }); 23 await check_results({ 24 context, 25 matches: [ 26 makeSearchResult(context, { 27 engineName: "Suggestions", 28 heuristic: true, 29 }), 30 ], 31 }); 32 // Add many visits. 33 const url = `https://${origin}/`; 34 await PlacesTestUtils.addVisits(new Array(10).fill(url)); 35 Assert.equal( 36 await PlacesUtils.metadata.get("origin_alt_frecency_threshold", 0), 37 0, 38 "Check there's no threshold initially" 39 ); 40 await PlacesFrecencyRecalculator.recalculateAnyOutdatedFrecencies(); 41 Assert.greater( 42 await PlacesUtils.metadata.get("origin_alt_frecency_threshold", 0), 43 0, 44 "Check a threshold has been calculated" 45 ); 46 await check_results({ 47 context, 48 autofilled: `${origin}/`, 49 completed: url, 50 matches: [ 51 makeVisitResult(context, { 52 uri: url, 53 title: `test visit for ${url}`, 54 heuristic: true, 55 }), 56 ], 57 }); 58 await PlacesUtils.history.clear(); 59 }); 60 61 add_task(async function test_autofill_www() { 62 const origin = "example.com"; 63 // Add many visits. 64 const url = `https://www.${origin}/`; 65 await PlacesTestUtils.addVisits(new Array(10).fill(url)); 66 await PlacesFrecencyRecalculator.recalculateAnyOutdatedFrecencies(); 67 68 let context = createContext(origin.substring(0, 2), { isPrivate: false }); 69 await check_results({ 70 context, 71 autofilled: `${origin}/`, 72 completed: url, 73 matches: [ 74 makeVisitResult(context, { 75 uri: url, 76 title: `test visit for ${url}`, 77 heuristic: true, 78 }), 79 ], 80 }); 81 await PlacesUtils.history.clear(); 82 }); 83 84 add_task( 85 { 86 pref_set: [["browser.urlbar.tabToSearch.onboard.interactionsLeft", 0]], 87 }, 88 async function test_autofill_prefix_priority() { 89 const origin = "localhost"; 90 const url = `https://${origin}/`; 91 await PlacesTestUtils.addVisits([url, `http://${origin}/`]); 92 await PlacesFrecencyRecalculator.recalculateAnyOutdatedFrecencies(); 93 94 let engine = Services.search.defaultEngine; 95 let context = createContext(origin.substring(0, 2), { isPrivate: false }); 96 await check_results({ 97 context, 98 autofilled: `${origin}/`, 99 completed: url, 100 matches: [ 101 makeVisitResult(context, { 102 uri: url, 103 title: `test visit for ${url}`, 104 heuristic: true, 105 }), 106 makeSearchResult(context, { 107 engineName: engine.name, 108 engineIconUri: UrlbarUtils.ICON.SEARCH_GLASS, 109 searchUrlDomainWithoutSuffix: UrlbarUtils.stripPublicSuffixFromHost( 110 engine.searchUrlDomain 111 ), 112 providesSearchMode: true, 113 query: "", 114 providerName: "UrlbarProviderTabToSearch", 115 }), 116 ], 117 }); 118 await PlacesUtils.history.clear(); 119 } 120 ); 121 122 add_task(async function test_autofill_threshold() { 123 await PlacesTestUtils.addVisits(new Array(10).fill("https://example.com/")); 124 // Add more visits to the same origins to differenciate the frecency scores. 125 await PlacesTestUtils.addVisits([ 126 "https://example.com/2", 127 "https://example.com/3", 128 ]); 129 await PlacesTestUtils.addVisits("https://somethingelse.org/"); 130 await PlacesFrecencyRecalculator.recalculateAnyOutdatedFrecencies(); 131 132 let threshold = await PlacesUtils.metadata.get( 133 "origin_alt_frecency_threshold", 134 0 135 ); 136 Assert.greater( 137 threshold, 138 await PlacesTestUtils.getDatabaseValue("moz_origins", "alt_frecency", { 139 host: "somethingelse.org", 140 }), 141 "Check mozilla.org has a lower frecency than the threshold" 142 ); 143 Assert.equal( 144 threshold, 145 await PlacesTestUtils.getDatabaseValue("moz_origins", "avg(alt_frecency)"), 146 "Check the threshold has been calculared correctly" 147 ); 148 149 let engine = Services.search.defaultEngine; 150 let context = createContext("so", { isPrivate: false }); 151 await check_results({ 152 context, 153 matches: [ 154 makeSearchResult(context, { 155 heuristic: true, 156 query: "so", 157 engineName: engine.name, 158 }), 159 makeVisitResult(context, { 160 uri: "https://somethingelse.org/", 161 title: "test visit for https://somethingelse.org/", 162 }), 163 ], 164 }); 165 await PlacesUtils.history.clear(); 166 }); 167 168 add_task(async function test_autofill_cutoff() { 169 // Add many visits older than the default 90 days cutoff. 170 const visitDate = new Date(Date.now() - 120 * 86400000); 171 await PlacesTestUtils.addVisits( 172 new Array(10).fill("https://example.com/").map(url => ({ url, visitDate })) 173 ); 174 await PlacesFrecencyRecalculator.recalculateAnyOutdatedFrecencies(); 175 176 Assert.strictEqual( 177 await PlacesTestUtils.getDatabaseValue("moz_origins", "alt_frecency", { 178 host: "example.com", 179 }), 180 null, 181 "Check example.com has a NULL frecency" 182 ); 183 184 let engine = Services.search.defaultEngine; 185 let context = createContext("ex", { isPrivate: false }); 186 await check_results({ 187 context, 188 matches: [ 189 makeSearchResult(context, { 190 heuristic: true, 191 query: "ex", 192 engineName: engine.name, 193 }), 194 makeVisitResult(context, { 195 uri: "https://example.com/", 196 title: "test visit for https://example.com/", 197 }), 198 ], 199 }); 200 await PlacesUtils.history.clear(); 201 }); 202 203 add_task(async function test_autofill_threshold_www() { 204 // Only one visit to the non-www origin, many to the www. version. We expect 205 // example.com to autofill even if its frecency is small, because the overall 206 // frecency for both origins should be considered. 207 await PlacesTestUtils.addVisits("https://example.com/"); 208 await PlacesTestUtils.addVisits( 209 new Array(10).fill("https://www.example.com/") 210 ); 211 await PlacesTestUtils.addVisits( 212 new Array(10).fill("https://www.somethingelse.org/") 213 ); 214 await PlacesFrecencyRecalculator.recalculateAnyOutdatedFrecencies(); 215 216 let threshold = await PlacesUtils.metadata.get( 217 "origin_alt_frecency_threshold", 218 0 219 ); 220 let frecencyOfExampleCom = await PlacesTestUtils.getDatabaseValue( 221 "moz_origins", 222 "alt_frecency", 223 { 224 host: "example.com", 225 } 226 ); 227 let frecencyOfWwwExampleCom = await PlacesTestUtils.getDatabaseValue( 228 "moz_origins", 229 "alt_frecency", 230 { 231 host: "www.example.com", 232 } 233 ); 234 Assert.greater( 235 threshold, 236 frecencyOfExampleCom, 237 "example.com frecency is lower than the threshold" 238 ); 239 Assert.greater( 240 frecencyOfWwwExampleCom, 241 threshold, 242 "www.example.com frecency is higher than the threshold" 243 ); 244 245 // We used to wrongly use the average between the 2 domains, so check also 246 // the average would not autofill. 247 Assert.greater( 248 threshold, 249 [frecencyOfExampleCom, frecencyOfWwwExampleCom].reduce( 250 (acc, v, i, arr) => acc + v / arr.length, 251 0 252 ), 253 "Check frecency average is lower than the threshold" 254 ); 255 256 let context = createContext("ex", { isPrivate: false }); 257 await check_results({ 258 context, 259 autofilled: "example.com/", 260 completed: "https://www.example.com/", 261 matches: [ 262 makeVisitResult(context, { 263 uri: "https://www.example.com/", 264 title: "test visit for https://www.example.com/", 265 heuristic: true, 266 }), 267 makeVisitResult(context, { 268 uri: "https://example.com/", 269 title: "test visit for https://example.com/", 270 }), 271 ], 272 }); 273 await PlacesUtils.history.clear(); 274 });