Completed
Push — dev ( d30456...4fd03f )
by Fike
33s
created

test/suites/integration/logger/slf4j.spec.js   B

Complexity

Total Complexity 53
Complexity/F 1.2

Size

Lines of Code 331
Function Count 44

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 0
nc 1
dl 0
loc 331
rs 7.4757
c 1
b 0
f 0
wmc 53
mnd 0
bc 44
fnc 44
bpm 1
cpm 1.2044
noi 17

How to fix   Complexity   

Complexity

Complex classes like test/suites/integration/logger/slf4j.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
/* global Logger */
4
5
var sinon = require('sinon')
6
var Chai = require('chai')
7
var assert = Chai.assert
8
var Loggers = require('../../../../lib/logger/index')
9
var slf4j = Loggers.slf4j
10
var Slf4j = slf4j.Slf4j
11
var Context = slf4j.Context
12
var Level = Loggers.Level
13
var expect = Chai.expect
14
15
Chai.use(require('chai-string'))
16
17
describe('Integration', function () {
18
  describe('/logger', function () {
19
    describe('/slf4j.js', function () {
20
      describe('.Slf4j', function () {
21
        var testMessage = 'Hey there, spectacular'
22
        var loggerName = 'ama-team.voxengine-sdk.test.spec.logger.slf4j.Slf4j'
23
        var threshold = Level.All
24
        var logs
25
        var writer
26
        var context
27
        var logger
28
29
        beforeEach(function () {
30
          logs = []
31
          writer = {
32
            write: sinon.spy(function (message) {
33
              logs.push(message)
34
              Logger.write(message)
35
            })
36
          }
37
          context = new Context(threshold, writer)
38
          logger = context.create(loggerName)
39
          context.setLevel(loggerName, threshold)
40
          context.setWriter(loggerName, writer)
41
        })
42
43
        describe('< new', function () {
44
          it('uses default context for direct creation if context is not specified', function () {
45
            logger = new Slf4j(loggerName)
46
            Slf4j.setWriter(writer)
47
            Slf4j.setLevel(loggerName, Level.All)
48
            expect(logger.getLevel()).to.eq(Level.All)
49
            Slf4j.setLevel(loggerName, Level.Error)
50
            expect(logger.getLevel()).to.eq(Level.Error)
51
            expect(logger.getWriter()).to.eq(writer)
52
          })
53
54
          it('provides backward compatibility for 0.2.0-style instantiation', function () {
55
            writer = {write: sinon.spy(Logger.write.bind(Logger))}
56
            logger = new Slf4j(loggerName, Level.All, writer)
57
            logger.info(testMessage)
58
            expect(writer.write.calledOnce).to.be.true
59
          })
60
61
          it('tolerates falsey logger name', function () {
62
            logger = new Slf4j(undefined, context)
63
            logger.error(testMessage)
64
          })
65
        })
66
67
        describe('#log', function () {
68
          it('passes call to writer.write', function () {
69
            logger.log(Level.Error, testMessage)
70
            assert(writer.write.calledOnce)
71
            assert(writer.write.calledWithMatch(testMessage))
72
          })
73
74
          it('includes logger name in output', function () {
75
            logger.log(Level.Error, testMessage)
76
            expect(logs[0]).to.contain(loggerName)
77
          })
78
79
          it('passes message with level equal to threshold', function () {
80
            context = new Context(Level.Error, writer)
81
            logger = context.create(loggerName)
82
            logger.log(Level.Error, testMessage)
83
            assert(writer.write.calledOnce)
84
            assert(writer.write.calledWithMatch(testMessage))
85
          })
86
87
          it('passes message with level higher than threshold', function () {
88
            context = new Context(Level.Info, writer)
89
            logger = context.create(loggerName)
90
            logger.log(Level.Error, testMessage)
91
            assert(writer.write.calledOnce)
92
            assert(writer.write.calledWithMatch(testMessage))
93
          })
94
95
          it('swallows message with level lesser than threshold', function () {
96
            context = new Context(Level.Error, writer)
97
            logger = new Slf4j(loggerName, context)
98
            logger.log(Level.Debug, testMessage)
99
            assert(writer.write.notCalled)
100
          })
101
102
          it('correctly renders object', function () {
103
            var parameter = {x: 12}
104
            logger.log(Level.Error, 'parametrized: {}', parameter)
105
            var message = writer.write.getCall(0).args[0]
106
            expect(message).to.endWith('parametrized: {"x":12}')
107
          })
108
109
          it('correctly renders string', function () {
110
            var parameter = 'value'
111
            logger.log(Level.Error, 'parametrized: {}', parameter)
112
            var message = writer.write.getCall(0).args[0]
113
            expect(message).to.endWith('parametrized: value')
114
          })
115
116
          it('correctly renders boolean', function () {
117
            var parameter = true
118
            logger.log(Level.Error, 'parametrized: {}', parameter)
119
            var message = writer.write.getCall(0).args[0]
120
            expect(message).to.endWith('parametrized: true')
121
          })
122
123
          it('correctly renders number', function () {
124
            var parameter = 42
125
            logger.log(Level.Error, 'parametrized: {}', parameter)
126
            var message = writer.write.getCall(0).args[0]
127
            expect(message).to.endWith('parametrized: 42')
128
          })
129
130
          it('correctly renders null', function () {
131
            var parameter = null
132
            logger.log(Level.Error, 'parametrized: {}', parameter)
133
            var message = writer.write.getCall(0).args[0]
134
            expect(message).to.endWith('parametrized: null')
135
          })
136
137
          it('correctly renders undefined', function () {
138
            logger.log(Level.Error, 'parametrized: {}', undefined)
139
            var message = writer.write.getCall(0).args[0]
140
            expect(message).to.endWith('parametrized: {undefined}')
141
          })
142
143
          it('correctly renders error', function () {
144
            var parameter = new Error()
145
            var stack = 'superFunc() at file:60:64\nanotherFunc() at file:60:64'
146
            var name = 'TestingException'
147
            var message = 'An exception has been thrown'
148
            var expected = [
149
              '[ERROR] ' + loggerName + ': Unhandled exception:',
150
              name + ': ' + message,
151
              'Stack:', stack
152
            ].join('\n')
153
            var pattern = 'Unhandled exception:'
154
155
            parameter.name = name
156
            parameter.message = message
157
            parameter.stack = stack
158
159
            logger.log(Level.Error, pattern, parameter)
160
            expect(writer.write.getCall(0).args[0]).to.eq(expected)
161
          })
162
        })
163
164
        describe('#setLevel', function () {
165
          it('allows threshold reconfiguration on-the-fly', function () {
166
            logger.setLevel(Level.Debug)
167
            logger.log(Level.Debug, 'Message #{}', 1)
168
            logger.setLevel(Level.Error)
169
            logger.log(Level.Debug, 'Message #{}', 2)
170
171
            expect(writer.write.callCount).to.eq(1)
172
            expect(writer.write.getCall(0).args[0]).to.contain('Message #1')
173
          })
174
        })
175
176
        describe('#setWriter', function () {
177
          it('allows writer reconfiguration on-the-fly', function () {
178
            var writerA = {
179
              write: sinon.spy(Logger.write)
180
            }
181
            var writerB = {
182
              write: sinon.spy(Logger.write)
183
            }
184
            expect(writerA.write.calledOnce).to.be.false
185
            expect(writerB.write.calledOnce).to.be.false
186
            logger = context.create(loggerName, Level.All, writerA)
187
            logger.log(Level.Error, 'Message #1')
188
            expect(writerA.write.calledOnce).to.be.true
189
            expect(writerB.write.calledOnce).to.be.false
190
            logger.setWriter(writerB)
191
            logger.log(Level.Error, 'Message #2')
192
            expect(writerA.write.calledOnce).to.be.true
193
            expect(writerB.write.calledOnce).to.be.true
194
          })
195
        })
196
197
        describe('#attach', function () {
198
          it('attaches diagnostic context that is printed later', function () {
199
            var name = 'alpha'
200
            var value = 'beta'
201
            logger.attach(name, value)
202
            logger.log(Level.Error, testMessage)
203
            expect(writer.write.getCall(0)).to.be.ok
204
            expect(writer.write.getCall(0).args.length).to.eq(1)
205
            var argument = writer.write.getCall(0).args[0]
206
            expect(argument).to.contain(name)
207
            expect(argument).to.contain(value)
208
          })
209
        })
210
211
        describe('#detach', function () {
212
          it('provides method to clear diagnostic context key', function () {
213
            var nameA = 'alpha'
214
            var valueA = 'beta'
215
            var nameB = 'gamma'
216
            var valueB = 'delta'
217
            logger.attach(nameA, valueA)
218
            logger.attach(nameB, valueB)
219
            logger.info(testMessage)
220
221
            expect(writer.write.getCall(0)).to.be.ok
222
            expect(writer.write.getCall(0).args.length).to.eq(1)
223
            var argument = writer.write.getCall(0).args[0]
224
            expect(argument).to.contain(nameA)
225
            expect(argument).to.contain(valueA)
226
            expect(argument).to.contain(nameB)
227
            expect(argument).to.contain(valueB)
228
229
            logger.detach(nameB, valueB)
230
            logger.info(testMessage)
231
232
            expect(writer.write.getCall(1)).to.be.ok
233
            expect(writer.write.getCall(1).args.length).to.eq(1)
234
            argument = writer.write.getCall(1).args[0]
235
            expect(argument).to.contain(nameA)
236
            expect(argument).to.contain(valueA)
237
            expect(argument).not.to.contain(nameB)
238
            expect(argument).not.to.contain(valueB)
239
          })
240
        })
241
242
        describe('#attachAll', function () {
243
          it('provides methods to set and clear diagnostic context in one call', function () {
244
            var nameA = 'alpha'
245
            var valueA = 'beta'
246
            var nameB = 'gamma'
247
            var valueB = 'delta'
248
            var mdc = {}
249
            var call
250
            var argument
251
            mdc[nameA] = valueA
252
            mdc[nameB] = valueB
253
            logger.attachAll(mdc)
254
255
            logger.info(testMessage)
256
257
            call = writer.write.getCall(0)
258
            expect(call).to.be.ok
259
            expect(call.args.length).to.eq(1)
260
            argument = call.args[0]
261
            expect(argument).to.contain(nameA)
262
            expect(argument).to.contain(valueA)
263
            expect(argument).to.contain(nameB)
264
            expect(argument).to.contain(valueB)
265
266
            logger.detachAll()
267
            logger.info(testMessage)
268
269
            call = writer.write.getCall(1)
270
            expect(call).to.be.ok
271
            expect(call.args.length).to.eq(1)
272
            argument = call.args[0]
273
            expect(argument).not.to.contain(nameA)
274
            expect(argument).not.to.contain(valueA)
275
            expect(argument).not.to.contain(nameB)
276
            expect(argument).not.to.contain(valueB)
277
          })
278
        })
279
280
        describe('.create', function () {
281
          it('provides static method for logger creation', function () {
282
            logger = Slf4j.create(loggerName)
283
            expect(logger).to.be.instanceof(Slf4j)
284
            expect(logger.getName()).to.eq(loggerName)
285
          })
286
        })
287
288
        describe('.setWriter', function () {
289
          it('provides static method for changing writer', function () {
290
            logger = Slf4j.create(loggerName, Level.All)
291
            writer = {
292
              write: sinon.spy(Logger.write)
293
            }
294
            logger.info(testMessage)
295
            expect(writer.write.calledOnce).to.be.false
296
            Slf4j.setWriter(loggerName, writer)
297
            logger.info(testMessage)
298
            expect(writer.write.calledOnce).to.be.true
299
          })
300
        })
301
302
        describe('.setLevel', function () {
303
          it('provides static method for changing threshold', function () {
304
            logger = Slf4j.create(loggerName, Level.All, writer)
305
            expect(writer.write.calledOnce).to.be.false
306
            logger.info(testMessage)
307
            expect(writer.write.calledOnce).to.be.true
308
            Slf4j.setLevel(loggerName, Level.Error)
309
            logger.info(testMessage)
310
            expect(writer.write.calledOnce).to.be.true
311
          })
312
        })
313
314
        describe('#getContext', function () {
315
          it('returns context it was created in', function () {
316
            var context = new Slf4j.Context()
317
            var logger = context.create(loggerName)
318
            expect(logger.getContext()).to.eq(context)
319
          })
320
        })
321
322
        describe('.factory', function () {
323
          it('tolerates invalid settings', function () {
324
            expect(Slf4j.factory(false)).to.be.instanceOf(Slf4j)
325
          })
326
327
          it('returns passed instance if it is present', function () {
328
            var mockingbird = {}
329
            expect(Slf4j.factory({instance: mockingbird})).to.eq(mockingbird)
330
          })
331
        })
332
      })
333
    })
334
  })
335
})
336