// Wave 3 (Addition 2) — RECORD BY GRADE TIER. // The tier calibration IS the credibility: A+ wins more than A, A more than // B. This suite locks (a) the shared row-building logic, (b) the tier order, // and (c) that the ONE shared TierRecord component is imported + rendered on // all three record surfaces (dashboard, /u, ledger). Plain-JS Jest — the .tsx // is asserted against source (same pattern as publicProfilePage/vyndrAppShell). 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 exists = (rel) => fs.existsSync(path.join(WEB, rel)); const { buildTierRows, TIER_ORDER, anyTierReady, isEdgeTier } = require('../../web/src/lib/tierRecord'); describe('buildTierRows — honesty rules', () => { // A ≥20 tier carries a real hit_pct (gate applied upstream); a small tier // arrives with hit_pct null even though it has settles. const byTier = { 'A+': { settled: 22, hits: 18, misses: 4, pushes: 0, hit_pct: 82 }, A: { settled: 25, hits: 17, misses: 8, pushes: 0, hit_pct: 68 }, B: { settled: 3, hits: 2, misses: 1, pushes: 0, hit_pct: null }, // small sample }; test('shows each tier W-L record ALWAYS, even at small n', () => { const rows = buildTierRows(byTier); const b = rows.find((r) => r.tier === 'B'); expect(b).toBeTruthy(); expect(b.record).toBe('2-1'); // honest at n=3 const ap = rows.find((r) => r.tier === 'A+'); expect(ap.record).toBe('18-4'); }); test('shows the hit-% ONLY when hit_pct != null; else RECORD BUILDING', () => { const rows = buildTierRows(byTier); const ap = rows.find((r) => r.tier === 'A+'); expect(ap.ready).toBe(true); expect(ap.hitPct).toBe(82); // Small-sample tier: no percentage, building copy with the settled count. const b = rows.find((r) => r.tier === 'B'); expect(b.ready).toBe(false); expect(b.hitPct).toBeNull(); expect(b.buildingLabel).toBe('RECORD BUILDING · 3 settled'); }); test('never fabricates a 0% from a null hit_pct (Number(null)===0 guard)', () => { const rows = buildTierRows({ C: { settled: 5, hits: 0, misses: 0, pushes: 0, hit_pct: null } }); expect(rows[0].hitPct).toBeNull(); expect(rows[0].ready).toBe(false); }); test('omits tiers with zero settled reads (no fake empty rows)', () => { const rows = buildTierRows({ A: { settled: 0, hits: 0, misses: 0, hit_pct: null }, B: { settled: 4, hits: 3, misses: 1, hit_pct: null } }); expect(rows.map((r) => r.tier)).toEqual(['B']); }); test('empty / missing map → no rows (self-hides)', () => { expect(buildTierRows(null)).toEqual([]); expect(buildTierRows(undefined)).toEqual([]); expect(buildTierRows({})).toEqual([]); }); }); describe('tier order + edge color contract', () => { test('renders A+ → F in canonical order', () => { expect(TIER_ORDER).toEqual(['A+', 'A', 'B', 'C', 'D', 'F']); }); test('buildTierRows preserves A+ → F order regardless of map insertion order', () => { const rows = buildTierRows({ F: { settled: 2, hits: 0, misses: 2, hit_pct: null }, A: { settled: 3, hits: 2, misses: 1, hit_pct: null }, 'A+': { settled: 4, hits: 4, misses: 0, hit_pct: null }, C: { settled: 5, hits: 2, misses: 3, hit_pct: null }, }); expect(rows.map((r) => r.tier)).toEqual(['A+', 'A', 'C', 'F']); }); test('GLOW RESERVED FOR A-TIER — only A+/A are edge tiers', () => { expect(isEdgeTier('A+')).toBe(true); expect(isEdgeTier('A')).toBe(true); expect(isEdgeTier('B')).toBe(false); expect(isEdgeTier('C')).toBe(false); expect(isEdgeTier('F')).toBe(false); }); test('anyTierReady reflects the upstream n≥20 gate', () => { expect(anyTierReady({ A: { settled: 5, hits: 3, misses: 2, hit_pct: null } })).toBe(false); expect(anyTierReady({ A: { settled: 25, hits: 17, misses: 8, hit_pct: 68 } })).toBe(true); }); }); describe('the ONE shared component reaches all three record surfaces', () => { test('TierRecord.tsx exists and is exported from the vyndr barrel', () => { expect(exists('components/vyndr/TierRecord.tsx')).toBe(true); expect(read('components/vyndr/index.ts')).toContain("export { default as TierRecord } from './TierRecord'"); }); test('TierRecord renders W-L always + % only when ready, else BUILDING', () => { const src = read('components/vyndr/TierRecord.tsx'); expect(src).toContain('buildTierRows'); expect(src).toContain('{r.record}'); // W-L always expect(src).toContain('{r.hitPct}% HIT'); // % only in the ready branch expect(src).toContain('RECORD BUILDING · {r.settled} settled'); }); test('/u PublicProfile imports AND renders TierRecord', () => { const src = read('app/u/[handle]/PublicProfile.tsx'); expect(src).toMatch(/import TierRecord from '@\/components\/vyndr\/TierRecord'/); expect(src).toContain(' { const src = read('app/dashboard/page.tsx'); expect(src).toMatch(/TierRecord/); expect(src).toContain(' { const src = read('app/ledger/page.tsx'); expect(src).toContain('TierRecord'); expect(src).toContain('