inbound-defaults.test.ts 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import { describe, expect, it } from 'vitest';
  2. import {
  3. createDefaultHttpInboundSettings,
  4. createDefaultHysteriaClient,
  5. createDefaultHysteriaInboundSettings,
  6. createDefaultMixedInboundSettings,
  7. createDefaultShadowsocksClient,
  8. createDefaultShadowsocksInboundSettings,
  9. createDefaultTrojanClient,
  10. createDefaultTrojanInboundSettings,
  11. createDefaultTunnelInboundSettings,
  12. createDefaultVlessClient,
  13. createDefaultVlessInboundSettings,
  14. createDefaultVmessClient,
  15. createDefaultVmessInboundSettings,
  16. createDefaultWireguardInboundSettings,
  17. } from '@/lib/xray/inbound-defaults';
  18. import { createHysteriaTlsSettingsWithDefaultCert } from '@/lib/xray/inbound-tls-defaults';
  19. import { HttpInboundSettingsSchema } from '@/schemas/protocols/inbound/http';
  20. import { HysteriaClientSchema, HysteriaInboundSettingsSchema } from '@/schemas/protocols/inbound/hysteria';
  21. import { MixedInboundSettingsSchema } from '@/schemas/protocols/inbound/mixed';
  22. import { ShadowsocksClientSchema, ShadowsocksInboundSettingsSchema } from '@/schemas/protocols/inbound/shadowsocks';
  23. import { TrojanClientSchema, TrojanInboundSettingsSchema } from '@/schemas/protocols/inbound/trojan';
  24. import { TunnelInboundSettingsSchema } from '@/schemas/protocols/inbound/tunnel';
  25. import { VlessClientSchema, VlessInboundSettingsSchema } from '@/schemas/protocols/inbound/vless';
  26. import { VmessClientSchema, VmessInboundSettingsSchema } from '@/schemas/protocols/inbound/vmess';
  27. import { WireguardInboundSettingsSchema } from '@/schemas/protocols/inbound/wireguard';
  28. // Tests pass explicit seeds for every random field so the assertions don't
  29. // depend on window.crypto (the node test env has no crypto.randomUUID).
  30. // Each factory is verified two ways:
  31. // 1. snapshot — locks the exact shape
  32. // 2. Zod parse round-trip — confirms the factory output is a valid
  33. // member of the protocol's client schema (no missing defaults, no
  34. // stray fields)
  35. const seed = {
  36. email: '[email protected]',
  37. subId: 'fixed-sub-id-1234',
  38. };
  39. describe('createDefaultVlessClient', () => {
  40. it('produces a Zod-valid client', () => {
  41. const c = createDefaultVlessClient({ ...seed, id: '11111111-2222-4333-8444-555555555555' });
  42. expect(c).toMatchSnapshot();
  43. expect(VlessClientSchema.parse(c)).toEqual(c);
  44. });
  45. });
  46. describe('createDefaultVmessClient', () => {
  47. it('produces a Zod-valid client', () => {
  48. const c = createDefaultVmessClient({ ...seed, id: 'aaaaaaaa-bbbb-4ccc-9ddd-eeeeeeeeeeee' });
  49. expect(c).toMatchSnapshot();
  50. expect(VmessClientSchema.parse(c)).toEqual(c);
  51. });
  52. });
  53. describe('createDefaultTrojanClient', () => {
  54. it('produces a Zod-valid client', () => {
  55. const c = createDefaultTrojanClient({ ...seed, password: 'fixed-trojan-pw' });
  56. expect(c).toMatchSnapshot();
  57. expect(TrojanClientSchema.parse(c)).toEqual(c);
  58. });
  59. });
  60. describe('createDefaultShadowsocksClient', () => {
  61. it('produces a Zod-valid client', () => {
  62. const c = createDefaultShadowsocksClient({ ...seed, password: 'ZmFrZS1zcy1wYXNzd29yZA==' });
  63. expect(c).toMatchSnapshot();
  64. expect(ShadowsocksClientSchema.parse(c)).toEqual(c);
  65. });
  66. });
  67. describe('createDefaultHysteriaClient', () => {
  68. it('produces a Zod-valid client', () => {
  69. const c = createDefaultHysteriaClient({ ...seed, auth: 'fixed-hyst-auth' });
  70. expect(c).toMatchSnapshot();
  71. expect(HysteriaClientSchema.parse(c)).toEqual(c);
  72. });
  73. });
  74. describe('createDefault*InboundSettings factories', () => {
  75. it('vless', () => {
  76. const s = createDefaultVlessInboundSettings();
  77. expect(s).toMatchSnapshot();
  78. expect(VlessInboundSettingsSchema.parse(s)).toEqual(s);
  79. });
  80. it('vmess', () => {
  81. const s = createDefaultVmessInboundSettings();
  82. expect(s).toMatchSnapshot();
  83. expect(VmessInboundSettingsSchema.parse(s)).toEqual(s);
  84. });
  85. it('trojan', () => {
  86. const s = createDefaultTrojanInboundSettings();
  87. expect(s).toMatchSnapshot();
  88. expect(TrojanInboundSettingsSchema.parse(s)).toEqual(s);
  89. });
  90. it('shadowsocks', () => {
  91. const s = createDefaultShadowsocksInboundSettings({ password: 'ZmFrZS1zcy1zZWVk' });
  92. expect(s).toMatchSnapshot();
  93. expect(ShadowsocksInboundSettingsSchema.parse(s)).toEqual(s);
  94. });
  95. it('hysteria (v1, defaults to v2 wire version)', () => {
  96. const s = createDefaultHysteriaInboundSettings();
  97. expect(s).toMatchSnapshot();
  98. expect(HysteriaInboundSettingsSchema.parse(s)).toEqual(s);
  99. });
  100. it('http', () => {
  101. const s = createDefaultHttpInboundSettings();
  102. expect(s.allowTransparent).toBe(false);
  103. const accounts = s.accounts ?? [];
  104. expect(accounts).toHaveLength(1);
  105. expect(accounts[0].user.length).toBe(8);
  106. expect(accounts[0].pass.length).toBe(12);
  107. expect(HttpInboundSettingsSchema.parse(s)).toEqual(s);
  108. });
  109. it('mixed', () => {
  110. const s = createDefaultMixedInboundSettings();
  111. expect(s.auth).toBe('password');
  112. expect(s.udp).toBe(false);
  113. expect(s.ip).toBe('127.0.0.1');
  114. const accounts = s.accounts ?? [];
  115. expect(accounts).toHaveLength(1);
  116. expect(accounts[0].user.length).toBe(8);
  117. expect(accounts[0].pass.length).toBe(12);
  118. expect(MixedInboundSettingsSchema.parse(s)).toEqual(s);
  119. });
  120. it('tunnel', () => {
  121. const s = createDefaultTunnelInboundSettings();
  122. expect(s).toMatchSnapshot();
  123. expect(TunnelInboundSettingsSchema.parse(s)).toEqual(s);
  124. });
  125. it('wireguard', () => {
  126. const s = createDefaultWireguardInboundSettings({
  127. secretKey: 'QGVlb2dXc1ZTWGw0ZXBzZndsWmtMaUM5MUlNYjBHWFdYbz0=',
  128. peerPrivateKey: 'cGVlci1maXh0dXJlLXByaXZhdGUta2V5LWZvci10ZXN0cw==',
  129. });
  130. expect(s).toMatchSnapshot();
  131. expect(WireguardInboundSettingsSchema.parse(s)).toEqual(s);
  132. });
  133. });
  134. describe('createHysteriaTlsSettingsWithDefaultCert', () => {
  135. it('defaults Hysteria TLS to uTLS None and h3 ALPN', () => {
  136. const tls = createHysteriaTlsSettingsWithDefaultCert();
  137. expect(tls.alpn).toEqual(['h3']);
  138. expect((tls.settings as Record<string, unknown>).fingerprint).toBe('');
  139. expect(tls.certificates).toEqual([
  140. expect.objectContaining({
  141. useFile: true,
  142. certificateFile: '',
  143. keyFile: '',
  144. }),
  145. ]);
  146. });
  147. });