test_weather_keywords.js (16645B)
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 the keywords behavior of quick suggest weather. 6 7 "use strict"; 8 9 add_setup(async () => { 10 await QuickSuggestTestUtils.ensureQuickSuggestInit({ 11 remoteSettingsRecords: [QuickSuggestTestUtils.weatherRecord()], 12 prefs: [ 13 ["suggest.quicksuggest.sponsored", true], 14 ["weather.featureGate", true], 15 ], 16 }); 17 await MerinoTestUtils.initWeather(); 18 }); 19 20 // * Settings data: none 21 // * Nimbus values: none 22 // * Min keyword length pref: none 23 // * Expected: no suggestion 24 add_task(async function () { 25 await doKeywordsTest({ 26 desc: "No data", 27 tests: { 28 "": false, 29 w: false, 30 we: false, 31 wea: false, 32 weat: false, 33 weath: false, 34 weathe: false, 35 weather: false, 36 }, 37 }); 38 }); 39 40 // * Settings data: keywords and min keyword length > 0 41 // * Nimbus values: none 42 // * Min keyword length pref: none 43 // * Expected: use settings data 44 add_task(async function () { 45 await doKeywordsTest({ 46 desc: "Settings only, min keyword length > 0", 47 settingsData: { 48 keywords: ["weather"], 49 min_keyword_length: 3, 50 }, 51 tests: { 52 "": false, 53 w: false, 54 we: false, 55 wea: true, 56 weat: true, 57 weath: true, 58 weathe: true, 59 weather: true, 60 }, 61 }); 62 }); 63 64 // * Settings data: keywords and min keyword length = 0 65 // * Nimbus values: none 66 // * Min keyword length pref: 6 67 // * Expected: no prefix matching because when min keyword length = 0, the Rust 68 // component requires full keywords to be typed 69 add_task(async function () { 70 await doKeywordsTest({ 71 desc: "Settings only, min keyword length = 0, pref exists", 72 settingsData: { 73 keywords: ["weather"], 74 min_keyword_length: 0, 75 }, 76 minKeywordLength: 6, 77 tests: { 78 "": false, 79 w: false, 80 we: false, 81 wea: false, 82 weat: false, 83 weath: false, 84 weathe: false, 85 weather: true, 86 }, 87 }); 88 }); 89 90 // * Settings data: keywords and min keyword length > 0 91 // * Nimbus values: none 92 // * Min keyword length pref: 6 93 // * Expected: use settings keywords and min keyword length pref 94 add_task(async function () { 95 await doKeywordsTest({ 96 desc: "Settings only, min keyword length > 0, pref exists", 97 settingsData: { 98 keywords: ["weather"], 99 min_keyword_length: 3, 100 }, 101 minKeywordLength: 6, 102 tests: { 103 "": false, 104 w: false, 105 we: false, 106 wea: false, 107 weat: false, 108 weath: false, 109 weathe: true, 110 weather: true, 111 }, 112 }); 113 }); 114 115 // * Settings data: keywords and min keyword length > 0 116 // * Nimbus values: min keyword length = 0 117 // * Min keyword length pref: none 118 // * Expected: Settings min keyword length 119 add_task(async function () { 120 await doKeywordsTest({ 121 desc: "Settings: keywords, min keyword length > 0; Nimbus: min keyword length = 0", 122 settingsData: { 123 keywords: ["weather"], 124 min_keyword_length: 3, 125 }, 126 nimbusValues: { 127 weatherKeywordsMinimumLength: 0, 128 }, 129 tests: { 130 "": false, 131 w: false, 132 we: false, 133 wea: true, 134 weat: true, 135 weath: true, 136 weathe: true, 137 weather: true, 138 }, 139 }); 140 }); 141 142 // * Settings data: keywords and min keyword length > 0 143 // * Nimbus values: min keyword length > settings min keyword length 144 // * Min keyword length pref: none 145 // * Expected: Nimbus min keyword length 146 add_task(async function () { 147 await doKeywordsTest({ 148 desc: "Settings: keywords, min keyword length > 0; Nimbus: min keyword length > settings min keyword length", 149 settingsData: { 150 keywords: ["weather"], 151 min_keyword_length: 3, 152 }, 153 nimbusValues: { 154 weatherKeywordsMinimumLength: 4, 155 }, 156 tests: { 157 "": false, 158 w: false, 159 we: false, 160 wea: false, 161 weat: true, 162 weath: true, 163 weathe: true, 164 weather: true, 165 }, 166 }); 167 }); 168 169 // * Settings data: keywords and min keyword length > 0 170 // * Nimbus values: min keyword length = 0 171 // * Min keyword length pref: exists 172 // * Expected: Min keyword length pref 173 add_task(async function () { 174 await doKeywordsTest({ 175 desc: "Settings: keywords, min keyword length > 0; Nimbus: min keyword length = 0; pref exists", 176 settingsData: { 177 keywords: ["weather"], 178 min_keyword_length: 3, 179 }, 180 nimbusValues: { 181 weatherKeywordsMinimumLength: 0, 182 }, 183 minKeywordLength: 6, 184 tests: { 185 "": false, 186 w: false, 187 we: false, 188 wea: false, 189 weat: false, 190 weath: false, 191 weathe: true, 192 weather: true, 193 }, 194 }); 195 }); 196 197 // * Settings data: keywords and min keyword length > 0 198 // * Nimbus values: min keyword length > settings min keyword length 199 // * Min keyword length pref: exists 200 // * Expected: min keyword length pref 201 add_task(async function () { 202 await doKeywordsTest({ 203 desc: "Settings: keywords, min keyword length > 0; Nimbus: min keyword length > settings min keyword length; pref exists", 204 settingsData: { 205 keywords: ["weather"], 206 min_keyword_length: 3, 207 }, 208 nimbusValues: { 209 weatherKeywordsMinimumLength: 4, 210 }, 211 minKeywordLength: 6, 212 tests: { 213 "": false, 214 w: false, 215 we: false, 216 wea: false, 217 weat: false, 218 weath: false, 219 weathe: true, 220 weather: true, 221 }, 222 }); 223 }); 224 225 // * Settings data: keywords only 226 // * Nimbus values: min keyword length = 0 227 // * Min keyword length pref: none 228 // * Expected: Full keywords are required due to the Rust component 229 add_task(async function () { 230 await doKeywordsTest({ 231 desc: "Settings: keywords only; Nimbus: min keyword length = 0", 232 settingsData: { 233 keywords: ["weather"], 234 }, 235 nimbusValues: { 236 weatherKeywordsMinimumLength: 0, 237 }, 238 tests: { 239 "": false, 240 w: false, 241 we: false, 242 wea: false, 243 weat: false, 244 weath: false, 245 weathe: false, 246 weather: true, 247 }, 248 }); 249 }); 250 251 // * Settings data: keywords only 252 // * Nimbus values: min keyword length > 0 253 // * Min keyword length pref: none 254 // * Expected: Full keywords are required due to the Rust component; the Nimbus 255 // min-length check only happens after the Rust component has returned 256 // suggestions 257 add_task(async function () { 258 await doKeywordsTest({ 259 desc: "Settings: keywords only; Nimbus: min keyword length > 0", 260 settingsData: { 261 keywords: ["weather"], 262 }, 263 nimbusValues: { 264 weatherKeywordsMinimumLength: 4, 265 }, 266 tests: { 267 "": false, 268 w: false, 269 we: false, 270 wea: false, 271 weat: false, 272 weath: false, 273 weathe: false, 274 weather: true, 275 }, 276 }); 277 }); 278 279 // * Settings data: keywords only 280 // * Nimbus values: min keyword length = 0 281 // * Min keyword length pref: exists 282 // * Expected: Full keywords are required due to the Rust component; the pref 283 // min-length check only happens after the Rust component has returned 284 // suggestions; full keywords < min length pref are not matched 285 add_task(async function () { 286 await doKeywordsTest({ 287 desc: "Settings: keywords only; Nimbus: min keyword length = 0; pref exists", 288 settingsData: { 289 keywords: ["weather", "wind"], 290 }, 291 nimbusValues: { 292 weatherKeywordsMinimumLength: 0, 293 }, 294 minKeywordLength: 6, 295 tests: { 296 "": false, 297 w: false, 298 we: false, 299 wea: false, 300 weat: false, 301 weath: false, 302 weathe: false, 303 weather: true, 304 wi: false, 305 win: false, 306 wind: false, 307 }, 308 }); 309 }); 310 311 // * Settings data: keywords and min keyword length > 0 312 // * Nimbus values: min keyword length > settings min keyword length 313 // * Min keyword length pref: exists 314 // * Expected: Full keywords are required due to the Rust component; the pref 315 // and Nimbus min-length checks only happens after the Rust component has 316 // returned suggestions; full keywords < min length pref are not matched 317 add_task(async function () { 318 await doKeywordsTest({ 319 desc: "Settings: keywords only; Nimbus: min keyword length > settings min keyword length; pref exists", 320 settingsData: { 321 keywords: ["weather", "wind"], 322 }, 323 nimbusValues: { 324 weatherKeywordsMinimumLength: 4, 325 }, 326 minKeywordLength: 6, 327 tests: { 328 "": false, 329 w: false, 330 we: false, 331 wea: false, 332 weat: false, 333 weath: false, 334 weathe: false, 335 weather: true, 336 wi: false, 337 win: false, 338 wind: false, 339 }, 340 }); 341 }); 342 343 // Leading and trailing spaces should be ignored. 344 add_task(async function leadingAndTrailingSpaces() { 345 await doKeywordsTest({ 346 settingsData: { 347 keywords: ["weather"], 348 min_keyword_length: 3, 349 }, 350 tests: { 351 " wea": true, 352 " wea": true, 353 "wea ": true, 354 "wea ": true, 355 " wea ": true, 356 " weat": true, 357 " weat": true, 358 "weat ": true, 359 "weat ": true, 360 " weat ": true, 361 }, 362 }); 363 }); 364 365 add_task(async function caseInsensitive() { 366 await doKeywordsTest({ 367 desc: "Case insensitive", 368 settingsData: { 369 keywords: ["weather"], 370 min_keyword_length: 3, 371 }, 372 tests: { 373 wea: true, 374 WEA: true, 375 Wea: true, 376 WeA: true, 377 WEATHER: true, 378 Weather: true, 379 WeAtHeR: true, 380 }, 381 }); 382 }); 383 384 async function doKeywordsTest({ 385 desc, 386 tests, 387 nimbusValues = null, 388 settingsData = null, 389 minKeywordLength = undefined, 390 }) { 391 info("Doing keywords test: " + desc); 392 info(JSON.stringify({ nimbusValues, settingsData, minKeywordLength })); 393 394 let cleanup = GeolocationTestUtils.stubGeolocation( 395 GeolocationTestUtils.SAN_FRANCISCO 396 ); 397 398 let nimbusCleanup; 399 if (nimbusValues) { 400 nimbusCleanup = await UrlbarTestUtils.initNimbusFeature(nimbusValues); 401 } 402 403 let records = []; 404 if (settingsData) { 405 records.push(QuickSuggestTestUtils.weatherRecord(settingsData)); 406 } 407 await QuickSuggestTestUtils.setRemoteSettingsRecords(records); 408 409 if (minKeywordLength) { 410 UrlbarPrefs.set("weather.minKeywordLength", minKeywordLength); 411 } 412 413 let expectedResult = QuickSuggestTestUtils.weatherResult(); 414 415 for (let [searchString, expected] of Object.entries(tests)) { 416 info( 417 "Doing keywords test search: " + 418 JSON.stringify({ 419 searchString, 420 expected, 421 }) 422 ); 423 424 await check_results({ 425 context: createContext(searchString, { 426 providers: [UrlbarProviderQuickSuggest.name], 427 isPrivate: false, 428 }), 429 matches: expected ? [expectedResult] : [], 430 }); 431 } 432 433 await nimbusCleanup?.(); 434 435 await QuickSuggestTestUtils.setRemoteSettingsRecords([ 436 QuickSuggestTestUtils.weatherRecord(), 437 ]); 438 439 UrlbarPrefs.clear("weather.minKeywordLength"); 440 441 await cleanup(); 442 } 443 444 // Tests the "Show less frequently" command when no show-less-frequently cap is 445 // defined. 446 add_task(async function () { 447 await doShowLessFrequentlyTest({ 448 desc: "No cap", 449 weather: { 450 keywords: ["forecast"], 451 min_keyword_length: 3, 452 }, 453 tests: [ 454 { 455 input: "for", 456 before: { 457 canShowLessFrequently: true, 458 showLessFrequentlyCount: 0, 459 minKeywordLength: 0, 460 }, 461 after: { 462 canShowLessFrequently: true, 463 showLessFrequentlyCount: 1, 464 minKeywordLength: 4, 465 }, 466 }, 467 { 468 input: "fore", 469 before: { 470 canShowLessFrequently: true, 471 showLessFrequentlyCount: 1, 472 minKeywordLength: 4, 473 }, 474 after: { 475 canShowLessFrequently: true, 476 showLessFrequentlyCount: 2, 477 minKeywordLength: 5, 478 }, 479 }, 480 { 481 input: "forecast", 482 before: { 483 canShowLessFrequently: true, 484 showLessFrequentlyCount: 2, 485 minKeywordLength: 5, 486 }, 487 after: { 488 canShowLessFrequently: true, 489 showLessFrequentlyCount: 3, 490 minKeywordLength: 9, 491 }, 492 }, 493 ], 494 }); 495 }); 496 497 // Tests the "Show less frequently" command when the show-less-frequently cap is 498 // defined in the remote settings config, Nimbus, or both. 499 add_task(async function () { 500 for (let configuration of [null, { show_less_frequently_cap: 3 }]) { 501 for (let nimbusValues of [null, { weatherShowLessFrequentlyCap: 3 }]) { 502 if (!configuration && !nimbusValues) { 503 continue; 504 } 505 await doShowLessFrequentlyTest({ 506 desc: "Cap: " + JSON.stringify({ configuration, nimbusValues }), 507 weather: { 508 keywords: ["forecast"], 509 min_keyword_length: 3, 510 }, 511 configuration, 512 nimbusValues, 513 tests: [ 514 { 515 input: "for", 516 before: { 517 canShowLessFrequently: true, 518 showLessFrequentlyCount: 0, 519 minKeywordLength: 0, 520 }, 521 after: { 522 canShowLessFrequently: true, 523 showLessFrequentlyCount: 1, 524 minKeywordLength: 4, 525 }, 526 }, 527 { 528 input: "fore", 529 before: { 530 canShowLessFrequently: true, 531 showLessFrequentlyCount: 1, 532 minKeywordLength: 4, 533 }, 534 after: { 535 canShowLessFrequently: true, 536 showLessFrequentlyCount: 2, 537 minKeywordLength: 5, 538 }, 539 }, 540 { 541 input: "forecast", 542 before: { 543 canShowLessFrequently: true, 544 showLessFrequentlyCount: 2, 545 minKeywordLength: 5, 546 }, 547 after: { 548 // Shouldn't be able to show less frequently now. 549 canShowLessFrequently: false, 550 showLessFrequentlyCount: 3, 551 minKeywordLength: 9, 552 }, 553 }, 554 ], 555 }); 556 } 557 } 558 }); 559 560 async function doShowLessFrequentlyTest({ 561 desc, 562 tests, 563 weather, 564 configuration = null, 565 nimbusValues = null, 566 }) { 567 info("Doing increment test: " + desc); 568 info(JSON.stringify({ weather, configuration, nimbusValues })); 569 570 let cleanup = GeolocationTestUtils.stubGeolocation( 571 GeolocationTestUtils.SAN_FRANCISCO 572 ); 573 574 let nimbusCleanup; 575 if (nimbusValues) { 576 nimbusCleanup = await UrlbarTestUtils.initNimbusFeature(nimbusValues); 577 } 578 579 let records = [QuickSuggestTestUtils.weatherRecord(weather)]; 580 if (configuration) { 581 records.push({ 582 type: "configuration", 583 configuration, 584 }); 585 } 586 await QuickSuggestTestUtils.setRemoteSettingsRecords(records); 587 588 let feature = QuickSuggest.getFeature("WeatherSuggestions"); 589 let expectedResult = QuickSuggestTestUtils.weatherResult(); 590 591 for (let { input, before, after } of tests) { 592 info("Doing increment test case: " + JSON.stringify({ input })); 593 594 await check_results({ 595 context: createContext(input, { 596 providers: [UrlbarProviderQuickSuggest.name], 597 isPrivate: false, 598 }), 599 matches: [expectedResult], 600 }); 601 602 Assert.equal( 603 UrlbarPrefs.get("weather.minKeywordLength"), 604 before.minKeywordLength, 605 "weather.minKeywordLength before" 606 ); 607 Assert.equal( 608 feature.canShowLessFrequently, 609 before.canShowLessFrequently, 610 "feature.canShowLessFrequently before" 611 ); 612 Assert.equal( 613 feature.showLessFrequentlyCount, 614 before.showLessFrequentlyCount, 615 "feature.showLessFrequentlyCount before" 616 ); 617 618 triggerCommand({ 619 feature, 620 result: expectedResult, 621 command: "show_less_frequently", 622 searchString: input, 623 expectedCountsByCall: { 624 acknowledgeFeedback: 1, 625 invalidateResultMenuCommands: after.canShowLessFrequently ? 0 : 1, 626 }, 627 }); 628 629 Assert.equal( 630 UrlbarPrefs.get("weather.minKeywordLength"), 631 after.minKeywordLength, 632 "weather.minKeywordLength after" 633 ); 634 Assert.equal( 635 feature.canShowLessFrequently, 636 after.canShowLessFrequently, 637 "feature.canShowLessFrequently after" 638 ); 639 Assert.equal( 640 feature.showLessFrequentlyCount, 641 after.showLessFrequentlyCount, 642 "feature.showLessFrequentlyCount after" 643 ); 644 645 await check_results({ 646 context: createContext(input, { 647 providers: [UrlbarProviderQuickSuggest.name], 648 isPrivate: false, 649 }), 650 matches: [], 651 }); 652 } 653 654 await nimbusCleanup?.(); 655 656 await QuickSuggestTestUtils.setRemoteSettingsRecords([ 657 QuickSuggestTestUtils.weatherRecord(), 658 ]); 659 UrlbarPrefs.clear("weather.minKeywordLength"); 660 UrlbarPrefs.clear("weather.showLessFrequentlyCount"); 661 662 await cleanup(); 663 }