mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-11-05 16:57:32 +00:00
## 迁移
dashboard_js_scope_test.go → webui/test/
embed_read_test.go → webui/test/
mascot_asset_test.go → webui/test/
这三个原先都直接读未导出的 `dashboardFS`(`go:embed` 的变量)。
上一批已经加了导出入口 `FrontendAsset(name)`,所以只需换调用即可,
不涉及行为改动。
## 迁移暴露的三处重复(一并去重)
迁过去之后编译报了三组重复定义:
stripJSComments helpers_test.go 与 dashboard_js_scope_test.go 各一份
dashboardJSSource helpers_test.go 与 dashboard_js_scope_test.go 各一份
mustReadEmbedded embed_read_test.go 里定义,kernel_buttons_render_test.go 在用
前两个是**迁移造成的镜像**:原本包内的辅助函数在迁到 test/ 时被复制了一份。
逐字比较确认两份 `stripJSComments` 实现完全相同,删掉包内那份、保留
`test/helpers_test.go` 里的共享版本。
第三个不同:`mustReadEmbedded` 只有包内的 `kernel_buttons_render_test.go` 在用。
把它改成直接调导出的 `FrontendAsset`,不再需要这个辅助函数 ——
包内测试从此也不再依赖"哪个变量装着 embed 资源"这种实现细节。
## 顺带清掉一批未使用导入
批量迁移+脚本改包名之后,多个文件留着已经不用的 `webui` 导入
(有的只在注释里提到 `webui.FrontendAsset`)。用 `go vet` 的输出逐个清理,
最后 `go vet ./internal/plugins/webui/...` 干净。
## 判据未失效(变异验证)
把 dashboard.js 里 ack 超时 `}, 600000);` 改成 `}, 30000);`:
--- FAIL: TestChatAckTimeoutIsGenerous
chat_ack_timeout_test.go:59: ★ 受理超时只有 30000 ms —— 太小。
恢复后全绿。
## 进度
webui/ 180 条(原 186,迁走 6 条)
webui/test/ 22 条
合计 202 条,与迁移前一致(+ 之前新增的契约判据)
`webui/` 剩下 20 个测试文件,全部依赖 `handleXxx` / `newTestHandler` /
`testSDK` 等未导出 handler 与装配辅助,需要先有导出入口才能迁。
其中 `proxy_test.go`(45 处)和 `handler_test.go`(90 处)是最大两块,
要迁必须先给 webui 导出"起一个带路由的 handler"的测试入口。
## 验证
go build ./... PASS
go vet ./internal/plugins/webui/... PASS
gofmt -l 干净
go test ./... -count=1 65 包全过,0 FAIL
webui 连跑 3 次 0 失败
99 lines
2.5 KiB
Go
99 lines
2.5 KiB
Go
package test
|
|
|
|
// 本文件是 test 包的共享测试辅助(不属于任何单个判据)。
|
|
//
|
|
// 放在这里而不是某个 *_test.go 里:多个判据文件都要用它,
|
|
// 而在"测试与源码分离"之后,它们不能再从包内符号借用。
|
|
|
|
import (
|
|
"github.com/JianFeeeee/HologramAgent/internal/plugins/webui"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// stripJSComments 剥掉 // 行注释与 /* */ 块注释(粗粒度,但足够用于词频统计)。
|
|
//
|
|
// 不做完整的 JS 词法分析:本判据只用于「统计某个标识符出现次数」,
|
|
// 粗粒度剥离已经足够,且不会误伤字符串里的 //(本文件没有这类内容,
|
|
// 若将来有,宁可少剥也不能多剥 —— 多剥会让判据漏报)。
|
|
func stripJSComments(s string) string {
|
|
var b strings.Builder
|
|
b.Grow(len(s))
|
|
inLine, inBlock := false, false
|
|
var inStr byte
|
|
for i := 0; i < len(s); i++ {
|
|
c := s[i]
|
|
if inLine {
|
|
if c == '\n' {
|
|
inLine = false
|
|
b.WriteByte(c)
|
|
}
|
|
continue
|
|
}
|
|
if inBlock {
|
|
if c == '*' && i+1 < len(s) && s[i+1] == '/' {
|
|
inBlock = false
|
|
i++
|
|
}
|
|
continue
|
|
}
|
|
if c == '\n' {
|
|
b.WriteByte(c)
|
|
continue
|
|
}
|
|
if inStr != 0 {
|
|
b.WriteByte(c)
|
|
if c == '\\' {
|
|
if i+1 < len(s) {
|
|
b.WriteByte(s[i+1])
|
|
i++
|
|
}
|
|
continue
|
|
}
|
|
if c == inStr {
|
|
inStr = 0
|
|
}
|
|
continue
|
|
}
|
|
if c == '"' || c == '\'' || c == '`' {
|
|
// 反引号也是字符串定界符,但它可跨行 —— 本判据只统计标识符,
|
|
// 跨行模板串里出现标识符属正常,此处按普通字符串处理即可。
|
|
inStr = c
|
|
b.WriteByte(c)
|
|
continue
|
|
}
|
|
if c == '/' && i+1 < len(s) && s[i+1] == '/' {
|
|
inLine = true
|
|
i++
|
|
continue
|
|
}
|
|
if c == '/' && i+1 < len(s) && s[i+1] == '*' {
|
|
inBlock = true
|
|
i++
|
|
continue
|
|
}
|
|
b.WriteByte(c)
|
|
}
|
|
return b.String()
|
|
}
|
|
|
|
// dashboardJSSource 取出待测的前端脚本原文。
|
|
//
|
|
// 经导出的 webui.FrontendAsset 读 —— 与"资源存在哪个变量、怎么 embed"
|
|
// 完全无关,测试只关心「实际会被发出去的那份文本」。
|
|
func dashboardJSSource(t *testing.T) string {
|
|
t.Helper()
|
|
b, err := webui.FrontendAsset("dashboard.js")
|
|
if err != nil {
|
|
t.Fatalf("读 dashboard.js: %v", err)
|
|
}
|
|
return string(b)
|
|
}
|
|
|
|
// dashboardJS 与 dashboardJSSource 同义,保留两个名字是因为
|
|
// 原来的判据文件各自用其中一个(迁移时不做无谓重命名)。
|
|
func dashboardJS(t *testing.T) string {
|
|
t.Helper()
|
|
return dashboardJSSource(t)
|
|
}
|