Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

expect(spy1).toHaveBeenCalledBefore(spy2) #201

Closed
wants to merge 2 commits into
from
Jump to file or symbol
Failed to load files and symbols.
+169 −24
Split
@@ -84,7 +84,7 @@ jasmine.HtmlReporter = function(_doc) {
};
self.reportRunnerResults = function(runner) {
- reporterView.complete();
+ reporterView && reporterView.complete();
};
self.reportSuiteResults = function(suite) {
@@ -197,12 +197,12 @@ jasmine.any = function(clazz) {
};
/**
- * Returns a matchable subset of a hash/JSON object. For use in expectations when you don't care about all of the
+ * Returns a matchable subset of a JSON object. For use in expectations when you don't care about all of the
* attributes on the object.
*
* @example
* // don't care about any other attributes than foo.
- * expect(mySpy).toHaveBeenCalledWith(jasmine.hashContaining({foo: "bar"});
+ * expect(mySpy).toHaveBeenCalledWith(jasmine.objectContaining({foo: "bar"});
*
* @param sample {Object} sample
* @returns matchable object for the sample
@@ -293,7 +293,7 @@ jasmine.Spy = function(name) {
};
/**
- * Tells a spy to call through to the actual implementation.
+ * Tells a spy to call through to the actual implemenatation.
*
* @example
* var foo = {
@@ -398,6 +398,7 @@ jasmine.createSpy = function(name) {
spyObj.mostRecentCall.args = args;
spyObj.argsForCall.push(args);
spyObj.calls.push({object: this, args: args});
+ jasmine.getEnv().currentSpec.spyCalls.push({object: this, args: args});
return spyObj.plan.apply(this, arguments);
};
@@ -929,12 +930,12 @@ jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) {
return a.getTime() == b.getTime();
}
- if (a instanceof jasmine.Matchers.Any) {
- return a.matches(b);
+ if (a.jasmineMatches) {
+ return a.jasmineMatches(b);
}
- if (b instanceof jasmine.Matchers.Any) {
- return b.matches(a);
+ if (b.jasmineMatches) {
+ return b.jasmineMatches(a);
}
if (a instanceof jasmine.Matchers.ObjectContaining) {
@@ -1235,7 +1236,7 @@ jasmine.Matchers.prototype.toEqual = function(expected) {
/**
* toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual
* @param expected
- * @deprecated as of 1.0. Use not.toNotEqual() instead.
+ * @deprecated as of 1.0. Use not.toEqual() instead.
*/
jasmine.Matchers.prototype.toNotEqual = function(expected) {
return !this.env.equals_(this.actual, expected);
@@ -1396,6 +1397,51 @@ jasmine.Matchers.prototype.wasNotCalledWith = function() {
};
/**
+ * Matcher that checks if the actual, a spy, was called before the expected, another spy, sometime during the spec
+ *
+ * @param {Object} expected
+ */
+jasmine.Matchers.prototype.toHaveBeenCalledBefore = function(expected) {
+ if (!jasmine.isSpy(this.actual)) {
+ throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
+ }
+ if (!jasmine.isSpy(expected)) {
+ throw new Error('Expected a spy, but got ' + jasmine.pp(expected) + '.');
+ }
+
+
+ this.message = function() {
+ var messages = [
+ undefined,
+ "Expected " + jasmine.pp(this.actual) + " not to have been called before " + jasmine.pp(expected) + " but it was."
+ ];
+ if (this.actual.callCount === 0) {
+ messages[0] = ("Expected " + jasmine.pp(this.actual) + " to have been called before " + jasmine.pp(expected) + " but it was never called.");
+ } else {
+ messages[0] = ("Expected " + jasmine.pp(this.actual) + " to have been called before " + jasmine.pp(expected) + " but it was called after.");
+ }
+ return messages;
+ };
+
+ if(this.actual.callCount === 0) {
+ return false;
+ }
+ if(expected.callCount === 0) {
+ return true;
+ }
+
+ var me = this;
+ var indexOfSpyCall = function(spy){
+ for(var i = 0; i < me.spec.spyCalls.length; i++){
+ if(me.env.equals_(me.spec.spyCalls[i].object[spy.identity], spy)) return i;
+ }
+ return NaN;
+ }
+
+ return indexOfSpyCall(this.actual) < indexOfSpyCall(expected);
+};
+
+/**
* Matcher that checks that the expected item is an element in the actual Array.
*
* @param {Object} expected
@@ -1408,7 +1454,7 @@ jasmine.Matchers.prototype.toContain = function(expected) {
* Matcher that checks that the expected item is NOT an element in the actual Array.
*
* @param {Object} expected
- * @deprecated as of 1.0. Use not.toNotContain() instead.
+ * @deprecated as of 1.0. Use not.toContain() instead.
*/
jasmine.Matchers.prototype.toNotContain = function(expected) {
return !this.env.contains_(this.actual, expected);
@@ -1476,7 +1522,7 @@ jasmine.Matchers.Any = function(expectedClass) {
this.expectedClass = expectedClass;
};
-jasmine.Matchers.Any.prototype.matches = function(other) {
+jasmine.Matchers.Any.prototype.jasmineMatches = function(other) {
if (this.expectedClass == String) {
return typeof other == 'string' || other instanceof String;
}
@@ -1496,15 +1542,15 @@ jasmine.Matchers.Any.prototype.matches = function(other) {
return other instanceof this.expectedClass;
};
-jasmine.Matchers.Any.prototype.toString = function() {
+jasmine.Matchers.Any.prototype.jasmineToString = function() {
return '<jasmine.any(' + this.expectedClass + ')>';
};
jasmine.Matchers.ObjectContaining = function (sample) {
this.sample = sample;
};
-jasmine.Matchers.ObjectContaining.prototype.matches = function(other, mismatchKeys, mismatchValues) {
+jasmine.Matchers.ObjectContaining.prototype.jasmineMatches = function(other, mismatchKeys, mismatchValues) {
mismatchKeys = mismatchKeys || [];
mismatchValues = mismatchValues || [];
@@ -1526,8 +1572,8 @@ jasmine.Matchers.ObjectContaining.prototype.matches = function(other, mismatchKe
return (mismatchKeys.length === 0 && mismatchValues.length === 0);
};
-jasmine.Matchers.ObjectContaining.prototype.toString = function () {
- return "<jasmine.hashContaining(" + jasmine.pp(this.sample) + ")>";
+jasmine.Matchers.ObjectContaining.prototype.jasmineToString = function () {
+ return "<jasmine.objectContaining(" + jasmine.pp(this.sample) + ")>";
};
/**
* @constructor
@@ -1669,8 +1715,8 @@ jasmine.PrettyPrinter.prototype.format = function(value) {
this.emitScalar('null');
} else if (value === jasmine.getGlobal()) {
this.emitScalar('<global>');
- } else if (value instanceof jasmine.Matchers.Any) {
- this.emitScalar(value.toString());
+ } else if (value.jasmineToString) {
+ this.emitScalar(value.jasmineToString());
} else if (typeof value === 'string') {
this.emitString(value);
} else if (jasmine.isSpy(value)) {
@@ -2107,6 +2153,7 @@ jasmine.Spec.prototype.after = function(doAfter) {
jasmine.Spec.prototype.execute = function(onComplete) {
var spec = this;
+ spec.spyCalls = [];
if (!spec.env.specFilter(spec)) {
spec.results_.skipped = true;
spec.finish(onComplete);
@@ -2524,5 +2571,5 @@ jasmine.version_= {
"major": 1,
"minor": 1,
"build": 0,
- "revision": 1299963843
+ "revision": 1331891345
};
View
@@ -1103,6 +1103,37 @@ describe("jasmine.Matchers", function() {
});
});
+ describe('toHaveBeenCalledBefore', function(){
+ var before, after, never;
+ beforeEach(function(){
+ before = { fn: function(){}};
+ after = { fn: function(){}};
+ never = { fn: function(){}};
+ spyOn(before, 'fn');
+ spyOn(after, 'fn');
+ spyOn(never, 'fn');
+
+ before.fn();
+ after.fn();
+ });
+ it('should return true if the spy was called before the argument spy', function(){
+ expect(before.fn).toHaveBeenCalledBefore(after.fn);
+ });
+ it('should return true if the spy was called before and after the argument spy', function(){
+ before.fn();
+ expect(before.fn).toHaveBeenCalledBefore(after.fn);
+ });
+ it('should return false if the spy was called after the argument spy', function(){
+ expect(after.fn).not.toHaveBeenCalledBefore(before.fn);
+ });
+ it('should return false if the spy was never called', function(){
+ expect(never.fn).not.toHaveBeenCalledBefore(before.fn);
+ });
+ it('should return true if the spy was called and the argument spy was never called', function(){
+ expect(before.fn).toHaveBeenCalledBefore(never.fn);
+ });
+ });
+
describe("all matchers", function() {
it("should return null, for future-proofing, since we might eventually allow matcher chaining", function() {
expect(match(true).toBe(true)).toBeUndefined();
View
@@ -53,6 +53,12 @@ describe('Spec', function () {
});
});
+ it('execute should clear jasmine spyCalls upon beginning execution', function () {
+ spec.spyCalls = [{name:'spy one', method: function(){}},{name:'spy two', method: function(){}}];
+
+ spec.execute();
+ expect(spec.spyCalls.length).toEqual(0);
+ });
it('results shows the total number of expectations for each spec after execution', function () {
expect(results.totalCount).toEqual(0);
@@ -113,12 +119,12 @@ describe('Spec', function () {
spec.execute();
var items = results.getItems();
expect(items).toEqual([
- jasmine.any(jasmine.ExpectationResult),
- jasmine.any(jasmine.ExpectationResult),
- jasmine.any(jasmine.MessageResult)
- ]);
+ jasmine.any(jasmine.ExpectationResult),
+ jasmine.any(jasmine.ExpectationResult),
+ jasmine.any(jasmine.MessageResult)
+ ]);
var logResult = items[2];
expect(logResult.values).toEqual(["here's some log message", {key: 'value'}, 123]);
});
});
-});
+});
View
@@ -22,6 +22,20 @@ describe('Spies', function () {
expect(TestClass.someFunction.mostRecentCall.args).toEqual(['bar']);
});
+ it('calling a spy should push its name to spec.spyCalls', function() {
+ var obj1 = { fn1: function(){}};
+ var obj2 = { fn2: function(){}};
+ spyOn(obj1, 'fn1');
+ spyOn(obj2, 'fn2');
+
+ obj1.fn1();
+ obj2.fn2();
+
+ expect(this.spyCalls.length).toEqual(2);
+ expect(this.spyCalls[0].object).toEqual(obj1);
+ expect(this.spyCalls[1].object).toEqual(obj2);
+ });
+
it('should allow you to view args for a particular call', function() {
var originalFunctionWasCalled = false;
var TestClass = {
View
@@ -265,6 +265,51 @@ jasmine.Matchers.prototype.wasNotCalledWith = function() {
};
/**
+ * Matcher that checks if the actual, a spy, was called before the expected, another spy, sometime during the spec
+ *
+ * @param {Object} expected
+ */
+jasmine.Matchers.prototype.toHaveBeenCalledBefore = function(expected) {
+ if (!jasmine.isSpy(this.actual)) {
+ throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
+ }
+ if (!jasmine.isSpy(expected)) {
+ throw new Error('Expected a spy, but got ' + jasmine.pp(expected) + '.');
+ }
+
+
+ this.message = function() {
+ var messages = [
+ undefined,
+ "Expected " + jasmine.pp(this.actual) + " not to have been called before " + jasmine.pp(expected) + " but it was."
+ ];
+ if (this.actual.callCount === 0) {
+ messages[0] = ("Expected " + jasmine.pp(this.actual) + " to have been called before " + jasmine.pp(expected) + " but it was never called.");
+ } else {
+ messages[0] = ("Expected " + jasmine.pp(this.actual) + " to have been called before " + jasmine.pp(expected) + " but it was called after.");
+ }
+ return messages;
+ };
+
+ if(this.actual.callCount === 0) {
+ return false;
+ }
+ if(expected.callCount === 0) {
+ return true;
+ }
+
+ var me = this;
+ var indexOfSpyCall = function(spy){
+ for(var i = 0; i < me.spec.spyCalls.length; i++){
+ if(me.env.equals_(me.spec.spyCalls[i].object[spy.identity], spy)) return i;
+ }
+ return NaN;
+ }
+
+ return indexOfSpyCall(this.actual) < indexOfSpyCall(expected);
+};
+
+/**
* Matcher that checks that the expected item is an element in the actual Array.
*
* @param {Object} expected
View
@@ -162,6 +162,7 @@ jasmine.Spec.prototype.after = function(doAfter) {
jasmine.Spec.prototype.execute = function(onComplete) {
var spec = this;
+ spec.spyCalls = [];
if (!spec.env.specFilter(spec)) {
spec.results_.skipped = true;
spec.finish(onComplete);
View
@@ -398,6 +398,7 @@ jasmine.createSpy = function(name) {
spyObj.mostRecentCall.args = args;
spyObj.argsForCall.push(args);
spyObj.calls.push({object: this, args: args});
+ jasmine.getEnv().currentSpec.spyCalls.push({object: this, args: args});
return spyObj.plan.apply(this, arguments);
};
View
@@ -2,5 +2,5 @@ jasmine.version_= {
"major": 1,
"minor": 1,
"build": 0,
- "revision": 1320442951
+ "revision": 1331891345
};