test(frontend): broaden golden coverage to remaining inbounds + stream + security DUs

Round out Step 3b. Four more inbound fixtures complete the protocol set
(http with two accounts, mixed with socks-style auth, tunnel with a port
map, hysteria v1). Two parallel test files cover the other DUs:
stream.test.ts walks tcp/ws/grpc fixtures through NetworkSettingsSchema,
and security.test.ts walks none/tls/reality through SecuritySettingsSchema.

Snapshot count is now 16 across three test files. The reality fixture
locks in the array form of serverNames/shortIds (the panel class stores
them comma-joined internally but they ship as arrays on the wire). The
TLS fixture pins the file-vs-inline cert DU on the file branch.

Stream coverage for httpupgrade/xhttp/kcp and security mixed-with-stream
combos follow in the next turn, alongside the shadow harness.
This commit is contained in:
MHSanaei
2026-05-25 23:26:27 +02:00
parent a9359e921b
commit 2176e816f0
15 changed files with 363 additions and 0 deletions

View File

@@ -1,5 +1,47 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`InboundSettingsSchema fixtures > parses http-basic byte-stably 1`] = `
{
"protocol": "http",
"settings": {
"accounts": [
{
"pass": "proxypass",
"user": "proxyuser",
},
{
"pass": "guest123",
"user": "guest",
},
],
"allowTransparent": false,
},
}
`;
exports[`InboundSettingsSchema fixtures > parses hysteria-basic byte-stably 1`] = `
{
"protocol": "hysteria",
"settings": {
"clients": [
{
"auth": "hyst3ria-v1-token-XYZ",
"comment": "legacy v1",
"email": "hy1-client@example.test",
"enable": true,
"expiryTime": 0,
"limitIp": 0,
"reset": 0,
"subId": "hy1-001",
"tgId": 0,
"totalGB": 0,
},
],
"version": 1,
},
}
`;
exports[`InboundSettingsSchema fixtures > parses hysteria2-basic byte-stably 1`] = `
{
"protocol": "hysteria2",
@@ -23,6 +65,23 @@ exports[`InboundSettingsSchema fixtures > parses hysteria2-basic byte-stably 1`]
}
`;
exports[`InboundSettingsSchema fixtures > parses mixed-basic byte-stably 1`] = `
{
"protocol": "mixed",
"settings": {
"accounts": [
{
"pass": "sockspass",
"user": "socksuser",
},
],
"auth": "password",
"ip": "127.0.0.1",
"udp": true,
},
}
`;
exports[`InboundSettingsSchema fixtures > parses shadowsocks-2022 byte-stably 1`] = `
{
"protocol": "shadowsocks",
@@ -73,6 +132,22 @@ exports[`InboundSettingsSchema fixtures > parses trojan-basic byte-stably 1`] =
}
`;
exports[`InboundSettingsSchema fixtures > parses tunnel-basic byte-stably 1`] = `
{
"protocol": "tunnel",
"settings": {
"allowedNetwork": "tcp,udp",
"followRedirect": false,
"portMap": {
"8080": "10.0.0.5:80",
"8443": "10.0.0.5:443",
},
"rewriteAddress": "1.1.1.1",
"rewritePort": 53,
},
}
`;
exports[`InboundSettingsSchema fixtures > parses vless-tcp-none byte-stably 1`] = `
{
"protocol": "vless",

View File

@@ -0,0 +1,72 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`SecuritySettingsSchema fixtures > parses none byte-stably 1`] = `
{
"security": "none",
}
`;
exports[`SecuritySettingsSchema fixtures > parses reality-basic byte-stably 1`] = `
{
"realitySettings": {
"maxClientVer": "",
"maxTimediff": 0,
"minClientVer": "",
"mldsa65Seed": "",
"privateKey": "wM-2_oQRWXyLcXhV5q1ifTBcS3K8mYR3wQI3PqGFK1k",
"serverNames": [
"yahoo.com",
"www.yahoo.com",
],
"settings": {
"fingerprint": "chrome",
"mldsa65Verify": "",
"publicKey": "Tx5yj1bRcOPHkdvT2pIAQ2zh0gQ8m4OPdnzqXJxxV3o",
"serverName": "",
"spiderX": "/",
},
"shortIds": [
"a3f1",
"b8c2",
"d9e4",
],
"show": false,
"target": "yahoo.com:443",
"xver": 0,
},
"security": "reality",
}
`;
exports[`SecuritySettingsSchema fixtures > parses tls-cert-file byte-stably 1`] = `
{
"security": "tls",
"tlsSettings": {
"alpn": [
"h2",
"http/1.1",
],
"certificates": [
{
"buildChain": false,
"certificateFile": "/etc/ssl/certs/cdn.example.test.crt",
"keyFile": "/etc/ssl/private/cdn.example.test.key",
"oneTimeLoading": false,
"usage": "encipherment",
},
],
"cipherSuites": "",
"disableSystemRoot": false,
"echServerKeys": "",
"enableSessionResumption": false,
"maxVersion": "1.3",
"minVersion": "1.2",
"rejectUnknownSni": false,
"serverName": "cdn.example.test",
"settings": {
"echConfigList": "",
"fingerprint": "chrome",
},
},
}
`;

View File

@@ -0,0 +1,34 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`NetworkSettingsSchema fixtures > parses grpc-basic byte-stably 1`] = `
{
"grpcSettings": {
"authority": "grpc.example.test",
"multiMode": false,
"serviceName": "GunService",
},
"network": "grpc",
}
`;
exports[`NetworkSettingsSchema fixtures > parses tcp-none byte-stably 1`] = `
{
"network": "tcp",
"tcpSettings": {},
}
`;
exports[`NetworkSettingsSchema fixtures > parses ws-default byte-stably 1`] = `
{
"network": "ws",
"wsSettings": {
"acceptProxyProtocol": false,
"headers": {
"X-Forwarded-Proto": "https",
},
"heartbeatPeriod": 30,
"host": "cdn.example.test",
"path": "/api/v2",
},
}
`;

View File

@@ -0,0 +1,10 @@
{
"protocol": "http",
"settings": {
"accounts": [
{ "user": "proxyuser", "pass": "proxypass" },
{ "user": "guest", "pass": "guest123" }
],
"allowTransparent": false
}
}

View File

@@ -0,0 +1,20 @@
{
"protocol": "hysteria",
"settings": {
"version": 1,
"clients": [
{
"auth": "hyst3ria-v1-token-XYZ",
"email": "hy1-client@example.test",
"limitIp": 0,
"totalGB": 0,
"expiryTime": 0,
"enable": true,
"tgId": 0,
"subId": "hy1-001",
"comment": "legacy v1",
"reset": 0
}
]
}
}

View File

@@ -0,0 +1,11 @@
{
"protocol": "mixed",
"settings": {
"auth": "password",
"accounts": [
{ "user": "socksuser", "pass": "sockspass" }
],
"udp": true,
"ip": "127.0.0.1"
}
}

View File

@@ -0,0 +1,13 @@
{
"protocol": "tunnel",
"settings": {
"rewriteAddress": "1.1.1.1",
"rewritePort": 53,
"portMap": {
"8080": "10.0.0.5:80",
"8443": "10.0.0.5:443"
},
"allowedNetwork": "tcp,udp",
"followRedirect": false
}
}

View File

@@ -0,0 +1,3 @@
{
"security": "none"
}

View File

@@ -0,0 +1,22 @@
{
"security": "reality",
"realitySettings": {
"show": false,
"xver": 0,
"target": "yahoo.com:443",
"serverNames": ["yahoo.com", "www.yahoo.com"],
"privateKey": "wM-2_oQRWXyLcXhV5q1ifTBcS3K8mYR3wQI3PqGFK1k",
"minClientVer": "",
"maxClientVer": "",
"maxTimediff": 0,
"shortIds": ["a3f1", "b8c2", "d9e4"],
"mldsa65Seed": "",
"settings": {
"publicKey": "Tx5yj1bRcOPHkdvT2pIAQ2zh0gQ8m4OPdnzqXJxxV3o",
"fingerprint": "chrome",
"serverName": "",
"spiderX": "/",
"mldsa65Verify": ""
}
}
}

View File

@@ -0,0 +1,27 @@
{
"security": "tls",
"tlsSettings": {
"serverName": "cdn.example.test",
"minVersion": "1.2",
"maxVersion": "1.3",
"cipherSuites": "",
"rejectUnknownSni": false,
"disableSystemRoot": false,
"enableSessionResumption": false,
"certificates": [
{
"certificateFile": "/etc/ssl/certs/cdn.example.test.crt",
"keyFile": "/etc/ssl/private/cdn.example.test.key",
"oneTimeLoading": false,
"usage": "encipherment",
"buildChain": false
}
],
"alpn": ["h2", "http/1.1"],
"echServerKeys": "",
"settings": {
"fingerprint": "chrome",
"echConfigList": ""
}
}
}

View File

@@ -0,0 +1,8 @@
{
"network": "grpc",
"grpcSettings": {
"serviceName": "GunService",
"authority": "grpc.example.test",
"multiMode": false
}
}

View File

@@ -0,0 +1,4 @@
{
"network": "tcp",
"tcpSettings": {}
}

View File

@@ -0,0 +1,12 @@
{
"network": "ws",
"wsSettings": {
"acceptProxyProtocol": false,
"path": "/api/v2",
"host": "cdn.example.test",
"headers": {
"X-Forwarded-Proto": "https"
},
"heartbeatPeriod": 30
}
}

View File

@@ -0,0 +1,26 @@
/// <reference types="vite/client" />
import { describe, expect, it } from 'vitest';
import { SecuritySettingsSchema } from '@/schemas/protocols';
const securityFixtures = import.meta.glob<unknown>(
'./golden/fixtures/security/*.json',
{ eager: true, import: 'default' },
);
function fixtureName(path: string): string {
const file = path.split('/').pop() ?? path;
return file.replace(/\.json$/, '');
}
describe('SecuritySettingsSchema fixtures', () => {
const entries = Object.entries(securityFixtures).sort(([a], [b]) => a.localeCompare(b));
expect(entries.length, 'expected at least one fixture under golden/fixtures/security').toBeGreaterThan(0);
for (const [path, raw] of entries) {
it(`parses ${fixtureName(path)} byte-stably`, () => {
const parsed = SecuritySettingsSchema.parse(raw);
expect(parsed).toMatchSnapshot();
});
}
});

View File

@@ -0,0 +1,26 @@
/// <reference types="vite/client" />
import { describe, expect, it } from 'vitest';
import { NetworkSettingsSchema } from '@/schemas/protocols';
const streamFixtures = import.meta.glob<unknown>(
'./golden/fixtures/stream/*.json',
{ eager: true, import: 'default' },
);
function fixtureName(path: string): string {
const file = path.split('/').pop() ?? path;
return file.replace(/\.json$/, '');
}
describe('NetworkSettingsSchema fixtures', () => {
const entries = Object.entries(streamFixtures).sort(([a], [b]) => a.localeCompare(b));
expect(entries.length, 'expected at least one fixture under golden/fixtures/stream').toBeGreaterThan(0);
for (const [path, raw] of entries) {
it(`parses ${fixtureName(path)} byte-stably`, () => {
const parsed = NetworkSettingsSchema.parse(raw);
expect(parsed).toMatchSnapshot();
});
}
});