import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import { AudioService, LogLevel } from '../src/services/audioService'; describe('AudioService Logging Optimization', () => { let audioService: AudioService; let consoleSpy: any; beforeEach(() => { AudioService.resetInstance(); // Spy on console methods consoleSpy = { debug: vi.spyOn(console, 'debug').mockImplementation(() => {}), info: vi.spyOn(console, 'info').mockImplementation(() => {}), warn: vi.spyOn(console, 'warn').mockImplementation(() => {}), error: vi.spyOn(console, 'error').mockImplementation(() => {}) }; }); afterEach(() => { vi.restoreAllMocks(); }); describe('Environment-based Log Level Detection', () => { it('should use DEBUG level in development environment (localhost)', () => { // Mock localhost environment const originalLocation = window.location; delete (window as any).location; window.location = { hostname: 'localhost' } as any; audioService = AudioService.getInstance(); expect(consoleSpy.info).toHaveBeenCalledWith( expect.stringContaining('DEBUG') ); window.location = originalLocation; }); it('should use WARN level in production environment', () => { // Mock production environment const originalLocation = window.location; delete (window as any).location; window.location = { hostname: 'example.com' } as any; audioService = AudioService.getInstance(); expect(consoleSpy.info).toHaveBeenCalledWith( expect.stringContaining('WARN') ); window.location = originalLocation; }); it('should use DEBUG level with audioDebug query parameter', () => { // Mock production environment with debug parameter const originalLocation = window.location; delete (window as any).location; window.location = { hostname: 'example.com', search: '?audioDebug=true' } as any; audioService = AudioService.getInstance(); expect(consoleSpy.info).toHaveBeenCalledWith( expect.stringContaining('log level: DEBUG') ); window.location = originalLocation; }); }); describe('Log Throttling', () => { it('should throttle rapid-fire log calls', () => { // Mock development environment const originalLocation = window.location; delete (window as any).location; window.location = { hostname: 'localhost' } as any; audioService = AudioService.getInstance(); // Call log multiple times rapidly for (let i = 0; i < 10; i++) { audioService['log'](LogLevel.DEBUG, `Test log ${i}`); } // Should only log a few times due to throttling expect(consoleSpy.debug).toHaveBeenCalled(); // Should be called fewer times due to throttling const callCount = consoleSpy.debug.mock.calls.length; expect(callCount).toBeLessThanOrEqual(3); window.location = originalLocation; }); }); describe('Log Level Filtering', () => { it('should filter out logs below current log level', () => { // Mock production environment (WARN level) const originalLocation = window.location; delete (window as any).location; window.location = { hostname: 'example.com' } as any; audioService = AudioService.getInstance(); // Try to log INFO level message in WARN environment audioService['log'](LogLevel.INFO, 'This should not appear'); // Should not call console.info expect(consoleSpy.info).not.toHaveBeenCalledWith( expect.stringContaining('This should not appear') ); // WARN level should appear audioService['log'](LogLevel.WARN, 'This should appear'); expect(consoleSpy.warn).toHaveBeenCalledWith( expect.stringContaining('This should appear') ); window.location = originalLocation; }); it('should allow DEBUG logs in development environment', () => { // Mock development environment const originalLocation = window.location; delete (window as any).location; window.location = { hostname: 'localhost' } as any; audioService = AudioService.getInstance(); // DEBUG level should appear in development audioService['log'](LogLevel.DEBUG, 'Debug message'); expect(consoleSpy.debug).toHaveBeenCalledWith( expect.stringContaining('Debug message') ); window.location = originalLocation; }); }); describe('Verbose Log Reduction', () => { it('should not log play/pause/seek calls in production', () => { // Mock production environment const originalLocation = window.location; delete (window as any).location; window.location = { hostname: 'example.com' } as any; audioService = AudioService.getInstance(); // These should not appear in production (INFO level, but production uses WARN) audioService['log'](LogLevel.INFO, 'AudioService.play called'); audioService['log'](LogLevel.INFO, 'AudioService.pause called'); audioService['log'](LogLevel.INFO, 'AudioService.seekTo called'); // Should not call console.info for these expect(consoleSpy.info).not.toHaveBeenCalledWith( expect.stringContaining('AudioService.play called') ); expect(consoleSpy.info).not.toHaveBeenCalledWith( expect.stringContaining('AudioService.pause called') ); expect(consoleSpy.info).not.toHaveBeenCalledWith( expect.stringContaining('AudioService.seekTo called') ); window.location = originalLocation; }); it('should log errors in both environments', () => { // Test in production environment const originalLocation = window.location; delete (window as any).location; window.location = { hostname: 'example.com' } as any; audioService = AudioService.getInstance(); // Error logs should always appear audioService['log'](LogLevel.ERROR, 'Critical error'); expect(consoleSpy.error).toHaveBeenCalledWith( expect.stringContaining('Critical error') ); window.location = originalLocation; }); }); });