import { describe, it, expect } from 'vitest' import { PerformanceTracker } from '@/lib/monitoring/performance-tracker' describe('PerformanceTracker', () => { it('tracks requests and computes metrics', () => { const tracker = new PerformanceTracker(1000) tracker.track('GET', '/api/posts', 200, 120) tracker.track('GET', '/api/posts', 200, 250) tracker.track('GET', '/api/posts', 500, 800) const metrics = tracker.getMetrics('1h') expect(metrics.avgResponseTimeMs).toBeCloseTo(390, -1) expect(metrics.errorRate).toBeCloseTo(0.333, 2) expect(metrics.requestsPerMinute).toBeGreaterThan(0) expect(metrics.p95ResponseTimeMs).toBeGreaterThanOrEqual(metrics.avgResponseTimeMs) }) it('ring buffer evicts old entries when capacity is exceeded', () => { const tracker = new PerformanceTracker(2) tracker.track('GET', '/a', 200, 100) tracker.track('GET', '/b', 200, 200) tracker.track('GET', '/c', 200, 300) const metrics = tracker.getMetrics('1h') // Only the last 2 entries should remain (200ms and 300ms) expect(metrics.avgResponseTimeMs).toBeCloseTo(250, -1) }) it('returns zeros when no entries exist', () => { const tracker = new PerformanceTracker(100) const metrics = tracker.getMetrics('1h') expect(metrics.avgResponseTimeMs).toBe(0) expect(metrics.p95ResponseTimeMs).toBe(0) expect(metrics.p99ResponseTimeMs).toBe(0) expect(metrics.errorRate).toBe(0) expect(metrics.requestsPerMinute).toBe(0) }) it('computes p95 and p99 correctly', () => { const tracker = new PerformanceTracker(200) for (let i = 1; i <= 100; i++) { tracker.track('GET', '/test', 200, i) } const metrics = tracker.getMetrics('1h') expect(metrics.p95ResponseTimeMs).toBeGreaterThanOrEqual(95) expect(metrics.p99ResponseTimeMs).toBeGreaterThanOrEqual(99) expect(metrics.avgResponseTimeMs).toBeCloseTo(50, -1) }) it('only counts 5xx status codes as errors', () => { const tracker = new PerformanceTracker(100) tracker.track('GET', '/a', 200, 100) tracker.track('GET', '/b', 404, 100) tracker.track('GET', '/c', 500, 100) tracker.track('GET', '/d', 503, 100) const metrics = tracker.getMetrics('1h') expect(metrics.errorRate).toBeCloseTo(0.5, 2) }) })