unexpected-sinon
Advanced tools
Comparing version 10.0.0 to 10.1.0
@@ -38,2 +38,14 @@ Passes if all the calls of a spy [satisfy](http://unexpected.js.org/assertions/any/to-satisfy/) a given spec: | ||
An array entry value will be interpreted as a shorthand for `{ args: ... }`: | ||
```js | ||
expect(increment, 'to have a call satisfying', [ 42 ]); | ||
``` | ||
Likewise for an object with only numerical properties: | ||
```js | ||
expect(increment, 'to have a call satisfying', { 1: 'yadda' }); | ||
``` | ||
Note that the individual arguments are matched with | ||
@@ -40,0 +52,0 @@ [`to satisfy`](http://unexpected.js.org/assertions/any/to-satisfy/) |
Passes if the spy was called with the provided arguments. | ||
THIS ASSERTION IS DEPRECATED AND WILL BE REMOVED IN A LATER VERSION. | ||
Please use [`to have a call satisfying`](../to-have-a-call-satisfying/) instead. | ||
```js | ||
@@ -4,0 +7,0 @@ var mySpy = sinon.spy().named('mySpy'); |
@@ -18,10 +18,29 @@ --- | ||
```js | ||
var obj = { spy: sinon.spy() }; | ||
obj.spy(42); | ||
obj.spy({ foo: 'bar' }, 'baz', "qux"); | ||
expect(obj.spy, "was called twice"); | ||
expect(obj.spy, 'was called with', { foo: 'bar' }, 'baz', expect.it('to be truthy')); | ||
expect(obj.spy, 'was always called on', obj); | ||
var mySpy = sinon.spy().named('mySpy'); | ||
mySpy(42); | ||
mySpy({ foo: 'bar' }, 'baz', 'qux'); | ||
expect(mySpy, 'was called twice'); | ||
expect(mySpy, 'to have calls satisfying', function () { | ||
mySpy(42); | ||
mySpy({ foo: 'baz' }, expect.it('to be a string')); | ||
}); | ||
``` | ||
```output | ||
expected mySpy to have calls satisfying | ||
mySpy( 42 ); | ||
mySpy( { foo: 'baz' }, expect.it('to be a string') ); | ||
mySpy( 42 ); at theFunction (theFileName:xx:yy) | ||
mySpy( | ||
{ | ||
foo: 'bar' // should equal 'baz' | ||
// -bar | ||
// +baz | ||
}, | ||
'baz', | ||
'qux' // should be removed | ||
); at theFunction (theFileName:xx:yy) | ||
``` | ||
[![NPM version](https://badge.fury.io/js/unexpected-sinon.svg)](http://badge.fury.io/js/unexpected-sinon) | ||
@@ -95,27 +114,2 @@ [![Build Status](https://travis-ci.org/unexpectedjs/unexpected-sinon.svg?branch=master)](https://travis-ci.org/unexpectedjs/unexpected-sinon) | ||
## Expectations on arguments of individual calls | ||
```js | ||
var spy = sinon.spy(); | ||
spy({ foo: 'bar' }, 'baz'); | ||
spy('qux'); | ||
spy('quux'); | ||
expect(spy.args, 'to equal', [ | ||
[{ foo: 'bar' }, 'baz'], | ||
['qux'], | ||
['quux'] | ||
]); | ||
expect(spy.args[1], 'to equal', ['qux']); | ||
expect(spy.args, 'to satisfy', { | ||
0: [ | ||
{ foo: 'bar' }, | ||
expect.it('to be a string').and('to have length', 3) | ||
], | ||
2: ['quux'] | ||
}); | ||
``` | ||
## Source | ||
@@ -122,0 +116,0 @@ |
@@ -81,2 +81,50 @@ /*global location*/ | ||
function recordSpyCalls(spies, fn) { | ||
var originalValues = spies.map(function (spy) { | ||
var originalValue = { | ||
func: spy.func | ||
}; | ||
// Temporarily override the body of the spied-on function, if any. | ||
// This prevents spies with side effects from breaking while | ||
// the expected calls are being recorded: | ||
spy.func = function () {}; | ||
for (var propertyName in spy) { | ||
if (spy.hasOwnProperty(propertyName) && typeof spy[propertyName] !== 'function') { | ||
if (Array.isArray(spy[propertyName])) { | ||
originalValue[propertyName] = [].concat(spy[propertyName]); | ||
} else { | ||
originalValue[propertyName] = spy[propertyName]; | ||
} | ||
} | ||
} | ||
return originalValue; | ||
}); | ||
fn(); | ||
var expectedSpyCallSpecs = []; | ||
spies.forEach(function (spy, i) { | ||
var originalValue = originalValues[i]; | ||
for (var j = originalValue.args.length ; j < spy.args.length ; j += 1) { | ||
var thisValue = spy.thisValues[j]; | ||
var calledWithNew = thisValue instanceof spy; | ||
var expectedSpyCallSpec = { | ||
proxy: spy, | ||
call: spy.getCall(j), | ||
args: spy.args[j], | ||
callId: spy.callIds[j], | ||
calledWithNew: calledWithNew | ||
}; | ||
expectedSpyCallSpec.call.getStackFrames = false; | ||
expectedSpyCallSpecs.push(expectedSpyCallSpec); | ||
} | ||
for (var propertyName in originalValue) { | ||
spy[propertyName] = originalValue[propertyName]; | ||
} | ||
}); | ||
expectedSpyCallSpecs.sort(function (a, b) { | ||
return a.callId - b.callId; | ||
}); | ||
return expectedSpyCallSpecs; | ||
} | ||
return { | ||
@@ -336,46 +384,3 @@ name: 'unexpected-sinon', | ||
} | ||
var originalValues = spies.map(function (spy) { | ||
var originalValue = { | ||
func: spy.func | ||
}; | ||
// Temporarily override the body of the spied-on function, if any. | ||
// This prevents spies with side effects from breaking while | ||
// the expected calls are being recorded: | ||
spy.func = function () {}; | ||
for (var propertyName in spy) { | ||
if (spy.hasOwnProperty(propertyName) && typeof spy[propertyName] !== 'function') { | ||
if (Array.isArray(spy[propertyName])) { | ||
originalValue[propertyName] = [].concat(spy[propertyName]); | ||
} else { | ||
originalValue[propertyName] = spy[propertyName]; | ||
} | ||
} | ||
} | ||
return originalValue; | ||
}); | ||
value(); | ||
var expectedSpyCallSpecs = []; | ||
spies.forEach(function (spy, i) { | ||
var originalValue = originalValues[i]; | ||
for (var j = originalValue.args.length ; j < spy.args.length ; j += 1) { | ||
var thisValue = spy.thisValues[j]; | ||
var calledWithNew = thisValue instanceof spy; | ||
var expectedSpyCallSpec = { | ||
proxy: spy, | ||
call: spy.getCall(j), | ||
args: spy.args[j], | ||
callId: spy.callIds[j], | ||
calledWithNew: calledWithNew | ||
}; | ||
expectedSpyCallSpec.call.getStackFrames = false; | ||
expectedSpyCallSpecs.push(expectedSpyCallSpec); | ||
} | ||
for (var propertyName in originalValue) { | ||
spy[propertyName] = originalValue[propertyName]; | ||
} | ||
}); | ||
expectedSpyCallSpecs.sort(function (a, b) { | ||
return a.callId - b.callId; | ||
}); | ||
var expectedSpyCallSpecs = recordSpyCalls(spies, value); | ||
var expectedSpyCalls = []; | ||
@@ -415,3 +420,15 @@ expectedSpyCallSpecs.forEach(function (expectedSpyCallSpec) { | ||
return { spy: obj }; | ||
} else { | ||
} else if (Array.isArray(obj)) { | ||
return { args: obj }; | ||
} else if (obj && typeof obj === 'object') { | ||
var keys = Object.keys(obj); | ||
if ( | ||
keys.length > 0 && | ||
keys.every(function (key) { | ||
return /^[1-9]*[0-9]+$/.test(key); | ||
}) | ||
) { | ||
return { args: obj }; | ||
} | ||
if (isSpy(obj.spy)) { | ||
@@ -421,2 +438,7 @@ seenSpies.push(obj.spy); | ||
return obj; | ||
} else { | ||
expect.errorMode = 'nested'; | ||
expect.fail(function () { | ||
this.error('unsupported value in spy call spec: ').appendInspected(obj); | ||
}); | ||
} | ||
@@ -504,2 +526,55 @@ } | ||
expect.addAssertion('<spy> to have a call [exhaustively] satisfying <object>', function (expect, subject, value) { | ||
var keys = Object.keys(value); | ||
if ( | ||
keys.length > 0 && | ||
keys.every(function (key) { | ||
return /^[1-9]*[0-9]+$/.test(key); | ||
}) | ||
) { | ||
return expect(subject, 'to have a call [exhaustively] satisfying', { args: value }); | ||
} | ||
expect.errorMode = 'defaultOrNested'; | ||
var calls = getCalls(subject); | ||
var promises = calls.map(function (call) { | ||
return expect.promise(function () { | ||
return expect(call, 'to [exhaustively] satisfy', value); | ||
}); | ||
}); | ||
return expect.promise.settle(promises).then(function () { | ||
var failed = promises.every(function (promise) { | ||
return promise.isRejected(); | ||
}); | ||
if (failed) { | ||
return expect(calls, 'to have items [exhaustively] satisfying', value); | ||
} | ||
}); | ||
}); | ||
expect.addAssertion('<spy> to have a call [exhaustively] satisfying <array>', function (expect, subject, value) { | ||
return expect(subject, 'to have a call [exhaustively] satisfying', { args: value }); | ||
}); | ||
expect.addAssertion('<spy> to have a call satisfying <function>', function (expect, subject, value) { | ||
var expectedSpyCallSpecs = recordSpyCalls([subject], value); | ||
var expectedSpyCalls = []; | ||
expectedSpyCallSpecs.forEach(function (expectedSpyCallSpec) { | ||
expectedSpyCalls.push(expectedSpyCallSpec.call); | ||
delete expectedSpyCallSpec.call; | ||
delete expectedSpyCallSpec.callId; | ||
}); | ||
if (expectedSpyCalls.length > 0) { | ||
expect.argsOutput[0] = function (output) { | ||
output.appendInspected(expectedSpyCalls); | ||
}; | ||
} | ||
if (expectedSpyCallSpecs.length !== 1) { | ||
expect.errorMode = 'nested'; | ||
expect.fail('expected the provided function to call the spy exactly once, but it called it ' + expectedSpyCallSpecs.length + ' times'); | ||
} | ||
return expect(subject, 'to have a call satisfying', expectedSpyCallSpecs[0]); | ||
}); | ||
expect.addAssertion('<spy> was [always] called with [exactly] <any*>', function (expect, subject) { | ||
@@ -506,0 +581,0 @@ expect.errorMode = 'defaultOrNested'; |
{ | ||
"name": "unexpected-sinon", | ||
"version": "10.0.0", | ||
"version": "10.1.0", | ||
"author": "Sune Sloth Simonsen <sune@we-knowhow.dk>", | ||
@@ -21,3 +21,3 @@ "keywords": [ | ||
"lint": "jshint .", | ||
"test": "mocha --require ./test/common && npm run lint", | ||
"test": "mocha --compilers md:unexpected-markdown test/*.js `find documentation -name '*.md'` && npm run lint", | ||
"travis": "npm test && npm run coverage && (<coverage/lcov.info coveralls || true) && npm run generate-site", | ||
@@ -33,3 +33,3 @@ "test-browser": "serve .", | ||
"sinon": "*", | ||
"unexpected": "^10.6.0" | ||
"unexpected": "^10.8.0" | ||
}, | ||
@@ -43,5 +43,6 @@ "devDependencies": { | ||
"sinon": "1.16.1", | ||
"unexpected": "10.6.0", | ||
"unexpected-documentation-site-generator": "^3.3.1" | ||
"unexpected": "10.8.0", | ||
"unexpected-documentation-site-generator": "^4.0.0", | ||
"unexpected-markdown": "^1.3.1" | ||
} | ||
} |
@@ -703,2 +703,175 @@ /*global describe, it, beforeEach, sinon, unexpected*/ | ||
describe('to have a call satisfying', function () { | ||
describe('when passed a spec object', function () { | ||
it('should succeed when a spy call satisfies the spec', function () { | ||
spy(123, 456); | ||
expect(spy, 'to have a call satisfying', { | ||
args: [ 123, 456 ] | ||
}); | ||
}); | ||
it('should fail when the spy was not called at all', function () { | ||
expect(function () { | ||
expect(spy, 'to have a call satisfying', { | ||
args: [ 123, 456 ] | ||
}); | ||
}, 'to throw', | ||
"expected spy1 to have a call satisfying { args: [ 123, 456 ] }\n" + | ||
" expected [] to have items satisfying { args: [ 123, 456 ] }\n" + | ||
" expected [] to be non-empty" | ||
); | ||
}); | ||
it('should fail when the spy was called but never with the right arguments', function () { | ||
spy(456); | ||
spy(567); | ||
expect(function () { | ||
expect(spy, 'to have a call satisfying', { | ||
args: [ 123, 456 ] | ||
}); | ||
}, 'to throw', | ||
"expected spy1 to have a call satisfying { args: [ 123, 456 ] }\n" + | ||
"\n" + | ||
"spy1(\n" + | ||
" // missing 123\n" + | ||
" 456\n" + | ||
"); at theFunction (theFileName:xx:yy)\n" + | ||
"spy1(\n" + | ||
" 567 // should equal 123\n" + | ||
" // missing 456\n" + | ||
"); at theFunction (theFileName:xx:yy)" | ||
); | ||
}); | ||
describe('with the exhaustively flag', function () { | ||
it('should succeed when a spy call satisfies the spec', function () { | ||
spy(123, { foo: 'bar' }); | ||
expect(spy, 'to have a call satisfying', { | ||
args: [ 123, { foo: 'bar' } ] | ||
}); | ||
}); | ||
it('should fail when a spy call does not satisfy the spec only because of the "exhaustively" semantics', function () { | ||
spy(123, { foo: 'bar', quux: 'baz' }); | ||
expect(function () { | ||
expect(spy, 'to have a call exhaustively satisfying', { | ||
args: [ 123, { foo: 'bar' } ] | ||
}); | ||
}, 'to throw', | ||
"expected spy1 to have a call exhaustively satisfying { args: [ 123, { foo: 'bar' } ] }\n" + | ||
"\n" + | ||
"spy1(\n" + | ||
" 123,\n" + | ||
" {\n" + | ||
" foo: 'bar',\n" + | ||
" quux: 'baz' // should be removed\n" + | ||
" }\n" + | ||
"); at theFunction (theFileName:xx:yy)" | ||
); | ||
}); | ||
}); | ||
}); | ||
describe('when passed an array (shorthand for {args: ...})', function () { | ||
it('should succeed', function () { | ||
spy(123, { foo: 'bar' }); | ||
expect(spy, 'to have a call satisfying', [ 123, { foo: 'bar' } ]); | ||
}); | ||
it('should fail with a diff', function () { | ||
expect(function () { | ||
spy(123, { foo: 'bar' }); | ||
expect(spy, 'to have a call satisfying', [ 123, { foo: 'baz' } ]); | ||
}, 'to throw', | ||
"expected spy1 to have a call satisfying [ 123, { foo: 'baz' } ]\n" + | ||
"\n" + | ||
"spy1(\n" + | ||
" 123,\n" + | ||
" {\n" + | ||
" foo: 'bar' // should equal 'baz'\n" + | ||
" // -bar\n" + | ||
" // +baz\n" + | ||
" }\n" + | ||
"); at theFunction (theFileName:xx:yy)" | ||
); | ||
}); | ||
}); | ||
describe('when passed an array with only numerical properties (shorthand for {args: ...})', function () { | ||
it('should succeed', function () { | ||
spy(123, { foo: 'bar' }); | ||
expect(spy, 'to have a call satisfying', {0: 123, 1: {foo: 'bar'}}); | ||
}); | ||
it('should fail with a diff', function () { | ||
expect(function () { | ||
spy(123, { foo: 'bar' }); | ||
expect(spy, 'to have a call satisfying', {0: 123, 1: {foo: 'baz'}}); | ||
}, 'to throw', | ||
"expected spy1 to have a call satisfying { 0: 123, 1: { foo: 'baz' } }\n" + | ||
"\n" + | ||
"spy1(\n" + | ||
" 123,\n" + | ||
" {\n" + | ||
" foo: 'bar' // should equal 'baz'\n" + | ||
" // -bar\n" + | ||
" // +baz\n" + | ||
" }\n" + | ||
"); at theFunction (theFileName:xx:yy)" | ||
); | ||
}); | ||
}); | ||
describe('when passed a function that performs the expected call', function () { | ||
it('should succeed when a spy call satisfies the spec', function () { | ||
spy(123, 456); | ||
expect(spy, 'to have a call satisfying', function () { | ||
spy(123, 456); | ||
}); | ||
}); | ||
it('should fail if the function does not call the spy', function () { | ||
expect(function () { | ||
expect(spy, 'to have a call satisfying', function () {}); | ||
}, 'to throw', | ||
"expected spy1 to have a call satisfying function () {}\n" + | ||
" expected the provided function to call the spy exactly once, but it called it 0 times" | ||
); | ||
}); | ||
it('should fail if the function calls the spy more than once', function () { | ||
expect(function () { | ||
expect(spy, 'to have a call satisfying', function () { | ||
spy(123); | ||
spy(456); | ||
}); | ||
}, 'to throw', | ||
"expected spy1 to have a call satisfying\n" + | ||
"spy1( 123 );\n" + | ||
"spy1( 456 );\n" + | ||
" expected the provided function to call the spy exactly once, but it called it 2 times" | ||
); | ||
}); | ||
it('should fail when the spy was called but never with the right arguments', function () { | ||
spy(123); | ||
spy(456); | ||
expect(function () { | ||
expect(spy, 'to have a call satisfying', function () { | ||
spy(789); | ||
}); | ||
}, 'to throw', | ||
"expected spy1 to have a call satisfying spy1( 789 );\n" + | ||
"\n" + | ||
"spy1(\n" + | ||
" 123 // should equal 789\n" + | ||
"); at theFunction (theFileName:xx:yy)\n" + | ||
"spy1(\n" + | ||
" 456 // should equal 789\n" + | ||
"); at theFunction (theFileName:xx:yy)" | ||
); | ||
}); | ||
}); | ||
}); | ||
describe('to have calls satisfying', function () { | ||
@@ -762,2 +935,52 @@ it('should satisfy against a list of all calls to the specified spies', function () { | ||
describe('when passed an array entry (shorthand for {args: ...})', function () { | ||
it('should succeed', function () { | ||
spy(123, { foo: 'bar' }); | ||
expect(spy, 'to have calls satisfying', [ [ 123, { foo: 'bar' } ] ]); | ||
}); | ||
it('should fail with a diff', function () { | ||
expect(function () { | ||
spy(123, { foo: 'bar' }); | ||
expect(spy, 'to have calls satisfying', [ [ 123, { foo: 'baz' } ] ]); | ||
}, 'to throw', | ||
"expected spy1 to have calls satisfying [ [ 123, { foo: 'baz' } ] ]\n" + | ||
"\n" + | ||
"spy1(\n" + | ||
" 123,\n" + | ||
" {\n" + | ||
" foo: 'bar' // should equal 'baz'\n" + | ||
" // -bar\n" + | ||
" // +baz\n" + | ||
" }\n" + | ||
"); at theFunction (theFileName:xx:yy)" | ||
); | ||
}); | ||
}); | ||
describe('when passed an array with only numerical properties (shorthand for {args: ...})', function () { | ||
it('should succeed', function () { | ||
spy(123, { foo: 'bar' }); | ||
expect(spy, 'to have calls satisfying', [{0: 123, 1: {foo: 'bar'}}]); | ||
}); | ||
it('should fail with a diff', function () { | ||
expect(function () { | ||
spy(123, { foo: 'bar' }); | ||
expect(spy, 'to have calls satisfying', [{0: 123, 1: {foo: 'baz'}}]); | ||
}, 'to throw', | ||
"expected spy1 to have calls satisfying [ { 0: 123, 1: { foo: 'baz' } } ]\n" + | ||
"\n" + | ||
"spy1(\n" + | ||
" 123,\n" + | ||
" {\n" + | ||
" foo: 'bar' // should equal 'baz'\n" + | ||
" // -bar\n" + | ||
" // +baz\n" + | ||
" }\n" + | ||
"); at theFunction (theFileName:xx:yy)" | ||
); | ||
}); | ||
}); | ||
it('should complain if the spy list does not contain a spy that is contained by the spec', function () { | ||
@@ -776,2 +999,11 @@ var spy2 = sinon.spy(function spy2() { | ||
it('should complain if a spy call spec contains an unsupported type', function () { | ||
expect(function () { | ||
expect(spy, 'to have calls satisfying', [123]); | ||
}, 'to throw', | ||
"expected spy1 to have calls satisfying [ 123 ]\n" + | ||
" unsupported value in spy call spec: 123" | ||
); | ||
}); | ||
describe('with the exhaustively flag', function () { | ||
@@ -778,0 +1010,0 @@ it('should fail if an object parameter contains additional properties', function () { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
364119
9
28
6377