80481d6f6a
- StreaksPanel renders THE LENS (interpreted read + tonight difficulty) + snapshot grade letters; streaks are FREE for every tier per the product definition (the picture is free, the read is paid) — only hot lists keep the free top-3 gate. - One stat selection now filters ALL layers: card props narrow together with streaks + hot lists (Slate activeStat → slateGameToCardData). - /explore = server SEO shell (daily-indexable: 'MLB Hit Streaks, Hot Hitters & Stat Leaders') + ExploreHub client: leaders + full streaks + hot lists, real-tier gated, defaults to the in-season sport. - Landing teaser fixed: it pointed at NBA (off-season → self-hid forever); now MLB top-3 through the lens — the anonymous-visitor hook actually shows. - Player dossier: ACTIVE STREAKS block (free, lens reads) via new ?player= filter on /api/streaks/:sport. - Schedule layer already the Slate base (mergeSlate) — verified, no change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
45 lines
1.9 KiB
JavaScript
45 lines
1.9 KiB
JavaScript
// Session 42 — Stats Explorer; Session 60 (night2/C) — the AGGREGATOR hub.
|
|
// The page is now a server shell (SEO metadata) around the ExploreHub client
|
|
// component: leaders + full streaks + hot lists = the "entire picture" page.
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const WEB = path.join(__dirname, '..', '..', 'web', 'src');
|
|
const hub = fs.readFileSync(path.join(WEB, 'components', 'ExploreHub.tsx'), 'utf8');
|
|
const shell = fs.readFileSync(path.join(WEB, 'app', 'explore', 'page.tsx'), 'utf8');
|
|
|
|
describe('Stats Explorer hub (client)', () => {
|
|
it('consumes the real /api/stats/leaders endpoint', () => {
|
|
expect(hub).toContain('/api/stats/leaders');
|
|
});
|
|
it('has NBA/MLB/WNBA sport tabs + a player search filter', () => {
|
|
expect(hub).toContain('NBA');
|
|
expect(hub).toContain('MLB');
|
|
expect(hub).toContain('WNBA');
|
|
expect(hub).toContain('Search players');
|
|
});
|
|
it('rows link to the player profile', () => {
|
|
expect(hub).toContain('playerHref');
|
|
});
|
|
it('handles loading / error / empty states', () => {
|
|
expect(hub).toContain("'loading'");
|
|
expect(hub).toContain("'error'");
|
|
expect(hub).toContain('No graded props');
|
|
});
|
|
// Session 60 — the aggregator: full streaks + hot lists on one page,
|
|
// gated by the REAL tier (streaks free for all; hot lists top-3 free).
|
|
it('mounts the streaks + hot-list aggregator with the real tier', () => {
|
|
expect(hub).toContain('<StreaksPanel sport={sport} tier={tier}');
|
|
expect(hub).toContain('<HotListPanel sport={sport} tier={tier}');
|
|
});
|
|
});
|
|
|
|
describe('Explore page shell (server, SEO)', () => {
|
|
it('is a server component carrying daily-indexable metadata', () => {
|
|
expect(shell).not.toContain("'use client'");
|
|
expect(shell).toContain('export const metadata');
|
|
expect(shell).toContain('Hit Streaks');
|
|
expect(shell).toContain('<ExploreHub />');
|
|
});
|
|
});
|