Skip to main content
Glama
mkXultra
by mkXultra
RoomsAdapter.test.ts13.5 kB
import { describe, it, expect, beforeEach, vi } from 'vitest'; import { MockDataLayer } from '../../helpers/MockDataLayer.js'; import { RoomNotFoundError, RoomAlreadyExistsError, AgentNotInRoomError } from '../../../src/errors/index.js'; // Mock RoomsAdapter since it doesn't exist yet class MockRoomsAdapter { constructor(private dataLayer: MockDataLayer) {} async listRooms() { const rooms = this.dataLayer.getAllRooms(); return { rooms }; } async createRoom(params: { roomName: string; description?: string }) { if (this.dataLayer.roomExists(params.roomName)) { throw new RoomAlreadyExistsError(params.roomName); } const room = { name: params.roomName, description: params.description || '', createdAt: new Date().toISOString(), messageCount: 0 }; this.dataLayer.createRoom(room); return { success: true, roomName: params.roomName }; } async enterRoom(params: { agentName: string; roomName: string }) { if (!this.dataLayer.roomExists(params.roomName)) { throw new RoomNotFoundError(params.roomName); } this.dataLayer.addAgentToRoom(params.roomName, params.agentName); return { success: true }; } async leaveRoom(params: { agentName: string; roomName: string }) { if (!this.dataLayer.roomExists(params.roomName)) { throw new RoomNotFoundError(params.roomName); } const roomAgents = this.dataLayer.getRoomAgents(params.roomName); if (!roomAgents.includes(params.agentName)) { throw new AgentNotInRoomError(params.agentName, params.roomName); } this.dataLayer.removeAgentFromRoom(params.roomName, params.agentName); return { success: true }; } async listRoomUsers(params: { roomName: string }) { if (!this.dataLayer.roomExists(params.roomName)) { throw new RoomNotFoundError(params.roomName); } const agents = this.dataLayer.getRoomAgents(params.roomName); return { agents }; } async roomExists(roomName: string): Promise<boolean> { return this.dataLayer.roomExists(roomName); } } describe('RoomsAdapter Integration Tests', () => { let dataLayer: MockDataLayer; let adapter: MockRoomsAdapter; beforeEach(() => { dataLayer = new MockDataLayer(); adapter = new MockRoomsAdapter(dataLayer); }); describe('listRooms', () => { it('should return empty list when no rooms exist', async () => { const result = await adapter.listRooms(); expect(result.rooms).toEqual([]); }); it('should return all rooms when they exist', async () => { // Create test rooms await adapter.createRoom({ roomName: 'room1', description: 'First room' }); await adapter.createRoom({ roomName: 'room2', description: 'Second room' }); const result = await adapter.listRooms(); expect(result.rooms).toHaveLength(2); expect(result.rooms.map(r => r.name)).toContain('room1'); expect(result.rooms.map(r => r.name)).toContain('room2'); }); it('should include room metadata', async () => { await adapter.createRoom({ roomName: 'test-room', description: 'Test description' }); const result = await adapter.listRooms(); const room = result.rooms[0]; expect(room.name).toBe('test-room'); expect(room.description).toBe('Test description'); expect(room.createdAt).toBeDefined(); expect(room.messageCount).toBe(0); }); }); describe('createRoom', () => { it('should create room successfully with description', async () => { const result = await adapter.createRoom({ roomName: 'new-room', description: 'A new room' }); expect(result.success).toBe(true); expect(result.roomName).toBe('new-room'); // Verify room was created const rooms = await adapter.listRooms(); expect(rooms.rooms).toHaveLength(1); expect(rooms.rooms[0].name).toBe('new-room'); expect(rooms.rooms[0].description).toBe('A new room'); }); it('should create room successfully without description', async () => { const result = await adapter.createRoom({ roomName: 'minimal-room' }); expect(result.success).toBe(true); expect(result.roomName).toBe('minimal-room'); const rooms = await adapter.listRooms(); expect(rooms.rooms[0].description).toBe(''); }); it('should throw RoomAlreadyExistsError for duplicate room name', async () => { await adapter.createRoom({ roomName: 'duplicate-room' }); await expect(adapter.createRoom({ roomName: 'duplicate-room' })).rejects.toThrow(RoomAlreadyExistsError); }); it('should handle concurrent room creation', async () => { const promises = Array.from({ length: 5 }, (_, i) => adapter.createRoom({ roomName: `room-${i}` }) ); const results = await Promise.all(promises); results.forEach((result, i) => { expect(result.success).toBe(true); expect(result.roomName).toBe(`room-${i}`); }); const rooms = await adapter.listRooms(); expect(rooms.rooms).toHaveLength(5); }); }); describe('enterRoom', () => { beforeEach(async () => { await adapter.createRoom({ roomName: 'test-room' }); }); it('should allow agent to enter existing room', async () => { const result = await adapter.enterRoom({ agentName: 'agent1', roomName: 'test-room' }); expect(result.success).toBe(true); // Verify agent is in room const users = await adapter.listRoomUsers({ roomName: 'test-room' }); expect(users.agents).toContain('agent1'); }); it('should allow multiple agents to enter same room', async () => { await adapter.enterRoom({ agentName: 'agent1', roomName: 'test-room' }); await adapter.enterRoom({ agentName: 'agent2', roomName: 'test-room' }); const users = await adapter.listRoomUsers({ roomName: 'test-room' }); expect(users.agents).toContain('agent1'); expect(users.agents).toContain('agent2'); expect(users.agents).toHaveLength(2); }); it('should allow same agent to enter multiple times (idempotent)', async () => { await adapter.enterRoom({ agentName: 'agent1', roomName: 'test-room' }); await adapter.enterRoom({ agentName: 'agent1', roomName: 'test-room' }); const users = await adapter.listRoomUsers({ roomName: 'test-room' }); expect(users.agents).toEqual(['agent1']); }); it('should throw RoomNotFoundError for non-existent room', async () => { await expect(adapter.enterRoom({ agentName: 'agent1', roomName: 'non-existent' })).rejects.toThrow(RoomNotFoundError); }); }); describe('leaveRoom', () => { beforeEach(async () => { await adapter.createRoom({ roomName: 'test-room' }); await adapter.enterRoom({ agentName: 'agent1', roomName: 'test-room' }); await adapter.enterRoom({ agentName: 'agent2', roomName: 'test-room' }); }); it('should allow agent to leave room', async () => { const result = await adapter.leaveRoom({ agentName: 'agent1', roomName: 'test-room' }); expect(result.success).toBe(true); // Verify agent is no longer in room const users = await adapter.listRoomUsers({ roomName: 'test-room' }); expect(users.agents).not.toContain('agent1'); expect(users.agents).toContain('agent2'); }); it('should throw RoomNotFoundError for non-existent room', async () => { await expect(adapter.leaveRoom({ agentName: 'agent1', roomName: 'non-existent' })).rejects.toThrow(RoomNotFoundError); }); it('should throw AgentNotInRoomError when agent not in room', async () => { await expect(adapter.leaveRoom({ agentName: 'agent3', roomName: 'test-room' })).rejects.toThrow(AgentNotInRoomError); }); it('should handle agent leaving multiple times gracefully', async () => { await adapter.leaveRoom({ agentName: 'agent1', roomName: 'test-room' }); await expect(adapter.leaveRoom({ agentName: 'agent1', roomName: 'test-room' })).rejects.toThrow(AgentNotInRoomError); }); }); describe('listRoomUsers', () => { beforeEach(async () => { await adapter.createRoom({ roomName: 'test-room' }); }); it('should return empty list for room with no users', async () => { const result = await adapter.listRoomUsers({ roomName: 'test-room' }); expect(result.agents).toEqual([]); }); it('should return all users in room', async () => { await adapter.enterRoom({ agentName: 'agent1', roomName: 'test-room' }); await adapter.enterRoom({ agentName: 'agent2', roomName: 'test-room' }); const result = await adapter.listRoomUsers({ roomName: 'test-room' }); expect(result.agents).toHaveLength(2); expect(result.agents).toContain('agent1'); expect(result.agents).toContain('agent2'); }); it('should throw RoomNotFoundError for non-existent room', async () => { await expect(adapter.listRoomUsers({ roomName: 'non-existent' })).rejects.toThrow(RoomNotFoundError); }); it('should update user list when agents leave', async () => { await adapter.enterRoom({ agentName: 'agent1', roomName: 'test-room' }); await adapter.enterRoom({ agentName: 'agent2', roomName: 'test-room' }); await adapter.leaveRoom({ agentName: 'agent1', roomName: 'test-room' }); const result = await adapter.listRoomUsers({ roomName: 'test-room' }); expect(result.agents).toEqual(['agent2']); }); }); describe('room lifecycle integration', () => { it('should handle complete room lifecycle', async () => { // Create room const createResult = await adapter.createRoom({ roomName: 'lifecycle-room', description: 'Test lifecycle' }); expect(createResult.success).toBe(true); // Agents enter await adapter.enterRoom({ agentName: 'agent1', roomName: 'lifecycle-room' }); await adapter.enterRoom({ agentName: 'agent2', roomName: 'lifecycle-room' }); // Check users let users = await adapter.listRoomUsers({ roomName: 'lifecycle-room' }); expect(users.agents).toHaveLength(2); // Agent leaves await adapter.leaveRoom({ agentName: 'agent1', roomName: 'lifecycle-room' }); // Check users again users = await adapter.listRoomUsers({ roomName: 'lifecycle-room' }); expect(users.agents).toEqual(['agent2']); // Verify room still exists const rooms = await adapter.listRooms(); expect(rooms.rooms.map(r => r.name)).toContain('lifecycle-room'); }); it('should maintain room state across multiple operations', async () => { await adapter.createRoom({ roomName: 'state-room' }); // Multiple agents join and leave for (let i = 1; i <= 5; i++) { await adapter.enterRoom({ agentName: `agent${i}`, roomName: 'state-room' }); } // Some agents leave await adapter.leaveRoom({ agentName: 'agent1', roomName: 'state-room' }); await adapter.leaveRoom({ agentName: 'agent3', roomName: 'state-room' }); const users = await adapter.listRoomUsers({ roomName: 'state-room' }); expect(users.agents).toHaveLength(3); expect(users.agents).toEqual(['agent2', 'agent4', 'agent5']); }); }); describe('error handling and edge cases', () => { it('should handle special characters in room names', async () => { const result = await adapter.createRoom({ roomName: 'room-with_special.chars', description: 'Special chars test' }); expect(result.success).toBe(true); // Test operations with special char room await adapter.enterRoom({ agentName: 'agent1', roomName: 'room-with_special.chars' }); const users = await adapter.listRoomUsers({ roomName: 'room-with_special.chars' }); expect(users.agents).toContain('agent1'); }); it('should handle empty descriptions gracefully', async () => { const result = await adapter.createRoom({ roomName: 'empty-desc-room', description: '' }); expect(result.success).toBe(true); const rooms = await adapter.listRooms(); const room = rooms.rooms.find(r => r.name === 'empty-desc-room'); expect(room?.description).toBe(''); }); it('should maintain data consistency during concurrent operations', async () => { await adapter.createRoom({ roomName: 'concurrent-room' }); // Concurrent enters and leaves const operations = [ adapter.enterRoom({ agentName: 'agent1', roomName: 'concurrent-room' }), adapter.enterRoom({ agentName: 'agent2', roomName: 'concurrent-room' }), adapter.enterRoom({ agentName: 'agent3', roomName: 'concurrent-room' }) ]; await Promise.all(operations); const users = await adapter.listRoomUsers({ roomName: 'concurrent-room' }); expect(users.agents).toHaveLength(3); }); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mkXultra/agent-communication-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server