Wrap base matchers from jasmine.Matcher prototype automatically at env instantiation time rather than manually.

This commit is contained in:
Christian Williams 2009-11-13 14:32:08 -05:00
parent 2fc78a0fe2
commit 1a53838d97
4 changed files with 121 additions and 153 deletions

View File

@ -8,7 +8,7 @@ describe("jasmine.Matchers", function() {
}); });
function match(value) { function match(value) {
return new jasmine.Matchers(env, value, mockSpec); return new env.matchersClass(env, value, mockSpec);
} }
it("toEqual with primitives, objects, dates, html nodes, etc.", function() { it("toEqual with primitives, objects, dates, html nodes, etc.", function() {
@ -435,9 +435,9 @@ describe("jasmine.Matchers", function() {
}); });
it("toThrow", function() { it("toThrow", function() {
var expected = new jasmine.Matchers(env, function() { var expected = match(function() {
throw new Error("Fake Error"); throw new Error("Fake Error");
}, mockSpec); });
expect(expected.toThrow()).toEqual(true); expect(expected.toThrow()).toEqual(true);
expect(expected.toThrow("Fake Error")).toEqual(true); expect(expected.toThrow("Fake Error")).toEqual(true);
expect(expected.toThrow(new Error("Fake Error"))).toEqual(true); expect(expected.toThrow(new Error("Fake Error"))).toEqual(true);

View File

@ -10,7 +10,7 @@ jasmine.Env = function() {
this.reporter = new jasmine.MultiReporter(); this.reporter = new jasmine.MultiReporter();
this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL;
this.lastUpdate = 0; this.lastUpdate = 0;
this.specFilter = function() { this.specFilter = function() {
return true; return true;
@ -19,6 +19,17 @@ jasmine.Env = function() {
this.nextSpecId_ = 0; this.nextSpecId_ = 0;
this.nextSuiteId_ = 0; this.nextSuiteId_ = 0;
this.equalityTesters_ = []; this.equalityTesters_ = [];
// wrap matchers
this.matchersClass = function() {
jasmine.Matchers.apply(this, arguments);
};
jasmine.util.inherit(this.matchersClass, jasmine.Matchers);
for (var methodName in jasmine.Matchers.prototype) {
var orig = jasmine.Matchers.prototype[methodName];
this.matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig);
}
}; };

View File

@ -24,11 +24,10 @@ jasmine.Matchers.prototype.report = function(result, failing_message, details) {
return result; return result;
}; };
jasmine.Matchers.matcherFn_ = function(matcherName, options) { jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) {
return function () { return function() {
jasmine.util.extend(this, options);
var matcherArgs = jasmine.util.argsToArray(arguments); var matcherArgs = jasmine.util.argsToArray(arguments);
var result = options.test.apply(this, arguments); var result = matcherFunction.apply(this, arguments);
var message; var message;
if (!result) { if (!result) {
if (this.message) { if (this.message) {
@ -65,21 +64,17 @@ jasmine.Matchers.matcherFn_ = function(matcherName, options) {
* @param expected * @param expected
*/ */
jasmine.Matchers.prototype.toBe = jasmine.Matchers.matcherFn_('toBe', { jasmine.Matchers.prototype.toBe = function(expected) {
test: function(expected) { return this.actual === expected;
return this.actual === expected; };
}
});
/** /**
* toNotBe: compares the actual to the expected using !== * toNotBe: compares the actual to the expected using !==
* @param expected * @param expected
*/ */
jasmine.Matchers.prototype.toNotBe = jasmine.Matchers.matcherFn_('toNotBe', { jasmine.Matchers.prototype.toNotBe = function(expected) {
test: function(expected) { return this.actual !== expected;
return this.actual !== expected; };
}
});
/** /**
* toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc. * toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc.
@ -87,21 +82,17 @@ jasmine.Matchers.prototype.toNotBe = jasmine.Matchers.matcherFn_('toNotBe', {
* @param expected * @param expected
*/ */
jasmine.Matchers.prototype.toEqual = jasmine.Matchers.matcherFn_('toEqual', { jasmine.Matchers.prototype.toEqual = function(expected) {
test: function(expected) { return this.env.equals_(this.actual, expected);
return this.env.equals_(this.actual, expected); };
}
});
/** /**
* toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual
* @param expected * @param expected
*/ */
jasmine.Matchers.prototype.toNotEqual = jasmine.Matchers.matcherFn_('toNotEqual', { jasmine.Matchers.prototype.toNotEqual = function(expected) {
test: function(expected) { return !this.env.equals_(this.actual, 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 * Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp, so takes
@ -109,124 +100,91 @@ jasmine.Matchers.prototype.toNotEqual = jasmine.Matchers.matcherFn_('toNotEqual'
* *
* @param reg_exp * @param reg_exp
*/ */
jasmine.Matchers.prototype.toMatch = jasmine.Matchers.matcherFn_('toMatch', { jasmine.Matchers.prototype.toMatch = function(expected) {
test: function(expected) { return new RegExp(expected).test(this.actual);
return new RegExp(expected).test(this.actual); };
}
});
/** /**
* Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch
* @param reg_exp * @param reg_exp
*/ */
jasmine.Matchers.prototype.toNotMatch = jasmine.Matchers.matcherFn_('toNotMatch', { jasmine.Matchers.prototype.toNotMatch = function(expected) {
test: function(expected) { return !(new RegExp(expected).test(this.actual));
return !(new RegExp(expected).test(this.actual)); };
}
});
/** /**
* Matcher that compares the actual to undefined. * Matcher that compares the actual to undefined.
*/ */
jasmine.Matchers.prototype.toBeDefined = jasmine.Matchers.matcherFn_('toBeDefined', { jasmine.Matchers.prototype.toBeDefined = function() {
test: function() { return (this.actual !== undefined);
return (this.actual !== undefined); };
}
});
/** /**
* Matcher that compares the actual to undefined. * Matcher that compares the actual to undefined.
*/ */
jasmine.Matchers.prototype.toBeUndefined = jasmine.Matchers.matcherFn_('toBeUndefined', { jasmine.Matchers.prototype.toBeUndefined = function() {
test: function() { return (this.actual === undefined);
return (this.actual === undefined); };
}
});
/** /**
* Matcher that compares the actual to null. * Matcher that compares the actual to null.
*/ */
jasmine.Matchers.prototype.toBeNull = jasmine.Matchers.matcherFn_('toBeNull', { jasmine.Matchers.prototype.toBeNull = function() {
test: function() { return (this.actual === null);
return (this.actual === null); };
}
});
/** /**
* Matcher that boolean not-nots the actual. * Matcher that boolean not-nots the actual.
*/ */
jasmine.Matchers.prototype.toBeTruthy = jasmine.Matchers.matcherFn_('toBeTruthy', { jasmine.Matchers.prototype.toBeTruthy = function() {
test: function() { return !!this.actual;
return !!this.actual; };
}
});
/** /**
* Matcher that boolean nots the actual. * Matcher that boolean nots the actual.
*/ */
jasmine.Matchers.prototype.toBeFalsy = jasmine.Matchers.matcherFn_('toBeFalsy', { jasmine.Matchers.prototype.toBeFalsy = function() {
test: function() { return !this.actual;
return !this.actual; };
}
});
/** /**
* Matcher that checks to see if the actual, a Jasmine spy, was called. * Matcher that checks to see if the actual, a Jasmine spy, was called.
*/ */
jasmine.Matchers.prototype.wasCalled = function() {
jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.matcherFn_('wasCalled', { if (arguments.length > 0) {
test: function() { throw new Error('wasCalled does not take arguments, use wasCalledWith');
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) + '.');
}
this.message = function() {
return "Expected spy " + this.actual.identity + " to have been called.";
};
return this.actual.wasCalled;
} }
});
if (!jasmine.isSpy(this.actual)) {
throw new Error('Expected a spy, but got ' + jasmine.Matchers.pp(this.actual) + '.');
}
this.message = function() {
return "Expected spy " + this.actual.identity + " to have been called.";
};
return this.actual.wasCalled;
};
/** /**
* Matcher that checks to see if the actual, a Jasmine spy, was not called. * Matcher that checks to see if the actual, a Jasmine spy, was not called.
*/ */
jasmine.Matchers.prototype.wasNotCalled = jasmine.Matchers.matcherFn_('wasNotCalled', { jasmine.Matchers.prototype.wasNotCalled = function() {
test: function() { if (arguments.length > 0) {
if (arguments.length > 0) { throw new Error('wasNotCalled does not take arguments');
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) + '.');
}
this.message = function() {
return "Expected spy " + this.actual.identity + " to not have been called.";
};
return !this.actual.wasCalled;
} }
});
jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.matcherFn_('wasCalledWith', { if (!jasmine.isSpy(this.actual)) {
test: function() { throw new Error('Expected a spy, but got ' + jasmine.Matchers.pp(this.actual) + '.');
if (!jasmine.isSpy(this.actual)) {
throw new Error('Expected a spy, but got ' + jasmine.Matchers.pp(this.actual) + '.');
}
this.message = function() {
return "Expected spy to have been called with " + jasmine.pp(arguments) + " but was called with " + jasmine.pp(this.actual.argsForCall);
};
return this.env.contains_(this.actual.argsForCall, jasmine.util.argsToArray(arguments));
} }
});
this.message = function() {
return "Expected spy " + this.actual.identity + " to not have been called.";
};
return !this.actual.wasCalled;
};
/** /**
* Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters. * Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters.
@ -234,49 +192,51 @@ jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.matcherFn_('wasCalle
* @example * @example
* *
*/ */
jasmine.Matchers.prototype.wasCalledWith = function() {
if (!jasmine.isSpy(this.actual)) {
throw new Error('Expected a spy, but got ' + jasmine.Matchers.pp(this.actual) + '.');
}
this.message = function() {
return "Expected spy to have been called with " + jasmine.pp(arguments) + " but was called with " + jasmine.pp(this.actual.argsForCall);
};
return this.env.contains_(this.actual.argsForCall, jasmine.util.argsToArray(arguments));
};
/** /**
* Matcher that checks that the expected item is an element in the actual Array. * Matcher that checks that the expected item is an element in the actual Array.
* *
* @param {Object} item * @param {Object} item
*/ */
jasmine.Matchers.prototype.toContain = function(expected) {
jasmine.Matchers.prototype.toContain = jasmine.Matchers.matcherFn_('toContain', { return this.env.contains_(this.actual, expected);
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. * Matcher that checks that the expected item is NOT an element in the actual Array.
* *
* @param {Object} item * @param {Object} item
*/ */
jasmine.Matchers.prototype.toNotContain = jasmine.Matchers.matcherFn_('toNotContain', { jasmine.Matchers.prototype.toNotContain = function(expected) {
test: function(expected) { return !this.env.contains_(this.actual, expected);
return !this.env.contains_(this.actual, expected); };
}
});
jasmine.Matchers.prototype.toBeLessThan = jasmine.Matchers.matcherFn_('toBeLessThan', { jasmine.Matchers.prototype.toBeLessThan = function(expected) {
test: function(expected) { return this.actual < expected;
return this.actual < expected; };
}
});
jasmine.Matchers.prototype.toBeGreaterThan = jasmine.Matchers.matcherFn_('toBeGreaterThan', { jasmine.Matchers.prototype.toBeGreaterThan = function(expected) {
test: function(expected) { return this.actual > expected;
return this.actual > expected; };
}
});
/** /**
* Matcher that checks that the expected exception was thrown by the actual. * Matcher that checks that the expected exception was thrown by the actual.
* *
* @param {String} expectedException * @param {String} expectedException
*/ */
jasmine.Matchers.prototype.toThrow = jasmine.Matchers.matcherFn_('toThrow', { jasmine.Matchers.prototype.toThrow = function(expected) {
getException_: function(actual, expected) { function getException_(actual, expected) {
var exception; var exception;
if (typeof actual != 'function') { if (typeof actual != 'function') {
throw new Error('Actual is not a function'); throw new Error('Actual is not a function');
@ -287,26 +247,25 @@ jasmine.Matchers.prototype.toThrow = jasmine.Matchers.matcherFn_('toThrow', {
exception = e; exception = e;
} }
return exception; 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));
}
this.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.";
}
};
return result;
} }
});
var result = false;
var exception = getException_(this.actual, expected);
if (exception) {
result = (expected === undefined || this.env.equals_(exception.message || exception, expected.message || expected));
}
this.message = function(expected) {
var exception = 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.";
}
};
return result;
};
jasmine.Matchers.Any = function(expectedClass) { jasmine.Matchers.Any = function(expectedClass) {
this.expectedClass = expectedClass; this.expectedClass = expectedClass;

View File

@ -10,11 +10,9 @@ jasmine.Spec = function(env, suite, description) {
if (!env) { if (!env) {
throw new Error('jasmine.Env() required'); throw new Error('jasmine.Env() required');
} }
;
if (!suite) { if (!suite) {
throw new Error('jasmine.Suite() required'); throw new Error('jasmine.Suite() required');
} }
;
var spec = this; var spec = this;
spec.id = env.nextSpecId ? env.nextSpecId() : null; spec.id = env.nextSpecId ? env.nextSpecId() : null;
spec.env = env; spec.env = env;
@ -91,7 +89,7 @@ jasmine.Spec.prototype.fail = function (e) {
}; };
jasmine.Spec.prototype.getMatchersClass_ = function() { jasmine.Spec.prototype.getMatchersClass_ = function() {
return this.matchersClass || jasmine.Matchers; return this.matchersClass || this.env.matchersClass;
}; };
jasmine.Spec.prototype.addMatchers = function(matchersPrototype) { jasmine.Spec.prototype.addMatchers = function(matchersPrototype) {