tuic-client-config.test.ts 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. import { describe, expect, it } from 'vitest';
  2. import { buildTuicClientConfig } from '@/pages/clients/tuicConfig';
  3. import type { ClientRecord, InboundOption } from '@/hooks/useClients';
  4. const client: ClientRecord = {
  5. id: 1,
  6. email: '[email protected]',
  7. uuid: 'e79b9107-1607-4e6c-a496-d8f99e4f0dc5',
  8. password: 'testpassword123',
  9. inboundIds: [10],
  10. };
  11. const inbound: InboundOption = {
  12. id: 10,
  13. tag: 'in-8443-udp',
  14. remark: 'TUIC Main',
  15. protocol: 'tuic',
  16. port: 8443,
  17. tuicServer: {
  18. sni: 'vpn.example.com',
  19. congestion_control: 'cubic',
  20. alpn: ['h3', 'spdy/3.1'],
  21. udp_relay_mode: 'native',
  22. zero_rtt_handshake: true,
  23. },
  24. };
  25. describe('buildTuicClientConfig', () => {
  26. it('builds valid YAML proxy entry from tuicServer option', () => {
  27. const cfg = buildTuicClientConfig(client, inbound, 'server.example.com', '');
  28. expect(cfg).toContain('type: tuic');
  29. expect(cfg).toContain('server: server.example.com');
  30. expect(cfg).toContain('port: 8443');
  31. expect(cfg).toContain('uuid: e79b9107-1607-4e6c-a496-d8f99e4f0dc5');
  32. expect(cfg).toContain('password: "testpassword123"');
  33. expect(cfg).toContain('sni: vpn.example.com');
  34. expect(cfg).toContain('congestion-controller: cubic');
  35. expect(cfg).toContain('udp-relay-mode: native');
  36. expect(cfg).toContain('reduce-rtt: true');
  37. });
  38. it('falls back to endpointHost when sni is empty', () => {
  39. const inboundNoSni: InboundOption = {
  40. ...inbound,
  41. tuicServer: {
  42. ...inbound.tuicServer,
  43. sni: '',
  44. },
  45. };
  46. const cfg = buildTuicClientConfig(client, inboundNoSni, 'server.example.com', '');
  47. expect(cfg).toContain('sni: server.example.com');
  48. });
  49. it('exports canonical controller values for legacy settings', () => {
  50. const legacyInbound = {
  51. ...inbound,
  52. tuicServer: { ...inbound.tuicServer, congestion_control: ' RENO ' },
  53. } as InboundOption;
  54. const cfg = buildTuicClientConfig(client, legacyInbound, 'server.example.com', '');
  55. expect(cfg).toContain('congestion-controller: new_reno');
  56. expect(cfg).not.toContain('congestion-controller: RENO ');
  57. });
  58. it('escapes quotes in passwords and remarks', () => {
  59. const dangerousClient: ClientRecord = {
  60. ...client,
  61. password: 'pass"with"quotes\nnewline',
  62. };
  63. const cfg = buildTuicClientConfig(dangerousClient, inbound, 'server.example.com', '');
  64. expect(cfg).toContain('password: "pass\\"with\\"quotes\\nnewline"');
  65. });
  66. it.each([
  67. ['bbr', 'bbr'],
  68. ['cubic', 'cubic'],
  69. [' RENO ', 'new_reno'],
  70. ['unknown', 'new_reno'],
  71. ])('keeps controller %s and relay settings when applying a Host', (controller, expected) => {
  72. const config = buildTuicClientConfig(
  73. client,
  74. {
  75. ...inbound,
  76. tuicServer: {
  77. ...inbound.tuicServer,
  78. congestion_control: controller,
  79. udp_relay_mode: 'quic',
  80. zero_rtt_handshake: false,
  81. },
  82. } as InboundOption,
  83. 'panel.example.com',
  84. '',
  85. {
  86. dest: 'edge.example.com',
  87. port: 9443,
  88. remark: 'Edge',
  89. sni: 'edge.sni.example.com',
  90. alpn: ['h3'],
  91. allowInsecure: true,
  92. },
  93. );
  94. expect(config).toContain('server: edge.example.com');
  95. expect(config).toContain('port: 9443');
  96. expect(config).toContain('sni: edge.sni.example.com');
  97. expect(config).toContain('alpn:\n - h3\n');
  98. expect(config).toContain(`congestion-controller: ${expected}`);
  99. expect(config).toContain('udp-relay-mode: quic');
  100. expect(config).toContain('reduce-rtt: false');
  101. expect(config).toContain('skip-cert-verify: true');
  102. });
  103. });