adapt-authoring-logger 1.1.2 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "adapt-authoring-logger",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Basic logger for the Adapt authoring tool",
|
|
5
5
|
"homepage": "https://github.com/adapt-security/adapt-authoring-logger",
|
|
6
6
|
"license": "GPL-3.0",
|
|
@@ -8,10 +8,16 @@
|
|
|
8
8
|
"main": "index.js",
|
|
9
9
|
"repository": "adapt-security/adapt-authoring-logger",
|
|
10
10
|
"dependencies": {
|
|
11
|
+
"adapt-authoring-core": "^1.7.0",
|
|
11
12
|
"chalk": "^5.3.0"
|
|
12
13
|
},
|
|
13
14
|
"peerDependencies": {
|
|
14
|
-
"adapt-authoring-
|
|
15
|
+
"adapt-authoring-config": "^1.1.4"
|
|
16
|
+
},
|
|
17
|
+
"peerDependenciesMeta": {
|
|
18
|
+
"adapt-authoring-config": {
|
|
19
|
+
"optional": true
|
|
20
|
+
}
|
|
15
21
|
},
|
|
16
22
|
"devDependencies": {
|
|
17
23
|
"@semantic-release/git": "^10.0.1",
|
|
@@ -35,10 +41,18 @@
|
|
|
35
41
|
],
|
|
36
42
|
"@semantic-release/npm",
|
|
37
43
|
"@semantic-release/github",
|
|
38
|
-
|
|
44
|
+
[
|
|
45
|
+
"@semantic-release/git",
|
|
46
|
+
{
|
|
47
|
+
"assets": [
|
|
48
|
+
"package.json"
|
|
49
|
+
],
|
|
50
|
+
"message": "Chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
|
|
51
|
+
}
|
|
52
|
+
]
|
|
39
53
|
]
|
|
40
54
|
},
|
|
41
55
|
"scripts": {
|
|
42
|
-
"test": "node --test"
|
|
56
|
+
"test": "node --test tests/*.spec.js"
|
|
43
57
|
}
|
|
44
58
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import assert from 'assert'
|
|
2
1
|
import { describe, it, beforeEach, afterEach } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
3
3
|
import chalk from 'chalk'
|
|
4
|
+
import { AbstractModule } from 'adapt-authoring-core'
|
|
4
5
|
import LoggerModule from '../lib/LoggerModule.js'
|
|
5
6
|
|
|
6
7
|
describe('LoggerModule', () => {
|
|
7
|
-
describe('colourise()', () => {
|
|
8
|
+
describe('#colourise()', () => {
|
|
8
9
|
it('should return string with colour function applied', () => {
|
|
9
10
|
const result = LoggerModule.colourise('test', chalk.red)
|
|
10
11
|
assert.ok(result.includes('test'))
|
|
@@ -17,20 +18,30 @@ describe('LoggerModule', () => {
|
|
|
17
18
|
|
|
18
19
|
it('should return uncoloured string if no colour function provided', () => {
|
|
19
20
|
const result = LoggerModule.colourise('test', null)
|
|
20
|
-
assert.
|
|
21
|
+
assert.equal(result, 'test')
|
|
21
22
|
})
|
|
22
23
|
|
|
23
24
|
it('should handle undefined colour function', () => {
|
|
24
25
|
const result = LoggerModule.colourise('test', undefined)
|
|
25
|
-
assert.
|
|
26
|
+
assert.equal(result, 'test')
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it('should return empty string unchanged when no colour', () => {
|
|
30
|
+
const result = LoggerModule.colourise('', null)
|
|
31
|
+
assert.equal(result, '')
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
it('should apply colour function to empty string', () => {
|
|
35
|
+
const result = LoggerModule.colourise('', chalk.red)
|
|
36
|
+
assert.equal(typeof result, 'string')
|
|
26
37
|
})
|
|
27
38
|
})
|
|
28
39
|
|
|
29
|
-
describe('getDateStamp()', () => {
|
|
40
|
+
describe('#getDateStamp()', () => {
|
|
30
41
|
it('should return empty string when timestamp is disabled', () => {
|
|
31
42
|
const config = { timestamp: false }
|
|
32
43
|
const result = LoggerModule.getDateStamp(config)
|
|
33
|
-
assert.
|
|
44
|
+
assert.equal(result, '')
|
|
34
45
|
})
|
|
35
46
|
|
|
36
47
|
it('should return ISO format date when dateFormat is "iso"', () => {
|
|
@@ -42,11 +53,23 @@ describe('LoggerModule', () => {
|
|
|
42
53
|
it('should return short format date when dateFormat is "short"', () => {
|
|
43
54
|
const config = { timestamp: true, dateFormat: 'short' }
|
|
44
55
|
const result = LoggerModule.getDateStamp(config)
|
|
45
|
-
assert.ok(/\d{1,2}\/\d{2}\/\d{2}-\d{2}:\d{2}:\d{2}/.test(result))
|
|
56
|
+
assert.ok(/\d{1,2}\/\d{2}\/\d{2}-\d{1,2}:\d{1,2}:\d{2}/.test(result))
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('should return undefined-based string for unrecognised dateFormat', () => {
|
|
60
|
+
const config = { timestamp: true, dateFormat: 'unknown' }
|
|
61
|
+
const result = LoggerModule.getDateStamp(config)
|
|
62
|
+
assert.ok(result.includes('undefined'))
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
it('should include trailing space in formatted timestamp', () => {
|
|
66
|
+
const config = { timestamp: true, dateFormat: 'iso' }
|
|
67
|
+
const result = LoggerModule.getDateStamp(config)
|
|
68
|
+
assert.ok(result.includes(' '))
|
|
46
69
|
})
|
|
47
70
|
})
|
|
48
71
|
|
|
49
|
-
describe('isLevelEnabled()', () => {
|
|
72
|
+
describe('#isLevelEnabled()', () => {
|
|
50
73
|
let logger
|
|
51
74
|
|
|
52
75
|
beforeEach(() => {
|
|
@@ -55,28 +78,39 @@ describe('LoggerModule', () => {
|
|
|
55
78
|
})
|
|
56
79
|
|
|
57
80
|
it('should return true for enabled levels', () => {
|
|
58
|
-
assert.
|
|
59
|
-
assert.
|
|
60
|
-
assert.
|
|
81
|
+
assert.equal(logger.isLevelEnabled('error'), true)
|
|
82
|
+
assert.equal(logger.isLevelEnabled('warn'), true)
|
|
83
|
+
assert.equal(logger.isLevelEnabled('info'), true)
|
|
61
84
|
})
|
|
62
85
|
|
|
63
86
|
it('should return false for disabled levels', () => {
|
|
64
|
-
assert.
|
|
65
|
-
assert.
|
|
87
|
+
assert.equal(logger.isLevelEnabled('debug'), false)
|
|
88
|
+
assert.equal(logger.isLevelEnabled('verbose'), false)
|
|
66
89
|
})
|
|
67
90
|
|
|
68
91
|
it('should return false when level is explicitly disabled', () => {
|
|
69
92
|
logger.levelsConfig = ['error', '!warn', 'info']
|
|
70
|
-
assert.
|
|
93
|
+
assert.equal(logger.isLevelEnabled('warn'), false)
|
|
71
94
|
})
|
|
72
95
|
|
|
73
96
|
it('should give preference to explicit disable', () => {
|
|
74
97
|
logger.levelsConfig = ['warn', '!warn']
|
|
75
|
-
assert.
|
|
98
|
+
assert.equal(logger.isLevelEnabled('warn'), false)
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
it('should return false for empty levelsConfig', () => {
|
|
102
|
+
logger.levelsConfig = []
|
|
103
|
+
assert.equal(logger.isLevelEnabled('error'), false)
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
it('should not match partial level names', () => {
|
|
107
|
+
logger.levelsConfig = ['info']
|
|
108
|
+
assert.equal(logger.isLevelEnabled('inf'), false)
|
|
109
|
+
assert.equal(logger.isLevelEnabled('information'), false)
|
|
76
110
|
})
|
|
77
111
|
})
|
|
78
112
|
|
|
79
|
-
describe('getModuleOverrides()', () => {
|
|
113
|
+
describe('#getModuleOverrides()', () => {
|
|
80
114
|
let logger
|
|
81
115
|
|
|
82
116
|
beforeEach(() => {
|
|
@@ -88,7 +122,7 @@ describe('LoggerModule', () => {
|
|
|
88
122
|
const result = logger.getModuleOverrides('error')
|
|
89
123
|
assert.ok(result.includes('error.myModule'))
|
|
90
124
|
assert.ok(result.includes('error.anotherModule'))
|
|
91
|
-
assert.
|
|
125
|
+
assert.equal(result.length, 2)
|
|
92
126
|
})
|
|
93
127
|
|
|
94
128
|
it('should include negative overrides', () => {
|
|
@@ -100,7 +134,7 @@ describe('LoggerModule', () => {
|
|
|
100
134
|
it('should return empty array when no overrides exist', () => {
|
|
101
135
|
logger.levelsConfig = ['error', 'warn']
|
|
102
136
|
const result = logger.getModuleOverrides('info')
|
|
103
|
-
assert.
|
|
137
|
+
assert.equal(result.length, 0)
|
|
104
138
|
})
|
|
105
139
|
|
|
106
140
|
it('should not include overrides for other levels', () => {
|
|
@@ -108,9 +142,23 @@ describe('LoggerModule', () => {
|
|
|
108
142
|
const result = logger.getModuleOverrides('error')
|
|
109
143
|
assert.ok(!result.includes('warn.moduleB'))
|
|
110
144
|
})
|
|
145
|
+
|
|
146
|
+
it('should return both positive and negative overrides together', () => {
|
|
147
|
+
logger.levelsConfig = ['error', 'error.modA', '!error.modB']
|
|
148
|
+
const result = logger.getModuleOverrides('error')
|
|
149
|
+
assert.equal(result.length, 2)
|
|
150
|
+
assert.ok(result.includes('error.modA'))
|
|
151
|
+
assert.ok(result.includes('!error.modB'))
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
it('should return empty array for empty levelsConfig', () => {
|
|
155
|
+
logger.levelsConfig = []
|
|
156
|
+
const result = logger.getModuleOverrides('error')
|
|
157
|
+
assert.deepEqual(result, [])
|
|
158
|
+
})
|
|
111
159
|
})
|
|
112
160
|
|
|
113
|
-
describe('isLoggingEnabled()', () => {
|
|
161
|
+
describe('#isLoggingEnabled()', () => {
|
|
114
162
|
let logger
|
|
115
163
|
|
|
116
164
|
beforeEach(() => {
|
|
@@ -125,31 +173,54 @@ describe('LoggerModule', () => {
|
|
|
125
173
|
})
|
|
126
174
|
|
|
127
175
|
it('should return true for enabled levels', () => {
|
|
128
|
-
assert.
|
|
176
|
+
assert.equal(logger.isLoggingEnabled('error', 'anyId'), true)
|
|
129
177
|
})
|
|
130
178
|
|
|
131
179
|
it('should return false for disabled levels without overrides', () => {
|
|
132
|
-
assert.
|
|
180
|
+
assert.equal(logger.isLoggingEnabled('warn', 'generic'), false)
|
|
133
181
|
})
|
|
134
182
|
|
|
135
183
|
it('should return true for disabled level with positive override', () => {
|
|
136
|
-
assert.
|
|
184
|
+
assert.equal(logger.isLoggingEnabled('warn', 'specific'), true)
|
|
137
185
|
})
|
|
138
186
|
|
|
139
187
|
it('should return false for enabled level with negative override', () => {
|
|
140
|
-
assert.
|
|
188
|
+
assert.equal(logger.isLoggingEnabled('info', 'blocked'), false)
|
|
141
189
|
})
|
|
142
190
|
|
|
143
191
|
it('should return true for enabled level without override', () => {
|
|
144
|
-
assert.
|
|
192
|
+
assert.equal(logger.isLoggingEnabled('info', 'allowed'), true)
|
|
145
193
|
})
|
|
146
194
|
|
|
147
195
|
it('should handle missing level config gracefully', () => {
|
|
148
|
-
assert.
|
|
196
|
+
assert.equal(logger.isLoggingEnabled('nonexistent', 'id'), false)
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
it('should default moduleOverrides to empty array when undefined', () => {
|
|
200
|
+
logger.config = {
|
|
201
|
+
levels: {
|
|
202
|
+
error: { enable: true }
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
assert.equal(logger.isLoggingEnabled('error', 'anyId'), true)
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
it('should return false when both enable is false and no matching override', () => {
|
|
209
|
+
logger.config = {
|
|
210
|
+
levels: {
|
|
211
|
+
debug: { enable: false, moduleOverrides: ['debug.other'] }
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
assert.equal(logger.isLoggingEnabled('debug', 'notOther'), false)
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
it('should handle config being undefined gracefully', () => {
|
|
218
|
+
logger.config = undefined
|
|
219
|
+
assert.equal(logger.isLoggingEnabled('error', 'id'), false)
|
|
149
220
|
})
|
|
150
221
|
})
|
|
151
222
|
|
|
152
|
-
describe('log()', () => {
|
|
223
|
+
describe('#log()', () => {
|
|
153
224
|
let logger
|
|
154
225
|
let logOutput
|
|
155
226
|
let originalConsoleLog
|
|
@@ -184,24 +255,24 @@ describe('LoggerModule', () => {
|
|
|
184
255
|
it('should not log when muted', () => {
|
|
185
256
|
logger.config.mute = true
|
|
186
257
|
logger.log('info', 'test', 'message')
|
|
187
|
-
assert.
|
|
258
|
+
assert.equal(logOutput.length, 0)
|
|
188
259
|
})
|
|
189
260
|
|
|
190
261
|
it('should not log when level is disabled', () => {
|
|
191
262
|
logger.config.levels.debug.enable = false
|
|
192
263
|
logger.log('debug', 'test', 'message')
|
|
193
|
-
assert.
|
|
264
|
+
assert.equal(logOutput.length, 0)
|
|
194
265
|
})
|
|
195
266
|
|
|
196
267
|
it('should log message when enabled', () => {
|
|
197
268
|
logger.log('info', 'testId', 'test message')
|
|
198
|
-
assert.
|
|
269
|
+
assert.equal(logOutput.length, 1)
|
|
199
270
|
assert.ok(logOutput[0].args.some(arg => typeof arg === 'string' && arg.includes('testId')))
|
|
200
271
|
})
|
|
201
272
|
|
|
202
273
|
it('should include multiple arguments', () => {
|
|
203
274
|
logger.log('info', 'test', 'arg1', 'arg2', 'arg3')
|
|
204
|
-
assert.
|
|
275
|
+
assert.equal(logOutput.length, 1)
|
|
205
276
|
const args = logOutput[0].args
|
|
206
277
|
assert.ok(args.includes('arg1'))
|
|
207
278
|
assert.ok(args.includes('arg2'))
|
|
@@ -210,7 +281,7 @@ describe('LoggerModule', () => {
|
|
|
210
281
|
|
|
211
282
|
it('should use correct console method for level', () => {
|
|
212
283
|
logger.log('error', 'test', 'message')
|
|
213
|
-
assert.
|
|
284
|
+
assert.equal(logOutput[0].level, 'error')
|
|
214
285
|
})
|
|
215
286
|
|
|
216
287
|
it('should invoke logHook with correct parameters', () => {
|
|
@@ -220,21 +291,73 @@ describe('LoggerModule', () => {
|
|
|
220
291
|
}
|
|
221
292
|
logger.log('info', 'testId', 'message')
|
|
222
293
|
assert.ok(hookArgs)
|
|
223
|
-
assert.
|
|
224
|
-
assert.
|
|
225
|
-
assert.
|
|
294
|
+
assert.equal(hookArgs[1], 'info')
|
|
295
|
+
assert.equal(hookArgs[2], 'testId')
|
|
296
|
+
assert.equal(hookArgs[3], 'message')
|
|
226
297
|
})
|
|
227
298
|
|
|
228
299
|
it('should colorise level in output', () => {
|
|
229
300
|
logger.log('info', 'test', 'message')
|
|
230
|
-
assert.
|
|
301
|
+
assert.equal(logOutput.length, 1)
|
|
231
302
|
assert.ok(logOutput[0].args[0].includes('info'))
|
|
232
303
|
})
|
|
233
304
|
|
|
234
305
|
it('should colorise id in output', () => {
|
|
235
306
|
logger.log('info', 'myModule', 'message')
|
|
236
|
-
assert.
|
|
307
|
+
assert.equal(logOutput.length, 1)
|
|
237
308
|
assert.ok(logOutput[0].args[0].includes('myModule'))
|
|
238
309
|
})
|
|
310
|
+
|
|
311
|
+
it('should treat string "true" mute value as muted', () => {
|
|
312
|
+
logger.config.mute = 'true'
|
|
313
|
+
logger.log('info', 'test', 'message')
|
|
314
|
+
assert.equal(logOutput.length, 0)
|
|
315
|
+
})
|
|
316
|
+
|
|
317
|
+
it('should not mute when mute is "false"', () => {
|
|
318
|
+
logger.config.mute = 'false'
|
|
319
|
+
logger.log('info', 'test', 'message')
|
|
320
|
+
assert.equal(logOutput.length, 1)
|
|
321
|
+
})
|
|
322
|
+
|
|
323
|
+
it('should fall back to console.log for unknown level', () => {
|
|
324
|
+
logger.config.levels.success = { enable: true, moduleOverrides: [], colour: chalk.green }
|
|
325
|
+
logger.log('success', 'test', 'message')
|
|
326
|
+
assert.equal(logOutput.length, 1)
|
|
327
|
+
assert.equal(logOutput[0].level, 'log')
|
|
328
|
+
})
|
|
329
|
+
|
|
330
|
+
it('should handle MODULE_READY id by using module name suffix', () => {
|
|
331
|
+
logger.name = 'adapt-authoring-logger'
|
|
332
|
+
logger.config.levels.verbose = { enable: true, moduleOverrides: [], colour: chalk.grey }
|
|
333
|
+
let hookArgs = null
|
|
334
|
+
logger.logHook.invoke = (...args) => { hookArgs = args }
|
|
335
|
+
logger.log('verbose', AbstractModule.MODULE_READY, 'some-init-time')
|
|
336
|
+
assert.equal(logOutput.length, 1)
|
|
337
|
+
assert.ok(logOutput[0].args[0].includes('logger'))
|
|
338
|
+
assert.equal(hookArgs[2], 'logger')
|
|
339
|
+
assert.equal(hookArgs[3], AbstractModule.MODULE_READY)
|
|
340
|
+
assert.equal(hookArgs[4], 'some-init-time')
|
|
341
|
+
})
|
|
342
|
+
|
|
343
|
+
it('should prepend date stamp when timestamp is enabled', () => {
|
|
344
|
+
logger.config.timestamp = true
|
|
345
|
+
logger.config.dateFormat = 'iso'
|
|
346
|
+
logger.log('info', 'test', 'message')
|
|
347
|
+
assert.equal(logOutput.length, 1)
|
|
348
|
+
assert.ok(/\d{4}-\d{2}-\d{2}T/.test(logOutput[0].args[0]))
|
|
349
|
+
})
|
|
350
|
+
|
|
351
|
+
it('should pass Date as first argument to logHook', () => {
|
|
352
|
+
let hookArgs = null
|
|
353
|
+
logger.logHook.invoke = (...args) => { hookArgs = args }
|
|
354
|
+
logger.log('info', 'test', 'message')
|
|
355
|
+
assert.ok(hookArgs[0] instanceof Date)
|
|
356
|
+
})
|
|
357
|
+
|
|
358
|
+
it('should handle config being undefined gracefully', () => {
|
|
359
|
+
logger.config = undefined
|
|
360
|
+
assert.doesNotThrow(() => logger.log('info', 'test', 'message'))
|
|
361
|
+
})
|
|
239
362
|
})
|
|
240
363
|
})
|