Files
mihomo-patchbay/web/delay-test.ts
T
im0o c5ac59ecf9 按审查结论重构:先补测试网,再搬代码
顺序是刻意的。前端一行测试都没有,直接挪代码挪坏了 bun test 不会红,所以先把纯逻辑
抽到能被测试的位置并补上用例,最后才动组件。测试从 37 条增加到 77 条。

抽出来的四块:
- shared/outbound-chain.ts  「这个端口现在走哪条线」的链路解析,带防环,9 条测试
- web/delay-test.ts          延迟测试失败时说什么,6 个分支原本一条测试都没有
- web/runtime.ts             运行时状态的模块级单例,照 prefs.ts 已有的模式
- web/components/InboundList.vue  入站列表

出站的文本原本散成四份(读一份、显示一份、写回一份、表单又抄一份),加一种出站模式
要同时改四处,漏一个就是显示与写回不一致。合并成 OUTBOUND_PRESETS 一张表。

给认证和透传白名单补了 20 条测试。两者都是安全边界、都是纯函数、都不需要内核在线,
之前却只靠需要活内核的冒烟脚本间接覆盖。其中「形似但不是健康检查的路径」几条确认了
正则没写松。

另外:配置快照不再把整份文件原文下发(前端从不读,白白让响应体积翻倍);
yaml-cosmetics 的测试改走生产路径,之前它自己拼了一遍三步流程,落盘链路漏掉其中一步
测试照样会绿。
2026-08-10 18:21:23 +08:00

75 lines
2.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 线路延迟测试。
*
* 单独成一个模块,是因为「测失败了该跟用户说什么」有六个分支,而它原本写在组件里,
* 一条测试都加不了。这些话是用户唯一能看到的诊断信息,值得测。
*/
import { ref } from 'vue'
import { ApiError, api } from './api'
/** 超时,毫秒。文案里会用到它,所以不能让接口和文案各写一个数。 */
export const TEST_TIMEOUT_MS = 5000
/**
* 把内核的延迟测试结果翻译成一句说明原因的话。
*
* 内核对这件事的回答是精确的(内核源码 hub/route/proxies.go:122-145):
* 504 在给定超时内没有完成
* 503 连接建立失败,或者测得的延迟为 0
* 404 这个名字不在内核的全局出站表里
* 笼统说一句「测不通」会把它们混在一起,而这三种要查的地方完全不一样。
*/
export function describeTestFailure(
name: string,
error: unknown,
timeoutMs = TEST_TIMEOUT_MS,
): string {
if (!(error instanceof ApiError)) return `${name} 延迟测试失败:${String(error)}`
if (error.status === 504) {
return `${name} 延迟测试超时,${String(timeoutMs / 1000)} 秒内没有取到测试地址`
}
if (error.status === 404) {
return `${name} 不在内核的出站表里,无法测试。订阅线路需要从所属订阅进去测。`
}
const detail = String(error.payload.message ?? '')
// 内核对连接失败给的是一句没有信息量的通用英文,替换成能指导排查的话
const generic = detail === '' || detail === 'An error occurred in the delay test'
if (error.status === 503) {
return generic
? `${name} 无法建立连接,线路可能已失效,或本机到该服务器的网络不通`
: `${name} 无法建立连接:${detail}`
}
return `${name} 延迟测试失败(HTTP ${String(error.status)})${generic ? '' : `:${detail}`}`
}
/**
* 管理「哪几条线路正在测」。
*
* 测延迟是纯读操作,不影响配置也不影响别的线路,所以它只标记自己那一条忙碌,
* 不禁用界面上的任何其它东西。
*/
export function useDelayTest(onFinished: () => void, onFailure: (message: string) => void) {
const testing = ref<string[]>([])
async function test(name: string, provider?: string) {
if (testing.value.includes(name)) return
testing.value = [...testing.value, name]
try {
await api.testLine(name, provider, TEST_TIMEOUT_MS)
onFinished()
} catch (error) {
// 测不通是关于线路的结论,不是 Patchbay 出了故障
onFailure(describeTestFailure(name, error))
} finally {
testing.value = testing.value.filter((n) => n !== name)
}
}
return { testing, test }
}