import { ConfigService } from '@nestjs/config'; import { AppLoggerService } from './app-logger.service'; describe('AppLoggerService', () => { let level = 'verbose'; const config = { get: jest.fn(() => level) } as unknown as ConfigService; let stdout: jest.SpyInstance; let stderr: jest.SpyInstance; beforeEach(() => { level = 'verbose'; stdout = jest.spyOn(process.stdout, 'write').mockImplementation(() => true); stderr = jest.spyOn(process.stderr, 'write').mockImplementation(() => true); }); afterEach(() => { stdout.mockRestore(); stderr.mockRestore(); }); it('writes structured messages, errors, traces, and HTTP metadata', () => { const logger = new AppLoggerService(config); logger.log('hello', 'Test'); logger.warn({ id: 1 }); logger.debug(new Error('debug failed')); logger.verbose('details'); logger.logHttp({ method: 'GET', path: '/health' }); logger.error('broken', 'trace-text', 'Test'); expect(stdout).toHaveBeenCalledTimes(5); const logEntry = JSON.parse(String(stdout.mock.calls[0][0])); expect(logEntry).toEqual(expect.objectContaining({ level: 'log', context: 'Test', message: 'hello' })); const structured = JSON.parse(String(stdout.mock.calls[1][0])); expect(structured).toEqual(expect.objectContaining({ message: 'structured_log', payload: { id: 1 } })); const errorObject = JSON.parse(String(stdout.mock.calls[2][0])); expect(errorObject).toEqual(expect.objectContaining({ errorName: 'Error', message: 'debug failed' })); const http = JSON.parse(String(stdout.mock.calls[4][0])); expect(http).toEqual(expect.objectContaining({ context: 'HttpLogger', method: 'GET', path: '/health' })); const error = JSON.parse(String(stderr.mock.calls[0][0])); expect(error).toEqual(expect.objectContaining({ level: 'error', trace: 'trace-text' })); }); it('filters messages below the configured level and defaults to log', () => { level = 'warn'; const logger = new AppLoggerService(config); logger.log('hidden'); logger.debug('hidden'); logger.warn('visible'); expect(stdout).toHaveBeenCalledTimes(1); (config.get as jest.Mock).mockReturnValueOnce(undefined); logger.verbose('default-hidden'); expect(stdout).toHaveBeenCalledTimes(1); }); });