basics-freedom-strategy.test.ts 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. import { describe, it, expect } from 'vitest';
  2. import { directFreedomStrategy, setDirectFreedomStrategy } from '@/pages/xray/basics/helpers';
  3. import type { XraySettingsValue } from '@/hooks/useXraySetting';
  4. type Outbound = Record<string, unknown>;
  5. function settingsWithDirect(settings: Outbound, stream?: Outbound): XraySettingsValue {
  6. return {
  7. outbounds: [
  8. {
  9. protocol: 'freedom',
  10. tag: 'direct',
  11. settings,
  12. ...(stream ? { streamSettings: stream } : {}),
  13. },
  14. ],
  15. } as unknown as XraySettingsValue;
  16. }
  17. function directOutbound(t: XraySettingsValue): Outbound {
  18. return t.outbounds?.[0] as Outbound;
  19. }
  20. // This select used to write the deprecated settings key (issue #6482), which is
  21. // what made the core warn on every load; it has to write sockopt instead.
  22. describe('BasicsTab freedom strategy', () => {
  23. it('writes sockopt and clears both legacy placements', () => {
  24. const t = settingsWithDirect({ domainStrategy: 'UseIPv6', targetStrategy: 'UseIP' });
  25. setDirectFreedomStrategy(t, 'UseIPv4');
  26. const outbound = directOutbound(t);
  27. expect(outbound.settings).toEqual({});
  28. expect(outbound.streamSettings).toEqual({ sockopt: { domainStrategy: 'UseIPv4' } });
  29. });
  30. it('creates the direct outbound when the config has none', () => {
  31. const t = { outbounds: [] } as unknown as XraySettingsValue;
  32. setDirectFreedomStrategy(t, 'UseIPv4');
  33. expect(directOutbound(t)).toEqual({
  34. protocol: 'freedom',
  35. tag: 'direct',
  36. settings: {},
  37. streamSettings: { sockopt: { domainStrategy: 'UseIPv4' } },
  38. });
  39. });
  40. it('keeps other sockopt keys the transport form already set', () => {
  41. const t = settingsWithDirect({}, { sockopt: { tcpFastOpen: true } });
  42. setDirectFreedomStrategy(t, 'ForceIPv4');
  43. expect(directOutbound(t).streamSettings).toEqual({
  44. sockopt: { tcpFastOpen: true, domainStrategy: 'ForceIPv4' },
  45. });
  46. });
  47. it('drops the key again when AsIs is chosen', () => {
  48. const t = settingsWithDirect({}, { sockopt: { domainStrategy: 'UseIPv4' } });
  49. setDirectFreedomStrategy(t, 'AsIs');
  50. expect(directOutbound(t).streamSettings).toBeUndefined();
  51. });
  52. it('shows the value the core will run with: legacy settings outrank sockopt', () => {
  53. expect(
  54. directFreedomStrategy(
  55. settingsWithDirect(
  56. { domainStrategy: 'UseIPv6' },
  57. { sockopt: { domainStrategy: 'UseIPv4' } },
  58. ),
  59. ),
  60. ).toBe('UseIPv6');
  61. expect(directFreedomStrategy(settingsWithDirect({ targetStrategy: 'ForceIPv6' }))).toBe(
  62. 'ForceIPv6',
  63. );
  64. expect(directFreedomStrategy(settingsWithDirect({ domainStrategy: 'UseIPv4v6' }))).toBe(
  65. 'UseIPv4v6',
  66. );
  67. expect(
  68. directFreedomStrategy(settingsWithDirect({}, { sockopt: { domainStrategy: 'UseIPv4' } })),
  69. ).toBe('UseIPv4');
  70. expect(directFreedomStrategy(settingsWithDirect({}))).toBe('AsIs');
  71. expect(directFreedomStrategy(null)).toBe('AsIs');
  72. });
  73. it('does not let an inert AsIs alias mask the sockopt value', () => {
  74. expect(
  75. directFreedomStrategy(
  76. settingsWithDirect({ domainStrategy: 'AsIs' }, { sockopt: { domainStrategy: 'UseIPv4' } }),
  77. ),
  78. ).toBe('UseIPv4');
  79. });
  80. });