import { tap, expect } from '@git.zone/tstest/tapbundle'; import { VpnConfig } from '../ts/index.js'; import type { IVpnClientConfig, IVpnServerConfig } from '../ts/index.js'; // Valid 32-byte base64 keys for testing const TEST_KEY_A = 'YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWE='; const TEST_KEY_B = 'YmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmI='; const TEST_KEY_C = 'Y2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2M='; tap.test('VpnConfig: validate valid client config', async () => { const config: IVpnClientConfig = { serverUrl: 'wss://vpn.example.com/tunnel', serverPublicKey: TEST_KEY_A, clientPrivateKey: TEST_KEY_B, clientPublicKey: TEST_KEY_C, dns: ['1.1.1.1', '8.8.8.8'], mtu: 1420, keepaliveIntervalSecs: 30, }; // Should not throw VpnConfig.validateClientConfig(config); }); tap.test('VpnConfig: reject client config without serverUrl', async () => { const config = { serverPublicKey: TEST_KEY_A, clientPrivateKey: TEST_KEY_B, clientPublicKey: TEST_KEY_C, } as IVpnClientConfig; let threw = false; try { VpnConfig.validateClientConfig(config); } catch (e) { threw = true; expect((e as Error).message).toContain('serverUrl'); } expect(threw).toBeTrue(); }); tap.test('VpnConfig: reject client config with invalid serverUrl scheme', async () => { const config: IVpnClientConfig = { serverUrl: 'http://vpn.example.com/tunnel', serverPublicKey: TEST_KEY_A, clientPrivateKey: TEST_KEY_B, clientPublicKey: TEST_KEY_C, }; let threw = false; try { VpnConfig.validateClientConfig(config); } catch (e) { threw = true; expect((e as Error).message).toContain('wss://'); } expect(threw).toBeTrue(); }); tap.test('VpnConfig: reject client config without clientPrivateKey', async () => { const config = { serverUrl: 'wss://vpn.example.com/tunnel', serverPublicKey: TEST_KEY_A, clientPublicKey: TEST_KEY_C, } as IVpnClientConfig; let threw = false; try { VpnConfig.validateClientConfig(config); } catch (e) { threw = true; expect((e as Error).message).toContain('clientPrivateKey'); } expect(threw).toBeTrue(); }); tap.test('VpnConfig: reject client config with invalid MTU', async () => { const config: IVpnClientConfig = { serverUrl: 'wss://vpn.example.com/tunnel', serverPublicKey: TEST_KEY_A, clientPrivateKey: TEST_KEY_B, clientPublicKey: TEST_KEY_C, mtu: 100, }; let threw = false; try { VpnConfig.validateClientConfig(config); } catch (e) { threw = true; expect((e as Error).message).toContain('mtu'); } expect(threw).toBeTrue(); }); tap.test('VpnConfig: reject client config with invalid DNS', async () => { const config: IVpnClientConfig = { serverUrl: 'wss://vpn.example.com/tunnel', serverPublicKey: TEST_KEY_A, clientPrivateKey: TEST_KEY_B, clientPublicKey: TEST_KEY_C, dns: ['not-an-ip'], }; let threw = false; try { VpnConfig.validateClientConfig(config); } catch (e) { threw = true; expect((e as Error).message).toContain('DNS'); } expect(threw).toBeTrue(); }); tap.test('VpnConfig: validate valid server config', async () => { const config: IVpnServerConfig = { listenAddr: '0.0.0.0:443', privateKey: TEST_KEY_A, publicKey: TEST_KEY_B, subnet: '10.8.0.0/24', dns: ['1.1.1.1'], mtu: 1420, enableNat: true, clients: [ { clientId: 'test-client', publicKey: TEST_KEY_C }, ], }; // Should not throw VpnConfig.validateServerConfig(config); }); tap.test('VpnConfig: reject server config with invalid subnet', async () => { const config: IVpnServerConfig = { listenAddr: '0.0.0.0:443', privateKey: TEST_KEY_A, publicKey: TEST_KEY_B, subnet: 'invalid', }; let threw = false; try { VpnConfig.validateServerConfig(config); } catch (e) { threw = true; expect((e as Error).message).toContain('subnet'); } expect(threw).toBeTrue(); }); tap.test('VpnConfig: reject server config without privateKey', async () => { const config = { listenAddr: '0.0.0.0:443', publicKey: TEST_KEY_B, subnet: '10.8.0.0/24', } as IVpnServerConfig; let threw = false; try { VpnConfig.validateServerConfig(config); } catch (e) { threw = true; expect((e as Error).message).toContain('privateKey'); } expect(threw).toBeTrue(); }); tap.test('VpnConfig: reject server config with invalid client publicKey', async () => { const config: IVpnServerConfig = { listenAddr: '0.0.0.0:443', privateKey: TEST_KEY_A, publicKey: TEST_KEY_B, subnet: '10.8.0.0/24', clients: [ { clientId: 'bad-client', publicKey: 'short-key' }, ], }; let threw = false; try { VpnConfig.validateServerConfig(config); } catch (e) { threw = true; expect((e as Error).message).toContain('publicKey'); } expect(threw).toBeTrue(); }); export default tap.start();