package webui import ( "net/http" "net/http/httptest" "strings" "testing" "testing/fstest" ) func testFS() fstest.MapFS { return fstest.MapFS{ "index.html": &fstest.MapFile{Data: []byte(`{{.Title}}`)}, "assets/app-abc123.js": &fstest.MapFile{Data: []byte("console.log(1)")}, "favicon.svg": &fstest.MapFile{Data: []byte("")}, } } func newTestUI(t *testing.T) *UI { t.Helper() u, err := newFromFS(testFS()) if err != nil { t.Fatal(err) } return u } func get(t *testing.T, h http.Handler, path string) *httptest.ResponseRecorder { t.Helper() req := httptest.NewRequest(http.MethodGet, path, nil) rec := httptest.NewRecorder() h.ServeHTTP(rec, req) return rec } func TestSPAAndMeta(t *testing.T) { u := newTestUI(t) meta := func(r *http.Request) Meta { if strings.HasPrefix(r.URL.Path, "/notes/hello") { return Meta{Title: "笔记标题 - 站点", Description: "摘要", OGTitle: "笔记标题", OGType: "article", OGURL: "http://x/notes/hello", SiteName: "站点"} } return Meta{Title: "站点", Description: "默认", OGTitle: "站点", OGType: "website", SiteName: "站点"} } h := u.Handler(meta) // 根路径:默认 meta rec := get(t, h, "/") if rec.Code != 200 || !strings.Contains(rec.Body.String(), "站点") { t.Errorf("根路径应渲染默认 meta: %d %s", rec.Code, rec.Body.String()) } // SPA 深链:注入笔记 meta rec = get(t, h, "/notes/hello") if !strings.Contains(rec.Body.String(), "笔记标题 - 站点") { t.Errorf("深链应注入笔记 meta: %s", rec.Body.String()) } // html/template 自动转义:标题含恶意内容不破坏标签结构 h2 := u.Handler(func(r *http.Request) Meta { return Meta{Title: ``, OGTitle: `" onclick="x`} }) rec = get(t, h2, "/notes/evil") body := rec.Body.String() if strings.Contains(body, "