Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions frontend/src/pages/CharacterRankingsTab.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down
22 changes: 21 additions & 1 deletion frontend/src/pages/CharacterRankingsTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<div className="mt-4">
Expand All @@ -86,6 +91,15 @@ export default function CharacterRankingsTab({ data }: { data: CharacterRankings
))}
</select>
)}
<select
value={scope}
onChange={e => setScope(e.target.value as 'raid' | 'group')}
className="px-2 py-1 text-[0.82rem]"
aria-label="Content type"
>
<option value="raid">Raids</option>
<option value="group">Heroics</option>
</select>
{(['dps', 'hps'] as Metric[]).map(m => (
<button
key={m}
Expand All @@ -102,6 +116,12 @@ export default function CharacterRankingsTab({ data }: { data: CharacterRankings
</span>
</div>

{zones.length === 0 && (
<p className="text-text-muted text-[0.85rem] mb-4">
No ranked {scope === 'raid' ? 'raid' : 'heroic'} kills{xpac ? ' in this expansion' : ''}.
</p>
)}

{zones.map(zone => {
const allstars = metric === 'dps' ? zone.dps_allstars : zone.hps_allstars
return (
Expand Down
Loading