summaryrefslogtreecommitdiffstats
path: root/toolkit/components/extensions/test/xpcshell/test_ext_experiments.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/extensions/test/xpcshell/test_ext_experiments.js')
-rw-r--r--toolkit/components/extensions/test/xpcshell/test_ext_experiments.js377
1 files changed, 377 insertions, 0 deletions
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_experiments.js b/toolkit/components/extensions/test/xpcshell/test_ext_experiments.js
new file mode 100644
index 0000000000..802ec69240
--- /dev/null
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_experiments.js
@@ -0,0 +1,377 @@
+"use strict";
+
+/* globals browser */
+const { AddonSettings } = ChromeUtils.importESModule(
+ "resource://gre/modules/addons/AddonSettings.sys.mjs"
+);
+
+AddonTestUtils.init(this);
+AddonTestUtils.overrideCertDB();
+AddonTestUtils.createAppInfo(
+ "xpcshell@tests.mozilla.org",
+ "XPCShell",
+ "1",
+ "42"
+);
+
+add_task(async function setup() {
+ AddonTestUtils.overrideCertDB();
+ await ExtensionTestUtils.startAddonManager();
+});
+
+let fooExperimentAPIs = {
+ foo: {
+ schema: "schema.json",
+ parent: {
+ scopes: ["addon_parent"],
+ script: "parent.js",
+ paths: [["experiments", "foo", "parent"]],
+ },
+ child: {
+ scopes: ["addon_child"],
+ script: "child.js",
+ paths: [["experiments", "foo", "child"]],
+ },
+ },
+};
+
+let fooExperimentFiles = {
+ "schema.json": JSON.stringify([
+ {
+ namespace: "experiments.foo",
+ types: [
+ {
+ id: "Meh",
+ type: "object",
+ properties: {},
+ },
+ ],
+ functions: [
+ {
+ name: "parent",
+ type: "function",
+ async: true,
+ parameters: [],
+ },
+ {
+ name: "child",
+ type: "function",
+ parameters: [],
+ returns: { type: "string" },
+ },
+ ],
+ },
+ ]),
+
+ /* globals ExtensionAPI */
+ "parent.js": () => {
+ this.foo = class extends ExtensionAPI {
+ getAPI(context) {
+ return {
+ experiments: {
+ foo: {
+ parent() {
+ return Promise.resolve("parent");
+ },
+ },
+ },
+ };
+ }
+ };
+ },
+
+ "child.js": () => {
+ this.foo = class extends ExtensionAPI {
+ getAPI(context) {
+ return {
+ experiments: {
+ foo: {
+ child() {
+ return "child";
+ },
+ },
+ },
+ };
+ }
+ };
+ },
+};
+
+async function testFooExperiment() {
+ browser.test.assertEq(
+ "object",
+ typeof browser.experiments,
+ "typeof browser.experiments"
+ );
+
+ browser.test.assertEq(
+ "object",
+ typeof browser.experiments.foo,
+ "typeof browser.experiments.foo"
+ );
+
+ browser.test.assertEq(
+ "function",
+ typeof browser.experiments.foo.child,
+ "typeof browser.experiments.foo.child"
+ );
+
+ browser.test.assertEq(
+ "function",
+ typeof browser.experiments.foo.parent,
+ "typeof browser.experiments.foo.parent"
+ );
+
+ browser.test.assertEq(
+ "child",
+ browser.experiments.foo.child(),
+ "foo.child()"
+ );
+
+ browser.test.assertEq(
+ "parent",
+ await browser.experiments.foo.parent(),
+ "await foo.parent()"
+ );
+}
+
+async function testFooFailExperiment() {
+ browser.test.assertEq(
+ "object",
+ typeof browser.experiments,
+ "typeof browser.experiments"
+ );
+
+ browser.test.assertEq(
+ "undefined",
+ typeof browser.experiments.foo,
+ "typeof browser.experiments.foo"
+ );
+}
+
+add_task(async function test_bundled_experiments() {
+ let testCases = [
+ { isSystem: true, temporarilyInstalled: true, shouldHaveExperiments: true },
+ {
+ isSystem: true,
+ temporarilyInstalled: false,
+ shouldHaveExperiments: true,
+ },
+ {
+ isPrivileged: true,
+ temporarilyInstalled: true,
+ shouldHaveExperiments: true,
+ },
+ {
+ isPrivileged: true,
+ temporarilyInstalled: false,
+ shouldHaveExperiments: true,
+ },
+ {
+ isPrivileged: false,
+ temporarilyInstalled: true,
+ shouldHaveExperiments: AddonSettings.EXPERIMENTS_ENABLED,
+ },
+ {
+ isPrivileged: false,
+ temporarilyInstalled: false,
+ shouldHaveExperiments: AppConstants.MOZ_APP_NAME == "thunderbird",
+ },
+ ];
+
+ async function background(shouldHaveExperiments) {
+ if (shouldHaveExperiments) {
+ await testFooExperiment();
+ } else {
+ await testFooFailExperiment();
+ }
+
+ browser.test.notifyPass("background.experiments.foo");
+ }
+
+ for (let testCase of testCases) {
+ let extension = ExtensionTestUtils.loadExtension({
+ isPrivileged: testCase.isPrivileged,
+ isSystem: testCase.isSystem,
+ temporarilyInstalled: testCase.temporarilyInstalled,
+
+ manifest: {
+ experiment_apis: fooExperimentAPIs,
+ },
+
+ background: `
+ ${testFooExperiment}
+ ${testFooFailExperiment}
+ (${background})(${testCase.shouldHaveExperiments});
+ `,
+
+ files: fooExperimentFiles,
+ });
+
+ if (testCase.temporarilyInstalled && !testCase.shouldHaveExperiments) {
+ ExtensionTestUtils.failOnSchemaWarnings(false);
+ await Assert.rejects(
+ extension.startup(),
+ /Using 'experiment_apis' requires a privileged add-on/,
+ "startup failed without experimental api access"
+ );
+ ExtensionTestUtils.failOnSchemaWarnings(true);
+ } else {
+ await extension.startup();
+
+ await extension.awaitFinish("background.experiments.foo");
+
+ await extension.unload();
+ }
+ }
+});
+
+add_task(async function test_unbundled_experiments() {
+ async function background() {
+ await testFooExperiment();
+
+ browser.test.assertEq(
+ "object",
+ typeof browser.experiments.crunk,
+ "typeof browser.experiments.crunk"
+ );
+
+ browser.test.assertEq(
+ "function",
+ typeof browser.experiments.crunk.child,
+ "typeof browser.experiments.crunk.child"
+ );
+
+ browser.test.assertEq(
+ "function",
+ typeof browser.experiments.crunk.parent,
+ "typeof browser.experiments.crunk.parent"
+ );
+
+ browser.test.assertEq(
+ "crunk-child",
+ browser.experiments.crunk.child(),
+ "crunk.child()"
+ );
+
+ browser.test.assertEq(
+ "crunk-parent",
+ await browser.experiments.crunk.parent(),
+ "await crunk.parent()"
+ );
+
+ browser.test.notifyPass("background.experiments.crunk");
+ }
+
+ let extension = ExtensionTestUtils.loadExtension({
+ isPrivileged: true,
+
+ manifest: {
+ experiment_apis: fooExperimentAPIs,
+
+ permissions: ["experiments.crunk"],
+ },
+
+ background: `
+ ${testFooExperiment}
+ (${background})();
+ `,
+
+ files: fooExperimentFiles,
+ });
+
+ let apiExtension = ExtensionTestUtils.loadExtension({
+ isPrivileged: true,
+
+ manifest: {
+ browser_specific_settings: {
+ gecko: { id: "crunk@experiments.addons.mozilla.org" },
+ },
+
+ experiment_apis: {
+ crunk: {
+ schema: "schema.json",
+ parent: {
+ scopes: ["addon_parent"],
+ script: "parent.js",
+ paths: [["experiments", "crunk", "parent"]],
+ },
+ child: {
+ scopes: ["addon_child"],
+ script: "child.js",
+ paths: [["experiments", "crunk", "child"]],
+ },
+ },
+ },
+ },
+
+ files: {
+ "schema.json": JSON.stringify([
+ {
+ namespace: "experiments.crunk",
+ types: [
+ {
+ id: "Meh",
+ type: "object",
+ properties: {},
+ },
+ ],
+ functions: [
+ {
+ name: "parent",
+ type: "function",
+ async: true,
+ parameters: [],
+ },
+ {
+ name: "child",
+ type: "function",
+ parameters: [],
+ returns: { type: "string" },
+ },
+ ],
+ },
+ ]),
+
+ "parent.js": () => {
+ this.crunk = class extends ExtensionAPI {
+ getAPI(context) {
+ return {
+ experiments: {
+ crunk: {
+ parent() {
+ return Promise.resolve("crunk-parent");
+ },
+ },
+ },
+ };
+ }
+ };
+ },
+
+ "child.js": () => {
+ this.crunk = class extends ExtensionAPI {
+ getAPI(context) {
+ return {
+ experiments: {
+ crunk: {
+ child() {
+ return "crunk-child";
+ },
+ },
+ },
+ };
+ }
+ };
+ },
+ },
+ });
+
+ await apiExtension.startup();
+ await extension.startup();
+
+ await extension.awaitFinish("background.experiments.crunk");
+
+ await extension.unload();
+ await apiExtension.unload();
+});