// DS4 (Design v2) — the BILLBOARDS. Screenshot-first surfaces (the timeline is // customer #1): the STREAKS row, the grade reveal, the CLV reframe, and the /u // public profile. The .tsx surfaces are asserted against source (plain-JS Jest, // no TS transform) — same pattern as publicProfilePage / vyndrParityQA. The // CLV flat-vs-spread decision is a pure fn and is exercised directly. 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'); // ── 1. CLV reframe — the pure flat/spread decision (#16) ────────────────── describe('clvDisplay — flat CLV says so, spread shows bars', () => { const { clvMode, isFlatClv, CLV_FLAT_LINE } = require('../../web/src/lib/clvDisplay'); test('near-flat (73/74 at the close) is FLAT, not a broken histogram', () => { const dist = [ { label: '[-.5,0)', side: 'faded', count: 0 }, { label: '0', side: 'flat', count: 73 }, { label: '(0,.5]', side: 'beat', count: 1 }, ]; expect(clvMode(dist).mode).toBe('flat'); expect(isFlatClv(dist)).toBe(true); }); test('real dispersion is SPREAD (the bars are meaningful)', () => { const dist = [ { label: '[-1,-.5)', side: 'faded', count: 8 }, { label: '[-.5,0)', side: 'faded', count: 6 }, { label: '0', side: 'flat', count: 5 }, { label: '(0,.5]', side: 'beat', count: 9 }, { label: '(.5,1]', side: 'beat', count: 12 }, ]; expect(clvMode(dist).mode).toBe('spread'); expect(isFlatClv(dist)).toBe(false); }); test('null / empty / all-zero → none (renders nothing, never errored)', () => { expect(clvMode(null).mode).toBe('none'); expect(clvMode([]).mode).toBe('none'); expect(clvMode([{ side: 'flat', count: 0 }, { side: 'beat', count: 0 }]).mode).toBe('none'); }); test('the flat line is confident + VOICE-compliant (no jargon, no hype)', () => { expect(CLV_FLAT_LINE).toMatch(/grade the outcome, not the close/); expect(CLV_FLAT_LINE).not.toMatch(/!/); expect(CLV_FLAT_LINE.toLowerCase()).not.toMatch(/bayesian|regression|guarantee/); }); test('the ledger MODEL tab renders the flat line, not a histogram, when flat', () => { const src = read('app/ledger/page.tsx'); expect(src).toContain("import { clvMode, CLV_FLAT_LINE }"); expect(src).toMatch(/mode === 'flat'/); expect(src).toContain('CLV_FLAT_LINE'); // bars still exist for the spread branch expect(src).toContain('CLV DISTRIBUTION'); }); }); // ── 2. STREAKS row — the Bloomberg alert (#2) ───────────────────────────── describe('StreaksPanel — one hero figure, real identity, one accent', () => { const src = read('components/StreaksPanel.tsx'); test('uses the real PlayerAvatar entity (not a bare )', () => { expect(src).toContain('import PlayerAvatar'); expect(src).toContain(' { // heroNum renders currentStreak and is the biggest fontSize; the player // name is demoted well below it. expect(src).toMatch(/heroNum[\s\S]*fontSize:\s*38/); expect(src).toContain('{s.currentStreak}'); const heroSize = Number((src.match(/heroNum:[^}]*fontSize:\s*(\d+)/) || [])[1]); const nameSize = Number((src.match(/playerName:[^}]*fontSize:\s*(\d+)/) || [])[1]); expect(heroSize).toBeGreaterThan(nameSize); expect(heroSize).toBeGreaterThanOrEqual(32); }); test('the hero number is mono + tabular (data grammar)', () => { expect(src).toMatch(/heroNum:[\s\S]*fontVariantNumeric:\s*'tabular-nums'/); }); test('carries the muted "built vs" lens context', () => { expect(src).toContain('built vs'); expect(src).toContain('builtVs'); }); test('ONE severity accent — step-up amber / step-down green', () => { expect(src).toContain("diff === 'step up'"); expect(src).toContain('var(--amber'); expect(src).toContain("diff === 'step down'"); expect(src).toContain('var(--g-a'); }); test('the grade badge is tier-gated (the READ is the paid layer)', () => { expect(src).toMatch(/tier === 'analyst' \|\| tier === 'desk'/); expect(src).toContain(' { const src = read('components/vyndr/GradeResultCard.tsx'); test('a negative edge NEVER renders green — negative = var(--miss)', () => { // DS3 superseded DS4's local const with the centralized colorContract // enforcer — same semantics (negative → var(--miss)), now via the shared // helper. Both the confidence strip and the projection row route edge // through edgeColor(d.edge), never a hardcoded green. expect(src).toMatch(/import \{ edgeColor.*\} from '@\/lib\/colorContract'/); expect(src).toContain('color: edgeColor(d.edge)'); expect(src).toMatch(/d\.edge != null \? edgeColor\(d\.edge\) : 'var\(--text-2\)'/); }); test('the grade LETTER is still the hero (largest element)', () => { expect(src).toMatch(/grade-hero[\s\S]*fontSize: compact \? 92 : 116/); }); test('the MODEL/LINE/EDGE row is mono + tabular (demoted data)', () => { expect(src).toMatch(/fontSize: 19[\s\S]*fontVariantNumeric: 'tabular-nums'/); }); test('reveal choreography is reduced-motion safe', () => { const proc = read('components/vyndr/ProcessingGrade.tsx'); expect(proc).toContain("prefers-reduced-motion: reduce"); expect(proc).toMatch(/setPhase\('card'\)/); }); }); // ── 4. /u public profile — the shareable record billboard (#4) ──────────── describe('PublicProfile — the record hero (Session 65: no CLV claim)', () => { const src = read('app/u/[handle]/PublicProfile.tsx'); test('the hit rate is the bold hero figure (large mono tabular)', () => { expect(src).toMatch(/fontSize: 56[\s\S]*fontVariantNumeric: 'tabular-nums'/); expect(src).toContain('{agg.hit_pct}%'); expect(src).toContain('HIT RATE'); }); // Session 65 — UN-CLAIM. The beat-close figure and the ✓ CLV-VERIFIED badge // are GONE from this public surface: both read beat_close_pct, derived from // the legacy overwritable closing_line (C4 open). Display removal only — the // aggregate and its CLV_CAPTURE_RELIABLE gate in ledgerService are untouched. test('no closing-line claim renders on the public record hero', () => { expect(src).not.toContain('{agg.beat_close_pct}%'); expect(src).not.toContain('BEAT CLOSE'); expect(src).not.toContain('CLV-VERIFIED'); expect(src).not.toMatch(/clvVerified/); }); test('still honors the n-gate: RECORD BUILDING under min_sample', () => { expect(src).toContain('RECORD BUILDING'); expect(src).toMatch(/settled >= minSample/); }); test('renders real player identity (PlayerAvatar entity)', () => { expect(src).toContain('import PlayerAvatar'); expect(src).toContain(' { const src = read('app/u/[handle]/opengraph-image.tsx'); test('social crop size is preserved (1200x630)', () => { expect(src).toMatch(/size = \{ width: 1200, height: 630 \}/); }); test('renders the real hit% when the record is published, and claims no CLV', () => { expect(src).toContain('{rec.hit_pct}%'); // Session 65 — beat-close% + the CLV-VERIFIED eyebrow are un-claimed here. expect(src).not.toContain('{rec.beat_close_pct}%'); expect(src).not.toMatch(/CLV-VERIFIED|CLV-verified/); expect(src).toContain('SETTLED RECORD · 30D'); }); test('falls back gracefully to an honest tagline when there is no record', () => { expect(src).toContain('Every settled read · wins and misses · nothing curated'); }); });