import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { info, error, warn, debug, setContext, clearContext, runWithContext } from '../../server/utils/logger.js' describe('logger', () => { let originalLog let originalError let originalWarn let originalDebug let logCalls let errorCalls let warnCalls let debugCalls beforeEach(() => { logCalls = [] errorCalls = [] warnCalls = [] debugCalls = [] originalLog = console.log originalError = console.error originalWarn = console.warn originalDebug = console.debug console.log = vi.fn((...args) => logCalls.push(args)) console.error = vi.fn((...args) => errorCalls.push(args)) console.warn = vi.fn((...args) => warnCalls.push(args)) console.debug = vi.fn((...args) => debugCalls.push(args)) }) afterEach(() => { console.log = originalLog console.error = originalError console.warn = originalWarn console.debug = originalDebug }) it('logs info message', () => { info('Test message') expect(logCalls.length).toBe(1) const logMsg = logCalls[0][0] expect(logMsg).toContain('[INFO]') expect(logMsg).toContain('Test message') }) it('includes request context when set', async () => { await runWithContext('req-123', 'user-456', async () => { info('Test message') const logMsg = logCalls[0][0] expect(logMsg).toContain('req-123') expect(logMsg).toContain('user-456') }) }) it('includes additional context', () => { info('Test message', { key: 'value', count: 42 }) const logMsg = logCalls[0][0] expect(logMsg).toContain('key') expect(logMsg).toContain('value') expect(logMsg).toContain('42') }) it('logs error with stack trace', () => { const err = new Error('Test error') error('Failed', { error: err }) expect(errorCalls.length).toBe(1) const errorMsg = errorCalls[0][0] expect(errorMsg).toContain('[ERROR]') expect(errorMsg).toContain('Failed') expect(errorMsg).toContain('stack') }) it('logs warning', () => { warn('Warning message') expect(warnCalls.length).toBe(1) const warnMsg = warnCalls[0][0] expect(warnMsg).toContain('[WARN]') }) it('logs debug only in development', () => { const originalEnv = process.env.NODE_ENV process.env.NODE_ENV = 'development' debug('Debug message') expect(debugCalls.length).toBe(1) process.env.NODE_ENV = originalEnv }) it('does not log debug in production', () => { const originalEnv = process.env.NODE_ENV process.env.NODE_ENV = 'production' debug('Debug message') expect(debugCalls.length).toBe(0) process.env.NODE_ENV = originalEnv }) it('clears context', async () => { await runWithContext('req-123', 'user-456', async () => { info('Test with context') const logMsg = logCalls[0][0] expect(logMsg).toContain('req-123') }) // Context should be cleared after runWithContext completes info('Test without context') const logMsg = logCalls[logCalls.length - 1][0] expect(logMsg).not.toContain('req-123') }) it('supports deprecated setContext/clearContext API', async () => { await runWithContext(null, null, async () => { setContext('req-123', 'user-456') info('Test message') const logMsg = logCalls[0][0] expect(logMsg).toContain('req-123') expect(logMsg).toContain('user-456') clearContext() info('Test after clear') const logMsg2 = logCalls[1][0] expect(logMsg2).not.toContain('req-123') }) }) })