diff --git a/README.md b/README.md index 9c714aa..b0e2536 100644 --- a/README.md +++ b/README.md @@ -203,6 +203,76 @@ An array of behaviours, each having *one* of these properties: - **action.returnValue** - **action.throwError** +If `stub.actions` is set or updated explicitly, at least one call to `stub.callFn(fn)`, `stub.callOriginal()`, `stub.returnWith(val)`, `stub.throwWith(err)`, `stub.callback(...)`, `stub.callbackAtIndex(...)`, `stub.resolveWith(val)`, `stub.rejectWith(val)`, `stub.withActions(actions)` or `stub.withActions()` must be made. + +### stub.withActions(actions) *or* stub.withActions() + +Configures this stub to use the specified array of actions. See `stub.actions` above for the syntax of an action. + +Example: + +```js +var fn = simple.stub() + .withActions([{ returnValue: 'a' }, { returnValue: 'b' }]) +var returned1 = fn() +var returned2 = fn() +assert.equal(fn.callCount, 2) +assert.equal(returned1, 'a') +assert.equal(returned2, 'b') +``` + +`withActions` is, just like the others, chainable: + +```js +var fn = simple.stub() + .returnWith('a') + .withActions([{ returnValue: 'b' }, { returnValue: 'c' }]) + .returnWith('d') + +var returned1 = fn() +var returned2 = fn() +var returned3 = fn() +var returned4 = fn() + +assert.equal(fn.callCount, 4) +assert.equal(returned1, 'a') +assert.equal(returned2, 'b') +assert.equal(returned3, 'c') +assert.equal(returned4, 'd') +``` + +`stub.actions` may be set explicitly in which case you need to call `stub.withActions()`: + +```js +var fn = simple.stub() +fn.actions=[{ returnValue: 'a' }, { returnValue: 'b' }] +fn.withActions() + +var returned1 = fn() +var returned2 = fn() + +assert.equal(fn.callCount, 2) +assert.equal(returned1, 'a') +assert.equal(returned2, 'b') +``` + +... unless another configuration has been specified on the stub. In that case no call to `stub.withActions()` is needed: + +```js +var fn = simple.stub().returnWith('a') +fn.actions.push({ returnValue: 'b' }, { returnValue: 'c' }) + +var returned1 = fn() +var returned2 = fn() +var returned3 = fn() + +assert.equal(fn.callCount, 3) +assert.equal(returned1, 'a') +assert.equal(returned2, 'b') +assert.equal(returned3, 'c') +``` + + ### stub.loop Boolean (default: true) setting whether the queue of actions for this stub should repeat. diff --git a/index.js b/index.js index 5c774d6..2a5b165 100644 --- a/index.js +++ b/index.js @@ -178,6 +178,14 @@ return newFn // Chainable } + newFn.withActions = function (actions) { + wrappedFn = stubFn + if (actions && actions.length >= 0) { + Array.prototype.push.apply(newFn.actions, actions) + } + return newFn // Chainable + } + newFn.callOriginal = newFn.callOriginalFn = function () { wrappedFn = stubFn newFn.actions.push({ fn: originalFn }) diff --git a/test.js b/test.js index 26d86ab..1fc8349 100644 --- a/test.js +++ b/test.js @@ -539,6 +539,129 @@ describe('simple', function () { }) }) + describe('for withActions configurations', function () { + it('performs all types of actions', function (done) { + stubFn = simple.stub().withActions([{ returnValue: 'a' }, { cbArgs: [1, 2, 3] }, { throwError: new Error('my message') }]) + var returned = stubFn() // Call 1 + stubFn('a', function () { // Call 2 + var call2Args = arguments + try { + stubFn() // Call 3 + } catch (e) { + + assert.equal(stubFn.callCount, 3) + + // Verify Call 1: return 'a' + assert(returned) + assert.equal(returned, 'a') + + // Verify Call 2: callback with 1,2,3 + assert(stubFn.called) + assert.equal(stubFn.calls[1].args[0], 'a') + assert.equal(call2Args.length, 3) + assert.equal(call2Args[0], 1) + assert.equal(call2Args[1], 2) + assert.equal(call2Args[2], 3) + + // Verify Call 3: error thrown + assert(e instanceof Error) + assert.equal(e.message, 'my message') + done() + } + }) + }) + + it('can return over multiple calls, looping per default', function () { + stubFn = simple.stub().withActions([{ returnValue: 'a' }, { returnValue: 'b' }]) + + var returned = [] + returned.push(stubFn()) + returned.push(stubFn()) + returned.push(stubFn()) + + assert.equal(returned.length, 3) + assert(stubFn.called) + assert.equal(stubFn.callCount, 3) + assert.equal(returned[0], 'a') + assert.equal(returned[1], 'b') + assert.equal(returned[2], 'a') + }) + + it('can return over multiple calls, looping turned off', function () { + stubFn = simple.stub().withActions([{ returnValue: 'a' }, { returnValue: 'b' }]) + stubFn.loop = false + + var returned = [] + returned.push(stubFn()) + returned.push(stubFn()) + returned.push(stubFn()) + + assert.equal(returned.length, 3) + assert(stubFn.called) + assert.equal(stubFn.callCount, 3) + assert.equal(returned[0], 'a') + assert.equal(returned[1], 'b') + assert.equal(returned[2], undefined) + }) + + it('preserves previously added configurations', function () { + stubFn = simple.stub().returnWith('a').withActions([{ returnValue: 'b'}, { returnValue: 'c'}]) + var returned = [] + returned.push(stubFn()) + returned.push(stubFn()) + returned.push(stubFn()) + + assert.equal(returned.length, 3) + assert(stubFn.called) + assert.equal(stubFn.callCount, 3) + assert.equal(returned[0], 'a') + assert.equal(returned[1], 'b') + assert.equal(returned[2], 'c') + }) + + it('is chainable and more configurations may be added after', function () { + stubFn = simple.stub().withActions([{ returnValue: 'a'}, { returnValue: 'b'}]).returnWith('c') + var returned = [] + returned.push(stubFn()) + returned.push(stubFn()) + returned.push(stubFn()) + + assert.equal(returned.length, 3) + assert(stubFn.called) + assert.equal(stubFn.callCount, 3) + assert.equal(returned[0], 'a') + assert.equal(returned[1], 'b') + assert.equal(returned[2], 'c') + }) + + it('allows setting actions array and then calling withActions', function () { + stubFn = simple.stub() + stubFn.actions = [{ returnValue: 'a'}] + stubFn.withActions() + + var returned = stubFn() + + assert.equal(returned.length, 1) + assert(stubFn.called) + assert.equal(stubFn.callCount, 1) + assert.equal(returned, 'a') + }) + + it('allows calling withActions and then setting actions array', function () { + stubFn = simple.stub() + stubFn.withActions() + stubFn.actions = [{ returnValue: 'a'}] + + var returned = stubFn() + + assert.equal(returned.length, 1) + assert(stubFn.called) + assert.equal(stubFn.callCount, 1) + assert.equal(returned, 'a') + }) + + }) + describe('for a specified function to call', function () { it('should be called with arguments and return', function () { var stubFn = simple.stub().callFn(function () {