121 lines
4.5 KiB
TypeScript
121 lines
4.5 KiB
TypeScript
import { OnlineDetectionService } from '../../../../src/domain/services/online-detection.service';
|
|
import { TimeWindow } from '../../../../src/domain/value-objects/time-window.vo';
|
|
|
|
describe('OnlineDetectionService', () => {
|
|
let service: OnlineDetectionService;
|
|
|
|
beforeEach(() => {
|
|
service = new OnlineDetectionService();
|
|
});
|
|
|
|
describe('isOnline', () => {
|
|
it('should return true for recent heartbeat', () => {
|
|
const now = new Date();
|
|
const recentTimestamp = Math.floor(now.getTime() / 1000) - 60; // 60 seconds ago
|
|
|
|
expect(service.isOnline(recentTimestamp, now)).toBe(true);
|
|
});
|
|
|
|
it('should return true for heartbeat within window', () => {
|
|
const now = new Date();
|
|
const withinWindow = Math.floor(now.getTime() / 1000) - 179; // 179 seconds ago (within 180 window)
|
|
|
|
expect(service.isOnline(withinWindow, now)).toBe(true);
|
|
});
|
|
|
|
it('should return false for heartbeat at window boundary', () => {
|
|
const now = new Date();
|
|
const atBoundary = Math.floor(now.getTime() / 1000) - 180; // Exactly 180 seconds ago
|
|
|
|
expect(service.isOnline(atBoundary, now)).toBe(false);
|
|
});
|
|
|
|
it('should return false for old heartbeat', () => {
|
|
const now = new Date();
|
|
const oldTimestamp = Math.floor(now.getTime() / 1000) - 300; // 5 minutes ago
|
|
|
|
expect(service.isOnline(oldTimestamp, now)).toBe(false);
|
|
});
|
|
|
|
it('should return false for very old heartbeat', () => {
|
|
const now = new Date();
|
|
const veryOldTimestamp = Math.floor(now.getTime() / 1000) - 3600; // 1 hour ago
|
|
|
|
expect(service.isOnline(veryOldTimestamp, now)).toBe(false);
|
|
});
|
|
|
|
it('should return true for heartbeat just now', () => {
|
|
const now = new Date();
|
|
const justNow = Math.floor(now.getTime() / 1000);
|
|
|
|
expect(service.isOnline(justNow, now)).toBe(true);
|
|
});
|
|
|
|
it('should use current time when no time provided', () => {
|
|
const justNow = Math.floor(Date.now() / 1000);
|
|
|
|
expect(service.isOnline(justNow)).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('getOnlineThreshold', () => {
|
|
it('should return correct threshold timestamp', () => {
|
|
const now = new Date('2025-01-01T12:00:00.000Z');
|
|
const threshold = service.getOnlineThreshold(now);
|
|
|
|
const expectedTimestamp = Math.floor(now.getTime() / 1000) - TimeWindow.DEFAULT_ONLINE_WINDOW_SECONDS;
|
|
expect(threshold).toBe(expectedTimestamp);
|
|
});
|
|
|
|
it('should use current time when no time provided', () => {
|
|
const beforeCall = Math.floor(Date.now() / 1000) - TimeWindow.DEFAULT_ONLINE_WINDOW_SECONDS;
|
|
const threshold = service.getOnlineThreshold();
|
|
const afterCall = Math.floor(Date.now() / 1000) - TimeWindow.DEFAULT_ONLINE_WINDOW_SECONDS;
|
|
|
|
expect(threshold).toBeGreaterThanOrEqual(beforeCall);
|
|
expect(threshold).toBeLessThanOrEqual(afterCall);
|
|
});
|
|
});
|
|
|
|
describe('getWindowSeconds', () => {
|
|
it('should return default window seconds', () => {
|
|
expect(service.getWindowSeconds()).toBe(TimeWindow.DEFAULT_ONLINE_WINDOW_SECONDS);
|
|
});
|
|
|
|
it('should return 180 seconds', () => {
|
|
expect(service.getWindowSeconds()).toBe(180);
|
|
});
|
|
});
|
|
|
|
describe('integration scenarios', () => {
|
|
it('should correctly determine online status for multiple users', () => {
|
|
const now = new Date();
|
|
const nowTimestamp = Math.floor(now.getTime() / 1000);
|
|
|
|
const users = [
|
|
{ id: 1, lastHeartbeat: nowTimestamp - 30, expectedOnline: true }, // 30s ago
|
|
{ id: 2, lastHeartbeat: nowTimestamp - 90, expectedOnline: true }, // 90s ago
|
|
{ id: 3, lastHeartbeat: nowTimestamp - 150, expectedOnline: true }, // 150s ago
|
|
{ id: 4, lastHeartbeat: nowTimestamp - 180, expectedOnline: false }, // 180s ago (boundary)
|
|
{ id: 5, lastHeartbeat: nowTimestamp - 200, expectedOnline: false }, // 200s ago
|
|
];
|
|
|
|
users.forEach((user) => {
|
|
expect(service.isOnline(user.lastHeartbeat, now)).toBe(user.expectedOnline);
|
|
});
|
|
});
|
|
|
|
it('should work correctly with getOnlineThreshold', () => {
|
|
const now = new Date();
|
|
const threshold = service.getOnlineThreshold(now);
|
|
|
|
// Users with timestamp > threshold should be online
|
|
expect(service.isOnline(threshold + 1, now)).toBe(true);
|
|
|
|
// Users with timestamp <= threshold should be offline
|
|
expect(service.isOnline(threshold, now)).toBe(false);
|
|
expect(service.isOnline(threshold - 1, now)).toBe(false);
|
|
});
|
|
});
|
|
});
|