Skip to content

Commit d56b530

Browse files
committed
executePlan needed breakdown => too much indirect
Decided to pull up the imperative stuff to the satisfy/index instead * Stubbing now responsible for telling you its current outcome based on how many calls it's gotten * Stubbing now stores satisfying calls for easier traceability by td.explain (future proofing)
1 parent 45ed951 commit d56b530

File tree

7 files changed

+120
-22
lines changed

7 files changed

+120
-22
lines changed

src/satisfy/execute-plan.js renamed to src/satisfy/deliver-outcome.js

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
export default function executePlan (double, call, stubbing) {
2-
// 1. get stubbed value
3-
// 2. stubbing.incrementSatisfactions()
4-
// 2a. invoke any callback matchers
5-
// 3. switch stubbing.type
1+
export default function executePlan (stubbing, call) {
2+
// switch stubbing.type
63
// case 'thenReturn': return value
74
// case 'thenDo': return value.apply(actualContext, actualArgs)
85
// case 'thenThrow': throw value

src/satisfy/index.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import findLastStubbingMatch from './find-last-stubbing-match'
2-
import executePlan from './execute-plan'
2+
import invokeCallbacks from './invoke-callbacks'
3+
import deliverOutcome from './deliver-outcome'
34

45
export default function satisfy (double, call) {
56
const stubbing = findLastStubbingMatch(double, call)
67
if (stubbing) {
7-
return executePlan(double, call, stubbing)
8+
stubbing.addSatisfyingCall(call)
9+
invokeCallbacks(stubbing, call)
10+
return deliverOutcome(stubbing, call)
811
}
912
}

src/satisfy/invoke-callbacks.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
export default function invokeCallbacks (stubbing, call) {
2+
}
3+
4+
var invokeCallbackFor = (stubbing, actualArgs) => {
5+
if (_.some(stubbing.args, isCallback)) {
6+
_.each(stubbing.args, (expectedArg, i) => {
7+
if (isCallback(expectedArg)) {
8+
callCallback(stubbing, actualArgs[i], callbackArgs(stubbing, expectedArg))
9+
}
10+
})
11+
}
12+
}
13+
14+
var callbackArgs = (stubbing, expectedArg) => {
15+
if (expectedArg.args != null) {
16+
return expectedArg.args
17+
} else if (stubbing.config.plan === 'thenCallback') {
18+
return stubbing.stubbedValues
19+
} else {
20+
return []
21+
}
22+
}
23+
24+
// stick this in a shared place?
25+
// callLater(func, delay, defer)
26+
var callCallback = (stubbing, callback, args) => {
27+
if (stubbing.config.delay) {
28+
return _.delay(callback, stubbing.config.delay, ...args)
29+
} else if (stubbing.config.defer) {
30+
return _.defer(callback, ...args)
31+
} else {
32+
return callback(...args) // eslint-disable-line
33+
}
34+
}
35+

src/value/stubbing.js

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,29 @@
1+
import _ from '../wrap/lodash'
2+
13
export default class Stubbing {
24
constructor (type, args, outcomes, options = {}) {
35
this.type = type
46
this.args = args
57
this.outcomes = outcomes
68
this.options = options
7-
this.satisfactionCount = 0
9+
this.satisfyingCalls = new Set()
810
}
911

1012
get hasTimesRemaining () {
1113
if (this.options.times == null) return true
12-
return this.satisfactionCount < this.options.times
14+
return this.satisfyingCalls.size < this.options.times
15+
}
16+
17+
get currentOutcome () {
18+
const outcomeIndex = Math.max(0, this.satisfyingCalls.size - 1)
19+
if (outcomeIndex < this.outcomes.length) {
20+
return this.outcomes[outcomeIndex]
21+
} else {
22+
return _.last(this.outcomes)
23+
}
1324
}
1425

15-
incrementSatisfactions () {
16-
this.satisfactionCount++
26+
addSatisfyingCall (call) {
27+
this.satisfyingCalls.add(call)
1728
}
1829
}

test/unit/satisfy/find-last-stubbing-match.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ module.exports = {
5353
stubbingRegister.add(double, stubbing1)
5454
stubbingRegister.add(double, stubbing2)
5555
stubbingRegister.add(double, stubbing3)
56-
stubbing3.incrementSatisfactions()
57-
stubbing3.incrementSatisfactions()
56+
stubbing3.addSatisfyingCall(new Call())
57+
stubbing3.addSatisfyingCall(new Call())
5858

5959
const result = subject(double, call)
6060

test/unit/satisfy/index.test.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ import Double from '../../../src/value/double'
22
import Call from '../../../src/value/call'
33
import Stubbing from '../../../src/value/stubbing'
44

5-
let findLastStubbingMatch, executePlan, subject
5+
let findLastStubbingMatch, invokeCallbacks, deliverOutcome, subject
66
module.exports = {
77
beforeEach: () => {
88
findLastStubbingMatch = td.replace('../../../src/satisfy/find-last-stubbing-match').default
9-
executePlan = td.replace('../../../src/satisfy/execute-plan').default
9+
invokeCallbacks = td.replace('../../../src/satisfy/invoke-callbacks').default
10+
deliverOutcome = td.replace('../../../src/satisfy/deliver-outcome').default
1011

1112
subject = require('../../../src/satisfy').default
1213
},
@@ -15,11 +16,13 @@ module.exports = {
1516
const call = new Call()
1617
const stubbing = new Stubbing()
1718
td.when(findLastStubbingMatch(double, call)).thenReturn(stubbing)
18-
td.when(executePlan(double, call, stubbing)).thenReturn('huzzah')
19+
td.when(deliverOutcome(stubbing, call)).thenReturn('huzzah')
1920

2021
const result = subject(double, call)
2122

2223
assert.equal(result, 'huzzah')
24+
assert.deepEqualSet(stubbing.satisfyingCalls, [call])
25+
td.verify(invokeCallbacks(stubbing, call))
2326
},
2427
'does nothing if no matching stubbing found': () => {
2528
const double = Double.create()
@@ -29,6 +32,7 @@ module.exports = {
2932
const result = subject(double, call)
3033

3134
assert.equal(result, undefined)
32-
assert.equal(td.explain(executePlan).callCount, 0)
35+
assert.equal(td.explain(deliverOutcome).callCount, 0)
36+
assert.equal(td.explain(invokeCallbacks).callCount, 0)
3337
}
3438
}

test/unit/value/stubbing.test.js

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import Call from '../../../src/value/call'
12
import Stubbing from '../../../src/value/stubbing'
23

34
module.exports = {
@@ -7,7 +8,7 @@ module.exports = {
78

89
assert.equal(subject.hasTimesRemaining, true)
910

10-
subject.incrementSatisfactions()
11+
subject.addSatisfyingCall(new Call())
1112

1213
assert.equal(subject.hasTimesRemaining, true)
1314
},
@@ -16,7 +17,7 @@ module.exports = {
1617

1718
assert.equal(subject.hasTimesRemaining, false)
1819

19-
subject.incrementSatisfactions()
20+
subject.addSatisfyingCall(new Call())
2021

2122
assert.equal(subject.hasTimesRemaining, false)
2223
},
@@ -25,7 +26,7 @@ module.exports = {
2526

2627
assert.equal(subject.hasTimesRemaining, true)
2728

28-
subject.incrementSatisfactions()
29+
subject.addSatisfyingCall(new Call())
2930

3031
assert.equal(subject.hasTimesRemaining, false)
3132
},
@@ -34,14 +35,61 @@ module.exports = {
3435

3536
assert.equal(subject.hasTimesRemaining, true)
3637

37-
subject.incrementSatisfactions()
38+
subject.addSatisfyingCall(new Call())
3839

3940
assert.equal(subject.hasTimesRemaining, true)
4041

41-
subject.incrementSatisfactions()
42+
subject.addSatisfyingCall(new Call())
43+
44+
assert.equal(subject.hasTimesRemaining, false)
45+
},
46+
'guards against duplicate calls (only count once)': () => {
47+
const subject = new Stubbing(null, null, null, {times: 2})
48+
49+
assert.equal(subject.hasTimesRemaining, true)
50+
51+
const call = new Call()
52+
subject.addSatisfyingCall(call)
53+
subject.addSatisfyingCall(call)
54+
subject.addSatisfyingCall(call)
55+
56+
assert.equal(subject.hasTimesRemaining, true)
57+
58+
subject.addSatisfyingCall(new Call())
4259

4360
assert.equal(subject.hasTimesRemaining, false)
4461
}
62+
},
63+
'.currentOutcome': {
64+
'one outcome set': () => {
65+
const subject = new Stubbing(null, null, ['pants'])
66+
67+
assert.equal(subject.currentOutcome, 'pants')
68+
69+
subject.addSatisfyingCall(new Call())
4570

71+
assert.equal(subject.currentOutcome, 'pants')
72+
73+
subject.addSatisfyingCall(new Call())
74+
75+
assert.equal(subject.currentOutcome, 'pants')
76+
},
77+
'two outcomes set': () => {
78+
const subject = new Stubbing(null, null, ['pants', 'hat'])
79+
80+
assert.equal(subject.currentOutcome, 'pants')
81+
82+
subject.addSatisfyingCall(new Call())
83+
84+
assert.equal(subject.currentOutcome, 'pants')
85+
86+
subject.addSatisfyingCall(new Call())
87+
88+
assert.equal(subject.currentOutcome, 'hat')
89+
90+
subject.addSatisfyingCall(new Call())
91+
92+
assert.equal(subject.currentOutcome, 'hat')
93+
}
4694
}
4795
}

0 commit comments

Comments
 (0)