Files
vyndr/tests/unit/vyndrCoreScreens.test.js
T
builtbykev c8790fde55 Session 57: Phase 0 — Kill the Lies (2309 tests)
Work-order Phase 0 (Jul 10 live audit): every fabricated UI element deleted
or rewired to real data. Deletion sprint — no new product features.

0.1 Fake NBA game: root cause was scheduleService fetching the ESPN
    scoreboard with no ?dates= param or date filter — off-season ESPN
    returns the NEAREST slate (Jun 13 NYK@SA Finals rendered as tonight).
    Now pinned to the requested ET date + defensive filter; undated events
    dropped. Honest month-aware per-sport empty states (lib/emptyState.js).
0.2 Fake header counters: liveTick stripped to a bare 1s pulse (the
    auto-incrementing "247 graded", sin-driven brain-%, aPlus/cascades are
    dead). New GET /api/snapshot/summary (cache-only, before /:sport) +
    Next proxy; HeartbeatBar shows the real graded count and SYNC =
    elapsed since the last pipeline run (amber past 5 min).
0.3 Ticker: hardcoded fallback items deleted (real snapshot exhaust only);
    MOVE kept — computeLineDeltas is real movement. <4 real items → no
    ticker; bar publishes --ticker-h so the fixed header collapses cleanly.
0.4 /terminal retired: route redirects to /dashboard; VVI/injury-wire/
    leaders layouts preserved unrouted as §12 content-engine templates.
    Nav PRIMARY = Slate/Scan/Ledger; BottomTabBar Terminal→Explore; PWA
    shortcut Terminal→Ledger; #terminal alias → /dashboard.
0.5 ›Query nav pill deleted (duplicate /scan link).

Backend 2289 → 2309 tests (199 suites), web build exit 0.
Spec: specs/phase-0-kill-the-lies.md. Next: work-order Phase 1 (ledger
persistence + settlement).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 20:17:49 -04:00

160 lines
6.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// VYNDR 2.0 — Phase D core screens (Session 35). Adapter LOGIC is exercised
// directly via the CommonJS gradeAdapter; the .tsx screens/components are
// asserted against source text (the plain-JS Jest config has no TS transform).
const fs = require('fs');
const path = require('path');
const WEB = path.join(__dirname, '..', '..', 'web', 'src');
const read = (rel) => fs.readFileSync(path.join(WEB, rel), 'utf8');
const adapter = require('../../web/src/lib/gradeAdapter');
describe('Phase D — grade adapter (engine → §7 contract)', () => {
const base = {
player: 'Nikola Jokic', sport: 'NBA', stat: 'home_runs', line: 26.5, direction: 'over',
grade: 'A', projection: 29.4, confidence: 67, sample_size: 34,
factors: { matchup: 'soft interior', trend: 'hot', usage: 'up', rest: 'rested', pace: 'fast' },
kill_conditions: [{ code: 'BLOWOUT', reason: 'Blowout risk caps minutes' }],
alt_lines: [{ line: 24.5, grade: 'A+' }, { line: 28.5, grade: 'B' }],
};
it('maps direction → side and humanizes the stat', () => {
const out = adapter.mapScanToGradeResult({ ...base, tier: 'desk' });
expect(out.side).toBe('Over');
expect(out.stat).toBe('Home Runs');
expect(out.player).toBe('Nikola Jokic');
});
it('computes a signed percentage edge from projection vs line', () => {
expect(adapter.computeEdge(29.4, 26.5, 'over')).toBeCloseTo(10.9, 1);
expect(adapter.computeEdge(24, 26.5, 'over')).toBeLessThan(0);
expect(adapter.computeEdge(24, 26.5, 'under')).toBeGreaterThan(0);
});
it('flags phosphor confirmed only for A/A+ with strong support', () => {
expect(adapter.isPhosphorConfirmed('A+', 80, 40)).toBe(true);
expect(adapter.isPhosphorConfirmed('A', 50, 35)).toBe(true); // sample carries it
expect(adapter.isPhosphorConfirmed('B', 90, 90)).toBe(false);
expect(adapter.isPhosphorConfirmed('A', 40, 5)).toBe(false);
});
it('FREE tier teases 3 signals, hides kill conditions and the alt ladder', () => {
const out = adapter.mapScanToGradeResult({ ...base, tier: 'free' });
expect(out.signals.length).toBe(3);
expect(out.killConditions).toEqual([]);
expect(out.altLadder).toEqual([]);
});
it('ANALYST tier shows kill conditions + all signals, but no alt ladder', () => {
const out = adapter.mapScanToGradeResult({ ...base, tier: 'analyst' });
expect(out.signals.length).toBe(5);
expect(out.killConditions).toEqual(['Blowout risk caps minutes']);
expect(out.altLadder).toEqual([]);
});
it('DESK tier unlocks the alt line ladder', () => {
const out = adapter.mapScanToGradeResult({ ...base, tier: 'desk' });
expect(out.altLadder).toEqual([{ line: 24.5, grade: 'A+' }, { line: 28.5, grade: 'B' }]);
});
it('defaults missing fields safely', () => {
const out = adapter.mapScanToGradeResult({});
expect(out.grade).toBe('—');
expect(out.side).toBe('Over');
expect(out.signals).toEqual([]);
expect(out.books).toEqual([]);
});
});
describe('Phase D — GradeResultCard (the core moment)', () => {
const src = read('components/vyndr/GradeResultCard.tsx');
it('renders the grade letter at hero size (92116px)', () => {
expect(src).toContain('116');
expect(src).toContain('92');
});
it('uses the intel-surface for the grade hero zone + grade-reveal', () => {
expect(src).toContain('intel-surface');
expect(src).toContain('grade-reveal');
});
it('highlights the best book with green tint + green left border', () => {
expect(src).toContain('rgba(0,212,160,.13)');
expect(src).toContain("borderLeft: b.best ? '2px solid var(--g-a)'");
});
it('renders kill conditions with amber border, gated on non-empty', () => {
expect(src).toContain('hasKill');
expect(src).toContain('rgba(255,179,71,.4)');
expect(src).toContain('KILL CONDITIONS');
});
it('self-hides books / alt ladder when empty', () => {
expect(src).toContain('hasBooks');
expect(src).toContain('hasAlt');
});
});
describe('Phase D — ProcessingGrade', () => {
const src = read('components/vyndr/ProcessingGrade.tsx');
it('plays the factor-ignite + proc-scan sequence then reveals the card', () => {
expect(src).toContain('factor-ignite');
expect(src).toContain('proc-scan');
expect(src).toContain('<GradeResultCard');
});
});
describe('Phase D — GameCard (Bloomberg best/worst lines)', () => {
const src = read('components/vyndr/GameCard.tsx');
it('renders team abbreviations', () => {
expect(src).toContain('g.away.abbr');
expect(src).toContain('g.home.abbr');
});
it('best line = green tint + green border; worst = subtle red', () => {
expect(src).toContain('rgba(0,212,160,.13)');
expect(src).toContain('rgba(255,82,82,.07)');
});
it('shows a live-dot for live games and grades props with GradeBadge', () => {
expect(src).toContain('live-dot');
expect(src).toContain('<GradeBadge');
});
});
describe('Phase D — ClaimMeter', () => {
const src = read('components/vyndr/ClaimMeter.tsx');
it('renders the amber founder-seat scarcity bar', () => {
expect(src).toContain('CLAIMED');
expect(src).toContain('var(--amber)');
});
});
// Session 57 (Phase 0) — the Terminal surface was fabricated sample data
// (Finals-era NBA content rendered as live intelligence). The route now
// redirects to /dashboard; the layouts survive UNROUTED as §12 templates.
describe('Phase 0 — Terminal retired (fabricated surface)', () => {
it('the route redirects to the slate instead of rendering fake intel', () => {
const src = read('app/terminal/page.tsx');
expect(src).toContain("redirect('/dashboard')");
expect(src).not.toContain('INJURY_WIRE');
expect(src).not.toContain('Wembanyama');
});
it('preserves the VVI / cascade / leaders layouts as unrouted templates', () => {
const tpl = read('components/intel/TerminalTemplates.tsx');
expect(tpl).toContain('NOT ROUTED');
expect(tpl).toContain('VOLATILITY INDEX');
expect(tpl).toContain('INJURY WIRE');
expect(tpl).toContain('GRADEABLE LEADERS');
});
});
describe('Phase D — scan + landing wiring', () => {
it('scan renders the new ProcessingGrade card via the adapter (legacy GradeCard removed)', () => {
const src = read('app/scan/page.tsx');
expect(src).toContain('ProcessingGrade');
expect(src).toContain('mapScanToGradeResult');
expect(src).not.toContain("from '@/components/GradeCard'");
});
it('scan keeps sportsbook deep-links safe (noopener noreferrer)', () => {
expect(read('app/scan/page.tsx')).toContain('noopener noreferrer');
});
it('landing mounts the ClaimMeter', () => {
expect(read('app/page.tsx')).toContain('ClaimMeter');
});
});