import { PresenceService } from './presence.service'; describe('PresenceService', () => { const pipeline = { exists: jest.fn().mockReturnThis(), exec: jest.fn(), }; const redis = { set: jest.fn(), exists: jest.fn(), raw: { scan: jest.fn(), pipeline: jest.fn(() => pipeline), }, }; let service: PresenceService; beforeEach(() => { jest.clearAllMocks(); service = new PresenceService(redis as never); }); it('touches player key with 120s TTL', async () => { await service.touch(42n); expect(redis.set).toHaveBeenCalledWith('presence:player:42', '1', 120); }); it('checks single player online status', async () => { redis.exists.mockResolvedValue(true); await expect(service.isOnline(7n)).resolves.toBe(true); expect(redis.exists).toHaveBeenCalledWith('presence:player:7'); }); it('counts online keys via SCAN', async () => { redis.raw.scan .mockResolvedValueOnce(['1', ['presence:player:1', 'presence:player:2']]) .mockResolvedValueOnce(['0', ['presence:player:3']]); await expect(service.getOnlineCount()).resolves.toBe(3); expect(redis.raw.scan).toHaveBeenCalledWith( '0', 'MATCH', 'presence:player:*', 'COUNT', 200, ); }); it('filters online ids with pipeline exists', async () => { pipeline.exec.mockResolvedValue([ [null, 1], [null, 0], [null, 1], ]); const result = await service.filterOnlineIds([10n, 20n, 30n]); expect(result).toEqual(new Set(['10', '30'])); expect(pipeline.exists).toHaveBeenCalledTimes(3); expect(pipeline.exists).toHaveBeenNthCalledWith(1, 'presence:player:10'); expect(pipeline.exists).toHaveBeenNthCalledWith(2, 'presence:player:20'); expect(pipeline.exists).toHaveBeenNthCalledWith(3, 'presence:player:30'); }); it('returns empty set when no ids provided', async () => { await expect(service.filterOnlineIds([])).resolves.toEqual(new Set()); expect(redis.raw.pipeline).not.toHaveBeenCalled(); }); });