import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import { setDebug, isDebugEnabled, logDebug, logError, } from '../src/utils/logger'; describe('logger', () => { beforeEach(() => { setDebug(false); }); afterEach(() => { vi.restoreAllMocks(); }); describe('setDebug', () => { it('should enable debug mode', () => { expect(isDebugEnabled()).toBe(false); setDebug(true); expect(isDebugEnabled()).toBe(true); }); it('should disable debug mode', () => { setDebug(true); expect(isDebugEnabled()).toBe(true); setDebug(false); expect(isDebugEnabled()).toBe(false); }); }); describe('isDebugEnabled', () => { it('should return current debug state', () => { expect(isDebugEnabled()).toBe(false); setDebug(true); expect(isDebugEnabled()).toBe(true); }); }); describe('logDebug', () => { it('should not log when debug is disabled', () => { const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {}); logDebug('Test', 'This should not appear'); expect(consoleSpy).not.toHaveBeenCalled(); }); it('should log message when debug is enabled', () => { setDebug(true); const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {}); logDebug('Test', 'This should appear'); expect(consoleSpy).toHaveBeenCalled(); }); it('should log message with data when debug is enabled', () => { setDebug(true); const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {}); logDebug('Test', 'Message with data', { key: 'value', num: 123 }); expect(consoleSpy).toHaveBeenCalled(); const loggedMessage = consoleSpy.mock.calls[0].join(' '); expect(loggedMessage).toContain('[LightSDK][Test]'); expect(loggedMessage).toContain('Message with data'); }); it('should include timestamp in log message', () => { setDebug(true); const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {}); logDebug('Module', 'Test message'); expect(consoleSpy).toHaveBeenCalled(); const loggedMessage = consoleSpy.mock.calls[0][0]; expect(loggedMessage).toMatch(/^\[LightSDK\]\[Module\]/); }); it('should handle message without data', () => { setDebug(true); const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {}); logDebug('Module', 'Simple message'); expect(consoleSpy).toHaveBeenCalled(); }); it('should handle undefined data', () => { setDebug(true); const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {}); logDebug('Module', 'Message', undefined); expect(consoleSpy).toHaveBeenCalled(); }); it('should handle null data', () => { setDebug(true); const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {}); logDebug('Module', 'Message', null); expect(consoleSpy).toHaveBeenCalled(); }); it('should handle complex data objects', () => { setDebug(true); const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {}); const complexData = { nested: { deeply: { value: 123 } }, array: [1, 2, 3], bool: true, null: null, }; logDebug('Module', 'Complex data', complexData); expect(consoleSpy).toHaveBeenCalled(); }); }); describe('logError', () => { it('should always log errors even when debug is disabled', () => { setDebug(false); const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {}); logError('Test', 'This should always appear'); expect(consoleSpy).toHaveBeenCalled(); consoleSpy.mockRestore(); }); it('should log error message when debug is enabled', () => { setDebug(true); const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {}); logError('Test', 'This error should appear'); expect(consoleSpy).toHaveBeenCalled(); consoleSpy.mockRestore(); }); it('should include ERROR tag in log message', () => { const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {}); logError('Module', 'Error message'); expect(consoleSpy).toHaveBeenCalled(); const loggedMessage = consoleSpy.mock.calls[0][0]; expect(loggedMessage).toContain('[LightSDK][Module][ERROR]'); consoleSpy.mockRestore(); }); it('should log error with error data', () => { const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {}); const error = new Error('Test error'); logError('Module', 'Error occurred', error); expect(consoleSpy).toHaveBeenCalled(); consoleSpy.mockRestore(); }); it('should handle plain object error', () => { const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {}); const errorObj = { status: 404, message: 'Not found' }; logError('Module', 'Request failed', errorObj); expect(consoleSpy).toHaveBeenCalled(); consoleSpy.mockRestore(); }); it('should handle error message without data', () => { const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {}); logError('Module', 'Simple error'); expect(consoleSpy).toHaveBeenCalled(); consoleSpy.mockRestore(); }); it('should handle string error', () => { const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {}); logError('Module', 'String error', 'error details'); expect(consoleSpy).toHaveBeenCalled(); consoleSpy.mockRestore(); }); it('should handle undefined error', () => { const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {}); logError('Module', 'Error without details', undefined); expect(consoleSpy).toHaveBeenCalled(); consoleSpy.mockRestore(); }); }); describe('debug toggle behavior', () => { it('should toggle debug logs between enabled and disabled', () => { const consoleLogSpy = vi.spyOn(console, 'log').mockImplementation(() => {}); const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {}); setDebug(true); logDebug('Test', 'Debug on'); expect(consoleLogSpy).toHaveBeenCalled(); setDebug(false); logDebug('Test', 'Debug off'); expect(consoleLogSpy).toHaveBeenCalledTimes(1); // logError should always work regardless of debug flag setDebug(true); logError('Test', 'Error on'); const errorCallCountWhenOn = consoleWarnSpy.mock.calls.length; expect(errorCallCountWhenOn).toBeGreaterThan(0); setDebug(false); logError('Test', 'Error off'); expect(consoleWarnSpy).toHaveBeenCalledTimes(errorCallCountWhenOn + 1); consoleLogSpy.mockRestore(); consoleWarnSpy.mockRestore(); }); }); });