tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_langPackMatcher.js (8550B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 const { getAddonAndLocalAPIsMocker } = ChromeUtils.importESModule(
      6  "resource://testing-common/LangPackMatcherTestUtils.sys.mjs"
      7 );
      8 const { LangPackMatcher } = ChromeUtils.importESModule(
      9  "resource://gre/modules/LangPackMatcher.sys.mjs"
     10 );
     11 const { sinon } = ChromeUtils.importESModule(
     12  "resource://testing-common/Sinon.sys.mjs"
     13 );
     14 
     15 const sandbox = sinon.createSandbox();
     16 const mockAddonAndLocaleAPIs = getAddonAndLocalAPIsMocker(this, sandbox);
     17 
     18 add_task(function initSandbox() {
     19  registerCleanupFunction(() => {
     20    sandbox.restore();
     21  });
     22 });
     23 
     24 add_task(function test_appLocaleLanguageMismatch() {
     25  sandbox.restore();
     26  mockAddonAndLocaleAPIs({
     27    systemLocale: "es-ES",
     28    appLocale: "en-US",
     29  });
     30 
     31  deepEqual(LangPackMatcher.getAppAndSystemLocaleInfo(), {
     32    systemLocaleRaw: "es-ES",
     33    systemLocale: { baseName: "es-ES", language: "es", region: "ES" },
     34    appLocaleRaw: "en-US",
     35    appLocale: { baseName: "en-US", language: "en", region: "US" },
     36    matchType: "language-mismatch",
     37    canLiveReload: true,
     38    displayNames: {
     39      systemLanguage: "Español (ES)",
     40      appLanguage: "English (US)",
     41    },
     42  });
     43 });
     44 
     45 add_task(function test_appLocaleRegionMismatch() {
     46  sandbox.restore();
     47  mockAddonAndLocaleAPIs({
     48    sandbox,
     49    systemLocale: "en-CA",
     50    appLocale: "en-US",
     51  });
     52 
     53  deepEqual(LangPackMatcher.getAppAndSystemLocaleInfo(), {
     54    systemLocaleRaw: "en-CA",
     55    systemLocale: { baseName: "en-CA", language: "en", region: "CA" },
     56    appLocaleRaw: "en-US",
     57    appLocale: { baseName: "en-US", language: "en", region: "US" },
     58    matchType: "region-mismatch",
     59    canLiveReload: true,
     60    displayNames: {
     61      systemLanguage: "English (CA)",
     62      appLanguage: "English (US)",
     63    },
     64  });
     65 });
     66 
     67 add_task(function test_appLocaleScriptMismatch() {
     68  sandbox.restore();
     69  // Script mismatch:
     70  mockAddonAndLocaleAPIs({
     71    sandbox,
     72    systemLocale: "zh-Hans-CN",
     73    appLocale: "zh-CN",
     74  });
     75 
     76  deepEqual(LangPackMatcher.getAppAndSystemLocaleInfo(), {
     77    systemLocaleRaw: "zh-Hans-CN",
     78    systemLocale: { baseName: "zh-Hans-CN", language: "zh", region: "CN" },
     79    appLocaleRaw: "zh-CN",
     80    appLocale: { baseName: "zh-CN", language: "zh", region: "CN" },
     81    matchType: "match",
     82    canLiveReload: true,
     83    displayNames: {
     84      systemLanguage: "Chinese (Hans, China)",
     85      appLanguage: "简体中文",
     86    },
     87  });
     88 });
     89 
     90 add_task(function test_appLocaleInvalidSystem() {
     91  sandbox.restore();
     92  // Script mismatch:
     93  mockAddonAndLocaleAPIs({
     94    sandbox,
     95    systemLocale: "Not valid",
     96    appLocale: "en-US",
     97  });
     98 
     99  deepEqual(LangPackMatcher.getAppAndSystemLocaleInfo(), {
    100    systemLocaleRaw: "Not valid",
    101    systemLocale: null,
    102    appLocaleRaw: "en-US",
    103    appLocale: { baseName: "en-US", language: "en", region: "US" },
    104    matchType: "unknown",
    105    canLiveReload: null,
    106    displayNames: { systemLanguage: null, appLanguage: "English (US)" },
    107  });
    108 });
    109 
    110 add_task(function test_bidiSwitchDisabled() {
    111  Services.prefs.setBoolPref(
    112    "intl.multilingual.liveReloadBidirectional",
    113    false
    114  );
    115  sandbox.restore();
    116  // Script mismatch:
    117  mockAddonAndLocaleAPIs({
    118    sandbox,
    119    systemLocale: "ar-EG",
    120    appLocale: "en-US",
    121  });
    122 
    123  deepEqual(LangPackMatcher.getAppAndSystemLocaleInfo(), {
    124    systemLocaleRaw: "ar-EG",
    125    systemLocale: { baseName: "ar-EG", language: "ar", region: "EG" },
    126    appLocaleRaw: "en-US",
    127    appLocale: { baseName: "en-US", language: "en", region: "US" },
    128    matchType: "language-mismatch",
    129    canLiveReload: false,
    130    displayNames: {
    131      systemLanguage: "Arabic (Egypt)",
    132      appLanguage: "English (US)",
    133    },
    134  });
    135  Services.prefs.clearUserPref("intl.multilingual.liveReloadBidirectional");
    136 });
    137 
    138 add_task(async function test_bidiSwitchEnabled() {
    139  Services.prefs.setBoolPref("intl.multilingual.liveReloadBidirectional", true);
    140  sandbox.restore();
    141  // Script mismatch:
    142  mockAddonAndLocaleAPIs({
    143    sandbox,
    144    systemLocale: "ar-EG",
    145    appLocale: "en-US",
    146  });
    147 
    148  deepEqual(LangPackMatcher.getAppAndSystemLocaleInfo(), {
    149    systemLocaleRaw: "ar-EG",
    150    systemLocale: { baseName: "ar-EG", language: "ar", region: "EG" },
    151    appLocaleRaw: "en-US",
    152    appLocale: { baseName: "en-US", language: "en", region: "US" },
    153    matchType: "language-mismatch",
    154    canLiveReload: true,
    155    displayNames: {
    156      systemLanguage: "Arabic (Egypt)",
    157      appLanguage: "English (US)",
    158    },
    159  });
    160 
    161  Services.prefs.clearUserPref("intl.multilingual.liveReloadBidirectional");
    162 });
    163 
    164 function shuffle(array) {
    165  return array
    166    .map(value => ({ value, sort: Math.random() }))
    167    .sort((a, b) => a.sort - b.sort)
    168    .map(({ value }) => value);
    169 }
    170 
    171 add_task(async function test_negotiateLangPacks() {
    172  const negotiations = [
    173    {
    174      // Exact match found.
    175      systemLocale: "en-US",
    176      availableLangPacks: ["en", "en-US", "zh", "zh-CN", "zh-Hans-CN"],
    177      expectedLangPack: "en-US",
    178      expectedDisplayName: "English (US)",
    179    },
    180    {
    181      // Region-less match.
    182      systemLocale: "en-CA",
    183      availableLangPacks: ["en", "en-US", "zh", "zh-CN", "zh-Hans-CN"],
    184      expectedLangPack: "en",
    185      expectedDisplayName: "English",
    186    },
    187    {
    188      // Fallback to a different region.
    189      systemLocale: "en-CA",
    190      availableLangPacks: ["en-US", "zh", "zh-CN", "zh-Hans-CN"],
    191      expectedLangPack: "en-US",
    192      expectedDisplayName: "English (US)",
    193    },
    194    {
    195      // Match with a script. zh-Hans-CN is the locale used with simplified
    196      // Chinese scripts, while zh-CN uses the Latin script.
    197      systemLocale: "zh-Hans-CN",
    198      availableLangPacks: ["en", "en-US", "zh", "zh-CN", "zh-TW", "zh-Hans-CN"],
    199      expectedLangPack: "zh-Hans-CN",
    200      expectedDisplayName: "Chinese (Hans, China)",
    201    },
    202    {
    203      // Match excluding script but matching region. zh-Hant-TW should
    204      // match zh-TW before zh-CN.
    205      systemLocale: "zh-Hant-TW",
    206      availableLangPacks: ["en", "zh", "zh-CN", "zh-TW"],
    207      expectedLangPack: "zh-TW",
    208      expectedDisplayName: "正體中文",
    209    },
    210    {
    211      // No reasonable match could be found.
    212      systemLocale: "tlh", // Klingon
    213      availableLangPacks: ["en", "en-US", "zh", "zh-CN", "zh-Hans-CN"],
    214      expectedLangPack: null,
    215      expectedDisplayName: null,
    216    },
    217    {
    218      // Weird, but valid locale identifiers.
    219      systemLocale: "en-US-u-hc-h23-ca-islamic-civil-ss-true",
    220      availableLangPacks: ["en", "en-US", "zh", "zh-CN", "zh-Hans-CN"],
    221      expectedLangPack: "en-US",
    222      expectedDisplayName: "English (US)",
    223    },
    224    {
    225      // Invalid system locale
    226      systemLocale: "Not valid",
    227      availableLangPacks: ["en", "en-US", "zh", "zh-CN", "zh-Hans-CN"],
    228      expectedLangPack: null,
    229      expectedDisplayName: null,
    230    },
    231  ];
    232 
    233  for (const {
    234    systemLocale,
    235    availableLangPacks,
    236    expectedLangPack,
    237    expectedDisplayName,
    238  } of negotiations) {
    239    sandbox.restore();
    240    const { resolveLangPacks } = mockAddonAndLocaleAPIs({
    241      sandbox,
    242      systemLocale,
    243    });
    244 
    245    const promise = LangPackMatcher.negotiateLangPackForLanguageMismatch();
    246    // Shuffle the order to ensure that this test doesn't require on ordering of the
    247    // langpack responses.
    248    resolveLangPacks(shuffle(availableLangPacks));
    249    const { langPack, langPackDisplayName } = await promise;
    250    equal(
    251      langPack?.target_locale,
    252      expectedLangPack,
    253      `Resolve the systemLocale "${systemLocale}" with available langpacks: ${JSON.stringify(
    254        availableLangPacks
    255      )}`
    256    );
    257    equal(
    258      langPackDisplayName,
    259      expectedDisplayName,
    260      "The display name matches."
    261    );
    262  }
    263 });
    264 
    265 add_task(async function test_ensureLangPackInstalled() {
    266  sandbox.restore();
    267  const { resolveLangPacks, resolveInstaller } = mockAddonAndLocaleAPIs({
    268    sandbox,
    269    systemLocale: "es-ES",
    270    appLocale: "en-US",
    271  });
    272 
    273  const negotiatePromise =
    274    LangPackMatcher.negotiateLangPackForLanguageMismatch();
    275  resolveLangPacks(["es-ES"]);
    276  const { langPack } = await negotiatePromise;
    277 
    278  const installPromise1 = LangPackMatcher.ensureLangPackInstalled(langPack);
    279  const installPromise2 = LangPackMatcher.ensureLangPackInstalled(langPack);
    280 
    281  resolveInstaller(["fake langpack"]);
    282 
    283  info("Ensure both installers resolve when called twice in a row.");
    284  await installPromise1;
    285  await installPromise2;
    286  ok(true, "Both were called.");
    287 });