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"use strict";
5
6var EXPORTED_SYMBOLS = ["getAddonAndLocalAPIsMocker"];
7
8const { LangPackMatcher } = ChromeUtils.import(
9  "resource://gre/modules/LangPackMatcher.jsm"
10);
11
12/**
13 * LangPackMatcher.jsm calls out to to the addons store, which involves network requests.
14 * Other tests create a fake addons server, and install mock XPIs. At the time of this
15 * writing that infrastructure is not available for mochitests.
16 *
17 * Instead, this test mocks out APIs that have a side-effect, so the addons of the browser
18 * are never modified.
19 *
20 * The calls to get the app's locale and system's locale are also mocked so that the
21 * different language mismatch scenarios can be run through.
22 *
23 * The locales are BCP 47 identifiers:
24 *
25 * @param {{
26 *   sandbox: SinonSandbox,
27 *   systemLocale: string,
28 *   appLocale, string,
29 * }}
30 */
31function getAddonAndLocalAPIsMocker(testScope, sandbox) {
32  const { info } = testScope;
33  return function mockAddonAndLocaleAPIs({ systemLocale, appLocale }) {
34    info("Mocking LangPackMatcher.jsm APIs");
35
36    let resolveLangPacks;
37    const langPackPromise = new Promise(resolve => {
38      resolveLangPacks = availableLangpacks => {
39        info(
40          `Resolving which langpacks are available for download: ${JSON.stringify(
41            availableLangpacks
42          )}`
43        );
44        resolve(
45          availableLangpacks.map(locale => ({
46            guid: `langpack-${locale}@firefox.mozilla.org`,
47            type: "language",
48            target_locale: locale,
49            current_compatible_version: {
50              files: [
51                {
52                  platform: "all",
53                  url: `http://example.com/${locale}.langpack.xpi`,
54                },
55              ],
56            },
57          }))
58        );
59      };
60    });
61
62    let resolveInstaller;
63    const installerPromise = new Promise(resolve => {
64      resolveInstaller = () => {
65        info("LangPack install finished.");
66        resolve();
67      };
68    });
69
70    const { mockable } = LangPackMatcher;
71    if (appLocale) {
72      sandbox.stub(mockable, "getAvailableLocales").returns([appLocale]);
73      sandbox.stub(mockable, "getAppLocaleAsBCP47").returns(appLocale);
74    }
75    if (systemLocale) {
76      sandbox.stub(mockable, "getSystemLocale").returns(systemLocale);
77    }
78
79    sandbox.stub(mockable, "getAvailableLangpacks").callsFake(() => {
80      info("Requesting which langpacks are available for download");
81      return langPackPromise;
82    });
83
84    sandbox.stub(mockable, "installLangPack").callsFake(langPack => {
85      info(`LangPack install started, but pending: ${langPack.target_locale}`);
86      return installerPromise;
87    });
88
89    sandbox.stub(mockable, "setRequestedAppLocales").callsFake(locales => {
90      info(
91        `Changing the browser's requested locales to: ${JSON.stringify(
92          locales
93        )}`
94      );
95    });
96
97    return {
98      /**
99       * Resolves the addons API call with available langpacks. Call with a list
100       * of BCP 47 identifiers.
101       *
102       * @type {(availableLangpacks: string[]) => {}}
103       */
104      resolveLangPacks,
105
106      /**
107       * Resolves the pending call to install a langpack.
108       *
109       * @type {() => {}}
110       */
111      resolveInstaller,
112
113      /**
114       * The mocked APIs.
115       */
116      mockable,
117    };
118  };
119}
120