Bug 984172 (part 1) - add Assert.rejects. r=mikedeboer
authorMark Hammond <mhammond@skippinet.com.au>
Fri, 17 Oct 2014 13:06:38 +1100
changeset 210788 7f47fcab5b5c60bd9fa6ffcd6846564e5492b9b8
parent 210787 6e7bdaa5a71ff2e87cbca793a3e4ab2630828f70
child 210789 b2a0cc22e9a62ecb55164d4b126d958671a2850e
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersmikedeboer
bugs984172
milestone36.0a1
Bug 984172 (part 1) - add Assert.rejects. r=mikedeboer
testing/modules/Assert.jsm
testing/modules/tests/xpcshell/test_assert.js
--- a/testing/modules/Assert.jsm
+++ b/testing/modules/Assert.jsm
@@ -11,16 +11,20 @@
 // MIT license: http://opensource.org/licenses/MIT
 
 "use strict";
 
 this.EXPORTED_SYMBOLS = [
   "Assert"
 ];
 
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "Promise",
+                                  "resource://gre/modules/Promise.jsm");
 /**
  * 1. The assert module provides functions that throw AssertionError's when
  * particular conditions are not met.
  *
  * To use the module you'll need to instantiate it first, which allows consumers
  * to override certain behavior on the newly obtained instance. For examples,
  * see the javadoc comments for the `report` member function.
  */
@@ -437,8 +441,39 @@ proto.throws = function(block, expected,
   }
 
   if ((actual && expected && !expectedException(actual, expected))) {
     throw actual;
   }
 
   this.report(false, expected, expected, message);
 };
+
+/**
+ * A promise that is expected to reject:
+ * assert.rejects(promise, expected, message);
+ *
+ * @param promise
+ *        (promise) A promise that is expected to reject
+ * @param expected (optional)
+ *        (mixed) Test reference to evaluate against the rejection result
+ * @param message (optional)
+ *        (string) Short explanation of the expected result
+ */
+proto.rejects = function(promise, expected, message) {
+  return new Promise((resolve, reject) => {
+    if (typeof expected === "string") {
+      message = expected;
+      expected = null;
+    }
+    return promise.then(
+      () => this.report(true, null, expected, "Missing expected exception " + message),
+      err => {
+        if (expected && !expectedException(err, expected)) {
+          reject(err);
+          return;
+        }
+        this.report(false, err, expected, message);
+        resolve();
+      }
+    ).then(null, reject);
+  });
+};
--- a/testing/modules/tests/xpcshell/test_assert.js
+++ b/testing/modules/tests/xpcshell/test_assert.js
@@ -292,9 +292,52 @@ function run_test() {
     actual: {
       toJSON: function() {
         throw "bam!";
       }
     },
     expected: "foo",
     operator: "="
   }).message, "[object Object] = \"foo\"");
+
+  run_next_test();
 }
+
+add_task(function* test_rejects() {
+  let ns = {};
+  Components.utils.import("resource://testing-common/Assert.jsm", ns);
+  let assert = new ns.Assert();
+
+  // A helper function to test failures.
+  function* checkRejectsFails(err, expected) {
+    try {
+      yield assert.rejects(Promise.reject(err), expected);
+      ok(false, "should have thrown");
+    } catch(ex) {
+      deepEqual(ex, err, "Assert.rejects threw the original unexpected error");
+    }
+  }
+
+  // A "throwable" error that's not an actual Error().
+  let SomeErrorLikeThing = function() {};
+
+  // The actual tests...
+  // No "expected" or "message" values supplied.
+  yield assert.rejects(Promise.reject(new Error("oh no")));
+  yield assert.rejects(Promise.reject("oh no"));
+
+  // An explicit error object:
+  // An instance to check against.
+  yield assert.rejects(Promise.reject(new Error("oh no")), Error, "rejected");
+  // A regex to match against the message.
+  yield assert.rejects(Promise.reject(new Error("oh no")), /oh no/, "rejected");
+
+  // Failure cases:
+  // An instance to check against that doesn't match.
+  yield checkRejectsFails(new Error("something else"), SomeErrorLikeThing);
+  // A regex that doesn't match.
+  yield checkRejectsFails(new Error("something else"), /oh no/);
+
+  // Check simple string messages.
+  yield assert.rejects(Promise.reject("oh no"), /oh no/, "rejected");
+  // Wrong message.
+  yield checkRejectsFails("something else", /oh no/);
+});