testdouble
Advanced tools
Comparing version 0.8.0 to 0.9.0
@@ -246,2 +246,98 @@ # Stubbing behavior | ||
### Stubbing callback APIs | ||
Callback APIs are very common, especially in Node.js, and for terseness and | ||
convenience sake, testdouble.js provides conveniences for stubbing functions | ||
that expect a callback argument. | ||
Suppose you'd like to test-drive a function like this: | ||
``` js | ||
function deleteFiles(pattern, glob, rm) { | ||
glob(pattern, function(er, files) { | ||
files.forEach(function(file){ | ||
rm(file) | ||
}) | ||
}) | ||
} | ||
``` | ||
You could write a test for `deleteFiles` using `td.when`'s `thenCallback` API: | ||
``` js | ||
var glob = td.function() | ||
var rm = td.function() | ||
td.when(glob('some/pattern/**')).thenCallback(null, ['foo', 'bar']) | ||
deleteFiles('some/pattern/**', glob, rm) | ||
td.verify(rm('foo')) | ||
td.verify(rm('bar')) | ||
``` | ||
The above is very terse and gets the job done, but it makes some assumptions that | ||
may not apply to every situation. The above assumes: | ||
* that `glob`'s callback argument is the last argument users will pass to it | ||
(which is a pretty common convention) | ||
* that the return value of `glob` is not significant | ||
Note that **all callbacks are invoked synchronously**, which makes unit testing | ||
functions which are only incidentally asynchronous much simpler. | ||
#### Callback APIs with a callback argument at an arbitrary position | ||
Take the same example above, but suppose that `glob`'s arguments were reversed: | ||
the callback was in the first position and the string pattern was passed second. | ||
This can be done by placing a reference to `td.callback` as a marker for its | ||
argument position to the stubbing: | ||
``` js | ||
td.when(glob(td.callback, 'some/pattern/**')).thenCallback(null, ['foo', 'bar']) | ||
``` | ||
#### Callback APIs with meaningful return values | ||
Suppose in the above example that `glob`'s return value was also significant, | ||
in that case we can trade terseness for some added explicitness by treating | ||
`td.callback` as an argument matcher and chaining `td.when` with `thenReturn` | ||
as we might normally do: | ||
``` js | ||
td.when(glob('some/pattern/**', td.callback(null, ['foo', 'bar']))).thenReturn(8) | ||
``` | ||
Now, calls that satisfy the above stubbing on `glob` will both invoke the callback | ||
with the parameters provided to `td.callback` and also return `8`. | ||
#### Callback APIs with multiple callback arguments | ||
Some APIs have multiple callback functions, all of which need to be invoked to | ||
properly exercise the subject. Suppose your code depends on | ||
`doWork(onStart, onEnd)`, and both callback arguments should be invoked in a | ||
single test, you could: | ||
``` js | ||
var doWork = td.function() | ||
td.when(doWork(td.callback(null, 42), td.callback(null, 58))).thenReturn() | ||
var percent = 0 | ||
doWork(function(er, progress) { | ||
percent += progress | ||
}, function(er, progress) { | ||
percent += progress | ||
}) | ||
assert.equal(percent, 100) | ||
``` | ||
Remember, not every test needs to invoke every callback; it's fine to specify | ||
them separately, especially if it would lead to more focused tests. You could | ||
break up the above into two tests by matching the other function argument with | ||
an `isA(Function)` matcher: | ||
``` js | ||
td.when(doWork(td.callback(null, 42), td.matchers.isA(Function))).thenReturn() | ||
``` | ||
### Configuring stubbings | ||
@@ -248,0 +344,0 @@ |
@@ -61,3 +61,3 @@ # Verifying interactions | ||
As you can see, the expected arguments of the failed verification are pritned | ||
As you can see, the expected arguments of the failed verification are printed | ||
along with any actual invocations of the test double function. | ||
@@ -64,0 +64,0 @@ |
@@ -5,2 +5,6 @@ // Generated by CoffeeScript 1.10.0 | ||
window.td = window.testdouble; | ||
window.NODE_JS = false; | ||
}).call(this); |
// Generated by CoffeeScript 1.10.0 | ||
(function() { | ||
var slice = [].slice; | ||
global.expect = chai.expect; | ||
global.requireSubject = function(path) { | ||
var lib, pathComponents, ref; | ||
if (path == null) { | ||
return testdouble; | ||
} | ||
ref = path.split('/'), lib = ref[0], pathComponents = 2 <= ref.length ? slice.call(ref, 1) : []; | ||
return _.reduce(pathComponents, function(memo, nextProp) { | ||
return memo[nextProp]; | ||
}, testdouble); | ||
}; | ||
global.xThen = function() {}; | ||
@@ -25,3 +12,3 @@ | ||
afterEach(function() { | ||
return testdouble.reset(); | ||
return td.reset(); | ||
}); | ||
@@ -28,0 +15,0 @@ |
@@ -5,19 +5,10 @@ // Generated by CoffeeScript 1.10.0 | ||
Given(function() { | ||
return this.when = requireSubject('lib/when'); | ||
return this.testDouble = td["function"](); | ||
}); | ||
Given(function() { | ||
return this.verify = requireSubject('lib/verify'); | ||
return this.captor = td.matchers.captor(); | ||
}); | ||
Given(function() { | ||
return this.testDouble = requireSubject('lib/function')(); | ||
}); | ||
Given(function() { | ||
return this.subject = requireSubject('lib/matchers/captor'); | ||
}); | ||
Given(function() { | ||
return this.captor = this.subject(); | ||
}); | ||
describe('when stubbing', function() { | ||
Given(function() { | ||
return this.when(this.testDouble(this.captor.capture())).thenReturn('foobaby'); | ||
return td.when(this.testDouble(this.captor.capture())).thenReturn('foobaby'); | ||
}); | ||
@@ -39,3 +30,3 @@ When(function() { | ||
When(function() { | ||
return this.verify(this.testDouble(this.captor.capture())); | ||
return td.verify(this.testDouble(this.captor.capture())); | ||
}); | ||
@@ -42,0 +33,0 @@ return Then(function() { |
@@ -5,15 +5,6 @@ // Generated by CoffeeScript 1.10.0 | ||
Given(function() { | ||
return this.explain = requireSubject('lib/explain'); | ||
return this.testDouble = td["function"](); | ||
}); | ||
Given(function() { | ||
return this["function"] = requireSubject('lib/function'); | ||
}); | ||
Given(function() { | ||
return this.when = requireSubject('lib/when'); | ||
}); | ||
Given(function() { | ||
return this.testDouble = this["function"](); | ||
}); | ||
When(function() { | ||
return this.result = this.explain(this.testDouble); | ||
return this.result = td.explain(this.testDouble); | ||
}); | ||
@@ -31,3 +22,3 @@ context('a brand new test double', function() { | ||
Given(function() { | ||
return this.testDouble = this["function"]("foobaby"); | ||
return this.testDouble = td["function"]("foobaby"); | ||
}); | ||
@@ -40,6 +31,6 @@ return Then(function() { | ||
Given(function() { | ||
return this.when(this.testDouble(88)).thenReturn(5); | ||
return td.when(this.testDouble(88)).thenReturn(5); | ||
}); | ||
Given(function() { | ||
return this.when(this.testDouble("two things!")).thenReturn("woah", "such"); | ||
return td.when(this.testDouble("two things!")).thenReturn("woah", "such"); | ||
}); | ||
@@ -46,0 +37,0 @@ Given(function() { |
// Generated by CoffeeScript 1.10.0 | ||
(function() { | ||
describe('.matchers', function() { | ||
Given(function() { | ||
return this.matchers = requireSubject('lib/matchers'); | ||
}); | ||
describe('.isA', function() { | ||
context('numbers', function() { | ||
Given(function() { | ||
return this.matcher = this.matchers.isA(Number); | ||
return this.matcher = td.matchers.isA(Number); | ||
}); | ||
@@ -30,3 +27,3 @@ Then(function() { | ||
Given(function() { | ||
return this.matcher = this.matchers.isA(String); | ||
return this.matcher = td.matchers.isA(String); | ||
}); | ||
@@ -48,3 +45,3 @@ Then(function() { | ||
Given(function() { | ||
return this.matcher = this.matchers.isA(Boolean); | ||
return this.matcher = td.matchers.isA(Boolean); | ||
}); | ||
@@ -72,12 +69,12 @@ Then(function() { | ||
Then(function() { | ||
return this.matchers.isA(Array).__matches([]) === true; | ||
return td.matchers.isA(Array).__matches([]) === true; | ||
}); | ||
Then(function() { | ||
return this.matchers.isA(Object).__matches([]) === true; | ||
return td.matchers.isA(Object).__matches([]) === true; | ||
}); | ||
Then(function() { | ||
return this.matchers.isA(Date).__matches(new Date()) === true; | ||
return td.matchers.isA(Date).__matches(new Date()) === true; | ||
}); | ||
return Then(function() { | ||
return this.matchers.isA(Date).__matches(new Object()) === false; | ||
return td.matchers.isA(Date).__matches(new Object()) === false; | ||
}); | ||
@@ -88,12 +85,12 @@ }); | ||
Then(function() { | ||
return this.matchers.anything().__matches(null) === true; | ||
return td.matchers.anything().__matches(null) === true; | ||
}); | ||
Then(function() { | ||
return this.matchers.anything().__matches(void 0) === true; | ||
return td.matchers.anything().__matches(void 0) === true; | ||
}); | ||
Then(function() { | ||
return this.matchers.anything().__matches(new Date()) === true; | ||
return td.matchers.anything().__matches(new Date()) === true; | ||
}); | ||
return Then(function() { | ||
return this.matchers.anything().__matches({ | ||
return td.matchers.anything().__matches({ | ||
a: 'foo', | ||
@@ -107,6 +104,6 @@ b: 'bar' | ||
Then(function() { | ||
return this.matchers.contains('bar').__matches('foobarbaz') === true; | ||
return td.matchers.contains('bar').__matches('foobarbaz') === true; | ||
}); | ||
Then(function() { | ||
return this.matchers.contains('biz').__matches('foobarbaz') === false; | ||
return td.matchers.contains('biz').__matches('foobarbaz') === false; | ||
}); | ||
@@ -116,3 +113,3 @@ return Then(function() { | ||
return function() { | ||
return _this.matchers.contains(48).__matches(); | ||
return td.matchers.contains(48).__matches(); | ||
}; | ||
@@ -124,15 +121,15 @@ })(this)), "the contains() matcher only supports strings, arrays, and plain objects"); | ||
Then(function() { | ||
return this.matchers.contains('a').__matches(['a', 'b', 'c']) === true; | ||
return td.matchers.contains('a').__matches(['a', 'b', 'c']) === true; | ||
}); | ||
Then(function() { | ||
return this.matchers.contains('a', 'c').__matches(['a', 'b', 'c']) === true; | ||
return td.matchers.contains('a', 'c').__matches(['a', 'b', 'c']) === true; | ||
}); | ||
Then(function() { | ||
return this.matchers.contains(['a', 'c']).__matches(['a', 'b', 'c']) === false; | ||
return td.matchers.contains(['a', 'c']).__matches(['a', 'b', 'c']) === false; | ||
}); | ||
Then(function() { | ||
return this.matchers.contains(['a', 'c']).__matches([1, ['a', 'c'], 4]) === true; | ||
return td.matchers.contains(['a', 'c']).__matches([1, ['a', 'c'], 4]) === true; | ||
}); | ||
return Then(function() { | ||
return this.matchers.contains(['a', 'c']).__matches(['a', 'b', 'z']) === false; | ||
return td.matchers.contains(['a', 'c']).__matches(['a', 'b', 'z']) === false; | ||
}); | ||
@@ -142,3 +139,3 @@ }); | ||
Then(function() { | ||
return this.matchers.contains({ | ||
return td.matchers.contains({ | ||
foo: 'bar', | ||
@@ -153,3 +150,3 @@ baz: 42 | ||
Then(function() { | ||
return this.matchers.contains({ | ||
return td.matchers.contains({ | ||
foo: 'bar', | ||
@@ -163,3 +160,3 @@ lol: 42 | ||
Then(function() { | ||
return this.matchers.contains({ | ||
return td.matchers.contains({ | ||
lol: { | ||
@@ -176,3 +173,3 @@ deep: [4, 2] | ||
Then(function() { | ||
return this.matchers.contains({ | ||
return td.matchers.contains({ | ||
deep: { | ||
@@ -184,3 +181,3 @@ thing: 'stuff' | ||
Then(function() { | ||
return this.matchers.contains({ | ||
return td.matchers.contains({ | ||
deep: { | ||
@@ -197,3 +194,3 @@ thing: 'stuff' | ||
return Then(function() { | ||
return this.matchers.contains({ | ||
return td.matchers.contains({ | ||
container: { | ||
@@ -214,3 +211,3 @@ size: 'S' | ||
Then(function() { | ||
return this.matchers.argThat(function(arg) { | ||
return td.matchers.argThat(function(arg) { | ||
return arg > 5; | ||
@@ -220,3 +217,3 @@ }).__matches(6) === true; | ||
return Then(function() { | ||
return this.matchers.argThat(function(arg) { | ||
return td.matchers.argThat(function(arg) { | ||
return arg > 5; | ||
@@ -223,0 +220,0 @@ }).__matches(5) === false; |
// Generated by CoffeeScript 1.10.0 | ||
(function() { | ||
describe('testdouble.object', function() { | ||
Given(function() { | ||
return this.subject = requireSubject('lib/object'); | ||
}); | ||
Given(function() { | ||
return this.when = requireSubject('lib/when'); | ||
}); | ||
Given(function() { | ||
return this.verify = requireSubject('lib/verify'); | ||
}); | ||
describe('making a test double object based on a Prototypal thing', function() { | ||
@@ -28,6 +19,6 @@ Given(function() { | ||
Given(function() { | ||
return this.testDouble = this.subject(this.someType); | ||
return this.testDouble = td.object(this.someType); | ||
}); | ||
When(function() { | ||
return this.when(this.testDouble.bar()).thenReturn('yay'); | ||
return td.when(this.testDouble.bar()).thenReturn('yay'); | ||
}); | ||
@@ -54,6 +45,6 @@ Then(function() { | ||
Given(function() { | ||
return this.testDouble = this.subject(this.funcBag); | ||
return this.testDouble = td.object(this.funcBag); | ||
}); | ||
When(function() { | ||
return this.when(this.testDouble.kek()).thenReturn('nay!'); | ||
return td.when(this.testDouble.kek()).thenReturn('nay!'); | ||
}); | ||
@@ -75,6 +66,6 @@ Then(function() { | ||
Given(function() { | ||
return this.testDouble = this.subject(['biz', 'bam', 'boo']); | ||
return this.testDouble = td.object(['biz', 'bam', 'boo']); | ||
}); | ||
When(function() { | ||
return this.when(this.testDouble.biz()).thenReturn('zing!'); | ||
return td.when(this.testDouble.biz()).thenReturn('zing!'); | ||
}); | ||
@@ -94,3 +85,3 @@ Then(function() { | ||
Given(function() { | ||
return this.testDouble = this.subject('Thing'); | ||
return this.testDouble = td.object('Thing'); | ||
}); | ||
@@ -101,6 +92,6 @@ Given(function() { | ||
When(function() { | ||
return this.when(this.testDouble.whateverYouWant()).thenReturn('YESS'); | ||
return td.when(this.testDouble.whateverYouWant()).thenReturn('YESS'); | ||
}); | ||
Then(function() { | ||
return this.verify(this.testDouble.magic('sauce')); | ||
return td.verify(this.testDouble.magic('sauce')); | ||
}); | ||
@@ -118,3 +109,3 @@ And(function() { | ||
Given(function() { | ||
return this.testDouble = this.subject('Stuff', { | ||
return this.testDouble = td.object('Stuff', { | ||
excludeMethods: ['then', 'fun'] | ||
@@ -129,3 +120,3 @@ }); | ||
Given(function() { | ||
return this.testDouble = this.subject(); | ||
return this.testDouble = td.object(); | ||
}); | ||
@@ -132,0 +123,0 @@ Then(function() { |
@@ -12,23 +12,17 @@ // Generated by CoffeeScript 1.10.0 | ||
describe('.replace', function() { | ||
Given(function() { | ||
return this.td = requireSubject(); | ||
}); | ||
Given(function() { | ||
return this.replace = requireSubject('lib/replace'); | ||
}); | ||
return describe('creating a fake, returning it, and quibbling it into subject', function() { | ||
Given(function() { | ||
return this.passenger = this.replace('../fixtures/passenger'); | ||
return this.passenger = td.replace('../fixtures/passenger'); | ||
}); | ||
Given(function() { | ||
return this.honk = this.replace('../fixtures/honk'); | ||
return this.honk = td.replace('../fixtures/honk'); | ||
}); | ||
Given(function() { | ||
return this.turn = this.replace('../fixtures/turn'); | ||
return this.turn = td.replace('../fixtures/turn'); | ||
}); | ||
Given(function() { | ||
return this.brake = this.replace('../fixtures/brake', 'ANYTHING I WANT'); | ||
return this.brake = td.replace('../fixtures/brake', 'ANYTHING I WANT'); | ||
}); | ||
Given(function() { | ||
return this.lights = this.replace('../fixtures/lights'); | ||
return this.lights = td.replace('../fixtures/lights'); | ||
}); | ||
@@ -40,3 +34,3 @@ Given(function() { | ||
Given(function() { | ||
return this.td.when(this.passenger.sit()).thenReturn('ow'); | ||
return td.when(this.passenger.sit()).thenReturn('ow'); | ||
}); | ||
@@ -57,3 +51,3 @@ When(function() { | ||
Given(function() { | ||
return this.td.when(this.car.turn()).thenReturn('wee'); | ||
return td.when(this.car.turn()).thenReturn('wee'); | ||
}); | ||
@@ -60,0 +54,0 @@ Then(function() { |
// Generated by CoffeeScript 1.10.0 | ||
(function() { | ||
if (!NODE_JS) { | ||
return; | ||
} | ||
describe("testdouble.js", function() { | ||
Given(function() { | ||
return this.subject = requireSubject(); | ||
}); | ||
return describe("where all the functions are", function() { | ||
Then(function() { | ||
return this.subject.when === requireSubject('lib/when'); | ||
return td.when === require('../../src/when'); | ||
}); | ||
Then(function() { | ||
return this.subject.verify === requireSubject('lib/verify'); | ||
return td.verify === require('../../src/verify'); | ||
}); | ||
Then(function() { | ||
return this.subject["function"] === requireSubject('lib/function'); | ||
return td["function"] === require('../../src/function'); | ||
}); | ||
Then(function() { | ||
return this.subject.object === requireSubject('lib/object'); | ||
return td.object === require('../../src/object'); | ||
}); | ||
Then(function() { | ||
return this.subject.matchers === requireSubject('lib/matchers'); | ||
return td.matchers === require('../../src/matchers'); | ||
}); | ||
Then(function() { | ||
return this.subject.explain === requireSubject('lib/explain'); | ||
return td.callback === require('../../src/matchers/callback'); | ||
}); | ||
Then(function() { | ||
return this.subject.reset === requireSubject('lib/reset'); | ||
return td.explain === require('../../src/explain'); | ||
}); | ||
Then(function() { | ||
return this.subject.replace === requireSubject('lib/replace'); | ||
return td.reset === require('../../src/reset'); | ||
}); | ||
Then(function() { | ||
return td.replace === require('../../src/replace'); | ||
}); | ||
return Then(function() { | ||
return !!this.subject.version.match(/\d+\.\d+\.\d+/); | ||
return td.version === require('../../package').version; | ||
}); | ||
@@ -35,0 +39,0 @@ }); |
@@ -5,13 +5,4 @@ // Generated by CoffeeScript 1.10.0 | ||
Given(function() { | ||
return this.verify = requireSubject('lib/verify'); | ||
return this.testDouble = td["function"](); | ||
}); | ||
Given(function() { | ||
return this["function"] = requireSubject('lib/function'); | ||
}); | ||
Given(function() { | ||
return this.object = requireSubject('lib/object'); | ||
}); | ||
Given(function() { | ||
return this.testDouble = this["function"](); | ||
}); | ||
context('a satisfied verification', function() { | ||
@@ -22,3 +13,3 @@ When(function() { | ||
return Then(function() { | ||
return this.verify(this.testDouble("dogs", "cats")); | ||
return td.verify(this.testDouble("dogs", "cats")); | ||
}); | ||
@@ -30,3 +21,3 @@ }); | ||
return function() { | ||
return _this.verify(_this.testDouble("WOAH")); | ||
return td.verify(_this.testDouble("WOAH")); | ||
}; | ||
@@ -43,3 +34,3 @@ })(this)), "Unsatisfied verification on test double.\n\n Wanted:\n - called with `(\"WOAH\")`.\n\n But there were no invocations of the test double."); | ||
return function() { | ||
return _this.verify(_this.testDouble("WOAH")); | ||
return td.verify(_this.testDouble("WOAH")); | ||
}; | ||
@@ -56,3 +47,3 @@ })(this)), "Unsatisfied verification on test double.\n\n Wanted:\n - called with `(\"WOAH\")`.\n\n But was actually called:\n - called with `(\"the wrong WOAH\")`."); | ||
return function() { | ||
return _this.verify(_this.testDouble("good")); | ||
return td.verify(_this.testDouble("good")); | ||
}; | ||
@@ -64,3 +55,3 @@ })(this)), "Unsatisfied verification on test double.\n\n Wanted:\n - called with `(\"good\")`.\n\n But was actually called:\n - called with `(\"good\", \"bad\")`."); | ||
Given(function() { | ||
return this.testDouble = this["function"]("#footime"); | ||
return this.testDouble = td["function"]("#footime"); | ||
}); | ||
@@ -70,3 +61,3 @@ When(function() { | ||
return function() { | ||
return _this.verify(_this.testDouble()); | ||
return td.verify(_this.testDouble()); | ||
}; | ||
@@ -93,3 +84,3 @@ })(this)); | ||
Given(function() { | ||
return this.testDoubleObj = this.object(this.SomeType); | ||
return this.testDoubleObj = td.object(this.SomeType); | ||
}); | ||
@@ -99,3 +90,3 @@ When(function() { | ||
return function() { | ||
return _this.verify(_this.testDoubleObj.baz()); | ||
return td.verify(_this.testDoubleObj.baz()); | ||
}; | ||
@@ -113,3 +104,3 @@ })(this)); | ||
Given(function() { | ||
return this.testDouble = this["function"](); | ||
return this.testDouble = td["function"](); | ||
}); | ||
@@ -119,3 +110,3 @@ When(function() { | ||
return function() { | ||
return _this.verify(_this.testDouble(_this.someTestDoubleArg)); | ||
return td.verify(_this.testDouble(_this.someTestDoubleArg)); | ||
}; | ||
@@ -126,3 +117,3 @@ })(this)); | ||
Given(function() { | ||
return this.someTestDoubleArg = this["function"](); | ||
return this.someTestDoubleArg = td["function"](); | ||
}); | ||
@@ -135,3 +126,3 @@ return Then(function() { | ||
Given(function() { | ||
return this.someTestDoubleArg = this["function"]("#foo"); | ||
return this.someTestDoubleArg = td["function"]("#foo"); | ||
}); | ||
@@ -147,3 +138,3 @@ return Then(function() { | ||
return function() { | ||
return _this.verify(); | ||
return td.verify(); | ||
}; | ||
@@ -154,5 +145,2 @@ })(this)), "No test double invocation detected for `verify()`.\n\n Usage:\n verify(myTestDouble('foo'))"); | ||
context('using matchers', function() { | ||
Given(function() { | ||
return this.matchers = requireSubject('lib/matchers'); | ||
}); | ||
When(function() { | ||
@@ -165,3 +153,3 @@ return this.testDouble(55); | ||
return function() { | ||
return _this.verify(_this.testDouble(_this.matchers.isA(Number))); | ||
return td.verify(_this.testDouble(td.matchers.isA(Number))); | ||
}; | ||
@@ -175,3 +163,3 @@ })(this)); | ||
return function() { | ||
return _this.verify(_this.testDouble(_this.matchers.isA(String))); | ||
return td.verify(_this.testDouble(td.matchers.isA(String))); | ||
}; | ||
@@ -190,3 +178,3 @@ })(this)); | ||
return function() { | ||
return _this.verify(_this.testDouble('matters'), { | ||
return td.verify(_this.testDouble('matters'), { | ||
ignoreExtraArgs: true | ||
@@ -203,3 +191,3 @@ }); | ||
return function() { | ||
return _this.verify(_this.testDouble(), { | ||
return td.verify(_this.testDouble(), { | ||
times: 0 | ||
@@ -218,3 +206,3 @@ }); | ||
return function() { | ||
return _this.verify(_this.testDouble(), { | ||
return td.verify(_this.testDouble(), { | ||
times: 0 | ||
@@ -233,3 +221,3 @@ }); | ||
return function() { | ||
return _this.verify(_this.testDouble(), { | ||
return td.verify(_this.testDouble(), { | ||
times: 1 | ||
@@ -251,3 +239,3 @@ }); | ||
return function() { | ||
return _this.verify(_this.testDouble(), { | ||
return td.verify(_this.testDouble(), { | ||
times: 1 | ||
@@ -275,3 +263,3 @@ }); | ||
return function() { | ||
return _this.verify(_this.testDouble(), { | ||
return td.verify(_this.testDouble(), { | ||
times: 4 | ||
@@ -296,3 +284,3 @@ }); | ||
return function() { | ||
return _this.verify(_this.testDouble(), { | ||
return td.verify(_this.testDouble(), { | ||
times: 4 | ||
@@ -299,0 +287,0 @@ }); |
@@ -5,14 +5,8 @@ // Generated by CoffeeScript 1.10.0 | ||
Given(function() { | ||
return this.when = requireSubject('lib/when'); | ||
return this.testDouble = td["function"](); | ||
}); | ||
Given(function() { | ||
return this["function"] = requireSubject('lib/function'); | ||
}); | ||
Given(function() { | ||
return this.testDouble = this["function"](); | ||
}); | ||
describe('no-arg stubbing', function() { | ||
context('foo', function() { | ||
Given(function() { | ||
return this.when(this.testDouble()).thenReturn("foo"); | ||
return td.when(this.testDouble()).thenReturn("foo"); | ||
}); | ||
@@ -25,3 +19,3 @@ return Then(function() { | ||
Given(function() { | ||
return this.when(this.testDouble()).thenReturn("bar"); | ||
return td.when(this.testDouble()).thenReturn("bar"); | ||
}); | ||
@@ -35,6 +29,6 @@ return Then(function() { | ||
Given(function() { | ||
return this.when(this.testDouble("something")).thenReturn("gold"); | ||
return td.when(this.testDouble("something")).thenReturn("gold"); | ||
}); | ||
Given(function() { | ||
return this.when(this.testDouble("something")).thenReturn("iron"); | ||
return td.when(this.testDouble("something")).thenReturn("iron"); | ||
}); | ||
@@ -47,9 +41,9 @@ return Then(function() { | ||
Given(function() { | ||
return this.when(this.testDouble(1)).thenReturn("foo"); | ||
return td.when(this.testDouble(1)).thenReturn("foo"); | ||
}); | ||
Given(function() { | ||
return this.when(this.testDouble(2)).thenReturn("bar"); | ||
return td.when(this.testDouble(2)).thenReturn("bar"); | ||
}); | ||
Given(function() { | ||
return this.when(this.testDouble({ | ||
return td.when(this.testDouble({ | ||
lol: 'cheese' | ||
@@ -59,3 +53,3 @@ })).thenReturn('nom'); | ||
Given(function() { | ||
return this.when(this.testDouble({ | ||
return td.when(this.testDouble({ | ||
lol: 'fungus' | ||
@@ -65,3 +59,3 @@ })).thenReturn('eww'); | ||
Given(function() { | ||
return this.when(this.testDouble({ | ||
return td.when(this.testDouble({ | ||
lol: 'fungus' | ||
@@ -97,6 +91,6 @@ }, 2)).thenReturn('eww2'); | ||
Given(function() { | ||
return this.td1 = this.when(this["function"]()()).thenReturn("lol1"); | ||
return this.td1 = td.when(td["function"]()()).thenReturn("lol1"); | ||
}); | ||
Given(function() { | ||
return this.td2 = this.when(this["function"]()()).thenReturn("lol2"); | ||
return this.td2 = td.when(td["function"]()()).thenReturn("lol2"); | ||
}); | ||
@@ -112,7 +106,4 @@ Then(function() { | ||
Given(function() { | ||
return this.matchers = requireSubject('lib/matchers'); | ||
return td.when(this.testDouble(88, td.matchers.isA(Number))).thenReturn("yay"); | ||
}); | ||
Given(function() { | ||
return this.when(this.testDouble(88, this.matchers.isA(Number))).thenReturn("yay"); | ||
}); | ||
Then(function() { | ||
@@ -131,3 +122,3 @@ return this.testDouble(88, 5) === "yay"; | ||
Given(function() { | ||
return this.when(this.testDouble()).thenReturn(10, 9); | ||
return td.when(this.testDouble()).thenReturn(10, 9); | ||
}); | ||
@@ -150,3 +141,3 @@ When(function() { | ||
Given(function() { | ||
return this.when(this.testDouble()).thenReturn('A'); | ||
return td.when(this.testDouble()).thenReturn('A'); | ||
}); | ||
@@ -157,3 +148,3 @@ Given(function() { | ||
Given(function() { | ||
return this.when(this.testDouble()).thenReturn('B', 'C'); | ||
return td.when(this.testDouble()).thenReturn('B', 'C'); | ||
}); | ||
@@ -167,10 +158,7 @@ return Then(function() { | ||
Given(function() { | ||
return this.verify = requireSubject('lib/verify'); | ||
return this.someAction = td["function"](); | ||
}); | ||
Given(function() { | ||
return this.someAction = this["function"](); | ||
return td.when(this.testDouble(55)).thenDo(this.someAction); | ||
}); | ||
Given(function() { | ||
return this.when(this.testDouble(55)).thenDo(this.someAction); | ||
}); | ||
When(function() { | ||
@@ -180,3 +168,3 @@ return this.testDouble(55); | ||
return Then(function() { | ||
return this.verify(this.someAction(55)); | ||
return td.verify(this.someAction(55)); | ||
}); | ||
@@ -189,3 +177,3 @@ }); | ||
Given(function() { | ||
return this.when(this.testDouble(42)).thenThrow(this.error); | ||
return td.when(this.testDouble(42)).thenThrow(this.error); | ||
}); | ||
@@ -209,3 +197,3 @@ When(function() { | ||
Given(function() { | ||
return this.when(this.testDouble(), { | ||
return td.when(this.testDouble(), { | ||
ignoreExtraArgs: true | ||
@@ -223,3 +211,3 @@ }).thenReturn('pewpew'); | ||
Given(function() { | ||
return this.when(this.testDouble('important'), { | ||
return td.when(this.testDouble('important'), { | ||
ignoreExtraArgs: true | ||
@@ -253,3 +241,3 @@ }).thenReturn('neat'); | ||
Given(function() { | ||
return this.when(this.testDouble(), { | ||
return td.when(this.testDouble(), { | ||
times: 2 | ||
@@ -267,6 +255,6 @@ }).thenReturn('pants'); | ||
Given(function() { | ||
return this.when(this.testDouble()).thenReturn('NO'); | ||
return td.when(this.testDouble()).thenReturn('NO'); | ||
}); | ||
Given(function() { | ||
return this.when(this.testDouble(), { | ||
return td.when(this.testDouble(), { | ||
times: 1 | ||
@@ -273,0 +261,0 @@ }).thenReturn('YES'); |
// Generated by CoffeeScript 1.10.0 | ||
(function() { | ||
global.testdouble = require('./../src/testdouble'); | ||
global.td = require('./../src/testdouble'); | ||
@@ -9,4 +9,6 @@ global._ = require('lodash'); | ||
global.NODE_JS = true; | ||
require('./general-helper'); | ||
}).call(this); |
// Generated by CoffeeScript 1.10.0 | ||
(function() { | ||
var _, argsMatch, callsStore, executePlan, hasTimesRemaining, isSatisfied, store, stubbedValueFor, stubbingFor; | ||
var _, argsMatch, callback, callsStore, executePlan, hasTimesRemaining, invokeCallbackFor, isSatisfied, store, stubbedValueFor, stubbingFor; | ||
@@ -11,4 +11,6 @@ _ = require('lodash'); | ||
argsMatch = require('./../args-match'); | ||
argsMatch = require('../args-match'); | ||
callback = require('../matchers/callback'); | ||
module.exports = { | ||
@@ -23,8 +25,8 @@ add: function(testDouble, args, stubbedValues, config) { | ||
}, | ||
invoke: function(testDouble, args) { | ||
invoke: function(testDouble, actualArgs) { | ||
var stubbing; | ||
if (!(stubbing = stubbingFor(testDouble, args))) { | ||
if (!(stubbing = stubbingFor(testDouble, actualArgs))) { | ||
return; | ||
} | ||
return executePlan(stubbing, args); | ||
return executePlan(stubbing, actualArgs); | ||
}, | ||
@@ -42,6 +44,7 @@ "for": function(testDouble) { | ||
executePlan = function(stubbing, args) { | ||
executePlan = function(stubbing, actualArgs) { | ||
var value; | ||
value = stubbedValueFor(stubbing); | ||
stubbing.callCount += 1; | ||
invokeCallbackFor(stubbing, actualArgs); | ||
switch (stubbing.config.plan) { | ||
@@ -51,3 +54,3 @@ case "thenReturn": | ||
case "thenDo": | ||
return value.apply(null, args); | ||
return value.apply(null, actualArgs); | ||
case "thenThrow": | ||
@@ -58,2 +61,16 @@ throw value; | ||
invokeCallbackFor = function(stubbing, actualArgs) { | ||
if (!_.some(stubbing.args, callback.isCallback)) { | ||
return; | ||
} | ||
return _.each(stubbing.args, function(expectedArg, i) { | ||
var callbackArgs; | ||
if (!callback.isCallback(expectedArg)) { | ||
return; | ||
} | ||
callbackArgs = expectedArg.args != null ? expectedArg.args : stubbing.config.plan === 'thenCallback' ? stubbing.stubbedValues : []; | ||
return actualArgs[i].apply(actualArgs, callbackArgs); | ||
}); | ||
}; | ||
stubbedValueFor = function(stubbing) { | ||
@@ -60,0 +77,0 @@ if (stubbing.callCount < stubbing.stubbedValues.length) { |
@@ -9,2 +9,3 @@ // Generated by CoffeeScript 1.10.0 | ||
matchers: require('./matchers/index'), | ||
callback: require('./matchers/callback'), | ||
explain: require('./explain'), | ||
@@ -11,0 +12,0 @@ replace: require('./replace'), |
// Generated by CoffeeScript 1.10.0 | ||
(function() { | ||
var _, addStubbing, calls, stubbings, | ||
var _, addStubbing, callback, calls, concatImpliedCallback, stubbings, | ||
slice = [].slice; | ||
@@ -12,2 +12,4 @@ | ||
callback = require('./matchers/callback'); | ||
module.exports = function(__userDoesPretendInvocationHere__, config) { | ||
@@ -23,2 +25,7 @@ if (config == null) { | ||
}, | ||
thenCallback: function() { | ||
var stubbedValues; | ||
stubbedValues = 1 <= arguments.length ? slice.call(arguments, 0) : []; | ||
return addStubbing(stubbedValues, config, 'thenCallback'); | ||
}, | ||
thenDo: function() { | ||
@@ -43,3 +50,3 @@ var stubbedValues; | ||
if (last = calls.pop()) { | ||
stubbings.add(last.testDouble, last.args, stubbedValues, config); | ||
stubbings.add(last.testDouble, concatImpliedCallback(last.args, config), stubbedValues, config); | ||
return last.testDouble; | ||
@@ -51,2 +58,13 @@ } else { | ||
concatImpliedCallback = function(args, config) { | ||
if (config.plan !== 'thenCallback') { | ||
return args; | ||
} | ||
if (!_(args).some(callback.isCallback)) { | ||
return args.concat(callback); | ||
} else { | ||
return args; | ||
} | ||
}; | ||
}).call(this); |
{ | ||
"name": "testdouble", | ||
"version": "0.8.0", | ||
"version": "0.9.0", | ||
"description": "A minimal test double library for TDD with JavaScript", | ||
@@ -14,7 +14,6 @@ "homepage": "https://github.com/testdouble/testdouble.js", | ||
"build_file": "dist/testdouble.js", | ||
"mocha_reporter": "spec" | ||
"mocha_reporter": "dot" | ||
}, | ||
"scripts": { | ||
"clean": "rm -rf generated dist lib && git checkout -- dist", | ||
"start": "testem", | ||
"compile:node": "coffee --output lib --compile src", | ||
@@ -25,2 +24,3 @@ "compile:test": "coffee --output generated/test --compile test", | ||
"test": "mocha --ui mocha-given --reporter $npm_package_config_mocha_reporter --compilers coffee:coffee-script --recursive test/node-helper.coffee test/lib", | ||
"test:browser": "npm run compile && testem ci", | ||
"test:example": "cd examples/node && npm i && npm test && cd ../..", | ||
@@ -27,0 +27,0 @@ "test:ci": "npm run test --testdouble:mocha_reporter=tap && testem ci && npm run test:example", |
@@ -80,5 +80,5 @@ # testdouble.js | ||
1. [testdouble-chai](https://github.com/basecase/testdouble-chai) | ||
2. [testdouble-jasmine](https://github.com/testdouble/testdouble.js/issues/41) | ||
2. [testdouble-jasmine](https://github.com/BrianGenisio/testdouble-jasmine) | ||
11. [Frequently Asked Questions](docs/B-frequently-asked-questions.md#frequently-asked-questions) | ||
1. [Why doesn't `td.replace()` work with external CommonJS modules?](docs/B-frequently-asked-questions.md#why-doesnt-tdreplace-work-with-external-commonjs-modules) | ||
var pkg = require('./package.json'); | ||
browserLauncher = process.env['TESTEM_BROWSER'] || 'phantomjs'; | ||
module.exports = { | ||
launch_in_dev: [ 'node', browserLauncher], | ||
launch_in_ci: [/* run node tests outside testem */, browserLauncher], | ||
launch_in_dev: [], | ||
launch_in_ci: ['phantomjs'], | ||
launchers: { | ||
node: { | ||
command: 'npm test --testdouble:mocha_reporter=tap', | ||
protocol: 'tap' | ||
} | ||
}, | ||
framework: 'mocha+chai', | ||
before_tests: "npm run compile", | ||
//might want to add this if you do a lot of file-delete/add churn; faster w/o. | ||
//after_tests: "npm run clean", | ||
serve_files: [ | ||
@@ -35,8 +23,3 @@ // subject | ||
"generated/test/lib/**/*.js" | ||
], | ||
watch_files: [ | ||
"src/**/*", | ||
"test/**/*" | ||
] | ||
}; |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
690267
136
6
15631