Files
electric-cherry/tests/unit/ui-player-map-records.test.ts
T
2026-10-10 13:50:53 -04:00

162 lines
5.3 KiB
TypeScript

import { expect, it, vi } from 'vitest';
import { render } from 'svelte/server';
import { writable } from 'svelte/store';
import PlayerProfilePage from '../../src/routes/leaderboard/players/[guid]/+page.svelte';
import PlayerMapCards from '../../src/lib/ui/components/PlayerMapCards.svelte';
import type { PlayerMapRecord, PlayerProfile, RecordEvidence } from '../../src/lib/leaderboard.js';
vi.mock('$app/stores', () => ({
page: writable({
url: new URL('http://localhost/leaderboard/players/101?players=2'),
data: { user: null }
})
}));
vi.mock('$app/navigation', () => ({ goto: vi.fn(), invalidateAll: vi.fn() }));
const evidence: RecordEvidence = {
matchId: 71,
game: 't5',
mapKey: 't5:theater',
mapName: 'Kino Der Toten',
server: 't5_zombie_theater_1',
startedAt: '2026-10-06T12:00:00Z',
endedAt: '2026-10-06T13:00:00Z',
startObserved: true,
presentAtStart: true,
firstObservedRound: 0,
value: 22
};
const stats = {
highestRound: 22,
bestKills: 507,
bestScore: 5290,
kills: 722,
roundsSurvived: 41,
headshots: 10,
revives: 2,
downs: 3,
gamesPlayed: 9,
gamesCompleted: 8
};
const map: PlayerMapRecord = {
...stats,
game: 't5',
key: 't5:theater',
name: 'Kino Der Toten',
lastSeen: evidence.endedAt!,
ranks: { highestRound: 7, bestKills: 12, bestScore: 3 },
records: {
highestRound: evidence,
bestKills: { ...evidence, matchId: 72, value: 507 },
bestScore: { ...evidence, matchId: 73, value: 5290 }
}
};
function expectRankedRecords(body: string) {
for (const [label, rank] of [
['Best round', 7],
['Best kills', 12],
['Best score', 3]
]) {
expect(body).toContain(`aria-label="Kino Der Toten ${label} rank ${rank}"`);
expect(body).toContain(`Rank #${rank}`);
}
for (const id of [71, 72, 73]) expect(body).toContain(`/matches/${id}?returnTo=`);
for (const value of ['22', '507', '5,290']) expect(body).toContain(`>${value}</a>`);
}
it('shows each record rank and preserves match links in mobile map cards', () => {
expectRankedRecords(
render(PlayerMapCards, {
props: { maps: [map], returnTo: '/leaderboard/players/101?players=2' }
}).body
);
});
it('shows the same ranks in the desktop profile with lifetime map scope explained', () => {
const profile: PlayerProfile = {
guid: '101',
name: 'Cherry',
firstSeen: evidence.startedAt,
lastSeen: evidence.endedAt!,
stats,
records: map.records,
maps: [map],
matches: [],
matchesTotal: 0,
limit: 25,
offset: 0
};
const body = render(PlayerProfilePage, {
props: {
data: {
profile,
returnTo: '/leaderboard',
scope: { game: '', map: '', players: '2', metric: 'kills', entry: null }
}
}
}).body;
const table = body.slice(body.indexOf('<table'), body.indexOf('</table>'));
expectRankedRecords(table);
expect(body.replace(/\s+/g, ' ')).toContain(
'Lifetime personal bests across all squad sizes, ranked against other players on each map.'
);
expect(body).toContain('Tied records share a rank.');
expect(body).not.toContain('No qualifying match history yet');
expect(body).toContain('Show all completed matches');
});
it('renders a known player without qualifying history with identity and unavailable personal bests', () => {
const profile: PlayerProfile = {
guid: '101',
name: 'New player',
firstSeen: evidence.startedAt,
lastSeen: evidence.startedAt,
stats: {
highestRound: 0,
bestKills: 0,
bestScore: 0,
kills: 0,
roundsSurvived: 0,
headshots: 0,
revives: 0,
downs: 0,
gamesPlayed: 0,
gamesCompleted: 0
},
records: null,
maps: [],
matches: [],
matchesTotal: 0,
limit: 25,
offset: 0
};
const body = render(PlayerProfilePage, {
props: {
data: {
profile,
returnTo: '/leaderboard',
scope: { game: '', map: '', players: '', metric: 'highestRound', entry: null }
}
}
}).body;
const text = body.replace(/<[^>]*>/g, ' ').replace(/\s+/g, ' ');
expect(text).toContain('New player');
expect(text).toContain('No qualifying match history yet');
expect(text).toContain('Stats appear after a recorded game ends');
expect(text).toContain('observed at round 2 or later');
expect(text).toContain('Lifetime best round —');
expect(text).toContain('Best game kills —');
expect(text).toContain('Highest reported score —');
expect(text).toContain('Lifetime games played 0');
expect(text).toContain('No map records yet');
expect(text).toContain('No qualifying matches recorded');
expect(text).toContain('First seen');
expect(text).toContain('Last seen');
expect(body).toContain('Player GUID');
expect(body).not.toContain('/matches/');
expect(body).not.toContain('Show all completed matches');
expect(body).not.toContain('<table');
expect(body).not.toContain('NaN');
});