import { tap, expect } from '@git.zone/tstest/tapbundle'; import { DcRouter } from '../ts/classes.dcrouter.js'; /** * Unit tests for socket-handler functionality * These tests focus on the configuration and route generation logic * without actually starting services on real ports */ let dcRouter: DcRouter; tap.test('DNS route generation with dnsDomain', async () => { dcRouter = new DcRouter({ dnsDomain: 'dns.unit.test' }); // Test the route generation directly const dnsRoutes = (dcRouter as any).generateDnsRoutes(); expect(dnsRoutes).toBeDefined(); expect(dnsRoutes.length).toEqual(2); // Check /dns-query route const dnsQueryRoute = dnsRoutes[0]; expect(dnsQueryRoute.name).toEqual('dns-over-https-dns-query'); expect(dnsQueryRoute.match.ports).toEqual([443]); expect(dnsQueryRoute.match.domains).toEqual(['dns.unit.test']); expect(dnsQueryRoute.match.path).toEqual('/dns-query'); expect(dnsQueryRoute.action.type).toEqual('socket-handler'); expect(dnsQueryRoute.action.socketHandler).toBeDefined(); // Check /resolve route const resolveRoute = dnsRoutes[1]; expect(resolveRoute.name).toEqual('dns-over-https-resolve'); expect(resolveRoute.match.ports).toEqual([443]); expect(resolveRoute.match.domains).toEqual(['dns.unit.test']); expect(resolveRoute.match.path).toEqual('/resolve'); expect(resolveRoute.action.type).toEqual('socket-handler'); expect(resolveRoute.action.socketHandler).toBeDefined(); }); tap.test('DNS route generation without dnsDomain', async () => { dcRouter = new DcRouter({ // No dnsDomain set }); const dnsRoutes = (dcRouter as any).generateDnsRoutes(); expect(dnsRoutes).toBeDefined(); expect(dnsRoutes.length).toEqual(0); // No routes generated }); tap.test('Email route generation with socket-handler', async () => { const emailConfig = { ports: [25, 587, 465], hostname: 'mail.unit.test', domains: ['unit.test'], routes: [], useSocketHandler: true }; dcRouter = new DcRouter({ emailConfig }); const emailRoutes = (dcRouter as any).generateEmailRoutes(emailConfig); expect(emailRoutes).toBeDefined(); expect(emailRoutes.length).toEqual(3); // Check all routes use socket-handler emailRoutes.forEach((route: any) => { expect(route.action.type).toEqual('socket-handler'); expect(route.action.socketHandler).toBeDefined(); expect(typeof route.action.socketHandler).toEqual('function'); }); // Check specific ports const port25Route = emailRoutes.find((r: any) => r.match.ports[0] === 25); expect(port25Route.name).toEqual('smtp-route'); const port587Route = emailRoutes.find((r: any) => r.match.ports[0] === 587); expect(port587Route.name).toEqual('submission-route'); const port465Route = emailRoutes.find((r: any) => r.match.ports[0] === 465); expect(port465Route.name).toEqual('smtps-route'); }); tap.test('Email route generation with traditional forwarding', async () => { const emailConfig = { ports: [25, 587], hostname: 'mail.unit.test', domains: ['unit.test'], routes: [], useSocketHandler: false // Traditional mode }; dcRouter = new DcRouter({ emailConfig }); const emailRoutes = (dcRouter as any).generateEmailRoutes(emailConfig); expect(emailRoutes).toBeDefined(); expect(emailRoutes.length).toEqual(2); // Check all routes use forward action emailRoutes.forEach((route: any) => { expect(route.action.type).toEqual('forward'); expect(route.action.target).toBeDefined(); expect(route.action.target.host).toEqual('localhost'); expect(route.action.target.port).toBeGreaterThan(10000); // Internal port }); }); tap.test('Email TLS modes are set correctly', async () => { const emailConfig = { ports: [25, 465], hostname: 'mail.unit.test', domains: ['unit.test'], routes: [], useSocketHandler: false }; dcRouter = new DcRouter({ emailConfig }); const emailRoutes = (dcRouter as any).generateEmailRoutes(emailConfig); // Port 25 should use passthrough (STARTTLS) const port25Route = emailRoutes.find((r: any) => r.match.ports[0] === 25); expect(port25Route.action.tls.mode).toEqual('passthrough'); // Port 465 should use terminate (implicit TLS) const port465Route = emailRoutes.find((r: any) => r.match.ports[0] === 465); expect(port465Route.action.tls.mode).toEqual('terminate'); expect(port465Route.action.tls.certificate).toEqual('auto'); }); tap.test('Combined DNS and email configuration', async () => { dcRouter = new DcRouter({ dnsDomain: 'dns.combined.test', emailConfig: { ports: [25], hostname: 'mail.combined.test', domains: ['combined.test'], routes: [], useSocketHandler: true } }); // Generate both types of routes const dnsRoutes = (dcRouter as any).generateDnsRoutes(); const emailRoutes = (dcRouter as any).generateEmailRoutes(dcRouter.options.emailConfig); // Check DNS routes expect(dnsRoutes.length).toEqual(2); dnsRoutes.forEach((route: any) => { expect(route.action.type).toEqual('socket-handler'); expect(route.match.domains).toEqual(['dns.combined.test']); }); // Check email routes expect(emailRoutes.length).toEqual(1); expect(emailRoutes[0].action.type).toEqual('socket-handler'); expect(emailRoutes[0].match.ports).toEqual([25]); }); tap.test('Socket handler functions are created correctly', async () => { dcRouter = new DcRouter({ dnsDomain: 'dns.handler.test', emailConfig: { ports: [25, 465], hostname: 'mail.handler.test', domains: ['handler.test'], routes: [], useSocketHandler: true } }); // Test DNS socket handler creation const dnsHandler = (dcRouter as any).createDnsSocketHandler(); expect(dnsHandler).toBeDefined(); expect(typeof dnsHandler).toEqual('function'); // Test email socket handler creation for different ports const smtp25Handler = (dcRouter as any).createMailSocketHandler(25); expect(smtp25Handler).toBeDefined(); expect(typeof smtp25Handler).toEqual('function'); const smtp465Handler = (dcRouter as any).createMailSocketHandler(465); expect(smtp465Handler).toBeDefined(); expect(typeof smtp465Handler).toEqual('function'); // Handlers should be different functions expect(smtp25Handler).not.toEqual(smtp465Handler); }); tap.test('stop', async () => { await tap.stopForcefully(); }); export default tap.start();