happ-presets.test.ts 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. import { describe, expect, it } from 'vitest';
  2. import { buildHappPresetDeeplink, toBase64Utf8 } from '@/pages/settings/happPresets';
  3. describe('Happ presets and helpers', () => {
  4. it('generates valid happ://routing/off for off preset', () => {
  5. const link = buildHappPresetDeeplink('off');
  6. expect(link).toBe('happ://routing/off');
  7. });
  8. it('generates valid base64 payload for iran-bypass preset', () => {
  9. const link = buildHappPresetDeeplink('iran-bypass');
  10. expect(link.startsWith('happ://routing/onadd/')).toBe(true);
  11. const b64 = link.replace('happ://routing/onadd/', '');
  12. const jsonStr = atob(b64);
  13. const parsed = JSON.parse(jsonStr);
  14. expect(parsed.Name).toBe('Iran Bypass');
  15. expect(parsed.GlobalProxy).toBe('true');
  16. expect(parsed.DirectSites).toContain('domain:ir');
  17. expect(parsed.DirectIp).toContain('geoip:ir');
  18. expect(parsed.BlockSites).toEqual([]);
  19. });
  20. it('generates valid base64 payload for china-direct preset', () => {
  21. const link = buildHappPresetDeeplink('china-direct');
  22. expect(link.startsWith('happ://routing/onadd/')).toBe(true);
  23. const b64 = link.replace('happ://routing/onadd/', '');
  24. const jsonStr = atob(b64);
  25. const parsed = JSON.parse(jsonStr);
  26. expect(parsed).toEqual({
  27. Name: 'Bypass-CN',
  28. GlobalProxy: 'true',
  29. RouteOrder: 'block-proxy-direct',
  30. RemoteDNSType: 'DoH',
  31. RemoteDNSDomain: 'https://cloudflare-dns.com/dns-query',
  32. RemoteDNSIP: '1.1.1.1',
  33. DomesticDNSType: 'DoH',
  34. DomesticDNSDomain: 'https://dns.alidns.com/dns-query',
  35. DomesticDNSIP: '223.5.5.5',
  36. DnsHosts: {
  37. 'cloudflare-dns.com': '1.1.1.1',
  38. 'dns.alidns.com': '223.5.5.5',
  39. },
  40. DirectSites: ['geosite:private', 'geosite:cn', 'geosite:geolocation-cn'],
  41. DirectIp: [
  42. 'geoip:cn',
  43. 'geoip:private',
  44. '127.0.0.0/8',
  45. '10.0.0.0/8',
  46. '172.16.0.0/12',
  47. '192.168.0.0/16',
  48. '169.254.0.0/16',
  49. '224.0.0.0/4',
  50. '255.255.255.255',
  51. ],
  52. ProxySites: [],
  53. ProxyIp: [],
  54. BlockSites: [],
  55. BlockIp: [],
  56. DomainStrategy: 'IPIfNonMatch',
  57. FakeDNS: 'false',
  58. UseChunkFiles: 'true',
  59. });
  60. });
  61. it.each(['iran-bypass', 'china-direct', 'global', 'lan-bypass'])(
  62. 'adds ad blocking only when opted in for %s without changing its routing',
  63. (preset) => {
  64. const decode = (link: string) => JSON.parse(atob(link.replace('happ://routing/onadd/', '')));
  65. const base = decode(buildHappPresetDeeplink(preset));
  66. const withAds = decode(buildHappPresetDeeplink(preset, true));
  67. const withoutAds = decode(buildHappPresetDeeplink(preset, false));
  68. expect(base.BlockSites).toEqual([]);
  69. expect(withAds.BlockSites).toEqual(['geosite:category-ads-all']);
  70. expect({ ...withAds, BlockSites: [] }).toEqual(base);
  71. expect(withoutAds).toEqual(base);
  72. },
  73. );
  74. it('keeps routing disabled even when ad blocking is selected', () => {
  75. expect(buildHappPresetDeeplink('off', true)).toBe('happ://routing/off');
  76. });
  77. it.each(['adblock', 'unknown'])(
  78. 'does not generate a profile for unsupported preset %s',
  79. (preset) => {
  80. expect(buildHappPresetDeeplink(preset)).toBe('');
  81. },
  82. );
  83. it('keeps the global preset without direct exceptions', () => {
  84. const link = buildHappPresetDeeplink('global');
  85. const b64 = link.replace('happ://routing/onadd/', '');
  86. const jsonStr = atob(b64);
  87. const parsed = JSON.parse(jsonStr);
  88. expect(parsed.Name).toBe('Global Proxy');
  89. expect(parsed.GlobalProxy).toBe('true');
  90. expect(parsed.DirectSites).toEqual([]);
  91. expect(parsed.DirectIp).toEqual([]);
  92. expect(parsed.DomainStrategy).toBe('AsIs');
  93. });
  94. it('generates a separate LAN bypass preset with proxy as the default', () => {
  95. const link = buildHappPresetDeeplink('lan-bypass');
  96. const prefix = 'happ://routing/onadd/';
  97. expect(link.startsWith(prefix)).toBe(true);
  98. const parsed = JSON.parse(atob(link.slice(prefix.length)));
  99. expect(parsed.Name).toBe('Global Bypass Local Network');
  100. expect(parsed.GlobalProxy).toBe('true');
  101. expect(parsed.DirectSites).toEqual(['geosite:private']);
  102. expect(parsed.DirectIp).toEqual(['geoip:private']);
  103. expect(parsed.BlockSites).toEqual([]);
  104. expect(parsed.DomainStrategy).toBe('AsIs');
  105. });
  106. it('encodes unicode properly via toBase64Utf8', () => {
  107. const text = 'فیلترشکن و روتینگ';
  108. const b64 = toBase64Utf8(text);
  109. const decoded = decodeURIComponent(
  110. Array.prototype.map
  111. .call(atob(b64), (c: string) => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2))
  112. .join(''),
  113. );
  114. expect(decoded).toBe(text);
  115. });
  116. });