Add toHaveBeenCalledBefore matcher

This matcher makes sure the 'actual' spy is called before the
'expected' spy.

This code has been written in cooperation with Benjamin Van Ryseghem.
This commit is contained in:
Damien Cassou
2016-12-12 10:28:40 +01:00
parent 43f96d3ecd
commit 4cfdd06700
4 changed files with 119 additions and 0 deletions

View File

@@ -0,0 +1,69 @@
describe("toHaveBeenCalledBefore", function() {
it("throws an exception when the actual is not a spy", function() {
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledBefore(),
fn = function() {},
secondSpy = jasmineUnderTest.createSpy('second spy');
expect(function() { matcher.compare(fn, secondSpy) }).toThrowError(Error, /Expected a spy, but got Function./);
});
it("throws an exception when the expected is not a spy", function() {
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledBefore(),
firstSpy = jasmineUnderTest.createSpy('first spy'),
fn = function() {};
expect(function() { matcher.compare(firstSpy, fn) }).toThrowError(Error, /Expected a spy, but got Function./);
});
it("fails when the actual was not called", function() {
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledBefore(),
firstSpy = jasmineUnderTest.createSpy('first spy'),
secondSpy = jasmineUnderTest.createSpy('second spy');
secondSpy();
result = matcher.compare(firstSpy, secondSpy);
expect(result.pass).toBe(false);
expect(result.message).toMatch(/Expected spy first spy to have been called./);
});
it("fails when the expected was not called", function() {
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledBefore(),
firstSpy = jasmineUnderTest.createSpy('first spy'),
secondSpy = jasmineUnderTest.createSpy('second spy');
firstSpy();
result = matcher.compare(firstSpy, secondSpy);
expect(result.pass).toBe(false);
expect(result.message).toMatch(/Expected spy second spy to have been called./);
});
it("fails when the actual is called after the expected", function() {
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledBefore(),
firstSpy = jasmineUnderTest.createSpy('first spy'),
secondSpy = jasmineUnderTest.createSpy('second spy'),
result;
secondSpy();
firstSpy();
result = matcher.compare(firstSpy, secondSpy);
expect(result.pass).toBe(false);
expect(result.message).toEqual('Expected first spy to have been called before second spy');
});
it("passes when first spy is called before second spy", function() {
var matcher = jasmineUnderTest.matchers.toHaveBeenCalledBefore(),
firstSpy = jasmineUnderTest.createSpy('first spy'),
secondSpy = jasmineUnderTest.createSpy('second spy'),
result;
firstSpy();
secondSpy();
result = matcher.compare(firstSpy, secondSpy);
expect(result.pass).toBe(true);
expect(result.message).toEqual('Expected first spy to not have been called before second spy, but it was');
});
});

View File

@@ -1,5 +1,13 @@
getJasmineRequireObj().Spy = function (j$) {
var nextOrder = (function() {
var order = 0;
return function() {
return order++;
};
})();
function Spy(name, originalFn) {
var args = buildArgs(),
/*`eval` is the only option to preserve both this and context:
@@ -21,6 +29,7 @@ getJasmineRequireObj().Spy = function (j$) {
spy = function () {
var callData = {
object: this,
invocationOrder: nextOrder(),
args: Array.prototype.slice.apply(arguments)
};

View File

@@ -15,6 +15,7 @@ getJasmineRequireObj().requireMatchers = function(jRequire, j$) {
'toContain',
'toEqual',
'toHaveBeenCalled',
'toHaveBeenCalledBefore',
'toHaveBeenCalledWith',
'toHaveBeenCalledTimes',
'toMatch',

View File

@@ -0,0 +1,40 @@
getJasmineRequireObj().toHaveBeenCalledBefore = function(j$) {
var getErrorMsg = j$.formatErrorMsg('<toHaveBeenCalledBefore>', 'expect(<spyObj>).toHaveBeenCalledBefore(<spyObj>)');
function toHaveBeenCalledBefore() {
return {
compare: function(firstSpy, latterSpy) {
if (!j$.isSpy(firstSpy)) {
throw new Error(getErrorMsg('Expected a spy, but got ' + j$.pp(firstSpy) + '.'));
}
if (!j$.isSpy(latterSpy)) {
throw new Error(getErrorMsg('Expected a spy, but got ' + j$.pp(latterSpy) + '.'));
}
var result = { pass: false };
if (!firstSpy.calls.count()) {
result.message = 'Expected spy ' + firstSpy.and.identity() + ' to have been called.';
return result;
}
if (!latterSpy.calls.count()) {
result.message = 'Expected spy ' + latterSpy.and.identity() + ' to have been called.';
return result;
}
result.pass = firstSpy.calls.mostRecent().invocationOrder < latterSpy.calls.mostRecent().invocationOrder;
if (result.pass) {
result.message = 'Expected ' + firstSpy.and.identity() + ' to not have been called before ' + latterSpy.and.identity() + ', but it was';
} else {
result.message = 'Expected ' + firstSpy.and.identity() + ' to have been called before ' + latterSpy.and.identity();
}
return result;
}
};
}
return toHaveBeenCalledBefore;
};