summaryrefslogtreecommitdiffstats
path: root/toolkit/components/search/tests/xpcshell/searchconfigs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
commit6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /toolkit/components/search/tests/xpcshell/searchconfigs
parentInitial commit. (diff)
downloadthunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz
thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/components/search/tests/xpcshell/searchconfigs')
-rw-r--r--toolkit/components/search/tests/xpcshell/searchconfigs/head_searchconfig.js614
-rw-r--r--toolkit/components/search/tests/xpcshell/searchconfigs/test_amazon.js361
-rw-r--r--toolkit/components/search/tests/xpcshell/searchconfigs/test_baidu.js43
-rw-r--r--toolkit/components/search/tests/xpcshell/searchconfigs/test_bing.js133
-rw-r--r--toolkit/components/search/tests/xpcshell/searchconfigs/test_distributions.js346
-rw-r--r--toolkit/components/search/tests/xpcshell/searchconfigs/test_duckduckgo.js35
-rw-r--r--toolkit/components/search/tests/xpcshell/searchconfigs/test_ebay.js290
-rw-r--r--toolkit/components/search/tests/xpcshell/searchconfigs/test_ecosia.js37
-rw-r--r--toolkit/components/search/tests/xpcshell/searchconfigs/test_google.js173
-rw-r--r--toolkit/components/search/tests/xpcshell/searchconfigs/test_mailru.js38
-rw-r--r--toolkit/components/search/tests/xpcshell/searchconfigs/test_qwant.js38
-rw-r--r--toolkit/components/search/tests/xpcshell/searchconfigs/test_rakuten.js37
-rw-r--r--toolkit/components/search/tests/xpcshell/searchconfigs/test_selector_db_out_of_date.js58
-rw-r--r--toolkit/components/search/tests/xpcshell/searchconfigs/test_yahoojp.js38
-rw-r--r--toolkit/components/search/tests/xpcshell/searchconfigs/test_yandex.js117
-rw-r--r--toolkit/components/search/tests/xpcshell/searchconfigs/xpcshell.ini34
16 files changed, 2392 insertions, 0 deletions
diff --git a/toolkit/components/search/tests/xpcshell/searchconfigs/head_searchconfig.js b/toolkit/components/search/tests/xpcshell/searchconfigs/head_searchconfig.js
new file mode 100644
index 0000000000..87ade57a51
--- /dev/null
+++ b/toolkit/components/search/tests/xpcshell/searchconfigs/head_searchconfig.js
@@ -0,0 +1,614 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const { XPCOMUtils } = ChromeUtils.importESModule(
+ "resource://gre/modules/XPCOMUtils.sys.mjs"
+);
+
+ChromeUtils.defineESModuleGetters(this, {
+ AddonManager: "resource://gre/modules/AddonManager.sys.mjs",
+ AddonTestUtils: "resource://testing-common/AddonTestUtils.sys.mjs",
+ Region: "resource://gre/modules/Region.sys.mjs",
+ RemoteSettings: "resource://services-settings/remote-settings.sys.mjs",
+ SearchEngine: "resource://gre/modules/SearchEngine.sys.mjs",
+ SearchEngineSelector: "resource://gre/modules/SearchEngineSelector.sys.mjs",
+ SearchTestUtils: "resource://testing-common/SearchTestUtils.sys.mjs",
+ SearchUtils: "resource://gre/modules/SearchUtils.sys.mjs",
+ sinon: "resource://testing-common/Sinon.sys.mjs",
+});
+
+XPCOMUtils.defineLazyModuleGetters(this, {
+ ObjectUtils: "resource://gre/modules/ObjectUtils.jsm",
+});
+
+XPCOMUtils.defineLazyGlobalGetters(this, ["fetch"]);
+
+const GLOBAL_SCOPE = this;
+const TEST_DEBUG = Services.env.get("TEST_DEBUG");
+
+const URLTYPE_SUGGEST_JSON = "application/x-suggestions+json";
+const URLTYPE_SEARCH_HTML = "text/html";
+const SUBMISSION_PURPOSES = [
+ "searchbar",
+ "keyword",
+ "contextmenu",
+ "homepage",
+ "newtab",
+];
+
+let engineSelector;
+
+/**
+ * This function is used to override the remote settings configuration
+ * if the SEARCH_CONFIG environment variable is set. This allows testing
+ * against a remote server.
+ */
+async function maybeSetupConfig() {
+ const SEARCH_CONFIG = Services.env.get("SEARCH_CONFIG");
+ if (SEARCH_CONFIG) {
+ if (!(SEARCH_CONFIG in SearchUtils.ENGINES_URLS)) {
+ throw new Error(`Invalid value for SEARCH_CONFIG`);
+ }
+ const url = SearchUtils.ENGINES_URLS[SEARCH_CONFIG];
+ const response = await fetch(url);
+ const config = await response.json();
+ const settings = await RemoteSettings(SearchUtils.SETTINGS_KEY);
+ sinon.stub(settings, "get").returns(config.data);
+ }
+}
+
+/**
+ * This class implements the test harness for search configuration tests.
+ * These tests are designed to ensure that the correct search engines are
+ * loaded for the various region/locale configurations.
+ *
+ * The configuration for each test is represented by an object having the
+ * following properties:
+ *
+ * - identifier (string)
+ * The identifier for the search engine under test.
+ * - default (object)
+ * An inclusion/exclusion configuration (see below) to detail when this engine
+ * should be listed as default.
+ *
+ * The inclusion/exclusion configuration is represented as an object having the
+ * following properties:
+ *
+ * - included (array)
+ * An optional array of region/locale pairs.
+ * - excluded (array)
+ * An optional array of region/locale pairs.
+ *
+ * If the object is empty, the engine is assumed not to be part of any locale/region
+ * pair.
+ * If the object has `excluded` but not `included`, then the engine is assumed to
+ * be part of every locale/region pair except for where it matches the exclusions.
+ *
+ * The region/locale pairs are represented as an object having the following
+ * properties:
+ *
+ * - region (array)
+ * An array of two-letter region codes.
+ * - locale (object)
+ * A locale object which may consist of:
+ * - matches (array)
+ * An array of locale strings which should exactly match the locale.
+ * - startsWith (array)
+ * An array of locale strings which the locale should start with.
+ */
+class SearchConfigTest {
+ /**
+ * @param {object} config
+ * The initial configuration for this test, see above.
+ */
+ constructor(config = {}) {
+ this._config = config;
+ }
+
+ /**
+ * Sets up the test.
+ *
+ * @param {string} [version]
+ * The version to simulate for running the tests.
+ */
+ async setup(version = "42.0") {
+ AddonTestUtils.init(GLOBAL_SCOPE);
+ AddonTestUtils.createAppInfo(
+ "xpcshell@tests.mozilla.org",
+ "XPCShell",
+ version,
+ version
+ );
+
+ await maybeSetupConfig();
+
+ // Disable region checks.
+ Services.prefs.setBoolPref("browser.search.geoSpecificDefaults", false);
+
+ // Enable separatePrivateDefault testing. We test with this on, as we have
+ // separate tests for ensuring the normal = private when this is off.
+ Services.prefs.setBoolPref(
+ SearchUtils.BROWSER_SEARCH_PREF + "separatePrivateDefault.ui.enabled",
+ true
+ );
+ Services.prefs.setBoolPref(
+ SearchUtils.BROWSER_SEARCH_PREF + "separatePrivateDefault",
+ true
+ );
+
+ await AddonTestUtils.promiseStartupManager();
+ await Services.search.init();
+
+ // We must use the engine selector that the search service has created (if
+ // it has), as remote settings can only easily deal with us loading the
+ // configuration once - after that, it tries to access the network.
+ engineSelector =
+ Services.search.wrappedJSObject._engineSelector ||
+ new SearchEngineSelector();
+
+ // Note: we don't use the helper function here, so that we have at least
+ // one message output per process.
+ Assert.ok(
+ Services.search.isInitialized,
+ "Should have correctly initialized the search service"
+ );
+ }
+
+ /**
+ * Runs the test.
+ */
+ async run() {
+ const locales = await this._getLocales();
+ const regions = this._regions;
+
+ // We loop on region and then locale, so that we always cause a re-init
+ // when updating the requested/available locales.
+ for (let region of regions) {
+ for (let locale of locales) {
+ const engines = await this._getEngines(region, locale);
+ this._assertEngineRules([engines[0]], region, locale, "default");
+ const isPresent = this._assertAvailableEngines(region, locale, engines);
+ if (isPresent) {
+ this._assertEngineDetails(region, locale, engines);
+ }
+ }
+ }
+ }
+
+ async _getEngines(region, locale) {
+ let engines = [];
+ let configs = await engineSelector.fetchEngineConfiguration({
+ locale,
+ region: region || "default",
+ channel: SearchUtils.MODIFIED_APP_CHANNEL,
+ });
+ for (let config of configs.engines) {
+ let engine = await Services.search.wrappedJSObject._makeEngineFromConfig(
+ config
+ );
+ engines.push(engine);
+ }
+ return engines;
+ }
+
+ /**
+ * @returns {Set} the list of regions for the tests to run with.
+ */
+ get _regions() {
+ // TODO: The legacy configuration worked with null as an unknown region,
+ // for the search engine selector, we expect "default" but apply the
+ // fallback in _getEngines. Once we remove the legacy configuration, we can
+ // simplify this.
+ if (TEST_DEBUG) {
+ return new Set(["by", "cn", "kz", "us", "ru", "tr", null]);
+ }
+ return [...Services.intl.getAvailableLocaleDisplayNames("region"), null];
+ }
+
+ /**
+ * @returns {Array} the list of locales for the tests to run with.
+ */
+ async _getLocales() {
+ if (TEST_DEBUG) {
+ return ["be", "en-US", "kk", "tr", "ru", "zh-CN", "ach", "unknown"];
+ }
+ const data = await IOUtils.readUTF8(do_get_file("all-locales").path);
+ // "en-US" is not in all-locales as it is the default locale
+ // add it manually to ensure it is tested.
+ let locales = [...data.split("\n").filter(e => e != ""), "en-US"];
+ // BCP47 requires all variants are 5-8 characters long. Our
+ // build sytem uses the short `mac` variant, this is invalid, and inside
+ // the app we turn it into `ja-JP-macos`
+ locales = locales.map(l => (l == "ja-JP-mac" ? "ja-JP-macos" : l));
+ // The locale sometimes can be unknown or a strange name, e.g. if the updater
+ // is disabled, it may be "und", add one here so we know what happens if we
+ // hit it.
+ locales.push("unknown");
+ return locales;
+ }
+
+ /**
+ * Determines if a locale matches with a locales section in the configuration.
+ *
+ * @param {object} locales
+ * The config locales config, containing the locals to match against.
+ * @param {Array} [locales.matches]
+ * Array of locale names to match exactly.
+ * @param {Array} [locales.startsWith]
+ * Array of locale names to match the start.
+ * @param {string} locale
+ * The two-letter locale code.
+ * @returns {boolean}
+ * True if the locale matches.
+ */
+ _localeIncludes(locales, locale) {
+ if ("matches" in locales && locales.matches.includes(locale)) {
+ return true;
+ }
+ if ("startsWith" in locales) {
+ return !!locales.startsWith.find(element => locale.startsWith(element));
+ }
+
+ return false;
+ }
+
+ /**
+ * Determines if a locale/region pair match a section of the configuration.
+ *
+ * @param {object} section
+ * The configuration section to match against.
+ * @param {string} region
+ * The two-letter region code.
+ * @param {string} locale
+ * The two-letter locale code.
+ * @returns {boolean}
+ * True if the locale/region pair matches the section.
+ */
+ _localeRegionInSection(section, region, locale) {
+ for (const { regions, locales } of section) {
+ // If we only specify a regions or locales section then
+ // it is always considered included in the other section.
+ const inRegions = !regions || regions.includes(region);
+ const inLocales = !locales || this._localeIncludes(locales, locale);
+ if (inRegions && inLocales) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Helper function to find an engine from within a list.
+ *
+ * @param {Array} engines
+ * The list of engines to check.
+ * @param {string} identifier
+ * The identifier to look for in the list.
+ * @param {boolean} exactMatch
+ * Whether to use an exactMatch for the identifier.
+ * @returns {Engine}
+ * Returns the engine if found, null otherwise.
+ */
+ _findEngine(engines, identifier, exactMatch) {
+ return engines.find(engine =>
+ exactMatch
+ ? engine.identifier == identifier
+ : engine.identifier.startsWith(identifier)
+ );
+ }
+
+ /**
+ * Asserts whether the engines rules defined in the configuration are met.
+ *
+ * @param {Array} engines
+ * The list of engines to check.
+ * @param {string} region
+ * The two-letter region code.
+ * @param {string} locale
+ * The two-letter locale code.
+ * @param {string} section
+ * The section of the configuration to check.
+ * @returns {boolean}
+ * Returns true if the engine is expected to be present, false otherwise.
+ */
+ _assertEngineRules(engines, region, locale, section) {
+ const infoString = `region: "${region}" locale: "${locale}"`;
+ const config = this._config[section];
+ const hasIncluded = "included" in config;
+ const hasExcluded = "excluded" in config;
+ const identifierIncluded = !!this._findEngine(
+ engines,
+ this._config.identifier,
+ this._config.identifierExactMatch ?? false
+ );
+
+ // If there's not included/excluded, then this shouldn't be the default anywhere.
+ if (section == "default" && !hasIncluded && !hasExcluded) {
+ this.assertOk(
+ !identifierIncluded,
+ `Should not be ${section} for any locale/region,
+ currently set for ${infoString}`
+ );
+ return false;
+ }
+
+ // If there's no included section, we assume the engine is default everywhere
+ // and we should apply the exclusions instead.
+ let included =
+ hasIncluded &&
+ this._localeRegionInSection(config.included, region, locale);
+
+ let excluded =
+ hasExcluded &&
+ this._localeRegionInSection(config.excluded, region, locale);
+ if (
+ (included && (!hasExcluded || !excluded)) ||
+ (!hasIncluded && hasExcluded && !excluded)
+ ) {
+ this.assertOk(
+ identifierIncluded,
+ `Should be ${section} for ${infoString}`
+ );
+ return true;
+ }
+ this.assertOk(
+ !identifierIncluded,
+ `Should not be ${section} for ${infoString}`
+ );
+ return false;
+ }
+
+ /**
+ * Asserts whether the engine is correctly set as default or not.
+ *
+ * @param {string} region
+ * The two-letter region code.
+ * @param {string} locale
+ * The two-letter locale code.
+ */
+ _assertDefaultEngines(region, locale) {
+ this._assertEngineRules(
+ [Services.search.appDefaultEngine],
+ region,
+ locale,
+ "default"
+ );
+ // At the moment, this uses the same section as the normal default, as
+ // we don't set this differently for any region/locale.
+ this._assertEngineRules(
+ [Services.search.appPrivateDefaultEngine],
+ region,
+ locale,
+ "default"
+ );
+ }
+
+ /**
+ * Asserts whether the engine is correctly available or not.
+ *
+ * @param {string} region
+ * The two-letter region code.
+ * @param {string} locale
+ * The two-letter locale code.
+ * @param {Array} engines
+ * The current visible engines.
+ * @returns {boolean}
+ * Returns true if the engine is expected to be present, false otherwise.
+ */
+ _assertAvailableEngines(region, locale, engines) {
+ return this._assertEngineRules(engines, region, locale, "available");
+ }
+
+ /**
+ * Asserts the engine follows various rules.
+ *
+ * @param {string} region
+ * The two-letter region code.
+ * @param {string} locale
+ * The two-letter locale code.
+ * @param {Array} engines
+ * The current visible engines.
+ */
+ _assertEngineDetails(region, locale, engines) {
+ const details = this._config.details.filter(value => {
+ const included = this._localeRegionInSection(
+ value.included,
+ region,
+ locale
+ );
+ const excluded =
+ value.excluded &&
+ this._localeRegionInSection(value.excluded, region, locale);
+ return included && !excluded;
+ });
+ this.assertEqual(
+ details.length,
+ 1,
+ `Should have just one details section for region: ${region} locale: ${locale}`
+ );
+
+ const engine = this._findEngine(
+ engines,
+ this._config.identifier,
+ this._config.identifierExactMatch ?? false
+ );
+ this.assertOk(engine, "Should have an engine present");
+
+ if (this._config.aliases) {
+ this.assertDeepEqual(
+ engine.aliases,
+ this._config.aliases,
+ "Should have the correct aliases for the engine"
+ );
+ }
+
+ const location = `in region:${region}, locale:${locale}`;
+
+ for (const rule of details) {
+ this._assertCorrectDomains(location, engine, rule);
+ if (rule.codes) {
+ this._assertCorrectCodes(location, engine, rule);
+ }
+ if (rule.searchUrlCode || rule.suggestUrlCode) {
+ this._assertCorrectUrlCode(location, engine, rule);
+ }
+ if (rule.aliases) {
+ this.assertDeepEqual(
+ engine.aliases,
+ rule.aliases,
+ "Should have the correct aliases for the engine"
+ );
+ }
+ if (rule.telemetryId) {
+ this.assertEqual(
+ engine.telemetryId,
+ rule.telemetryId,
+ `Should have the correct telemetryId ${location}.`
+ );
+ }
+ }
+ }
+
+ /**
+ * Asserts whether the engine is using the correct domains or not.
+ *
+ * @param {string} location
+ * Debug string with locale + region information.
+ * @param {object} engine
+ * The engine being tested.
+ * @param {object} rules
+ * Rules to test.
+ */
+ _assertCorrectDomains(location, engine, rules) {
+ this.assertOk(
+ rules.domain,
+ `Should have an expectedDomain for the engine ${location}`
+ );
+
+ const searchForm = new URL(engine.searchForm);
+ this.assertOk(
+ searchForm.host.endsWith(rules.domain),
+ `Should have the correct search form domain ${location}.
+ Got "${searchForm.host}", expected to end with "${rules.domain}".`
+ );
+
+ let submission = engine.getSubmission("test", URLTYPE_SEARCH_HTML);
+
+ this.assertOk(
+ submission.uri.host.endsWith(rules.domain),
+ `Should have the correct domain for type: ${URLTYPE_SEARCH_HTML} ${location}.
+ Got "${submission.uri.host}", expected to end with "${rules.domain}".`
+ );
+
+ submission = engine.getSubmission("test", URLTYPE_SUGGEST_JSON);
+ if (this._config.noSuggestionsURL || rules.noSuggestionsURL) {
+ this.assertOk(!submission, "Should not have a submission url");
+ } else if (this._config.suggestionUrlBase) {
+ this.assertEqual(
+ submission.uri.prePath + submission.uri.filePath,
+ this._config.suggestionUrlBase,
+ `Should have the correct domain for type: ${URLTYPE_SUGGEST_JSON} ${location}.`
+ );
+ this.assertOk(
+ submission.uri.query.includes(rules.suggestUrlCode),
+ `Should have the code in the uri`
+ );
+ }
+ }
+
+ /**
+ * Asserts whether the engine is using the correct codes or not.
+ *
+ * @param {string} location
+ * Debug string with locale + region information.
+ * @param {object} engine
+ * The engine being tested.
+ * @param {object} rules
+ * Rules to test.
+ */
+ _assertCorrectCodes(location, engine, rules) {
+ for (const purpose of SUBMISSION_PURPOSES) {
+ // Don't need to repeat the code if we use it for all purposes.
+ const code =
+ typeof rules.codes === "string" ? rules.codes : rules.codes[purpose];
+ const submission = engine.getSubmission("test", "text/html", purpose);
+ const submissionQueryParams = submission.uri.query.split("&");
+ this.assertOk(
+ submissionQueryParams.includes(code),
+ `Expected "${code}" in url "${submission.uri.spec}" from purpose "${purpose}" ${location}`
+ );
+
+ const paramName = code.split("=")[0];
+ this.assertOk(
+ submissionQueryParams.filter(param => param.startsWith(paramName))
+ .length == 1,
+ `Expected only one "${paramName}" parameter in "${submission.uri.spec}" from purpose "${purpose}" ${location}`
+ );
+ }
+ }
+
+ /**
+ * Asserts whether the engine is using the correct URL codes or not.
+ *
+ * @param {string} location
+ * Debug string with locale + region information.
+ * @param {object} engine
+ * The engine being tested.
+ * @param {object} rule
+ * Rules to test.
+ */
+ _assertCorrectUrlCode(location, engine, rule) {
+ if (rule.searchUrlCode) {
+ const submission = engine.getSubmission("test", URLTYPE_SEARCH_HTML);
+ this.assertOk(
+ submission.uri.query.split("&").includes(rule.searchUrlCode),
+ `Expected "${rule.searchUrlCode}" in search url "${submission.uri.spec}"`
+ );
+ let uri = engine.searchForm;
+ this.assertOk(
+ !uri.includes(rule.searchUrlCode),
+ `"${rule.searchUrlCode}" should not be in the search form URL.`
+ );
+ }
+ if (rule.searchUrlCodeNotInQuery) {
+ const submission = engine.getSubmission("test", URLTYPE_SEARCH_HTML);
+ this.assertOk(
+ submission.uri.includes(rule.searchUrlCodeNotInQuery),
+ `Expected "${rule.searchUrlCodeNotInQuery}" in search url "${submission.uri.spec}"`
+ );
+ }
+ if (rule.suggestUrlCode) {
+ const submission = engine.getSubmission("test", URLTYPE_SUGGEST_JSON);
+ this.assertOk(
+ submission.uri.query.split("&").includes(rule.suggestUrlCode),
+ `Expected "${rule.suggestUrlCode}" in suggestion url "${submission.uri.spec}"`
+ );
+ }
+ }
+
+ /**
+ * Helper functions which avoid outputting test results when there are no
+ * failures. These help the tests to run faster, and avoid clogging up the
+ * python test runner process.
+ */
+
+ assertOk(value, message) {
+ if (!value || TEST_DEBUG) {
+ Assert.ok(value, message);
+ }
+ }
+
+ assertEqual(actual, expected, message) {
+ if (actual != expected || TEST_DEBUG) {
+ Assert.equal(actual, expected, message);
+ }
+ }
+
+ assertDeepEqual(actual, expected, message) {
+ if (!ObjectUtils.deepEqual(actual, expected)) {
+ Assert.deepEqual(actual, expected, message);
+ }
+ }
+}
diff --git a/toolkit/components/search/tests/xpcshell/searchconfigs/test_amazon.js b/toolkit/components/search/tests/xpcshell/searchconfigs/test_amazon.js
new file mode 100644
index 0000000000..30d4d478f0
--- /dev/null
+++ b/toolkit/components/search/tests/xpcshell/searchconfigs/test_amazon.js
@@ -0,0 +1,361 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const mainShippedRegions = [
+ "at",
+ "au",
+ "be",
+ "ca",
+ "ch",
+ "cn",
+ "de",
+ "es",
+ "fr",
+ "mc",
+ "gb",
+ "ie",
+ "it",
+ "jp",
+ "nl",
+ "pt",
+ "se",
+ "sm",
+ "us",
+ "va",
+];
+
+const amazondotcomLocales = [
+ "ach",
+ "af",
+ "ar",
+ "az",
+ "bg",
+ "cak",
+ "cy",
+ "da",
+ "el",
+ "en-US",
+ "en-GB",
+ "eo",
+ "es-AR",
+ "eu",
+ "fa",
+ "ga-IE",
+ "gd",
+ "gl",
+ "gn",
+ "hr",
+ "hy-AM",
+ "ia",
+ "is",
+ "ka",
+ "km",
+ "lt",
+ "mk",
+ "ms",
+ "my",
+ "nb-NO",
+ "nn-NO",
+ "pt-PT",
+ "ro",
+ "si",
+ "sq",
+ "sr",
+ "th",
+ "tl",
+ "trs",
+ "uz",
+];
+
+const test = new SearchConfigTest({
+ identifier: "amazon",
+ default: {
+ // Not default anywhere.
+ },
+ available: {
+ included: [
+ {
+ // The main regions we ship Amazon to. Below this are special cases.
+ regions: mainShippedRegions,
+ },
+ {
+ // Amazon.com ships to all of these locales, excluding the ones where
+ // we ship other items, but it does not matter that they are duplicated
+ // in the available list.
+ locales: {
+ matches: amazondotcomLocales,
+ },
+ },
+ {
+ // Amazon.in
+ regions: ["in"],
+ locales: {
+ matches: ["bn", "gu-IN", "kn", "mr", "pa-IN", "ta", "te", "ur"],
+ },
+ },
+ ],
+ excluded: [
+ {
+ // Extra special case for cn as that only ships to the one locale.
+ regions: ["in"],
+ locales: {
+ matches: amazondotcomLocales,
+ },
+ },
+ ],
+ },
+ details: [
+ {
+ domain: "amazon.com.au",
+ telemetryId: "amazon-au",
+ aliases: ["@amazon"],
+ included: [
+ {
+ regions: ["au"],
+ },
+ ],
+ suggestionUrlBase: "https://completion.amazon.com.au/search/complete",
+ suggestUrlCode: "mkt=111172",
+ },
+ {
+ domain: "amazon.ca",
+ telemetryId: "amazon-ca",
+ aliases: ["@amazon"],
+ included: [
+ {
+ regions: ["ca"],
+ },
+ ],
+ searchUrlCode: "tag=mozillacanada-20",
+ suggestionUrlBase: "https://completion.amazon.ca/search/complete",
+ suggestUrlCode: "mkt=7",
+ },
+ {
+ domain: "amazon.cn",
+ telemetryId: "amazondotcn",
+ included: [
+ {
+ regions: ["cn"],
+ },
+ ],
+ searchUrlCode: "ix=sunray",
+ noSuggestionsURL: true,
+ },
+ {
+ domain: "amazon.co.jp",
+ telemetryId: "amazon-jp",
+ aliases: ["@amazon"],
+ included: [
+ {
+ regions: ["jp"],
+ },
+ ],
+ searchUrlCode: "tag=mozillajapan-fx-22",
+ suggestionUrlBase: "https://completion.amazon.co.jp/search/complete",
+ suggestUrlCode: "mkt=6",
+ },
+ {
+ domain: "amazon.co.uk",
+ telemetryId: "amazon-en-GB",
+ aliases: ["@amazon"],
+ included: [
+ {
+ regions: ["gb", "ie"],
+ },
+ ],
+ searchUrlCode: "tag=firefox-uk-21",
+ suggestionUrlBase: "https://completion.amazon.co.uk/search/complete",
+ suggestUrlCode: "mkt=3",
+ },
+ {
+ domain: "amazon.com",
+ telemetryId: "amazondotcom-us",
+ aliases: ["@amazon"],
+ included: [
+ {
+ regions: ["us"],
+ },
+ ],
+ searchUrlCode: "tag=moz-us-20",
+ },
+ {
+ domain: "amazon.com",
+ telemetryId: "amazondotcom",
+ aliases: ["@amazon"],
+ included: [
+ {
+ locales: {
+ matches: amazondotcomLocales,
+ },
+ },
+ ],
+ excluded: [{ regions: mainShippedRegions }],
+ searchUrlCode: "tag=mozilla-20",
+ },
+ {
+ domain: "amazon.de",
+ telemetryId: "amazon-de",
+ aliases: ["@amazon"],
+ included: [
+ {
+ regions: ["at", "ch", "de"],
+ },
+ ],
+ searchUrlCode: "tag=firefox-de-21",
+ suggestionUrlBase: "https://completion.amazon.de/search/complete",
+ suggestUrlCode: "mkt=4",
+ },
+ {
+ domain: "amazon.es",
+ telemetryId: "amazon-es",
+ aliases: ["@amazon"],
+ included: [
+ {
+ regions: ["es", "pt"],
+ },
+ ],
+ searchUrlCode: "tag=mozillaspain-21",
+ suggestionUrlBase: "https://completion.amazon.es/search/complete",
+ suggestUrlCode: "mkt=44551",
+ },
+ {
+ domain: "amazon.fr",
+ telemetryId: "amazon-france",
+ aliases: ["@amazon"],
+ included: [
+ {
+ regions: ["fr", "mc"],
+ },
+ {
+ regions: ["be"],
+ locales: {
+ matches: ["fr"],
+ },
+ },
+ ],
+ searchUrlCode: "tag=firefox-fr-21",
+ suggestionUrlBase: "https://completion.amazon.fr/search/complete",
+ suggestUrlCode: "mkt=5",
+ },
+ {
+ domain: "amazon.in",
+ telemetryId: "amazon-in",
+ aliases: ["@amazon"],
+ included: [
+ {
+ locales: {
+ matches: ["bn", "gu-IN", "kn", "mr", "pa-IN", "ta", "te", "ur"],
+ },
+ regions: ["in"],
+ },
+ ],
+ suggestionUrlBase: "https://completion.amazon.in/search/complete",
+ suggestUrlCode: "mkt=44571",
+ },
+ {
+ domain: "amazon.it",
+ telemetryId: "amazon-it",
+ aliases: ["@amazon"],
+ included: [
+ {
+ regions: ["it", "sm", "va"],
+ },
+ ],
+ searchUrlCode: "tag=firefoxit-21",
+ suggestionUrlBase: "https://completion.amazon.it/search/complete",
+ suggestUrlCode: "mkt=35691",
+ },
+ {
+ domain: "amazon.nl",
+ telemetryId: "amazon-nl",
+ aliases: ["@amazon"],
+ included: [
+ {
+ regions: ["nl"],
+ },
+ ],
+ searchUrlCode: "tag=mozillanether-21",
+ suggestionUrlBase: "https://completion.amazon.nl/search/complete",
+ suggestUrlCode: "mkt=328451",
+ },
+ {
+ domain: "amazon.nl",
+ telemetryId: "amazon-nl",
+ aliases: ["@amazon"],
+ included: [
+ {
+ regions: ["be"],
+ },
+ ],
+ excluded: [
+ {
+ locales: {
+ matches: ["fr"],
+ },
+ },
+ ],
+ searchUrlCode: "tag=mozillanether-21",
+ suggestionUrlBase: "https://completion.amazon.nl/search/complete",
+ suggestUrlCode: "mkt=328451",
+ },
+ {
+ domain: "amazon.se",
+ telemetryId: "amazon-se",
+ aliases: ["@amazon"],
+ included: [
+ {
+ regions: ["se"],
+ },
+ ],
+ searchUrlCode: "tag=mozillasweede-21",
+ suggestionUrlBase: "https://completion.amazon.se/search/complete",
+ suggestUrlCode: "mkt=704403121",
+ },
+ ],
+});
+
+add_task(async function setup() {
+ // We only need to do setup on one of the tests.
+ await test.setup("89.0");
+});
+
+add_task(async function test_searchConfig_amazon() {
+ await test.run();
+});
+
+add_task(async function test_searchConfig_amazon_pre89() {
+ AddonTestUtils.createAppInfo(
+ "xpcshell@tests.mozilla.org",
+ "XPCShell",
+ "88.0",
+ "88.0"
+ );
+ // For pre-89, Amazon has a slightly different config.
+ let details = test._config.details.find(
+ d => d.telemetryId == "amazondotcom-us"
+ );
+ details.telemetryId = "amazondotcom";
+ details.searchUrlCode = "tag=mozilla-20";
+
+ // nl not present due to urls that don't work.
+ let availableIn = test._config.available.included;
+ availableIn[0].regions = availableIn[0].regions.filter(
+ r => r != "be" && r != "nl"
+ );
+ availableIn.push({
+ regions: ["be"],
+ locales: {
+ matches: ["fr"],
+ },
+ });
+ // Due to the way the exclusions work, no Amazon present in nl/be in the
+ // dot com locales for pre-89.
+ test._config.available.excluded[0].regions.push("be", "nl");
+ test._config.details = test._config.details.filter(
+ d => d.telemetryId != "amazon-nl"
+ );
+
+ await test.run();
+});
diff --git a/toolkit/components/search/tests/xpcshell/searchconfigs/test_baidu.js b/toolkit/components/search/tests/xpcshell/searchconfigs/test_baidu.js
new file mode 100644
index 0000000000..01094b260a
--- /dev/null
+++ b/toolkit/components/search/tests/xpcshell/searchconfigs/test_baidu.js
@@ -0,0 +1,43 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const test = new SearchConfigTest({
+ identifier: "baidu",
+ aliases: ["@\u767E\u5EA6", "@baidu"],
+ default: {
+ included: [
+ {
+ regions: ["cn"],
+ locales: {
+ matches: ["zh-CN"],
+ },
+ },
+ ],
+ },
+ available: {
+ included: [
+ {
+ locales: {
+ matches: ["zh-CN"],
+ },
+ },
+ ],
+ },
+ details: [
+ {
+ included: [{}],
+ domain: "baidu.com",
+ telemetryId: "baidu",
+ },
+ ],
+});
+
+add_task(async function setup() {
+ await test.setup();
+});
+
+add_task(async function test_searchConfig_baidu() {
+ await test.run();
+});
diff --git a/toolkit/components/search/tests/xpcshell/searchconfigs/test_bing.js b/toolkit/components/search/tests/xpcshell/searchconfigs/test_bing.js
new file mode 100644
index 0000000000..5e91c9f49b
--- /dev/null
+++ b/toolkit/components/search/tests/xpcshell/searchconfigs/test_bing.js
@@ -0,0 +1,133 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const test = new SearchConfigTest({
+ identifier: "bing",
+ aliases: ["@bing"],
+ default: {
+ // Not included anywhere.
+ },
+ available: {
+ included: [
+ {
+ // regions: [
+ // These arent currently enforced.
+ // "au", "at", "be", "br", "ca", "fi", "fr", "de",
+ // "in", "ie", "it", "jp", "my", "mx", "nl", "nz",
+ // "no", "sg", "es", "se", "ch", "gb", "us",
+ // ],
+ locales: {
+ matches: [
+ "ach",
+ "af",
+ "an",
+ "ar",
+ "ast",
+ "az",
+ "bs",
+ "ca",
+ "ca-valencia",
+ "cak",
+ "cs",
+ "cy",
+ "da",
+ "de",
+ "dsb",
+ "el",
+ "eo",
+ "es-CL",
+ "es-ES",
+ "es-MX",
+ "eu",
+ "fa",
+ "ff",
+ "fi",
+ "fr",
+ "fur",
+ "fy-NL",
+ "gd",
+ "gl",
+ "gn",
+ "gu-IN",
+ "he",
+ "hi-IN",
+ "hr",
+ "hsb",
+ "hy-AM",
+ "ia",
+ "id",
+ "is",
+ "it",
+ "ja-JP-macos",
+ "ja",
+ "ka",
+ "kab",
+ "km",
+ "kn",
+ "lij",
+ "lo",
+ "lt",
+ "meh",
+ "mk",
+ "ms",
+ "my",
+ "nb-NO",
+ "ne-NP",
+ "nl",
+ "nn-NO",
+ "oc",
+ "pa-IN",
+ "pt-BR",
+ "rm",
+ "ro",
+ "sc",
+ "sco",
+ "son",
+ "sq",
+ "sr",
+ "sv-SE",
+ "te",
+ "th",
+ "tl",
+ "tr",
+ "trs",
+ "uk",
+ "ur",
+ "uz",
+ "wo",
+ "xh",
+ "zh-CN",
+ ],
+ startsWith: ["bn", "en"],
+ },
+ },
+ ],
+ },
+ details: [
+ {
+ included: [{}],
+ domain: "bing.com",
+ telemetryId:
+ SearchUtils.MODIFIED_APP_CHANNEL == "esr" ? "bing-esr" : "bing",
+ codes: {
+ searchbar: "form=MOZSBR",
+ keyword: "form=MOZLBR",
+ contextmenu: "form=MOZCON",
+ homepage: "form=MOZSPG",
+ newtab: "form=MOZTSB",
+ },
+ searchUrlCode:
+ SearchUtils.MODIFIED_APP_CHANNEL == "esr" ? "pc=MOZR" : "pc=MOZI",
+ },
+ ],
+});
+
+add_task(async function setup() {
+ await test.setup();
+});
+
+add_task(async function test_searchConfig_bing() {
+ await test.run();
+});
diff --git a/toolkit/components/search/tests/xpcshell/searchconfigs/test_distributions.js b/toolkit/components/search/tests/xpcshell/searchconfigs/test_distributions.js
new file mode 100644
index 0000000000..0b44a5509e
--- /dev/null
+++ b/toolkit/components/search/tests/xpcshell/searchconfigs/test_distributions.js
@@ -0,0 +1,346 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+ChromeUtils.defineESModuleGetters(this, {
+ SearchEngineSelector: "resource://gre/modules/SearchEngineSelector.sys.mjs",
+ SearchService: "resource://gre/modules/SearchService.sys.mjs",
+});
+
+const tests = [];
+
+for (let canonicalId of ["canonical", "canonical-001"]) {
+ tests.push({
+ locale: "en-US",
+ region: "US",
+ distribution: canonicalId,
+ test: engines =>
+ hasParams(engines, "Google", "searchbar", "client=ubuntu") &&
+ hasParams(engines, "Google", "searchbar", "channel=fs") &&
+ hasTelemetryId(engines, "Google", "google-canonical"),
+ });
+
+ tests.push({
+ locale: "en-US",
+ region: "GB",
+ distribution: canonicalId,
+ test: engines =>
+ hasParams(engines, "Google", "searchbar", "client=ubuntu") &&
+ hasParams(engines, "Google", "searchbar", "channel=fs") &&
+ hasTelemetryId(engines, "Google", "google-canonical"),
+ });
+}
+
+tests.push({
+ locale: "en-US",
+ region: "US",
+ distribution: "canonical-002",
+ test: engines =>
+ hasParams(engines, "Google", "searchbar", "client=ubuntu-sn") &&
+ hasParams(engines, "Google", "searchbar", "channel=fs") &&
+ hasTelemetryId(engines, "Google", "google-ubuntu-sn"),
+});
+
+tests.push({
+ locale: "en-US",
+ region: "GB",
+ distribution: "canonical-002",
+ test: engines =>
+ hasParams(engines, "Google", "searchbar", "client=ubuntu-sn") &&
+ hasParams(engines, "Google", "searchbar", "channel=fs") &&
+ hasTelemetryId(engines, "Google", "google-ubuntu-sn"),
+});
+
+tests.push({
+ locale: "zh-CN",
+ region: "CN",
+ distribution: "MozillaOnline",
+ test: engines =>
+ hasParams(engines, "亚马逊", "searchbar", "ie=UTF8") &&
+ hasParams(engines, "亚马逊", "suggestions", "tag=mozilla") &&
+ hasParams(engines, "亚马逊", "homepage", "camp=536") &&
+ hasParams(engines, "亚马逊", "homepage", "creative=3200") &&
+ hasParams(engines, "亚马逊", "homepage", "index=aps") &&
+ hasParams(engines, "亚马逊", "homepage", "linkCode=ur2") &&
+ hasEnginesFirst(engines, ["百度", "Bing", "Google", "亚马逊", "维基百科"]),
+});
+
+tests.push({
+ locale: "fr",
+ distribution: "qwant-001",
+ test: engines =>
+ hasParams(engines, "Qwant", "searchbar", "client=firefoxqwant") &&
+ hasDefault(engines, "Qwant") &&
+ hasEnginesFirst(engines, ["Qwant", "Qwant Junior"]),
+});
+
+tests.push({
+ locale: "fr",
+ distribution: "qwant-001",
+ test: engines =>
+ hasParams(engines, "Qwant Junior", "searchbar", "client=firefoxqwant"),
+});
+
+tests.push({
+ locale: "fr",
+ distribution: "qwant-002",
+ test: engines =>
+ hasParams(engines, "Qwant", "searchbar", "client=firefoxqwant") &&
+ hasDefault(engines, "Qwant") &&
+ hasEnginesFirst(engines, ["Qwant", "Qwant Junior"]),
+});
+
+tests.push({
+ locale: "fr",
+ distribution: "qwant-002",
+ test: engines =>
+ hasParams(engines, "Qwant Junior", "searchbar", "client=firefoxqwant"),
+});
+
+for (const locale of ["en-US", "de"]) {
+ tests.push({
+ locale,
+ distribution: "1und1",
+ test: engines =>
+ hasParams(engines, "1&1 Suche", "searchbar", "enc=UTF-8") &&
+ hasDefault(engines, "1&1 Suche") &&
+ hasEnginesFirst(engines, ["1&1 Suche"]),
+ });
+
+ tests.push({
+ locale,
+ distribution: "gmx",
+ test: engines =>
+ hasParams(engines, "GMX Suche", "searchbar", "enc=UTF-8") &&
+ hasDefault(engines, "GMX Suche") &&
+ hasEnginesFirst(engines, ["GMX Suche"]),
+ });
+
+ tests.push({
+ locale,
+ distribution: "gmx",
+ test: engines =>
+ hasParams(engines, "GMX Shopping", "searchbar", "origin=br_osd"),
+ });
+
+ tests.push({
+ locale,
+ distribution: "mail.com",
+ test: engines =>
+ hasParams(engines, "mail.com search", "searchbar", "enc=UTF-8") &&
+ hasDefault(engines, "mail.com search") &&
+ hasEnginesFirst(engines, ["mail.com search"]),
+ });
+
+ tests.push({
+ locale,
+ distribution: "webde",
+ test: engines =>
+ hasParams(engines, "WEB.DE Suche", "searchbar", "enc=UTF-8") &&
+ hasDefault(engines, "WEB.DE Suche") &&
+ hasEnginesFirst(engines, ["WEB.DE Suche"]),
+ });
+}
+
+tests.push({
+ locale: "ru",
+ region: "RU",
+ distribution: "gmx",
+ test: engines => hasDefault(engines, "GMX Suche"),
+});
+
+tests.push({
+ locale: "en-GB",
+ distribution: "gmxcouk",
+ test: engines =>
+ hasURLs(
+ engines,
+ "GMX Search",
+ "https://go.gmx.co.uk/br/moz_search_web/?enc=UTF-8&q=test",
+ "https://suggestplugin.gmx.co.uk/s?q=test&brand=gmxcouk&origin=moz_splugin_ff&enc=UTF-8"
+ ) &&
+ hasDefault(engines, "GMX Search") &&
+ hasEnginesFirst(engines, ["GMX Search"]),
+});
+
+tests.push({
+ locale: "ru",
+ region: "RU",
+ distribution: "gmxcouk",
+ test: engines => hasDefault(engines, "GMX Search"),
+});
+
+tests.push({
+ locale: "es",
+ distribution: "gmxes",
+ test: engines =>
+ hasURLs(
+ engines,
+ "GMX - Búsqueda web",
+ "https://go.gmx.es/br/moz_search_web/?enc=UTF-8&q=test",
+ "https://suggestplugin.gmx.es/s?q=test&brand=gmxes&origin=moz_splugin_ff&enc=UTF-8"
+ ) &&
+ hasDefault(engines, "GMX Search") &&
+ hasEnginesFirst(engines, ["GMX Search"]),
+});
+
+tests.push({
+ locale: "ru",
+ region: "RU",
+ distribution: "gmxes",
+ test: engines => hasDefault(engines, "GMX - Búsqueda web"),
+});
+
+tests.push({
+ locale: "fr",
+ distribution: "gmxfr",
+ test: engines =>
+ hasURLs(
+ engines,
+ "GMX - Recherche web",
+ "https://go.gmx.fr/br/moz_search_web/?enc=UTF-8&q=test",
+ "https://suggestplugin.gmx.fr/s?q=test&brand=gmxfr&origin=moz_splugin_ff&enc=UTF-8"
+ ) &&
+ hasDefault(engines, "GMX Search") &&
+ hasEnginesFirst(engines, ["GMX Search"]),
+});
+
+tests.push({
+ locale: "ru",
+ region: "RU",
+ distribution: "gmxfr",
+ test: engines => hasDefault(engines, "GMX - Recherche web"),
+});
+
+tests.push({
+ locale: "en-US",
+ region: "US",
+ distribution: "mint-001",
+ test: engines =>
+ hasParams(engines, "DuckDuckGo", "searchbar", "t=lm") &&
+ hasParams(engines, "Google", "searchbar", "client=firefox-b-1-lm") &&
+ hasDefault(engines, "Google") &&
+ hasEnginesFirst(engines, ["Google"]) &&
+ hasTelemetryId(engines, "Google", "google-b-1-lm"),
+});
+
+tests.push({
+ locale: "en-GB",
+ region: "GB",
+ distribution: "mint-001",
+ test: engines =>
+ hasParams(engines, "DuckDuckGo", "searchbar", "t=lm") &&
+ hasParams(engines, "Google", "searchbar", "client=firefox-b-lm") &&
+ hasDefault(engines, "Google") &&
+ hasEnginesFirst(engines, ["Google"]) &&
+ hasTelemetryId(engines, "Google", "google-b-lm"),
+});
+
+function hasURLs(engines, engineName, url, suggestURL) {
+ let engine = engines.find(e => e._name === engineName);
+ Assert.ok(engine, `Should be able to find ${engineName}`);
+
+ let submission = engine.getSubmission("test", "text/html");
+ Assert.equal(
+ submission.uri.spec,
+ url,
+ `Should have the correct submission url for ${engineName}`
+ );
+
+ submission = engine.getSubmission("test", "application/x-suggestions+json");
+ Assert.equal(
+ submission.uri.spec,
+ suggestURL,
+ `Should have the correct suggestion url for ${engineName}`
+ );
+}
+
+function hasParams(engines, engineName, purpose, param) {
+ let engine = engines.find(e => e._name === engineName);
+ Assert.ok(engine, `Should be able to find ${engineName}`);
+
+ let submission = engine.getSubmission("test", "text/html", purpose);
+ let queries = submission.uri.query.split("&");
+
+ let paramNames = new Set();
+ for (let query of queries) {
+ let queryParam = query.split("=")[0];
+ Assert.ok(
+ !paramNames.has(queryParam),
+ `Should not have a duplicate ${queryParam} param`
+ );
+ paramNames.add(queryParam);
+ }
+
+ let result = queries.includes(param);
+ Assert.ok(result, `expect ${submission.uri.query} to include ${param}`);
+ return true;
+}
+
+function hasTelemetryId(engines, engineName, telemetryId) {
+ let engine = engines.find(e => e._name === engineName);
+ Assert.ok(engine, `Should be able to find ${engineName}`);
+
+ Assert.equal(
+ engine.telemetryId,
+ telemetryId,
+ "Should have the correct telemetryId"
+ );
+ return true;
+}
+
+function hasDefault(engines, expectedDefaultName) {
+ Assert.equal(
+ engines[0].name,
+ expectedDefaultName,
+ "Should have the expected engine set as default"
+ );
+ return true;
+}
+
+function hasEnginesFirst(engines, expectedEngines) {
+ for (let [i, expectedEngine] of expectedEngines.entries()) {
+ Assert.equal(
+ engines[i].name,
+ expectedEngine,
+ `Should have the expected engine in position ${i}`
+ );
+ }
+}
+
+engineSelector = new SearchEngineSelector();
+
+AddonTestUtils.init(GLOBAL_SCOPE);
+AddonTestUtils.createAppInfo(
+ "xpcshell@tests.mozilla.org",
+ "XPCShell",
+ "42",
+ "42"
+);
+
+add_task(async function setup() {
+ await AddonTestUtils.promiseStartupManager();
+
+ await maybeSetupConfig();
+});
+
+add_task(async function test_expected_distribution_engines() {
+ let searchService = new SearchService();
+ for (const { distribution, locale = "en-US", region = "US", test } of tests) {
+ let config = await engineSelector.fetchEngineConfiguration({
+ locale,
+ region,
+ distroID: distribution,
+ });
+ let engines = await SearchTestUtils.searchConfigToEngines(config.engines);
+ searchService._engines = engines;
+ searchService._searchDefault = {
+ id: config.engines[0].webExtension.id,
+ locale:
+ config.engines[0]?.webExtension?.locale ?? SearchUtils.DEFAULT_TAG,
+ };
+ engines = searchService._sortEnginesByDefaults(engines);
+ test(engines);
+ }
+});
diff --git a/toolkit/components/search/tests/xpcshell/searchconfigs/test_duckduckgo.js b/toolkit/components/search/tests/xpcshell/searchconfigs/test_duckduckgo.js
new file mode 100644
index 0000000000..379ef9d217
--- /dev/null
+++ b/toolkit/components/search/tests/xpcshell/searchconfigs/test_duckduckgo.js
@@ -0,0 +1,35 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const test = new SearchConfigTest({
+ identifier: "ddg",
+ aliases: ["@duckduckgo", "@ddg"],
+ default: {
+ // Not included anywhere.
+ },
+ available: {
+ excluded: [
+ // Should be available everywhere.
+ ],
+ },
+ details: [
+ {
+ included: [{}],
+ domain: "duckduckgo.com",
+ telemetryId:
+ SearchUtils.MODIFIED_APP_CHANNEL == "esr" ? "ddg-esr" : "ddg",
+ searchUrlCode:
+ SearchUtils.MODIFIED_APP_CHANNEL == "esr" ? "t=ftsa" : "t=ffab",
+ },
+ ],
+});
+
+add_task(async function setup() {
+ await test.setup();
+});
+
+add_task(async function test_searchConfig_duckduckgo() {
+ await test.run();
+});
diff --git a/toolkit/components/search/tests/xpcshell/searchconfigs/test_ebay.js b/toolkit/components/search/tests/xpcshell/searchconfigs/test_ebay.js
new file mode 100644
index 0000000000..df89072425
--- /dev/null
+++ b/toolkit/components/search/tests/xpcshell/searchconfigs/test_ebay.js
@@ -0,0 +1,290 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const DOMAIN_LOCALES = {
+ "ebay-ca": ["en-CA"],
+ "ebay-ch": ["rm"],
+ "ebay-de": ["de", "dsb", "hsb"],
+ "ebay-es": ["an", "ast", "ca", "ca-valencia", "es-ES", "eu", "gl"],
+ "ebay-ie": ["ga-IE", "ie"],
+ "ebay-it": ["fur", "it", "lij", "sc"],
+ "ebay-nl": ["fy-NL", "nl"],
+ "ebay-uk": ["cy", "en-GB", "gd"],
+};
+
+const test = new SearchConfigTest({
+ identifier: "ebay",
+ aliases: ["@ebay"],
+ default: {
+ // Not included anywhere.
+ },
+ available: {
+ included: [
+ {
+ // We don't currently enforce by region, but do locale instead.
+ // regions: [
+ // "us", "gb", "ca", "ie", "fr", "it", "de", "at", "es", "nl", "ch", "au"
+ // ],
+ locales: {
+ matches: [
+ "an",
+ "ast",
+ "br",
+ "ca",
+ "ca-valencia",
+ "cy",
+ "de",
+ "dsb",
+ "en-CA",
+ "en-GB",
+ "es-ES",
+ "eu",
+ "fur",
+ "fr",
+ "fy-NL",
+ "ga-IE",
+ "gd",
+ "gl",
+ "hsb",
+ "it",
+ "lij",
+ "nl",
+ "rm",
+ "sc",
+ "wo",
+ ],
+ },
+ },
+ {
+ regions: ["au", "be", "ca", "ch", "gb", "ie", "nl", "us"],
+ locales: {
+ matches: ["en-US"],
+ },
+ },
+ {
+ regions: ["gb"],
+ locales: {
+ matches: ["sco"],
+ },
+ },
+ ],
+ },
+ suggestionUrlBase: "https://autosug.ebay.com/autosug",
+ details: [
+ {
+ // Note: These should be based on region, but we don't currently enforce that.
+ // Note: the order here is important. A region/locale match higher up in the
+ // list will override a region/locale match lower down.
+ domain: "www.befr.ebay.be",
+ telemetryId: "ebay-be",
+ included: [
+ {
+ regions: ["be"],
+ locales: {
+ matches: ["br", "unknown", "en-US", "fr", "fy-NL", "nl", "wo"],
+ },
+ },
+ ],
+ searchUrlCode: "mkrid=1553-53471-19255-0",
+ suggestUrlCode: "sId=23",
+ },
+ {
+ domain: "www.ebay.at",
+ telemetryId: "ebay-at",
+ included: [
+ {
+ regions: ["at"],
+ locales: { matches: ["de", "dsb", "hsb"] },
+ },
+ ],
+ searchUrlCode: "mkrid=5221-53469-19255-0",
+ suggestUrlCode: "sId=16",
+ },
+ {
+ domain: "www.ebay.ca",
+ telemetryId: "ebay-ca",
+ included: [
+ {
+ locales: { matches: DOMAIN_LOCALES["ebay-ca"] },
+ },
+ {
+ regions: ["ca"],
+ },
+ ],
+ excluded: [
+ {
+ locales: {
+ matches: [
+ ...DOMAIN_LOCALES["ebay-ch"],
+ ...DOMAIN_LOCALES["ebay-de"],
+ ...DOMAIN_LOCALES["ebay-es"],
+ ...DOMAIN_LOCALES["ebay-ie"],
+ ...DOMAIN_LOCALES["ebay-it"],
+ ...DOMAIN_LOCALES["ebay-nl"],
+ ...DOMAIN_LOCALES["ebay-uk"],
+ ],
+ },
+ },
+ ],
+ searchUrlCode: "mkrid=706-53473-19255-0",
+ suggestUrlCode: "sId=2",
+ },
+ {
+ domain: "www.ebay.ch",
+ telemetryId: "ebay-ch",
+ included: [
+ {
+ locales: { matches: DOMAIN_LOCALES["ebay-ch"] },
+ },
+ {
+ regions: ["ch"],
+ },
+ ],
+ excluded: [
+ {
+ locales: {
+ matches: [
+ ...DOMAIN_LOCALES["ebay-ca"],
+ ...DOMAIN_LOCALES["ebay-es"],
+ ...DOMAIN_LOCALES["ebay-ie"],
+ ...DOMAIN_LOCALES["ebay-it"],
+ ...DOMAIN_LOCALES["ebay-nl"],
+ ...DOMAIN_LOCALES["ebay-uk"],
+ ],
+ },
+ },
+ ],
+ searchUrlCode: "mkrid=5222-53480-19255-0",
+ suggestUrlCode: "sId=193",
+ },
+ {
+ domain: "www.ebay.com",
+ telemetryId: "ebay",
+ included: [
+ {
+ locales: { matches: ["unknown", "en-US"] },
+ },
+ ],
+ excluded: [{ regions: ["au", "be", "ca", "ch", "gb", "ie", "nl"] }],
+ searchUrlCode: "mkrid=711-53200-19255-0",
+ suggestUrlCode: "sId=0",
+ },
+ {
+ domain: "www.ebay.com.au",
+ telemetryId: "ebay-au",
+ included: [
+ {
+ regions: ["au"],
+ locales: { matches: ["cy", "unknown", "en-GB", "en-US", "gd"] },
+ },
+ ],
+ searchUrlCode: "mkrid=705-53470-19255-0",
+ suggestUrlCode: "sId=15",
+ },
+ {
+ domain: "www.ebay.ie",
+ telemetryId: "ebay-ie",
+ included: [
+ {
+ locales: { matches: DOMAIN_LOCALES["ebay-ie"] },
+ },
+ {
+ regions: ["ie"],
+ locales: { matches: ["cy", "unknown", "en-GB", "en-US", "gd"] },
+ },
+ ],
+ searchUrlCode: "mkrid=5282-53468-19255-0",
+ suggestUrlCode: "sId=205",
+ },
+ {
+ domain: "www.ebay.co.uk",
+ telemetryId: "ebay-uk",
+ included: [
+ {
+ locales: { matches: DOMAIN_LOCALES["ebay-uk"] },
+ },
+ {
+ locales: { matches: ["unknown", "en-US", "sco"] },
+ regions: ["gb"],
+ },
+ ],
+ excluded: [{ regions: ["au", "ie"] }],
+ searchUrlCode: "mkrid=710-53481-19255-0",
+ suggestUrlCode: "sId=3",
+ },
+ {
+ domain: "www.ebay.de",
+ telemetryId: "ebay-de",
+ included: [
+ {
+ locales: { matches: DOMAIN_LOCALES["ebay-de"] },
+ },
+ ],
+ excluded: [{ regions: ["at", "ch"] }],
+ searchUrlCode: "mkrid=707-53477-19255-0",
+ suggestUrlCode: "sId=77",
+ },
+ {
+ domain: "www.ebay.es",
+ telemetryId: "ebay-es",
+ included: [
+ {
+ locales: {
+ matches: DOMAIN_LOCALES["ebay-es"],
+ },
+ },
+ ],
+ searchUrlCode: "mkrid=1185-53479-19255-0",
+ suggestUrlCode: "sId=186",
+ },
+ {
+ domain: "www.ebay.fr",
+ telemetryId: "ebay-fr",
+ included: [
+ {
+ locales: { matches: ["br", "fr", "wo"] },
+ },
+ ],
+ excluded: [{ regions: ["be", "ca", "ch"] }],
+ searchUrlCode: "mkrid=709-53476-19255-0",
+ suggestUrlCode: "sId=71",
+ },
+ {
+ domain: "www.ebay.it",
+ telemetryId: "ebay-it",
+ included: [
+ {
+ locales: { matches: DOMAIN_LOCALES["ebay-it"] },
+ },
+ ],
+ searchUrlCode: "mkrid=724-53478-19255-0",
+ suggestUrlCode: "sId=101",
+ },
+ {
+ domain: "www.ebay.nl",
+ telemetryId: "ebay-nl",
+ included: [
+ {
+ locales: { matches: DOMAIN_LOCALES["ebay-nl"] },
+ },
+ {
+ locales: { matches: ["unknown", "en-US"] },
+ regions: ["nl"],
+ },
+ ],
+ excluded: [{ regions: ["be"] }],
+ searchUrlCode: "mkrid=1346-53482-19255-0",
+ suggestUrlCode: "sId=146",
+ },
+ ],
+});
+
+add_task(async function setup() {
+ await test.setup();
+});
+
+add_task(async function test_searchConfig_ebay() {
+ await test.run();
+});
diff --git a/toolkit/components/search/tests/xpcshell/searchconfigs/test_ecosia.js b/toolkit/components/search/tests/xpcshell/searchconfigs/test_ecosia.js
new file mode 100644
index 0000000000..61d2fd9abc
--- /dev/null
+++ b/toolkit/components/search/tests/xpcshell/searchconfigs/test_ecosia.js
@@ -0,0 +1,37 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const test = new SearchConfigTest({
+ identifier: "ecosia",
+ aliases: [],
+ default: {
+ // Not default anywhere.
+ },
+ available: {
+ included: [
+ {
+ locales: {
+ matches: ["de"],
+ },
+ },
+ ],
+ },
+ details: [
+ {
+ included: [{}],
+ domain: "www.ecosia.org",
+ telemetryId: "ecosia",
+ searchUrlCode: "tt=mzl",
+ },
+ ],
+});
+
+add_task(async function setup() {
+ await test.setup();
+});
+
+add_task(async function test_searchConfig_ecosia() {
+ await test.run();
+});
diff --git a/toolkit/components/search/tests/xpcshell/searchconfigs/test_google.js b/toolkit/components/search/tests/xpcshell/searchconfigs/test_google.js
new file mode 100644
index 0000000000..dc2098b066
--- /dev/null
+++ b/toolkit/components/search/tests/xpcshell/searchconfigs/test_google.js
@@ -0,0 +1,173 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+ChromeUtils.defineESModuleGetters(this, {
+ NimbusFeatures: "resource://nimbus/ExperimentAPI.sys.mjs",
+});
+
+const test = new SearchConfigTest({
+ identifier: "google",
+ aliases: ["@google"],
+ default: {
+ // Included everywhere apart from the exclusions below. These are basically
+ // just excluding what Yandex and Baidu include.
+ excluded: [
+ {
+ regions: ["cn"],
+ locales: {
+ matches: ["zh-CN"],
+ },
+ },
+ ],
+ },
+ available: {
+ excluded: [
+ // Should be available everywhere.
+ ],
+ },
+ details: [
+ {
+ included: [{ regions: ["us"] }],
+ domain: "google.com",
+ telemetryId:
+ SearchUtils.MODIFIED_APP_CHANNEL == "esr"
+ ? "google-b-1-e"
+ : "google-b-1-d",
+ codes:
+ SearchUtils.MODIFIED_APP_CHANNEL == "esr"
+ ? "client=firefox-b-1-e"
+ : "client=firefox-b-1-d",
+ },
+ {
+ excluded: [{ regions: ["us", "by", "kz", "ru", "tr"] }],
+ included: [{}],
+ domain: "google.com",
+ telemetryId:
+ SearchUtils.MODIFIED_APP_CHANNEL == "esr" ? "google-b-e" : "google-b-d",
+ codes:
+ SearchUtils.MODIFIED_APP_CHANNEL == "esr"
+ ? "client=firefox-b-e"
+ : "client=firefox-b-d",
+ },
+ {
+ included: [{ regions: ["by", "kz", "ru", "tr"] }],
+ domain: "google.com",
+ telemetryId: "google-com-nocodes",
+ },
+ ],
+});
+
+add_task(async function setup() {
+ sinon.spy(NimbusFeatures.search, "onUpdate");
+ sinon.stub(NimbusFeatures.search, "ready").resolves();
+ await test.setup();
+});
+
+add_task(async function test_searchConfig_google() {
+ await test.run();
+});
+
+add_task(async function test_searchConfig_google_with_mozparam() {
+ // Test a couple of configurations with a MozParam set up.
+ const TEST_DATA = [
+ {
+ locale: "en-US",
+ region: "US",
+ pref: "google_channel_us",
+ expected: "us_param",
+ },
+ {
+ locale: "en-US",
+ region: "GB",
+ pref: "google_channel_row",
+ expected: "row_param",
+ },
+ ];
+
+ const defaultBranch = Services.prefs.getDefaultBranch(
+ SearchUtils.BROWSER_SEARCH_PREF
+ );
+ for (const testData of TEST_DATA) {
+ defaultBranch.setCharPref("param." + testData.pref, testData.expected);
+ }
+
+ for (const testData of TEST_DATA) {
+ info(`Checking region ${testData.region}, locale ${testData.locale}`);
+ const engines = await test._getEngines(testData.region, testData.locale);
+
+ Assert.ok(
+ engines[0].identifier.startsWith("google"),
+ "Should have the correct engine"
+ );
+ console.log(engines[0]);
+
+ const submission = engines[0].getSubmission("test", URLTYPE_SEARCH_HTML);
+ Assert.ok(
+ submission.uri.query.split("&").includes("channel=" + testData.expected),
+ "Should be including the correct MozParam parameter for the engine"
+ );
+ }
+
+ // Reset the pref values for next tests
+ for (const testData of TEST_DATA) {
+ defaultBranch.setCharPref("param." + testData.pref, "");
+ }
+});
+
+add_task(async function test_searchConfig_google_with_nimbus() {
+ let sandbox = sinon.createSandbox();
+ // Test a couple of configurations with a MozParam set up.
+ const TEST_DATA = [
+ {
+ locale: "en-US",
+ region: "US",
+ expected: "nimbus_us_param",
+ },
+ {
+ locale: "en-US",
+ region: "GB",
+ expected: "nimbus_row_param",
+ },
+ ];
+
+ Assert.ok(
+ NimbusFeatures.search.onUpdate.called,
+ "Should register an update listener for Nimbus experiments"
+ );
+ // Stub getVariable to populate the cache with our expected data
+ sandbox.stub(NimbusFeatures.search, "getVariable").returns([
+ { key: "google_channel_us", value: "nimbus_us_param" },
+ { key: "google_channel_row", value: "nimbus_row_param" },
+ ]);
+ // Set the pref cache with Nimbus values
+ NimbusFeatures.search.onUpdate.firstCall.args[0]();
+
+ for (const testData of TEST_DATA) {
+ info(`Checking region ${testData.region}, locale ${testData.locale}`);
+ const engines = await test._getEngines(testData.region, testData.locale);
+
+ Assert.ok(
+ engines[0].identifier.startsWith("google"),
+ "Should have the correct engine"
+ );
+ console.log(engines[0]);
+
+ const submission = engines[0].getSubmission("test", URLTYPE_SEARCH_HTML);
+ Assert.ok(
+ NimbusFeatures.search.ready.called,
+ "Should wait for Nimbus to get ready"
+ );
+ Assert.ok(
+ NimbusFeatures.search.getVariable,
+ "Should call NimbusFeatures.search.getVariable to populate the cache"
+ );
+ Assert.ok(
+ submission.uri.query.split("&").includes("channel=" + testData.expected),
+ "Should be including the correct MozParam parameter for the engine"
+ );
+ }
+
+ sandbox.restore();
+});
diff --git a/toolkit/components/search/tests/xpcshell/searchconfigs/test_mailru.js b/toolkit/components/search/tests/xpcshell/searchconfigs/test_mailru.js
new file mode 100644
index 0000000000..4d413f0b5b
--- /dev/null
+++ b/toolkit/components/search/tests/xpcshell/searchconfigs/test_mailru.js
@@ -0,0 +1,38 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const test = new SearchConfigTest({
+ identifier: "mailru",
+ aliases: [],
+ default: {
+ // Not default anywhere.
+ },
+ available: {
+ included: [
+ {
+ locales: {
+ matches: ["ru"],
+ },
+ },
+ ],
+ },
+ details: [
+ {
+ included: [{}],
+ domain: "go.mail.ru",
+ telemetryId: "mailru",
+ codes: "gp=900200",
+ searchUrlCode: "frc=900200",
+ },
+ ],
+});
+
+add_task(async function setup() {
+ await test.setup();
+});
+
+add_task(async function test_searchConfig_mailru() {
+ await test.run();
+}).skip();
diff --git a/toolkit/components/search/tests/xpcshell/searchconfigs/test_qwant.js b/toolkit/components/search/tests/xpcshell/searchconfigs/test_qwant.js
new file mode 100644
index 0000000000..8db31fcc24
--- /dev/null
+++ b/toolkit/components/search/tests/xpcshell/searchconfigs/test_qwant.js
@@ -0,0 +1,38 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const test = new SearchConfigTest({
+ identifier: "qwant",
+ aliases: ["@qwant"],
+ default: {
+ // Not default anywhere.
+ },
+ available: {
+ included: [
+ {
+ locales: {
+ matches: ["fr"],
+ },
+ },
+ ],
+ },
+ details: [
+ {
+ included: [{}],
+ domain: "www.qwant.com",
+ telemetryId: "qwant",
+ searchUrlCode: "client=brz-moz",
+ suggestUrlCode: "client=opensearch",
+ },
+ ],
+});
+
+add_task(async function setup() {
+ await test.setup();
+});
+
+add_task(async function test_searchConfig_qwant() {
+ await test.run();
+});
diff --git a/toolkit/components/search/tests/xpcshell/searchconfigs/test_rakuten.js b/toolkit/components/search/tests/xpcshell/searchconfigs/test_rakuten.js
new file mode 100644
index 0000000000..0577490dc2
--- /dev/null
+++ b/toolkit/components/search/tests/xpcshell/searchconfigs/test_rakuten.js
@@ -0,0 +1,37 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const test = new SearchConfigTest({
+ identifier: "rakuten",
+ aliases: [],
+ default: {
+ // Not default anywhere.
+ },
+ available: {
+ included: [
+ {
+ locales: {
+ matches: ["ja", "ja-JP-macos"],
+ },
+ },
+ ],
+ },
+ details: [
+ {
+ included: [{}],
+ domain: "rakuten.co.jp",
+ telemetryId: "rakuten",
+ searchUrlCodeNotInQuery: "013ca98b.cd7c5f0c",
+ },
+ ],
+});
+
+add_task(async function setup() {
+ await test.setup();
+});
+
+add_task(async function test_searchConfig_rakuten() {
+ await test.run();
+});
diff --git a/toolkit/components/search/tests/xpcshell/searchconfigs/test_selector_db_out_of_date.js b/toolkit/components/search/tests/xpcshell/searchconfigs/test_selector_db_out_of_date.js
new file mode 100644
index 0000000000..742cfaec8a
--- /dev/null
+++ b/toolkit/components/search/tests/xpcshell/searchconfigs/test_selector_db_out_of_date.js
@@ -0,0 +1,58 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+ChromeUtils.defineESModuleGetters(this, {
+ RemoteSettingsWorker:
+ "resource://services-settings/RemoteSettingsWorker.sys.mjs",
+ SearchEngineSelector: "resource://gre/modules/SearchEngineSelector.sys.mjs",
+});
+
+do_get_profile();
+
+add_task(async function test_selector_db_out_of_date() {
+ let searchConfig = RemoteSettings(SearchUtils.SETTINGS_KEY);
+
+ // Do an initial get to pre-seed the database.
+ await searchConfig.get();
+
+ // Now clear the database and re-fill it.
+ let db = searchConfig.db;
+ await db.clear();
+ let databaseEntries = await db.list();
+ Assert.equal(databaseEntries.length, 0, "Should have cleared the database.");
+
+ // Add a dummy record with an out-of-date last modified.
+ await RemoteSettingsWorker._execute("_test_only_import", [
+ "main",
+ SearchUtils.SETTINGS_KEY,
+ [
+ {
+ id: "b70edfdd-1c3f-4b7b-ab55-38cb048636c0",
+ default: "yes",
+ webExtension: { id: "outofdate@search.mozilla.org" },
+ appliesTo: [{ included: { everywhere: true } }],
+ last_modified: 1606227264000,
+ },
+ ],
+ 1606227264000,
+ ]);
+
+ // Now load the configuration and check we get what we expect.
+ let engineSelector = new SearchEngineSelector();
+ let result = await engineSelector.fetchEngineConfiguration({
+ // Use the fallback default locale/regions to get a simple list.
+ locale: "default",
+ region: "default",
+ });
+ Assert.deepEqual(
+ result.engines.map(e => e.webExtension.id),
+ [
+ "google@search.mozilla.org",
+ "wikipedia@search.mozilla.org",
+ "ddg@search.mozilla.org",
+ ],
+ "Should have returned the correct data."
+ );
+});
diff --git a/toolkit/components/search/tests/xpcshell/searchconfigs/test_yahoojp.js b/toolkit/components/search/tests/xpcshell/searchconfigs/test_yahoojp.js
new file mode 100644
index 0000000000..25091fc37e
--- /dev/null
+++ b/toolkit/components/search/tests/xpcshell/searchconfigs/test_yahoojp.js
@@ -0,0 +1,38 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const test = new SearchConfigTest({
+ identifier: "yahoo-jp",
+ identifierExactMatch: true,
+ aliases: [],
+ default: {
+ // Not default anywhere.
+ },
+ available: {
+ included: [
+ {
+ locales: {
+ matches: ["ja", "ja-JP-macos"],
+ },
+ },
+ ],
+ },
+ details: [
+ {
+ included: [{}],
+ domain: "search.yahoo.co.jp",
+ telemetryId: "yahoo-jp",
+ searchUrlCode: "fr=mozff",
+ },
+ ],
+});
+
+add_task(async function setup() {
+ await test.setup();
+});
+
+add_task(async function test_searchConfig_yahoojp() {
+ await test.run();
+});
diff --git a/toolkit/components/search/tests/xpcshell/searchconfigs/test_yandex.js b/toolkit/components/search/tests/xpcshell/searchconfigs/test_yandex.js
new file mode 100644
index 0000000000..c315165e5f
--- /dev/null
+++ b/toolkit/components/search/tests/xpcshell/searchconfigs/test_yandex.js
@@ -0,0 +1,117 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const test = new SearchConfigTest({
+ identifier: "yandex",
+ aliases: ["@\u044F\u043D\u0434\u0435\u043A\u0441", "@yandex"],
+ default: {
+ included: [
+ {
+ regions: ["ru", "tr", "by", "kz"],
+ locales: {
+ matches: ["ru", "tr", "be", "kk"],
+ startsWith: ["en"],
+ },
+ },
+ ],
+ },
+ available: {
+ included: [
+ {
+ locales: {
+ matches: ["az", "ru", "be", "kk", "tr"],
+ },
+ },
+ {
+ regions: ["ru", "tr", "by", "kz"],
+ locales: {
+ startsWith: ["en"],
+ },
+ },
+ ],
+ },
+ details: [
+ {
+ included: [{ locales: { matches: ["az"] } }],
+ domain: "yandex.az",
+ telemetryId: "yandex-az",
+ codes: {
+ searchbar: "clid=2186618",
+ keyword: "clid=2186621",
+ contextmenu: "clid=2186623",
+ homepage: "clid=2186617",
+ newtab: "clid=2186620",
+ },
+ },
+ {
+ included: [{ locales: { startsWith: ["en"] } }],
+ domain: "yandex.com",
+ telemetryId: "yandex-en",
+ codes: {
+ searchbar: "clid=2186618",
+ keyword: "clid=2186621",
+ contextmenu: "clid=2186623",
+ homepage: "clid=2186617",
+ newtab: "clid=2186620",
+ },
+ },
+ {
+ included: [{ locales: { matches: ["ru"] } }],
+ domain: "yandex.ru",
+ telemetryId: "yandex-ru",
+ codes: {
+ searchbar: "clid=2186618",
+ keyword: "clid=2186621",
+ contextmenu: "clid=2186623",
+ homepage: "clid=2186617",
+ newtab: "clid=2186620",
+ },
+ },
+ {
+ included: [{ locales: { matches: ["be"] } }],
+ domain: "yandex.by",
+ telemetryId: "yandex-by",
+ codes: {
+ searchbar: "clid=2186618",
+ keyword: "clid=2186621",
+ contextmenu: "clid=2186623",
+ homepage: "clid=2186617",
+ newtab: "clid=2186620",
+ },
+ },
+ {
+ included: [{ locales: { matches: ["kk"] } }],
+ domain: "yandex.kz",
+ telemetryId: "yandex-kk",
+ codes: {
+ searchbar: "clid=2186618",
+ keyword: "clid=2186621",
+ contextmenu: "clid=2186623",
+ homepage: "clid=2186617",
+ newtab: "clid=2186620",
+ },
+ },
+ {
+ included: [{ locales: { matches: ["tr"] } }],
+ domain: "yandex.com.tr",
+ telemetryId: "yandex-tr",
+ codes: {
+ searchbar: "clid=2186618",
+ keyword: "clid=2186621",
+ contextmenu: "clid=2186623",
+ homepage: "clid=2186617",
+ newtab: "clid=2186620",
+ },
+ },
+ ],
+});
+
+add_task(async function setup() {
+ await test.setup();
+});
+
+add_task(async function test_searchConfig_yandex() {
+ await test.run();
+}).skip();
diff --git a/toolkit/components/search/tests/xpcshell/searchconfigs/xpcshell.ini b/toolkit/components/search/tests/xpcshell/searchconfigs/xpcshell.ini
new file mode 100644
index 0000000000..17cbd5350d
--- /dev/null
+++ b/toolkit/components/search/tests/xpcshell/searchconfigs/xpcshell.ini
@@ -0,0 +1,34 @@
+[DEFAULT]
+firefox-appdir = browser
+head = head_searchconfig.js
+dupe-manifest =
+support-files =
+ ../../../../../../browser/locales/all-locales
+tags=searchconfig remote-settings
+# These are extensive tests, we don't need to run them on asan/tsan.
+# They are also skipped for mobile and Thunderbird as these are specifically
+# testing the Firefox config at the moment.
+skip-if =
+ toolkit == 'android'
+ appname == "thunderbird"
+ asan
+ tsan
+ debug
+ (os == "win" && ccov)
+# These tests do take a little longer on Linux ccov, so allow that here.
+requesttimeoutfactor = 2
+
+[test_amazon.js]
+[test_baidu.js]
+[test_bing.js]
+[test_distributions.js]
+[test_duckduckgo.js]
+[test_ebay.js]
+[test_ecosia.js]
+[test_google.js]
+[test_mailru.js]
+[test_qwant.js]
+[test_rakuten.js]
+[test_selector_db_out_of_date.js]
+[test_yahoojp.js]
+[test_yandex.js]