Skip to content

Commit 4984a26

Browse files
committed
implement most of the td.when rewrite children
1 parent d9ce1f9 commit 4984a26

10 files changed

+197
-5
lines changed
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
export default () => {}
1+
export default function (type, args) {
2+
}

src/when/chain-stubbing.js

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,32 @@
1-
export default () => {}
1+
import warnIfPromiseless from './warn-if-promiseless'
2+
3+
export default function chainStubbing (double, completeStubbing) {
4+
return {
5+
thenReturn (...stubbedValues) {
6+
completeStubbing('thenReturn', stubbedValues)
7+
return double.fake
8+
},
9+
thenCallback (...stubbedValues) {
10+
completeStubbing('thenCallback', stubbedValues)
11+
return double.fake
12+
},
13+
thenDo (...stubbedActions) {
14+
completeStubbing('thenDo', stubbedActions)
15+
return double.fake
16+
},
17+
thenThrow (...stubbedErrors) {
18+
completeStubbing('thenThrow', stubbedErrors)
19+
return double.fake
20+
},
21+
thenResolve (...stubbedValues) {
22+
warnIfPromiseless()
23+
completeStubbing('thenResolve', stubbedValues)
24+
return double.fake
25+
},
26+
thenReject (...stubbedErrors) {
27+
warnIfPromiseless()
28+
completeStubbing('thenReject', stubbedErrors)
29+
return double.fake
30+
}
31+
}
32+
}

src/when/ensure-rehearsal.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,13 @@
1-
export default () => {}
1+
import log from '../log'
2+
3+
export default function ensureRehearsal (rehearsal) {
4+
if (!rehearsal) {
5+
log.error('td.when', `\
6+
No test double invocation call detected for \`when()\`.
7+
8+
Usage:
9+
when(myTestDouble('foo')).thenReturn('bar')\
10+
`
11+
)
12+
}
13+
}

src/when/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import Stubbing from '../value/stubbing'
88
export default (__rehearseInvocationHere__, options) => {
99
const rehearsal = CallLog.instance.pop()
1010
ensureRehearsal(rehearsal)
11-
return chainStubbing((type, outcomes) => {
11+
return chainStubbing(rehearsal.double, (type, outcomes) => {
1212
StubbingRegister.instance.add(rehearsal.double, new Stubbing(
1313
type,
1414
addImpliedCallbackArgIfNecessary(type, rehearsal.call.args),

src/when/warn-if-promiseless.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import config from '../config'
2+
import log from '../log'
3+
4+
export default function warnIfPromiseless () {
5+
if (config().promiseConstructor == null) {
6+
log.warn('td.when', `\
7+
no promise constructor is set, so this \`thenResolve\` or \`thenReject\` stubbing
8+
will fail if it's satisfied by an invocation on the test double. You can tell
9+
testdouble.js which promise constructor to use with \`td.config\`, like so:
10+
11+
td.config({
12+
promiseConstructor: require('bluebird')
13+
})\
14+
`
15+
)
16+
}
17+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
3+
}

test/unit/when/chain-stubbing.test.js

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import Double from '../../../src/value/double'
2+
3+
let warnIfPromiseless, subject
4+
let double, type, outcomes, callback
5+
module.exports = {
6+
beforeEach: () => {
7+
warnIfPromiseless = td.replace('../../../src/when/warn-if-promiseless').default
8+
9+
subject = require('../../../src/when/chain-stubbing').default
10+
11+
// Common setup across tests:
12+
double = Double.create(null, null, null, () => 'a fake')
13+
callback = (t, o) => { type = t; outcomes = o }
14+
},
15+
'.thenReturn': () => {
16+
const result = subject(double, callback).thenReturn(12, 23)
17+
18+
assert.equal(result, 'a fake')
19+
assert.equal(type, 'thenReturn')
20+
assert.deepEqual(outcomes, [12, 23])
21+
},
22+
'.thenCallback': () => {
23+
const func = () => {}
24+
25+
const result = subject(double, callback).thenCallback(func)
26+
27+
assert.equal(result, 'a fake')
28+
assert.equal(type, 'thenCallback')
29+
assert.deepEqual(outcomes, [func])
30+
},
31+
'.thenDo': () => {
32+
const func = () => {}
33+
34+
const result = subject(double, callback).thenDo(func)
35+
36+
assert.equal(result, 'a fake')
37+
assert.equal(type, 'thenDo')
38+
assert.deepEqual(outcomes, [func])
39+
},
40+
'.thenThrow': () => {
41+
const error = new Error('hi')
42+
43+
const result = subject(double, callback).thenThrow(error)
44+
45+
assert.equal(result, 'a fake')
46+
assert.equal(type, 'thenThrow')
47+
assert.deepEqual(outcomes, [error])
48+
},
49+
'.thenResolve': () => {
50+
const result = subject(double, callback).thenResolve('pants')
51+
52+
td.verify(warnIfPromiseless())
53+
assert.equal(result, 'a fake')
54+
assert.equal(type, 'thenResolve')
55+
assert.deepEqual(outcomes, ['pants'])
56+
},
57+
'.thenReject': () => {
58+
const error = new Error('hi')
59+
60+
const result = subject(double, callback).thenReject(error)
61+
62+
td.verify(warnIfPromiseless())
63+
assert.equal(result, 'a fake')
64+
assert.equal(type, 'thenReject')
65+
assert.deepEqual(outcomes, [error])
66+
}
67+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import Call from '../../../src/value/call'
2+
3+
let log, subject
4+
module.exports = {
5+
beforeEach: () => {
6+
log = td.replace('../../../src/log').default
7+
8+
subject = require('../../../src/when/ensure-rehearsal').default
9+
},
10+
'no rehearsal raises error': () => {
11+
subject(null)
12+
13+
td.verify(log.error('td.when', `\
14+
No test double invocation call detected for \`when()\`.
15+
16+
Usage:
17+
when(myTestDouble('foo')).thenReturn('bar')\
18+
`
19+
))
20+
},
21+
'with rehearsal does nothing': () => {
22+
const call = new Call()
23+
24+
subject(call)
25+
26+
assert.equal(td.explain(log.error).callCount, 0)
27+
}
28+
29+
}

test/unit/when/index.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ module.exports = {
1515
const double = Double.create()
1616
const call = new Call(null, ['arg1', 'arg2'])
1717
CallLog.instance.log(double, call)
18-
td.when(chainStubbing(td.callback('a type', ['a stub']))).thenReturn('chained methods')
18+
td.when(chainStubbing(double, td.callback('a type', ['a stub']))).thenReturn('chained methods')
1919
td.when(addImpliedCallbackArgIfNecessary('a type', ['arg1', 'arg2'])).thenReturn('good args')
2020

2121
const result = subject('_fake rehearsal arg_', 'some options')
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
let config, log, subject
2+
module.exports = {
3+
beforeEach: () => {
4+
config = td.replace('../../../src/config').default
5+
log = td.replace('../../../src/log').default
6+
7+
subject = require('../../../src/when/warn-if-promiseless').default
8+
},
9+
'config has no promise set': () => {
10+
td.when(config()).thenReturn({promiseConstructor: null})
11+
12+
subject()
13+
14+
td.verify(log.warn('td.when', `\
15+
no promise constructor is set, so this \`thenResolve\` or \`thenReject\` stubbing
16+
will fail if it's satisfied by an invocation on the test double. You can tell
17+
testdouble.js which promise constructor to use with \`td.config\`, like so:
18+
19+
td.config({
20+
promiseConstructor: require('bluebird')
21+
})\
22+
`
23+
))
24+
},
25+
'config has a promise set': () => {
26+
td.when(config()).thenReturn({promiseConstructor: function () {}})
27+
28+
subject()
29+
30+
assert.equal(td.explain(log.warn).callCount, 0)
31+
}
32+
}

0 commit comments

Comments
 (0)