1 /* Any copyright is dedicated to the Public Domain.
2 * http://creativecommons.org/publicdomain/zero/1.0/
5 // Tests AddonRepository.jsm
7 var gServer = createHttpServer({ hosts: ["example.com"] });
9 const PREF_GETADDONS_BROWSEADDONS = "extensions.getAddons.browseAddons";
10 const PREF_GETADDONS_BROWSESEARCHRESULTS =
11 "extensions.getAddons.search.browseURL";
12 const PREF_GET_BROWSER_MAPPINGS = "extensions.getAddons.browserMappings.url";
14 const BASE_URL = "http://example.com";
15 const DEFAULT_URL = "about:blank";
22 browser_specific_settings: {
23 gecko: { id: "test_AddonRepository_1@tests.mozilla.org" },
32 browser_specific_settings: {
33 gecko: { id: "test_AddonRepository_2@tests.mozilla.org" },
42 browser_specific_settings: {
43 gecko: { id: "test_AddonRepository_3@tests.mozilla.org" },
49 // Path to source URI of installing add-on
50 const INSTALL_URL2 = "/addons/test_AddonRepository_2.xpi";
51 // Path to source URI of non-active add-on (state = STATE_AVAILABLE)
52 const INSTALL_URL3 = "/addons/test_AddonRepository_3.xpi";
54 // Properties of an individual add-on that should be checked
55 // Note: name is checked separately
56 var ADDON_PROPERTIES = [
79 // Results of getAddonsByIDs
82 id: "test1@tests.mozilla.org",
86 name: "Test Creator 1",
87 url: BASE_URL + "/creator1.html",
91 name: "Test Developer 1",
92 url: BASE_URL + "/developer1.html",
95 description: "Test Summary 1",
96 fullDescription: "Test Description 1",
97 iconURL: BASE_URL + "/icon1.png",
98 icons: { 32: BASE_URL + "/icon1.png" },
101 url: BASE_URL + "/full1-1.png",
104 thumbnailURL: BASE_URL + "/thumbnail1-1.png",
106 thumbnailHeight: 150,
107 caption: "Caption 1 - 1",
110 url: BASE_URL + "/full2-1.png",
111 thumbnailURL: BASE_URL + "/thumbnail2-1.png",
112 caption: "Caption 2 - 1",
115 supportURL: BASE_URL + "/support1.html",
116 contributionURL: BASE_URL + "/contribution1.html",
119 reviewURL: BASE_URL + "/review1.html",
120 weeklyDownloads: 3333,
121 sourceURI: BASE_URL + INSTALL_URL2,
122 updateDate: new Date(1265033045000),
124 "https://addons.mozilla.org/en-US/firefox/addon/test1@tests.mozilla.org/",
127 id: "test2@tests.mozilla.org",
131 sourceURI: "http://example.com/addons/bleah.xpi",
134 id: "test_AddonRepository_1@tests.mozilla.org",
141 // Values for testing AddonRepository.getAddonsByIDs()
143 preference: PREF_GETADDONS_BYIDS,
144 preferenceValue: BASE_URL + "/%OS%/%VERSION%/%IDS%",
145 failedIDs: ["test1@tests.mozilla.org"],
146 failedURL: "/XPCShell/1/test1%40tests.mozilla.org",
148 "test1@tests.mozilla.org",
149 "test2@tests.mozilla.org",
150 "{00000000-1111-2222-3333-444444444444}",
151 "test_AddonRepository_1@tests.mozilla.org",
154 "/XPCShell/1/test1%40tests.mozilla.org%2C" +
155 "test2%40tests.mozilla.org%2C" +
156 "%7B00000000-1111-2222-3333-444444444444%7D%2C" +
157 "test_AddonRepository_1%40tests.mozilla.org",
159 "/XPCShell/1/rta%3AdGVzdDFAdGVzdHMubW96aWxsYS5vcmc%2C" +
160 "test2%40tests.mozilla.org%2C" +
161 "%7B00000000-1111-2222-3333-444444444444%7D%2C" +
162 "test_AddonRepository_1%40tests.mozilla.org",
165 const GET_BROWSER_MAPPINGS_URL = `${BASE_URL}/browser-mappings/%BROWSER%`;
167 // Test that actual results and expected results are equal
168 function check_results(aActualAddons, aExpectedAddons) {
169 do_check_addons(aActualAddons, aExpectedAddons, ADDON_PROPERTIES);
172 aActualAddons.forEach(function check_each_addon(aActualAddon) {
173 // Separately check name so better messages are output when test fails
174 if (aActualAddon.name == "FAIL") {
175 do_throw(aActualAddon.id + " - " + aActualAddon.description);
177 if (aActualAddon.name != "PASS") {
178 do_throw(aActualAddon.id + " - invalid add-on name " + aActualAddon.name);
183 add_task(async function setup() {
185 createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9");
187 let xpis = ADDONS.map(addon => createTempWebExtensionFile(addon));
189 // Register other add-on XPI files
190 gServer.registerFile(INSTALL_URL2, xpis[1]);
191 gServer.registerFile(INSTALL_URL3, xpis[2]);
193 // Register files used to test search failure
194 gServer.registerFile(
196 do_get_file("data/test_AddonRepository_fail.json")
199 // Register files used to test search success
200 gServer.registerFile(
201 GET_TEST.successfulURL,
202 do_get_file("data/test_AddonRepository_getAddonsByIDs.json")
204 // Register file for RTA test
205 gServer.registerFile(
206 GET_TEST.successfulRTAURL,
207 do_get_file("data/test_AddonRepository_getAddonsByIDs.json")
210 // Register some files/handlers for browser mapping tests.
211 gServer.registerFile(
212 // Keep in sync with `GET_BROWSER_MAPPINGS_URL`.
213 "/browser-mappings/valid-browser-id",
214 do_get_file("data/test_AddonRepository_getMappedAddons.json")
216 gServer.registerFile(
217 // This is used in `test_getMappedAddons_empty_mapping()` and should be
218 // updated if `GET_BROWSER_MAPPINGS_URL` is also updated.
219 "/browser-mappings/browser-id-empty-results",
220 do_get_file("data/test_AddonRepository_getMappedAddons_empty.json")
222 gServer.registerPrefixHandler(
223 // Keep in sync with the pref set in `test_getMappedAddons_with_paging()`.
224 "/browser-mappings/with-paging/valid-browser-id/",
225 // This handler parses the query string of the request it receives in order
226 // to force the `getMappedAddons()` method to call the same API endpoint a
227 // few times (by incrementing the integer value in the query string every
228 // time). After that, this handler returns a "next' URL that points to one
229 // of the valid endpoints registered above, which won't have a "next" URL.
230 // We do this to verify that `getMappedAddons()` supports paginated API
232 (request, response) => {
233 const page = parseInt(request.queryString, 10);
236 ? `with-paging/valid-browser-id/?${page + 1}`
237 : `valid-browser-id`;
239 response.setHeader("content-type", "application/json");
243 next: `${BASE_URL}/browser-mappings/${nextPath}`,
253 await promiseStartupManager();
255 // Install an add-on so can check that it isn't returned in the results
256 await promiseInstallFile(xpis[0]);
257 await promiseRestartManager();
259 // Create an active AddonInstall so can check that it isn't returned in the results
260 let install = await AddonManager.getInstallForURL(BASE_URL + INSTALL_URL2);
261 let promise = promiseCompleteInstall(install);
262 registerCleanupFunction(() => promise);
264 // Create a non-active AddonInstall so can check that it is returned in the results
265 await AddonManager.getInstallForURL(BASE_URL + INSTALL_URL3);
268 // Tests homepageURL and getSearchURL()
269 add_task(async function test_1() {
270 function check_urls(aPreference, aGetURL, aTests) {
271 aTests.forEach(function (aTest) {
272 Services.prefs.setCharPref(aPreference, aTest.preferenceValue);
273 Assert.equal(aGetURL(aTest), aTest.expectedURL);
279 preferenceValue: BASE_URL,
280 expectedURL: BASE_URL,
283 preferenceValue: BASE_URL + "/%OS%/%VERSION%",
284 expectedURL: BASE_URL + "/XPCShell/1",
288 // Extra tests for AddonRepository.getSearchURL();
289 var searchURLTests = [
292 preferenceValue: BASE_URL + "/search?q=%TERMS%",
293 expectedURL: BASE_URL + "/search?q=test",
296 searchTerms: "test search",
297 preferenceValue: BASE_URL + "/%TERMS%",
298 expectedURL: BASE_URL + "/test%20search",
301 searchTerms: 'odd=search:with&weird"characters',
302 preferenceValue: BASE_URL + "/%TERMS%",
303 expectedURL: BASE_URL + "/odd%3Dsearch%3Awith%26weird%22characters",
307 // Setup tests for homepageURL and getSearchURL()
310 initiallyUndefined: true,
311 preference: PREF_GETADDONS_BROWSEADDONS,
313 getURL: () => AddonRepository.homepageURL,
316 initiallyUndefined: false,
317 preference: PREF_GETADDONS_BROWSESEARCHRESULTS,
318 urlTests: urlTests.concat(searchURLTests),
319 getURL: function getSearchURL(aTest) {
321 aTest && aTest.searchTerms ? aTest.searchTerms : "unused terms";
322 return AddonRepository.getSearchURL(searchTerms);
327 tests.forEach(function url_test(aTest) {
328 if (aTest.initiallyUndefined) {
329 // Preference is not defined by default
331 Services.prefs.getPrefType(aTest.preference),
332 Services.prefs.PREF_INVALID
334 Assert.equal(aTest.getURL(), DEFAULT_URL);
337 check_urls(aTest.preference, aTest.getURL, aTest.urlTests);
341 // Tests failure of AddonRepository.getAddonsByIDs()
342 add_task(async function test_getAddonsByID_fails() {
343 Services.prefs.setCharPref(GET_TEST.preference, GET_TEST.preferenceValue);
345 await Assert.rejects(
346 AddonRepository.getAddonsByIDs(GET_TEST.failedIDs),
347 /Error: GET.*?failed/
351 // Tests success of AddonRepository.getAddonsByIDs()
352 add_task(async function test_getAddonsByID_succeeds() {
353 let result = await AddonRepository.getAddonsByIDs(GET_TEST.successfulIDs);
355 check_results(result, GET_RESULTS);
358 // Tests success of AddonRepository.getAddonsByIDs() with rta ID.
359 add_task(async function test_getAddonsByID_rta() {
360 let id = `rta:${btoa(GET_TEST.successfulIDs[0])}`.slice(0, -1);
361 GET_TEST.successfulIDs[0] = id;
362 let result = await AddonRepository.getAddonsByIDs(GET_TEST.successfulIDs);
364 check_results(result, GET_RESULTS);
369 pref_set: [[PREF_GET_BROWSER_MAPPINGS, GET_BROWSER_MAPPINGS_URL]],
371 async function test_getMappedAddons() {
376 } = await AddonRepository.getMappedAddons("valid-browser-id", [
377 "browser-extension-test-1",
378 "browser-extension-test-2",
379 // This one is mapped but the search API won't return any data.
380 "browser-extension-test-3",
381 "browser-extension-test-4",
382 // These ones are not mapped to any Firefox add-ons.
383 "browser-extension-test-5",
384 "browser-extension-test-6",
386 Assert.equal(result.length, 3, "expected 3 mapped add-ons");
387 check_results(result, GET_RESULTS);
388 Assert.deepEqual(matchedIDs, [
389 "browser-extension-test-1",
390 "browser-extension-test-2",
391 "browser-extension-test-3",
392 "browser-extension-test-4",
394 Assert.deepEqual(unmatchedIDs, [
395 "browser-extension-test-5",
396 "browser-extension-test-6",
403 pref_set: [[PREF_GET_BROWSER_MAPPINGS, GET_BROWSER_MAPPINGS_URL]],
405 async function test_getMappedAddons_empty_list_of_ids() {
410 } = await AddonRepository.getMappedAddons("valid-browser-id", []);
411 Assert.equal(result.length, 0, "expected 0 mapped add-ons");
412 Assert.equal(matchedIDs.length, 0, "expected 0 matched IDs");
413 Assert.equal(unmatchedIDs.length, 0, "expected 0 unmatched IDs");
419 pref_set: [[PREF_GET_BROWSER_MAPPINGS, GET_BROWSER_MAPPINGS_URL]],
421 async function test_getMappedAddons_invalid_ids() {
426 } = await AddonRepository.getMappedAddons("valid-browser-id", [
431 Assert.equal(result.length, 0, "expected 0 mapped add-ons");
432 Assert.equal(matchedIDs.length, 0, "expected 0 matched IDs");
433 Assert.deepEqual(unmatchedIDs, ["", null, undefined]);
439 pref_set: [[PREF_GET_BROWSER_MAPPINGS, GET_BROWSER_MAPPINGS_URL]],
441 async function test_getMappedAddons_empty_mapping() {
446 } = await AddonRepository.getMappedAddons("browser-id-empty-results", [
447 "browser-extension-test-1",
448 "browser-extension-test-2",
449 "browser-extension-test-3",
451 Assert.equal(result.length, 0, "expected no mapped add-ons");
452 Assert.equal(matchedIDs.length, 0, "expected 0 matched IDs");
453 Assert.equal(unmatchedIDs.length, 3, "expected 3 unmatched IDs");
461 PREF_GET_BROWSER_MAPPINGS,
462 `${BASE_URL}/browser-mappings/with-paging/%BROWSER%/?1`,
466 async function test_getMappedAddons_with_paging() {
471 } = await AddonRepository.getMappedAddons("valid-browser-id", [
472 "browser-extension-test-1",
473 "browser-extension-test-2",
474 // This one is mapped but the search API won't return any data.
475 "browser-extension-test-3",
476 "browser-extension-test-4",
478 Assert.equal(result.length, 3, "expected 3 mapped add-ons");
479 check_results(result, GET_RESULTS);
480 Assert.deepEqual(matchedIDs, [
481 "browser-extension-test-1",
482 "browser-extension-test-2",
483 "browser-extension-test-3",
484 "browser-extension-test-4",
486 Assert.deepEqual(unmatchedIDs, []);