/** * @constructor * @param {jasmine.Env} env * @param actual * @param {jasmine.Spec} spec */ jasmine.Matchers = function(env, actual, spec) { this.env = env; this.actual = actual; this.spec = spec; }; jasmine.Matchers.pp = function(str) { return jasmine.util.htmlEscape(jasmine.pp(str)); }; jasmine.Matchers.prototype.report = function(result, failing_message, details) { var expectationResult = new jasmine.ExpectationResult({ passed: result, message: failing_message, details: details }); this.spec.addMatcherResult(expectationResult); return result; }; jasmine.Matchers.matcherFn_ = function(matcherName, options) { return function () { jasmine.util.extend(this, options); var matcherArgs = jasmine.util.argsToArray(arguments); var result = options.test.apply(this, arguments); var message; if (!result) { if (options.message) { message = options.message.apply(this, arguments); } else { var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); }); message = "Expected " + jasmine.pp(this.actual) + " " + englishyPredicate; if (matcherArgs.length > 0) { for (var i = 0; i < matcherArgs.length; i++) { if (i > 0) message += ","; message += " " + jasmine.pp(matcherArgs[i]); } } message += "."; } } var expectationResult = new jasmine.ExpectationResult({ matcherName: matcherName, passed: result, expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0], actual: this.actual, message: message }); this.spec.addMatcherResult(expectationResult); return result; }; }; /** * toBe: compares the actual to the expected using === * @param expected */ jasmine.Matchers.prototype.toBe = jasmine.Matchers.matcherFn_('toBe', { test: function(expected) { return this.actual === expected; } }); /** * toNotBe: compares the actual to the expected using !== * @param expected */ jasmine.Matchers.prototype.toNotBe = jasmine.Matchers.matcherFn_('toNotBe', { test: function(expected) { return this.actual !== expected; } }); /** * toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc. * * @param expected */ jasmine.Matchers.prototype.toEqual = jasmine.Matchers.matcherFn_('toEqual', { test: function(expected) { return this.env.equals_(this.actual, expected); } }); /** * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual * @param expected */ jasmine.Matchers.prototype.toNotEqual = jasmine.Matchers.matcherFn_('toNotEqual', { test: function(expected) { return !this.env.equals_(this.actual, expected); } }); /** * Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp, so takes * a pattern or a String. * * @param reg_exp */ jasmine.Matchers.prototype.toMatch = jasmine.Matchers.matcherFn_('toMatch', { test: function(expected) { return new RegExp(expected).test(this.actual); }, message: function(expected) { return jasmine.pp(this.actual) + " does not match the regular expression " + new RegExp(expected).toString(); } }); /** * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch * @param reg_exp */ jasmine.Matchers.prototype.toNotMatch = jasmine.Matchers.matcherFn_('toNotMatch', { test: function(expected) { return !(new RegExp(expected).test(this.actual)); }, message: function(expected) { return jasmine.pp(this.actual) + " should not match " + new RegExp(expected).toString(); } }); /** * Matcher that compares the actual to undefined. */ jasmine.Matchers.prototype.toBeDefined = jasmine.Matchers.matcherFn_('toBeDefined', { test: function() { return (this.actual !== undefined); } }); /** * Matcher that compares the actual to undefined. */ jasmine.Matchers.prototype.toBeUndefined = jasmine.Matchers.matcherFn_('toBeUndefined', { test: function() { return (this.actual === undefined); } }); /** * Matcher that compares the actual to null. */ jasmine.Matchers.prototype.toBeNull = jasmine.Matchers.matcherFn_('toBeNull', { test: function() { return (this.actual === null); } }); /** * Matcher that boolean not-nots the actual. */ jasmine.Matchers.prototype.toBeTruthy = jasmine.Matchers.matcherFn_('toBeTruthy', { test: function() { return !!this.actual; } }); /** * Matcher that boolean nots the actual. */ jasmine.Matchers.prototype.toBeFalsy = jasmine.Matchers.matcherFn_('toBeFalsy', { test: function() { return !this.actual; } }); /** * Matcher that checks to see if the actual, a Jasmine spy, was called. */ jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.matcherFn_('wasCalled', { test: function() { if (arguments.length > 0) { throw new Error('wasCalled does not take arguments, use wasCalledWith'); } if (!jasmine.isSpy(this.actual)) { throw new Error('Expected a spy, but got ' + jasmine.Matchers.pp(this.actual) + '.'); } return this.actual.wasCalled; }, message: function() { return "Expected spy " + this.actual.identity + " to have been called."; } }); /** * Matcher that checks to see if the actual, a Jasmine spy, was not called. */ jasmine.Matchers.prototype.wasNotCalled = jasmine.Matchers.matcherFn_('wasNotCalled', { test: function() { if (arguments.length > 0) { throw new Error('wasNotCalled does not take arguments'); } if (!jasmine.isSpy(this.actual)) { throw new Error('Expected a spy, but got ' + jasmine.Matchers.pp(this.actual) + '.'); } return !this.actual.wasCalled; }, message: function() { return "Expected spy " + this.actual.identity + " to not have been called."; } }); jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.matcherFn_('wasCalledWith', { test: function() { if (!jasmine.isSpy(this.actual)) { throw new Error('Expected a spy, but got ' + jasmine.Matchers.pp(this.actual) + '.'); } return this.env.contains_(this.actual.argsForCall, arguments); }, message: function() { return "Expected spy to have been called with " + jasmine.pp(arguments) + " but was called with " + this.actual.argsForCall; } }); /** * Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters. * * @example * */ /** * Matcher that checks that the expected item is an element in the actual Array. * * @param {Object} item */ jasmine.Matchers.prototype.toContain = jasmine.Matchers.matcherFn_('toContain', { test: function(expected) { return this.env.contains_(this.actual, expected); } }); /** * Matcher that checks that the expected item is NOT an element in the actual Array. * * @param {Object} item */ jasmine.Matchers.prototype.toNotContain = jasmine.Matchers.matcherFn_('toNotContain', { test: function(expected) { return !this.env.contains_(this.actual, expected); } }); jasmine.Matchers.prototype.toBeLessThan = jasmine.Matchers.matcherFn_('toBeLessThan', { test: function(expected) { return this.actual < expected; } }); jasmine.Matchers.prototype.toBeGreaterThan = jasmine.Matchers.matcherFn_('toBeGreaterThan', { test: function(expected) { return this.actual > expected; } }); /** * Matcher that checks that the expected exception was thrown by the actual. * * @param {String} expectedException */ jasmine.Matchers.prototype.toThrow = jasmine.Matchers.matcherFn_('toThrow', { getException_: function(actual, expected) { var exception; if (typeof actual != 'function') { throw new Error('Actual is not a function'); } try { actual(); } catch (e) { exception = e; } return exception; }, test: function(expected) { var result = false; var exception = this.getException_(this.actual, expected); if (exception) { result = (expected === undefined || this.env.equals_(exception.message || exception, expected.message || expected)); } return result; }, message: function(expected) { var exception = this.getException_(this.actual, expected); if (exception && (expected === undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) { return ["Expected function to throw", expected.message || expected, ", but it threw", exception.message || exception ].join(' '); } else { return "Expected function to throw an exception."; } } }); jasmine.Matchers.Any = function(expectedClass) { this.expectedClass = expectedClass; }; jasmine.Matchers.Any.prototype.matches = function(other) { if (this.expectedClass == String) { return typeof other == 'string' || other instanceof String; } if (this.expectedClass == Number) { return typeof other == 'number' || other instanceof Number; } if (this.expectedClass == Function) { return typeof other == 'function' || other instanceof Function; } if (this.expectedClass == Object) { return typeof other == 'object'; } return other instanceof this.expectedClass; }; jasmine.Matchers.Any.prototype.toString = function() { return ''; };