Files
jasmine/src/core/matchers/toThrowError.js
2018-01-29 16:46:30 -08:00

167 lines
4.8 KiB
JavaScript

getJasmineRequireObj().toThrowError = function(j$) {
var getErrorMsg = j$.formatErrorMsg('<toThrowError>', 'expect(function() {<expectation>}).toThrowError(<ErrorConstructor>, <message>)');
/**
* {@link expect} a function to `throw` an `Error`.
* @function
* @name matchers#toThrowError
* @param {Error} [expected] - `Error` constructor the object that was thrown needs to be an instance of. If not provided, `Error` will be used.
* @param {RegExp|String} [message] - The message that should be set on the thrown `Error`
* @example
* expect(function() { return 'things'; }).toThrowError(MyCustomError, 'message');
* expect(function() { return 'things'; }).toThrowError(MyCustomError, /bar/);
* expect(function() { return 'stuff'; }).toThrowError(MyCustomError);
* expect(function() { return 'other'; }).toThrowError(/foo/);
* expect(function() { return 'other'; }).toThrowError();
*/
function toThrowError () {
return {
compare: function(actual) {
var errorMatcher = getMatcher.apply(null, arguments),
thrown;
if (typeof actual != 'function') {
throw new Error(getErrorMsg('Actual is not a Function'));
}
try {
actual();
return fail('Expected function to throw an Error.');
} catch (e) {
thrown = e;
}
if (!j$.isError_(thrown)) {
return fail(function() { return 'Expected function to throw an Error, but it threw ' + j$.pp(thrown) + '.'; });
}
return errorMatcher.match(thrown);
}
};
function getMatcher() {
var expected, errorType;
if (arguments[2]) {
errorType = arguments[1];
expected = arguments[2];
if (!isAnErrorType(errorType)) {
throw new Error(getErrorMsg('Expected error type is not an Error.'));
}
return exactMatcher(expected, errorType);
} else if (arguments[1]) {
expected = arguments[1];
if (isAnErrorType(arguments[1])) {
return exactMatcher(null, arguments[1]);
} else {
return exactMatcher(arguments[1], null);
}
} else {
return anyMatcher();
}
}
function anyMatcher() {
return {
match: function(error) {
return pass('Expected function not to throw an Error, but it threw ' + j$.fnNameFor(error) + '.');
}
};
}
function exactMatcher(expected, errorType) {
if (expected && !isStringOrRegExp(expected)) {
if (errorType) {
throw new Error(getErrorMsg('Expected error message is not a string or RegExp.'));
} else {
throw new Error(getErrorMsg('Expected is not an Error, string, or RegExp.'));
}
}
function messageMatch(message) {
if (typeof expected == 'string') {
return expected == message;
} else {
return expected.test(message);
}
}
var errorTypeDescription = errorType ? j$.fnNameFor(errorType) : 'an exception';
function thrownDescription(thrown) {
var thrownName = errorType ? j$.fnNameFor(thrown.constructor) : 'an exception',
thrownMessage = '';
if (expected) {
thrownMessage = ' with message ' + j$.pp(thrown.message);
}
return thrownName + thrownMessage;
}
function messageDescription() {
if (expected === null) {
return '';
} else if (expected instanceof RegExp) {
return ' with a message matching ' + j$.pp(expected);
} else {
return ' with message ' + j$.pp(expected);
}
}
function matches(error) {
return (errorType === null || error instanceof errorType) &&
(expected === null || messageMatch(error.message));
}
return {
match: function(thrown) {
if (matches(thrown)) {
return pass(function() {
return 'Expected function not to throw ' + errorTypeDescription + messageDescription() + '.';
});
} else {
return fail(function() {
return 'Expected function to throw ' + errorTypeDescription + messageDescription() +
', but it threw ' + thrownDescription(thrown) + '.';
});
}
}
};
}
function isStringOrRegExp(potential) {
return potential instanceof RegExp || (typeof potential == 'string');
}
function isAnErrorType(type) {
if (typeof type !== 'function') {
return false;
}
var Surrogate = function() {};
Surrogate.prototype = type.prototype;
return j$.isError_(new Surrogate());
}
}
function pass(message) {
return {
pass: true,
message: message
};
}
function fail(message) {
return {
pass: false,
message: message
};
}
return toThrowError;
};