mirror of
https://github.com/Sea-Haven-Industries/proposal-system.git
synced 2026-10-07 16:18:57 +00:00
77 lines
2.4 KiB
TypeScript
77 lines
2.4 KiB
TypeScript
|
|
/**
|
||
|
|
* QA-C5: Auth storage module tests (replaces the Redux authSlice tests).
|
||
|
|
*
|
||
|
|
* Tests the sessionStorage-backed session persistence (WEB-C1):
|
||
|
|
* - setAuthUser/getAuthUser round-trip
|
||
|
|
* - getAuthUser tolerates malformed stored JSON
|
||
|
|
* - clearAuth removes the stored session
|
||
|
|
* - isTokenValid accepts unexpired JWTs and rejects expired/malformed ones
|
||
|
|
*/
|
||
|
|
import { describe, it, expect, beforeEach } from 'vitest';
|
||
|
|
import type { AuthUser } from '@proposal-system/api-contracts';
|
||
|
|
import { getAuthUser, setAuthUser, clearAuth, isTokenValid } from '../authStorage';
|
||
|
|
import { STORAGE_KEY_TOKEN } from '../../../constants';
|
||
|
|
|
||
|
|
function createToken(expOffsetSeconds: number): string {
|
||
|
|
const header = btoa(JSON.stringify({ alg: 'HS256' }));
|
||
|
|
const payload = btoa(JSON.stringify({
|
||
|
|
sub: 'test-user',
|
||
|
|
exp: Math.floor(Date.now() / 1000) + expOffsetSeconds,
|
||
|
|
}));
|
||
|
|
return `${header}.${payload}.fake-signature`;
|
||
|
|
}
|
||
|
|
|
||
|
|
const user: AuthUser = {
|
||
|
|
id: 'user-1',
|
||
|
|
email: 'admin@test.com',
|
||
|
|
displayName: 'Admin',
|
||
|
|
role: 'Admin',
|
||
|
|
token: createToken(3600),
|
||
|
|
};
|
||
|
|
|
||
|
|
describe('authStorage', () => {
|
||
|
|
beforeEach(() => {
|
||
|
|
window.sessionStorage.clear();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('QA-C5: setAuthUser persists to sessionStorage and getAuthUser reads it back', () => {
|
||
|
|
setAuthUser(user);
|
||
|
|
|
||
|
|
expect(window.sessionStorage.getItem(STORAGE_KEY_TOKEN)).not.toBeNull();
|
||
|
|
expect(getAuthUser()).toEqual(user);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('QA-C5: getAuthUser returns null when nothing is stored', () => {
|
||
|
|
expect(getAuthUser()).toBeNull();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('QA-C5: getAuthUser returns null for malformed stored JSON', () => {
|
||
|
|
window.sessionStorage.setItem(STORAGE_KEY_TOKEN, 'not-valid-json{{{');
|
||
|
|
|
||
|
|
expect(getAuthUser()).toBeNull();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('QA-C5: clearAuth removes the stored session', () => {
|
||
|
|
setAuthUser(user);
|
||
|
|
clearAuth();
|
||
|
|
|
||
|
|
expect(window.sessionStorage.getItem(STORAGE_KEY_TOKEN)).toBeNull();
|
||
|
|
expect(getAuthUser()).toBeNull();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('QA-C5: isTokenValid accepts a token expiring in the future', () => {
|
||
|
|
expect(isTokenValid(createToken(3600))).toBe(true);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('QA-C5: isTokenValid rejects an expired token', () => {
|
||
|
|
expect(isTokenValid(createToken(-3600))).toBe(false);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('QA-C5: isTokenValid rejects missing or malformed tokens', () => {
|
||
|
|
expect(isTokenValid(null)).toBe(false);
|
||
|
|
expect(isTokenValid(undefined)).toBe(false);
|
||
|
|
expect(isTokenValid('')).toBe(false);
|
||
|
|
expect(isTokenValid('not-a-jwt')).toBe(false);
|
||
|
|
});
|
||
|
|
});
|