// Pure unit test of the open-redirect guard — no DOM needed. The safelist is // the security-load-bearing part of the auth flow, so it gets a direct test. import { describe, expect, test } from 'vitest' import { safeNext } from './redirect' describe('safeNext', () => { test('passes a same-origin absolute path through', () => { expect(safeNext('/dashboard', '/')).toBe('/dashboard') expect(safeNext('/a/b?x=1', '/')).toBe('/a/b?x=1') }) test('falls back to home for a missing value', () => { expect(safeNext(null, '/home')).toBe('/home') expect(safeNext(undefined, '/home')).toBe('/home') expect(safeNext('', '/home')).toBe('/home') }) test('rejects cross-origin + protocol-relative + absolute URLs', () => { expect(safeNext('https://evil.example/login', '/')).toBe('/') expect(safeNext('//evil.example', '/')).toBe('/') expect(safeNext('/\\evil.example', '/')).toBe('/') expect(safeNext('javascript:alert(1)', '/')).toBe('/') }) })