Files
automaker/libs/utils/tests/logger.test.ts
Kacper 8e1a9addc1 fix: update logger test expectations to include log level prefixes
- Modified test cases in logger.test.ts to assert that log messages include appropriate log level prefixes (INFO, ERROR, WARN, DEBUG).
- Ensured consistency in log output formatting across various logging methods, enhancing clarity in test results.
2026-01-02 20:54:39 +01:00

295 lines
8.4 KiB
TypeScript

import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
import { createLogger, LogLevel, getLogLevel, setLogLevel } from '../src/logger';
describe('logger.ts', () => {
let originalConsoleError: typeof console.error;
let originalConsoleWarn: typeof console.warn;
let originalConsoleLog: typeof console.log;
let originalLogLevel: LogLevel;
beforeEach(() => {
// Save original console methods and log level
originalConsoleError = console.error;
originalConsoleWarn = console.warn;
originalConsoleLog = console.log;
originalLogLevel = getLogLevel();
// Mock console methods
console.error = vi.fn();
console.warn = vi.fn();
console.log = vi.fn();
});
afterEach(() => {
// Restore original console methods and log level
console.error = originalConsoleError;
console.warn = originalConsoleWarn;
console.log = originalConsoleLog;
setLogLevel(originalLogLevel);
});
describe('createLogger', () => {
it('should create logger with context prefix', () => {
const logger = createLogger('TestContext');
setLogLevel(LogLevel.INFO);
logger.info('test message');
expect(console.log).toHaveBeenCalledWith('INFO [TestContext]', 'test message');
});
it('should handle multiple arguments', () => {
const logger = createLogger('Test');
setLogLevel(LogLevel.INFO);
logger.info('message', { data: 123 }, [1, 2, 3]);
expect(console.log).toHaveBeenCalledWith('INFO [Test]', 'message', { data: 123 }, [1, 2, 3]);
});
});
describe('Log levels', () => {
it('should log error at ERROR level', () => {
const logger = createLogger('Test');
setLogLevel(LogLevel.ERROR);
logger.error('error message');
logger.warn('warn message');
logger.info('info message');
logger.debug('debug message');
expect(console.error).toHaveBeenCalledTimes(1);
expect(console.warn).not.toHaveBeenCalled();
expect(console.log).not.toHaveBeenCalled();
});
it('should log error and warn at WARN level', () => {
const logger = createLogger('Test');
setLogLevel(LogLevel.WARN);
logger.error('error message');
logger.warn('warn message');
logger.info('info message');
logger.debug('debug message');
expect(console.error).toHaveBeenCalledTimes(1);
expect(console.warn).toHaveBeenCalledTimes(1);
expect(console.log).not.toHaveBeenCalled();
});
it('should log error, warn, and info at INFO level', () => {
const logger = createLogger('Test');
setLogLevel(LogLevel.INFO);
logger.error('error message');
logger.warn('warn message');
logger.info('info message');
logger.debug('debug message');
expect(console.error).toHaveBeenCalledTimes(1);
expect(console.warn).toHaveBeenCalledTimes(1);
expect(console.log).toHaveBeenCalledTimes(1); // Only info, not debug
});
it('should log all messages at DEBUG level', () => {
const logger = createLogger('Test');
setLogLevel(LogLevel.DEBUG);
logger.error('error message');
logger.warn('warn message');
logger.info('info message');
logger.debug('debug message');
expect(console.error).toHaveBeenCalledTimes(1);
expect(console.warn).toHaveBeenCalledTimes(1);
expect(console.log).toHaveBeenCalledTimes(2); // info + debug
});
});
describe('error method', () => {
it('should use console.error', () => {
const logger = createLogger('ErrorTest');
setLogLevel(LogLevel.ERROR);
logger.error('error occurred', { code: 500 });
expect(console.error).toHaveBeenCalledWith('ERROR [ErrorTest]', 'error occurred', {
code: 500,
});
});
it('should not log when level is below ERROR', () => {
const logger = createLogger('Test');
setLogLevel((LogLevel.ERROR - 1) as LogLevel);
logger.error('should not appear');
expect(console.error).not.toHaveBeenCalled();
});
});
describe('warn method', () => {
it('should use console.warn', () => {
const logger = createLogger('WarnTest');
setLogLevel(LogLevel.WARN);
logger.warn('warning message');
expect(console.warn).toHaveBeenCalledWith('WARN [WarnTest]', 'warning message');
});
it('should not log when level is below WARN', () => {
const logger = createLogger('Test');
setLogLevel(LogLevel.ERROR);
logger.warn('should not appear');
expect(console.warn).not.toHaveBeenCalled();
});
});
describe('info method', () => {
it('should use console.log', () => {
const logger = createLogger('InfoTest');
setLogLevel(LogLevel.INFO);
logger.info('info message');
expect(console.log).toHaveBeenCalledWith('INFO [InfoTest]', 'info message');
});
it('should not log when level is below INFO', () => {
const logger = createLogger('Test');
setLogLevel(LogLevel.WARN);
logger.info('should not appear');
expect(console.log).not.toHaveBeenCalled();
});
});
describe('debug method', () => {
it('should use console.log with DEBUG prefix', () => {
const logger = createLogger('DebugTest');
setLogLevel(LogLevel.DEBUG);
logger.debug('debug details', { trace: '...' });
expect(console.log).toHaveBeenCalledWith('DEBUG [DebugTest]', 'debug details', {
trace: '...',
});
});
it('should not log when level is below DEBUG', () => {
const logger = createLogger('Test');
setLogLevel(LogLevel.INFO);
logger.debug('should not appear');
expect(console.log).not.toHaveBeenCalled();
});
});
describe('getLogLevel', () => {
it('should return current log level', () => {
setLogLevel(LogLevel.DEBUG);
expect(getLogLevel()).toBe(LogLevel.DEBUG);
setLogLevel(LogLevel.ERROR);
expect(getLogLevel()).toBe(LogLevel.ERROR);
});
});
describe('setLogLevel', () => {
it('should change log level', () => {
setLogLevel(LogLevel.WARN);
expect(getLogLevel()).toBe(LogLevel.WARN);
setLogLevel(LogLevel.DEBUG);
expect(getLogLevel()).toBe(LogLevel.DEBUG);
});
it('should affect subsequent logging', () => {
const logger = createLogger('Test');
setLogLevel(LogLevel.ERROR);
logger.info('should not log');
expect(console.log).not.toHaveBeenCalled();
setLogLevel(LogLevel.INFO);
logger.info('should log');
expect(console.log).toHaveBeenCalledWith('INFO [Test]', 'should log');
});
});
describe('Multiple logger instances', () => {
it('should maintain separate contexts', () => {
const logger1 = createLogger('Service1');
const logger2 = createLogger('Service2');
setLogLevel(LogLevel.INFO);
logger1.info('from service 1');
logger2.info('from service 2');
expect(console.log).toHaveBeenNthCalledWith(1, 'INFO [Service1]', 'from service 1');
expect(console.log).toHaveBeenNthCalledWith(2, 'INFO [Service2]', 'from service 2');
});
it('should share log level setting', () => {
const logger1 = createLogger('Service1');
const logger2 = createLogger('Service2');
setLogLevel(LogLevel.ERROR);
logger1.info('should not log');
logger2.info('should not log');
expect(console.log).not.toHaveBeenCalled();
});
});
describe('Edge cases', () => {
it('should handle empty context string', () => {
const logger = createLogger('');
setLogLevel(LogLevel.INFO);
logger.info('message');
expect(console.log).toHaveBeenCalledWith('INFO []', 'message');
});
it('should handle context with special characters', () => {
const logger = createLogger('Test-Service_v2.0');
setLogLevel(LogLevel.INFO);
logger.info('message');
expect(console.log).toHaveBeenCalledWith('INFO [Test-Service_v2.0]', 'message');
});
it('should handle no arguments to log methods', () => {
const logger = createLogger('Test');
setLogLevel(LogLevel.INFO);
logger.info();
expect(console.log).toHaveBeenCalledWith('INFO [Test]');
});
it('should handle complex object arguments', () => {
const logger = createLogger('Test');
setLogLevel(LogLevel.INFO);
const complexObj = {
nested: { deep: { value: 123 } },
array: [1, 2, 3],
fn: () => {},
};
logger.info('complex', complexObj);
expect(console.log).toHaveBeenCalledWith('INFO [Test]', 'complex', complexObj);
});
});
});