Merge branch 'Eradev-issue-1991'
* Merges #2051 from @Eradev * Fixes #1991
This commit is contained in:
@@ -162,6 +162,7 @@ getJasmineRequireObj().requireMatchers = function(jRequire, j$) {
|
||||
'toHaveClass',
|
||||
'toHaveClasses',
|
||||
'toHaveSpyInteractions',
|
||||
'toHaveNoOtherSpyInteractions',
|
||||
'toMatch',
|
||||
'toThrow',
|
||||
'toThrowError',
|
||||
@@ -2898,6 +2899,10 @@ getJasmineRequireObj().CallTracker = function(j$) {
|
||||
this.saveArgumentsByValue = function() {
|
||||
opts.cloneArgs = true;
|
||||
};
|
||||
|
||||
this.unverifiedCount = function() {
|
||||
return calls.reduce((count, call) => count + (call.verified ? 0 : 1), 0);
|
||||
};
|
||||
}
|
||||
|
||||
return CallTracker;
|
||||
@@ -6231,6 +6236,8 @@ getJasmineRequireObj().toHaveBeenCalled = function(j$) {
|
||||
|
||||
result.pass = actual.calls.any();
|
||||
|
||||
actual.calls.all().forEach(call => (call.verified = true));
|
||||
|
||||
result.message = result.pass
|
||||
? 'Expected spy ' + actual.and.identity + ' not to have been called.'
|
||||
: 'Expected spy ' + actual.and.identity + ' to have been called.';
|
||||
@@ -6295,6 +6302,9 @@ getJasmineRequireObj().toHaveBeenCalledBefore = function(j$) {
|
||||
result.pass = latest1stSpyCall < first2ndSpyCall;
|
||||
|
||||
if (result.pass) {
|
||||
firstSpy.calls.mostRecent().verified = true;
|
||||
latterSpy.calls.first().verified = true;
|
||||
|
||||
result.message =
|
||||
'Expected spy ' +
|
||||
firstSpy.and.identity +
|
||||
@@ -6351,7 +6361,7 @@ getJasmineRequireObj().toHaveBeenCalledOnceWith = function(j$) {
|
||||
* @example
|
||||
* expect(mySpy).toHaveBeenCalledOnceWith('foo', 'bar', 2);
|
||||
*/
|
||||
function toHaveBeenCalledOnceWith(util) {
|
||||
function toHaveBeenCalledOnceWith(matchersUtil) {
|
||||
return {
|
||||
compare: function() {
|
||||
const args = Array.prototype.slice.call(arguments, 0),
|
||||
@@ -6360,20 +6370,29 @@ getJasmineRequireObj().toHaveBeenCalledOnceWith = function(j$) {
|
||||
|
||||
if (!j$.isSpy(actual)) {
|
||||
throw new Error(
|
||||
getErrorMsg('Expected a spy, but got ' + util.pp(actual) + '.')
|
||||
getErrorMsg(
|
||||
'Expected a spy, but got ' + matchersUtil.pp(actual) + '.'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
const prettyPrintedCalls = actual.calls
|
||||
.allArgs()
|
||||
.map(function(argsForCall) {
|
||||
return ' ' + util.pp(argsForCall);
|
||||
return ' ' + matchersUtil.pp(argsForCall);
|
||||
});
|
||||
|
||||
if (
|
||||
actual.calls.count() === 1 &&
|
||||
util.contains(actual.calls.allArgs(), expectedArgs)
|
||||
matchersUtil.contains(actual.calls.allArgs(), expectedArgs)
|
||||
) {
|
||||
const firstIndex = actual.calls
|
||||
.all()
|
||||
.findIndex(call => matchersUtil.equals(call.args, expectedArgs));
|
||||
if (firstIndex > -1) {
|
||||
actual.calls.all()[firstIndex].verified = true;
|
||||
}
|
||||
|
||||
return {
|
||||
pass: true,
|
||||
message:
|
||||
@@ -6381,7 +6400,7 @@ getJasmineRequireObj().toHaveBeenCalledOnceWith = function(j$) {
|
||||
actual.and.identity +
|
||||
' to have been called 0 times, multiple times, or once, but with arguments different from:\n' +
|
||||
' ' +
|
||||
util.pp(expectedArgs) +
|
||||
matchersUtil.pp(expectedArgs) +
|
||||
'\n' +
|
||||
'But the actual call was:\n' +
|
||||
prettyPrintedCalls.join(',\n') +
|
||||
@@ -6392,7 +6411,7 @@ getJasmineRequireObj().toHaveBeenCalledOnceWith = function(j$) {
|
||||
function getDiffs() {
|
||||
return actual.calls.allArgs().map(function(argsForCall, callIx) {
|
||||
const diffBuilder = new j$.DiffBuilder();
|
||||
util.equals(argsForCall, expectedArgs, diffBuilder);
|
||||
matchersUtil.equals(argsForCall, expectedArgs, diffBuilder);
|
||||
return diffBuilder.getMessage();
|
||||
});
|
||||
}
|
||||
@@ -6425,7 +6444,7 @@ getJasmineRequireObj().toHaveBeenCalledOnceWith = function(j$) {
|
||||
actual.and.identity +
|
||||
' to have been called only once, and with given args:\n' +
|
||||
' ' +
|
||||
util.pp(expectedArgs) +
|
||||
matchersUtil.pp(expectedArgs) +
|
||||
'\n' +
|
||||
butString()
|
||||
};
|
||||
@@ -6474,23 +6493,35 @@ getJasmineRequireObj().toHaveBeenCalledTimes = function(j$) {
|
||||
}
|
||||
|
||||
actual = args[0];
|
||||
const calls = actual.calls.count();
|
||||
|
||||
const callsCount = actual.calls.count();
|
||||
const timesMessage = expected === 1 ? 'once' : expected + ' times';
|
||||
result.pass = calls === expected;
|
||||
|
||||
result.pass = callsCount === expected;
|
||||
|
||||
if (result.pass) {
|
||||
const allCalls = actual.calls.all();
|
||||
const max = Math.min(expected, callsCount);
|
||||
|
||||
for (let i = 0; i < max; i++) {
|
||||
allCalls[i].verified = true;
|
||||
}
|
||||
}
|
||||
|
||||
result.message = result.pass
|
||||
? 'Expected spy ' +
|
||||
actual.and.identity +
|
||||
' not to have been called ' +
|
||||
timesMessage +
|
||||
'. It was called ' +
|
||||
calls +
|
||||
callsCount +
|
||||
' times.'
|
||||
: 'Expected spy ' +
|
||||
actual.and.identity +
|
||||
' to have been called ' +
|
||||
timesMessage +
|
||||
'. It was called ' +
|
||||
calls +
|
||||
callsCount +
|
||||
' times.';
|
||||
return result;
|
||||
}
|
||||
@@ -6546,6 +6577,11 @@ getJasmineRequireObj().toHaveBeenCalledWith = function(j$) {
|
||||
}
|
||||
|
||||
if (matchersUtil.contains(actual.calls.allArgs(), expectedArgs)) {
|
||||
actual.calls
|
||||
.all()
|
||||
.filter(call => matchersUtil.equals(call.args, expectedArgs))
|
||||
.forEach(call => (call.verified = true));
|
||||
|
||||
result.pass = true;
|
||||
result.message = function() {
|
||||
return (
|
||||
@@ -6672,6 +6708,94 @@ getJasmineRequireObj().toHaveClasses = function(j$) {
|
||||
return toHaveClasses;
|
||||
};
|
||||
|
||||
getJasmineRequireObj().toHaveNoOtherSpyInteractions = function(j$) {
|
||||
const getErrorMsg = j$.formatErrorMsg(
|
||||
'<toHaveNoOtherSpyInteractions>',
|
||||
'expect(<spyObj>).toHaveNoOtherSpyInteractions()'
|
||||
);
|
||||
|
||||
/**
|
||||
* {@link expect} the actual (a {@link SpyObj}) spies to have not been called except interactions which was already tracked with `toHaveBeenCalled`.
|
||||
* @function
|
||||
* @name matchers#toHaveNoOtherSpyInteractions
|
||||
* @example
|
||||
* expect(mySpyObj).toHaveNoOtherSpyInteractions();
|
||||
* expect(mySpyObj).not.toHaveNoOtherSpyInteractions();
|
||||
*/
|
||||
function toHaveNoOtherSpyInteractions(matchersUtil) {
|
||||
return {
|
||||
compare: function(actual) {
|
||||
const result = {};
|
||||
|
||||
if (!j$.isObject_(actual)) {
|
||||
throw new Error(
|
||||
getErrorMsg('Expected an object, but got ' + typeof actual + '.')
|
||||
);
|
||||
}
|
||||
|
||||
if (arguments.length > 1) {
|
||||
throw new Error(getErrorMsg('Does not take arguments'));
|
||||
}
|
||||
|
||||
result.pass = true;
|
||||
let hasSpy = false;
|
||||
const unexpectedCalls = [];
|
||||
|
||||
for (const spy of Object.values(actual)) {
|
||||
if (!j$.isSpy(spy)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
hasSpy = true;
|
||||
|
||||
const unverifiedCalls = spy.calls
|
||||
.all()
|
||||
.filter(call => !call.verified);
|
||||
|
||||
if (unverifiedCalls.length > 0) {
|
||||
result.pass = false;
|
||||
}
|
||||
|
||||
unverifiedCalls.forEach(unverifiedCall => {
|
||||
unexpectedCalls.push([
|
||||
spy.and.identity,
|
||||
matchersUtil.pp(unverifiedCall.args)
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
if (!hasSpy) {
|
||||
throw new Error(
|
||||
getErrorMsg(
|
||||
'Expected an object with spies, but object has no spies.'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (result.pass) {
|
||||
result.message =
|
||||
"Expected to have other spy interactions but it didn't.";
|
||||
} else {
|
||||
const ppUnexpectedCalls = unexpectedCalls
|
||||
.map(
|
||||
([spyName, arguments]) => ` ${spyName} called with ${arguments}`
|
||||
)
|
||||
.join(',\n');
|
||||
|
||||
result.message =
|
||||
'Expected to have no other spy interactions, but it had the following calls:\n' +
|
||||
ppUnexpectedCalls +
|
||||
'.\n\n';
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return toHaveNoOtherSpyInteractions;
|
||||
};
|
||||
|
||||
getJasmineRequireObj().toHaveSize = function(j$) {
|
||||
/**
|
||||
* {@link expect} the actual size to be equal to the expected, using array-like length or object keys size.
|
||||
@@ -9250,7 +9374,8 @@ getJasmineRequireObj().Spy = function(j$) {
|
||||
const callData = {
|
||||
object: context,
|
||||
invocationOrder: nextOrder(),
|
||||
args: Array.prototype.slice.apply(args)
|
||||
args: Array.prototype.slice.apply(args),
|
||||
verified: false
|
||||
};
|
||||
|
||||
callTracker.track(callData);
|
||||
|
||||
@@ -675,6 +675,23 @@ describe('Matchers (Integration)', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('toHaveNoOtherSpyInteractions', function() {
|
||||
let spyObj;
|
||||
|
||||
beforeEach(function() {
|
||||
spyObj = env.createSpyObj('NewClass', ['spyA', 'spyB']);
|
||||
});
|
||||
|
||||
verifyPasses(function(env) {
|
||||
env.expect(spyObj).toHaveNoOtherSpyInteractions();
|
||||
});
|
||||
|
||||
verifyFails(function(env) {
|
||||
spyObj.spyA();
|
||||
env.expect(spyObj).toHaveNoOtherSpyInteractions();
|
||||
});
|
||||
});
|
||||
|
||||
describe('toMatch', function() {
|
||||
verifyPasses(function(env) {
|
||||
env.expect('foo').toMatch(/oo$/);
|
||||
|
||||
@@ -112,4 +112,20 @@ describe('toHaveBeenCalledBefore', function() {
|
||||
'Expected spy first spy to not have been called before spy second spy, but it was'
|
||||
);
|
||||
});
|
||||
|
||||
it('set the correct calls as verified when passing', function() {
|
||||
const matcher = jasmineUnderTest.matchers.toHaveBeenCalledBefore(),
|
||||
firstSpy = new jasmineUnderTest.Spy('first spy'),
|
||||
secondSpy = new jasmineUnderTest.Spy('second spy');
|
||||
|
||||
firstSpy();
|
||||
secondSpy();
|
||||
|
||||
matcher.compare(firstSpy, secondSpy);
|
||||
|
||||
expect(firstSpy.calls.count()).toBe(1);
|
||||
expect(firstSpy.calls.unverifiedCount()).toBe(0);
|
||||
expect(secondSpy.calls.count()).toBe(1);
|
||||
expect(secondSpy.calls.unverifiedCount()).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -105,4 +105,18 @@ describe('toHaveBeenCalledOnceWith', function() {
|
||||
matcher.compare(fn);
|
||||
}).toThrowError(/Expected a spy, but got Function./);
|
||||
});
|
||||
|
||||
it('set the correct calls as verified when passing', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter(),
|
||||
util = new jasmineUnderTest.MatchersUtil({ pp: pp }),
|
||||
matcher = jasmineUnderTest.matchers.toHaveBeenCalledOnceWith(util),
|
||||
calledSpy = new jasmineUnderTest.Spy('called-spy');
|
||||
|
||||
calledSpy('x');
|
||||
|
||||
matcher.compare(calledSpy, 'x');
|
||||
|
||||
expect(calledSpy.calls.count()).toBe(1);
|
||||
expect(calledSpy.calls.unverifiedCount()).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -50,4 +50,16 @@ describe('toHaveBeenCalled', function() {
|
||||
'Expected spy sample-spy to have been called.'
|
||||
);
|
||||
});
|
||||
|
||||
it('set the correct calls as verified when passing', function() {
|
||||
const matcher = jasmineUnderTest.matchers.toHaveBeenCalled(),
|
||||
spy = new jasmineUnderTest.Spy('sample-spy');
|
||||
|
||||
spy();
|
||||
|
||||
matcher.compare(spy);
|
||||
|
||||
expect(spy.calls.count()).toBe(1);
|
||||
expect(spy.calls.unverifiedCount()).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -87,4 +87,17 @@ describe('toHaveBeenCalledTimes', function() {
|
||||
' times.'
|
||||
);
|
||||
});
|
||||
|
||||
it('set the correct calls as verified when passing', function() {
|
||||
const matcher = jasmineUnderTest.matchers.toHaveBeenCalledTimes(),
|
||||
spy = new jasmineUnderTest.Spy('sample-spy');
|
||||
|
||||
spy();
|
||||
spy();
|
||||
|
||||
matcher.compare(spy, 2);
|
||||
|
||||
expect(spy.calls.count()).toBe(2);
|
||||
expect(spy.calls.unverifiedCount()).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,6 +2,7 @@ describe('toHaveBeenCalledWith', function() {
|
||||
it('passes when the actual was called with matching parameters', function() {
|
||||
const matchersUtil = {
|
||||
contains: jasmine.createSpy('delegated-contains').and.returnValue(true),
|
||||
equals: jasmine.createSpy('delegated-equals').and.returnValue(true),
|
||||
pp: jasmineUnderTest.makePrettyPrinter()
|
||||
},
|
||||
matcher = jasmineUnderTest.matchers.toHaveBeenCalledWith(matchersUtil),
|
||||
@@ -92,4 +93,20 @@ describe('toHaveBeenCalledWith', function() {
|
||||
matcher.compare(fn);
|
||||
}).toThrowError(/Expected a spy, but got Function./);
|
||||
});
|
||||
|
||||
it('set the correct calls as verified when passing', function() {
|
||||
const matchersUtil = {
|
||||
contains: jasmine.createSpy('delegated-contains').and.returnValue(true),
|
||||
equals: jasmine.createSpy('delegated-equals').and.returnValue(true),
|
||||
pp: jasmineUnderTest.makePrettyPrinter()
|
||||
},
|
||||
matcher = jasmineUnderTest.matchers.toHaveBeenCalledWith(matchersUtil),
|
||||
calledSpy = new jasmineUnderTest.Spy('called-spy');
|
||||
|
||||
calledSpy('a', 'b');
|
||||
matcher.compare(calledSpy, 'a', 'b');
|
||||
|
||||
expect(calledSpy.calls.count()).toBe(1);
|
||||
expect(calledSpy.calls.unverifiedCount()).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
151
spec/core/matchers/toHaveNoOtherSpyInteractionsSpec.js
Normal file
151
spec/core/matchers/toHaveNoOtherSpyInteractionsSpec.js
Normal file
@@ -0,0 +1,151 @@
|
||||
describe('toHaveNoOtherSpyInteractions', function() {
|
||||
it('passes when there are no spy interactions', function() {
|
||||
let matcher = jasmineUnderTest.matchers.toHaveNoOtherSpyInteractions();
|
||||
let spyObj = jasmineUnderTest
|
||||
.getEnv()
|
||||
.createSpyObj('NewClass', ['spyA', 'spyB']);
|
||||
|
||||
let result = matcher.compare(spyObj);
|
||||
expect(result.pass).toBeTrue();
|
||||
});
|
||||
|
||||
it('passes when there are multiple spy interactions where checked by toHaveBeenCalled', function() {
|
||||
let matcher = jasmineUnderTest.matchers.toHaveNoOtherSpyInteractions();
|
||||
let toHaveBeenCalledMatcher = jasmineUnderTest.matchers.toHaveBeenCalled();
|
||||
let spyObj = jasmineUnderTest
|
||||
.getEnv()
|
||||
.createSpyObj('NewClass', ['spyA', 'spyB']);
|
||||
|
||||
spyObj.spyA();
|
||||
spyObj.spyB();
|
||||
spyObj.spyA();
|
||||
toHaveBeenCalledMatcher.compare(spyObj.spyA);
|
||||
toHaveBeenCalledMatcher.compare(spyObj.spyB);
|
||||
let result = matcher.compare(spyObj);
|
||||
expect(result.pass).toBeTrue();
|
||||
});
|
||||
|
||||
it('fails when there are spy interactions', function() {
|
||||
const matchersUtil = new jasmineUnderTest.MatchersUtil({
|
||||
pp: jasmineUnderTest.makePrettyPrinter()
|
||||
});
|
||||
let matcher = jasmineUnderTest.matchers.toHaveNoOtherSpyInteractions(
|
||||
matchersUtil
|
||||
);
|
||||
let spyObj = jasmineUnderTest
|
||||
.getEnv()
|
||||
.createSpyObj('NewClass', ['spyA', 'spyB']);
|
||||
|
||||
spyObj.spyA('x');
|
||||
|
||||
let result = matcher.compare(spyObj);
|
||||
expect(result.pass).toBeFalse();
|
||||
expect(result.message).toContain(
|
||||
'Expected to have no other spy interactions, but it had the following calls:'
|
||||
);
|
||||
});
|
||||
|
||||
it('shows the right message is negated', function() {
|
||||
const matchersUtil = new jasmineUnderTest.MatchersUtil({
|
||||
pp: jasmineUnderTest.makePrettyPrinter()
|
||||
});
|
||||
let matcher = jasmineUnderTest.matchers.toHaveNoOtherSpyInteractions(
|
||||
matchersUtil
|
||||
);
|
||||
let spyObj = jasmineUnderTest
|
||||
.getEnv()
|
||||
.createSpyObj('NewClass', ['spyA', 'spyB']);
|
||||
|
||||
spyObj.spyA();
|
||||
spyObj.spyB();
|
||||
|
||||
let result = matcher.compare(spyObj);
|
||||
expect(result.pass).toBeFalse(),
|
||||
expect(result.message).toContain(
|
||||
'Expected to have no other spy interactions, but it had the following calls:'
|
||||
);
|
||||
});
|
||||
|
||||
it('passes when only non-observed spy object interactions are interacted', function() {
|
||||
let matcher = jasmineUnderTest.matchers.toHaveNoOtherSpyInteractions();
|
||||
let spyObj = jasmineUnderTest
|
||||
.getEnv()
|
||||
.createSpyObj('NewClass', ['spyA', 'spyB']);
|
||||
spyObj.otherMethod = function() {};
|
||||
|
||||
spyObj.otherMethod();
|
||||
|
||||
let result = matcher.compare(spyObj);
|
||||
expect(result.pass).toBeTrue();
|
||||
expect(result.message).toContain(
|
||||
"Expected to have other spy interactions but it didn't"
|
||||
);
|
||||
});
|
||||
|
||||
it(`throws an error if a non-object is passed`, function() {
|
||||
let matcher = jasmineUnderTest.matchers.toHaveNoOtherSpyInteractions();
|
||||
|
||||
expect(function() {
|
||||
matcher.compare(true);
|
||||
}).toThrowError(Error, /Expected an object, but got/);
|
||||
|
||||
expect(function() {
|
||||
matcher.compare(123);
|
||||
}).toThrowError(Error, /Expected an object, but got/);
|
||||
|
||||
expect(function() {
|
||||
matcher.compare('string');
|
||||
}).toThrowError(Error, /Expected an object, but got/);
|
||||
});
|
||||
|
||||
it('throws an error if arguments are passed', function() {
|
||||
let matcher = jasmineUnderTest.matchers.toHaveNoOtherSpyInteractions();
|
||||
let spyObj = jasmineUnderTest
|
||||
.getEnv()
|
||||
.createSpyObj('NewClass', ['spyA', 'spyB']);
|
||||
|
||||
expect(function() {
|
||||
matcher.compare(spyObj, 'an argument');
|
||||
}).toThrowError(Error, /Does not take arguments/);
|
||||
});
|
||||
|
||||
it('throws an error if the spy object has no spies', function() {
|
||||
let matcher = jasmineUnderTest.matchers.toHaveNoOtherSpyInteractions();
|
||||
const spyObj = jasmineUnderTest
|
||||
.getEnv()
|
||||
.createSpyObj('NewClass', ['notSpy']);
|
||||
// Removing spy since spy objects cannot be created without spies.
|
||||
spyObj.notSpy = function() {};
|
||||
|
||||
expect(function() {
|
||||
matcher.compare(spyObj);
|
||||
}).toThrowError(
|
||||
Error,
|
||||
/Expected an object with spies, but object has no spies/
|
||||
);
|
||||
});
|
||||
|
||||
it('handles multiple interactions with a single spy', function() {
|
||||
const matchersUtil = new jasmineUnderTest.MatchersUtil({
|
||||
pp: jasmineUnderTest.makePrettyPrinter()
|
||||
}),
|
||||
matcher = jasmineUnderTest.matchers.toHaveNoOtherSpyInteractions(
|
||||
matchersUtil
|
||||
),
|
||||
toHaveBeenCalledWithMatcher = jasmineUnderTest.matchers.toHaveBeenCalledWith(
|
||||
matchersUtil
|
||||
),
|
||||
spyObj = jasmineUnderTest
|
||||
.getEnv()
|
||||
.createSpyObj('NewClass', ['spyA', 'spyB']);
|
||||
|
||||
spyObj.spyA('x');
|
||||
spyObj.spyA('y');
|
||||
|
||||
toHaveBeenCalledWithMatcher.compare(spyObj.spyA, 'x');
|
||||
|
||||
let result = matcher.compare(spyObj);
|
||||
|
||||
expect(result.pass).toBeFalse();
|
||||
});
|
||||
});
|
||||
@@ -125,6 +125,10 @@ getJasmineRequireObj().CallTracker = function(j$) {
|
||||
this.saveArgumentsByValue = function() {
|
||||
opts.cloneArgs = true;
|
||||
};
|
||||
|
||||
this.unverifiedCount = function() {
|
||||
return calls.reduce((count, call) => count + (call.verified ? 0 : 1), 0);
|
||||
};
|
||||
}
|
||||
|
||||
return CallTracker;
|
||||
|
||||
@@ -26,7 +26,8 @@ getJasmineRequireObj().Spy = function(j$) {
|
||||
const callData = {
|
||||
object: context,
|
||||
invocationOrder: nextOrder(),
|
||||
args: Array.prototype.slice.apply(args)
|
||||
args: Array.prototype.slice.apply(args),
|
||||
verified: false
|
||||
};
|
||||
|
||||
callTracker.track(callData);
|
||||
|
||||
@@ -30,6 +30,7 @@ getJasmineRequireObj().requireMatchers = function(jRequire, j$) {
|
||||
'toHaveClass',
|
||||
'toHaveClasses',
|
||||
'toHaveSpyInteractions',
|
||||
'toHaveNoOtherSpyInteractions',
|
||||
'toMatch',
|
||||
'toThrow',
|
||||
'toThrowError',
|
||||
|
||||
@@ -34,6 +34,8 @@ getJasmineRequireObj().toHaveBeenCalled = function(j$) {
|
||||
|
||||
result.pass = actual.calls.any();
|
||||
|
||||
actual.calls.all().forEach(call => (call.verified = true));
|
||||
|
||||
result.message = result.pass
|
||||
? 'Expected spy ' + actual.and.identity + ' not to have been called.'
|
||||
: 'Expected spy ' + actual.and.identity + ' to have been called.';
|
||||
|
||||
@@ -50,6 +50,9 @@ getJasmineRequireObj().toHaveBeenCalledBefore = function(j$) {
|
||||
result.pass = latest1stSpyCall < first2ndSpyCall;
|
||||
|
||||
if (result.pass) {
|
||||
firstSpy.calls.mostRecent().verified = true;
|
||||
latterSpy.calls.first().verified = true;
|
||||
|
||||
result.message =
|
||||
'Expected spy ' +
|
||||
firstSpy.and.identity +
|
||||
|
||||
@@ -13,7 +13,7 @@ getJasmineRequireObj().toHaveBeenCalledOnceWith = function(j$) {
|
||||
* @example
|
||||
* expect(mySpy).toHaveBeenCalledOnceWith('foo', 'bar', 2);
|
||||
*/
|
||||
function toHaveBeenCalledOnceWith(util) {
|
||||
function toHaveBeenCalledOnceWith(matchersUtil) {
|
||||
return {
|
||||
compare: function() {
|
||||
const args = Array.prototype.slice.call(arguments, 0),
|
||||
@@ -22,20 +22,29 @@ getJasmineRequireObj().toHaveBeenCalledOnceWith = function(j$) {
|
||||
|
||||
if (!j$.isSpy(actual)) {
|
||||
throw new Error(
|
||||
getErrorMsg('Expected a spy, but got ' + util.pp(actual) + '.')
|
||||
getErrorMsg(
|
||||
'Expected a spy, but got ' + matchersUtil.pp(actual) + '.'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
const prettyPrintedCalls = actual.calls
|
||||
.allArgs()
|
||||
.map(function(argsForCall) {
|
||||
return ' ' + util.pp(argsForCall);
|
||||
return ' ' + matchersUtil.pp(argsForCall);
|
||||
});
|
||||
|
||||
if (
|
||||
actual.calls.count() === 1 &&
|
||||
util.contains(actual.calls.allArgs(), expectedArgs)
|
||||
matchersUtil.contains(actual.calls.allArgs(), expectedArgs)
|
||||
) {
|
||||
const firstIndex = actual.calls
|
||||
.all()
|
||||
.findIndex(call => matchersUtil.equals(call.args, expectedArgs));
|
||||
if (firstIndex > -1) {
|
||||
actual.calls.all()[firstIndex].verified = true;
|
||||
}
|
||||
|
||||
return {
|
||||
pass: true,
|
||||
message:
|
||||
@@ -43,7 +52,7 @@ getJasmineRequireObj().toHaveBeenCalledOnceWith = function(j$) {
|
||||
actual.and.identity +
|
||||
' to have been called 0 times, multiple times, or once, but with arguments different from:\n' +
|
||||
' ' +
|
||||
util.pp(expectedArgs) +
|
||||
matchersUtil.pp(expectedArgs) +
|
||||
'\n' +
|
||||
'But the actual call was:\n' +
|
||||
prettyPrintedCalls.join(',\n') +
|
||||
@@ -54,7 +63,7 @@ getJasmineRequireObj().toHaveBeenCalledOnceWith = function(j$) {
|
||||
function getDiffs() {
|
||||
return actual.calls.allArgs().map(function(argsForCall, callIx) {
|
||||
const diffBuilder = new j$.DiffBuilder();
|
||||
util.equals(argsForCall, expectedArgs, diffBuilder);
|
||||
matchersUtil.equals(argsForCall, expectedArgs, diffBuilder);
|
||||
return diffBuilder.getMessage();
|
||||
});
|
||||
}
|
||||
@@ -87,7 +96,7 @@ getJasmineRequireObj().toHaveBeenCalledOnceWith = function(j$) {
|
||||
actual.and.identity +
|
||||
' to have been called only once, and with given args:\n' +
|
||||
' ' +
|
||||
util.pp(expectedArgs) +
|
||||
matchersUtil.pp(expectedArgs) +
|
||||
'\n' +
|
||||
butString()
|
||||
};
|
||||
|
||||
@@ -36,23 +36,35 @@ getJasmineRequireObj().toHaveBeenCalledTimes = function(j$) {
|
||||
}
|
||||
|
||||
actual = args[0];
|
||||
const calls = actual.calls.count();
|
||||
|
||||
const callsCount = actual.calls.count();
|
||||
const timesMessage = expected === 1 ? 'once' : expected + ' times';
|
||||
result.pass = calls === expected;
|
||||
|
||||
result.pass = callsCount === expected;
|
||||
|
||||
if (result.pass) {
|
||||
const allCalls = actual.calls.all();
|
||||
const max = Math.min(expected, callsCount);
|
||||
|
||||
for (let i = 0; i < max; i++) {
|
||||
allCalls[i].verified = true;
|
||||
}
|
||||
}
|
||||
|
||||
result.message = result.pass
|
||||
? 'Expected spy ' +
|
||||
actual.and.identity +
|
||||
' not to have been called ' +
|
||||
timesMessage +
|
||||
'. It was called ' +
|
||||
calls +
|
||||
callsCount +
|
||||
' times.'
|
||||
: 'Expected spy ' +
|
||||
actual.and.identity +
|
||||
' to have been called ' +
|
||||
timesMessage +
|
||||
'. It was called ' +
|
||||
calls +
|
||||
callsCount +
|
||||
' times.';
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -44,6 +44,11 @@ getJasmineRequireObj().toHaveBeenCalledWith = function(j$) {
|
||||
}
|
||||
|
||||
if (matchersUtil.contains(actual.calls.allArgs(), expectedArgs)) {
|
||||
actual.calls
|
||||
.all()
|
||||
.filter(call => matchersUtil.equals(call.args, expectedArgs))
|
||||
.forEach(call => (call.verified = true));
|
||||
|
||||
result.pass = true;
|
||||
result.message = function() {
|
||||
return (
|
||||
|
||||
87
src/core/matchers/toHaveNoOtherSpyInteractions.js
Normal file
87
src/core/matchers/toHaveNoOtherSpyInteractions.js
Normal file
@@ -0,0 +1,87 @@
|
||||
getJasmineRequireObj().toHaveNoOtherSpyInteractions = function(j$) {
|
||||
const getErrorMsg = j$.formatErrorMsg(
|
||||
'<toHaveNoOtherSpyInteractions>',
|
||||
'expect(<spyObj>).toHaveNoOtherSpyInteractions()'
|
||||
);
|
||||
|
||||
/**
|
||||
* {@link expect} the actual (a {@link SpyObj}) spies to have not been called except interactions which was already tracked with `toHaveBeenCalled`.
|
||||
* @function
|
||||
* @name matchers#toHaveNoOtherSpyInteractions
|
||||
* @example
|
||||
* expect(mySpyObj).toHaveNoOtherSpyInteractions();
|
||||
* expect(mySpyObj).not.toHaveNoOtherSpyInteractions();
|
||||
*/
|
||||
function toHaveNoOtherSpyInteractions(matchersUtil) {
|
||||
return {
|
||||
compare: function(actual) {
|
||||
const result = {};
|
||||
|
||||
if (!j$.isObject_(actual)) {
|
||||
throw new Error(
|
||||
getErrorMsg('Expected an object, but got ' + typeof actual + '.')
|
||||
);
|
||||
}
|
||||
|
||||
if (arguments.length > 1) {
|
||||
throw new Error(getErrorMsg('Does not take arguments'));
|
||||
}
|
||||
|
||||
result.pass = true;
|
||||
let hasSpy = false;
|
||||
const unexpectedCalls = [];
|
||||
|
||||
for (const spy of Object.values(actual)) {
|
||||
if (!j$.isSpy(spy)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
hasSpy = true;
|
||||
|
||||
const unverifiedCalls = spy.calls
|
||||
.all()
|
||||
.filter(call => !call.verified);
|
||||
|
||||
if (unverifiedCalls.length > 0) {
|
||||
result.pass = false;
|
||||
}
|
||||
|
||||
unverifiedCalls.forEach(unverifiedCall => {
|
||||
unexpectedCalls.push([
|
||||
spy.and.identity,
|
||||
matchersUtil.pp(unverifiedCall.args)
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
if (!hasSpy) {
|
||||
throw new Error(
|
||||
getErrorMsg(
|
||||
'Expected an object with spies, but object has no spies.'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (result.pass) {
|
||||
result.message =
|
||||
"Expected to have other spy interactions but it didn't.";
|
||||
} else {
|
||||
const ppUnexpectedCalls = unexpectedCalls
|
||||
.map(
|
||||
([spyName, arguments]) => ` ${spyName} called with ${arguments}`
|
||||
)
|
||||
.join(',\n');
|
||||
|
||||
result.message =
|
||||
'Expected to have no other spy interactions, but it had the following calls:\n' +
|
||||
ppUnexpectedCalls +
|
||||
'.\n\n';
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return toHaveNoOtherSpyInteractions;
|
||||
};
|
||||
Reference in New Issue
Block a user