import { SMTPOverWSClient, ConnectionState, MessagePriority } from '../src/index'; describe('SMTPOverWSClient', () => { let client: SMTPOverWSClient; beforeEach(() => { client = new SMTPOverWSClient({ url: 'ws://localhost:3000/smtp', apiKey: 'test-api-key' }); }); afterEach(async () => { if (client) { await client.shutdown(); } }); describe('constructor', () => { it('should create client with default configuration', () => { expect(client.getConnectionState()).toBe(ConnectionState.DISCONNECTED); expect(client.getQueueSize()).toBe(0); }); it('should throw error for missing URL', () => { expect(() => { new SMTPOverWSClient({ url: '', apiKey: 'test-key' }); }).toThrow('URL is required'); }); it('should throw error for missing API key', () => { expect(() => { new SMTPOverWSClient({ url: 'ws://localhost:3000', apiKey: '' }); }).toThrow('API key is required'); }); }); describe('sendSMTPCommand', () => { it('should queue message and return promise', async () => { const promise = client.sendSMTPCommand('EHLO example.com\\r\\n'); expect(client.getQueueSize()).toBe(1); expect(promise).toBeInstanceOf(Promise); // Clean up client.clearQueue(); }); it('should respect priority ordering', async () => { // Queue messages with different priorities const lowPromise = client.sendSMTPCommand('LOW', { priority: MessagePriority.LOW }); const highPromise = client.sendSMTPCommand('HIGH', { priority: MessagePriority.HIGH }); const normalPromise = client.sendSMTPCommand('NORMAL', { priority: MessagePriority.NORMAL }); expect(client.getQueueSize()).toBe(3); // Clean up client.clearQueue(); }); it('should reject when client is shutting down', async () => { const shutdownPromise = client.shutdown(); await expect(client.sendSMTPCommand('TEST')).rejects.toThrow('Client is shutting down'); await shutdownPromise; }); it('should reject when queue is full', async () => { const smallQueueClient = new SMTPOverWSClient({ url: 'ws://localhost:3000/smtp', apiKey: 'test-key', maxQueueSize: 2 }); // Fill queue smallQueueClient.sendSMTPCommand('MSG1'); smallQueueClient.sendSMTPCommand('MSG2'); // This should fail await expect(smallQueueClient.sendSMTPCommand('MSG3')).rejects.toThrow('Queue is full'); await smallQueueClient.shutdown(); }); }); describe('statistics', () => { it('should provide initial statistics', () => { const stats = client.getStats(); expect(stats).toEqual({ messagesQueued: 0, messagesProcessed: 0, messagesFailed: 0, reconnectionAttempts: 0, totalConnections: 0, averageResponseTime: 0, queueSize: 0, connectionUptime: 0 }); }); }); describe('queue management', () => { it('should clear queue', () => { client.sendSMTPCommand('MSG1'); client.sendSMTPCommand('MSG2'); expect(client.getQueueSize()).toBe(2); client.clearQueue(); expect(client.getQueueSize()).toBe(0); }); }); describe('shutdown', () => { it('should shutdown gracefully', async () => { await expect(client.shutdown()).resolves.toBeUndefined(); expect(client.getConnectionState()).toBe(ConnectionState.DISCONNECTED); }); it('should timeout if shutdown takes too long', async () => { await expect(client.shutdown(100)).resolves.toBeUndefined(); }); }); });