Extracted the predicate version of toThrowError into its own matcher
This simplifies the signature of each matcher to something that jsdoc can actually handle. [Finishes #20622765]
This commit is contained in:
@@ -117,7 +117,8 @@ getJasmineRequireObj().requireMatchers = function(jRequire, j$) {
|
||||
'toHaveBeenCalledWith',
|
||||
'toMatch',
|
||||
'toThrow',
|
||||
'toThrowError'
|
||||
'toThrowError',
|
||||
'toThrowMatching',
|
||||
],
|
||||
matchers = {};
|
||||
|
||||
@@ -3842,8 +3843,6 @@ getJasmineRequireObj().toThrowError = function(j$) {
|
||||
|
||||
if (isAnErrorType(arguments[1])) {
|
||||
return exactMatcher(null, arguments[1]);
|
||||
} else if (j$.isFunction_(arguments[1])) {
|
||||
return predicateMatcher(arguments[1]);
|
||||
} else {
|
||||
return exactMatcher(arguments[1], null);
|
||||
}
|
||||
@@ -3860,30 +3859,12 @@ getJasmineRequireObj().toThrowError = function(j$) {
|
||||
};
|
||||
}
|
||||
|
||||
function predicateMatcher(predicate) {
|
||||
return {
|
||||
match: function(thrown) {
|
||||
if (predicate(thrown)) {
|
||||
return pass(function() {
|
||||
return 'Expected function not to throw an exception matching a predicate.';
|
||||
});
|
||||
} else {
|
||||
return fail(function() {
|
||||
return 'Expected function to throw an exception matching a predicate, ' +
|
||||
'but it threw ' + j$.fnNameFor(thrown.constructor) + ' with message ' +
|
||||
j$.pp(thrown.message) + '.';
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
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, RegExp, or Function.'));
|
||||
throw new Error(getErrorMsg('Expected is not an Error, string, or RegExp.'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3982,6 +3963,75 @@ getJasmineRequireObj().toThrowError = function(j$) {
|
||||
return toThrowError;
|
||||
};
|
||||
|
||||
getJasmineRequireObj().toThrowMatching = function(j$) {
|
||||
var usageError = j$.formatErrorMsg('<toThrowMatching>', 'expect(function() {<expectation>}).toThrowMatching(<Predicate>)');
|
||||
|
||||
/**
|
||||
* {@link expect} a function to `throw` something matching a predicate.
|
||||
* @function
|
||||
* @name matchers#toThrowMatching
|
||||
* @param {Function} predicate - A function that takes the thrown exception as its parameter and returns true if it matches.
|
||||
* @example
|
||||
* expect(function() { throw new Error('nope'); }).toThrowMatching(function(thrown) { return thrown.message === 'nope'; });
|
||||
*/
|
||||
function toThrowMatching() {
|
||||
return {
|
||||
compare: function(actual, predicate) {
|
||||
var thrown;
|
||||
|
||||
if (typeof actual !== 'function') {
|
||||
throw new Error(usageError('Actual is not a Function'));
|
||||
}
|
||||
|
||||
if (typeof predicate !== 'function') {
|
||||
throw new Error(usageError('Predicate is not a Function'));
|
||||
}
|
||||
|
||||
try {
|
||||
actual();
|
||||
return fail('Expected function to throw an exception.');
|
||||
} catch (e) {
|
||||
thrown = e;
|
||||
}
|
||||
|
||||
if (predicate(thrown)) {
|
||||
return pass('Expected function not to throw an exception matching a predicate.');
|
||||
} else {
|
||||
return fail(function() {
|
||||
return 'Expected function to throw an exception matching a predicate, ' +
|
||||
'but it threw ' + thrownDescription(thrown) + '.';
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function thrownDescription(thrown) {
|
||||
if (thrown && thrown.constructor) {
|
||||
return j$.fnNameFor(thrown.constructor) + ' with message ' +
|
||||
j$.pp(thrown.message);
|
||||
} else {
|
||||
return j$.pp(thrown);
|
||||
}
|
||||
}
|
||||
|
||||
function pass(message) {
|
||||
return {
|
||||
pass: true,
|
||||
message: message
|
||||
};
|
||||
}
|
||||
|
||||
function fail(message) {
|
||||
return {
|
||||
pass: false,
|
||||
message: message
|
||||
};
|
||||
}
|
||||
|
||||
return toThrowMatching;
|
||||
};
|
||||
|
||||
getJasmineRequireObj().MockDate = function() {
|
||||
function MockDate(global) {
|
||||
var self = this;
|
||||
|
||||
@@ -7,7 +7,7 @@ describe("toThrowError", function() {
|
||||
}).toThrowError(/Actual is not a Function/);
|
||||
});
|
||||
|
||||
it("throws an error when the expected is not an Error, string, RegExp, or function", function() {
|
||||
it("throws an error when the expected is not an Error, string, or RegExp", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toThrowError(),
|
||||
fn = function() {
|
||||
throw new Error("foo");
|
||||
@@ -15,7 +15,7 @@ describe("toThrowError", function() {
|
||||
|
||||
expect(function() {
|
||||
matcher.compare(fn, 1);
|
||||
}).toThrowError(/Expected is not an Error, string, RegExp, or Function./);
|
||||
}).toThrowError(/Expected is not an Error, string, or RegExp./);
|
||||
});
|
||||
|
||||
it("throws an error when the expected error type is not an Error", function() {
|
||||
@@ -312,32 +312,4 @@ describe("toThrowError", function() {
|
||||
expect(result.pass).toBe(false);
|
||||
expect(result.message()).toEqual("Expected function to throw TypeError with a message matching /bar/, but it threw TypeError with message 'foo'.");
|
||||
});
|
||||
|
||||
it("passes if the argument is a function that returns true when called with the error", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toThrowError(),
|
||||
predicate = function(e) { return e.message === "nope" },
|
||||
fn = function() {
|
||||
throw new TypeError("nope");
|
||||
},
|
||||
result;
|
||||
|
||||
result = matcher.compare(fn, predicate);
|
||||
|
||||
expect(result.pass).toBe(true);
|
||||
expect(result.message()).toEqual("Expected function not to throw an exception matching a predicate.");
|
||||
});
|
||||
|
||||
it("fails if the argument is a function that returns false when called with the error", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toThrowError(),
|
||||
predicate = function(e) { return e.message === "oh no" },
|
||||
fn = function() {
|
||||
throw new TypeError("nope");
|
||||
},
|
||||
result;
|
||||
|
||||
result = matcher.compare(fn, predicate);
|
||||
|
||||
expect(result.pass).toBe(false);
|
||||
expect(result.message()).toEqual("Expected function to throw an exception matching a predicate, but it threw TypeError with message 'nope'.");
|
||||
});
|
||||
});
|
||||
|
||||
73
spec/core/matchers/toThrowMatchingSpec.js
Normal file
73
spec/core/matchers/toThrowMatchingSpec.js
Normal file
@@ -0,0 +1,73 @@
|
||||
describe("toThrowMatching", function() {
|
||||
it("throws an error when the actual is not a function", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toThrowMatching();
|
||||
|
||||
expect(function() {
|
||||
matcher.compare({}, function() { return true; });
|
||||
}).toThrowError(/Actual is not a Function/);
|
||||
});
|
||||
|
||||
it("throws an error when the expected is not a function", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toThrowMatching(),
|
||||
fn = function() {
|
||||
throw new Error("foo");
|
||||
};
|
||||
|
||||
expect(function() {
|
||||
matcher.compare(fn, 1);
|
||||
}).toThrowError(/Predicate is not a Function/);
|
||||
});
|
||||
|
||||
it("fails if actual does not throw at all", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toThrowMatching(),
|
||||
fn = function() {
|
||||
return true;
|
||||
},
|
||||
result;
|
||||
|
||||
result = matcher.compare(fn, function() { return true; });
|
||||
|
||||
expect(result.pass).toBe(false);
|
||||
expect(result.message).toEqual("Expected function to throw an exception.");
|
||||
});
|
||||
|
||||
it("fails with the correct message if thrown is a falsy value", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toThrowMatching(),
|
||||
fn = function() {
|
||||
throw undefined;
|
||||
},
|
||||
result;
|
||||
|
||||
result = matcher.compare(fn, function() { return false; });
|
||||
expect(result.pass).toBe(false);
|
||||
expect(result.message()).toEqual("Expected function to throw an exception matching a predicate, but it threw undefined.");
|
||||
});
|
||||
|
||||
it("passes if the argument is a function that returns true when called with the error", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toThrowMatching(),
|
||||
predicate = function(e) { return e.message === "nope" },
|
||||
fn = function() {
|
||||
throw new TypeError("nope");
|
||||
},
|
||||
result;
|
||||
|
||||
result = matcher.compare(fn, predicate);
|
||||
|
||||
expect(result.pass).toBe(true);
|
||||
expect(result.message).toEqual("Expected function not to throw an exception matching a predicate.");
|
||||
});
|
||||
|
||||
it("fails if the argument is a function that returns false when called with the error", function() {
|
||||
var matcher = jasmineUnderTest.matchers.toThrowMatching(),
|
||||
predicate = function(e) { return e.message === "oh no" },
|
||||
fn = function() {
|
||||
throw new TypeError("nope");
|
||||
},
|
||||
result;
|
||||
|
||||
result = matcher.compare(fn, predicate);
|
||||
|
||||
expect(result.pass).toBe(false);
|
||||
expect(result.message()).toEqual("Expected function to throw an exception matching a predicate, but it threw TypeError with message 'nope'.");
|
||||
});
|
||||
});
|
||||
@@ -23,7 +23,8 @@ getJasmineRequireObj().requireMatchers = function(jRequire, j$) {
|
||||
'toHaveBeenCalledWith',
|
||||
'toMatch',
|
||||
'toThrow',
|
||||
'toThrowError'
|
||||
'toThrowError',
|
||||
'toThrowMatching',
|
||||
],
|
||||
matchers = {};
|
||||
|
||||
|
||||
@@ -56,8 +56,6 @@ getJasmineRequireObj().toThrowError = function(j$) {
|
||||
|
||||
if (isAnErrorType(arguments[1])) {
|
||||
return exactMatcher(null, arguments[1]);
|
||||
} else if (j$.isFunction_(arguments[1])) {
|
||||
return predicateMatcher(arguments[1]);
|
||||
} else {
|
||||
return exactMatcher(arguments[1], null);
|
||||
}
|
||||
@@ -74,30 +72,12 @@ getJasmineRequireObj().toThrowError = function(j$) {
|
||||
};
|
||||
}
|
||||
|
||||
function predicateMatcher(predicate) {
|
||||
return {
|
||||
match: function(thrown) {
|
||||
if (predicate(thrown)) {
|
||||
return pass(function() {
|
||||
return 'Expected function not to throw an exception matching a predicate.';
|
||||
});
|
||||
} else {
|
||||
return fail(function() {
|
||||
return 'Expected function to throw an exception matching a predicate, ' +
|
||||
'but it threw ' + j$.fnNameFor(thrown.constructor) + ' with message ' +
|
||||
j$.pp(thrown.message) + '.';
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
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, RegExp, or Function.'));
|
||||
throw new Error(getErrorMsg('Expected is not an Error, string, or RegExp.'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
68
src/core/matchers/toThrowMatching.js
Normal file
68
src/core/matchers/toThrowMatching.js
Normal file
@@ -0,0 +1,68 @@
|
||||
getJasmineRequireObj().toThrowMatching = function(j$) {
|
||||
var usageError = j$.formatErrorMsg('<toThrowMatching>', 'expect(function() {<expectation>}).toThrowMatching(<Predicate>)');
|
||||
|
||||
/**
|
||||
* {@link expect} a function to `throw` something matching a predicate.
|
||||
* @function
|
||||
* @name matchers#toThrowMatching
|
||||
* @param {Function} predicate - A function that takes the thrown exception as its parameter and returns true if it matches.
|
||||
* @example
|
||||
* expect(function() { throw new Error('nope'); }).toThrowMatching(function(thrown) { return thrown.message === 'nope'; });
|
||||
*/
|
||||
function toThrowMatching() {
|
||||
return {
|
||||
compare: function(actual, predicate) {
|
||||
var thrown;
|
||||
|
||||
if (typeof actual !== 'function') {
|
||||
throw new Error(usageError('Actual is not a Function'));
|
||||
}
|
||||
|
||||
if (typeof predicate !== 'function') {
|
||||
throw new Error(usageError('Predicate is not a Function'));
|
||||
}
|
||||
|
||||
try {
|
||||
actual();
|
||||
return fail('Expected function to throw an exception.');
|
||||
} catch (e) {
|
||||
thrown = e;
|
||||
}
|
||||
|
||||
if (predicate(thrown)) {
|
||||
return pass('Expected function not to throw an exception matching a predicate.');
|
||||
} else {
|
||||
return fail(function() {
|
||||
return 'Expected function to throw an exception matching a predicate, ' +
|
||||
'but it threw ' + thrownDescription(thrown) + '.';
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function thrownDescription(thrown) {
|
||||
if (thrown && thrown.constructor) {
|
||||
return j$.fnNameFor(thrown.constructor) + ' with message ' +
|
||||
j$.pp(thrown.message);
|
||||
} else {
|
||||
return j$.pp(thrown);
|
||||
}
|
||||
}
|
||||
|
||||
function pass(message) {
|
||||
return {
|
||||
pass: true,
|
||||
message: message
|
||||
};
|
||||
}
|
||||
|
||||
function fail(message) {
|
||||
return {
|
||||
pass: false,
|
||||
message: message
|
||||
};
|
||||
}
|
||||
|
||||
return toThrowMatching;
|
||||
};
|
||||
Reference in New Issue
Block a user