package web
import (
"html/template"
"path/filepath"
"strings"
"testing"
"rond-with-you/internal/config"
)
// TestSmokeRenderAllPages 把启动自检搬进 go test:每个页面都要能用「最小可用数据」渲染到底。
//
// 比 TestPageTemplatesParse 更强的地方在于**执行**:模板能解析不代表渲染得完,
// 「字段不存在 / 对着 nil 解引用」只在执行期暴露,而线上表现是「HTTP 200 + 半张页面」。
// 2026-10-09 的 /admin/settings 截断就是这么来的(新模板引用了旧结构体里没有的字段)。
func TestSmokeRenderAllPages(t *testing.T) {
srv := &Server{cfg: &config.Config{}}
pages := make(map[string]pageSet, len(pageFiles))
for key, def := range pageFiles {
tpl, err := template.New(filepath.Base(def.files[0])).Funcs(templateFuncs()).
ParseFS(tmplFS, def.files...)
if err != nil {
t.Fatalf("解析模板 %s 失败: %v", key, err)
}
pages[key] = pageSet{t: tpl, entry: def.entry}
}
srv.pages = pages
if err := srv.smokeRender(); err != nil {
t.Fatal(err)
}
// 定义性不变量:pageFiles 里每加一个页面,就必须在 pageProbe 里配一份自检数据,
// 否则那一页会悄悄逃过自检(smokeRender 会把缺项报成失败,这里再独立钉一次)。
for key := range pageFiles {
if _, ok := pageProbe[key]; !ok {
t.Errorf("页面 %s 没有自检数据(pageProbe 缺项)——新加页面时要一起补", key)
}
}
for key := range pageProbe {
if _, ok := pageFiles[key]; !ok {
t.Errorf("pageProbe 里的 %s 不是已注册页面(改名后忘了同步?)", key)
}
}
}
// TestSmokeRenderCatchesFieldDrift 变异验证:把页面数据换成**字段更少**的类型时必须报错。
//
// 光断言「当前代码自检通过」证明不了自检有效——它可能只是什么都没检查。
// 这里用 Page 顶替 SettingsData(模板引用的 .Modules / .S3Info 都不在 Page 上),
// 自检必须红,且错误信息里要能看到是哪一页。
func TestSmokeRenderCatchesFieldDrift(t *testing.T) {
srv := &Server{cfg: &config.Config{}}
pages := make(map[string]pageSet, len(pageFiles))
for key, def := range pageFiles {
tpl, err := template.New(filepath.Base(def.files[0])).Funcs(templateFuncs()).
ParseFS(tmplFS, def.files...)
if err != nil {
t.Fatalf("解析模板 %s 失败: %v", key, err)
}
pages[key] = pageSet{t: tpl, entry: def.entry}
}
srv.pages = pages
orig := pageProbe["admin/settings"]
pageProbe["admin/settings"] = func() any { return probePage("admin") }
t.Cleanup(func() { pageProbe["admin/settings"] = orig })
err := srv.smokeRender()
if err == nil {
t.Fatal("页面数据缺字段时自检必须报错,否则它什么也挡不住")
}
if !strings.Contains(err.Error(), "admin/settings") {
t.Errorf("自检报错要指名是哪个页面,实际为:%v", err)
}
}