import { afterEach, expect, test, vi } from 'vitest'; import { canAdminister, canOperate, clearAccessToken, getAccessToken, notifyUnauthorizedSession, PLATFORM_UNAUTHORIZED_EVENT, setAccessToken } from './session'; afterEach(() => { window.sessionStorage.clear(); window.localStorage.clear(); }); test('access token is scoped to the browser session and can be cleared', () => { setAccessToken(' secret-token '); expect(getAccessToken()).toBe('secret-token'); expect(window.localStorage.length).toBe(0); clearAccessToken(); expect(getAccessToken()).toBe(''); }); test('role helpers follow the server permission hierarchy', () => { expect(canOperate({ name: 'v', role: 'viewer', authMode: 'enforce' })).toBe(false); expect(canOperate({ name: 'o', role: 'operator', authMode: 'enforce' })).toBe(true); expect(canAdminister({ name: 'o', role: 'operator', authMode: 'enforce' })).toBe(false); expect(canAdminister({ name: 'a', role: 'admin', authMode: 'enforce' })).toBe(true); }); test('invalidates only the currently active rejected token', () => { const unauthorized = vi.fn(); window.addEventListener(PLATFORM_UNAUTHORIZED_EVENT, unauthorized); setAccessToken('new-token'); expect(notifyUnauthorizedSession('old-token')).toBe(false); expect(getAccessToken()).toBe('new-token'); expect(notifyUnauthorizedSession('new-token')).toBe(true); expect(getAccessToken()).toBe(''); expect(notifyUnauthorizedSession('new-token')).toBe(false); expect(unauthorized).toHaveBeenCalledTimes(1); window.removeEventListener(PLATFORM_UNAUTHORIZED_EVENT, unauthorized); });