import { tap, expect } from '@git.zone/tstest/tapbundle'; import { startTestServer, stopTestServer, type ITestServer } from '../../helpers/server.loader.js'; import { createSmtpClient } from '../../../ts/mail/delivery/smtpclient/index.js'; import type { SmtpClient } from '../../../ts/mail/delivery/smtpclient/smtp-client.js'; let testServer: ITestServer; let smtpClient: SmtpClient; tap.test('setup - start SMTP server for basic connection test', async () => { testServer = await startTestServer({ port: 2525, tlsEnabled: false, authRequired: false }); expect(testServer.port).toEqual(2525); }); tap.test('CCM-01: Basic TCP Connection - should connect to SMTP server', async () => { const startTime = Date.now(); try { // Create SMTP client smtpClient = createSmtpClient({ host: testServer.hostname, port: testServer.port, secure: false, connectionTimeout: 5000, debug: true }); // Verify connection const isConnected = await smtpClient.verify(); expect(isConnected).toBeTrue(); const duration = Date.now() - startTime; console.log(`✅ Basic TCP connection established in ${duration}ms`); } catch (error) { const duration = Date.now() - startTime; console.error(`❌ Basic TCP connection failed after ${duration}ms:`, error); throw error; } }); tap.test('CCM-01: Basic TCP Connection - should report connection status', async () => { // After verify(), connection is closed, so isConnected should be false expect(smtpClient.isConnected()).toBeFalse(); const poolStatus = smtpClient.getPoolStatus(); console.log('📊 Connection pool status:', poolStatus); // After verify(), pool should be empty expect(poolStatus.total).toEqual(0); expect(poolStatus.active).toEqual(0); // Test that connection status is correct during actual email send const email = new (await import('../../../ts/mail/core/classes.email.js')).Email({ from: 'sender@example.com', to: ['recipient@example.com'], subject: 'Connection status test', text: 'Testing connection status' }); // During sendMail, connection should be established const sendPromise = smtpClient.sendMail(email); // Check status while sending (might be too fast to catch) const duringStatus = smtpClient.getPoolStatus(); console.log('📊 Pool status during send:', duringStatus); await sendPromise; // After send, connection might be pooled or closed const afterStatus = smtpClient.getPoolStatus(); console.log('📊 Pool status after send:', afterStatus); }); tap.test('CCM-01: Basic TCP Connection - should handle multiple connect/disconnect cycles', async () => { // Close existing connection await smtpClient.close(); expect(smtpClient.isConnected()).toBeFalse(); // Create new client and test reconnection for (let i = 0; i < 3; i++) { const cycleClient = createSmtpClient({ host: testServer.hostname, port: testServer.port, secure: false, connectionTimeout: 5000 }); const isConnected = await cycleClient.verify(); expect(isConnected).toBeTrue(); await cycleClient.close(); expect(cycleClient.isConnected()).toBeFalse(); console.log(`✅ Connection cycle ${i + 1} completed`); } }); tap.test('CCM-01: Basic TCP Connection - should fail with invalid host', async () => { const invalidClient = createSmtpClient({ host: 'invalid.host.that.does.not.exist', port: 2525, secure: false, connectionTimeout: 3000 }); // verify() returns false on connection failure, doesn't throw const result = await invalidClient.verify(); expect(result).toBeFalse(); console.log('✅ Correctly failed to connect to invalid host'); await invalidClient.close(); }); tap.test('CCM-01: Basic TCP Connection - should timeout on unresponsive port', async () => { const startTime = Date.now(); const timeoutClient = createSmtpClient({ host: testServer.hostname, port: 9999, // Port that's not listening secure: false, connectionTimeout: 2000 }); // verify() returns false on connection failure, doesn't throw const result = await timeoutClient.verify(); expect(result).toBeFalse(); const duration = Date.now() - startTime; expect(duration).toBeLessThan(3000); // Should timeout within 3 seconds console.log(`✅ Connection timeout working correctly (${duration}ms)`); await timeoutClient.close(); }); tap.test('cleanup - close SMTP client', async () => { if (smtpClient && smtpClient.isConnected()) { await smtpClient.close(); } }); tap.test('cleanup - stop SMTP server', async () => { await stopTestServer(testServer); }); tap.start();