test_providerTabToSearch.js (17853B)
1 /* Any copyright is dedicated to the Public Domain. 2 * http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 /** 5 * Tests UrlbarProviderTabToSearch. See also 6 * browser/components/urlbar/tests/browser/browser_tabToSearch.js 7 */ 8 9 "use strict"; 10 11 let testEngine; 12 13 add_setup(async () => { 14 // Disable search suggestions for a less verbose test. 15 Services.prefs.setBoolPref("browser.search.suggest.enabled", false); 16 // Disable ScotchBonnet that provides its own tab to search implementation. 17 Services.prefs.setBoolPref( 18 "browser.urlbar.scotchBonnet.enableOverride", 19 false 20 ); 21 // Disable tab-to-search onboarding results. Those are covered in 22 // browser/components/urlbar/tests/browser/browser_tabToSearch.js. 23 Services.prefs.setIntPref( 24 "browser.urlbar.tabToSearch.onboard.interactionsLeft", 25 0 26 ); 27 await SearchTestUtils.installSearchExtension({ name: "Test" }); 28 testEngine = await Services.search.getEngineByName("Test"); 29 30 registerCleanupFunction(async () => { 31 Services.prefs.clearUserPref( 32 "browser.urlbar.tabToSearch.onboard.interactionsLeft" 33 ); 34 Services.prefs.clearUserPref("browser.search.suggest.enabled"); 35 Services.prefs.clearUserPref("browser.urlbar.scotchBonnet.enableOverride"); 36 }); 37 }); 38 39 // Tests that tab-to-search results appear when the engine's result domain is 40 // autofilled. 41 add_task(async function basic() { 42 await PlacesTestUtils.addVisits(["https://example.com/"]); 43 let context = createContext("examp", { isPrivate: false }); 44 await check_results({ 45 context, 46 autofilled: "example.com/", 47 completed: "https://example.com/", 48 matches: [ 49 makeVisitResult(context, { 50 uri: "https://example.com/", 51 title: "test visit for https://example.com/", 52 heuristic: true, 53 providerName: "UrlbarProviderAutofill", 54 }), 55 makeSearchResult(context, { 56 engineName: testEngine.name, 57 engineIconUri: UrlbarUtils.ICON.SEARCH_GLASS, 58 searchUrlDomainWithoutSuffix: UrlbarUtils.stripPublicSuffixFromHost( 59 testEngine.searchUrlDomain 60 ), 61 providesSearchMode: true, 62 query: "", 63 providerName: "UrlbarProviderTabToSearch", 64 }), 65 ], 66 }); 67 68 info("Repeat the search but with tab-to-search disabled through pref."); 69 Services.prefs.setBoolPref("browser.urlbar.suggest.engines", false); 70 await check_results({ 71 context, 72 autofilled: "example.com/", 73 completed: "https://example.com/", 74 matches: [ 75 makeVisitResult(context, { 76 uri: "https://example.com/", 77 title: "test visit for https://example.com/", 78 heuristic: true, 79 providerName: "UrlbarProviderAutofill", 80 }), 81 ], 82 }); 83 Services.prefs.clearUserPref("browser.urlbar.suggest.engines"); 84 85 await cleanupPlaces(); 86 }); 87 88 // Tests that tab-to-search results are shown when the typed string matches an 89 // engine domain even when there is no autofill. 90 add_task(async function noAutofill() { 91 // Note we are not adding any history visits. 92 let context = createContext("examp", { isPrivate: false }); 93 await check_results({ 94 context, 95 matches: [ 96 makeSearchResult(context, { 97 engineName: Services.search.defaultEngine.name, 98 engineIconUri: await Services.search.defaultEngine.getIconURL(), 99 heuristic: true, 100 providerName: "UrlbarProviderHeuristicFallback", 101 }), 102 makeSearchResult(context, { 103 engineName: testEngine.name, 104 engineIconUri: UrlbarUtils.ICON.SEARCH_GLASS, 105 searchUrlDomainWithoutSuffix: UrlbarUtils.stripPublicSuffixFromHost( 106 testEngine.searchUrlDomain 107 ), 108 providesSearchMode: true, 109 query: "", 110 providerName: "UrlbarProviderTabToSearch", 111 }), 112 ], 113 }); 114 }); 115 116 // Tests that tab-to-search results are not shown when the typed string matches 117 // an engine domain, but something else is being autofilled. 118 add_task(async function autofillDoesNotMatchEngine() { 119 await PlacesTestUtils.addVisits(["https://example.test.ca/"]); 120 let context = createContext("example", { isPrivate: false }); 121 await check_results({ 122 context, 123 autofilled: "example.test.ca/", 124 completed: "https://example.test.ca/", 125 matches: [ 126 makeVisitResult(context, { 127 uri: "https://example.test.ca/", 128 title: "test visit for https://example.test.ca/", 129 heuristic: true, 130 providerName: "UrlbarProviderAutofill", 131 }), 132 ], 133 }); 134 135 await cleanupPlaces(); 136 }); 137 138 // Tests that www. is ignored for the purposes of matching autofill to 139 // tab-to-search. 140 add_task(async function ignoreWww() { 141 // The history result has www., the engine does not. 142 await PlacesTestUtils.addVisits(["https://www.example.com/"]); 143 let context = createContext("www.examp", { isPrivate: false }); 144 await check_results({ 145 context, 146 autofilled: "www.example.com/", 147 completed: "https://www.example.com/", 148 matches: [ 149 makeVisitResult(context, { 150 uri: "https://www.example.com/", 151 title: "test visit for https://www.example.com/", 152 heuristic: true, 153 providerName: "UrlbarProviderAutofill", 154 }), 155 makeSearchResult(context, { 156 engineName: testEngine.name, 157 engineIconUri: UrlbarUtils.ICON.SEARCH_GLASS, 158 searchUrlDomainWithoutSuffix: UrlbarUtils.stripPublicSuffixFromHost( 159 testEngine.searchUrlDomain 160 ), 161 providesSearchMode: true, 162 query: "", 163 providerName: "UrlbarProviderTabToSearch", 164 }), 165 ], 166 }); 167 await cleanupPlaces(); 168 169 // The engine has www., the history result does not. 170 await PlacesTestUtils.addVisits(["https://foo.bar/"]); 171 let extension = await SearchTestUtils.installSearchExtension( 172 { 173 name: "TestWww", 174 search_url: "https://www.foo.bar/", 175 }, 176 { skipUnload: true } 177 ); 178 let wwwTestEngine = Services.search.getEngineByName("TestWww"); 179 context = createContext("foo", { isPrivate: false }); 180 await check_results({ 181 context, 182 autofilled: "foo.bar/", 183 completed: "https://foo.bar/", 184 matches: [ 185 makeVisitResult(context, { 186 uri: "https://foo.bar/", 187 title: "test visit for https://foo.bar/", 188 heuristic: true, 189 providerName: "UrlbarProviderAutofill", 190 }), 191 makeSearchResult(context, { 192 engineName: wwwTestEngine.name, 193 engineIconUri: UrlbarUtils.ICON.SEARCH_GLASS, 194 searchUrlDomainWithoutSuffix: UrlbarUtils.stripPublicSuffixFromHost( 195 wwwTestEngine.searchUrlDomain 196 ), 197 providesSearchMode: true, 198 query: "", 199 providerName: "UrlbarProviderTabToSearch", 200 }), 201 ], 202 }); 203 await cleanupPlaces(); 204 205 // Both the engine and the history result have www. 206 await PlacesTestUtils.addVisits(["https://www.foo.bar/"]); 207 context = createContext("foo", { isPrivate: false }); 208 await check_results({ 209 context, 210 autofilled: "foo.bar/", 211 completed: "https://www.foo.bar/", 212 matches: [ 213 makeVisitResult(context, { 214 uri: "https://www.foo.bar/", 215 title: "test visit for https://www.foo.bar/", 216 heuristic: true, 217 providerName: "UrlbarProviderAutofill", 218 }), 219 makeSearchResult(context, { 220 engineName: wwwTestEngine.name, 221 engineIconUri: UrlbarUtils.ICON.SEARCH_GLASS, 222 searchUrlDomainWithoutSuffix: UrlbarUtils.stripPublicSuffixFromHost( 223 wwwTestEngine.searchUrlDomain 224 ), 225 providesSearchMode: true, 226 query: "", 227 providerName: "UrlbarProviderTabToSearch", 228 }), 229 ], 230 }); 231 await cleanupPlaces(); 232 233 await extension.unload(); 234 }); 235 236 // Tests that when a user's query causes autofill to replace one engine's domain 237 // with another, the correct tab-to-search results are shown. 238 add_task(async function conflictingEngines() { 239 for (let i = 0; i < 3; i++) { 240 await PlacesTestUtils.addVisits([ 241 "https://foobar.com/", 242 "https://foo.com/", 243 ]); 244 } 245 let extension1 = await SearchTestUtils.installSearchExtension( 246 { 247 name: "TestFooBar", 248 search_url: "https://foobar.com/", 249 }, 250 { skipUnload: true } 251 ); 252 let extension2 = await SearchTestUtils.installSearchExtension( 253 { 254 name: "TestFoo", 255 search_url: "https://foo.com/", 256 }, 257 { skipUnload: true } 258 ); 259 let fooBarTestEngine = Services.search.getEngineByName("TestFooBar"); 260 let fooTestEngine = Services.search.getEngineByName("TestFoo"); 261 262 // Search for "foo", autofilling foo.com. Observe that the foo.com 263 // tab-to-search result is shown, even though the foobar.com engine was added 264 // first (and thus enginesForDomainPrefix puts it earlier in its returned 265 // array.) 266 let context = createContext("foo", { isPrivate: false }); 267 await check_results({ 268 context, 269 autofilled: "foo.com/", 270 completed: "https://foo.com/", 271 matches: [ 272 makeVisitResult(context, { 273 uri: "https://foo.com/", 274 title: "test visit for https://foo.com/", 275 heuristic: true, 276 providerName: "UrlbarProviderAutofill", 277 }), 278 makeSearchResult(context, { 279 engineName: fooTestEngine.name, 280 engineIconUri: UrlbarUtils.ICON.SEARCH_GLASS, 281 searchUrlDomainWithoutSuffix: UrlbarUtils.stripPublicSuffixFromHost( 282 fooTestEngine.searchUrlDomain 283 ), 284 providesSearchMode: true, 285 query: "", 286 providerName: "UrlbarProviderTabToSearch", 287 }), 288 makeVisitResult(context, { 289 uri: "https://foobar.com/", 290 title: "test visit for https://foobar.com/", 291 providerName: "UrlbarProviderPlaces", 292 }), 293 ], 294 }); 295 296 // Search for "foob", autofilling foobar.com. Observe that the foo.com 297 // tab-to-search result is replaced with the foobar.com tab-to-search result. 298 context = createContext("foob", { isPrivate: false }); 299 await check_results({ 300 context, 301 autofilled: "foobar.com/", 302 completed: "https://foobar.com/", 303 matches: [ 304 makeVisitResult(context, { 305 uri: "https://foobar.com/", 306 title: "test visit for https://foobar.com/", 307 heuristic: true, 308 providerName: "UrlbarProviderAutofill", 309 }), 310 makeSearchResult(context, { 311 engineName: fooBarTestEngine.name, 312 engineIconUri: UrlbarUtils.ICON.SEARCH_GLASS, 313 searchUrlDomainWithoutSuffix: UrlbarUtils.stripPublicSuffixFromHost( 314 fooBarTestEngine.searchUrlDomain 315 ), 316 providesSearchMode: true, 317 query: "", 318 providerName: "UrlbarProviderTabToSearch", 319 }), 320 ], 321 }); 322 323 await cleanupPlaces(); 324 await extension1.unload(); 325 await extension2.unload(); 326 }); 327 328 add_task(async function multipleEnginesForHostname() { 329 info( 330 "In case of multiple engines only one tab-to-search result should be returned" 331 ); 332 let extension = await SearchTestUtils.installSearchExtension( 333 { 334 name: "TestMaps", 335 search_url: "https://example.com/maps/", 336 }, 337 { skipUnload: true } 338 ); 339 340 let context = createContext("examp", { isPrivate: false }); 341 let maxResultCount = UrlbarPrefs.get("maxRichResults"); 342 343 // Add enough visits to autofill example.com. 344 for (let i = 0; i < maxResultCount; i++) { 345 await PlacesTestUtils.addVisits("https://example.com/"); 346 } 347 348 // Add enough visits to other URLs matching our query to fill up the list of 349 // results. 350 let otherVisitResults = []; 351 for (let i = 0; i < maxResultCount; i++) { 352 let url = `https://mochi${i}.test:8888/example/` + i; 353 await PlacesTestUtils.addVisits(url); 354 otherVisitResults.unshift( 355 makeVisitResult(context, { 356 uri: url, 357 title: "test visit for " + url, 358 }) 359 ); 360 } 361 362 await check_results({ 363 context, 364 autofilled: "example.com/", 365 completed: "https://example.com/", 366 matches: [ 367 makeVisitResult(context, { 368 uri: "https://example.com/", 369 title: "test visit for https://example.com/", 370 heuristic: true, 371 providerName: "UrlbarProviderAutofill", 372 }), 373 makeSearchResult(context, { 374 engineName: testEngine.name, 375 engineIconUri: UrlbarUtils.ICON.SEARCH_GLASS, 376 searchUrlDomainWithoutSuffix: UrlbarUtils.stripPublicSuffixFromHost( 377 testEngine.searchUrlDomain 378 ), 379 providesSearchMode: true, 380 query: "", 381 providerName: "UrlbarProviderTabToSearch", 382 }), 383 // There should be `maxResultCount` - 2 other visit results. If this fails 384 // because there are actually `maxResultCount` - 3 other results, then the 385 // muxer is improperly including both TabToSearch results in its 386 // calculation of the total available result span instead of only one, so 387 // one fewer visit result appears than expected. 388 ...otherVisitResults.slice(0, maxResultCount - 2), 389 ], 390 }); 391 await cleanupPlaces(); 392 await extension.unload(); 393 }); 394 395 add_task(async function test_casing() { 396 info("Tab-to-search results appear also in case of different casing."); 397 await PlacesTestUtils.addVisits(["https://example.com/"]); 398 let context = createContext("eXAm", { isPrivate: false }); 399 await check_results({ 400 context, 401 autofilled: "eXAmple.com/", 402 completed: "https://example.com/", 403 matches: [ 404 makeVisitResult(context, { 405 uri: "https://example.com/", 406 title: "test visit for https://example.com/", 407 heuristic: true, 408 providerName: "UrlbarProviderAutofill", 409 }), 410 makeSearchResult(context, { 411 engineName: testEngine.name, 412 engineIconUri: UrlbarUtils.ICON.SEARCH_GLASS, 413 searchUrlDomainWithoutSuffix: UrlbarUtils.stripPublicSuffixFromHost( 414 testEngine.searchUrlDomain 415 ), 416 providesSearchMode: true, 417 query: "", 418 providerName: "UrlbarProviderTabToSearch", 419 }), 420 ], 421 }); 422 await cleanupPlaces(); 423 }); 424 425 add_task(async function test_publicSuffix() { 426 info("Tab-to-search results appear also in case of partial host match."); 427 let extension = await SearchTestUtils.installSearchExtension( 428 { 429 name: "MyTest", 430 search_url: "https://test.mytest.it/", 431 }, 432 { skipUnload: true } 433 ); 434 let engine = Services.search.getEngineByName("MyTest"); 435 await PlacesTestUtils.addVisits(["https://test.mytest.it/"]); 436 let context = createContext("my", { isPrivate: false }); 437 await check_results({ 438 context, 439 matches: [ 440 makeSearchResult(context, { 441 engineName: Services.search.defaultEngine.name, 442 engineIconUri: await Services.search.defaultEngine.getIconURL(), 443 heuristic: true, 444 providerName: "UrlbarProviderHeuristicFallback", 445 }), 446 makeSearchResult(context, { 447 engineName: engine.name, 448 engineIconUri: UrlbarUtils.ICON.SEARCH_GLASS, 449 searchUrlDomainWithoutSuffix: UrlbarUtils.stripPublicSuffixFromHost( 450 engine.searchUrlDomain 451 ), 452 providesSearchMode: true, 453 query: "", 454 providerName: "UrlbarProviderTabToSearch", 455 satisfiesAutofillThreshold: true, 456 }), 457 makeVisitResult(context, { 458 uri: "https://test.mytest.it/", 459 title: "test visit for https://test.mytest.it/", 460 providerName: "UrlbarProviderPlaces", 461 }), 462 ], 463 }); 464 await cleanupPlaces(); 465 await extension.unload(); 466 }); 467 468 add_task(async function test_publicSuffixIsHost() { 469 info("Tab-to-search results does not appear in case we autofill a suffix."); 470 let extension = await SearchTestUtils.installSearchExtension( 471 { 472 name: "SuffixTest", 473 search_url: "https://somesuffix.com.mx/", 474 }, 475 { skipUnload: true } 476 ); 477 478 // The top level domain will be autofilled, not the full domain. 479 await PlacesTestUtils.addVisits(["https://com.mx/"]); 480 let context = createContext("co", { isPrivate: false }); 481 await check_results({ 482 context, 483 autofilled: "com.mx/", 484 completed: "https://com.mx/", 485 matches: [ 486 makeVisitResult(context, { 487 uri: "https://com.mx/", 488 title: "test visit for https://com.mx/", 489 heuristic: true, 490 providerName: "UrlbarProviderAutofill", 491 }), 492 ], 493 }); 494 await cleanupPlaces(); 495 await extension.unload(); 496 }); 497 498 add_task(async function test_disabledEngine() { 499 info("Tab-to-search results does not appear for a Pref-disabled engine."); 500 let extension = await SearchTestUtils.installSearchExtension( 501 { 502 name: "Disabled", 503 search_url: "https://disabled.com/", 504 }, 505 { skipUnload: true } 506 ); 507 let engine = Services.search.getEngineByName("Disabled"); 508 await PlacesTestUtils.addVisits(["https://disabled.com/"]); 509 let context = createContext("dis", { isPrivate: false }); 510 511 info("Sanity check that the engine would appear."); 512 await check_results({ 513 context, 514 autofilled: "disabled.com/", 515 completed: "https://disabled.com/", 516 matches: [ 517 makeVisitResult(context, { 518 uri: "https://disabled.com/", 519 title: "test visit for https://disabled.com/", 520 heuristic: true, 521 providerName: "UrlbarProviderAutofill", 522 }), 523 makeSearchResult(context, { 524 engineName: engine.name, 525 engineIconUri: UrlbarUtils.ICON.SEARCH_GLASS, 526 searchUrlDomainWithoutSuffix: UrlbarUtils.stripPublicSuffixFromHost( 527 engine.searchUrlDomain 528 ), 529 providesSearchMode: true, 530 query: "", 531 providerName: "UrlbarProviderTabToSearch", 532 }), 533 ], 534 }); 535 536 info("Now disable the engine."); 537 engine.hideOneOffButton = true; 538 539 await check_results({ 540 context, 541 autofilled: "disabled.com/", 542 completed: "https://disabled.com/", 543 matches: [ 544 makeVisitResult(context, { 545 uri: "https://disabled.com/", 546 title: "test visit for https://disabled.com/", 547 heuristic: true, 548 providerName: "UrlbarProviderAutofill", 549 }), 550 ], 551 }); 552 engine.hideOneOffButton = false; 553 554 await cleanupPlaces(); 555 await extension.unload(); 556 });