Skip to content

Commit 80ace20

Browse files
authored
New: Add tests (fixes #26) (#27)
2 parents 0d8ffbf + cf0de07 commit 80ace20

File tree

3 files changed

+258
-2
lines changed

3 files changed

+258
-2
lines changed

.github/workflows/tests.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
name: Run test scripts
2+
on: push
3+
jobs:
4+
default:
5+
runs-on: ubuntu-latest
6+
steps:
7+
- uses: actions/checkout@master
8+
- uses: actions/setup-node@master
9+
with:
10+
node-version: 'lts/*'
11+
cache: 'npm'
12+
- run: npm ci
13+
- run: npm test

package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@
1414
"adapt-authoring-core": "^1.0.0"
1515
},
1616
"devDependencies": {
17-
"standard": "^17.1.0",
1817
"@semantic-release/commit-analyzer": "^9.0.2",
1918
"@semantic-release/git": "^10.0.1",
2019
"@semantic-release/github": "^8.0.5",
2120
"@semantic-release/npm": "^9.0.1",
2221
"@semantic-release/release-notes-generator": "^10.0.3",
2322
"conventional-changelog-eslint": "^3.0.9",
2423
"semantic-release": "^21.0.1",
25-
"semantic-release-replace-plugin": "^1.2.7"
24+
"semantic-release-replace-plugin": "^1.2.7",
25+
"standard": "^17.1.0"
2626
},
2727
"release": {
2828
"plugins": [
@@ -50,5 +50,8 @@
5050
}
5151
]
5252
]
53+
},
54+
"scripts": {
55+
"test": "node --test"
5356
}
5457
}

test/LoggerModule.test.js

Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
import assert from 'assert'
2+
import { describe, it, beforeEach, afterEach } from 'node:test'
3+
import chalk from 'chalk'
4+
import LoggerModule from '../lib/LoggerModule.js'
5+
6+
describe('LoggerModule', () => {
7+
describe('colourise()', () => {
8+
it('should return string with colour function applied', () => {
9+
const result = LoggerModule.colourise('test', chalk.red)
10+
assert.ok(result.includes('test'))
11+
})
12+
13+
it('should accept colour name as string', () => {
14+
const result = LoggerModule.colourise('test', 'green')
15+
assert.ok(result.includes('test'))
16+
})
17+
18+
it('should return uncoloured string if no colour function provided', () => {
19+
const result = LoggerModule.colourise('test', null)
20+
assert.strictEqual(result, 'test')
21+
})
22+
23+
it('should handle undefined colour function', () => {
24+
const result = LoggerModule.colourise('test', undefined)
25+
assert.strictEqual(result, 'test')
26+
})
27+
})
28+
29+
describe('getDateStamp()', () => {
30+
it('should return empty string when timestamp is disabled', () => {
31+
const config = { timestamp: false }
32+
const result = LoggerModule.getDateStamp(config)
33+
assert.strictEqual(result, '')
34+
})
35+
36+
it('should return ISO format date when dateFormat is "iso"', () => {
37+
const config = { timestamp: true, dateFormat: 'iso' }
38+
const result = LoggerModule.getDateStamp(config)
39+
assert.ok(/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(result))
40+
})
41+
42+
it('should return short format date when dateFormat is "short"', () => {
43+
const config = { timestamp: true, dateFormat: 'short' }
44+
const result = LoggerModule.getDateStamp(config)
45+
assert.ok(/\d{1,2}\/\d{2}\/\d{2}-\d{2}:\d{2}:\d{2}/.test(result))
46+
})
47+
})
48+
49+
describe('isLevelEnabled()', () => {
50+
let logger
51+
52+
beforeEach(() => {
53+
logger = new LoggerModule('test-logger')
54+
logger.levelsConfig = ['error', 'warn', 'info']
55+
})
56+
57+
it('should return true for enabled levels', () => {
58+
assert.strictEqual(logger.isLevelEnabled('error'), true)
59+
assert.strictEqual(logger.isLevelEnabled('warn'), true)
60+
assert.strictEqual(logger.isLevelEnabled('info'), true)
61+
})
62+
63+
it('should return false for disabled levels', () => {
64+
assert.strictEqual(logger.isLevelEnabled('debug'), false)
65+
assert.strictEqual(logger.isLevelEnabled('verbose'), false)
66+
})
67+
68+
it('should return false when level is explicitly disabled', () => {
69+
logger.levelsConfig = ['error', '!warn', 'info']
70+
assert.strictEqual(logger.isLevelEnabled('warn'), false)
71+
})
72+
73+
it('should give preference to explicit disable', () => {
74+
logger.levelsConfig = ['warn', '!warn']
75+
assert.strictEqual(logger.isLevelEnabled('warn'), false)
76+
})
77+
})
78+
79+
describe('getModuleOverrides()', () => {
80+
let logger
81+
82+
beforeEach(() => {
83+
logger = new LoggerModule('test-logger')
84+
})
85+
86+
it('should return module-specific overrides for a level', () => {
87+
logger.levelsConfig = ['error', 'error.myModule', 'error.anotherModule', 'warn']
88+
const result = logger.getModuleOverrides('error')
89+
assert.ok(result.includes('error.myModule'))
90+
assert.ok(result.includes('error.anotherModule'))
91+
assert.strictEqual(result.length, 2)
92+
})
93+
94+
it('should include negative overrides', () => {
95+
logger.levelsConfig = ['error', '!error.myModule']
96+
const result = logger.getModuleOverrides('error')
97+
assert.ok(result.includes('!error.myModule'))
98+
})
99+
100+
it('should return empty array when no overrides exist', () => {
101+
logger.levelsConfig = ['error', 'warn']
102+
const result = logger.getModuleOverrides('info')
103+
assert.strictEqual(result.length, 0)
104+
})
105+
106+
it('should not include overrides for other levels', () => {
107+
logger.levelsConfig = ['error', 'error.moduleA', 'warn.moduleB']
108+
const result = logger.getModuleOverrides('error')
109+
assert.ok(!result.includes('warn.moduleB'))
110+
})
111+
})
112+
113+
describe('isLoggingEnabled()', () => {
114+
let logger
115+
116+
beforeEach(() => {
117+
logger = new LoggerModule('test-logger')
118+
logger.config = {
119+
levels: {
120+
error: { enable: true, moduleOverrides: [] },
121+
warn: { enable: false, moduleOverrides: ['warn.specific'] },
122+
info: { enable: true, moduleOverrides: ['!info.blocked'] }
123+
}
124+
}
125+
})
126+
127+
it('should return true for enabled levels', () => {
128+
assert.strictEqual(logger.isLoggingEnabled('error', 'anyId'), true)
129+
})
130+
131+
it('should return false for disabled levels without overrides', () => {
132+
assert.strictEqual(logger.isLoggingEnabled('warn', 'generic'), false)
133+
})
134+
135+
it('should return true for disabled level with positive override', () => {
136+
assert.strictEqual(logger.isLoggingEnabled('warn', 'specific'), true)
137+
})
138+
139+
it('should return false for enabled level with negative override', () => {
140+
assert.strictEqual(logger.isLoggingEnabled('info', 'blocked'), false)
141+
})
142+
143+
it('should return true for enabled level without override', () => {
144+
assert.strictEqual(logger.isLoggingEnabled('info', 'allowed'), true)
145+
})
146+
147+
it('should handle missing level config gracefully', () => {
148+
assert.strictEqual(logger.isLoggingEnabled('nonexistent', 'id'), false)
149+
})
150+
})
151+
152+
describe('log()', () => {
153+
let logger
154+
let logOutput
155+
let originalConsoleLog
156+
157+
beforeEach(() => {
158+
logger = new LoggerModule('test-logger')
159+
logger.config = {
160+
levels: {
161+
error: { enable: true, moduleOverrides: [], colour: chalk.red },
162+
warn: { enable: true, moduleOverrides: [], colour: chalk.yellow },
163+
info: { enable: true, moduleOverrides: [], colour: chalk.cyan },
164+
debug: { enable: true, moduleOverrides: [], colour: chalk.dim }
165+
},
166+
timestamp: false,
167+
dateFormat: 'iso',
168+
mute: false
169+
}
170+
logger.logHook = { invoke: () => {} }
171+
logOutput = []
172+
173+
originalConsoleLog = console.log
174+
console.log = (...args) => logOutput.push({ level: 'log', args })
175+
console.error = (...args) => logOutput.push({ level: 'error', args })
176+
console.warn = (...args) => logOutput.push({ level: 'warn', args })
177+
console.info = (...args) => logOutput.push({ level: 'info', args })
178+
})
179+
180+
afterEach(() => {
181+
console.log = originalConsoleLog
182+
})
183+
184+
it('should not log when muted', () => {
185+
logger.config.mute = true
186+
logger.log('info', 'test', 'message')
187+
assert.strictEqual(logOutput.length, 0)
188+
})
189+
190+
it('should not log when level is disabled', () => {
191+
logger.config.levels.debug.enable = false
192+
logger.log('debug', 'test', 'message')
193+
assert.strictEqual(logOutput.length, 0)
194+
})
195+
196+
it('should log message when enabled', () => {
197+
logger.log('info', 'testId', 'test message')
198+
assert.strictEqual(logOutput.length, 1)
199+
assert.ok(logOutput[0].args.some(arg => typeof arg === 'string' && arg.includes('testId')))
200+
})
201+
202+
it('should include multiple arguments', () => {
203+
logger.log('info', 'test', 'arg1', 'arg2', 'arg3')
204+
assert.strictEqual(logOutput.length, 1)
205+
const args = logOutput[0].args
206+
assert.ok(args.includes('arg1'))
207+
assert.ok(args.includes('arg2'))
208+
assert.ok(args.includes('arg3'))
209+
})
210+
211+
it('should use correct console method for level', () => {
212+
logger.log('error', 'test', 'message')
213+
assert.strictEqual(logOutput[0].level, 'error')
214+
})
215+
216+
it('should invoke logHook with correct parameters', () => {
217+
let hookArgs = null
218+
logger.logHook.invoke = (...args) => {
219+
hookArgs = args
220+
}
221+
logger.log('info', 'testId', 'message')
222+
assert.ok(hookArgs)
223+
assert.strictEqual(hookArgs[1], 'info')
224+
assert.strictEqual(hookArgs[2], 'testId')
225+
assert.strictEqual(hookArgs[3], 'message')
226+
})
227+
228+
it('should colorise level in output', () => {
229+
logger.log('info', 'test', 'message')
230+
assert.strictEqual(logOutput.length, 1)
231+
assert.ok(logOutput[0].args[0].includes('info'))
232+
})
233+
234+
it('should colorise id in output', () => {
235+
logger.log('info', 'myModule', 'message')
236+
assert.strictEqual(logOutput.length, 1)
237+
assert.ok(logOutput[0].args[0].includes('myModule'))
238+
})
239+
})
240+
})

0 commit comments

Comments
 (0)