import { describe, it, expect } from 'vitest'; import type { XraySettingsValue } from '@/hooks/useXraySetting'; import { propagateOutboundTagRename } from '@/pages/xray/basics/helpers'; function baseTemplate(): XraySettingsValue { return { outbounds: [ { tag: 'To-External-Proxy', protocol: 'vless' }, { tag: 'direct', protocol: 'freedom' }, ], routing: { rules: [ { type: 'field', inboundTag: ['iran-in'], outboundTag: 'To-External-Proxy', }, ], balancers: [ { tag: 'lb-1', selector: ['To-External-Proxy', 'direct'], fallbackTag: 'To-External-Proxy', }, ], }, } as XraySettingsValue; } describe('propagateOutboundTagRename', () => { it('updates routing rule outboundTag when outbound is renamed', () => { const t = baseTemplate(); propagateOutboundTagRename(t, 'To-External-Proxy', 'external-vps'); expect(t.routing?.rules?.[0]?.outboundTag).toBe('external-vps'); }); it('updates balancer selector and fallbackTag', () => { const t = baseTemplate(); propagateOutboundTagRename(t, 'To-External-Proxy', 'external-vps'); expect(t.routing?.balancers?.[0]?.selector).toEqual(['external-vps', 'direct']); expect(t.routing?.balancers?.[0]?.fallbackTag).toBe('external-vps'); }); it('updates sockopt dialerProxy references in other outbounds', () => { const t = baseTemplate(); (t.outbounds![1] as { streamSettings?: { sockopt?: { dialerProxy?: string } } }).streamSettings = { sockopt: { dialerProxy: 'To-External-Proxy' }, }; propagateOutboundTagRename(t, 'To-External-Proxy', 'external-vps'); const dialerProxy = (t.outbounds![1] as { streamSettings?: { sockopt?: { dialerProxy?: string } } }) .streamSettings?.sockopt?.dialerProxy; expect(dialerProxy).toBe('external-vps'); }); it('is a no-op when old and new tags are equal', () => { const t = baseTemplate(); propagateOutboundTagRename(t, 'To-External-Proxy', 'To-External-Proxy'); expect(t.routing?.rules?.[0]?.outboundTag).toBe('To-External-Proxy'); }); });