// DS2 (Design v2) — Dashboard Slate Rebuild. The founder's named #1 rebuild: // real entities per card, ONE bold hero, collapse pending-filler (#14), and the // NEVER-EMPTY hero (#1, Part 6) — first paint ALWAYS proves the model. The pure // engine lives in web/src/lib/slateAdapter.js (unit-tested directly); the .tsx // surfaces are asserted against source (plain-JS Jest) — same pattern as // ds4Billboards / vyndrParityQA. const fs = require('fs'); const path = require('path'); const ROOT = path.join(__dirname, '..', '..'); const WEB = path.join(ROOT, 'web', 'src'); const read = (rel) => fs.readFileSync(path.join(WEB, rel), 'utf8'); const adapter = require('../../web/src/lib/slateAdapter'); // ── 1. selectTopGrades — ranking VARIES on a real signal (#13) ───────────── describe('selectTopGrades — tier first, then the varying signal (confidence/edge)', () => { test('orders by grade tier, then confidence desc, then edge desc', () => { const grades = [ { player: 'C-low', grade: 'B', confidence: 40, edge: 1 }, { player: 'A-hiconf', grade: 'A', confidence: 90, edge: 2 }, { player: 'A-loconf', grade: 'A', confidence: 55, edge: 9 }, { player: 'Aplus', grade: 'A+', confidence: 10, edge: 0 }, ]; const out = adapter.selectTopGrades(grades, 10).map((g) => g.player); expect(out).toEqual(['Aplus', 'A-hiconf', 'A-loconf', 'C-low']); }); test('ties on grade break on confidence — rows are NOT identical-order noise', () => { const grades = [ { player: 'X', grade: 'B', confidence: 30 }, { player: 'Y', grade: 'B', confidence: 80 }, { player: 'Z', grade: 'B', confidence: 55 }, ]; expect(adapter.selectTopGrades(grades, 10).map((g) => g.player)).toEqual(['Y', 'Z', 'X']); }); test('honors the limit and drops gradeless rows; empty in → empty out', () => { const grades = [{ grade: 'A', confidence: 1 }, { grade: 'A', confidence: 2 }, { confidence: 9 }]; expect(adapter.selectTopGrades(grades, 1)).toHaveLength(1); expect(adapter.selectTopGrades([], 5)).toEqual([]); expect(adapter.selectTopGrades(null, 5)).toEqual([]); }); }); // ── 2. buildHeroReceipts — yesterday's A-tier settled HITS (#1) ──────────── describe('buildHeroReceipts — proven A-tier receipts, misses excluded', () => { const rows = [ { player_name: 'Aaron Judge', stat: 'total_bases', line: 1.5, side: 'over', grade: 'A+', outcome: 'hit', actual_value: 3, clv_result: 'beat', sport: 'mlb' }, { player_name: 'Missed Guy', stat: 'hits', line: 1.5, side: 'over', grade: 'A', outcome: 'miss', actual_value: 0 }, { player_name: 'B Guy', stat: 'runs', line: 0.5, side: 'over', grade: 'B', outcome: 'hit', actual_value: 1 }, { player_name: 'Aminus Hit', stat: 'rbi', line: 0.5, side: 'over', grade: 'A-', outcome: 'hit', actual_value: 2 }, ]; test('keeps only A-family grades that HIT (a miss never becomes proof)', () => { const out = adapter.buildHeroReceipts(rows, 8); const names = out.map((r) => r.player); expect(names).toContain('Aaron Judge'); expect(names).toContain('Aminus Hit'); expect(names).not.toContain('Missed Guy'); // A-tier but a MISS expect(names).not.toContain('B Guy'); // a hit but not A-tier }); test('carries the real result (actual + grade) so the receipt is verifiable', () => { const judge = adapter.buildHeroReceipts(rows, 8).find((r) => r.player === 'Aaron Judge'); expect(judge).toMatchObject({ grade: 'A+', outcome: 'hit', actual: 3 }); }); test('best-grade first, honors the limit, empty/absent → []', () => { expect(adapter.buildHeroReceipts(rows, 8)[0].grade).toBe('A+'); expect(adapter.buildHeroReceipts(rows, 1)).toHaveLength(1); expect(adapter.buildHeroReceipts([], 5)).toEqual([]); expect(adapter.buildHeroReceipts(null, 5)).toEqual([]); }); }); // ── 3. heroFallbackState — the NEVER-EMPTY hero engine (#1, Part 6) ──────── describe('heroFallbackState — tonight wins, else receipts, never empty when proof exists', () => { const settled = [{ player_name: 'Judge', stat: 'total_bases', line: 1.5, side: 'over', grade: 'A', outcome: 'hit', actual_value: 3 }]; test('tonight has graded props → mode tonight', () => { const s = adapter.heroFallbackState([{ player: 'P', grade: 'A', confidence: 70 }], settled, 10); expect(s.mode).toBe('tonight'); expect(s.items).toHaveLength(1); }); test('tonight EMPTY but yesterday has A-tier hits → mode receipts (proof, not empty)', () => { const s = adapter.heroFallbackState([], settled, 10); expect(s.mode).toBe('receipts'); expect(s.items[0].player).toBe('Judge'); }); test('only truly empty when BOTH are absent', () => { expect(adapter.heroFallbackState([], [], 10).mode).toBe('empty'); expect(adapter.heroFallbackState(null, null, 10).mode).toBe('empty'); }); }); // ── 4. pendingSummary — collapse the dead "Grades post" repetition (#14) ── describe('pendingSummary — six pending rows collapse to ONE line', () => { test('all-awaiting card → one summary counting props + players', () => { const strips = [ { player: 'One', props: [{ stat: 'TB', line: 1.5, awaiting: true }, { stat: 'HR', line: 0.5, awaiting: true }] }, { player: 'Two', props: [{ stat: 'Hits', line: 0.5, awaiting: true }] }, ]; const s = adapter.pendingSummary(strips); expect(s).not.toBeNull(); expect(s.count).toBe(3); expect(s.players).toBe(2); }); test('any graded prop present → no collapse (the card has real reads to show)', () => { const strips = [ { player: 'One', props: [{ stat: 'TB', line: 1.5, grade: 'A' }] }, { player: 'Two', props: [{ stat: 'Hits', line: 0.5, awaiting: true }] }, ]; expect(adapter.pendingSummary(strips)).toBeNull(); }); test('no awaiting props at all → null', () => { expect(adapter.pendingSummary([{ player: 'One', props: [] }])).toBeNull(); expect(adapter.pendingSummary([])).toBeNull(); expect(adapter.pendingSummary(null)).toBeNull(); }); }); // ── 5. topReadForCard — the ONE bold hero per card (#2) ──────────────────── describe('topReadForCard — the single best graded prop leads the card', () => { const strips = [ { player: 'Mid', team: 'NYY', props: [{ stat: 'Hits', line: 0.5, side: 'O', grade: 'B' }] }, { player: 'Best', team: 'BOS', archetype: { primary: 'BOMBER' }, props: [{ stat: 'TB', line: 1.5, side: 'O', grade: 'A+' }] }, { player: 'Dead', team: 'LAD', props: [{ stat: 'HR', line: 0.5, side: 'O', grade: 'A+', dead: true }] }, ]; test('picks the highest-tier live grade (dead reads never lead)', () => { const top = adapter.topReadForCard(strips); expect(top).not.toBeNull(); expect(top.player).toBe('Best'); expect(top.grade).toBe('A+'); expect(top.stat).toBe('TB'); }); test('no graded props → null (nothing to promote)', () => { expect(adapter.topReadForCard([{ player: 'X', props: [{ stat: 'TB', line: 1, awaiting: true }] }])).toBeNull(); expect(adapter.topReadForCard([])).toBeNull(); }); }); // ── 6. GameCard.tsx — one hero + pending collapse + real entities ───────── describe('GameCard.tsx wires the DS2 rebuild', () => { const src = read('components/vyndr/GameCard.tsx'); test('leads with the real team entity (logo) + a team-colored accent edge', () => { expect(src).toContain(' { expect(src).toContain('topReadForCard'); expect(src).toMatch(/fontVariantNumeric:\s*'tabular-nums'/); // the hero grade badge is the largest on the card (strips use size 'sm'). expect(src).toMatch(/size=\{48\}|size="lg"/); }); test('collapses all-awaiting cards to ONE pending line (kills the #14 repetition)', () => { expect(src).toContain('pendingSummary'); expect(src).toContain('nextRunLabelET'); expect(src).toContain('props pending'); }); }); // ── 7. dashboard/page.tsx — the never-empty hero + varying rankings ──────── describe('dashboard Top grades tonight — proof-first, ranked, honest', () => { const src = read('app/dashboard/page.tsx'); test('uses the never-empty engine (heroFallbackState / buildHeroReceipts)', () => { expect(src).toMatch(/heroFallbackState|buildHeroReceipts/); }); test('ranks tonight grades by the varying signal (selectTopGrades) and shows confidence', () => { expect(src).toContain('selectTopGrades'); expect(src).toContain('confidence'); }); test('falls back to yesterday PROVEN A-tier receipts (with the settled result)', () => { expect(src).toContain('/api/ledger/model'); expect(src).toMatch(/HIT|PROVEN|YESTERDAY/); }); test('still keeps the honest schedule-derived waiting copy for the truly-empty case (QA.22)', () => { expect(src).toContain('nextRunLabelET'); }); });