@@ -0,0 +1,71 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
"testing/fstest"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func TestMountSPA(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
dist := fstest.MapFS{
|
||||
"index.html": {Data: []byte("<html>spa-entry</html>")},
|
||||
"favicon.svg": {Data: []byte("<svg/>")},
|
||||
"assets/app.js": {Data: []byte("console.log(1)")},
|
||||
}
|
||||
r := gin.New()
|
||||
mountSPA(r, dist)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
path string
|
||||
wantStatus int
|
||||
wantBody string // 包含匹配;空跳过
|
||||
wantCache string // Cache-Control 精确匹配;空跳过
|
||||
wantJSON bool
|
||||
}{
|
||||
{name: "api 未知路径保持 JSON 404", path: "/api/v1/nope", wantStatus: 404, wantBody: "not found", wantJSON: true},
|
||||
{name: "ai 未知路径保持 JSON 404", path: "/ai/v1/nope", wantStatus: 404, wantBody: "not found", wantJSON: true},
|
||||
{name: "根路径出 index 且禁缓存", path: "/", wantStatus: 200, wantBody: "spa-entry", wantCache: "no-cache"},
|
||||
{name: "SPA 路由 fallback 到 index", path: "/ai-gateway/keys", wantStatus: 200, wantBody: "spa-entry", wantCache: "no-cache"},
|
||||
{name: "assets 命中带 immutable 长缓存", path: "/assets/app.js", wantStatus: 200, wantBody: "console.log", wantCache: "public, max-age=31536000, immutable"},
|
||||
{name: "非 assets 真实文件禁强缓存", path: "/favicon.svg", wantStatus: 200, wantCache: "no-cache"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(http.MethodGet, tt.path, nil)
|
||||
r.ServeHTTP(w, req)
|
||||
if w.Code != tt.wantStatus {
|
||||
t.Fatalf("status = %d, want %d", w.Code, tt.wantStatus)
|
||||
}
|
||||
if tt.wantBody != "" && !strings.Contains(w.Body.String(), tt.wantBody) {
|
||||
t.Fatalf("body %q does not contain %q", w.Body.String(), tt.wantBody)
|
||||
}
|
||||
if tt.wantCache != "" && w.Header().Get("Cache-Control") != tt.wantCache {
|
||||
t.Fatalf("cache-control = %q, want %q", w.Header().Get("Cache-Control"), tt.wantCache)
|
||||
}
|
||||
if tt.wantJSON && !strings.HasPrefix(w.Header().Get("Content-Type"), "application/json") {
|
||||
t.Fatalf("content-type = %q, want json", w.Header().Get("Content-Type"))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestRegisterWebUIPlaceholder 验证嵌入占位产物可挂载(裸 clone 后 go build/test 即过)。
|
||||
func TestRegisterWebUIPlaceholder(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
r := gin.New()
|
||||
if err := registerWebUI(r); err != nil {
|
||||
t.Fatalf("registerWebUI: %v", err)
|
||||
}
|
||||
w := httptest.NewRecorder()
|
||||
r.ServeHTTP(w, httptest.NewRequest(http.MethodGet, "/", nil))
|
||||
if w.Code != http.StatusOK {
|
||||
t.Fatalf("status = %d, want 200", w.Code)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user