diff --git a/frontend/src/pages/CharacterRankingsTab.test.tsx b/frontend/src/pages/CharacterRankingsTab.test.tsx index b870a093..12065b39 100644 --- a/frontend/src/pages/CharacterRankingsTab.test.tsx +++ b/frontend/src/pages/CharacterRankingsTab.test.tsx @@ -106,6 +106,41 @@ describe('CharacterRankingsTab', () => { expect(screen.queryByText("Veeshan's Peak")).not.toBeInTheDocument() }) + it('scope dropdown defaults to raids and switches to heroics', () => { + archetype = 'Fighter' + renderTab({ + ...DATA, + zones: [ + { ...DATA.zones[0], zone: 'Emerald Halls', scope: 'raid', expansion: 'KoS' }, + { ...DATA.zones[0], zone: 'Obelisk of Blight', scope: 'group', expansion: 'KoS' }, + ], + }) + // Raids by default — the heroic section is hidden. + expect(screen.getByText('Emerald Halls')).toBeInTheDocument() + expect(screen.queryByText('Obelisk of Blight')).not.toBeInTheDocument() + fireEvent.change(screen.getByLabelText('Content type'), { target: { value: 'group' } }) + expect(screen.getByText('Obelisk of Blight')).toBeInTheDocument() + expect(screen.queryByText('Emerald Halls')).not.toBeInTheDocument() + }) + + it('falls back to heroics when the character has no raid kills', () => { + archetype = 'Fighter' + renderTab({ + ...DATA, + zones: [{ ...DATA.zones[0], zone: 'Obelisk of Blight', scope: 'group', expansion: 'KoS' }], + }) + expect(screen.getByText('Obelisk of Blight')).toBeInTheDocument() + }) + + it('shows an empty state when the filter combo has no kills', () => { + archetype = 'Fighter' + renderTab() // raid-only fixture + expect(screen.queryByText(/No ranked/)).not.toBeInTheDocument() + fireEvent.change(screen.getByLabelText('Content type'), { target: { value: 'group' } }) + expect(screen.getByText(/No ranked heroic kills in this expansion/)).toBeInTheDocument() + expect(screen.queryByText('Deathtoll')).not.toBeInTheDocument() + }) + it('shows dashes for a metric the character never parsed', () => { archetype = 'Fighter' renderTab({ diff --git a/frontend/src/pages/CharacterRankingsTab.tsx b/frontend/src/pages/CharacterRankingsTab.tsx index 815d2448..07d7aa1a 100644 --- a/frontend/src/pages/CharacterRankingsTab.tsx +++ b/frontend/src/pages/CharacterRankingsTab.tsx @@ -69,7 +69,12 @@ export default function CharacterRankingsTab({ data }: { data: CharacterRankings // Expansion filter — the server sends only expansions this character has // ranked kills in, newest first. const [xpac, setXpac] = useState(() => data.expansions[0]?.short ?? '') - const zones = xpac ? data.zones.filter(z => z.expansion === xpac) : data.zones + // Scope filter — raids by default; fall back to heroics only when the + // character has no raid sections at all. + const [scope, setScope] = useState<'raid' | 'group'>(() => + data.zones.some(z => z.scope === 'raid') ? 'raid' : 'group', + ) + const zones = data.zones.filter(z => z.scope === scope && (!xpac || z.expansion === xpac)) return (
+ No ranked {scope === 'raid' ? 'raid' : 'heroic'} kills{xpac ? ' in this expansion' : ''}. +
+ )} + {zones.map(zone => { const allstars = metric === 'dps' ? zone.dps_allstars : zone.hps_allstars return (