import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest' import { initLogger, logError, logWarn, logInfo, logDebug } from '../../app/utils/logger.js' describe('logger', () => { let fetchMock beforeEach(() => { fetchMock = vi.fn().mockResolvedValue(undefined) vi.stubGlobal('$fetch', fetchMock) vi.useFakeTimers() }) afterEach(() => { vi.useRealTimers() vi.unstubAllGlobals() }) it('initLogger sets context', () => { initLogger('sess-1', 'user-1') logError('test', {}) vi.advanceTimersByTime(10) expect(fetchMock).toHaveBeenCalledWith('/api/log', expect.objectContaining({ method: 'POST', body: expect.objectContaining({ sessionId: 'sess-1', userId: 'user-1', level: 'error', message: 'test', }), })) }) it('logError sends error level', () => { logError('err', { code: 1 }) vi.advanceTimersByTime(10) expect(fetchMock).toHaveBeenCalledWith('/api/log', expect.objectContaining({ body: expect.objectContaining({ level: 'error', message: 'err', data: { code: 1 } }), })) }) it('logWarn sends warn level', () => { logWarn('warn', {}) vi.advanceTimersByTime(10) expect(fetchMock).toHaveBeenCalledWith('/api/log', expect.objectContaining({ body: expect.objectContaining({ level: 'warn', message: 'warn' }), })) }) it('logInfo sends info level', () => { logInfo('info', {}) vi.advanceTimersByTime(10) expect(fetchMock).toHaveBeenCalledWith('/api/log', expect.objectContaining({ body: expect.objectContaining({ level: 'info', message: 'info' }), })) }) it('logDebug sends debug level', () => { logDebug('debug', {}) vi.advanceTimersByTime(10) expect(fetchMock).toHaveBeenCalledWith('/api/log', expect.objectContaining({ body: expect.objectContaining({ level: 'debug', message: 'debug' }), })) }) it('does not throw when $fetch rejects', async () => { vi.stubGlobal('$fetch', vi.fn().mockRejectedValue(new Error('network'))) logError('x', {}) vi.advanceTimersByTime(10) await vi.advanceTimersByTimeAsync(0) }) })