/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // Tests the keywords behavior of quick suggest weather. "use strict"; add_setup(async () => { await QuickSuggestTestUtils.ensureQuickSuggestInit({ remoteSettingsRecords: [QuickSuggestTestUtils.weatherRecord()], prefs: [ ["suggest.quicksuggest.sponsored", true], ["weather.featureGate", true], ], }); await MerinoTestUtils.initWeather(); }); // * Settings data: none // * Nimbus values: none // * Min keyword length pref: none // * Expected: no suggestion add_task(async function () { await doKeywordsTest({ desc: "No data", tests: { "": false, w: false, we: false, wea: false, weat: false, weath: false, weathe: false, weather: false, }, }); }); // * Settings data: keywords and min keyword length > 0 // * Nimbus values: none // * Min keyword length pref: none // * Expected: use settings data add_task(async function () { await doKeywordsTest({ desc: "Settings only, min keyword length > 0", settingsData: { keywords: ["weather"], min_keyword_length: 3, }, tests: { "": false, w: false, we: false, wea: true, weat: true, weath: true, weathe: true, weather: true, }, }); }); // * Settings data: keywords and min keyword length = 0 // * Nimbus values: none // * Min keyword length pref: 6 // * Expected: no prefix matching because when min keyword length = 0, the Rust // component requires full keywords to be typed add_task(async function () { await doKeywordsTest({ desc: "Settings only, min keyword length = 0, pref exists", settingsData: { keywords: ["weather"], min_keyword_length: 0, }, minKeywordLength: 6, tests: { "": false, w: false, we: false, wea: false, weat: false, weath: false, weathe: false, weather: true, }, }); }); // * Settings data: keywords and min keyword length > 0 // * Nimbus values: none // * Min keyword length pref: 6 // * Expected: use settings keywords and min keyword length pref add_task(async function () { await doKeywordsTest({ desc: "Settings only, min keyword length > 0, pref exists", settingsData: { keywords: ["weather"], min_keyword_length: 3, }, minKeywordLength: 6, tests: { "": false, w: false, we: false, wea: false, weat: false, weath: false, weathe: true, weather: true, }, }); }); // * Settings data: keywords and min keyword length > 0 // * Nimbus values: min keyword length = 0 // * Min keyword length pref: none // * Expected: Settings min keyword length add_task(async function () { await doKeywordsTest({ desc: "Settings: keywords, min keyword length > 0; Nimbus: min keyword length = 0", settingsData: { keywords: ["weather"], min_keyword_length: 3, }, nimbusValues: { weatherKeywordsMinimumLength: 0, }, tests: { "": false, w: false, we: false, wea: true, weat: true, weath: true, weathe: true, weather: true, }, }); }); // * Settings data: keywords and min keyword length > 0 // * Nimbus values: min keyword length > settings min keyword length // * Min keyword length pref: none // * Expected: Nimbus min keyword length add_task(async function () { await doKeywordsTest({ desc: "Settings: keywords, min keyword length > 0; Nimbus: min keyword length > settings min keyword length", settingsData: { keywords: ["weather"], min_keyword_length: 3, }, nimbusValues: { weatherKeywordsMinimumLength: 4, }, tests: { "": false, w: false, we: false, wea: false, weat: true, weath: true, weathe: true, weather: true, }, }); }); // * Settings data: keywords and min keyword length > 0 // * Nimbus values: min keyword length = 0 // * Min keyword length pref: exists // * Expected: Min keyword length pref add_task(async function () { await doKeywordsTest({ desc: "Settings: keywords, min keyword length > 0; Nimbus: min keyword length = 0; pref exists", settingsData: { keywords: ["weather"], min_keyword_length: 3, }, nimbusValues: { weatherKeywordsMinimumLength: 0, }, minKeywordLength: 6, tests: { "": false, w: false, we: false, wea: false, weat: false, weath: false, weathe: true, weather: true, }, }); }); // * Settings data: keywords and min keyword length > 0 // * Nimbus values: min keyword length > settings min keyword length // * Min keyword length pref: exists // * Expected: min keyword length pref add_task(async function () { await doKeywordsTest({ desc: "Settings: keywords, min keyword length > 0; Nimbus: min keyword length > settings min keyword length; pref exists", settingsData: { keywords: ["weather"], min_keyword_length: 3, }, nimbusValues: { weatherKeywordsMinimumLength: 4, }, minKeywordLength: 6, tests: { "": false, w: false, we: false, wea: false, weat: false, weath: false, weathe: true, weather: true, }, }); }); // * Settings data: keywords only // * Nimbus values: min keyword length = 0 // * Min keyword length pref: none // * Expected: Full keywords are required due to the Rust component add_task(async function () { await doKeywordsTest({ desc: "Settings: keywords only; Nimbus: min keyword length = 0", settingsData: { keywords: ["weather"], }, nimbusValues: { weatherKeywordsMinimumLength: 0, }, tests: { "": false, w: false, we: false, wea: false, weat: false, weath: false, weathe: false, weather: true, }, }); }); // * Settings data: keywords only // * Nimbus values: min keyword length > 0 // * Min keyword length pref: none // * Expected: Full keywords are required due to the Rust component; the Nimbus // min-length check only happens after the Rust component has returned // suggestions add_task(async function () { await doKeywordsTest({ desc: "Settings: keywords only; Nimbus: min keyword length > 0", settingsData: { keywords: ["weather"], }, nimbusValues: { weatherKeywordsMinimumLength: 4, }, tests: { "": false, w: false, we: false, wea: false, weat: false, weath: false, weathe: false, weather: true, }, }); }); // * Settings data: keywords only // * Nimbus values: min keyword length = 0 // * Min keyword length pref: exists // * Expected: Full keywords are required due to the Rust component; the pref // min-length check only happens after the Rust component has returned // suggestions; full keywords < min length pref are not matched add_task(async function () { await doKeywordsTest({ desc: "Settings: keywords only; Nimbus: min keyword length = 0; pref exists", settingsData: { keywords: ["weather", "wind"], }, nimbusValues: { weatherKeywordsMinimumLength: 0, }, minKeywordLength: 6, tests: { "": false, w: false, we: false, wea: false, weat: false, weath: false, weathe: false, weather: true, wi: false, win: false, wind: false, }, }); }); // * Settings data: keywords and min keyword length > 0 // * Nimbus values: min keyword length > settings min keyword length // * Min keyword length pref: exists // * Expected: Full keywords are required due to the Rust component; the pref // and Nimbus min-length checks only happens after the Rust component has // returned suggestions; full keywords < min length pref are not matched add_task(async function () { await doKeywordsTest({ desc: "Settings: keywords only; Nimbus: min keyword length > settings min keyword length; pref exists", settingsData: { keywords: ["weather", "wind"], }, nimbusValues: { weatherKeywordsMinimumLength: 4, }, minKeywordLength: 6, tests: { "": false, w: false, we: false, wea: false, weat: false, weath: false, weathe: false, weather: true, wi: false, win: false, wind: false, }, }); }); // Leading and trailing spaces should be ignored. add_task(async function leadingAndTrailingSpaces() { await doKeywordsTest({ settingsData: { keywords: ["weather"], min_keyword_length: 3, }, tests: { " wea": true, " wea": true, "wea ": true, "wea ": true, " wea ": true, " weat": true, " weat": true, "weat ": true, "weat ": true, " weat ": true, }, }); }); add_task(async function caseInsensitive() { await doKeywordsTest({ desc: "Case insensitive", settingsData: { keywords: ["weather"], min_keyword_length: 3, }, tests: { wea: true, WEA: true, Wea: true, WeA: true, WEATHER: true, Weather: true, WeAtHeR: true, }, }); }); async function doKeywordsTest({ desc, tests, nimbusValues = null, settingsData = null, minKeywordLength = undefined, }) { info("Doing keywords test: " + desc); info(JSON.stringify({ nimbusValues, settingsData, minKeywordLength })); let cleanup = GeolocationTestUtils.stubGeolocation( GeolocationTestUtils.SAN_FRANCISCO ); let nimbusCleanup; if (nimbusValues) { nimbusCleanup = await UrlbarTestUtils.initNimbusFeature(nimbusValues); } let records = []; if (settingsData) { records.push(QuickSuggestTestUtils.weatherRecord(settingsData)); } await QuickSuggestTestUtils.setRemoteSettingsRecords(records); if (minKeywordLength) { UrlbarPrefs.set("weather.minKeywordLength", minKeywordLength); } let expectedResult = QuickSuggestTestUtils.weatherResult(); for (let [searchString, expected] of Object.entries(tests)) { info( "Doing keywords test search: " + JSON.stringify({ searchString, expected, }) ); await check_results({ context: createContext(searchString, { providers: [UrlbarProviderQuickSuggest.name], isPrivate: false, }), matches: expected ? [expectedResult] : [], }); } await nimbusCleanup?.(); await QuickSuggestTestUtils.setRemoteSettingsRecords([ QuickSuggestTestUtils.weatherRecord(), ]); UrlbarPrefs.clear("weather.minKeywordLength"); await cleanup(); } // Tests the "Show less frequently" command when no show-less-frequently cap is // defined. add_task(async function () { await doShowLessFrequentlyTest({ desc: "No cap", weather: { keywords: ["forecast"], min_keyword_length: 3, }, tests: [ { input: "for", before: { canShowLessFrequently: true, showLessFrequentlyCount: 0, minKeywordLength: 0, }, after: { canShowLessFrequently: true, showLessFrequentlyCount: 1, minKeywordLength: 4, }, }, { input: "fore", before: { canShowLessFrequently: true, showLessFrequentlyCount: 1, minKeywordLength: 4, }, after: { canShowLessFrequently: true, showLessFrequentlyCount: 2, minKeywordLength: 5, }, }, { input: "forecast", before: { canShowLessFrequently: true, showLessFrequentlyCount: 2, minKeywordLength: 5, }, after: { canShowLessFrequently: true, showLessFrequentlyCount: 3, minKeywordLength: 9, }, }, ], }); }); // Tests the "Show less frequently" command when the show-less-frequently cap is // defined in the remote settings config, Nimbus, or both. add_task(async function () { for (let configuration of [null, { show_less_frequently_cap: 3 }]) { for (let nimbusValues of [null, { weatherShowLessFrequentlyCap: 3 }]) { if (!configuration && !nimbusValues) { continue; } await doShowLessFrequentlyTest({ desc: "Cap: " + JSON.stringify({ configuration, nimbusValues }), weather: { keywords: ["forecast"], min_keyword_length: 3, }, configuration, nimbusValues, tests: [ { input: "for", before: { canShowLessFrequently: true, showLessFrequentlyCount: 0, minKeywordLength: 0, }, after: { canShowLessFrequently: true, showLessFrequentlyCount: 1, minKeywordLength: 4, }, }, { input: "fore", before: { canShowLessFrequently: true, showLessFrequentlyCount: 1, minKeywordLength: 4, }, after: { canShowLessFrequently: true, showLessFrequentlyCount: 2, minKeywordLength: 5, }, }, { input: "forecast", before: { canShowLessFrequently: true, showLessFrequentlyCount: 2, minKeywordLength: 5, }, after: { // Shouldn't be able to show less frequently now. canShowLessFrequently: false, showLessFrequentlyCount: 3, minKeywordLength: 9, }, }, ], }); } } }); async function doShowLessFrequentlyTest({ desc, tests, weather, configuration = null, nimbusValues = null, }) { info("Doing increment test: " + desc); info(JSON.stringify({ weather, configuration, nimbusValues })); let cleanup = GeolocationTestUtils.stubGeolocation( GeolocationTestUtils.SAN_FRANCISCO ); let nimbusCleanup; if (nimbusValues) { nimbusCleanup = await UrlbarTestUtils.initNimbusFeature(nimbusValues); } let records = [QuickSuggestTestUtils.weatherRecord(weather)]; if (configuration) { records.push({ type: "configuration", configuration, }); } await QuickSuggestTestUtils.setRemoteSettingsRecords(records); let feature = QuickSuggest.getFeature("WeatherSuggestions"); let expectedResult = QuickSuggestTestUtils.weatherResult(); for (let { input, before, after } of tests) { info("Doing increment test case: " + JSON.stringify({ input })); await check_results({ context: createContext(input, { providers: [UrlbarProviderQuickSuggest.name], isPrivate: false, }), matches: [expectedResult], }); Assert.equal( UrlbarPrefs.get("weather.minKeywordLength"), before.minKeywordLength, "weather.minKeywordLength before" ); Assert.equal( feature.canShowLessFrequently, before.canShowLessFrequently, "feature.canShowLessFrequently before" ); Assert.equal( feature.showLessFrequentlyCount, before.showLessFrequentlyCount, "feature.showLessFrequentlyCount before" ); triggerCommand({ feature, result: expectedResult, command: "show_less_frequently", searchString: input, expectedCountsByCall: { acknowledgeFeedback: 1, invalidateResultMenuCommands: after.canShowLessFrequently ? 0 : 1, }, }); Assert.equal( UrlbarPrefs.get("weather.minKeywordLength"), after.minKeywordLength, "weather.minKeywordLength after" ); Assert.equal( feature.canShowLessFrequently, after.canShowLessFrequently, "feature.canShowLessFrequently after" ); Assert.equal( feature.showLessFrequentlyCount, after.showLessFrequentlyCount, "feature.showLessFrequentlyCount after" ); await check_results({ context: createContext(input, { providers: [UrlbarProviderQuickSuggest.name], isPrivate: false, }), matches: [], }); } await nimbusCleanup?.(); await QuickSuggestTestUtils.setRemoteSettingsRecords([ QuickSuggestTestUtils.weatherRecord(), ]); UrlbarPrefs.clear("weather.minKeywordLength"); UrlbarPrefs.clear("weather.showLessFrequentlyCount"); await cleanup(); }