test: add session management tests
This commit is contained in:
@@ -0,0 +1,198 @@
|
||||
import { describe, it, expect, beforeEach } from '@jest/globals';
|
||||
import {
|
||||
createSession,
|
||||
isSessionValid,
|
||||
getSessionAge,
|
||||
getSessionTimeRemaining,
|
||||
isSessionExpired,
|
||||
createSessionWithCustomExpiration,
|
||||
Session,
|
||||
SessionData,
|
||||
} from './session';
|
||||
|
||||
describe('session management', () => {
|
||||
describe('createSession', () => {
|
||||
it('should create session with user data', () => {
|
||||
const session = createSession({ userId: '123', role: 'admin' });
|
||||
expect(session).toBeDefined();
|
||||
expect(session.userId).toBe('123');
|
||||
expect(session.role).toBe('admin');
|
||||
});
|
||||
|
||||
it('should create session with createdAt timestamp', () => {
|
||||
const beforeCreate = Date.now();
|
||||
const session = createSession({ userId: '123' });
|
||||
const afterCreate = Date.now();
|
||||
expect(session.createdAt).toBeGreaterThanOrEqual(beforeCreate);
|
||||
expect(session.createdAt).toBeLessThanOrEqual(afterCreate);
|
||||
});
|
||||
|
||||
it('should create session with 24 hour expiration', () => {
|
||||
const session = createSession({ userId: '123' });
|
||||
const expectedExpiration = session.createdAt + (24 * 60 * 60 * 1000);
|
||||
expect(session.expiresAt).toBe(expectedExpiration);
|
||||
});
|
||||
|
||||
it('should create session without optional role', () => {
|
||||
const session = createSession({ userId: '123' });
|
||||
expect(session.userId).toBe('123');
|
||||
expect(session.role).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('isSessionValid', () => {
|
||||
it('should return true for valid session', () => {
|
||||
const session = createSession({ userId: '123' });
|
||||
expect(isSessionValid(session)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for expired session', () => {
|
||||
const expiredSession = createSessionWithCustomExpiration({ userId: '123' }, -1000);
|
||||
expect(isSessionValid(expiredSession)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for session with zero expiration time', () => {
|
||||
const session = createSessionWithCustomExpiration({ userId: '123' }, 0);
|
||||
expect(isSessionValid(session)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true for session with 1ms remaining', () => {
|
||||
const session = createSessionWithCustomExpiration({ userId: '123' }, 1);
|
||||
expect(isSessionValid(session)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getSessionAge', () => {
|
||||
it('should return age of session in milliseconds', () => {
|
||||
const session = createSession({ userId: '123' });
|
||||
const age = getSessionAge(session);
|
||||
expect(age).toBeGreaterThanOrEqual(0);
|
||||
expect(age).toBeLessThan(100);
|
||||
});
|
||||
|
||||
it('should increase over time', async () => {
|
||||
const session = createSession({ userId: '123' });
|
||||
const age1 = getSessionAge(session);
|
||||
await new Promise(resolve => setTimeout(resolve, 10));
|
||||
const age2 = getSessionAge(session);
|
||||
expect(age2).toBeGreaterThan(age1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getSessionTimeRemaining', () => {
|
||||
it('should return positive time for valid session', () => {
|
||||
const session = createSession({ userId: '123' });
|
||||
const remaining = getSessionTimeRemaining(session);
|
||||
expect(remaining).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('should return approximately 24 hours for new session', () => {
|
||||
const session = createSession({ userId: '123' });
|
||||
const remaining = getSessionTimeRemaining(session);
|
||||
const expectedRemaining = 24 * 60 * 60 * 1000;
|
||||
const tolerance = 100;
|
||||
expect(remaining).toBeGreaterThanOrEqual(expectedRemaining - tolerance);
|
||||
expect(remaining).toBeLessThanOrEqual(expectedRemaining + tolerance);
|
||||
});
|
||||
|
||||
it('should return 0 for expired session', () => {
|
||||
const expiredSession = createSessionWithCustomExpiration({ userId: '123' }, -1000);
|
||||
const remaining = getSessionTimeRemaining(expiredSession);
|
||||
expect(remaining).toBe(0);
|
||||
});
|
||||
|
||||
it('should return 0 for session at exact expiration time', () => {
|
||||
const session = createSessionWithCustomExpiration({ userId: '123' }, 0);
|
||||
const remaining = getSessionTimeRemaining(session);
|
||||
expect(remaining).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isSessionExpired', () => {
|
||||
it('should return false for valid session', () => {
|
||||
const session = createSession({ userId: '123' });
|
||||
expect(isSessionExpired(session)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true for expired session', () => {
|
||||
const expiredSession = createSessionWithCustomExpiration({ userId: '123' }, -1000);
|
||||
expect(isSessionExpired(expiredSession)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true for session at exact expiration time', () => {
|
||||
const session = createSessionWithCustomExpiration({ userId: '123' }, 0);
|
||||
expect(isSessionExpired(session)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for session with 1ms remaining', () => {
|
||||
const session = createSessionWithCustomExpiration({ userId: '123' }, 1);
|
||||
expect(isSessionExpired(session)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('createSessionWithCustomExpiration', () => {
|
||||
it('should create session with custom expiration time', () => {
|
||||
const session = createSessionWithCustomExpiration({ userId: '123' }, 60000);
|
||||
const expectedExpiration = session.createdAt + 60000;
|
||||
expect(session.expiresAt).toBe(expectedExpiration);
|
||||
});
|
||||
|
||||
it('should create session with negative expiration time', () => {
|
||||
const session = createSessionWithCustomExpiration({ userId: '123' }, -1000);
|
||||
const expectedExpiration = session.createdAt - 1000;
|
||||
expect(session.expiresAt).toBe(expectedExpiration);
|
||||
});
|
||||
|
||||
it('should preserve user data', () => {
|
||||
const session = createSessionWithCustomExpiration(
|
||||
{ userId: '123', role: 'admin' },
|
||||
60000
|
||||
);
|
||||
expect(session.userId).toBe('123');
|
||||
expect(session.role).toBe('admin');
|
||||
});
|
||||
});
|
||||
|
||||
describe('session lifecycle', () => {
|
||||
it('should track session from creation to expiration', async () => {
|
||||
const session = createSessionWithCustomExpiration({ userId: '123' }, 100);
|
||||
|
||||
expect(isSessionValid(session)).toBe(true);
|
||||
expect(isSessionExpired(session)).toBe(false);
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 150));
|
||||
|
||||
expect(isSessionValid(session)).toBe(false);
|
||||
expect(isSessionExpired(session)).toBe(true);
|
||||
});
|
||||
|
||||
it('should have consistent age and time remaining', () => {
|
||||
const session = createSessionWithCustomExpiration({ userId: '123' }, 10000);
|
||||
const age = getSessionAge(session);
|
||||
const remaining = getSessionTimeRemaining(session);
|
||||
const totalLifetime = age + remaining;
|
||||
|
||||
expect(totalLifetime).toBeCloseTo(10000, -2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('session data integrity', () => {
|
||||
it('should maintain session data immutability', () => {
|
||||
const originalData: SessionData = { userId: '123', role: 'admin' };
|
||||
const session = createSession(originalData);
|
||||
|
||||
expect(session.userId).toBe(originalData.userId);
|
||||
expect(session.role).toBe(originalData.role);
|
||||
});
|
||||
|
||||
it('should handle empty role gracefully', () => {
|
||||
const session = createSession({ userId: '123', role: '' });
|
||||
expect(session.role).toBe('');
|
||||
});
|
||||
|
||||
it('should handle special characters in userId', () => {
|
||||
const session = createSession({ userId: 'user-123@example.com' });
|
||||
expect(session.userId).toBe('user-123@example.com');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,43 @@
|
||||
import { describe, it, expect } from '@jest/globals';
|
||||
|
||||
export interface SessionData {
|
||||
userId: string;
|
||||
role?: string;
|
||||
}
|
||||
|
||||
export interface Session extends SessionData {
|
||||
createdAt: number;
|
||||
expiresAt: number;
|
||||
}
|
||||
|
||||
export function createSession(userData: SessionData): Session {
|
||||
return {
|
||||
...userData,
|
||||
createdAt: Date.now(),
|
||||
expiresAt: Date.now() + (24 * 60 * 60 * 1000),
|
||||
};
|
||||
}
|
||||
|
||||
export function isSessionValid(session: Session): boolean {
|
||||
return Date.now() < session.expiresAt;
|
||||
}
|
||||
|
||||
export function getSessionAge(session: Session): number {
|
||||
return Date.now() - session.createdAt;
|
||||
}
|
||||
|
||||
export function getSessionTimeRemaining(session: Session): number {
|
||||
return Math.max(0, session.expiresAt - Date.now());
|
||||
}
|
||||
|
||||
export function isSessionExpired(session: Session): boolean {
|
||||
return Date.now() >= session.expiresAt;
|
||||
}
|
||||
|
||||
export function createSessionWithCustomExpiration(userData: SessionData, expiresInMs: number): Session {
|
||||
return {
|
||||
...userData,
|
||||
createdAt: Date.now(),
|
||||
expiresAt: Date.now() + expiresInMs,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user