| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- /// <reference types="vite/client" />
- 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: '[email protected]',
- 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);
- });
- });
|