testdouble
Advanced tools
Comparing version 2.0.0-pre.3 to 2.0.0-pre.4
# Change Log | ||
## [v2.0.0-pre.4](https://github.com/testdouble/testdouble.js/tree/v2.0.0-pre.4) (2017-03-12) | ||
[Full Changelog](https://github.com/testdouble/testdouble.js/compare/v2.0.0-pre.3...v2.0.0-pre.4) | ||
**Closed issues:** | ||
- How can I write a test for such situation? [\#199](https://github.com/testdouble/testdouble.js/issues/199) | ||
- stub also verified warning when using ignoreExtraArgs [\#181](https://github.com/testdouble/testdouble.js/issues/181) | ||
**Merged pull requests:** | ||
- Create test double functions and copy/fake their properties [\#204](https://github.com/testdouble/testdouble.js/pull/204) ([searls](https://github.com/searls)) | ||
- Support deep matchers [\#203](https://github.com/testdouble/testdouble.js/pull/203) ([searls](https://github.com/searls)) | ||
- introduce td.constructor\(\) as top-level API sibling to td.object\(\) & td.function\(\) [\#201](https://github.com/testdouble/testdouble.js/pull/201) ([searls](https://github.com/searls)) | ||
- Allow Babel compilation [\#197](https://github.com/testdouble/testdouble.js/pull/197) ([searls](https://github.com/searls)) | ||
- Improves warning when verifying a stub [\#196](https://github.com/testdouble/testdouble.js/pull/196) ([samjonester](https://github.com/samjonester)) | ||
## [v2.0.0-pre.3](https://github.com/testdouble/testdouble.js/tree/v2.0.0-pre.3) (2017-03-06) | ||
@@ -123,2 +139,6 @@ [Full Changelog](https://github.com/testdouble/testdouble.js/compare/v2.0.0-pre.2...v2.0.0-pre.3) | ||
**Implemented enhancements:** | ||
- td.replace for functions that have additional function properties [\#99](https://github.com/testdouble/testdouble.js/issues/99) | ||
**Closed issues:** | ||
@@ -125,0 +145,0 @@ |
# Creating Test Doubles | ||
Unlike most classical or functional languages, JavaScript under test might depend on many sorts of things: plain objects, instantiable constructor functions, ES2015 classes, or regular old functions. As a result, any good test double library needs to provide terse and convenient ways to create fake versions of all of these things. | ||
Unlike most classical or functional languages, JavaScript under test might | ||
depend on many sorts of things: plain objects, instantiable constructor | ||
functions, ES2015 classes, or regular old functions. As a result, any good test | ||
double library needs to provide terse and convenient ways to create fake | ||
versions of all of these things. | ||
The examples below will walk through the different ways to create new test doubles. Each example assumes you've aliased `testdouble` to `td`. | ||
The examples below will walk through the different ways to create new test | ||
doubles. Each example assumes you've aliased `testdouble` to `td`. | ||
This document discusses all the ways to manual create test doubles, but keep in | ||
mind that in practice many developers will lean on `td.replace`, which performs | ||
this duty on your behalf. Read more about `td.replace` on [its doc | ||
This document discusses all the ways to manually create test doubles, but keep | ||
in mind that in practice many developers will lean on `td.replace`, which | ||
performs this duty on your behalf. Read more about `td.replace` on [its doc | ||
page](7-replacing-dependencies.md). | ||
## td.function([name]) | ||
## td.function | ||
@@ -19,3 +24,3 @@ **Note that `td.func` is available as an alias of `td.function`.** | ||
``` javascript | ||
var bark = td.function() | ||
var bark = td.function() // '[test double (unnamed)]' | ||
``` | ||
@@ -28,40 +33,69 @@ | ||
``` javascript | ||
var woof = td.function('.woof') | ||
var woof = td.function('.woof') // test double for ".woof" | ||
``` | ||
## td.object() | ||
### Creating a test double function from a real function | ||
Creating a one-off function is really easy, but often our subjects will depend on objects with functions as properties. Because we don't want to encourage the use of [partial mocks](https://github.com/testdouble/contributing-tests/wiki/Partial-Mock), test double offers a number of ways to create objects whose function properties have all been replaced with fake functions. | ||
If you're replacing an actual function with a test double, you can also pass it | ||
to `td.function` and all of its properties will be copied over. If any of its | ||
properties are functions, those functions will be replaced with test double | ||
functions as well. | ||
Because there's a number of ways to create objects of test doubles, it's important that we provide some guidance on which tool to use when. Because we use test doubles to practice outside-in test-driven development, most of the fake objects we use represent code *that doesn't exist yet*. As a result, there are two styles you might take: | ||
```js | ||
function meow () { throw 'unimplemented' } | ||
meow.volume = 'loud' | ||
meow.stop = function () {} | ||
* Pass `td.object()` a real **constructor** with functions defined on its prototype object, an **ES2015 class**, or a **plain JavaScript object** which contains functions as properties. testdouble.js will mirror either of these by replacing all the functions it detects, including those inherited from its prototype chain. If you practice this style, it means part of your test-driven workflow will require you to define those constructors and objects as you go in your production code. This is a great way to take advantage of the TDD workflow to implement a skeleton of your object graph as you work, all-the-while keeping the contracts between your subject and its dependencies explicit enough to catch failures when you change the contract between the [subject](https://github.com/testdouble/contributing-tests/wiki/Subject) and its dependencies (i.e. if you change the name of a dependency's function, the test double function would disappear and break the caller's test). | ||
* Pass `td.object()` an **array of function names** or (if using a runtime that implements [ES2015 Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy)) a **name for the object**. This style makes prototyping interactions easier because it doesn't require the author to define production-scope functions of dependencies while authoring the caller's test. Conversely, it runs the risk of "fantasy green" tests that continue passing even if a dependency's functions change in the future | ||
var fakeMeow = td.function(meow) // test double for "meow" | ||
fakeMeow.volume // 'loud' | ||
fakeMeow.stop // test double for "meow.stop" | ||
``` | ||
No style is right or wrong, as they both have trade-offs (full disclosure: when practicing TDD in a greenfield application, the present author usually prefers the former style). However, we would encourage teams to pick one style and apply it consistently to reduce the cognitive load of keeping straight the expected behavior of tests when depended-on objects change. | ||
This can be handy when you're replacing a dependency that is a function but also | ||
has significant properties defined (imagine a module that exports a function as | ||
well as a synchronous version exposed via a `sync` property). | ||
### Creating objects that mirror production dependencies | ||
## td.object | ||
#### object(someConstructorFunction) | ||
Creating a one-off function is really easy, but often our subjects will depend | ||
on objects with functions as properties. Because we don't want to encourage the | ||
use of [partial | ||
mocks](https://github.com/testdouble/contributing-tests/wiki/Partial-Mock), | ||
test double offers a number of ways to create objects whose function properties | ||
have all been replaced with fake functions. | ||
Suppose you have a constructor function: | ||
Because there's a number of ways to create objects of test doubles, it's | ||
important that we provide some guidance on which tool to use when. Because we | ||
use test doubles to practice outside-in test-driven development, most of the | ||
fake objects we use represent code *that doesn't exist yet*. As a result, there | ||
are two styles you might take: | ||
``` javascript | ||
function Dog(){} | ||
Dog.prototype.bark = function(){} | ||
Dog.woof = function(){} | ||
``` | ||
* Pass `td.object()` a **plain JavaScript object** which contains functions as | ||
properties. testdouble.js will mirror either of these by replacing all the | ||
functions it detects. If you practice this style, it means part of your | ||
test-driven workflow will require you to define those types in your production | ||
code as you write your tests. This is a great way to take advantage of the TDD | ||
workflow to implement a skeleton of your object graph as you work, | ||
all-the-while keeping the contracts between your subject and its dependencies | ||
explicit enough to catch failures when you change the contract between the | ||
[subject](https://github.com/testdouble/contributing-tests/wiki/Subject) and | ||
its dependencies (i.e. if you change the name of a dependency's function, the | ||
test double function would disappear and break the caller's test). | ||
* Pass `td.object()` an **array of function names** or (if using a runtime that | ||
implements [ES2015 | ||
Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy)) | ||
a **name for the object**. This style makes prototyping interactions easier | ||
because it doesn't require the author to define production-scope functions of | ||
dependencies while authoring the caller's test. Conversely, it runs the risk | ||
of "fantasy green" tests that continue passing even if a dependency's | ||
functions change in the future | ||
To create a test double of the constructor that has prototypal function `bark` | ||
and "static" function `woof`, simply pass `Dog` to `td.object()` | ||
No style is right or wrong, as they both have trade-offs (full disclosure: when | ||
practicing TDD in a greenfield application, the present author usually prefers | ||
the former style). However, we would encourage teams to pick one style and apply | ||
it consistently to reduce the cognitive load of keeping straight the expected | ||
behavior of tests when depended-on objects change. | ||
``` javascript | ||
var FakeDog = td.object(Dog) | ||
### object(someObjectWithFunctions) | ||
FakeDog.prototype.bark // a test double function named 'Dog#bark' | ||
FakeDog.woof // a test double function named 'Dog.woof' | ||
``` | ||
#### object(someObjectWithFunctions) | ||
Suppose you have an object with some functions as properties (and perhaps some non-function properties). If passed to `td.object()`, testdouble.js will do a deep copy of the object and then a shallow search-and-replace of any functions found on the object while and return it. | ||
@@ -91,6 +125,4 @@ | ||
### Creating objects that don't depend on production dependencies | ||
### object(functionNames) | ||
#### object(functionNames) | ||
If you pass `td.object` an array of strings, it'll return a plain object with those properties set as named test double functions. | ||
@@ -114,3 +146,3 @@ | ||
#### Excluding certain methods from Proxy-based test doubles | ||
### Excluding certain methods from Proxy-based test doubles | ||
@@ -143,4 +175,56 @@ Sometimes, your subject code will check to see if a property is defined, which | ||
## td.constructor() | ||
Test Double can also create artificial constructor functions. This method can be | ||
passed either a constructor (or ES `class`) or an array of function names and | ||
will return a constructor whose functions are all replaced by test doubles. | ||
### constructor(someConstructorFunction) | ||
Suppose you have a constructor function: | ||
``` javascript | ||
function Dog(){} | ||
Dog.prototype.bark = function(){} | ||
Dog.woof = function(){} | ||
``` | ||
To create a test double of the constructor that has prototypal function `bark` | ||
and "static" function `woof`, simply pass `Dog` to `td.constructor()` | ||
``` javascript | ||
var FakeDog = td.object(Dog) | ||
FakeDog.prototype.bark // a test double function named 'Dog#bark' | ||
FakeDog.woof // a test double function named 'Dog.woof' | ||
``` | ||
When `FakeDog` is instantiated, any stubbings (or verifications) set up by the | ||
test on the `FakeDog.prototype` will also translate to the instances, for | ||
instance: | ||
```javascript | ||
td.when(FakeDog.prototype.bark()).thenReturn('YIP') | ||
var dog = new FakeDog() | ||
dog.bark() // 'YIP | ||
``` | ||
### constructor(arrayOfFunctionNames) | ||
If you want a fake constructable thing to have a certain set of instance methods | ||
defined on it, testdouble.js can also create one from an array of function | ||
names. | ||
```javascript | ||
var FakeCat = td.constructor(['meow', 'scratch']) | ||
FakeCat.prototype.meow // a test double function named '#meow' | ||
FakeCat.prototype.scratch // a test double function named '#scratch' | ||
``` | ||
## Conclusion | ||
As you can see, there are a plethora of ways to create test doubles with testdouble.js, each designed to handle a different style of organizing JavaScript code. We recommend on landing on one consistent style (e.g. each module as one function) for each project, which in turn would encourage one consistent style of creating test doubles. This API is written to be flexible for a number of potential contexts across objects, but it has come at the cost of a large enough surface area that if any project were to make ample use of all or most of the above invocation styles, it would confuse readers. |
@@ -23,6 +23,7 @@ # Debugging with testdouble.js | ||
``` javascript | ||
var myTestDouble = td.function() | ||
var myTestDouble = td.function('.someFunction') | ||
td.explain(myTestDouble) /* | ||
{ | ||
name: '.someFunction', | ||
callCount: 0, | ||
@@ -44,5 +45,6 @@ calls: [], | ||
{ | ||
name: 'someFunction', | ||
callCount: 0, | ||
calls: [], | ||
description: 'This test double has 1 stubbings and 0 invocations. | ||
description: 'This test double `.someFunction` has 1 stubbings and 0 invocations. | ||
@@ -65,2 +67,3 @@ Stubbings: | ||
{ | ||
name: '.someFunction', | ||
callCount: 1, | ||
@@ -67,0 +70,0 @@ calls: [ { args: [7], context: window } ], |
@@ -22,3 +22,3 @@ function SavesProblem() { | ||
createRandomProblem = td.function('createRandomProblem') | ||
FakeSavesProblem = td.object(SavesProblem) | ||
FakeSavesProblem = td.constructor(SavesProblem) | ||
submitProblem = td.function('submitProblem') | ||
@@ -25,0 +25,0 @@ subject = new MathProblem(createRandomProblem, new FakeSavesProblem(), submitProblem) |
@@ -23,3 +23,3 @@ function SavesProblem() { | ||
createRandomProblem = td.function('createRandomProblem') | ||
FakeSavesProblem = td.object(SavesProblem) | ||
FakeSavesProblem = td.constructor(SavesProblem) | ||
submitProblem = td.function('submitProblem') | ||
@@ -26,0 +26,0 @@ subject = new MathProblem(createRandomProblem, new FakeSavesProblem(), submitProblem) |
@@ -14,5 +14,6 @@ // Generated by CoffeeScript 1.12.4 | ||
brake: require('./brake'), | ||
lights: require('./lights') | ||
lights: require('./lights'), | ||
shift: require('./shift') | ||
}; | ||
}).call(this); |
@@ -1,47 +0,30 @@ | ||
// Generated by CoffeeScript 1.12.4 | ||
(function() { | ||
describe('td.config', function() { | ||
context('defaults', function() { | ||
Given(function() { | ||
return this.config = td.config(); | ||
}); | ||
return Then(function() { | ||
return expect(this.config).to.deep.equal({ | ||
promiseConstructor: global.Promise, | ||
ignoreWarnings: false, | ||
suppressErrors: false | ||
}); | ||
}); | ||
'use strict'; | ||
describe('td.config', function () { | ||
it('sets some ok defaults', function () { | ||
expect(td.config()).to.deep.equal({ | ||
promiseConstructor: global.Promise, | ||
ignoreWarnings: false, | ||
suppressErrors: false | ||
}); | ||
context('overriding', function() { | ||
Given(function() { | ||
return this.config = td.config({ | ||
ignoreWarnings: true | ||
}); | ||
}); | ||
Then(function() { | ||
return this.config.ignoreWarnings === true; | ||
}); | ||
return And(function() { | ||
return td.config().ignoreWarnings === true; | ||
}); | ||
}); | ||
return context('overriding a non-existent property', function() { | ||
Given(function() { | ||
var e; | ||
try { | ||
return this.config = td.config({ | ||
wat: 'wat?' | ||
}); | ||
} catch (error) { | ||
e = error; | ||
return this.error = e; | ||
} | ||
}); | ||
return Then(function() { | ||
return this.error.message === 'Error: testdouble.js - td.config - "wat" is not a valid configuration key (valid keys are: ["promiseConstructor", "ignoreWarnings", "suppressErrors"])'; | ||
}); | ||
}); | ||
}); | ||
}).call(this); | ||
it('overriding a real property', function () { | ||
var config = td.config({ ignoreWarnings: true }); | ||
expect(config.ignoreWarnings).to.eq(true); | ||
expect(td.config().ignoreWarnings).to.eq(true); | ||
}); | ||
it('overriding a non-existent property', function () { | ||
var error = void 0; | ||
try { | ||
td.config({ wat: 'wat?' }); | ||
} catch (e) { | ||
error = e; | ||
} | ||
expect(error.message).to.eq('Error: testdouble.js - td.config - "wat" is not a valid configuration ' + 'key (valid keys are: ["promiseConstructor", "ignoreWarnings", ' + '"suppressErrors"])'); | ||
}); | ||
}); |
@@ -13,2 +13,3 @@ // Generated by CoffeeScript 1.12.4 | ||
return expect(this.result).to.deep.eq({ | ||
name: void 0, | ||
calls: [], | ||
@@ -25,5 +26,8 @@ callCount: 0, | ||
}); | ||
return Then(function() { | ||
Then(function() { | ||
return expect(this.result.description).to.deep.eq("This test double `foobaby` has 0 stubbings and 0 invocations."); | ||
}); | ||
return And(function() { | ||
return this.result.name === "foobaby"; | ||
}); | ||
}); | ||
@@ -45,2 +49,3 @@ context('a double with some interactions', function() { | ||
return expect(this.result).to.deep.eq({ | ||
name: void 0, | ||
calls: [ | ||
@@ -67,2 +72,3 @@ { | ||
return expect(this.result).to.deep.eq({ | ||
name: void 0, | ||
calls: [], | ||
@@ -81,2 +87,3 @@ callCount: 0, | ||
return expect(this.result).to.deep.eq({ | ||
name: void 0, | ||
calls: [], | ||
@@ -95,2 +102,3 @@ callCount: 0, | ||
return expect(this.result).to.deep.eq({ | ||
name: void 0, | ||
calls: [], | ||
@@ -109,2 +117,3 @@ callCount: 0, | ||
return expect(this.result).to.deep.eq({ | ||
name: void 0, | ||
calls: [], | ||
@@ -111,0 +120,0 @@ callCount: 0, |
// Generated by CoffeeScript 1.12.4 | ||
(function() { | ||
var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, | ||
hasProp = {}.hasOwnProperty; | ||
describe('td.object', function() { | ||
describe('making a test double object based on a Prototypal thing', function() { | ||
var SuperThing, Thing; | ||
Thing = SuperThing = null; | ||
Given(function() { | ||
return SuperThing = (function() { | ||
function SuperThing() {} | ||
SuperThing.prototype.biz = function() { | ||
return 1; | ||
}; | ||
return SuperThing; | ||
})(); | ||
}); | ||
Given(function() { | ||
return Thing = (function(superClass) { | ||
extend(Thing, superClass); | ||
function Thing() { | ||
return Thing.__super__.constructor.apply(this, arguments); | ||
} | ||
return Thing; | ||
})(SuperThing); | ||
}); | ||
Given(function() { | ||
return Thing.prototype.foo = function() { | ||
return 2; | ||
}; | ||
}); | ||
Given(function() { | ||
return Thing.bar = function() { | ||
return 3; | ||
}; | ||
}); | ||
Given(function() { | ||
return Thing.prototype.instanceAttr = 'baz'; | ||
}); | ||
Given(function() { | ||
return Thing.staticAttr = 'qux'; | ||
}); | ||
Given(function() { | ||
return this.fakeType = td.object(Thing); | ||
}); | ||
Given(function() { | ||
return this.fakeInstance = new this.fakeType('pants'); | ||
}); | ||
describe('the constructor function itself', function() { | ||
Then(function() { | ||
return td.verify(this.fakeType('pants')); | ||
}); | ||
return describe('stubbing it (with an error, return makes no sense)', function() { | ||
Given(function() { | ||
return td.when(new this.fakeType('!')).thenThrow('¡'); | ||
}); | ||
Given(function() { | ||
return this.error = null; | ||
}); | ||
When(function() { | ||
var e; | ||
try { | ||
return new this.fakeType('!'); | ||
} catch (error1) { | ||
e = error1; | ||
return this.error = e; | ||
} | ||
}); | ||
return Then(function() { | ||
return this.error === '¡'; | ||
}); | ||
}); | ||
}); | ||
Then(function() { | ||
return td.when(this.fakeInstance.foo()).thenReturn(7)() === 7; | ||
}); | ||
describe('stub method on prototype, use from any instance', function() { | ||
When(function() { | ||
return td.when(this.fakeType.prototype.foo()).thenReturn(4); | ||
}); | ||
Then(function() { | ||
return this.fakeType.prototype.foo() === 4; | ||
}); | ||
return Then(function() { | ||
return this.fakeInstance.foo() === 4; | ||
}); | ||
}); | ||
Then(function() { | ||
return td.when(this.fakeType.bar()).thenReturn(5)() === 5; | ||
}); | ||
Then(function() { | ||
return td.when(this.fakeInstance.biz()).thenReturn(6)() === 6; | ||
}); | ||
Then(function() { | ||
return this.fakeType.toString() === '[test double constructor for "Thing"]'; | ||
}); | ||
Then(function() { | ||
return this.fakeType.prototype.foo.toString() === '[test double for "Thing#foo"]'; | ||
}); | ||
Then(function() { | ||
return this.fakeType.bar.toString() === '[test double for "Thing.bar"]'; | ||
}); | ||
Then(function() { | ||
return this.fakeInstance instanceof Thing; | ||
}); | ||
Then(function() { | ||
return this.fakeType.prototype.instanceAttr === 'baz'; | ||
}); | ||
Then(function() { | ||
return this.fakeInstance.instanceAttr === 'baz'; | ||
}); | ||
return Then(function() { | ||
return this.fakeType.staticAttr === 'qux'; | ||
}); | ||
}); | ||
describe('making a test double based on a plain object funcbag', function() { | ||
@@ -168,2 +49,27 @@ Given(function() { | ||
}); | ||
describe('passing a constructor function to td.object erroneously (1.x)', function() { | ||
Given(function() { | ||
var LolTypes; | ||
return this.someConstructor = LolTypes = (function() { | ||
function LolTypes() {} | ||
LolTypes.prototype.foo = function() {}; | ||
return LolTypes; | ||
})(); | ||
}); | ||
When(function() { | ||
var e; | ||
try { | ||
return td.object(this.someConstructor); | ||
} catch (error1) { | ||
e = error1; | ||
return this.result = e; | ||
} | ||
}); | ||
return Then(function() { | ||
return expect(this.result.message).to.contain("Please use the `td.constructor()` method instead"); | ||
}); | ||
}); | ||
if (global.Proxy != null) { | ||
@@ -170,0 +76,0 @@ return describe('creating a proxy object (ES2015; only supported in FF + Edge atm)', function() { |
@@ -355,2 +355,5 @@ // Generated by CoffeeScript 1.12.4 | ||
Given(function() { | ||
return this.shift = td.replace('../../fixtures/shift'); | ||
}); | ||
Given(function() { | ||
return this.brake = td.replace('../../fixtures/brake', 'ANYTHING I WANT'); | ||
@@ -391,2 +394,18 @@ }); | ||
}); | ||
describe('faking main function when property is also exported', function() { | ||
Given(function() { | ||
return td.when(this.car.shift()).thenReturn('Vroom'); | ||
}); | ||
return Then(function() { | ||
return this.car.shift() === 'Vroom'; | ||
}); | ||
}); | ||
describe('faking property on exported function', function() { | ||
Given(function() { | ||
return td.when(this.car.shift.neutral()).thenReturn('Clunk'); | ||
}); | ||
return Then(function() { | ||
return this.car.shift.neutral() === 'Clunk'; | ||
}); | ||
}); | ||
describe('manually stubbing an entry', function() { | ||
@@ -393,0 +412,0 @@ return Then(function() { |
@@ -34,2 +34,12 @@ // Generated by CoffeeScript 1.12.4 | ||
}); | ||
context('matchers', function() { | ||
Then(function() { | ||
return this.subject(td.matchers.isA(Number)) === 'isA(Number)'; | ||
}); | ||
return Then(function() { | ||
return expect(this.subject({ | ||
val: td.matchers.isA(Number) | ||
})).to.eq('{val: isA(Number)}'); | ||
}); | ||
}); | ||
context('long strings of objects should be multi-lined', function() { | ||
@@ -36,0 +46,0 @@ Given(function() { |
@@ -25,2 +25,5 @@ // Generated by CoffeeScript 1.12.4 | ||
Then(function() { | ||
return td.constructor === requireSource('constructor'); | ||
}); | ||
Then(function() { | ||
return td.matchers === requireSource('matchers'); | ||
@@ -27,0 +30,0 @@ }); |
@@ -100,3 +100,3 @@ // Generated by CoffeeScript 1.12.4 | ||
Given(function() { | ||
return this.testDoubleObj = td.object(this.SomeType); | ||
return this.testDoubleObj = td.constructor(this.SomeType); | ||
}); | ||
@@ -177,2 +177,91 @@ When(function() { | ||
}); | ||
context('using deep matchers', function() { | ||
context('single level', function() { | ||
When(function() { | ||
return this.testDouble({ | ||
value: 55 | ||
}); | ||
}); | ||
context('satisfied', function() { | ||
return Then(function() { | ||
return shouldNotThrow((function(_this) { | ||
return function() { | ||
return td.verify(_this.testDouble({ | ||
value: td.matchers.isA(Number) | ||
})); | ||
}; | ||
})(this)); | ||
}); | ||
}); | ||
return context('unsatisfied', function() { | ||
return Then(function() { | ||
return shouldThrow(((function(_this) { | ||
return function() { | ||
return td.verify(_this.testDouble({ | ||
value: td.matchers.isA(String) | ||
})); | ||
}; | ||
})(this)), "Unsatisfied verification on test double.\n\n Wanted:\n - called with `({value: isA(String)})`.\n\n All calls of the test double, in order were:\n - called with `({value: 55})`."); | ||
}); | ||
}); | ||
}); | ||
context('deeply nested', function() { | ||
When(function() { | ||
return this.testDouble({ | ||
value: { | ||
value: 55 | ||
} | ||
}); | ||
}); | ||
context('satisfied', function() { | ||
return Then(function() { | ||
return shouldNotThrow((function(_this) { | ||
return function() { | ||
return td.verify(_this.testDouble({ | ||
value: { | ||
value: td.matchers.isA(Number) | ||
} | ||
})); | ||
}; | ||
})(this)); | ||
}); | ||
}); | ||
return context('unsatisfied', function() { | ||
return Then(function() { | ||
return shouldThrow(((function(_this) { | ||
return function() { | ||
return td.verify(_this.testDouble({ | ||
value: { | ||
value: td.matchers.isA(String) | ||
} | ||
})); | ||
}; | ||
})(this)), "Unsatisfied verification on test double.\n\n Wanted:\n - called with `({value: {value: isA(String)}})`.\n\n All calls of the test double, in order were:\n - called with `({value: {value: 55}})`."); | ||
}); | ||
}); | ||
}); | ||
return context('array values', function() { | ||
When(function() { | ||
return this.testDouble([55]); | ||
}); | ||
context('satisfied', function() { | ||
return Then(function() { | ||
return shouldNotThrow((function(_this) { | ||
return function() { | ||
return td.verify(_this.testDouble([td.matchers.isA(Number)])); | ||
}; | ||
})(this)); | ||
}); | ||
}); | ||
return context('unsatisfied', function() { | ||
return Then(function() { | ||
return shouldThrow(((function(_this) { | ||
return function() { | ||
return td.verify(_this.testDouble([td.matchers.isA(String)])); | ||
}; | ||
})(this)), "Unsatisfied verification on test double.\n\n Wanted:\n - called with `([isA(String)])`.\n\n All calls of the test double, in order were:\n - called with `([55])`."); | ||
}); | ||
}); | ||
}); | ||
}); | ||
describe('configuration', function() { | ||
@@ -337,29 +426,63 @@ describe('ignoring extra arguments (more thoroughly tested via when())', function() { | ||
}); | ||
context('an exact match in calls', function() { | ||
Given(function() { | ||
return td.when(this.td(1)).thenReturn(5); | ||
context('warn user for', function() { | ||
context('an exact match in calls', function() { | ||
Given(function() { | ||
return td.when(this.td(1)).thenReturn(5); | ||
}); | ||
Given(function() { | ||
return this.td(1); | ||
}); | ||
When(function() { | ||
return td.verify(this.td(1)); | ||
}); | ||
return Then(function() { | ||
return this.warnings[0] === "Warning: testdouble.js - td.verify - test double `.foo` was both stubbed and verified with arguments (1), which is redundant and probably unnecessary. (see: https://github.com/testdouble/testdouble.js/blob/master/docs/B-frequently-asked-questions.md#why-shouldnt-i-call-both-tdwhen-and-tdverify-for-a-single-interaction-with-a-test-double )"; | ||
}); | ||
}); | ||
Given(function() { | ||
return this.td(1); | ||
context('a match where stub ignores extra arguments', function() { | ||
Given(function() { | ||
return td.when(this.td(1), { | ||
ignoreExtraArgs: true | ||
}).thenReturn(); | ||
}); | ||
Given(function() { | ||
return this.td(1, 2, 3); | ||
}); | ||
When(function() { | ||
return td.verify(this.td(1, 2, 3)); | ||
}); | ||
return Then(function() { | ||
return this.warnings[0] === "Warning: testdouble.js - td.verify - test double `.foo` was both stubbed and verified with arguments (1, 2, 3), which is redundant and probably unnecessary. (see: https://github.com/testdouble/testdouble.js/blob/master/docs/B-frequently-asked-questions.md#why-shouldnt-i-call-both-tdwhen-and-tdverify-for-a-single-interaction-with-a-test-double )"; | ||
}); | ||
}); | ||
When(function() { | ||
return td.verify(this.td(1)); | ||
return context('a match where stub uses a matcher', function() { | ||
Given(function() { | ||
return td.when(this.td(td.matchers.isA(Number))).thenReturn(5); | ||
}); | ||
Given(function() { | ||
return this.td(1); | ||
}); | ||
When(function() { | ||
return td.verify(this.td(1)); | ||
}); | ||
return Then(function() { | ||
return this.warnings[0] === "Warning: testdouble.js - td.verify - test double `.foo` was both stubbed and verified with arguments (1), which is redundant and probably unnecessary. (see: https://github.com/testdouble/testdouble.js/blob/master/docs/B-frequently-asked-questions.md#why-shouldnt-i-call-both-tdwhen-and-tdverify-for-a-single-interaction-with-a-test-double )"; | ||
}); | ||
}); | ||
return Then(function() { | ||
return this.warnings[0] === "Warning: testdouble.js - td.verify - test double `.foo` was both stubbed and verified with arguments (1), which is redundant and probably unnecessary. (see: https://github.com/testdouble/testdouble.js/blob/master/docs/B-frequently-asked-questions.md#why-shouldnt-i-call-both-tdwhen-and-tdverify-for-a-single-interaction-with-a-test-double )"; | ||
}); | ||
}); | ||
return context('matchers are used', function() { | ||
Given(function() { | ||
return td.when(this.td(td.matchers.isA(Number))).thenReturn(5); | ||
return context("don't warn user when", function() { | ||
return context("verify doesn't match the stub", function() { | ||
Given(function() { | ||
return td.when(this.td(1)).thenReturn(); | ||
}); | ||
Given(function() { | ||
return this.td(); | ||
}); | ||
When(function() { | ||
return td.verify(this.td()); | ||
}); | ||
return Then(function() { | ||
return this.warnings.length === 0; | ||
}); | ||
}); | ||
Given(function() { | ||
return this.td(1); | ||
}); | ||
When(function() { | ||
return td.verify(this.td(1)); | ||
}); | ||
return Then(function() { | ||
return this.warnings.length === 0; | ||
}); | ||
}); | ||
@@ -366,0 +489,0 @@ }); |
@@ -111,2 +111,91 @@ // Generated by CoffeeScript 1.12.4 | ||
}); | ||
describe('using deep matchers', function() { | ||
context('single level', function() { | ||
Given(function() { | ||
return td.when(this.testDouble({ | ||
key: td.matchers.isA(String) | ||
})).thenReturn("yay"); | ||
}); | ||
Then(function() { | ||
return this.testDouble({ | ||
key: "testytest" | ||
}) === "yay"; | ||
}); | ||
Then(function() { | ||
return this.testDouble({ | ||
key: 42 | ||
}) === void 0; | ||
}); | ||
Then(function() { | ||
return this.testDouble({}) === void 0; | ||
}); | ||
return Then(function() { | ||
return this.testDouble("i am a string") === void 0; | ||
}); | ||
}); | ||
context('deeply nested', function() { | ||
Given(function() { | ||
return td.when(this.testDouble({ | ||
a: { | ||
b: td.matchers.isA(String) | ||
} | ||
})).thenReturn("yay"); | ||
}); | ||
Then(function() { | ||
return this.testDouble({ | ||
a: { | ||
b: "testytest" | ||
} | ||
}) === "yay"; | ||
}); | ||
Then(function() { | ||
return this.testDouble({ | ||
a: { | ||
b: 42 | ||
} | ||
}) === void 0; | ||
}); | ||
return Then(function() { | ||
return this.testDouble({ | ||
a: "testytest" | ||
}) === void 0; | ||
}); | ||
}); | ||
context('array values', function() { | ||
Given(function() { | ||
return td.when(this.testDouble([5, td.matchers.isA(String)])).thenReturn("yay"); | ||
}); | ||
Then(function() { | ||
return this.testDouble([5, "testytest"]) === "yay"; | ||
}); | ||
Then(function() { | ||
return this.testDouble([5, 6]) === void 0; | ||
}); | ||
Then(function() { | ||
return this.testDouble([5]) === void 0; | ||
}); | ||
return Then(function() { | ||
return this.testDouble([]) === void 0; | ||
}); | ||
}); | ||
return context('arguments with circular structures', function() { | ||
Given(function() { | ||
return this.arg = { | ||
foo: 'bar' | ||
}; | ||
}); | ||
Given(function() { | ||
return this.arg.baz = this.arg; | ||
}); | ||
Given(function() { | ||
return td.when(this.testDouble(this.arg)).thenReturn("yay"); | ||
}); | ||
Then(function() { | ||
return this.testDouble(this.arg) === "yay"; | ||
}); | ||
return Then(function() { | ||
return this.testDouble('no') === void 0; | ||
}); | ||
}); | ||
}); | ||
describe('stubbing sequential returns', function() { | ||
@@ -113,0 +202,0 @@ context('a single stubbing', function() { |
@@ -23,4 +23,4 @@ // Generated by CoffeeScript 1.12.4 | ||
equalsWithMatchers = function(expectedArgs, actualArgs) { | ||
return _.every(expectedArgs, function(expectedArg, i) { | ||
return argumentMatchesExpectation(expectedArg, actualArgs[i]); | ||
return _.every(expectedArgs, function(expectedArg, key) { | ||
return argumentMatchesExpectation(expectedArg, actualArgs[key]); | ||
}); | ||
@@ -34,3 +34,6 @@ }; | ||
} else { | ||
return _.isEqual(expectedArg, actualArg); | ||
return _.isEqualWith(expectedArg, actualArg, function(expectedEl, actualEl) { | ||
var base; | ||
return typeof (base = matcherFor(expectedEl)) === "function" ? base(actualEl) : void 0; | ||
}); | ||
} | ||
@@ -37,0 +40,0 @@ }; |
@@ -23,2 +23,3 @@ // Generated by CoffeeScript 1.12.4 | ||
return { | ||
name: store["for"](testDouble).name, | ||
callCount: calls.length, | ||
@@ -33,2 +34,3 @@ calls: calls, | ||
return { | ||
name: void 0, | ||
callCount: 0, | ||
@@ -35,0 +37,0 @@ calls: [], |
// Generated by CoffeeScript 1.12.4 | ||
(function() { | ||
var _, calls, createTestDoubleFunction, store, stubbings, | ||
var _, calls, copyProperties, createTestDoubleForFunction, createTestDoubleFunction, createTestDoubleNamed, store, stubbings, | ||
slice = [].slice; | ||
@@ -14,3 +14,21 @@ | ||
module.exports = function(name) { | ||
copyProperties = require('./util/copy-properties'); | ||
module.exports = function(nameOrFunc, __optionalName) { | ||
if (_.isFunction(nameOrFunc)) { | ||
return createTestDoubleForFunction(nameOrFunc, __optionalName); | ||
} else { | ||
return createTestDoubleNamed(nameOrFunc || __optionalName); | ||
} | ||
}; | ||
createTestDoubleForFunction = function(func, optionalName) { | ||
return _.tap(copyProperties(func, createTestDoubleNamed(func.name || optionalName)), function(testDouble) { | ||
return _.each(_.functions(func), function(funcName) { | ||
return testDouble[funcName] = createTestDoubleNamed((func.name || optionalName || '') + "." + funcName); | ||
}); | ||
}); | ||
}; | ||
createTestDoubleNamed = function(name) { | ||
return _.tap(createTestDoubleFunction(), function(testDouble) { | ||
@@ -17,0 +35,0 @@ var entry; |
// Generated by CoffeeScript 1.12.4 | ||
(function() { | ||
var DEFAULT_OPTIONS, _, addToStringToDouble, cloneWithNonEnumerableProperties, createFakeObject, createFakePrototype, createTestDoubleViaProxy, createTestDoublesForFunctionNames, createTestDoublesForPlainObject, getAllCustomPrototypalFunctionNames, isConstructor, nameOf, tdFunction, withDefaults, | ||
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, | ||
hasProp = {}.hasOwnProperty; | ||
var DEFAULT_OPTIONS, _, addToStringToDouble, blowUpForConstructors, copyProperties, createTestDoubleViaProxy, createTestDoublesForFunctionNames, createTestDoublesForPlainObject, isConstructor, log, nameOf, tdConstructor, tdFunction, withDefaults; | ||
_ = require('./util/lodash-wrap'); | ||
cloneWithNonEnumerableProperties = require('./util/clone-with-non-enumerable-properties'); | ||
tdFunction = require('./function'); | ||
getAllCustomPrototypalFunctionNames = require('./util/get-all-custom-prototypal-function-names'); | ||
tdConstructor = require('./constructor'); | ||
copyProperties = require('./util/copy-properties'); | ||
isConstructor = require('./replace/is-constructor'); | ||
tdFunction = require('./function'); | ||
log = require('./log'); | ||
@@ -22,40 +22,5 @@ DEFAULT_OPTIONS = { | ||
module.exports = function(nameOrType, config) { | ||
if (isConstructor(nameOrType)) { | ||
return createFakePrototype(nameOrType); | ||
} else { | ||
return createFakeObject(nameOrType, config); | ||
} | ||
}; | ||
createFakePrototype = function(type) { | ||
var TestDoubleConstructor; | ||
TestDoubleConstructor = (function(superClass) { | ||
var ctor; | ||
extend(TestDoubleConstructor, superClass); | ||
function TestDoubleConstructor() { | ||
return ctor.apply(this, arguments); | ||
} | ||
ctor = tdFunction((nameOf(type)) + " constructor"); | ||
return TestDoubleConstructor; | ||
})(type); | ||
return _.tap(TestDoubleConstructor, function(fakeType) { | ||
_.each(_.functions(type), function(funcName) { | ||
return fakeType[funcName] = tdFunction((nameOf(type)) + "." + funcName); | ||
}); | ||
_.each(getAllCustomPrototypalFunctionNames(type), function(funcName) { | ||
return fakeType.prototype[funcName] = tdFunction((nameOf(type)) + "#" + funcName); | ||
}); | ||
return addToStringToDouble(fakeType, "constructor", type); | ||
}); | ||
}; | ||
createFakeObject = function(nameOrType, config) { | ||
var fakeObject; | ||
fakeObject = _.isPlainObject(nameOrType) ? createTestDoublesForPlainObject(nameOrType) : _.isArray(nameOrType) ? createTestDoublesForFunctionNames(nameOrType) : createTestDoubleViaProxy(nameOrType, withDefaults(config)); | ||
return addToStringToDouble(fakeObject, "object", nameOrType); | ||
fakeObject = _.isPlainObject(nameOrType) ? createTestDoublesForPlainObject(nameOrType) : _.isArray(nameOrType) ? createTestDoublesForFunctionNames(nameOrType) : isConstructor(nameOrType) ? blowUpForConstructors() : createTestDoubleViaProxy(nameOrType, withDefaults(config)); | ||
return addToStringToDouble(fakeObject, nameOrType); | ||
}; | ||
@@ -65,5 +30,5 @@ | ||
return _.reduce(_.functions(obj), function(memo, functionName) { | ||
memo[functionName] = isConstructor(obj[functionName]) ? createFakePrototype(obj[functionName]) : tdFunction("." + functionName); | ||
memo[functionName] = isConstructor(obj[functionName]) ? tdConstructor(obj[functionName]) : tdFunction("." + functionName); | ||
return memo; | ||
}, cloneWithNonEnumerableProperties(obj)); | ||
}, copyProperties(obj, _.clone(obj))); | ||
}; | ||
@@ -97,7 +62,7 @@ | ||
addToStringToDouble = function(fakeObject, type, nameOrType) { | ||
addToStringToDouble = function(fakeObject, nameOrType) { | ||
var name; | ||
name = nameOf(nameOrType); | ||
fakeObject.toString = function() { | ||
return "[test double " + type + (name ? " for \"" + name + "\"" : '') + "]"; | ||
return "[test double object" + (name ? " for \"" + name + "\"" : '') + "]"; | ||
}; | ||
@@ -108,5 +73,3 @@ return fakeObject; | ||
nameOf = function(nameOrType) { | ||
if (_.isFunction(nameOrType) && (nameOrType.name != null)) { | ||
return nameOrType.name; | ||
} else if (_.isString(nameOrType)) { | ||
if (_.isString(nameOrType)) { | ||
return nameOrType; | ||
@@ -118,2 +81,6 @@ } else { | ||
blowUpForConstructors = function() { | ||
return log.error("td.object", "Constructor functions are not valid arguments to `td.object` (as of\ntestdouble@2.0.0). Please use the `td.constructor()` method instead for\ncreating fake constructors."); | ||
}; | ||
}).call(this); |
// Generated by CoffeeScript 1.12.4 | ||
(function() { | ||
var _, isConstructor, log, object, stringifyAnything, tdFunction; | ||
var _, isConstructor, log, stringifyAnything, tdConstructor, tdFunction, tdObject; | ||
_ = require('../util/lodash-wrap'); | ||
object = require('../object'); | ||
tdConstructor = require('../constructor'); | ||
tdObject = require('../object'); | ||
tdFunction = require('../function'); | ||
@@ -18,6 +20,8 @@ | ||
module.exports = function(realThing, optionalName) { | ||
if (isConstructor(realThing) || _.isPlainObject(realThing)) { | ||
return object(realThing); | ||
if (isConstructor(realThing)) { | ||
return tdConstructor(realThing); | ||
} else if (_.isPlainObject(realThing)) { | ||
return tdObject(realThing); | ||
} else if (_.isFunction(realThing)) { | ||
return tdFunction((realThing != null ? realThing.name : void 0) ? realThing.name : optionalName); | ||
return tdFunction(realThing, optionalName); | ||
} else { | ||
@@ -24,0 +28,0 @@ return log.error("td.replace", "\"" + optionalName + "\" property was found, but test double only knows how to replace functions, constructors, & objects containing functions (its value was " + (stringifyAnything(realThing)) + ")."); |
@@ -7,3 +7,3 @@ // Generated by CoffeeScript 1.12.4 | ||
stringifyObject = require('stringify-object'); | ||
stringifyObject = require('stringify-object-es5'); | ||
@@ -23,3 +23,11 @@ module.exports = function(anything) { | ||
singleQuotes: false, | ||
inlineCharacterLimit: 65 | ||
inlineCharacterLimit: 65, | ||
transform: function(obj, prop, originalResult) { | ||
var ref; | ||
if (((ref = obj[prop]) != null ? ref.__matches : void 0) != null) { | ||
return obj[prop].__name; | ||
} else { | ||
return originalResult; | ||
} | ||
} | ||
}); | ||
@@ -26,0 +34,0 @@ } |
@@ -7,2 +7,3 @@ // Generated by CoffeeScript 1.12.4 | ||
object: require('./object'), | ||
constructor: require('./constructor'), | ||
when: require('./when'), | ||
@@ -9,0 +10,0 @@ verify: require('./verify'), |
@@ -1,37 +0,200 @@ | ||
// Generated by CoffeeScript 1.12.4 | ||
(function() { | ||
module.exports = { | ||
assign: require('lodash/assign'), | ||
capitalize: require('lodash/capitalize'), | ||
clone: require('lodash/clone'), | ||
each: require('lodash/each'), | ||
every: require('lodash/every'), | ||
extend: require('lodash/extend'), | ||
filter: require('lodash/filter'), | ||
find: require('lodash/find'), | ||
findLast: require('lodash/findLast'), | ||
flatten: require('lodash/flatten'), | ||
functions: require('lodash/functions'), | ||
groupBy: require('lodash/groupBy'), | ||
includes: require('lodash/includes'), | ||
isArray: require('lodash/isArray'), | ||
isBoolean: require('lodash/isBoolean'), | ||
isEqual: require('lodash/isEqual'), | ||
isFunction: require('lodash/isFunction'), | ||
isNumber: require('lodash/isNumber'), | ||
isPlainObject: require('lodash/isPlainObject'), | ||
isRegExp: require('lodash/isRegExp'), | ||
isString: require('lodash/isString'), | ||
keys: require('lodash/keys'), | ||
map: require('lodash/map'), | ||
last: require('lodash/last'), | ||
reduce: require('lodash/reduce'), | ||
reject: require('lodash/reject'), | ||
some: require('lodash/some'), | ||
tap: require('lodash/tap'), | ||
union: require('lodash/union'), | ||
uniq: require('lodash/uniq'), | ||
without: require('lodash/without') | ||
}; | ||
'use strict'; | ||
}).call(this); | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
var _lodash = require('lodash'); | ||
Object.defineProperty(exports, 'assign', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.assign; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'capitalize', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.capitalize; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'clone', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.clone; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'each', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.each; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'every', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.every; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'extend', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.extend; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'filter', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.filter; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'find', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.find; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'findLast', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.findLast; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'flatten', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.flatten; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'functions', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.functions; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'groupBy', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.groupBy; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'includes', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.includes; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'isArray', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.isArray; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'isBoolean', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.isBoolean; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'isEqual', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.isEqual; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'isEqualWith', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.isEqualWith; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'isFunction', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.isFunction; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'isNumber', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.isNumber; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'isPlainObject', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.isPlainObject; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'isRegExp', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.isRegExp; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'isString', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.isString; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'keys', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.keys; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'map', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.map; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'last', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.last; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'reduce', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.reduce; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'reject', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.reject; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'some', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.some; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'tap', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.tap; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'union', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.union; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'uniq', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.uniq; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'without', { | ||
enumerable: true, | ||
get: function get() { | ||
return _lodash.without; | ||
} | ||
}); |
@@ -37,5 +37,3 @@ // Generated by CoffeeScript 1.12.4 | ||
return _.find(stubbingsStore["for"](testDouble), function(stubbing) { | ||
if (argsMatch(stubbing.args, actualArgs, { | ||
allowMatchers: false | ||
})) { | ||
if (argsMatch(stubbing.args, actualArgs, stubbing.config)) { | ||
log.warn('td.verify', "test double" + (stringifyName(testDouble)) + " was both stubbed and verified with arguments (" + (stringifyArgs(actualArgs)) + "), which is redundant and probably unnecessary.", "https://github.com/testdouble/testdouble.js/blob/master/docs/B-frequently-asked-questions.md#why-shouldnt-i-call-both-tdwhen-and-tdverify-for-a-single-interaction-with-a-test-double"); | ||
@@ -42,0 +40,0 @@ return true; |
// Generated by CoffeeScript 1.12.4 | ||
(function() { | ||
module.exports = '2.0.0-pre.3'; | ||
module.exports = '2.0.0-pre.4'; | ||
}).call(this); |
{ | ||
"name": "testdouble", | ||
"version": "2.0.0-pre.3", | ||
"version": "2.0.0-pre.4", | ||
"description": "A minimal test double library for TDD with JavaScript", | ||
@@ -20,7 +20,11 @@ "homepage": "https://github.com/testdouble/testdouble.js", | ||
"clean": "rm -rf generated dist lib .coverage && yarn run clean:dist", | ||
"compile:node": "coffee --output lib --compile src", | ||
"compile:test": "coffee --output generated/test --compile test", | ||
"compile:node:coffee": "coffee --output lib --compile src", | ||
"compile:node:babel": "babel src -d lib", | ||
"compile:node": "yarn run compile:node:coffee && yarn run compile:node:babel", | ||
"compile:test:coffee": "coffee --output generated/test --compile test", | ||
"compile:test:babel": "babel test -d generated/test", | ||
"compile:test": "yarn run compile:test:coffee && yarn run compile:test:babel", | ||
"compile:browser": "browserify . --standalone td --outfile $npm_package_config_build_file --ignore 'quibble' -p headerify", | ||
"compile": "yarn run compile:node && yarn run compile:test && yarn run compile:browser", | ||
"test": "mocha --ui mocha-given --reporter $npm_package_config_mocha_reporter --compilers coffee:coffee-script $EXTRA_MOCHA_ARGS --recursive test/node-helper.coffee test/src", | ||
"test": "mocha --ui mocha-given --reporter $npm_package_config_mocha_reporter --compilers js:babel-core/register,coffee:coffee-script $EXTRA_MOCHA_ARGS --recursive test/node-helper.coffee test/src", | ||
"test:cover:instrument": "istanbul instrument lib -o .coverage/lib", | ||
@@ -47,2 +51,7 @@ "test:cover:run": "EXTRA_MOCHA_ARGS=\"--reporter mocha-istanbul\" COVER=.coverage/lib ISTANBUL_REPORT_DIR=.coverage ISTANBUL_REPORTERS=lcov,html yarn run test", | ||
}, | ||
"babel": { | ||
"presets": [ | ||
"env" | ||
] | ||
}, | ||
"browser": { | ||
@@ -55,5 +64,7 @@ "./lib/replace/module.js": "./lib/replace/module.browser.js", | ||
"quibble": "^0.4.0", | ||
"stringify-object": "^2.4.0" | ||
"stringify-object-es5": "^2.5.0" | ||
}, | ||
"devDependencies": { | ||
"babel-cli": "^6.23.0", | ||
"babel-preset-env": "^1.2.1", | ||
"browserify": "^11.0.1", | ||
@@ -74,2 +85,8 @@ "chai": "^3.2.0", | ||
}, | ||
"directories": { | ||
"doc": "./docs", | ||
"example": "./examples", | ||
"lib": "./lib", | ||
"src": "./src" | ||
}, | ||
"typings": "./index.d.ts", | ||
@@ -76,0 +93,0 @@ "keywords": [ |
@@ -90,6 +90,3 @@ # testdouble.js | ||
2. [test double objects with `td.object()`](docs/4-creating-test-doubles.md#tdobject) | ||
1. [objects that mirror a constructor function](docs/4-creating-test-doubles.md#objectsomeconstructorfunction) | ||
2. [objects that mirror an object of functions](docs/4-creating-test-doubles.md#objectsomeobjectwithfunctions) | ||
3. [object of functions for an array of names](docs/4-creating-test-doubles.md#objectfunctionnames) | ||
4. [object of any functions using ES2015 Proxy](docs/4-creating-test-doubles.md#objectobjectname) | ||
3. [test double constructors with `td.constructor()`](docs/4-creating-test-doubles.md#tdconstructor) | ||
5. [Stubbing responses](docs/5-stubbing-results.md#stubbing-behavior) | ||
@@ -96,0 +93,0 @@ 1. [td.when() API](docs/5-stubbing-results.md#tdwhen) |
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
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
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
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
1438207
196
26688
16
141
4
+ Addedstringify-object-es5@^2.5.0
+ Addedstringify-object-es5@2.5.0(transitive)
- Removedstringify-object@^2.4.0
- Removedstringify-object@2.4.0(transitive)