summaryrefslogtreecommitdiffstats
path: root/testing/mochitest/jetpack-package-harness.js
diff options
context:
space:
mode:
Diffstat (limited to 'testing/mochitest/jetpack-package-harness.js')
-rw-r--r--testing/mochitest/jetpack-package-harness.js250
1 files changed, 250 insertions, 0 deletions
diff --git a/testing/mochitest/jetpack-package-harness.js b/testing/mochitest/jetpack-package-harness.js
new file mode 100644
index 000000000..a25706f49
--- /dev/null
+++ b/testing/mochitest/jetpack-package-harness.js
@@ -0,0 +1,250 @@
+/* -*- js-indent-level: 2; tab-width: 2; indent-tabs-mode: nil -*- */
+const TEST_PACKAGE = "chrome://mochitests/content/";
+
+// Make sure to use the real add-on ID to get the e10s shims activated
+const TEST_ID = "mochikit@mozilla.org";
+
+var gConfig;
+
+if (Cc === undefined) {
+ var Cc = Components.classes;
+ var Ci = Components.interfaces;
+ var Cu = Components.utils;
+}
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Task.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "Services",
+ "resource://gre/modules/Services.jsm");
+
+setTimeout(testInit, 0);
+
+// Tests a single module
+function testModule(require, { url, expected }) {
+ return new Promise(resolve => {
+ let path = url.substring(TEST_PACKAGE.length);
+
+ const { stdout } = require("sdk/system");
+
+ const { runTests } = require("sdk/test/harness");
+ const loaderModule = require("toolkit/loader");
+ const options = require("sdk/test/options");
+
+ function findAndRunTests(loader, nextIteration) {
+ const { TestRunner } = loaderModule.main(loader, "sdk/deprecated/unit-test");
+
+ const NOT_TESTS = ['setup', 'teardown'];
+ var runner = new TestRunner();
+
+ let tests = [];
+
+ let suiteModule;
+ try {
+ dump("TEST-INFO: " + path + " | Loading test module\n");
+ suiteModule = loaderModule.main(loader, "tests/" + path.substring(0, path.length - 3));
+ }
+ catch (e) {
+ // If `Unsupported Application` error thrown during test,
+ // skip the test suite
+ suiteModule = {
+ 'test suite skipped': assert => assert.pass(e.message)
+ };
+ }
+
+ for (let name of Object.keys(suiteModule).sort()) {
+ if (NOT_TESTS.indexOf(name) != -1)
+ continue;
+
+ tests.push({
+ setup: suiteModule.setup,
+ teardown: suiteModule.teardown,
+ testFunction: suiteModule[name],
+ name: path + "." + name
+ });
+ }
+
+ runner.startMany({
+ tests: {
+ getNext: () => Promise.resolve(tests.shift())
+ },
+ stopOnError: options.stopOnError,
+ onDone: nextIteration
+ });
+ }
+
+ runTests({
+ findAndRunTests: findAndRunTests,
+ iterations: options.iterations,
+ filter: options.filter,
+ profileMemory: options.profileMemory,
+ stopOnError: options.stopOnError,
+ verbose: options.verbose,
+ parseable: options.parseable,
+ print: stdout.write,
+ onDone: resolve
+ });
+ });
+}
+
+// Sets the test prefs
+function setPrefs(root, options) {
+ Object.keys(options).forEach(id => {
+ const key = root + "." + id;
+ const value = options[id]
+ const type = typeof(value);
+
+ value === null ? void(0) :
+ value === undefined ? void(0) :
+ type === "boolean" ? Services.prefs.setBoolPref(key, value) :
+ type === "string" ? Services.prefs.setCharPref(key, value) :
+ type === "number" ? Services.prefs.setIntPref(key, parseInt(value)) :
+ type === "object" ? setPrefs(key, value) :
+ void(0);
+ });
+}
+
+function testInit() {
+ // Make sure to run the test harness for the first opened window only
+ if (Services.prefs.prefHasUserValue("testing.jetpackTestHarness.running"))
+ return;
+
+ Services.prefs.setBoolPref("testing.jetpackTestHarness.running", true);
+
+ // Need to set this very early, otherwise the false value gets cached in
+ // DOM bindings code.
+ Services.prefs.setBoolPref("dom.indexedDB.experimental", true);
+
+ // Get the list of tests to run
+ let config = readConfig();
+ getTestList(config, function(links) {
+ try {
+ let fileNames = [];
+ let fileNameRegexp = /test-.+\.js$/;
+ arrayOfTestFiles(links, fileNames, fileNameRegexp);
+
+ if (config.startAt || config.endAt) {
+ fileNames = skipTests(fileNames, config.startAt, config.endAt);
+ }
+
+ // The SDK assumes it is being run from resource URIs
+ let chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIChromeRegistry);
+ let realPath = chromeReg.convertChromeURL(Services.io.newURI(TEST_PACKAGE, null, null));
+ let resProtocol = Cc["@mozilla.org/network/protocol;1?name=resource"].getService(Ci.nsIResProtocolHandler);
+ resProtocol.setSubstitution("jetpack-package-tests", realPath);
+
+ // Set the test options
+ const options = {
+ test: {
+ iterations: config.runUntilFailure ? config.repeat : 1,
+ stop: false,
+ keepOpen: true,
+ },
+ profile: {
+ memory: false,
+ leaks: false,
+ },
+ output: {
+ logLevel: "verbose",
+ format: "tbpl",
+ },
+ console: {
+ logLevel: "info",
+ },
+ }
+ setPrefs("extensions." + TEST_ID + ".sdk", options);
+
+ // Override the SDK modules if necessary
+ let sdkpath = "resource://gre/modules/commonjs/";
+ try {
+ let sdklibs = Services.prefs.getCharPref("extensions.sdk.path");
+ // sdkpath is a file path, make it a URI and map a resource URI to it
+ let sdkfile = Cc["@mozilla.org/file/local;1"].
+ createInstance(Ci.nsIFile);
+ sdkfile.initWithPath(sdklibs);
+ let sdkuri = Services.io.newFileURI(sdkfile);
+ resProtocol.setSubstitution("jetpack-modules", sdkuri);
+ sdkpath = "resource://jetpack-modules/";
+ }
+ catch (e) {
+ // Stick with the built-in modules
+ }
+
+ const paths = {
+ "": sdkpath,
+ "tests/": "resource://jetpack-package-tests/",
+ };
+
+ // Create the base module loader to load the test harness
+ const loaderID = "toolkit/loader";
+ const loaderURI = paths[""] + loaderID + ".js";
+ const loaderModule = Cu.import(loaderURI, {}).Loader;
+
+ const modules = {};
+
+ // Manually set the loader's module cache to include itself;
+ // which otherwise fails due to lack of `Components`.
+ modules[loaderID] = loaderModule;
+ modules["@test/options"] = {};
+
+ let loader = loaderModule.Loader({
+ id: TEST_ID,
+ name: "addon-sdk",
+ version: "1.0",
+ loadReason: "install",
+ paths: paths,
+ modules: modules,
+ isNative: true,
+ rootURI: paths["tests/"],
+ prefixURI: paths["tests/"],
+ metadata: {},
+ });
+
+ const module = loaderModule.Module(loaderID, loaderURI);
+ const require = loaderModule.Require(loader, module);
+
+ // Wait until the add-on window is ready
+ require("sdk/addon/window").ready.then(() => {
+ let passed = 0;
+ let failed = 0;
+
+ function finish() {
+ if (passed + failed == 0) {
+ dump("TEST-UNEXPECTED-FAIL | jetpack-package-harness.js | " +
+ "No tests to run. Did you pass invalid test_paths?\n");
+ }
+ else {
+ dump("Jetpack Package Test Summary\n");
+ dump("\tPassed: " + passed + "\n" +
+ "\tFailed: " + failed + "\n" +
+ "\tTodo: 0\n");
+ }
+
+ if (config.closeWhenDone) {
+ require("sdk/system").exit(failed == 0 ? 0 : 1);
+ }
+ else {
+ loaderModule.unload(loader, "shutdown");
+ }
+ }
+
+ function testNextModule() {
+ if (fileNames.length == 0)
+ return finish();
+
+ let filename = fileNames.shift();
+ testModule(require, filename).then(tests => {
+ passed += tests.passed;
+ failed += tests.failed;
+ }).then(testNextModule);
+ }
+
+ testNextModule();
+ });
+ }
+ catch (e) {
+ dump("TEST-UNEXPECTED-FAIL: jetpack-package-harness.js | error starting test harness (" + e + ")\n");
+ dump(e.stack);
+ }
+ });
+}