Skip to content

Commit

Permalink
feat: update .throw to use new .checkError
Browse files Browse the repository at this point in the history
BREAKING CHANGE: Update failed assertion messages for `.throw` for
simplicity, consistency, and correctness. Update `.throw` to only
perform criteria matching on `Error` instances.
  • Loading branch information
meeber committed Dec 27, 2017
1 parent 9c1a99f commit a3ab487
Show file tree
Hide file tree
Showing 7 changed files with 276 additions and 257 deletions.
263 changes: 106 additions & 157 deletions lib/chai/core/assertions.js

Large diffs are not rendered by default.

10 changes: 0 additions & 10 deletions lib/chai/interface/assert.js
Original file line number Diff line number Diff line change
Expand Up @@ -1962,11 +1962,6 @@ module.exports = function (chai, util) {
*/

assert.throws = function (fn, errorLike, errMsgMatcher, msg) {
if ('string' === typeof errorLike || errorLike instanceof RegExp) {
errMsgMatcher = errorLike;
errorLike = null;
}

var assertErr = new Assertion(fn, msg, assert.throws, true)
.to.throw(errorLike, errMsgMatcher);
return flag(assertErr, 'object');
Expand Down Expand Up @@ -2002,11 +1997,6 @@ module.exports = function (chai, util) {
*/

assert.doesNotThrow = function (fn, errorLike, errMsgMatcher, msg) {
if ('string' === typeof errorLike || errorLike instanceof RegExp) {
errMsgMatcher = errorLike;
errorLike = null;
}

new Assertion(fn, msg, assert.doesNotThrow, true)
.to.not.throw(errorLike, errMsgMatcher);
};
Expand Down
15 changes: 12 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
},
"dependencies": {
"assertion-error": "^1.0.1",
"check-error": "^1.0.1",
"check-error": "git+https://github.com/meeber/check-error.git#add-check-error-function",
"deep-eql": "^3.0.1",
"get-func-name": "^2.0.0",
"pathval": "^1.0.0",
Expand Down
81 changes: 60 additions & 21 deletions test/assert.js
Original file line number Diff line number Diff line change
Expand Up @@ -1588,41 +1588,60 @@ describe('assert', function () {
assert(thrownErr instanceof Error, 'assert.' + throws + ' returns error');
assert(thrownErr.message === 'foo', 'assert.' + throws + ' returns error message');

var notErrFn = function () { throw { message: 'testing' }; }
assert[throws](notErrFn);

err(function () {
assert[throws](function() { throw new Error('foo') }, TypeError);
}, "expected [Function] to throw 'TypeError' but 'Error: foo' was thrown")
}, "expected [Function] to throw a TypeError but [Error: foo] was thrown")

err(function () {
assert[throws](function() { throw new Error('foo') }, 'bar');
}, "expected [Function] to throw error including 'bar' but got 'foo'")
}, "expected [Function] to throw an Error including 'bar' but [Error: foo] was thrown")

err(function () {
assert[throws](function() { throw new Error('foo') }, Error, 'bar', 'blah');
}, "blah: expected [Function] to throw error including 'bar' but got 'foo'")
}, "blah: expected [Function] to throw an Error including 'bar' but [Error: foo] was thrown")

err(function () {
assert[throws](function() { throw new Error('foo') }, TypeError, 'bar', 'blah');
}, "blah: expected [Function] to throw 'TypeError' but 'Error: foo' was thrown")
}, "blah: expected [Function] to throw a TypeError including 'bar' but [Error: foo] was thrown")

err(function () {
assert[throws](function() {});
}, "expected [Function] to throw an error");
}, "expected [Function] to throw");

err(function () {
assert[throws](function() { throw new Error('') }, 'bar');
}, "expected [Function] to throw error including 'bar' but got ''");
}, "expected [Function] to throw an Error including 'bar' but [Error] was thrown");

err(function () {
assert[throws](function() { throw new Error('') }, /bar/);
}, "expected [Function] to throw error matching /bar/ but got ''");
}, "expected [Function] to throw an Error matching /bar/ but [Error] was thrown");

err(function () {
assert[throws]({});
}, "expected {} to be a function");
}, "object tested must be a function, but object given");

err(function () {
assert[throws]({}, Error, 'testing', 'blah');
}, "blah: expected {} to be a function");
}, "blah: object tested must be a function, but object given");

err(function () {
assert[throws](function() {}, 'testing', 'testing');
}, "errMsgMatcher must be null or undefined when errLike is a string or regular expression", true);

err(function () {
assert[throws](function() {}, {});
}, "errLike must be an Error constructor or instance, string, regular expression, or criteria object", true);

err(function () {
assert[throws](function() {}, Error, {}, 'blah');
}, "errMsgMatcher must be a string or regular expression", true);

err(function () {
assert[throws](function() {}, new Error(), 'testing', 'blah');
}, "errMsgMatcher must be null or undefined when errLike is an Error instance", true);
});
});

Expand Down Expand Up @@ -1665,53 +1684,73 @@ describe('assert', function () {
throw new Error('This is a message');
}, TypeError, /Another message/);

var notErrFn = function () { throw { message: 'testing' }; }
assert.doesNotThrow(notErrFn, Error);
assert.doesNotThrow(notErrFn, 'testing');

err(function () {
assert.doesNotThrow(function() { throw new Error('foo'); });
}, "expected [Function] to not throw an error but 'Error: foo' was thrown");
}, "expected [Function] to not throw but [Error: foo] was thrown");

err(function () {
assert.doesNotThrow(function() { throw new CustomError('foo'); });
}, "expected [Function] to not throw an error but 'CustomError: foo' was thrown");
}, /expected \[Function\] to not throw but {.*name.*message.*} was thrown/);

err(function () {
assert.doesNotThrow(function() { throw new Error('foo'); }, Error);
}, "expected [Function] to not throw 'Error' but 'Error: foo' was thrown");
}, "expected [Function] to not throw an Error but [Error: foo] was thrown");

err(function () {
assert.doesNotThrow(function() { throw new CustomError('foo'); }, CustomError);
}, "expected [Function] to not throw 'CustomError' but 'CustomError: foo' was thrown");
}, /expected \[Function\] to not throw a CustomError but {.*name.*message.*} was thrown/);

err(function () {
assert.doesNotThrow(function() { throw new Error('foo'); }, 'foo');
}, "expected [Function] to throw error not including 'foo'");
}, "expected [Function] to not throw an Error including 'foo' but [Error: foo] was thrown");

err(function () {
assert.doesNotThrow(function() { throw new Error('foo'); }, /foo/);
}, "expected [Function] to throw error not matching /foo/");
}, "expected [Function] to not throw an Error matching /foo/ but [Error: foo] was thrown");

err(function () {
assert.doesNotThrow(function() { throw new Error('foo'); }, Error, 'foo', 'blah');
}, "blah: expected [Function] to not throw 'Error' but 'Error: foo' was thrown");
}, "blah: expected [Function] to not throw an Error including 'foo' but [Error: foo] was thrown");

err(function () {
assert.doesNotThrow(function() { throw new CustomError('foo'); }, CustomError, 'foo', 'blah');
}, "blah: expected [Function] to not throw 'CustomError' but 'CustomError: foo' was thrown");
}, /blah: expected \[Function\] to not throw a CustomError including 'foo' but {.*name.*message.*} was thrown/);

err(function () {
assert.doesNotThrow(function() { throw new Error(''); }, '');
}, "expected [Function] to throw error not including ''");
}, "expected [Function] to not throw an Error including '' but [Error] was thrown");

err(function () {
assert.doesNotThrow(function() { throw new Error(''); }, Error, '');
}, "expected [Function] to not throw 'Error' but 'Error' was thrown");
}, "expected [Function] to not throw an Error including '' but [Error] was thrown");

err(function () {
assert.doesNotThrow({});
}, "expected {} to be a function");
}, "object tested must be a function, but object given");

err(function () {
assert.doesNotThrow({}, Error, 'testing', 'blah');
}, "blah: expected {} to be a function");
}, "blah: object tested must be a function, but object given");

err(function () {
assert.doesNotThrow(function() {}, 'testing', 'testing');
}, "errMsgMatcher must be null or undefined when errLike is a string or regular expression", true);

err(function () {
assert.doesNotThrow(function() {}, {});
}, "errLike must be an Error constructor or instance, string, regular expression, or criteria object", true);

err(function () {
assert.doesNotThrow(function() {}, Error, {});
}, "errMsgMatcher must be a string or regular expression", true);

err(function () {
assert.doesNotThrow(function() {}, new Error(), 'testing');
}, "errMsgMatcher must be null or undefined when errLike is an Error instance", true);
});

it('ifError', function() {
Expand Down
76 changes: 48 additions & 28 deletions test/expect.js
Original file line number Diff line number Diff line change
Expand Up @@ -2722,9 +2722,9 @@ describe('expect', function () {
, ickyErrFn = function () { throw new PoorlyConstructedError(); }
, specificErrFn = function () { throw specificError; }
, customErrFn = function() { throw new CustomError('foo'); }
, notErrFn = function () { throw { message: 'testing' }; }
, emptyErrFn = function () { throw new Error(); }
, emptyStringErrFn = function () { throw new Error(''); };

expect(goodFn).to.not.throw();
expect(goodFn).to.not.throw(Error);
expect(goodFn).to.not.throw(specificError);
Expand Down Expand Up @@ -2760,113 +2760,133 @@ describe('expect', function () {
expect(badFn).to.not.throw(Error, 'I am the wrong error message');
expect(badFn).to.not.throw(TypeError, 'testing');

expect(notErrFn).to.throw();
expect(notErrFn).to.not.throw(Error);
expect(notErrFn).to.not.throw('testing');

err(function(){
expect(goodFn, 'blah').to.throw();
}, /^blah: expected \[Function(: goodFn)*\] to throw an error$/);
}, /^blah: expected \[Function(: goodFn)*\] to throw$/);

err(function(){
expect(goodFn, 'blah').to.throw(ReferenceError);
}, /^blah: expected \[Function(: goodFn)*\] to throw ReferenceError$/);
}, /^blah: expected \[Function(: goodFn)*\] to throw a ReferenceError but no error was thrown$/);

err(function(){
expect(goodFn, 'blah').to.throw(specificError);
}, /^blah: expected \[Function(: goodFn)*\] to throw 'RangeError: boo'$/);
}, /^blah: expected \[Function(: goodFn)*\] to throw \[RangeError: boo\] but no error was thrown$/);

err(function(){
expect(badFn, 'blah').to.not.throw();
}, /^blah: expected \[Function(: badFn)*\] to not throw an error but 'Error: testing' was thrown$/);
}, /^blah: expected \[Function(: badFn)*\] to not throw but \[Error: testing\] was thrown$/);

err(function(){
expect(badFn, 'blah').to.throw(ReferenceError);
}, /^blah: expected \[Function(: badFn)*\] to throw 'ReferenceError' but 'Error: testing' was thrown$/);
}, /^blah: expected \[Function(: badFn)*\] to throw a ReferenceError but \[Error: testing\] was thrown$/);

err(function(){
expect(badFn, 'blah').to.throw(specificError);
}, /^blah: expected \[Function(: badFn)*\] to throw 'RangeError: boo' but 'Error: testing' was thrown$/);
}, /^blah: expected \[Function(: badFn)*\] to throw \[RangeError: boo\] but \[Error: testing\] was thrown$/);

err(function(){
expect(badFn, 'blah').to.not.throw(Error);
}, /^blah: expected \[Function(: badFn)*\] to not throw 'Error' but 'Error: testing' was thrown$/);
}, /^blah: expected \[Function(: badFn)*\] to not throw an Error but \[Error: testing\] was thrown$/);

err(function(){
expect(refErrFn, 'blah').to.not.throw(ReferenceError);
}, /^blah: expected \[Function(: refErrFn)*\] to not throw 'ReferenceError' but 'ReferenceError: hello' was thrown$/);
}, /^blah: expected \[Function(: refErrFn)*\] to not throw a ReferenceError but \[ReferenceError: hello\] was thrown$/);

err(function(){
expect(badFn, 'blah').to.throw(PoorlyConstructedError);
}, /^blah: expected \[Function(: badFn)*\] to throw 'PoorlyConstructedError' but 'Error: testing' was thrown$/);
}, /^blah: expected \[Function(: badFn)*\] to throw a PoorlyConstructedError but \[Error: testing\] was thrown$/);

err(function(){
expect(ickyErrFn, 'blah').to.not.throw(PoorlyConstructedError);
}, /^blah: (expected \[Function(: ickyErrFn)*\] to not throw 'PoorlyConstructedError' but)(.*)(PoorlyConstructedError|\{ Object \()(.*)(was thrown)$/);
}, /^blah: expected \[Function(: ickyErrFn)*\] to not throw a PoorlyConstructedError but {.*name.*} was thrown$/);

err(function(){
expect(ickyErrFn, 'blah').to.throw(ReferenceError);
}, /^blah: (expected \[Function(: ickyErrFn)*\] to throw 'ReferenceError' but)(.*)(PoorlyConstructedError|\{ Object \()(.*)(was thrown)$/);
}, /^blah: expected \[Function(: ickyErrFn)*\] to throw a ReferenceError but {.*name.*} was thrown$/);

err(function(){
expect(specificErrFn, 'blah').to.throw(new ReferenceError('eek'));
}, /^blah: expected \[Function(: specificErrFn)*\] to throw 'ReferenceError: eek' but 'RangeError: boo' was thrown$/);
}, /^blah: expected \[Function(: specificErrFn)*\] to throw \[ReferenceError: eek\] but \[RangeError: boo\] was thrown$/);

err(function(){
expect(specificErrFn, 'blah').to.not.throw(specificError);
}, /^blah: expected \[Function(: specificErrFn)*\] to not throw 'RangeError: boo'$/);
}, /^blah: expected \[Function(: specificErrFn)*\] to not throw \[RangeError: boo\]$/);

err(function (){
expect(badFn, 'blah').to.not.throw(/testing/);
}, /^blah: expected \[Function(: badFn)*\] to throw error not matching \/testing\/$/);
}, /^blah: expected \[Function(: badFn)*\] to not throw an Error matching \/testing\/ but \[Error: testing\] was thrown$/);

err(function () {
expect(badFn, 'blah').to.throw(/hello/);
}, /^blah: expected \[Function(: badFn)*\] to throw error matching \/hello\/ but got 'testing'$/);
}, /^blah: expected \[Function(: badFn)*\] to throw an Error matching \/hello\/ but \[Error: testing\] was thrown$/);

err(function () {
expect(badFn).to.throw(Error, /hello/, 'blah');
}, /^blah: expected \[Function(: badFn)*\] to throw error matching \/hello\/ but got 'testing'$/);
}, /^blah: expected \[Function(: badFn)*\] to throw an Error matching \/hello\/ but \[Error: testing\] was thrown$/);

err(function () {
expect(badFn, 'blah').to.throw(Error, /hello/);
}, /^blah: expected \[Function(: badFn)*\] to throw error matching \/hello\/ but got 'testing'$/);
}, /^blah: expected \[Function(: badFn)*\] to throw an Error matching \/hello\/ but \[Error: testing\] was thrown$/);

err(function () {
expect(badFn).to.throw(Error, 'hello', 'blah');
}, /^blah: expected \[Function(: badFn)*\] to throw error including 'hello' but got 'testing'$/);
}, /^blah: expected \[Function(: badFn)*\] to throw an Error including 'hello' but \[Error: testing\] was thrown$/);

err(function () {
expect(badFn, 'blah').to.throw(Error, 'hello');
}, /^blah: expected \[Function(: badFn)*\] to throw error including 'hello' but got 'testing'$/);
}, /^blah: expected \[Function(: badFn)*\] to throw an Error including 'hello' but \[Error: testing\] was thrown$/);

err(function () {
expect(customErrFn, 'blah').to.not.throw();
}, /^blah: expected \[Function(: customErrFn)*\] to not throw an error but 'CustomError: foo' was thrown$/);
}, /^blah: expected \[Function(: customErrFn)*\] to not throw but {.*name.*message.*} was thrown$/);

err(function(){
expect(badFn).to.not.throw(Error, 'testing', 'blah');
}, /^blah: expected \[Function(: badFn)*\] to not throw 'Error' but 'Error: testing' was thrown$/);
}, /^blah: expected \[Function(: badFn)*\] to not throw an Error including 'testing' but \[Error: testing\] was thrown$/);

err(function(){
expect(badFn, 'blah').to.not.throw(Error, 'testing');
}, /^blah: expected \[Function(: badFn)*\] to not throw 'Error' but 'Error: testing' was thrown$/);
}, /^blah: expected \[Function(: badFn)*\] to not throw an Error including 'testing' but \[Error: testing\] was thrown$/);

err(function(){
expect(emptyStringErrFn).to.not.throw(Error, '', 'blah');
}, /^blah: expected \[Function(: emptyStringErrFn)*\] to not throw 'Error' but 'Error' was thrown$/);
}, /^blah: expected \[Function(: emptyStringErrFn)*\] to not throw an Error including '' but \[Error\] was thrown$/);

err(function(){
expect(emptyStringErrFn, 'blah').to.not.throw(Error, '');
}, /^blah: expected \[Function(: emptyStringErrFn)*\] to not throw 'Error' but 'Error' was thrown$/);
}, /^blah: expected \[Function(: emptyStringErrFn)*\] to not throw an Error including '' but \[Error\] was thrown$/);

err(function(){
expect(emptyStringErrFn, 'blah').to.not.throw('');
}, /^blah: expected \[Function(: emptyStringErrFn)*\] to throw error not including ''$/);
}, /^blah: expected \[Function(: emptyStringErrFn)*\] to not throw an Error including '' but \[Error\] was thrown$/);

err(function () {
expect({}, 'blah').to.throw();
}, "blah: expected {} to be a function");
}, "blah: object tested must be a function, but object given");

err(function () {
expect({}).to.throw(Error, 'testing', 'blah');
}, "blah: expected {} to be a function");
}, "blah: object tested must be a function, but object given");

err(function () {
expect(goodFn).to.throw('testing', 'testing');
}, "errMsgMatcher must be null or undefined when errLike is a string or regular expression", true);

err(function () {
expect(goodFn).to.throw({});
}, "errLike must be an Error constructor or instance, string, regular expression, or criteria object", true);

err(function () {
expect(goodFn).to.throw(Error, {});
}, "errMsgMatcher must be a string or regular expression", true);

err(function () {
expect(goodFn).to.throw(specificError, 'testing');
}, "errMsgMatcher must be null or undefined when errLike is an Error instance", true);
});

it('respondTo', function(){
Expand Down
Loading

0 comments on commit a3ab487

Please sign in to comment.