'use strict'; // Session 55 — the self-learning loop's public read endpoints. Redis is mocked // so these run offline; the store is seeded per-test via cacheGet. const request = require('supertest'); let mockStore = {}; jest.mock('../../src/utils/redis', () => ({ getRedisClient: () => ({}), cacheGet: async (k) => (k in mockStore ? mockStore[k] : null), cacheSet: async (k, v) => { mockStore[k] = v; return true; }, cacheDel: async () => true, isDegraded: () => false, })); const app = require('../../src/app'); beforeEach(() => { mockStore = {}; }); describe('GET /api/accuracy', () => { test('cold cache → valid empty-safe shape', async () => { const res = await request(app).get('/api/accuracy'); expect(res.status).toBe(200); expect(res.body).toHaveProperty('overall'); expect(res.body).toHaveProperty('sports'); expect(res.body.min_sample).toBeGreaterThan(0); }); test('returns the persisted record when present', async () => { mockStore['accuracy:overall'] = { sport: 'overall', updated_at: '2026-07-10T00:00:00Z', window_days: 30, sample: 20, overall: { hits: 14, misses: 6, pushes: 0, total: 20, pct: 70 }, byGrade: { 'A': { hits: 8, misses: 2, pushes: 0, total: 10, pct: 80 } }, }; mockStore['accuracy:mlb'] = mockStore['accuracy:overall']; const res = await request(app).get('/api/accuracy'); expect(res.body.overall.overall.pct).toBe(70); expect(res.body.sports.mlb).toBeTruthy(); }); }); describe('GET /api/ledger/accuracy', () => { test('returns grade-tier buckets from the accuracy record', async () => { mockStore['accuracy:overall'] = { sport: 'overall', updated_at: '2026-07-10T00:00:00Z', window_days: 30, sample: 15, overall: { hits: 10, misses: 5, pushes: 0, total: 15, pct: 67 }, byGrade: { 'A+': { hits: 3, misses: 0, pushes: 0, total: 3, pct: 100 }, 'A': { hits: 5, misses: 2, pushes: 0, total: 7, pct: 71 }, 'B': { hits: 2, misses: 3, pushes: 0, total: 5, pct: 40 }, }, }; const res = await request(app).get('/api/ledger/accuracy'); expect(res.status).toBe(200); expect(Array.isArray(res.body.buckets)).toBe(true); const grades = res.body.buckets.map((b) => b.grade); expect(grades).toContain('A+'); expect(grades).toContain('A'); }); test('cold cache → empty buckets, never 500', async () => { const res = await request(app).get('/api/ledger/accuracy'); expect(res.status).toBe(200); expect(res.body.buckets).toEqual([]); }); });