summaryrefslogtreecommitdiffstats
path: root/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest_addons.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest_addons.js')
-rw-r--r--browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest_addons.js558
1 files changed, 558 insertions, 0 deletions
diff --git a/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest_addons.js b/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest_addons.js
new file mode 100644
index 0000000000..c17f3f1655
--- /dev/null
+++ b/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest_addons.js
@@ -0,0 +1,558 @@
+/* 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 addon quick suggest results.
+
+"use strict";
+
+ChromeUtils.defineESModuleGetters(this, {
+ AddonManager: "resource://gre/modules/AddonManager.sys.mjs",
+ ExtensionTestCommon: "resource://testing-common/ExtensionTestCommon.sys.mjs",
+});
+
+// TODO: Firefox no longer uses `rating` and `number_of_ratings` but they are
+// still present in Merino and RS suggestions, so they are included here for
+// greater accuracy. We should remove them from Merino, RS, and tests.
+const MERINO_SUGGESTIONS = [
+ {
+ provider: "amo",
+ icon: "icon",
+ url: "https://example.com/merino-addon",
+ title: "title",
+ description: "description",
+ is_top_pick: true,
+ custom_details: {
+ amo: {
+ rating: "5",
+ number_of_ratings: "1234567",
+ guid: "test@addon",
+ },
+ },
+ },
+];
+
+const REMOTE_SETTINGS_RESULTS = [
+ {
+ type: "amo-suggestions",
+ attachment: [
+ {
+ url: "https://example.com/first-addon",
+ guid: "first@addon",
+ icon: "https://example.com/first-addon.svg",
+ title: "First Addon",
+ rating: "4.7",
+ keywords: ["first", "1st", "two words", "a b c"],
+ description: "Description for the First Addon",
+ number_of_ratings: 1256,
+ score: 0.25,
+ },
+ {
+ url: "https://example.com/second-addon",
+ guid: "second@addon",
+ icon: "https://example.com/second-addon.svg",
+ title: "Second Addon",
+ rating: "1.7",
+ keywords: ["second", "2nd"],
+ description: "Description for the Second Addon",
+ number_of_ratings: 256,
+ score: 0.25,
+ },
+ {
+ url: "https://example.com/third-addon",
+ guid: "third@addon",
+ icon: "https://example.com/third-addon.svg",
+ title: "Third Addon",
+ rating: "3.7",
+ keywords: ["third", "3rd"],
+ description: "Description for the Third Addon",
+ number_of_ratings: 3,
+ score: 0.25,
+ },
+ {
+ url: "https://example.com/fourth-addon?utm_medium=aaa&utm_source=bbb",
+ guid: "fourth@addon",
+ icon: "https://example.com/fourth-addon.svg",
+ title: "Fourth Addon",
+ rating: "4.7",
+ keywords: ["fourth", "4th"],
+ description: "Description for the Fourth Addon",
+ number_of_ratings: 4,
+ score: 0.25,
+ },
+ ],
+ },
+];
+
+add_setup(async function init() {
+ // Disable search suggestions so we don't hit the network.
+ Services.prefs.setBoolPref("browser.search.suggest.enabled", false);
+
+ await QuickSuggestTestUtils.ensureQuickSuggestInit({
+ remoteSettingsRecords: REMOTE_SETTINGS_RESULTS,
+ merinoSuggestions: MERINO_SUGGESTIONS,
+ prefs: [["suggest.quicksuggest.nonsponsored", true]],
+ });
+});
+
+add_task(async function telemetryType() {
+ Assert.equal(
+ QuickSuggest.getFeature("AddonSuggestions").getSuggestionTelemetryType({}),
+ "amo",
+ "Telemetry type should be 'amo'"
+ );
+});
+
+// When quick suggest prefs are disabled, addon suggestions should be disabled.
+add_tasks_with_rust(async function quickSuggestPrefsDisabled() {
+ let prefs = ["quicksuggest.enabled", "suggest.quicksuggest.nonsponsored"];
+ for (let pref of prefs) {
+ // Before disabling the pref, first make sure the suggestion is added.
+ await check_results({
+ context: createContext("test", {
+ providers: [UrlbarProviderQuickSuggest.name],
+ isPrivate: false,
+ }),
+ matches: [
+ makeExpectedResult({
+ suggestion: MERINO_SUGGESTIONS[0],
+ source: "merino",
+ }),
+ ],
+ });
+
+ // Now disable the pref.
+ UrlbarPrefs.set(pref, false);
+ await check_results({
+ context: createContext("test", {
+ providers: [UrlbarProviderQuickSuggest.name],
+ isPrivate: false,
+ }),
+ matches: [],
+ });
+
+ UrlbarPrefs.set(pref, true);
+ await QuickSuggestTestUtils.forceSync();
+ }
+});
+
+// When addon suggestions specific preference is disabled, addon suggestions
+// should not be added.
+add_tasks_with_rust(async function addonSuggestionsSpecificPrefDisabled() {
+ const prefs = ["suggest.addons", "addons.featureGate"];
+ for (const pref of prefs) {
+ // First make sure the suggestion is added.
+ await check_results({
+ context: createContext("test", {
+ providers: [UrlbarProviderQuickSuggest.name],
+ isPrivate: false,
+ }),
+ matches: [
+ makeExpectedResult({
+ suggestion: MERINO_SUGGESTIONS[0],
+ source: "merino",
+ }),
+ ],
+ });
+
+ // Now disable the pref.
+ UrlbarPrefs.set(pref, false);
+ await check_results({
+ context: createContext("test", {
+ providers: [UrlbarProviderQuickSuggest.name],
+ isPrivate: false,
+ }),
+ matches: [],
+ });
+
+ // Revert.
+ UrlbarPrefs.clear(pref);
+ await QuickSuggestTestUtils.forceSync();
+ }
+});
+
+// Check wheather the addon suggestions will be shown by the setup of Nimbus
+// variable.
+add_tasks_with_rust(async function nimbus() {
+ // Disable the fature gate.
+ UrlbarPrefs.set("addons.featureGate", false);
+ await check_results({
+ context: createContext("test", {
+ providers: [UrlbarProviderQuickSuggest.name],
+ isPrivate: false,
+ }),
+ matches: [],
+ });
+
+ // Enable by Nimbus.
+ const cleanUpNimbusEnable = await UrlbarTestUtils.initNimbusFeature({
+ addonsFeatureGate: true,
+ });
+ await QuickSuggestTestUtils.forceSync();
+ await check_results({
+ context: createContext("test", {
+ providers: [UrlbarProviderQuickSuggest.name],
+ isPrivate: false,
+ }),
+ matches: [
+ makeExpectedResult({
+ suggestion: MERINO_SUGGESTIONS[0],
+ source: "merino",
+ }),
+ ],
+ });
+ await cleanUpNimbusEnable();
+
+ // Enable locally.
+ UrlbarPrefs.set("addons.featureGate", true);
+ await QuickSuggestTestUtils.forceSync();
+
+ // Disable by Nimbus.
+ const cleanUpNimbusDisable = await UrlbarTestUtils.initNimbusFeature({
+ addonsFeatureGate: false,
+ });
+ await check_results({
+ context: createContext("test", {
+ providers: [UrlbarProviderQuickSuggest.name],
+ isPrivate: false,
+ }),
+ matches: [],
+ });
+ await cleanUpNimbusDisable();
+
+ // Revert.
+ UrlbarPrefs.clear("addons.featureGate");
+ await QuickSuggestTestUtils.forceSync();
+});
+
+add_tasks_with_rust(async function hideIfAlreadyInstalled() {
+ // Show suggestion.
+ await check_results({
+ context: createContext("test", {
+ providers: [UrlbarProviderQuickSuggest.name],
+ isPrivate: false,
+ }),
+ matches: [
+ makeExpectedResult({
+ suggestion: MERINO_SUGGESTIONS[0],
+ source: "merino",
+ }),
+ ],
+ });
+
+ // Install an addon for the suggestion.
+ const xpi = ExtensionTestCommon.generateXPI({
+ manifest: {
+ browser_specific_settings: {
+ gecko: { id: "test@addon" },
+ },
+ },
+ });
+ const addon = await AddonManager.installTemporaryAddon(xpi);
+
+ // Show suggestion for the addon installed.
+ await check_results({
+ context: createContext("test", {
+ providers: [UrlbarProviderQuickSuggest.name],
+ isPrivate: false,
+ }),
+ matches: [],
+ });
+
+ await addon.uninstall();
+ xpi.remove(false);
+});
+
+add_tasks_with_rust(async function remoteSettings() {
+ const testCases = [
+ {
+ input: "f",
+ expected: null,
+ },
+ {
+ input: "fi",
+ expected: null,
+ },
+ {
+ input: "fir",
+ expected: null,
+ },
+ {
+ input: "firs",
+ expected: null,
+ },
+ {
+ input: "first",
+ expected: makeExpectedResult({
+ suggestion: REMOTE_SETTINGS_RESULTS[0].attachment[0],
+ source: "remote-settings",
+ }),
+ },
+ {
+ input: "1st",
+ expected: makeExpectedResult({
+ suggestion: REMOTE_SETTINGS_RESULTS[0].attachment[0],
+ source: "remote-settings",
+ }),
+ },
+ {
+ input: "t",
+ expected: null,
+ },
+ {
+ input: "tw",
+ expected: null,
+ },
+ {
+ input: "two",
+ expected: makeExpectedResult({
+ suggestion: REMOTE_SETTINGS_RESULTS[0].attachment[0],
+ source: "remote-settings",
+ }),
+ },
+ {
+ input: "two ",
+ expected: makeExpectedResult({
+ suggestion: REMOTE_SETTINGS_RESULTS[0].attachment[0],
+ source: "remote-settings",
+ }),
+ },
+ {
+ input: "two w",
+ expected: makeExpectedResult({
+ suggestion: REMOTE_SETTINGS_RESULTS[0].attachment[0],
+ source: "remote-settings",
+ }),
+ },
+ {
+ input: "two wo",
+ expected: makeExpectedResult({
+ suggestion: REMOTE_SETTINGS_RESULTS[0].attachment[0],
+ source: "remote-settings",
+ }),
+ },
+ {
+ input: "two wor",
+ expected: makeExpectedResult({
+ suggestion: REMOTE_SETTINGS_RESULTS[0].attachment[0],
+ source: "remote-settings",
+ }),
+ },
+ {
+ input: "two word",
+ expected: makeExpectedResult({
+ suggestion: REMOTE_SETTINGS_RESULTS[0].attachment[0],
+ source: "remote-settings",
+ }),
+ },
+ {
+ input: "two words",
+ expected: makeExpectedResult({
+ suggestion: REMOTE_SETTINGS_RESULTS[0].attachment[0],
+ source: "remote-settings",
+ }),
+ },
+ {
+ input: "a",
+ expected: makeExpectedResult({
+ suggestion: REMOTE_SETTINGS_RESULTS[0].attachment[0],
+ source: "remote-settings",
+ }),
+ },
+ {
+ input: "a ",
+ expected: makeExpectedResult({
+ suggestion: REMOTE_SETTINGS_RESULTS[0].attachment[0],
+ source: "remote-settings",
+ }),
+ },
+ {
+ input: "a b",
+ expected: makeExpectedResult({
+ suggestion: REMOTE_SETTINGS_RESULTS[0].attachment[0],
+ source: "remote-settings",
+ }),
+ },
+ {
+ input: "a b ",
+ expected: makeExpectedResult({
+ suggestion: REMOTE_SETTINGS_RESULTS[0].attachment[0],
+ source: "remote-settings",
+ }),
+ },
+ {
+ input: "a b c",
+ expected: makeExpectedResult({
+ suggestion: REMOTE_SETTINGS_RESULTS[0].attachment[0],
+ source: "remote-settings",
+ }),
+ },
+ {
+ input: "second",
+ expected: makeExpectedResult({
+ suggestion: REMOTE_SETTINGS_RESULTS[0].attachment[1],
+ source: "remote-settings",
+ }),
+ },
+ {
+ input: "2nd",
+ expected: makeExpectedResult({
+ suggestion: REMOTE_SETTINGS_RESULTS[0].attachment[1],
+ source: "remote-settings",
+ }),
+ },
+ {
+ input: "third",
+ expected: makeExpectedResult({
+ suggestion: REMOTE_SETTINGS_RESULTS[0].attachment[2],
+ source: "remote-settings",
+ }),
+ },
+ {
+ input: "3rd",
+ expected: makeExpectedResult({
+ suggestion: REMOTE_SETTINGS_RESULTS[0].attachment[2],
+ source: "remote-settings",
+ }),
+ },
+ {
+ input: "fourth",
+ expected: makeExpectedResult({
+ suggestion: REMOTE_SETTINGS_RESULTS[0].attachment[3],
+ source: "remote-settings",
+ setUtmParams: false,
+ }),
+ },
+ {
+ input: "FoUrTh",
+ expected: makeExpectedResult({
+ suggestion: REMOTE_SETTINGS_RESULTS[0].attachment[3],
+ source: "remote-settings",
+ setUtmParams: false,
+ }),
+ },
+ ];
+
+ // Disable Merino so we trigger only remote settings suggestions.
+ UrlbarPrefs.set("quicksuggest.dataCollection.enabled", false);
+
+ for (let { input, expected } of testCases) {
+ await check_results({
+ context: createContext(input, {
+ providers: [UrlbarProviderQuickSuggest.name],
+ isPrivate: false,
+ }),
+ matches: expected ? [expected] : [],
+ });
+ }
+
+ UrlbarPrefs.set("quicksuggest.dataCollection.enabled", true);
+});
+
+add_task(async function merinoIsTopPick() {
+ const suggestion = JSON.parse(JSON.stringify(MERINO_SUGGESTIONS[0]));
+
+ // is_top_pick is specified as false.
+ suggestion.is_top_pick = false;
+ MerinoTestUtils.server.response.body.suggestions = [suggestion];
+ await check_results({
+ context: createContext("test", {
+ providers: [UrlbarProviderQuickSuggest.name],
+ isPrivate: false,
+ }),
+ matches: [
+ makeExpectedResult({
+ suggestion,
+ source: "merino",
+ }),
+ ],
+ });
+
+ // is_top_pick is undefined.
+ delete suggestion.is_top_pick;
+ MerinoTestUtils.server.response.body.suggestions = [suggestion];
+ await check_results({
+ context: createContext("test", {
+ providers: [UrlbarProviderQuickSuggest.name],
+ isPrivate: false,
+ }),
+ matches: [
+ makeExpectedResult({
+ suggestion,
+ source: "merino",
+ }),
+ ],
+ });
+});
+
+// Tests the "show less frequently" behavior.
+add_tasks_with_rust(async function showLessFrequently() {
+ await doShowLessFrequentlyTests({
+ feature: QuickSuggest.getFeature("AddonSuggestions"),
+ showLessFrequentlyCountPref: "addons.showLessFrequentlyCount",
+ nimbusCapVariable: "addonsShowLessFrequentlyCap",
+ expectedResult: makeExpectedResult({
+ suggestion: REMOTE_SETTINGS_RESULTS[0].attachment[0],
+ source: "remote-settings",
+ }),
+ keyword: "two words",
+ });
+});
+
+// The `Amo` Rust provider should be passed to the Rust component when querying
+// depending on whether addon suggestions are enabled.
+add_task(async function rustProviders() {
+ await doRustProvidersTests({
+ searchString: "first",
+ tests: [
+ {
+ prefs: {
+ "suggest.addons": true,
+ },
+ expectedUrls: ["https://example.com/first-addon"],
+ },
+ {
+ prefs: {
+ "suggest.addons": false,
+ },
+ expectedUrls: [],
+ },
+ ],
+ });
+
+ UrlbarPrefs.clear("suggest.addons");
+ await QuickSuggestTestUtils.forceSync();
+});
+
+function makeExpectedResult({ suggestion, source, setUtmParams = true }) {
+ if (
+ source == "remote-settings" &&
+ UrlbarPrefs.get("quicksuggest.rustEnabled")
+ ) {
+ source = "rust";
+ }
+
+ let provider;
+ switch (source) {
+ case "remote-settings":
+ provider = "AddonSuggestions";
+ break;
+ case "rust":
+ provider = "Amo";
+ break;
+ case "merino":
+ provider = "amo";
+ break;
+ }
+
+ return makeAmoResult({
+ source,
+ provider,
+ setUtmParams,
+ title: suggestion.title,
+ description: suggestion.description,
+ url: suggestion.url,
+ originalUrl: suggestion.url,
+ icon: suggestion.icon,
+ });
+}