Bug 1290901 - [webext] Add xpcshell test cases on nested namespaces and null/empty api objects. r=aswan draft
authorLuca Greco <lgreco@mozilla.com>
Tue, 02 Aug 2016 04:00:46 +0200
changeset 400685 4c2fa93c8fb43682ed4674bc7fe27ef2b1464efb
parent 400684 7cacd2d5b5c0e1ef354e2cef19c7d809cc632470
child 528292 5b6e735a0bc3bb86f035a9c2fcb5ad462ba8ecab
push id26244
push userluca.greco@alcacoop.it
push dateMon, 15 Aug 2016 13:54:41 +0000
reviewersaswan
bugs1290901
milestone51.0a1
Bug 1290901 - [webext] Add xpcshell test cases on nested namespaces and null/empty api objects. r=aswan MozReview-Commit-ID: HKh3gXTk09H
toolkit/components/extensions/test/xpcshell/test_ext_schemas.js
toolkit/components/extensions/test/xpcshell/test_ext_schemas_api_injection.js
toolkit/components/extensions/test/xpcshell/xpcshell.ini
--- a/toolkit/components/extensions/test/xpcshell/test_ext_schemas.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_schemas.js
@@ -1171,8 +1171,95 @@ add_task(function* testPermissions() {
   equal(typeof root.noPerms, "object", "noPerms namespace should exist");
   equal(typeof root.noPerms.noPerms, "function", "noPerms.noPerms method should exist");
   equal(typeof root.noPerms.fooPerm, "function", "noPerms.fooPerm method should exist");
 
   equal(typeof root.fooPerm, "object", "fooPerm namespace should exist");
   equal(typeof root.fooPerm.noPerms, "function", "noPerms.noPerms method should exist");
   equal(typeof root.fooPerm.fooBarPerm, "function", "noPerms.fooBarPerm method should exist");
 });
+
+let nestedNamespaceJson = [
+  {
+    "namespace": "nested.namespace",
+    "types": [
+      {
+        "id": "CustomType",
+        "type": "object",
+        "events": [
+          {
+            "name": "onEvent",
+          },
+        ],
+        "properties": {
+          "url": {
+            "type": "string",
+          },
+        },
+        "functions": [
+          {
+            "name": "functionOnCustomType",
+            "type": "function",
+            "parameters": [
+              {
+                "name": "title",
+                "type": "string",
+              },
+            ],
+          },
+        ],
+      },
+    ],
+    "properties": {
+      "instanceOfCustomType": {
+        "$ref": "CustomType",
+      },
+    },
+    "functions": [
+      {
+        "name": "create",
+        "type": "function",
+        "parameters": [
+          {
+            "name": "title",
+            "type": "string",
+          },
+        ],
+      },
+    ],
+  },
+];
+
+add_task(function* testNestedNamespace() {
+  let url = "data:," + JSON.stringify(nestedNamespaceJson);
+
+  yield Schemas.load(url);
+
+  let root = {};
+  Schemas.inject(root, wrapper);
+
+  talliedErrors.length = 0;
+
+  ok(root.nested, "The root object contains the first namespace level");
+  ok(root.nested.namespace, "The first level object contains the second namespace level");
+
+  ok(root.nested.namespace.create, "Got the expected function in the nested namespace");
+  do_check_eq(typeof root.nested.namespace.create, "function",
+     "The property is a function as expected");
+
+  let {instanceOfCustomType} = root.nested.namespace;
+
+  ok(instanceOfCustomType,
+     "Got the expected instance of the CustomType defined in the schema");
+  ok(instanceOfCustomType.functionOnCustomType,
+     "Got the expected method in the CustomType instance");
+
+  // TODO: test support events and properties in a SubModuleType defined in the schema,
+  // once implemented, e.g.:
+  //
+  // ok(instanceOfCustomType.url,
+  //    "Got the expected property defined in the CustomType instance)
+  //
+  // ok(instanceOfCustomType.onEvent &&
+  //    instanceOfCustomType.onEvent.addListener &&
+  //    typeof instanceOfCustomType.onEvent.addListener == "function",
+  //    "Got the expected event defined in the CustomType instance");
+});
new file mode 100644
--- /dev/null
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_schemas_api_injection.js
@@ -0,0 +1,100 @@
+"use strict";
+
+Components.utils.import("resource://gre/modules/Schemas.jsm");
+
+let {
+  Management,
+} = Components.utils.import("resource://gre/modules/Extension.jsm", {});
+
+let nestedNamespaceJson = [
+  {
+    "namespace": "backgroundAPI.testnamespace",
+    "functions": [
+      {
+        "name": "create",
+        "type": "function",
+        "parameters": [
+          {
+            "name": "title",
+            "type": "string",
+          },
+        ],
+      },
+    ],
+  },
+  {
+    "namespace": "noBackgroundAPI.testnamespace",
+    "functions": [
+      {
+        "name": "create",
+        "type": "function",
+        "parameters": [
+          {
+            "name": "title",
+            "type": "string",
+          },
+        ],
+      },
+    ],
+  },
+];
+
+add_task(function* testSchemaAPIInjection() {
+  let url = "data:," + JSON.stringify(nestedNamespaceJson);
+
+  // Load the schema of the fake APIs.
+  yield Schemas.load(url);
+
+  // Register an API that will skip the background page.
+  Management.registerSchemaAPI("noBackgroundAPI.testnamespace", (extension, context) => {
+    if (context.type !== "background") {
+      return {
+        noBackgroundAPI: {
+          testnamespace: {
+            create(title) {},
+          },
+        },
+      };
+    }
+
+    // This API should not be available in this context, return null so that
+    // the schema wrapper is removed as well.
+    return null;
+  });
+
+  // Register an API that will skip any but the background page.
+  Management.registerSchemaAPI("backgroundAPI.testnamespace", (extension, context) => {
+    if (context.type === "background") {
+      return {
+        backgroundAPI: {
+          testnamespace: {
+            create(title) {
+              return title;
+            },
+          },
+        },
+      };
+    }
+
+    // This API should not be available in this context, return null so that
+    // the schema wrapper is removed as well.
+    return null;
+  });
+
+  let extension = ExtensionTestUtils.loadExtension({
+    background() {
+      if (browser.noBackgroundAPI) {
+        browser.test.notifyFail("skipAPIonNull.done");
+      } else {
+        const res = browser.backgroundAPI.testnamespace.create("param-value");
+        browser.test.assertEq("param-value", res,
+                              "Got the expected result from the fake API method");
+        browser.test.notifyPass("skipAPIonNull.done");
+      }
+    },
+  });
+
+  yield extension.startup();
+  yield extension.awaitFinish("skipAPIonNull.done");
+  yield extension.unload();
+});
--- a/toolkit/components/extensions/test/xpcshell/xpcshell.ini
+++ b/toolkit/components/extensions/test/xpcshell/xpcshell.ini
@@ -36,15 +36,16 @@ skip-if = release_build
 [test_ext_manifest_content_security_policy.js]
 [test_ext_manifest_incognito.js]
 [test_ext_onmessage_removelistener.js]
 [test_ext_runtime_connect_no_receiver.js]
 [test_ext_runtime_getPlatformInfo.js]
 [test_ext_runtime_sendMessage.js]
 [test_ext_runtime_sendMessage_no_receiver.js]
 [test_ext_schemas.js]
+[test_ext_schemas_api_injection.js]
 [test_ext_simple.js]
 [test_ext_storage.js]
 [test_getAPILevelForWindow.js]
 [test_locale_converter.js]
 [test_locale_data.js]
 [test_native_messaging.js]
 skip-if = os == "android"