mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-06-05 20:54:14 +00:00
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:
parent
a9359e921b
commit
2176e816f0
15 changed files with 363 additions and 0 deletions
|
|
@ -1,5 +1,47 @@
|
||||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
// 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`] = `
|
exports[`InboundSettingsSchema fixtures > parses hysteria2-basic byte-stably 1`] = `
|
||||||
{
|
{
|
||||||
"protocol": "hysteria2",
|
"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`] = `
|
exports[`InboundSettingsSchema fixtures > parses shadowsocks-2022 byte-stably 1`] = `
|
||||||
{
|
{
|
||||||
"protocol": "shadowsocks",
|
"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`] = `
|
exports[`InboundSettingsSchema fixtures > parses vless-tcp-none byte-stably 1`] = `
|
||||||
{
|
{
|
||||||
"protocol": "vless",
|
"protocol": "vless",
|
||||||
|
|
|
||||||
72
frontend/src/test/__snapshots__/security.test.ts.snap
Normal file
72
frontend/src/test/__snapshots__/security.test.ts.snap
Normal 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",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`;
|
||||||
34
frontend/src/test/__snapshots__/stream.test.ts.snap
Normal file
34
frontend/src/test/__snapshots__/stream.test.ts.snap
Normal 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",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`;
|
||||||
10
frontend/src/test/golden/fixtures/inbound/http-basic.json
Normal file
10
frontend/src/test/golden/fixtures/inbound/http-basic.json
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"protocol": "http",
|
||||||
|
"settings": {
|
||||||
|
"accounts": [
|
||||||
|
{ "user": "proxyuser", "pass": "proxypass" },
|
||||||
|
{ "user": "guest", "pass": "guest123" }
|
||||||
|
],
|
||||||
|
"allowTransparent": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
11
frontend/src/test/golden/fixtures/inbound/mixed-basic.json
Normal file
11
frontend/src/test/golden/fixtures/inbound/mixed-basic.json
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"protocol": "mixed",
|
||||||
|
"settings": {
|
||||||
|
"auth": "password",
|
||||||
|
"accounts": [
|
||||||
|
{ "user": "socksuser", "pass": "sockspass" }
|
||||||
|
],
|
||||||
|
"udp": true,
|
||||||
|
"ip": "127.0.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
13
frontend/src/test/golden/fixtures/inbound/tunnel-basic.json
Normal file
13
frontend/src/test/golden/fixtures/inbound/tunnel-basic.json
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
3
frontend/src/test/golden/fixtures/security/none.json
Normal file
3
frontend/src/test/golden/fixtures/security/none.json
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"security": "none"
|
||||||
|
}
|
||||||
|
|
@ -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": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
8
frontend/src/test/golden/fixtures/stream/grpc-basic.json
Normal file
8
frontend/src/test/golden/fixtures/stream/grpc-basic.json
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"network": "grpc",
|
||||||
|
"grpcSettings": {
|
||||||
|
"serviceName": "GunService",
|
||||||
|
"authority": "grpc.example.test",
|
||||||
|
"multiMode": false
|
||||||
|
}
|
||||||
|
}
|
||||||
4
frontend/src/test/golden/fixtures/stream/tcp-none.json
Normal file
4
frontend/src/test/golden/fixtures/stream/tcp-none.json
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"network": "tcp",
|
||||||
|
"tcpSettings": {}
|
||||||
|
}
|
||||||
12
frontend/src/test/golden/fixtures/stream/ws-default.json
Normal file
12
frontend/src/test/golden/fixtures/stream/ws-default.json
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"network": "ws",
|
||||||
|
"wsSettings": {
|
||||||
|
"acceptProxyProtocol": false,
|
||||||
|
"path": "/api/v2",
|
||||||
|
"host": "cdn.example.test",
|
||||||
|
"headers": {
|
||||||
|
"X-Forwarded-Proto": "https"
|
||||||
|
},
|
||||||
|
"heartbeatPeriod": 30
|
||||||
|
}
|
||||||
|
}
|
||||||
26
frontend/src/test/security.test.ts
Normal file
26
frontend/src/test/security.test.ts
Normal 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();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
26
frontend/src/test/stream.test.ts
Normal file
26
frontend/src/test/stream.test.ts
Normal 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();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
Loading…
Reference in a new issue