Files

246 lines
8.7 KiB
TypeScript

import { RedisService } from '../../../src/Application/Services/RedisService';
import { logStartup, logError } from '../../../src/Application/Services/Logger';
describe('RedisService', () => {
let redisService: RedisService;
beforeAll(async () => {
redisService = RedisService.getInstance();
try {
await redisService.connect();
} catch (error) {
console.log('Redis not available for testing, skipping Redis tests');
return;
}
});
afterAll(async () => {
if (redisService.isRedisConnected()) {
await redisService.disconnect();
}
});
beforeEach(async () => {
// Skip tests if Redis is not connected
if (!redisService.isRedisConnected()) {
return;
}
// Clean up test data
const activeChats = await redisService.getAllActiveChats();
for (const chat of activeChats) {
if (chat.chatId.startsWith('test-')) {
await redisService.removeActiveChat(chat.chatId);
}
}
await redisService.removeActiveUser('test-user-1');
await redisService.removeActiveUser('test-user-2');
});
describe('Active Chat Management', () => {
it('should store and retrieve active chats', async () => {
if (!redisService.isRedisConnected()) {
return;
}
const testChatData = {
chatId: 'test-chat-1',
participants: ['user-1', 'user-2'],
lastActivity: new Date(),
messageCount: 5,
chatType: 'direct' as const,
name: 'Test Chat'
};
await redisService.setActiveChat('test-chat-1', testChatData);
const retrieved = await redisService.getActiveChat('test-chat-1');
expect(retrieved).toBeDefined();
expect(retrieved!.chatId).toBe('test-chat-1');
expect(retrieved!.participants).toEqual(['user-1', 'user-2']);
expect(retrieved!.messageCount).toBe(5);
expect(retrieved!.chatType).toBe('direct');
expect(retrieved!.name).toBe('Test Chat');
});
it('should return null for non-existent chat', async () => {
if (!redisService.isRedisConnected()) {
return;
}
const retrieved = await redisService.getActiveChat('non-existent-chat');
expect(retrieved).toBeNull();
});
it('should remove active chats', async () => {
if (!redisService.isRedisConnected()) {
return;
}
const testChatData = {
chatId: 'test-chat-2',
participants: ['user-1', 'user-2'],
lastActivity: new Date(),
messageCount: 0,
chatType: 'group' as const
};
await redisService.setActiveChat('test-chat-2', testChatData);
let retrieved = await redisService.getActiveChat('test-chat-2');
expect(retrieved).toBeDefined();
await redisService.removeActiveChat('test-chat-2');
retrieved = await redisService.getActiveChat('test-chat-2');
expect(retrieved).toBeNull();
});
it('should update chat activity', async () => {
if (!redisService.isRedisConnected()) {
return;
}
const originalTime = new Date(Date.now() - 60000); // 1 minute ago
const testChatData = {
chatId: 'test-chat-3',
participants: ['user-1', 'user-2'],
lastActivity: originalTime,
messageCount: 5,
chatType: 'direct' as const
};
await redisService.setActiveChat('test-chat-3', testChatData);
// Wait a bit to ensure timestamp difference
await new Promise(resolve => setTimeout(resolve, 10));
await redisService.updateChatActivity('test-chat-3', 6);
const retrieved = await redisService.getActiveChat('test-chat-3');
expect(retrieved).toBeDefined();
expect(retrieved!.messageCount).toBe(6);
expect(retrieved!.lastActivity.getTime()).toBeGreaterThan(originalTime.getTime());
});
});
describe('Active User Management', () => {
it('should store and retrieve active users', async () => {
if (!redisService.isRedisConnected()) {
return;
}
const testUserData = {
userId: 'test-user-1',
activeChatIds: ['chat-1', 'chat-2'],
lastActivity: new Date(),
isOnline: true
};
await redisService.setActiveUser('test-user-1', testUserData);
const retrieved = await redisService.getActiveUser('test-user-1');
expect(retrieved).toBeDefined();
expect(retrieved!.userId).toBe('test-user-1');
expect(retrieved!.activeChatIds).toEqual(['chat-1', 'chat-2']);
expect(retrieved!.isOnline).toBe(true);
});
it('should manage user-chat associations', async () => {
if (!redisService.isRedisConnected()) {
return;
}
// Add user to chats
await redisService.addUserToChat('test-user-2', 'chat-1');
await redisService.addUserToChat('test-user-2', 'chat-2');
let activeChatIds = await redisService.getUserActiveChats('test-user-2');
expect(activeChatIds).toContain('chat-1');
expect(activeChatIds).toContain('chat-2');
// Remove user from one chat
await redisService.removeUserFromChat('test-user-2', 'chat-1');
activeChatIds = await redisService.getUserActiveChats('test-user-2');
expect(activeChatIds).not.toContain('chat-1');
expect(activeChatIds).toContain('chat-2');
});
});
describe('Inactive Chat Cleanup', () => {
it('should identify inactive chats', async () => {
if (!redisService.isRedisConnected()) {
return;
}
const oldTime = new Date(Date.now() - 2 * 60 * 60 * 1000); // 2 hours ago
const recentTime = new Date();
// Create an inactive chat
await redisService.setActiveChat('test-inactive-chat', {
chatId: 'test-inactive-chat',
participants: ['user-1', 'user-2'],
lastActivity: oldTime,
messageCount: 3,
chatType: 'direct'
});
// Create an active chat
await redisService.setActiveChat('test-active-chat', {
chatId: 'test-active-chat',
participants: ['user-1', 'user-3'],
lastActivity: recentTime,
messageCount: 1,
chatType: 'direct'
});
const inactiveChats = await redisService.getInactiveChats(60); // 60 minutes
expect(inactiveChats).toContain('test-inactive-chat');
expect(inactiveChats).not.toContain('test-active-chat');
// Cleanup
await redisService.removeActiveChat('test-inactive-chat');
await redisService.removeActiveChat('test-active-chat');
});
it('should cleanup inactive chats', async () => {
if (!redisService.isRedisConnected()) {
return;
}
const oldTime = new Date(Date.now() - 2 * 60 * 60 * 1000); // 2 hours ago
await redisService.setActiveChat('test-cleanup-chat', {
chatId: 'test-cleanup-chat',
participants: ['user-1', 'user-2'],
lastActivity: oldTime,
messageCount: 0,
chatType: 'direct'
});
const cleanedUp = await redisService.cleanupInactiveChats(60);
expect(cleanedUp).toContain('test-cleanup-chat');
// Verify chat was removed
const retrieved = await redisService.getActiveChat('test-cleanup-chat');
expect(retrieved).toBeNull();
});
});
describe('Health Check', () => {
it('should ping Redis successfully', async () => {
if (!redisService.isRedisConnected()) {
return;
}
const pingResult = await redisService.ping();
expect(pingResult).toBe(true);
});
it('should report connection status', () => {
const isConnected = redisService.isRedisConnected();
expect(typeof isConnected).toBe('boolean');
});
});
});