import { describe, expect, it } from 'vitest'; import { contextHref, returnLabel, safeReturnHref } from '../../src/lib/navigation-context.js'; describe('navigation context', () => { it('restores Bank filters, pagination and the selected player from detail pages', () => { const source = '/bank?view=transactions&game=t5&offset=25&player=00042&historyOffset=25'; const target = new URL(contextHref('/matches/17', source), 'http://localhost'); expect(safeReturnHref(target.searchParams.get('returnTo'), '/')).toBe(source); expect(returnLabel(source)).toBe('Back to Bank'); }); it('retains nested origins, list scope, loaded results and anchors', () => { const source = new URL( 'http://localhost/leaderboard/players/42?game=t5&offset=25&returnTo=%2Fleaderboard%3Fq%3DAce#history-title' ); const match = new URL(contextHref('/matches/123', source), source); expect(safeReturnHref(match.searchParams.get('returnTo'), '/matches')).toBe( source.pathname + source.search + source.hash ); expect(returnLabel(match.searchParams.get('returnTo')!)).toBe('Back to player'); expect(returnLabel('/collections?view=history&launches=30')).toBe('Back to launch history'); }); it('retains Maintenance filters and a selected result when opening a detail', () => { const source = '/maintenance?view=activity&state=failed&offset=25#operation-12'; const target = new URL(contextHref('/provisioning/12', source), 'http://localhost'); expect(safeReturnHref(target.searchParams.get('returnTo'), '/')).toBe(source); expect(returnLabel(source)).toBe('Back to Maintenance'); }); it.each(['/activity', '/operations'])( 'replaces retired %s return links with their current history', (path) => { const source = `${path}?server=town&host=host-1&state=failed&offset=25`; const expected = '/servers/town?tab=history&host=host-1&state=failed&offset=25'; expect(safeReturnHref(source, '/')).toBe(expected); const target = new URL(contextHref('/provisioning/12', source), 'http://localhost'); expect(target.searchParams.get('returnTo')).toBe(expected); expect(returnLabel(expected)).toBe('Back to server'); } ); it('preserves the selected diagnostic tab on both sides of a contextual link', () => { const url = new URL( contextHref( '/servers/t5_zombie_theater_1?tab=logs&log=console', '/maintenance/incident?returnTo=%2Fmaintenance%3Fview%3Dactivity' ), 'http://localhost' ); expect(url.searchParams.get('tab')).toBe('logs'); expect(url.searchParams.get('log')).toBe('console'); expect(url.searchParams.get('returnTo')).toBe( '/maintenance/incident?returnTo=%2Fmaintenance%3Fview%3Dactivity' ); }); it.each([ '//evil.test', 'https://evil.test/', '/api/auth/logout', '/login', '/hosts/../../api/hosts', '/\\evil.test', '/hosts\n/42', '/unknown', '/' + 'x'.repeat(12000) ])('rejects unsafe or unsupported return paths: %s', (value) => { expect(safeReturnHref(value, '/betas')).toBe('/betas'); }); });