import { describe, it, expect } from 'vitest'; import { SessionLifetime } from '../../../../packages/automation-domain/value-objects/SessionLifetime'; describe('SessionLifetime Value Object', () => { describe('Construction', () => { it('should create with valid expiry date', () => { const futureDate = new Date(Date.now() + 3600000); expect(() => new SessionLifetime(futureDate)).not.toThrow(); }); it('should create with null expiry (no expiration)', () => { expect(() => new SessionLifetime(null)).not.toThrow(); }); it('should reject invalid dates', () => { const invalidDate = new Date('invalid'); expect(() => new SessionLifetime(invalidDate)).toThrow(); }); it('should reject dates in the past', () => { const pastDate = new Date(Date.now() - 3600000); expect(() => new SessionLifetime(pastDate)).toThrow(); }); }); describe('isExpired()', () => { it('should return true for expired date', () => { const pastDate = new Date(Date.now() - 1000); const lifetime = new SessionLifetime(pastDate); expect(lifetime.isExpired()).toBe(true); }); it('should return false for valid future date', () => { const futureDate = new Date(Date.now() + 3600000); const lifetime = new SessionLifetime(futureDate); expect(lifetime.isExpired()).toBe(false); }); it('should return false for null expiry (never expires)', () => { const lifetime = new SessionLifetime(null); expect(lifetime.isExpired()).toBe(false); }); it('should consider buffer time (5 minutes)', () => { const nearExpiryDate = new Date(Date.now() + 240000); const lifetime = new SessionLifetime(nearExpiryDate); expect(lifetime.isExpired()).toBe(true); }); it('should not consider expired when beyond buffer', () => { const safeDate = new Date(Date.now() + 360000); const lifetime = new SessionLifetime(safeDate); expect(lifetime.isExpired()).toBe(false); }); }); describe('isExpiringSoon()', () => { it('should return true for date within buffer window', () => { const soonDate = new Date(Date.now() + 240000); const lifetime = new SessionLifetime(soonDate); expect(lifetime.isExpiringSoon()).toBe(true); }); it('should return false for date far in future', () => { const farDate = new Date(Date.now() + 3600000); const lifetime = new SessionLifetime(farDate); expect(lifetime.isExpiringSoon()).toBe(false); }); it('should return false for null expiry', () => { const lifetime = new SessionLifetime(null); expect(lifetime.isExpiringSoon()).toBe(false); }); it('should return true exactly at buffer boundary (5 minutes)', () => { const boundaryDate = new Date(Date.now() + 300000); const lifetime = new SessionLifetime(boundaryDate); expect(lifetime.isExpiringSoon()).toBe(true); }); }); describe('Edge Cases', () => { it('should handle timezone correctly', () => { const utcDate = new Date('2025-12-31T23:59:59Z'); const lifetime = new SessionLifetime(utcDate); expect(lifetime.getExpiry()).toEqual(utcDate); }); it('should handle millisecond precision', () => { const preciseDate = new Date(Date.now() + 299999); const lifetime = new SessionLifetime(preciseDate); expect(lifetime.isExpiringSoon()).toBe(true); }); it('should provide remaining time', () => { const futureDate = new Date(Date.now() + 3600000); const lifetime = new SessionLifetime(futureDate); const remaining = lifetime.getRemainingTime(); expect(remaining).toBeGreaterThan(3000000); expect(remaining).toBeLessThanOrEqual(3600000); }); }); });