Completed
Push — dev ( 249398...dac991 )
by Fike
39s
created

test/suites/integration/Execution/Transition/Branch.spec.js   F

Complexity

Total Complexity 107
Complexity/F 2.43

Size

Lines of Code 204
Function Count 44

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 0
wmc 107
nc 16
mnd 1
bc 44
fnc 44
dl 0
loc 204
rs 3.12
bpm 1
cpm 2.4318
noi 2
c 2
b 0
f 0

2 Functions

Rating   Name   Duplication   Size   Complexity  
B Branch.spec.js ➔ describe(ꞌIntegrationꞌ) 0 187 1
A Branch.spec.js ➔ branchStopper 0 3 1

How to fix   Complexity   

Complexity

Complex classes like test/suites/integration/Execution/Transition/Branch.spec.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
/* eslint-env mocha */
2
/* eslint-disable no-unused-expressions */
3
4
var Sinon = require('sinon')
5
var Chai = require('chai')
6
var expect = Chai.expect
7
8
Chai.use(require('chai-as-promised'))
9
10
var SDK = require('@ama-team/voxengine-sdk')
11
var Concurrent = SDK.Concurrent
12
var CancellationToken = Concurrent.CancellationToken
13
var TimeoutException = Concurrent.TimeoutException
14
var ExecutionBranch = require('../../../../../lib/Execution/Transition/Branch').Branch
15
var Executor = require('../../../../../lib/Execution/Executor').Executor
16
17
function branchStopper () {
18
  throw new Error('This branch should not have executed')
19
}
20
21
describe('Integration', function () {
22
  describe('/Execution', function () {
23
    describe('/Transition', function () {
24
      describe('/Branch.js', function () {
25
        describe('.Branch', function () {
26
          var executor = new Executor(null)
27
          var optionsFactory = function (handler, onTimeout, name) {
28
            handler = handler || function () {
29
              return new Promise(function () {})
30
            }
31
            onTimeout = onTimeout || function (a, b, c, error) {
32
              return Promise.reject(error)
33
            }
34
            return {
35
              name: name || 'integration test',
36
              handler: {
37
                id: 'handler',
38
                handler: Sinon.spy(handler),
39
                timeout: null,
40
                onTimeout: {
41
                  id: 'timeoutHandler',
42
                  handler: Sinon.spy(onTimeout),
43
                  timeout: null
44
                }
45
              },
46
              executor: executor,
47
              logger: {}
48
            }
49
          }
50
51
          var factory = function (options) {
52
            return new ExecutionBranch(options)
53
          }
54
55
          describe('#run', function () {
56
            it('returns handler result ', function () {
57
              var value = {x: 12}
58
              var options = optionsFactory(function () {
59
                return Promise.resolve(value)
60
              })
61
              var branch = factory(options)
62
              return expect(branch.run()).to.eventually.eq(value)
63
            })
64
65
            it('doesn\'t run timeout handler if main handler executes correctly', function () {
66
              var value = {x: 12}
67
              var options = optionsFactory(function () {
68
                return Promise.resolve(value)
69
              })
70
              var branch = factory(options)
71
              return branch
72
                .run()
73
                .then(function () {
74
                  expect(options.handler.handler.callCount).to.eq(1)
75
                  expect(options.handler.onTimeout.handler.callCount).to.eq(0)
76
                })
77
            })
78
79
            it('runs and returns timeout handler result if main handler times out', function () {
80
              var value = {x: 12}
81
              var options = optionsFactory(null, function () {
82
                return Promise.resolve(value)
83
              })
84
              options.handler.timeout = 0
85
              var branch = factory(options)
86
              return branch
87
                .run()
88
                .then(function (result) {
89
                  expect(result).to.eq(value)
90
                  expect(options.handler.handler.callCount).to.eq(1)
91
                  expect(options.handler.onTimeout.handler.callCount).to.eq(1)
92
                })
93
            })
94
95
            it('runs and rejects with main handler rejection reason', function () {
96
              var reason = new Error()
97
              var options = optionsFactory(function () {
98
                return Promise.reject(reason)
99
              })
100
              var branch = factory(options)
101
              return expect(branch.run()).to.eventually.be.rejectedWith(reason)
102
            })
103
104
            it('runs and rejects with timeout rejection reason if main handler times out', function () {
105
              var reason = new Error()
106
              var options = optionsFactory(null, function () {
107
                return Promise.reject(reason)
108
              })
109
              options.handler.timeout = 0
110
              var branch = factory(options)
111
              return expect(branch.run()).to.eventually.be.rejectedWith(reason)
112
            })
113
114
            it('throws if called more than once', function () {
115
              var options = optionsFactory(function () {
116
                return Promise.resolve()
117
              })
118
              var branch = factory(options)
119
              return branch
120
                .run()
121
                .then(function () {
122
                  expect(branch.run).to.throw()
123
                })
124
            })
125
126
            it('rejects with TimeoutException if both handlers time out', function () {
127
              var handler = function () {
128
                return new Promise(function () {})
129
              }
130
              var options = optionsFactory(handler, handler)
131
              options.handler.timeout = 0
132
              options.handler.onTimeout.timeout = 0
133
              var branch = factory(options)
134
              return expect(branch.run()).to.eventually.be.rejectedWith(TimeoutException)
135
            })
136
137
            it('cancels tokens on timeouts', function () {
138
              var handler = function () {
139
                return new Promise(function () {})
140
              }
141
              var options = optionsFactory(handler, handler)
142
              var sources = [options.handler, options.handler.onTimeout]
143
              sources.forEach(function (source) {
144
                source.timeout = 0
145
              })
146
              var branch = factory(options)
147
              return branch
148
                .run()
149
                .then(branchStopper, function () {
150
                  var handlers = sources.map(function (source) {
151
                    return source.handler
152
                  })
153
                  handlers.forEach(function (handler) {
154
                    expect(handler.callCount).to.eq(1)
155
                    var token = handler.getCall(0).args[2]
156
                    expect(token).to.be.instanceOf(CancellationToken)
157
                    expect(token.isCancelled()).to.be.true
0 ignored issues
show
introduced by
The result of the property access to expect(token.isCancelled()).to.be.true is not used.
Loading history...
158
                  })
159
                })
160
            })
161
162
            var variants = [
163
              {
164
                name: 'handler',
165
                handler: function () {
166
                  return Promise.resolve()
167
                },
168
                timeout: null
169
              },
170
              {
171
                name: 'timeoutHandler',
172
                handler: function () {
173
                  return new Promise(function () {})
174
                },
175
                timeout: 0
176
              }
177
            ]
178
179
            variants.forEach(function (variant) {
180
              it('creates derived cancellation token for ' + variant.name, function () {
181
                var options = optionsFactory(variant.handler, function () {
182
                  return Promise.resolve()
183
                })
184
                var token = new CancellationToken()
185
                options.handler.timeout = variant.timeout
186
                var branch = factory(options)
187
                return branch
188
                  .run(null, null, token)
189
                  .then(function () {
190
                    var source = options.handler
191
                    source = variant.name === 'handler' ? source : source.onTimeout
192
                    var handler = source.handler
193
                    expect(handler.callCount).to.eq(1)
194
                    var passedToken = handler.getCall(0).args[2]
195
                    expect(passedToken).to.be.instanceOf(CancellationToken)
196
                    expect(passedToken.isCancelled()).to.be.false
0 ignored issues
show
introduced by
The result of the property access to expect(passedToken.isCancelled()).to.be.false is not used.
Loading history...
197
                    token.cancel()
198
                    return passedToken
199
                  })
200
              })
201
            })
202
          })
203
        })
204
      })
205
    })
206
  })
207
})
208