/// import { describe, expect, it } from 'vitest'; import { rawInboundToFormValues, formValuesToWirePayload, type RawInboundRow, } from '@/lib/xray/inbound-form-adapter'; import { InboundFormSchema } from '@/schemas/forms/inbound-form'; // Round-trip: raw DB row → InboundFormValues → wire payload, asserting // that the JSON-stringified settings/streamSettings/sniffing in the // payload deserialize back to the same data the raw row carried. interface FixtureCase { name: string; row: RawInboundRow; expectedProtocol: string; } const vlessRow: RawInboundRow = { id: 7, port: 12345, listen: '0.0.0.0', protocol: 'vless', remark: 'edge-1', enable: true, up: 1024, down: 2048, total: 1_000_000_000, expiryTime: 0, trafficReset: 'monthly', lastTrafficResetTime: 0, tag: 'inbound-1', nodeId: null, settings: { clients: [{ id: '8c14d6f7-2e3b-4a91-9d24-3f7a6b8c1e02', email: 'alice@example.test', flow: '', limitIp: 0, totalGB: 0, expiryTime: 0, enable: true, tgId: 0, subId: 'abc123def', comment: '', reset: 0, }], decryption: 'none', encryption: 'none', fallbacks: [], }, streamSettings: { network: 'tcp', security: 'none', tcpSettings: { header: { type: 'none' } }, }, sniffing: { enabled: false, destOverride: ['http', 'tls', 'quic', 'fakedns'], metadataOnly: false, routeOnly: false, ipsExcluded: [], domainsExcluded: [], }, } as RawInboundRow & { id: number }; const cases: FixtureCase[] = [ { name: 'vless tcp none', row: vlessRow, expectedProtocol: 'vless' }, { name: 'string-coerced settings', row: { ...vlessRow, settings: JSON.stringify(vlessRow.settings), streamSettings: JSON.stringify(vlessRow.streamSettings), sniffing: JSON.stringify(vlessRow.sniffing), }, expectedProtocol: 'vless', }, { name: 'empty stream settings drop to undefined', row: { ...vlessRow, streamSettings: '' }, expectedProtocol: 'vless', }, { name: 'unknown trafficReset coerces to never', row: { ...vlessRow, trafficReset: 'totally-fabricated' }, expectedProtocol: 'vless', }, ]; describe('rawInboundToFormValues', () => { for (const { name, row, expectedProtocol } of cases) { it(`maps ${name}`, () => { const values = rawInboundToFormValues(row); expect(values.protocol).toBe(expectedProtocol); expect(values.port).toBe(row.port); expect(values.remark).toBe(row.remark ?? ''); if (name === 'unknown trafficReset coerces to never') { expect(values.trafficReset).toBe('never'); } if (name === 'empty stream settings drop to undefined') { expect(values.streamSettings).toBeUndefined(); } }); } it('produces values that the InboundFormSchema accepts', () => { const values = rawInboundToFormValues(vlessRow); const result = InboundFormSchema.safeParse(values); expect(result.success).toBe(true); }); }); describe('formValuesToWirePayload', () => { it('stringifies settings/streamSettings/sniffing', () => { const values = rawInboundToFormValues(vlessRow); const payload = formValuesToWirePayload(values); expect(typeof payload.settings).toBe('string'); expect(typeof payload.streamSettings).toBe('string'); expect(typeof payload.sniffing).toBe('string'); expect(JSON.parse(payload.settings)).toEqual(vlessRow.settings); expect(JSON.parse(payload.streamSettings)).toEqual(vlessRow.streamSettings); expect(JSON.parse(payload.sniffing)).toEqual(vlessRow.sniffing); }); it('emits empty string for absent streamSettings', () => { const values = rawInboundToFormValues({ ...vlessRow, streamSettings: '' }); const payload = formValuesToWirePayload(values); expect(payload.streamSettings).toBe(''); }); it('omits nodeId when null', () => { const values = rawInboundToFormValues({ ...vlessRow, nodeId: null }); const payload = formValuesToWirePayload(values); expect('nodeId' in payload).toBe(false); }); it('includes nodeId when set', () => { const values = rawInboundToFormValues({ ...vlessRow, nodeId: 42 }); const payload = formValuesToWirePayload(values); expect(payload.nodeId).toBe(42); }); it('round-trips through raw → values → payload → values', () => { const original = rawInboundToFormValues(vlessRow); const payload = formValuesToWirePayload(original); const replay = rawInboundToFormValues({ port: payload.port, listen: payload.listen, protocol: payload.protocol, tag: payload.tag, settings: payload.settings, streamSettings: payload.streamSettings, sniffing: payload.sniffing, up: payload.up, down: payload.down, total: payload.total, remark: payload.remark, enable: payload.enable, expiryTime: payload.expiryTime, trafficReset: payload.trafficReset, lastTrafficResetTime: payload.lastTrafficResetTime, nodeId: payload.nodeId ?? null, }); expect(replay).toEqual(original); }); });