import { tap, expect } from '@git.zone/tstest/tapbundle'; import { DcRouter } from '../ts/classes.dcrouter.js'; import * as plugins from '../ts/plugins.js'; let dcRouter: DcRouter; tap.test('should NOT instantiate DNS server when dnsNsDomains is not set', async () => { dcRouter = new DcRouter({ smartProxyConfig: { routes: [] } }); await dcRouter.start(); // Check that DNS server is not created expect((dcRouter as any).dnsServer).toBeUndefined(); await dcRouter.stop(); }); tap.test('should generate DNS routes when dnsNsDomains is set', async () => { // This test checks the route generation logic WITHOUT starting the full DcRouter // Starting DcRouter would require DNS port 53 and cause conflicts dcRouter = new DcRouter({ dnsNsDomains: ['ns1.test.local', 'ns2.test.local'], dnsScopes: ['test.local'], smartProxyConfig: { routes: [] } }); // Check routes are generated correctly (without starting) const generatedRoutes = (dcRouter as any).generateDnsRoutes(); expect(generatedRoutes.length).toEqual(2); // /dns-query and /resolve // Check that routes have socket-handler action generatedRoutes.forEach((route: any) => { expect(route.action.type).toEqual('socket-handler'); expect(route.action.socketHandler).toBeDefined(); }); // Verify routes target the primary nameserver const dnsQueryRoute = generatedRoutes.find((r: any) => r.name === 'dns-over-https-dns-query'); expect(dnsQueryRoute).toBeDefined(); expect(dnsQueryRoute.match.domains).toContain('ns1.test.local'); }); tap.test('should create DNS routes with correct configuration', async () => { dcRouter = new DcRouter({ dnsNsDomains: ['ns1.example.com', 'ns2.example.com'], dnsScopes: ['example.com'], smartProxyConfig: { routes: [] } }); // Access the private method to generate routes const dnsRoutes = (dcRouter as any).generateDnsRoutes(); expect(dnsRoutes.length).toEqual(2); // Check first route (dns-query) - uses primary nameserver (first in array) const dnsQueryRoute = dnsRoutes.find((r: any) => r.name === 'dns-over-https-dns-query'); expect(dnsQueryRoute).toBeDefined(); expect(dnsQueryRoute.match.ports).toContain(443); expect(dnsQueryRoute.match.domains).toContain('ns1.example.com'); expect(dnsQueryRoute.match.path).toEqual('/dns-query'); // Check second route (resolve) const resolveRoute = dnsRoutes.find((r: any) => r.name === 'dns-over-https-resolve'); expect(resolveRoute).toBeDefined(); expect(resolveRoute.match.ports).toContain(443); expect(resolveRoute.match.domains).toContain('ns1.example.com'); expect(resolveRoute.match.path).toEqual('/resolve'); }); tap.test('DNS socket handler should be created correctly', async () => { // This test verifies the socket handler creation WITHOUT starting the full router dcRouter = new DcRouter({ dnsNsDomains: ['ns1.test.local', 'ns2.test.local'], dnsScopes: ['test.local'], smartProxyConfig: { routes: [] } }); // Get the socket handler (this doesn't require DNS server to be started) const socketHandler = (dcRouter as any).createDnsSocketHandler(); expect(socketHandler).toBeDefined(); expect(typeof socketHandler).toEqual('function'); // Create a mock socket to test the handler behavior without DNS server const mockSocket = new plugins.net.Socket(); let socketEnded = false; mockSocket.end = () => { socketEnded = true; return mockSocket; }; // When DNS server is not initialized, the handler should end the socket try { await socketHandler(mockSocket); } catch (error) { // Expected - DNS server not initialized } // Socket should be ended because DNS server wasn't started expect(socketEnded).toEqual(true); }); tap.test('DNS routes should only be generated when dnsNsDomains is configured', async () => { // Test without DNS configuration - should return empty routes dcRouter = new DcRouter({ smartProxyConfig: { routes: [] } }); const routesWithoutDns = (dcRouter as any).generateDnsRoutes(); expect(routesWithoutDns.length).toEqual(0); // Test with DNS configuration - should return routes const dcRouterWithDns = new DcRouter({ dnsNsDomains: ['ns1.example.com'], dnsScopes: ['example.com'], smartProxyConfig: { routes: [] } }); const routesWithDns = (dcRouterWithDns as any).generateDnsRoutes(); expect(routesWithDns.length).toEqual(2); // Verify socket handler can be created const socketHandler = (dcRouterWithDns as any).createDnsSocketHandler(); expect(socketHandler).toBeDefined(); expect(typeof socketHandler).toEqual('function'); }); tap.test('stop', async () => { await tap.stopForcefully(); }); export default tap.start();