Merge pull request #866 from meeber/throw-doc

docs: rewrite `.throw` jsdoc
This commit is contained in:
Keith Cirkel 2016-11-15 23:30:46 +00:00 committed by GitHub
commit 0836c4539e

View file

@ -1501,31 +1501,113 @@ module.exports = function (chai, _) {
Assertion.addMethod('key', assertKeys);
/**
* ### .throw(constructor)
* ### .throw([errorLike], [errMsgMatcher])
*
* Asserts that the target function will throw a specific error, or specific type of error
* (as determined using `instanceof`), optionally with a RegExp or String inclusion test
* for the error's message.
* If an Error instance is provided, it asserts that the error thrown and the instance
* provided are the same.
* If an Error constructor is provided, it asserts that the error thrown is an instance
* of the constructor provided.
* Invokes the target function and asserts that an error is thrown. The
* `throw` assertion accepts optional arguments that can be used to perform
* additional assertions on the thrown error, as explained below.
*
* var err = new ReferenceError('This is a bad function.');
* var fn = function () { throw err; }
* expect(fn).to.throw();
* expect(fn).to.throw(ReferenceError);
* expect(fn).to.throw(Error);
* expect(fn).to.throw(/bad function/);
* expect(fn).to.not.throw('good function');
* expect(fn).to.throw(ReferenceError, /bad function/);
* expect(fn).to.throw(err);
* If no arguments are provided, `throw` invokes the function and asserts that
* an error is thrown.
*
* Furthermore, `throw` changes the context of the assertion (just like `property`)
* to the thrown error. This permits for further chainable assertions on the thrown error.
* var badFn = function () { throw new TypeError("Illegal salmon!"); };
* expect(badFn).to.throw();
* var goodFn = function () {};
* expect(goodFn).to.not.throw();
*
* expect(fn).to.throw(ReferenceError)
* .and.have.property('message').equal('This is a bad function.');
* If the first argument is an error constructor, `throw` invokes the function
* and asserts that an error is thrown that's an instance of that constructor.
*
* var badFn = function () { throw new TypeError("Illegal salmon!"); };
* expect(badFn).to.throw(TypeError);
* expect(badFn).to.not.throw(ReferenceError);
*
* If the first argument is an error instance, `throw` invokes the function
* and asserts that an error is thrown that's referentially equal (===) to
* that instance.
*
* var err = new TypeError("Illegal salmon!");
* var badFn = function () { throw err; };
* expect(badFn).to.throw(err);
* expect(badFn).to.not.throw(new TypeError("Illegal salmon!"));
*
* If the first argument is a string, `throw` invokes the function and asserts
* that an error is thrown with a message that contains that string.
*
* var badFn = function () { throw new TypeError("Illegal salmon!"); };
* expect(badFn).to.throw("salmon");
* expect(badFn).to.not.throw("kangaroo");
*
* If the first argument is a regular expression, `throw` invokes the function
* and asserts that an error is thrown with a message that matches that
* regular expression.
*
* var badFn = function () { throw new TypeError("Illegal salmon!"); };
* expect(badFn).to.throw(/salmon/);
* expect(badFn).to.not.throw(/kangaroo/);
*
* It's also possible to combine two assertions into one by providing two
* arguments. If the first argument is an error instance or constructor, and
* the second argument is a string or regular expression, `throw` invokes the
* function and asserts that an error is thrown that passes both assertions as
* described above.
*
* var err = new TypeError("Illegal salmon!");
* var badFn = function () { throw err; };
* expect(badFn).to.throw(TypeError, "salmon");
* expect(badFn).to.throw(TypeError, /salmon/);
* expect(badFn).to.throw(err, "salmon");
* expect(badFn).to.throw(err, /salmon/);
* expect(badFn).to.not.throw(TypeError, "kangaroo");
* expect(badFn).to.not.throw(TypeError, /kangaroo/);
* expect(badFn).to.not.throw(ReferenceError, "salmon");
* expect(badFn).to.not.throw(ReferenceError, /salmon/);
* expect(badFn).to.not.throw(err, "kangaroo");
* expect(badFn).to.not.throw(err, /kangaroo/);
* expect(badFn).to.not.throw(new TypeError("Illegal salmon!"), "salmon");
* expect(badFn).to.not.throw(new TypeError("Illegal salmon!"), /salmon/);
*
* Note that `throw` changes the context of the assertion to the thrown error.
* This allows for further chainable assertions on the thrown error.
*
* var err = new TypeError("Illegal salmon!");
* err.code = 42;
* var badFn = function () { throw err; };
* expect(badFn).to.throw(TypeError).and.have.property('code', 42);
*
* Beware of some common mistakes when using the `throw` assertion. One common
* mistake is to accidentally invoke the function yourself instead of letting
* the `throw` assertion invoke the function for you. For example, when
* testing if a function named `fn` throws, provide `fn` instead of `fn()` as
* the target for the assertion:
*
* expect(fn).to.throw(); // Good! Tests `fn` as desired
* expect(fn()).to.throw(); // Bad! Tests result of `fn()`, not `fn`
*
* If you need to assert that your function `fn` throws when passed certain
* arguments, then wrap a call to `fn` inside of another function like so:
*
* expect(function () { fn(42); }).to.throw(); // Function expression
* expect(() => fn(42)).to.throw(); // ES6 arrow function
*
* Another common mistake is to provide an object method (or any stand-alone
* function that relies on `this`). Doing so is problematic because the `this`
* context will be lost when the function is invoked by the `throws`
* assertion; there's no way for it to know what `this` is supposed to be.
* There are two ways around this problem. One solution is to wrap the method
* or function call inside of another function. Another solution is to use
* `bind`. For example:
*
* expect(function () { cat.meow(); }).to.throw(); // Function expression
* expect(() => cat.meow()).to.throw(); // ES6 arrow function
* expect(cat.meow.bind(cat)).to.throw(); // Bind
*
* Finally, it's worth mentioning that it's a best practice in JavaScript to
* only throw `Error` and derivatives of `Error` such as `ReferenceError`,
* `TypeError`, and user-defined objects that extend `Error`. No other type of
* value will generate a stack trace when initialized. With that said, the
* `throw` assertion does technically support any type of value being thrown,
* not just `Error` and its derivatives.
*
* @name throw
* @alias throws