summaryrefslogtreecommitdiffstats
path: root/intl/locale/tests/unit/test_langPackMatcher.js
diff options
context:
space:
mode:
Diffstat (limited to 'intl/locale/tests/unit/test_langPackMatcher.js')
-rw-r--r--intl/locale/tests/unit/test_langPackMatcher.js287
1 files changed, 287 insertions, 0 deletions
diff --git a/intl/locale/tests/unit/test_langPackMatcher.js b/intl/locale/tests/unit/test_langPackMatcher.js
new file mode 100644
index 0000000000..03adec7bff
--- /dev/null
+++ b/intl/locale/tests/unit/test_langPackMatcher.js
@@ -0,0 +1,287 @@
+/* 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/. */
+
+const { getAddonAndLocalAPIsMocker } = ChromeUtils.importESModule(
+ "resource://testing-common/LangPackMatcherTestUtils.sys.mjs"
+);
+const { LangPackMatcher } = ChromeUtils.importESModule(
+ "resource://gre/modules/LangPackMatcher.sys.mjs"
+);
+const { sinon } = ChromeUtils.importESModule(
+ "resource://testing-common/Sinon.sys.mjs"
+);
+
+const sandbox = sinon.createSandbox();
+const mockAddonAndLocaleAPIs = getAddonAndLocalAPIsMocker(this, sandbox);
+
+add_task(function initSandbox() {
+ registerCleanupFunction(() => {
+ sandbox.restore();
+ });
+});
+
+add_task(function test_appLocaleLanguageMismatch() {
+ sandbox.restore();
+ mockAddonAndLocaleAPIs({
+ systemLocale: "es-ES",
+ appLocale: "en-US",
+ });
+
+ deepEqual(LangPackMatcher.getAppAndSystemLocaleInfo(), {
+ systemLocaleRaw: "es-ES",
+ systemLocale: { baseName: "es-ES", language: "es", region: "ES" },
+ appLocaleRaw: "en-US",
+ appLocale: { baseName: "en-US", language: "en", region: "US" },
+ matchType: "language-mismatch",
+ canLiveReload: true,
+ displayNames: {
+ systemLanguage: "Español (ES)",
+ appLanguage: "English (US)",
+ },
+ });
+});
+
+add_task(function test_appLocaleRegionMismatch() {
+ sandbox.restore();
+ mockAddonAndLocaleAPIs({
+ sandbox,
+ systemLocale: "en-CA",
+ appLocale: "en-US",
+ });
+
+ deepEqual(LangPackMatcher.getAppAndSystemLocaleInfo(), {
+ systemLocaleRaw: "en-CA",
+ systemLocale: { baseName: "en-CA", language: "en", region: "CA" },
+ appLocaleRaw: "en-US",
+ appLocale: { baseName: "en-US", language: "en", region: "US" },
+ matchType: "region-mismatch",
+ canLiveReload: true,
+ displayNames: {
+ systemLanguage: "English (CA)",
+ appLanguage: "English (US)",
+ },
+ });
+});
+
+add_task(function test_appLocaleScriptMismatch() {
+ sandbox.restore();
+ // Script mismatch:
+ mockAddonAndLocaleAPIs({
+ sandbox,
+ systemLocale: "zh-Hans-CN",
+ appLocale: "zh-CN",
+ });
+
+ deepEqual(LangPackMatcher.getAppAndSystemLocaleInfo(), {
+ systemLocaleRaw: "zh-Hans-CN",
+ systemLocale: { baseName: "zh-Hans-CN", language: "zh", region: "CN" },
+ appLocaleRaw: "zh-CN",
+ appLocale: { baseName: "zh-CN", language: "zh", region: "CN" },
+ matchType: "match",
+ canLiveReload: true,
+ displayNames: {
+ systemLanguage: "Chinese (Hans, China)",
+ appLanguage: "简体中文",
+ },
+ });
+});
+
+add_task(function test_appLocaleInvalidSystem() {
+ sandbox.restore();
+ // Script mismatch:
+ mockAddonAndLocaleAPIs({
+ sandbox,
+ systemLocale: "Not valid",
+ appLocale: "en-US",
+ });
+
+ deepEqual(LangPackMatcher.getAppAndSystemLocaleInfo(), {
+ systemLocaleRaw: "Not valid",
+ systemLocale: null,
+ appLocaleRaw: "en-US",
+ appLocale: { baseName: "en-US", language: "en", region: "US" },
+ matchType: "unknown",
+ canLiveReload: null,
+ displayNames: { systemLanguage: null, appLanguage: "English (US)" },
+ });
+});
+
+add_task(function test_bidiSwitchDisabled() {
+ Services.prefs.setBoolPref(
+ "intl.multilingual.liveReloadBidirectional",
+ false
+ );
+ sandbox.restore();
+ // Script mismatch:
+ mockAddonAndLocaleAPIs({
+ sandbox,
+ systemLocale: "ar-EG",
+ appLocale: "en-US",
+ });
+
+ deepEqual(LangPackMatcher.getAppAndSystemLocaleInfo(), {
+ systemLocaleRaw: "ar-EG",
+ systemLocale: { baseName: "ar-EG", language: "ar", region: "EG" },
+ appLocaleRaw: "en-US",
+ appLocale: { baseName: "en-US", language: "en", region: "US" },
+ matchType: "language-mismatch",
+ canLiveReload: false,
+ displayNames: {
+ systemLanguage: "Arabic (Egypt)",
+ appLanguage: "English (US)",
+ },
+ });
+ Services.prefs.clearUserPref("intl.multilingual.liveReloadBidirectional");
+});
+
+add_task(async function test_bidiSwitchEnabled() {
+ Services.prefs.setBoolPref("intl.multilingual.liveReloadBidirectional", true);
+ sandbox.restore();
+ // Script mismatch:
+ mockAddonAndLocaleAPIs({
+ sandbox,
+ systemLocale: "ar-EG",
+ appLocale: "en-US",
+ });
+
+ deepEqual(LangPackMatcher.getAppAndSystemLocaleInfo(), {
+ systemLocaleRaw: "ar-EG",
+ systemLocale: { baseName: "ar-EG", language: "ar", region: "EG" },
+ appLocaleRaw: "en-US",
+ appLocale: { baseName: "en-US", language: "en", region: "US" },
+ matchType: "language-mismatch",
+ canLiveReload: true,
+ displayNames: {
+ systemLanguage: "Arabic (Egypt)",
+ appLanguage: "English (US)",
+ },
+ });
+
+ Services.prefs.clearUserPref("intl.multilingual.liveReloadBidirectional");
+});
+
+function shuffle(array) {
+ return array
+ .map(value => ({ value, sort: Math.random() }))
+ .sort((a, b) => a.sort - b.sort)
+ .map(({ value }) => value);
+}
+
+add_task(async function test_negotiateLangPacks() {
+ const negotiations = [
+ {
+ // Exact match found.
+ systemLocale: "en-US",
+ availableLangPacks: ["en", "en-US", "zh", "zh-CN", "zh-Hans-CN"],
+ expectedLangPack: "en-US",
+ expectedDisplayName: "English (US)",
+ },
+ {
+ // Region-less match.
+ systemLocale: "en-CA",
+ availableLangPacks: ["en", "en-US", "zh", "zh-CN", "zh-Hans-CN"],
+ expectedLangPack: "en",
+ expectedDisplayName: "English",
+ },
+ {
+ // Fallback to a different region.
+ systemLocale: "en-CA",
+ availableLangPacks: ["en-US", "zh", "zh-CN", "zh-Hans-CN"],
+ expectedLangPack: "en-US",
+ expectedDisplayName: "English (US)",
+ },
+ {
+ // Match with a script. zh-Hans-CN is the locale used with simplified
+ // Chinese scripts, while zh-CN uses the Latin script.
+ systemLocale: "zh-Hans-CN",
+ availableLangPacks: ["en", "en-US", "zh", "zh-CN", "zh-TW", "zh-Hans-CN"],
+ expectedLangPack: "zh-Hans-CN",
+ expectedDisplayName: "Chinese (Hans, China)",
+ },
+ {
+ // Match excluding script but matching region. zh-Hant-TW should
+ // match zh-TW before zh-CN.
+ systemLocale: "zh-Hant-TW",
+ availableLangPacks: ["en", "zh", "zh-CN", "zh-TW"],
+ expectedLangPack: "zh-TW",
+ expectedDisplayName: "正體中文",
+ },
+ {
+ // No reasonable match could be found.
+ systemLocale: "tlh", // Klingon
+ availableLangPacks: ["en", "en-US", "zh", "zh-CN", "zh-Hans-CN"],
+ expectedLangPack: null,
+ expectedDisplayName: null,
+ },
+ {
+ // Weird, but valid locale identifiers.
+ systemLocale: "en-US-u-hc-h23-ca-islamic-civil-ss-true",
+ availableLangPacks: ["en", "en-US", "zh", "zh-CN", "zh-Hans-CN"],
+ expectedLangPack: "en-US",
+ expectedDisplayName: "English (US)",
+ },
+ {
+ // Invalid system locale
+ systemLocale: "Not valid",
+ availableLangPacks: ["en", "en-US", "zh", "zh-CN", "zh-Hans-CN"],
+ expectedLangPack: null,
+ expectedDisplayName: null,
+ },
+ ];
+
+ for (const {
+ systemLocale,
+ availableLangPacks,
+ expectedLangPack,
+ expectedDisplayName,
+ } of negotiations) {
+ sandbox.restore();
+ const { resolveLangPacks } = mockAddonAndLocaleAPIs({
+ sandbox,
+ systemLocale,
+ });
+
+ const promise = LangPackMatcher.negotiateLangPackForLanguageMismatch();
+ // Shuffle the order to ensure that this test doesn't require on ordering of the
+ // langpack responses.
+ resolveLangPacks(shuffle(availableLangPacks));
+ const { langPack, langPackDisplayName } = await promise;
+ equal(
+ langPack?.target_locale,
+ expectedLangPack,
+ `Resolve the systemLocale "${systemLocale}" with available langpacks: ${JSON.stringify(
+ availableLangPacks
+ )}`
+ );
+ equal(
+ langPackDisplayName,
+ expectedDisplayName,
+ "The display name matches."
+ );
+ }
+});
+
+add_task(async function test_ensureLangPackInstalled() {
+ sandbox.restore();
+ const { resolveLangPacks, resolveInstaller } = mockAddonAndLocaleAPIs({
+ sandbox,
+ systemLocale: "es-ES",
+ appLocale: "en-US",
+ });
+
+ const negotiatePromise =
+ LangPackMatcher.negotiateLangPackForLanguageMismatch();
+ resolveLangPacks(["es-ES"]);
+ const { langPack } = await negotiatePromise;
+
+ const installPromise1 = LangPackMatcher.ensureLangPackInstalled(langPack);
+ const installPromise2 = LangPackMatcher.ensureLangPackInstalled(langPack);
+
+ resolveInstaller(["fake langpack"]);
+
+ info("Ensure both installers resolve when called twice in a row.");
+ await installPromise1;
+ await installPromise2;
+ ok(true, "Both were called.");
+});