72 lines
3.6 KiB
TypeScript
72 lines
3.6 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import {
|
|
leaderboardReturnHref,
|
|
playerContextHref,
|
|
profileViewHref
|
|
} from '../../src/lib/leaderboard-navigation.js';
|
|
|
|
describe('leaderboard profile navigation', () => {
|
|
it('preserves leaderboard scope, search and page while starting profile history on its first page', () => {
|
|
const source = '/leaderboard?game=t6&map=t6%3Atown&metric=kills&q=Player+One&offset=50';
|
|
const profile = new URL(playerContextHref('001/2?#', source), 'http://localhost');
|
|
expect(profile.pathname).toBe('/leaderboard/players/001%2F2%3F%23');
|
|
expect(profile.searchParams.get('returnTo')).toBe(source);
|
|
expect(profile.searchParams.get('game')).toBe('t6');
|
|
expect(profile.searchParams.get('map')).toBe('t6:town');
|
|
expect(profile.searchParams.get('metric')).toBe('kills');
|
|
expect(profile.searchParams.has('q')).toBe(false);
|
|
expect(profile.searchParams.has('offset')).toBe(false);
|
|
});
|
|
|
|
it('keeps profile filters and return context through pagination and resets history pages on filter changes', () => {
|
|
const current = new URL(
|
|
'http://localhost/leaderboard/players/101?returnTo=%2Fleaderboard%3Fq%3DAce&game=t5&map=t5%3Atheater&metric=highestRound&offset=25'
|
|
);
|
|
const next = new URL(profileViewHref(current, { offset: '50' }), current);
|
|
expect(next.searchParams.get('offset')).toBe('50');
|
|
expect(next.searchParams.get('returnTo')).toBe('/leaderboard?q=Ace');
|
|
expect(next.searchParams.get('map')).toBe('t5:theater');
|
|
const filtered = new URL(profileViewHref(current, { game: 't6', map: '' }), current);
|
|
expect(filtered.searchParams.has('offset')).toBe(false);
|
|
expect(filtered.searchParams.get('map')).toBe('');
|
|
expect(filtered.searchParams.get('game')).toBe('t6');
|
|
expect(filtered.searchParams.get('returnTo')).toBe('/leaderboard?q=Ace');
|
|
});
|
|
|
|
it('preserves explicit all maps and squad scope through profile links and paging', () => {
|
|
const source = '/leaderboard?map=&players=2&metric=highestRound';
|
|
expect(leaderboardReturnHref(source)).toBe(source);
|
|
const profile = new URL(playerContextHref('101', source), 'http://localhost');
|
|
expect(profile.searchParams.get('map')).toBe('');
|
|
expect(profile.searchParams.get('players')).toBe('2');
|
|
const next = new URL(profileViewHref(profile, { offset: '25' }), profile);
|
|
expect(next.searchParams.get('map')).toBe('');
|
|
expect(next.searchParams.get('players')).toBe('2');
|
|
});
|
|
|
|
it('restricts supplied return destinations to the local leaderboard', () => {
|
|
for (const value of [
|
|
null,
|
|
'',
|
|
'https://example.com/leaderboard',
|
|
'//example.com/leaderboard',
|
|
'/leaderboard/players/101',
|
|
'/leaderboard/../settings',
|
|
'/leaderboard\\@example.com'
|
|
]) {
|
|
expect(leaderboardReturnHref(value)).toBe('/leaderboard');
|
|
}
|
|
expect(leaderboardReturnHref('/leaderboard?q=A%26B&unrelated=drop#fragment')).toBe(
|
|
'/leaderboard?q=A%26B'
|
|
);
|
|
});
|
|
|
|
it('uses the displayed fallback scope when a shared leaderboard URL contains unknown filters', () => {
|
|
const source = '/leaderboard?game=t7&metric=unknown&q=101';
|
|
const profile = new URL(playerContextHref('101', source), 'http://localhost');
|
|
expect(profile.searchParams.get('returnTo')).toBe(source);
|
|
expect(profile.searchParams.has('game')).toBe(false);
|
|
expect(profile.searchParams.has('metric')).toBe(false);
|
|
});
|
|
});
|