import { describe, it, expect, beforeAll, afterAll, beforeEach } from '@jest/globals'; import { AppDataSource } from '../../../src/Infrastructure/ormconfig'; import { ChatRepository } from '../../../src/Infrastructure/Repository/ChatRepository'; import { ChatArchiveRepository } from '../../../src/Infrastructure/Repository/ChatArchiveRepository'; import { UserRepository } from '../../../src/Infrastructure/Repository/UserRepository'; import { ChatType } from '../../../src/Domain/Chat/ChatAggregate'; import { UserState } from '../../../src/Domain/User/UserAggregate'; import { v4 as uuidv4 } from 'uuid'; describe('Chat Messaging System', () => { let chatRepository: ChatRepository; let chatArchiveRepository: ChatArchiveRepository; let userRepository: UserRepository; let testUser1: any; let testUser2: any; let testPremiumUser: any; beforeAll(async () => { if (!AppDataSource.isInitialized) { await AppDataSource.initialize(); } chatRepository = new ChatRepository(); chatArchiveRepository = new ChatArchiveRepository(); userRepository = new UserRepository(); }); beforeEach(async () => { // Create test users testUser1 = await userRepository.create({ username: `testuser1_${Date.now()}`, email: `test1_${Date.now()}@example.com`, password: 'hashedpassword', fname: 'Test', lname: 'User1', type: 'regular', state: UserState.VERIFIED_REGULAR }); testUser2 = await userRepository.create({ username: `testuser2_${Date.now()}`, email: `test2_${Date.now()}@example.com`, password: 'hashedpassword', fname: 'Test', lname: 'User2', type: 'regular', state: UserState.VERIFIED_REGULAR }); testPremiumUser = await userRepository.create({ username: `premiumuser_${Date.now()}`, email: `premium_${Date.now()}@example.com`, password: 'hashedpassword', fname: 'Premium', lname: 'User', type: 'premium', state: UserState.VERIFIED_PREMIUM }); }); afterAll(async () => { if (AppDataSource.isInitialized) { await AppDataSource.destroy(); } }); describe('Direct Chat Creation', () => { it('should create a direct chat between two users', async () => { const chat = await chatRepository.create({ type: ChatType.DIRECT, users: [testUser1.id, testUser2.id], messages: [], lastActivity: new Date() }); expect(chat).toBeDefined(); expect(chat.type).toBe(ChatType.DIRECT); expect(chat.users).toEqual([testUser1.id, testUser2.id]); expect(chat.messages).toEqual([]); }); }); describe('Group Chat Creation', () => { it('should create a group chat', async () => { const chat = await chatRepository.create({ type: ChatType.GROUP, name: 'Test Group', createdBy: testPremiumUser.id, users: [testPremiumUser.id, testUser1.id, testUser2.id], messages: [], lastActivity: new Date() }); expect(chat).toBeDefined(); expect(chat.type).toBe(ChatType.GROUP); expect(chat.name).toBe('Test Group'); expect(chat.createdBy).toBe(testPremiumUser.id); expect(chat.users.length).toBe(3); }); }); describe('Game Chat Creation', () => { it('should create a game chat', async () => { const gameId = uuidv4(); const chat = await chatRepository.create({ type: ChatType.GAME, name: 'Test Game Chat', gameId: gameId, users: [testUser1.id, testUser2.id], messages: [], lastActivity: new Date() }); expect(chat).toBeDefined(); expect(chat.type).toBe(ChatType.GAME); expect(chat.gameId).toBe(gameId); expect(chat.name).toBe('Test Game Chat'); }); it('should find game chat by game id', async () => { const gameId = uuidv4(); await chatRepository.create({ type: ChatType.GAME, name: 'Test Game Chat', gameId: gameId, users: [testUser1.id, testUser2.id], messages: [], lastActivity: new Date() }); const foundChat = await chatRepository.findByGameId(gameId); expect(foundChat).toBeDefined(); expect(foundChat!.gameId).toBe(gameId); }); }); describe('Message Management', () => { it('should add and retrieve messages', async () => { const chat = await chatRepository.create({ type: ChatType.DIRECT, users: [testUser1.id, testUser2.id], messages: [], lastActivity: new Date() }); const message = { id: uuidv4(), date: new Date(), userid: testUser1.id, text: 'Hello, this is a test message!' }; await chatRepository.update(chat.id, { messages: [message], lastActivity: new Date() }); const updatedChat = await chatRepository.findById(chat.id); expect(updatedChat!.messages).toHaveLength(1); expect(updatedChat!.messages[0].text).toBe('Hello, this is a test message!'); expect(updatedChat!.messages[0].userid).toBe(testUser1.id); }); }); describe('Chat Archiving', () => { it('should archive a chat with messages', async () => { const message = { id: uuidv4(), date: new Date(), userid: testUser1.id, text: 'Message to be archived' }; const chat = await chatRepository.create({ type: ChatType.DIRECT, users: [testUser1.id, testUser2.id], messages: [message], lastActivity: new Date() }); const archive = await chatRepository.archiveChat(chat); expect(archive).toBeDefined(); expect(archive.chatId).toBe(chat.id); expect(archive.archivedMessages).toHaveLength(1); expect(archive.archivedMessages[0].text).toBe('Message to be archived'); // Check that chat messages were cleared const archivedChat = await chatRepository.findById(chat.id); expect(archivedChat!.messages).toEqual([]); expect(archivedChat!.archiveDate).toBeDefined(); }); it('should retrieve archived chat', async () => { const message = { id: uuidv4(), date: new Date(), userid: testUser1.id, text: 'Archived message' }; const chat = await chatRepository.create({ type: ChatType.DIRECT, users: [testUser1.id, testUser2.id], messages: [message], lastActivity: new Date() }); await chatRepository.archiveChat(chat); const archive = await chatRepository.getArchivedChat(chat.id); expect(archive).toBeDefined(); expect(archive!.archivedMessages).toHaveLength(1); expect(archive!.archivedMessages[0].text).toBe('Archived message'); }); }); describe('Chat Queries', () => { it('should find chats by user id', async () => { const chat1 = await chatRepository.create({ type: ChatType.DIRECT, users: [testUser1.id, testUser2.id], messages: [], lastActivity: new Date() }); const chat2 = await chatRepository.create({ type: ChatType.GROUP, name: 'Test Group', createdBy: testPremiumUser.id, users: [testPremiumUser.id, testUser1.id], messages: [], lastActivity: new Date() }); const userChats = await chatRepository.findByUserId(testUser1.id); expect(userChats.length).toBeGreaterThanOrEqual(2); const chatIds = userChats.map(c => c.id); expect(chatIds).toContain(chat1.id); expect(chatIds).toContain(chat2.id); }); it('should find active chats for user', async () => { await chatRepository.create({ type: ChatType.DIRECT, users: [testUser1.id, testUser2.id], messages: [], lastActivity: new Date() }); const activeChats = await chatRepository.findActiveChatsForUser(testUser1.id); expect(activeChats.length).toBeGreaterThanOrEqual(1); // All returned chats should be active activeChats.forEach(chat => { expect(chat.users).toContain(testUser1.id); }); }); it('should find inactive chats', async () => { const oldDate = new Date(Date.now() - 2 * 60 * 60 * 1000); // 2 hours ago await chatRepository.create({ type: ChatType.DIRECT, users: [testUser1.id, testUser2.id], messages: [], lastActivity: oldDate }); const inactiveChats = await chatRepository.findInactiveChats(60); // 60 minutes expect(inactiveChats.length).toBeGreaterThanOrEqual(1); }); }); });