/** * Logger Integration Tests * * Tests the core functionality of the simplified @stock-bot/logger package. */ import { describe, it, expect, beforeEach, afterEach } from 'bun:test'; import { Logger, getLogger, shutdownLoggers } from '../src'; import { loggerTestHelpers } from './setup'; describe('Logger Integration Tests', () => { let logger: Logger; let testLoggerInstance: ReturnType; beforeEach(() => { testLoggerInstance = loggerTestHelpers.createTestLogger('integration-test'); logger = testLoggerInstance.logger; }); afterEach(async () => { testLoggerInstance.clearCapturedLogs(); // Clear any global logger cache await shutdownLoggers(); }); describe('Core Logger Functionality', () => { it('should log messages at different levels', () => { // Test multiple log levels logger.debug('Debug message'); logger.info('Info message'); logger.warn('Warning message'); logger.error('Error message'); // Get captured logs const logs = testLoggerInstance.getCapturedLogs(); // Verify logs were captured expect(logs.length).toBe(4); expect(logs[0].level).toBe('debug'); expect(logs[0].msg).toBe('Debug message'); expect(logs[1].level).toBe('info'); expect(logs[1].msg).toBe('Info message'); expect(logs[2].level).toBe('warn'); expect(logs[2].msg).toBe('Warning message'); expect(logs[3].level).toBe('error'); expect(logs[3].msg).toBe('Error message'); }); it('should log objects as structured logs', () => { // Log an object logger.info('User logged in', { userId: '123', action: 'login' }); // Get captured logs const logs = testLoggerInstance.getCapturedLogs(); // Verify structured log expect(logs.length).toBe(1); expect(logs[0].userId).toBe('123'); expect(logs[0].action).toBe('login'); expect(logs[0].msg).toBe('User logged in'); }); it('should handle error objects in error logs', () => { const testError = new Error('Test error message'); // Log error with error object logger.error('Something went wrong', { error: testError }); // Get captured logs const logs = testLoggerInstance.getCapturedLogs(); // Verify error was logged expect(logs.length).toBe(1); expect(logs[0].level).toBe('error'); expect(logs[0].msg).toBe('Something went wrong'); }); it('should create child loggers with additional context', () => { // Create a child logger with additional context const childLogger = logger.child({ transactionId: 'tx-789', operation: 'payment' }); // Log with child logger childLogger.info('Child logger test'); // Get captured logs const logs = testLoggerInstance.getCapturedLogs(); // Verify child logger logged something expect(logs.length).toBe(1); expect(logs[0].msg).toBe('Child logger test'); }); }); describe('Factory Functions', () => { it('should export factory functions', () => { // Verify that the factory functions are exported and callable expect(typeof getLogger).toBe('function'); }); it('should create different logger instances', () => { const logger1Instance = loggerTestHelpers.createTestLogger('service-1'); const logger2Instance = loggerTestHelpers.createTestLogger('service-2'); logger1Instance.logger.info('Message from service 1'); logger2Instance.logger.info('Message from service 2'); const logs1 = logger1Instance.getCapturedLogs(); expect(logs1.length).toBe(1); expect(logs1[0].service).toBe('service-1'); const logs2 = logger2Instance.getCapturedLogs(); expect(logs2.length).toBe(1); expect(logs2[0].service).toBe('service-2'); }); }); describe('Error Handling', () => { it('should normalize Error objects', () => { const error = new Error('Test error'); error.stack = 'Error stack trace'; logger.error('Error occurred', error); const logs = testLoggerInstance.getCapturedLogs(); expect(logs.length).toBe(1); expect(logs[0].level).toBe('error'); expect(logs[0].msg).toBe('Error occurred'); }); it('should handle error-like objects', () => { const errorLike = { name: 'CustomError', message: 'Custom error message', code: 'ERR_CUSTOM' }; logger.error('Custom error occurred', { error: errorLike }); const logs = testLoggerInstance.getCapturedLogs(); expect(logs.length).toBe(1); expect(logs[0].level).toBe('error'); expect(logs[0].msg).toBe('Custom error occurred'); }); it('should handle primitive error values', () => { logger.error('String error occurred', { error: 'Simple string error' }); const logs = testLoggerInstance.getCapturedLogs(); expect(logs.length).toBe(1); expect(logs[0].level).toBe('error'); expect(logs[0].msg).toBe('String error occurred'); }); }); describe('Metadata Handling', () => { it('should include metadata in logs', () => { const metadata = { requestId: 'req-123', userId: 'user-456', operation: 'data-fetch' }; logger.info('Operation completed', metadata); const logs = testLoggerInstance.getCapturedLogs(); expect(logs.length).toBe(1); expect(logs[0].requestId).toBe('req-123'); expect(logs[0].userId).toBe('user-456'); expect(logs[0].operation).toBe('data-fetch'); }); it('should handle object messages', () => { const objectMessage = { event: 'user_action', action: 'login', timestamp: Date.now() }; logger.info(objectMessage); const logs = testLoggerInstance.getCapturedLogs(); expect(logs.length).toBe(1); expect(logs[0].level).toBe('info'); }); }); });