import { Logger, LogLevel } from '@common/Logger'; describe('Logger — leveled logging', () => { let logger: Logger; let sink: jest.Mock; beforeEach(() => { logger = new Logger(); sink = jest.fn(); logger.setSink(sink); }); it('suppresses messages below the threshold', () => { logger.setLevel(LogLevel.Warn); logger.debug('mod', 'hidden'); logger.info('mod', 'hidden'); logger.warn('mod', 'shown'); logger.error('mod', 'shown'); expect(sink).toHaveBeenCalledTimes(2); }); it('forwards module + message + rest args to the sink', () => { logger.setLevel(LogLevel.Debug); logger.info('Pool', 'size', 5); expect(sink).toHaveBeenCalledWith(LogLevel.Info, 'Pool', 'size', 5); }); it('Silent level disables all output', () => { logger.setLevel(LogLevel.Silent); logger.error('mod', 'ignored'); expect(sink).not.toHaveBeenCalled(); }); }); describe('Logger — performance metrics', () => { let logger: Logger; beforeEach(() => { logger = new Logger(); }); it('records samples under a metric name', () => { for (const v of [10, 20, 30, 40, 50]) { logger.metric({ name: 'touch_ms', value: v }); } const agg = logger.aggregate('touch_ms'); expect(agg).toBeDefined(); expect(agg!.count).toBe(5); expect(agg!.min).toBe(10); expect(agg!.max).toBe(50); expect(agg!.avg).toBeCloseTo(30); expect(agg!.p50).toBe(30); expect(agg!.p95).toBe(50); }); it('returns undefined aggregate for unknown metric', () => { expect(logger.aggregate('ghost')).toBeUndefined(); }); it('timerStart/timerEnd records elapsed time', () => { logger.timerStart('frame', 1000); const elapsed = logger.timerEnd('frame', 1016); expect(elapsed).toBe(16); expect(logger.aggregate('frame')!.avg).toBe(16); }); it('timerEnd without start returns undefined', () => { expect(logger.timerEnd('never', 100)).toBeUndefined(); }); it('resetMetrics clears all samples and running timers', () => { logger.metric({ name: 'a', value: 1 }); logger.timerStart('b', 0); logger.resetMetrics(); expect(logger.aggregate('a')).toBeUndefined(); expect(logger.timerEnd('b', 10)).toBeUndefined(); }); });