summaryrefslogtreecommitdiffstats
path: root/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest_scoreMap.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest_scoreMap.js')
-rw-r--r--browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest_scoreMap.js670
1 files changed, 670 insertions, 0 deletions
diff --git a/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest_scoreMap.js b/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest_scoreMap.js
new file mode 100644
index 0000000000..224dd6cb22
--- /dev/null
+++ b/browser/components/urlbar/tests/quicksuggest/unit/test_quicksuggest_scoreMap.js
@@ -0,0 +1,670 @@
+/* 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 `quickSuggestScoreMap` Nimbus variable that assigns scores to
+// specified types of quick suggest suggestions. The scores in the map should
+// override the scores in the individual suggestion objects so that experiments
+// can fully control the relative ranking of suggestions.
+
+"use strict";
+
+const { DEFAULT_SUGGESTION_SCORE } = UrlbarProviderQuickSuggest;
+
+const REMOTE_SETTINGS_RECORDS = [
+ {
+ type: "data",
+ attachment: [
+ // sponsored without score
+ QuickSuggestTestUtils.ampRemoteSettings({
+ score: undefined,
+ keywords: [
+ "sponsored without score",
+ "sponsored without score, nonsponsored without score",
+ "sponsored without score, nonsponsored with score",
+ "sponsored without score, addon without score",
+ ],
+ url: "https://example.com/sponsored-without-score",
+ title: "Sponsored without score",
+ }),
+ // sponsored with score
+ QuickSuggestTestUtils.ampRemoteSettings({
+ score: 2 * DEFAULT_SUGGESTION_SCORE,
+ keywords: [
+ "sponsored with score",
+ "sponsored with score, nonsponsored without score",
+ "sponsored with score, nonsponsored with score",
+ "sponsored with score, addon with score",
+ ],
+ url: "https://example.com/sponsored-with-score",
+ title: "Sponsored with score",
+ }),
+ // nonsponsored without score
+ QuickSuggestTestUtils.wikipediaRemoteSettings({
+ score: undefined,
+ keywords: [
+ "nonsponsored without score",
+ "sponsored without score, nonsponsored without score",
+ "sponsored with score, nonsponsored without score",
+ ],
+ url: "https://example.com/nonsponsored-without-score",
+ title: "Nonsponsored without score",
+ }),
+ // nonsponsored with score
+ QuickSuggestTestUtils.wikipediaRemoteSettings({
+ score: 2 * DEFAULT_SUGGESTION_SCORE,
+ keywords: [
+ "nonsponsored with score",
+ "sponsored without score, nonsponsored with score",
+ "sponsored with score, nonsponsored with score",
+ ],
+ url: "https://example.com/nonsponsored-with-score",
+ title: "Nonsponsored with score",
+ }),
+ ],
+ },
+ {
+ type: "amo-suggestions",
+ attachment: [
+ // addon with score
+ QuickSuggestTestUtils.amoRemoteSettings({
+ score: 2 * DEFAULT_SUGGESTION_SCORE,
+ keywords: [
+ "addon with score",
+ "sponsored with score, addon with score",
+ ],
+ url: "https://example.com/addon-with-score",
+ title: "Addon with score",
+ }),
+ ],
+ },
+];
+
+const ADM_RECORD = REMOTE_SETTINGS_RECORDS[0];
+const SPONSORED_WITHOUT_SCORE = ADM_RECORD.attachment[0];
+const SPONSORED_WITH_SCORE = ADM_RECORD.attachment[1];
+const NONSPONSORED_WITHOUT_SCORE = ADM_RECORD.attachment[2];
+const NONSPONSORED_WITH_SCORE = ADM_RECORD.attachment[3];
+
+const ADDON_RECORD = REMOTE_SETTINGS_RECORDS[1];
+const ADDON_WITH_SCORE = ADDON_RECORD.attachment[0];
+
+const MERINO_SPONSORED_SUGGESTION = {
+ provider: "adm",
+ score: DEFAULT_SUGGESTION_SCORE,
+ iab_category: "22 - Shopping",
+ is_sponsored: true,
+ keywords: ["test"],
+ full_keyword: "test",
+ block_id: 1,
+ url: "https://example.com/merino-sponsored",
+ title: "Merino sponsored",
+ click_url: "https://example.com/click",
+ impression_url: "https://example.com/impression",
+ advertiser: "TestAdvertiser",
+ icon: "1234",
+};
+
+const MERINO_ADDON_SUGGESTION = {
+ provider: "amo",
+ score: DEFAULT_SUGGESTION_SCORE,
+ keywords: ["test"],
+ icon: "https://example.com/addon.svg",
+ url: "https://example.com/merino-addon",
+ title: "Merino addon",
+ description: "Merino addon",
+ custom_details: {
+ amo: {
+ guid: "merino-addon@example.com",
+ rating: "4.7",
+ number_of_ratings: "1256",
+ },
+ },
+};
+
+const MERINO_UNKNOWN_SUGGESTION = {
+ provider: "some_unknown_provider",
+ score: DEFAULT_SUGGESTION_SCORE,
+ keywords: ["test"],
+ url: "https://example.com/merino-unknown",
+ title: "Merino unknown",
+};
+
+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_RECORDS,
+ merinoSuggestions: [],
+ prefs: [
+ ["suggest.quicksuggest.sponsored", true],
+ ["suggest.quicksuggest.nonsponsored", true],
+ ],
+ });
+});
+
+add_task(async function sponsoredWithout_nonsponsoredWithout_sponsoredWins() {
+ let keyword = "sponsored without score, nonsponsored without score";
+ let score = 10 * DEFAULT_SUGGESTION_SCORE;
+ await doTest({
+ keyword,
+ scoreMap: {
+ adm_sponsored: score,
+ },
+ expectedFeatureName: "AdmWikipedia",
+ expectedScore: score,
+ expectedResult: makeExpectedAdmResult({
+ keyword,
+ suggestion: SPONSORED_WITHOUT_SCORE,
+ }),
+ });
+});
+
+add_task(
+ async function sponsoredWithout_nonsponsoredWithout_nonsponsoredWins() {
+ let keyword = "sponsored without score, nonsponsored without score";
+ let score = 10 * DEFAULT_SUGGESTION_SCORE;
+ await doTest({
+ keyword,
+ scoreMap: {
+ adm_nonsponsored: score,
+ },
+ expectedFeatureName: "AdmWikipedia",
+ expectedScore: score,
+ expectedResult: makeExpectedWikipediaResult({
+ keyword,
+ suggestion: NONSPONSORED_WITHOUT_SCORE,
+ }),
+ });
+ }
+);
+
+add_task(
+ async function sponsoredWithout_nonsponsoredWithout_sponsoredWins_both() {
+ let keyword = "sponsored without score, nonsponsored without score";
+ let score = 10 * DEFAULT_SUGGESTION_SCORE;
+ await doTest({
+ keyword,
+ scoreMap: {
+ adm_sponsored: score,
+ adm_nonsponsored: score / 2,
+ },
+ expectedFeatureName: "AdmWikipedia",
+ expectedScore: score,
+ expectedResult: makeExpectedAdmResult({
+ keyword,
+ suggestion: SPONSORED_WITHOUT_SCORE,
+ }),
+ });
+ }
+);
+
+add_task(
+ async function sponsoredWithout_nonsponsoredWithout_nonsponsoredWins_both() {
+ let keyword = "sponsored without score, nonsponsored without score";
+ let score = 10 * DEFAULT_SUGGESTION_SCORE;
+ await doTest({
+ keyword,
+ scoreMap: {
+ adm_nonsponsored: score,
+ adm_sponsored: score / 2,
+ },
+ expectedFeatureName: "AdmWikipedia",
+ expectedScore: score,
+ expectedResult: makeExpectedWikipediaResult({
+ keyword,
+ suggestion: NONSPONSORED_WITHOUT_SCORE,
+ }),
+ });
+ }
+);
+
+add_task(async function sponsoredWith_nonsponsoredWith_sponsoredWins() {
+ let keyword = "sponsored with score, nonsponsored with score";
+ let score = 10 * DEFAULT_SUGGESTION_SCORE;
+ await doTest({
+ keyword,
+ scoreMap: {
+ adm_sponsored: score,
+ },
+ expectedFeatureName: "AdmWikipedia",
+ expectedScore: score,
+ expectedResult: makeExpectedAdmResult({
+ keyword,
+ suggestion: SPONSORED_WITH_SCORE,
+ }),
+ });
+});
+
+add_task(async function sponsoredWith_nonsponsoredWith_nonsponsoredWins() {
+ let keyword = "sponsored with score, nonsponsored with score";
+ let score = 10 * DEFAULT_SUGGESTION_SCORE;
+ await doTest({
+ keyword,
+ scoreMap: {
+ adm_nonsponsored: score,
+ },
+ expectedFeatureName: "AdmWikipedia",
+ expectedScore: score,
+ expectedResult: makeExpectedWikipediaResult({
+ keyword,
+ suggestion: NONSPONSORED_WITH_SCORE,
+ }),
+ });
+});
+
+add_task(async function sponsoredWith_nonsponsoredWith_sponsoredWins_both() {
+ let keyword = "sponsored with score, nonsponsored with score";
+ let score = 10 * DEFAULT_SUGGESTION_SCORE;
+ await doTest({
+ keyword,
+ scoreMap: {
+ adm_sponsored: score,
+ adm_nonsponsored: score / 2,
+ },
+ expectedFeatureName: "AdmWikipedia",
+ expectedScore: score,
+ expectedResult: makeExpectedAdmResult({
+ keyword,
+ suggestion: SPONSORED_WITH_SCORE,
+ }),
+ });
+});
+
+add_task(async function sponsoredWith_nonsponsoredWith_nonsponsoredWins_both() {
+ let keyword = "sponsored with score, nonsponsored with score";
+ let score = 10 * DEFAULT_SUGGESTION_SCORE;
+ await doTest({
+ keyword,
+ scoreMap: {
+ adm_nonsponsored: score,
+ adm_sponsored: score / 2,
+ },
+ expectedFeatureName: "AdmWikipedia",
+ expectedScore: score,
+ expectedResult: makeExpectedWikipediaResult({
+ keyword,
+ suggestion: NONSPONSORED_WITH_SCORE,
+ }),
+ });
+});
+
+add_task(async function sponsoredWithout_addonWithout_sponsoredWins() {
+ let keyword = "sponsored without score, addon without score";
+ let score = 10 * DEFAULT_SUGGESTION_SCORE;
+ await doTest({
+ keyword,
+ scoreMap: {
+ adm_sponsored: score,
+ },
+ expectedFeatureName: "AdmWikipedia",
+ expectedScore: score,
+ expectedResult: makeExpectedAdmResult({
+ keyword,
+ suggestion: SPONSORED_WITHOUT_SCORE,
+ }),
+ });
+});
+
+add_task(async function sponsoredWithout_addonWithout_sponsoredWins_both() {
+ let keyword = "sponsored without score, addon without score";
+ let score = 10 * DEFAULT_SUGGESTION_SCORE;
+ await doTest({
+ keyword,
+ scoreMap: {
+ adm_sponsored: score,
+ amo: score / 2,
+ },
+ expectedFeatureName: "AdmWikipedia",
+ expectedScore: score,
+ expectedResult: makeExpectedAdmResult({
+ keyword,
+ suggestion: SPONSORED_WITHOUT_SCORE,
+ }),
+ });
+});
+
+add_task(async function sponsoredWith_addonWith_sponsoredWins() {
+ let keyword = "sponsored with score, addon with score";
+ let score = 10 * DEFAULT_SUGGESTION_SCORE;
+ await doTest({
+ keyword,
+ scoreMap: {
+ adm_sponsored: score,
+ },
+ expectedFeatureName: "AdmWikipedia",
+ expectedScore: score,
+ expectedResult: makeExpectedAdmResult({
+ keyword,
+ suggestion: SPONSORED_WITH_SCORE,
+ }),
+ });
+});
+
+add_task(async function sponsoredWith_addonWith_addonWins() {
+ let keyword = "sponsored with score, addon with score";
+ let score = 10 * DEFAULT_SUGGESTION_SCORE;
+ await doTest({
+ keyword,
+ scoreMap: {
+ amo: score,
+ },
+ expectedFeatureName: "AddonSuggestions",
+ expectedScore: score,
+ expectedResult: makeExpectedAddonResult({
+ suggestion: ADDON_WITH_SCORE,
+ }),
+ });
+});
+
+add_task(async function sponsoredWith_addonWith_sponsoredWins_both() {
+ let keyword = "sponsored with score, addon with score";
+ let score = 10 * DEFAULT_SUGGESTION_SCORE;
+ await doTest({
+ keyword,
+ scoreMap: {
+ adm_sponsored: score,
+ amo: score / 2,
+ },
+ expectedFeatureName: "AdmWikipedia",
+ expectedScore: score,
+ expectedResult: makeExpectedAdmResult({
+ keyword,
+ suggestion: SPONSORED_WITH_SCORE,
+ }),
+ });
+});
+
+add_task(async function sponsoredWith_addonWith_addonWins_both() {
+ let keyword = "sponsored with score, addon with score";
+ let score = 10 * DEFAULT_SUGGESTION_SCORE;
+ await doTest({
+ keyword,
+ scoreMap: {
+ amo: score,
+ adm_sponsored: score / 2,
+ },
+ expectedFeatureName: "AddonSuggestions",
+ expectedScore: score,
+ expectedResult: makeExpectedAddonResult({
+ suggestion: ADDON_WITH_SCORE,
+ }),
+ });
+});
+
+add_task(async function merino_sponsored_addon_sponsoredWins() {
+ await QuickSuggestTestUtils.setRemoteSettingsRecords([]);
+
+ MerinoTestUtils.server.response.body.suggestions = [
+ MERINO_SPONSORED_SUGGESTION,
+ MERINO_ADDON_SUGGESTION,
+ ];
+
+ let score = 10 * DEFAULT_SUGGESTION_SCORE;
+ await doTest({
+ keyword: "test",
+ scoreMap: {
+ adm_sponsored: score,
+ },
+ expectedFeatureName: "AdmWikipedia",
+ expectedScore: score,
+ expectedResult: makeExpectedAdmResult({
+ keyword: "test",
+ suggestion: MERINO_SPONSORED_SUGGESTION,
+ source: "merino",
+ provider: "adm",
+ requestId: MerinoTestUtils.server.response.body.request_id,
+ }),
+ });
+
+ await QuickSuggestTestUtils.setRemoteSettingsRecords(REMOTE_SETTINGS_RECORDS);
+});
+
+add_task(async function merino_sponsored_addon_addonWins() {
+ await QuickSuggestTestUtils.setRemoteSettingsRecords([]);
+
+ MerinoTestUtils.server.response.body.suggestions = [
+ MERINO_SPONSORED_SUGGESTION,
+ MERINO_ADDON_SUGGESTION,
+ ];
+
+ let score = 10 * DEFAULT_SUGGESTION_SCORE;
+ await doTest({
+ keyword: "test",
+ scoreMap: {
+ amo: score,
+ },
+ expectedFeatureName: "AddonSuggestions",
+ expectedScore: score,
+ expectedResult: makeExpectedAddonResult({
+ suggestion: MERINO_ADDON_SUGGESTION,
+ source: "merino",
+ provider: "amo",
+ requestId: MerinoTestUtils.server.response.body.request_id,
+ }),
+ });
+
+ await QuickSuggestTestUtils.setRemoteSettingsRecords(REMOTE_SETTINGS_RECORDS);
+});
+
+add_task(async function merino_sponsored_unknown_sponsoredWins() {
+ await QuickSuggestTestUtils.setRemoteSettingsRecords([]);
+
+ MerinoTestUtils.server.response.body.suggestions = [
+ MERINO_SPONSORED_SUGGESTION,
+ MERINO_UNKNOWN_SUGGESTION,
+ ];
+
+ let score = 10 * DEFAULT_SUGGESTION_SCORE;
+ await doTest({
+ keyword: "test",
+ scoreMap: {
+ adm_sponsored: score,
+ },
+ expectedFeatureName: "AdmWikipedia",
+ expectedScore: score,
+ expectedResult: makeExpectedAdmResult({
+ keyword: "test",
+ suggestion: MERINO_SPONSORED_SUGGESTION,
+ source: "merino",
+ provider: "adm",
+ requestId: MerinoTestUtils.server.response.body.request_id,
+ }),
+ });
+
+ await QuickSuggestTestUtils.setRemoteSettingsRecords(REMOTE_SETTINGS_RECORDS);
+});
+
+add_task(async function merino_sponsored_unknown_unknownWins() {
+ await QuickSuggestTestUtils.setRemoteSettingsRecords([]);
+
+ MerinoTestUtils.server.response.body.suggestions = [
+ MERINO_SPONSORED_SUGGESTION,
+ MERINO_UNKNOWN_SUGGESTION,
+ ];
+
+ let score = 10 * DEFAULT_SUGGESTION_SCORE;
+ await doTest({
+ keyword: "test",
+ scoreMap: {
+ [MERINO_UNKNOWN_SUGGESTION.provider]: score,
+ },
+ expectedFeatureName: null,
+ expectedScore: score,
+ expectedResult: makeExpectedDefaultResult({
+ suggestion: MERINO_UNKNOWN_SUGGESTION,
+ }),
+ });
+
+ await QuickSuggestTestUtils.setRemoteSettingsRecords(REMOTE_SETTINGS_RECORDS);
+});
+
+add_task(async function stringValue() {
+ let keyword = "sponsored with score, nonsponsored with score";
+ await doTest({
+ keyword,
+ scoreMap: {
+ adm_sponsored: "123.456",
+ },
+ expectedFeatureName: "AdmWikipedia",
+ expectedScore: 123.456,
+ expectedResult: makeExpectedAdmResult({
+ keyword,
+ suggestion: SPONSORED_WITH_SCORE,
+ }),
+ });
+});
+
+/**
+ * Sets up Nimbus with a `quickSuggestScoreMap` variable value, does a search,
+ * and makes sure the expected result is shown and the expected score is set on
+ * the suggestion.
+ *
+ * @param {object} options
+ * Options object.
+ * @param {string} options.keyword
+ * The search string. This should be equal to a keyword from one or more
+ * suggestions.
+ * @param {object} options.scoreMap
+ * The value to set for the `quickSuggestScoreMap` variable.
+ * @param {string} options.expectedFeatureName
+ * The name of the `BaseFeature` instance that is expected to create the
+ * `UrlbarResult` that's shown. If the suggestion is intentionally from an
+ * unknown Merino provider and therefore the quick suggest provider is
+ * expected to create a default result for it, set this to null.
+ * @param {UrlbarResultstring} options.expectedResult
+ * The `UrlbarResult` that's expected to be shown.
+ * @param {number} options.expectedScore
+ * The final `score` value that's expected to be defined on the suggestion
+ * object.
+ */
+async function doTest({
+ keyword,
+ scoreMap,
+ expectedFeatureName,
+ expectedResult,
+ expectedScore,
+}) {
+ let cleanUpNimbus = await UrlbarTestUtils.initNimbusFeature({
+ quickSuggestScoreMap: scoreMap,
+ });
+
+ // Stub the expected feature's `makeResult()` so we can see the value of the
+ // passed-in suggestion's score. If the suggestion's type is in the score map,
+ // the provider will set its score before calling `makeResult()`.
+ let actualScore;
+ let sandbox;
+ if (expectedFeatureName) {
+ sandbox = sinon.createSandbox();
+ let feature = QuickSuggest.getFeature(expectedFeatureName);
+ let stub = sandbox
+ .stub(feature, "makeResult")
+ .callsFake((queryContext, suggestion, searchString) => {
+ actualScore = suggestion.score;
+ return stub.wrappedMethod.call(
+ feature,
+ queryContext,
+ suggestion,
+ searchString
+ );
+ });
+ }
+
+ await check_results({
+ context: createContext(keyword, {
+ providers: [UrlbarProviderQuickSuggest.name],
+ isPrivate: false,
+ }),
+ matches: [expectedResult],
+ });
+
+ if (expectedFeatureName) {
+ Assert.equal(
+ actualScore,
+ expectedScore,
+ "Suggestion score should be set correctly"
+ );
+ sandbox.restore();
+ }
+
+ await cleanUpNimbus();
+}
+
+function makeExpectedAdmResult({
+ suggestion,
+ keyword,
+ source,
+ provider,
+ requestId,
+}) {
+ return makeAmpResult({
+ keyword,
+ source,
+ provider,
+ requestId,
+ title: suggestion.title,
+ url: suggestion.url,
+ originalUrl: suggestion.url,
+ impressionUrl: suggestion.impression_url,
+ clickUrl: suggestion.click_url,
+ blockId: suggestion.id,
+ advertiser: suggestion.advertiser,
+ icon: suggestion.icon,
+ });
+}
+
+function makeExpectedWikipediaResult({ suggestion, keyword, source }) {
+ return makeWikipediaResult({
+ keyword,
+ source,
+ title: suggestion.title,
+ url: suggestion.url,
+ originalUrl: suggestion.url,
+ impressionUrl: suggestion.impression_url,
+ clickUrl: suggestion.click_url,
+ blockId: suggestion.id,
+ });
+}
+
+function makeExpectedAddonResult({ suggestion, source, provider }) {
+ return makeAmoResult({
+ source,
+ provider,
+ title: suggestion.title,
+ description: suggestion.description,
+ url: suggestion.url,
+ originalUrl: suggestion.url,
+ icon: suggestion.icon,
+ });
+}
+
+function makeExpectedDefaultResult({ suggestion }) {
+ return {
+ type: UrlbarUtils.RESULT_TYPE.URL,
+ source: UrlbarUtils.RESULT_SOURCE.SEARCH,
+ heuristic: false,
+ payload: {
+ source: "merino",
+ provider: suggestion.provider,
+ telemetryType: suggestion.provider,
+ isSponsored: suggestion.is_sponsored,
+ title: suggestion.title,
+ url: suggestion.url,
+ displayUrl: suggestion.url.replace(/^https:\/\//, ""),
+ icon: suggestion.icon,
+ descriptionL10n: suggestion.is_sponsored
+ ? { id: "urlbar-result-action-sponsored" }
+ : undefined,
+ shouldShowUrl: true,
+ helpUrl: QuickSuggest.HELP_URL,
+ helpL10n: {
+ id: "urlbar-result-menu-learn-more-about-firefox-suggest",
+ },
+ isBlockable: true,
+ blockL10n: {
+ id: "urlbar-result-menu-dismiss-firefox-suggest",
+ },
+ },
+ };
+}