Skip to main content
Glama
mkXultra
by mkXultra
MessagingAdapter.test.ts9.01 kB
import { describe, it, expect, beforeEach, vi } from 'vitest'; import { MockDataLayer } from '../../helpers/MockDataLayer.js'; import { RoomNotFoundError, AgentNotInRoomError } from '../../../src/errors/index.js'; // Mock MessagingAdapter since it doesn't exist yet class MockMessagingAdapter { constructor(private dataLayer: MockDataLayer) {} async sendMessage(params: { agentName: string; roomName: string; message: 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); } const mentions = (params.message.match(/@(\w+)/g) || []).map(m => m.slice(1)); const message = { id: `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, agentName: params.agentName, roomName: params.roomName, message: params.message, timestamp: new Date().toISOString(), mentions }; this.dataLayer.addMessage(params.roomName, message); return { success: true, messageId: message.id, mentions }; } async getMessages(params: { agentName: string; roomName: string; limit?: number; before?: 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); } const messages = this.dataLayer.getMessages(params.roomName, params.limit, params.before, params.offset); return { messages }; } } describe('MessagingAdapter Integration Tests', () => { let dataLayer: MockDataLayer; let adapter: MockMessagingAdapter; beforeEach(() => { dataLayer = new MockDataLayer(); adapter = new MockMessagingAdapter(dataLayer); // Setup test room and agent dataLayer.createRoom({ name: 'test-room', description: 'Test room', createdAt: new Date().toISOString(), messageCount: 0 }); dataLayer.addAgentToRoom('test-room', 'agent1'); dataLayer.addAgentToRoom('test-room', 'agent2'); }); describe('sendMessage', () => { it('should send message successfully when agent is in room', async () => { const result = await adapter.sendMessage({ agentName: 'agent1', roomName: 'test-room', message: 'Hello everyone!' }); expect(result.success).toBe(true); expect(result.messageId).toMatch(/^msg_\d+_[a-z0-9]+$/); expect(result.mentions).toEqual([]); }); it('should extract mentions from message', async () => { const result = await adapter.sendMessage({ agentName: 'agent1', roomName: 'test-room', message: 'Hello @agent2 and @agent3!' }); expect(result.mentions).toEqual(['agent2', 'agent3']); }); it('should throw RoomNotFoundError for non-existent room', async () => { await expect(adapter.sendMessage({ agentName: 'agent1', roomName: 'non-existent', message: 'Hello!' })).rejects.toThrow(RoomNotFoundError); }); it('should throw AgentNotInRoomError when agent not in room', async () => { await expect(adapter.sendMessage({ agentName: 'agent3', roomName: 'test-room', message: 'Hello!' })).rejects.toThrow(AgentNotInRoomError); }); it('should handle concurrent message sending', async () => { const promises = Array.from({ length: 5 }, (_, i) => adapter.sendMessage({ agentName: 'agent1', roomName: 'test-room', message: `Message ${i}` }) ); const results = await Promise.all(promises); results.forEach(result => { expect(result.success).toBe(true); expect(result.messageId).toBeDefined(); }); // Verify all messages were stored const messages = await adapter.getMessages({ agentName: 'agent1', roomName: 'test-room' }); expect(messages.messages).toHaveLength(5); }); }); describe('getMessages', () => { beforeEach(async () => { // Send test messages for (let i = 1; i <= 10; i++) { await adapter.sendMessage({ agentName: 'agent1', roomName: 'test-room', message: `Message ${i}` }); } }); it('should retrieve messages when agent is in room', async () => { const result = await adapter.getMessages({ agentName: 'agent1', roomName: 'test-room' }); expect(result.messages).toHaveLength(10); expect(result.messages[0].message).toBe('Message 1'); expect(result.messages[9].message).toBe('Message 10'); }); it('should limit number of messages returned', async () => { const result = await adapter.getMessages({ agentName: 'agent1', roomName: 'test-room', limit: 5 }); expect(result.messages).toHaveLength(5); }); it('should support pagination with offset', async () => { const firstBatch = await adapter.getMessages({ agentName: 'agent1', roomName: 'test-room', limit: 5 }); expect(firstBatch.messages).toHaveLength(5); expect(firstBatch.messages[0].message).toBe('Message 1'); expect(firstBatch.messages[4].message).toBe('Message 5'); const secondBatch = await adapter.getMessages({ agentName: 'agent1', roomName: 'test-room', limit: 5, offset: 5 }); expect(secondBatch.messages).toHaveLength(5); expect(secondBatch.messages[0].message).toBe('Message 6'); expect(secondBatch.messages[4].message).toBe('Message 10'); expect(secondBatch.messages[0].id).not.toBe(firstBatch.messages[0].id); }); it('should throw RoomNotFoundError for non-existent room', async () => { await expect(adapter.getMessages({ agentName: 'agent1', roomName: 'non-existent' })).rejects.toThrow(RoomNotFoundError); }); it('should throw AgentNotInRoomError when agent not in room', async () => { await expect(adapter.getMessages({ agentName: 'agent3', roomName: 'test-room' })).rejects.toThrow(AgentNotInRoomError); }); }); describe('message storage integration', () => { it('should maintain message order across multiple sends', async () => { const messages = ['First', 'Second', 'Third']; for (const msg of messages) { await adapter.sendMessage({ agentName: 'agent1', roomName: 'test-room', message: msg }); } const result = await adapter.getMessages({ agentName: 'agent1', roomName: 'test-room' }); expect(result.messages.map(m => m.message)).toEqual(messages); }); it('should persist mentions in stored messages', async () => { await adapter.sendMessage({ agentName: 'agent1', roomName: 'test-room', message: 'Hey @agent2, check this out @agent3!' }); const result = await adapter.getMessages({ agentName: 'agent1', roomName: 'test-room' }); expect(result.messages[0].mentions).toEqual(['agent2', 'agent3']); }); it('should handle empty messages gracefully', async () => { await expect(adapter.sendMessage({ agentName: 'agent1', roomName: 'test-room', message: '' })).resolves.toBeDefined(); }); }); describe('error handling and recovery', () => { it('should handle malformed mention patterns', async () => { const result = await adapter.sendMessage({ agentName: 'agent1', roomName: 'test-room', message: 'Invalid @@ mention and valid @agent2' }); expect(result.mentions).toEqual(['agent2']); }); it('should maintain data consistency on errors', async () => { // Send valid message await adapter.sendMessage({ agentName: 'agent1', roomName: 'test-room', message: 'Valid message' }); // Attempt invalid operation try { await adapter.sendMessage({ agentName: 'agent3', roomName: 'test-room', message: 'Should fail' }); } catch (error) { // Expected to fail } // Verify original message still exists const result = await adapter.getMessages({ agentName: 'agent1', roomName: 'test-room' }); expect(result.messages).toHaveLength(1); expect(result.messages[0].message).toBe('Valid message'); }); }); });

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