@xiboplayer/utils 0.1.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/src/logger.js ADDED
@@ -0,0 +1,237 @@
1
+ /**
2
+ * Configurable Logger for Xibo Players
3
+ *
4
+ * Supports log levels: DEBUG, INFO, WARNING, ERROR, NONE
5
+ *
6
+ * Level precedence (highest wins):
7
+ * 1. URL param ?logLevel=DEBUG
8
+ * 2. localStorage xibo_log_level
9
+ * 3. CMS setting via RegisterDisplay (call applyCmsLogLevel())
10
+ * 4. Default: DEBUG on localhost, INFO in production
11
+ *
12
+ * Loggers created without an explicit level are REACTIVE — they follow
13
+ * the global level at call time, so setLogLevel() affects all of them.
14
+ */
15
+
16
+ const LOG_LEVELS = {
17
+ DEBUG: 0,
18
+ INFO: 1,
19
+ WARNING: 2,
20
+ ERROR: 3,
21
+ NONE: 4
22
+ };
23
+
24
+ // Log sink system — external consumers (e.g., LogReporter) can intercept all log output
25
+ const logSinks = [];
26
+
27
+ class Logger {
28
+ /**
29
+ * @param {string} name - Logger name (shown in prefix)
30
+ * @param {string|null} level - Explicit level string, or null to follow global
31
+ */
32
+ constructor(name, level = null) {
33
+ this.name = name;
34
+ this.useGlobal = (level === null);
35
+ if (!this.useGlobal) {
36
+ this.setLevel(level);
37
+ }
38
+ }
39
+
40
+ setLevel(level) {
41
+ this.useGlobal = false;
42
+ if (typeof level === 'string') {
43
+ this.level = LOG_LEVELS[level.toUpperCase()] ?? LOG_LEVELS.INFO;
44
+ } else {
45
+ this.level = level;
46
+ }
47
+ }
48
+
49
+ /** Effective level: own override or global */
50
+ getEffectiveLevel() {
51
+ return this.useGlobal ? globalConfig.level : this.level;
52
+ }
53
+
54
+ debug(...args) {
55
+ if (this.getEffectiveLevel() <= LOG_LEVELS.DEBUG) {
56
+ console.log(`[${this.name}] DEBUG:`, ...args);
57
+ }
58
+ _dispatchToSinks('debug', this.name, args);
59
+ }
60
+
61
+ info(...args) {
62
+ if (this.getEffectiveLevel() <= LOG_LEVELS.INFO) {
63
+ console.log(`[${this.name}]`, ...args);
64
+ }
65
+ _dispatchToSinks('info', this.name, args);
66
+ }
67
+
68
+ warn(...args) {
69
+ if (this.getEffectiveLevel() <= LOG_LEVELS.WARNING) {
70
+ console.warn(`[${this.name}]`, ...args);
71
+ }
72
+ _dispatchToSinks('warning', this.name, args);
73
+ }
74
+
75
+ error(...args) {
76
+ if (this.getEffectiveLevel() <= LOG_LEVELS.ERROR) {
77
+ console.error(`[${this.name}]`, ...args);
78
+ }
79
+ _dispatchToSinks('error', this.name, args);
80
+ }
81
+
82
+ // Convenience method for conditional logging
83
+ log(level, ...args) {
84
+ switch (level.toUpperCase()) {
85
+ case 'DEBUG': return this.debug(...args);
86
+ case 'INFO': return this.info(...args);
87
+ case 'WARNING':
88
+ case 'WARN': return this.warn(...args);
89
+ case 'ERROR': return this.error(...args);
90
+ }
91
+ }
92
+ }
93
+
94
+ // Global log level configuration
95
+ const globalConfig = {
96
+ level: LOG_LEVELS.INFO, // Default: INFO and above
97
+
98
+ setGlobalLevel(level) {
99
+ if (typeof level === 'string') {
100
+ this.level = LOG_LEVELS[level.toUpperCase()] ?? LOG_LEVELS.INFO;
101
+ } else {
102
+ this.level = level;
103
+ }
104
+
105
+ console.log(`[Logger] Global log level set to: ${this.getLevelName(this.level)}`);
106
+ },
107
+
108
+ getLevelName(level) {
109
+ return Object.keys(LOG_LEVELS).find(key => LOG_LEVELS[key] === level) || 'UNKNOWN';
110
+ }
111
+ };
112
+
113
+ // Track whether the level was set by a local override (URL param / localStorage)
114
+ let hasLocalOverride = false;
115
+
116
+ // Set global level from environment or localStorage
117
+ if (typeof window !== 'undefined') {
118
+ const urlParams = new URLSearchParams(window.location.search);
119
+ const urlLevel = urlParams.get('logLevel');
120
+ const storageLevel = localStorage.getItem('xibo_log_level');
121
+
122
+ if (urlLevel) {
123
+ globalConfig.setGlobalLevel(urlLevel);
124
+ hasLocalOverride = true;
125
+ } else if (storageLevel) {
126
+ globalConfig.setGlobalLevel(storageLevel);
127
+ hasLocalOverride = true;
128
+ } else if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') {
129
+ // Development mode - debug logging
130
+ globalConfig.setGlobalLevel('DEBUG');
131
+ } else {
132
+ // Production mode - INFO by default (CMS can override later)
133
+ globalConfig.setGlobalLevel('INFO');
134
+ }
135
+ }
136
+
137
+ // Factory function — loggers follow global level by default (reactive)
138
+ export function createLogger(name, level = null) {
139
+ return new Logger(name, level);
140
+ }
141
+
142
+ // Set global log level (and persist to localStorage)
143
+ export function setLogLevel(level) {
144
+ globalConfig.setGlobalLevel(level);
145
+
146
+ // Save to localStorage
147
+ if (typeof window !== 'undefined') {
148
+ localStorage.setItem('xibo_log_level', level.toUpperCase());
149
+ }
150
+ }
151
+
152
+ // Get current log level name
153
+ export function getLogLevel() {
154
+ return globalConfig.getLevelName(globalConfig.level);
155
+ }
156
+
157
+ /**
158
+ * Returns true when the effective global level is DEBUG.
159
+ * Use this for conditional debug features (video controls, overlays, etc.)
160
+ */
161
+ export function isDebug() {
162
+ return globalConfig.level <= LOG_LEVELS.DEBUG;
163
+ }
164
+
165
+ /**
166
+ * Apply CMS logLevel setting — only if no local override (URL/localStorage) exists.
167
+ * @param {string} cmsLevel - CMS level string: 'error', 'audit', 'info', 'debug'
168
+ * @returns {boolean} true if the level was applied
169
+ */
170
+ export function applyCmsLogLevel(cmsLevel) {
171
+ if (hasLocalOverride) return false;
172
+ if (!cmsLevel) return false;
173
+
174
+ const mapped = mapCmsLogLevel(cmsLevel);
175
+ globalConfig.setGlobalLevel(mapped);
176
+ return true;
177
+ }
178
+
179
+ /**
180
+ * Map CMS logLevel strings to internal level names.
181
+ * CMS uses: 'emergency','alert','critical','error','warning','notice','info','debug','audit'
182
+ * We collapse them to our 4 levels.
183
+ */
184
+ export function mapCmsLogLevel(cmsLevel) {
185
+ switch ((cmsLevel || '').toLowerCase()) {
186
+ case 'debug':
187
+ return 'DEBUG';
188
+ case 'info':
189
+ case 'notice':
190
+ case 'audit':
191
+ return 'INFO';
192
+ case 'warning':
193
+ return 'WARNING';
194
+ case 'error':
195
+ case 'critical':
196
+ case 'alert':
197
+ case 'emergency':
198
+ return 'ERROR';
199
+ default:
200
+ return 'INFO';
201
+ }
202
+ }
203
+
204
+ /**
205
+ * Dispatch log entry to all registered sinks.
206
+ * Sinks receive { level, name, args } and should not throw.
207
+ * @private
208
+ */
209
+ function _dispatchToSinks(level, name, args) {
210
+ if (logSinks.length === 0) return;
211
+ for (const fn of logSinks) {
212
+ try {
213
+ fn({ level, name, args });
214
+ } catch (_) {
215
+ // Sink errors must never break logging
216
+ }
217
+ }
218
+ }
219
+
220
+ /**
221
+ * Register a log sink — receives all log output regardless of level filtering.
222
+ * @param {function} fn - Callback: ({ level, name, args }) => void
223
+ */
224
+ export function registerLogSink(fn) {
225
+ logSinks.push(fn);
226
+ }
227
+
228
+ /**
229
+ * Unregister a previously registered log sink.
230
+ * @param {function} fn - The same function reference passed to registerLogSink
231
+ */
232
+ export function unregisterLogSink(fn) {
233
+ const idx = logSinks.indexOf(fn);
234
+ if (idx >= 0) logSinks.splice(idx, 1);
235
+ }
236
+
237
+ export { LOG_LEVELS };
@@ -0,0 +1,477 @@
1
+ /**
2
+ * Logger Tests
3
+ *
4
+ * Tests for configurable logging with log levels
5
+ */
6
+
7
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
8
+ import { createLogger, setLogLevel, getLogLevel, LOG_LEVELS } from './logger.js';
9
+
10
+ describe('Logger', () => {
11
+ let consoleLogSpy;
12
+ let consoleWarnSpy;
13
+ let consoleErrorSpy;
14
+
15
+ beforeEach(() => {
16
+ consoleLogSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
17
+ consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
18
+ consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
19
+ });
20
+
21
+ afterEach(() => {
22
+ vi.restoreAllMocks();
23
+ });
24
+
25
+ describe('Log Levels', () => {
26
+ it('should have correct log level hierarchy', () => {
27
+ expect(LOG_LEVELS.DEBUG).toBe(0);
28
+ expect(LOG_LEVELS.INFO).toBe(1);
29
+ expect(LOG_LEVELS.WARNING).toBe(2);
30
+ expect(LOG_LEVELS.ERROR).toBe(3);
31
+ expect(LOG_LEVELS.NONE).toBe(4);
32
+ });
33
+ });
34
+
35
+ describe('Logger Creation', () => {
36
+ it('should create logger with default INFO level', () => {
37
+ const logger = createLogger('TestModule');
38
+
39
+ expect(logger.name).toBe('TestModule');
40
+ // When no explicit level is given, logger follows global level (useGlobal=true)
41
+ // so logger.level is undefined — check getEffectiveLevel() instead
42
+ expect(logger.getEffectiveLevel()).toBeLessThanOrEqual(LOG_LEVELS.INFO);
43
+ });
44
+
45
+ it('should create logger with custom level', () => {
46
+ const logger = createLogger('TestModule', 'DEBUG');
47
+
48
+ expect(logger.level).toBe(LOG_LEVELS.DEBUG);
49
+ });
50
+
51
+ it('should create logger with numeric level', () => {
52
+ const logger = createLogger('TestModule', LOG_LEVELS.WARNING);
53
+
54
+ expect(logger.level).toBe(LOG_LEVELS.WARNING);
55
+ });
56
+ });
57
+
58
+ describe('debug()', () => {
59
+ it('should log at DEBUG level', () => {
60
+ const logger = createLogger('Test', 'DEBUG');
61
+
62
+ logger.debug('Debug message', { data: 'value' });
63
+
64
+ expect(consoleLogSpy).toHaveBeenCalledWith(
65
+ '[Test] DEBUG:',
66
+ 'Debug message',
67
+ { data: 'value' }
68
+ );
69
+ });
70
+
71
+ it('should not log when level is INFO', () => {
72
+ const logger = createLogger('Test', 'INFO');
73
+
74
+ logger.debug('Debug message');
75
+
76
+ expect(consoleLogSpy).not.toHaveBeenCalled();
77
+ });
78
+
79
+ it('should not log when level is WARNING', () => {
80
+ const logger = createLogger('Test', 'WARNING');
81
+
82
+ logger.debug('Debug message');
83
+
84
+ expect(consoleLogSpy).not.toHaveBeenCalled();
85
+ });
86
+
87
+ it('should not log when level is ERROR', () => {
88
+ const logger = createLogger('Test', 'ERROR');
89
+
90
+ logger.debug('Debug message');
91
+
92
+ expect(consoleLogSpy).not.toHaveBeenCalled();
93
+ });
94
+ });
95
+
96
+ describe('info()', () => {
97
+ it('should log at INFO level', () => {
98
+ const logger = createLogger('Test', 'INFO');
99
+
100
+ logger.info('Info message', 'arg1', 'arg2');
101
+
102
+ expect(consoleLogSpy).toHaveBeenCalledWith(
103
+ '[Test]',
104
+ 'Info message',
105
+ 'arg1',
106
+ 'arg2'
107
+ );
108
+ });
109
+
110
+ it('should log when level is DEBUG', () => {
111
+ const logger = createLogger('Test', 'DEBUG');
112
+
113
+ logger.info('Info message');
114
+
115
+ expect(consoleLogSpy).toHaveBeenCalled();
116
+ });
117
+
118
+ it('should not log when level is WARNING', () => {
119
+ const logger = createLogger('Test', 'WARNING');
120
+
121
+ logger.info('Info message');
122
+
123
+ expect(consoleLogSpy).not.toHaveBeenCalled();
124
+ });
125
+
126
+ it('should not log when level is ERROR', () => {
127
+ const logger = createLogger('Test', 'ERROR');
128
+
129
+ logger.info('Info message');
130
+
131
+ expect(consoleLogSpy).not.toHaveBeenCalled();
132
+ });
133
+ });
134
+
135
+ describe('warn()', () => {
136
+ it('should log at WARNING level', () => {
137
+ const logger = createLogger('Test', 'WARNING');
138
+
139
+ logger.warn('Warning message', { warn: true });
140
+
141
+ expect(consoleWarnSpy).toHaveBeenCalledWith(
142
+ '[Test]',
143
+ 'Warning message',
144
+ { warn: true }
145
+ );
146
+ });
147
+
148
+ it('should log when level is DEBUG', () => {
149
+ const logger = createLogger('Test', 'DEBUG');
150
+
151
+ logger.warn('Warning');
152
+
153
+ expect(consoleWarnSpy).toHaveBeenCalled();
154
+ });
155
+
156
+ it('should log when level is INFO', () => {
157
+ const logger = createLogger('Test', 'INFO');
158
+
159
+ logger.warn('Warning');
160
+
161
+ expect(consoleWarnSpy).toHaveBeenCalled();
162
+ });
163
+
164
+ it('should not log when level is ERROR', () => {
165
+ const logger = createLogger('Test', 'ERROR');
166
+
167
+ logger.warn('Warning');
168
+
169
+ expect(consoleWarnSpy).not.toHaveBeenCalled();
170
+ });
171
+ });
172
+
173
+ describe('error()', () => {
174
+ it('should log at ERROR level', () => {
175
+ const logger = createLogger('Test', 'ERROR');
176
+
177
+ logger.error('Error message', new Error('Test error'));
178
+
179
+ expect(consoleErrorSpy).toHaveBeenCalledWith(
180
+ '[Test]',
181
+ 'Error message',
182
+ expect.any(Error)
183
+ );
184
+ });
185
+
186
+ it('should log when level is DEBUG', () => {
187
+ const logger = createLogger('Test', 'DEBUG');
188
+
189
+ logger.error('Error');
190
+
191
+ expect(consoleErrorSpy).toHaveBeenCalled();
192
+ });
193
+
194
+ it('should log when level is INFO', () => {
195
+ const logger = createLogger('Test', 'INFO');
196
+
197
+ logger.error('Error');
198
+
199
+ expect(consoleErrorSpy).toHaveBeenCalled();
200
+ });
201
+
202
+ it('should log when level is WARNING', () => {
203
+ const logger = createLogger('Test', 'WARNING');
204
+
205
+ logger.error('Error');
206
+
207
+ expect(consoleErrorSpy).toHaveBeenCalled();
208
+ });
209
+
210
+ it('should not log when level is NONE', () => {
211
+ const logger = createLogger('Test', 'NONE');
212
+
213
+ logger.error('Error');
214
+
215
+ expect(consoleErrorSpy).not.toHaveBeenCalled();
216
+ });
217
+ });
218
+
219
+ describe('log(level, ...)', () => {
220
+ let logger;
221
+
222
+ beforeEach(() => {
223
+ logger = createLogger('Test', 'DEBUG');
224
+ });
225
+
226
+ it('should delegate to debug()', () => {
227
+ logger.log('DEBUG', 'message');
228
+
229
+ expect(consoleLogSpy).toHaveBeenCalledWith('[Test] DEBUG:', 'message');
230
+ });
231
+
232
+ it('should delegate to info()', () => {
233
+ logger.log('INFO', 'message');
234
+
235
+ expect(consoleLogSpy).toHaveBeenCalledWith('[Test]', 'message');
236
+ });
237
+
238
+ it('should delegate to warn() for WARNING', () => {
239
+ logger.log('WARNING', 'message');
240
+
241
+ expect(consoleWarnSpy).toHaveBeenCalledWith('[Test]', 'message');
242
+ });
243
+
244
+ it('should delegate to warn() for WARN', () => {
245
+ logger.log('WARN', 'message');
246
+
247
+ expect(consoleWarnSpy).toHaveBeenCalledWith('[Test]', 'message');
248
+ });
249
+
250
+ it('should delegate to error()', () => {
251
+ logger.log('ERROR', 'message');
252
+
253
+ expect(consoleErrorSpy).toHaveBeenCalledWith('[Test]', 'message');
254
+ });
255
+
256
+ it('should handle lowercase level names', () => {
257
+ logger.log('debug', 'message');
258
+
259
+ expect(consoleLogSpy).toHaveBeenCalledWith('[Test] DEBUG:', 'message');
260
+ });
261
+ });
262
+
263
+ describe('setLevel()', () => {
264
+ let logger;
265
+
266
+ beforeEach(() => {
267
+ logger = createLogger('Test', 'INFO');
268
+ });
269
+
270
+ it('should change level from string', () => {
271
+ logger.setLevel('DEBUG');
272
+
273
+ expect(logger.level).toBe(LOG_LEVELS.DEBUG);
274
+ });
275
+
276
+ it('should change level from number', () => {
277
+ logger.setLevel(LOG_LEVELS.WARNING);
278
+
279
+ expect(logger.level).toBe(LOG_LEVELS.WARNING);
280
+ });
281
+
282
+ it('should handle lowercase level names', () => {
283
+ logger.setLevel('debug');
284
+
285
+ expect(logger.level).toBe(LOG_LEVELS.DEBUG);
286
+ });
287
+
288
+ it('should default to INFO for invalid level', () => {
289
+ logger.setLevel('INVALID');
290
+
291
+ expect(logger.level).toBe(LOG_LEVELS.INFO);
292
+ });
293
+
294
+ it('should affect subsequent log calls', () => {
295
+ logger.setLevel('ERROR');
296
+
297
+ logger.info('Should not log');
298
+ logger.error('Should log');
299
+
300
+ expect(consoleLogSpy).not.toHaveBeenCalled();
301
+ expect(consoleErrorSpy).toHaveBeenCalled();
302
+ });
303
+ });
304
+
305
+ describe('Global Log Level', () => {
306
+ it('should set global log level', () => {
307
+ setLogLevel('WARNING');
308
+
309
+ const level = getLogLevel();
310
+
311
+ expect(level).toBe('WARNING');
312
+ });
313
+
314
+ it('should affect new loggers', () => {
315
+ setLogLevel('ERROR');
316
+
317
+ // setLogLevel() internally calls console.log() to announce the level change,
318
+ // so reset the spy before testing actual logger behavior
319
+ consoleLogSpy.mockClear();
320
+
321
+ const logger = createLogger('NewLogger');
322
+
323
+ logger.info('Should not log');
324
+ logger.error('Should log');
325
+
326
+ expect(consoleLogSpy).not.toHaveBeenCalled();
327
+ expect(consoleErrorSpy).toHaveBeenCalled();
328
+ });
329
+
330
+ it('should handle lowercase in setLogLevel', () => {
331
+ setLogLevel('debug');
332
+
333
+ expect(getLogLevel()).toBe('DEBUG');
334
+ });
335
+ });
336
+
337
+ describe('Multiple Arguments', () => {
338
+ let logger;
339
+
340
+ beforeEach(() => {
341
+ logger = createLogger('Test', 'DEBUG');
342
+ });
343
+
344
+ it('should pass all arguments to console', () => {
345
+ logger.info('Message', 1, 'two', { three: 3 }, [4, 5]);
346
+
347
+ expect(consoleLogSpy).toHaveBeenCalledWith(
348
+ '[Test]',
349
+ 'Message',
350
+ 1,
351
+ 'two',
352
+ { three: 3 },
353
+ [4, 5]
354
+ );
355
+ });
356
+
357
+ it('should handle zero arguments', () => {
358
+ logger.info();
359
+
360
+ expect(consoleLogSpy).toHaveBeenCalledWith('[Test]');
361
+ });
362
+
363
+ it('should handle objects and errors', () => {
364
+ const error = new Error('Test');
365
+ const obj = { key: 'value' };
366
+
367
+ logger.error('Error:', error, obj);
368
+
369
+ expect(consoleErrorSpy).toHaveBeenCalledWith(
370
+ '[Test]',
371
+ 'Error:',
372
+ error,
373
+ obj
374
+ );
375
+ });
376
+ });
377
+
378
+ describe('Module Names', () => {
379
+ it('should prefix logs with module name', () => {
380
+ const logger = createLogger('MyModule', 'INFO');
381
+
382
+ logger.info('Test');
383
+
384
+ expect(consoleLogSpy).toHaveBeenCalledWith('[MyModule]', 'Test');
385
+ });
386
+
387
+ it('should support different module names', () => {
388
+ const logger1 = createLogger('Module1', 'INFO');
389
+ const logger2 = createLogger('Module2', 'INFO');
390
+
391
+ logger1.info('From 1');
392
+ logger2.info('From 2');
393
+
394
+ expect(consoleLogSpy).toHaveBeenCalledWith('[Module1]', 'From 1');
395
+ expect(consoleLogSpy).toHaveBeenCalledWith('[Module2]', 'From 2');
396
+ });
397
+ });
398
+
399
+ describe('Edge Cases', () => {
400
+ it('should handle null module name', () => {
401
+ const logger = createLogger(null, 'INFO');
402
+
403
+ logger.info('Test');
404
+
405
+ expect(consoleLogSpy).toHaveBeenCalledWith('[null]', 'Test');
406
+ });
407
+
408
+ it('should handle undefined level (use default)', () => {
409
+ const logger = createLogger('Test', undefined);
410
+
411
+ // When level is undefined, logger follows global level (useGlobal=true)
412
+ // so logger.level is undefined — check getEffectiveLevel() instead
413
+ expect(logger.getEffectiveLevel()).toBeDefined();
414
+ });
415
+
416
+ it('should handle very long messages', () => {
417
+ const logger = createLogger('Test', 'INFO');
418
+ const longMessage = 'a'.repeat(10000);
419
+
420
+ logger.info(longMessage);
421
+
422
+ expect(consoleLogSpy).toHaveBeenCalledWith('[Test]', longMessage);
423
+ });
424
+
425
+ it('should handle circular references in objects', () => {
426
+ const logger = createLogger('Test', 'INFO');
427
+ const circular = { a: 1 };
428
+ circular.self = circular;
429
+
430
+ // Should not throw
431
+ expect(() => {
432
+ logger.info('Circular:', circular);
433
+ }).not.toThrow();
434
+ });
435
+ });
436
+
437
+ describe('Performance', () => {
438
+ it('should skip expensive operations when level too low', () => {
439
+ const logger = createLogger('Test', 'ERROR');
440
+
441
+ const expensiveOperation = vi.fn(() => {
442
+ return 'expensive result';
443
+ });
444
+
445
+ logger.debug('Debug:', expensiveOperation());
446
+
447
+ // expensiveOperation still called (JS evaluates args before function call)
448
+ // But console.log should not be called
449
+ expect(consoleLogSpy).not.toHaveBeenCalled();
450
+ });
451
+
452
+ it('should handle high volume logging', () => {
453
+ const logger = createLogger('Test', 'INFO');
454
+
455
+ for (let i = 0; i < 1000; i++) {
456
+ logger.info(`Message ${i}`);
457
+ }
458
+
459
+ expect(consoleLogSpy).toHaveBeenCalledTimes(1000);
460
+ });
461
+ });
462
+
463
+ describe('Logging Disabled (NONE)', () => {
464
+ it('should not log anything when level is NONE', () => {
465
+ const logger = createLogger('Test', 'NONE');
466
+
467
+ logger.debug('Debug');
468
+ logger.info('Info');
469
+ logger.warn('Warn');
470
+ logger.error('Error');
471
+
472
+ expect(consoleLogSpy).not.toHaveBeenCalled();
473
+ expect(consoleWarnSpy).not.toHaveBeenCalled();
474
+ expect(consoleErrorSpy).not.toHaveBeenCalled();
475
+ });
476
+ });
477
+ });