1
0
Files
nex/backend/cmd/desktop/static_test.go
lanyuanxiaoyao 0b05e08705 feat: 新增桌面应用支持
- 新增 desktop 应用入口,将后端与前端打包为单一可执行文件
- 集成系统托盘功能(getlantern/systray)
- 支持单实例锁和端口冲突检测
- 启动时自动打开浏览器显示管理界面
- 新增 embedfs 模块嵌入静态资源
- 新增跨平台构建脚本(macOS/Windows/Linux)
- 新增 macOS .app 打包脚本
- 统一 Makefile,移除 backend/Makefile
- 更新 README 添加桌面应用使用说明
2026-04-22 19:27:27 +08:00

124 lines
2.8 KiB
Go

package main
import (
"io/fs"
"net/http/httptest"
"strings"
"testing"
"github.com/gin-gonic/gin"
"nex/embedfs"
)
func TestSetupStaticFiles(t *testing.T) {
gin.SetMode(gin.TestMode)
distFS, err := fs.Sub(embedfs.FrontendDist, "frontend-dist")
if err != nil {
t.Skipf("跳过测试: 前端资源未构建: %v", err)
return
}
getContentType := func(path string) string {
if strings.HasSuffix(path, ".js") {
return "application/javascript"
}
if strings.HasSuffix(path, ".css") {
return "text/css"
}
if strings.HasSuffix(path, ".svg") {
return "image/svg+xml"
}
return "application/octet-stream"
}
r := gin.New()
r.GET("/assets/*filepath", func(c *gin.Context) {
filepath := c.Param("filepath")
data, err := fs.ReadFile(distFS, "assets"+filepath)
if err != nil {
c.Status(404)
return
}
c.Data(200, getContentType(filepath), data)
})
r.GET("/favicon.svg", func(c *gin.Context) {
data, err := fs.ReadFile(distFS, "favicon.svg")
if err != nil {
c.Status(404)
return
}
c.Data(200, "image/svg+xml", data)
})
r.NoRoute(func(c *gin.Context) {
path := c.Request.URL.Path
if strings.HasPrefix(path, "/api/") ||
strings.HasPrefix(path, "/v1/") ||
strings.HasPrefix(path, "/health") {
c.JSON(404, gin.H{"error": "not found"})
return
}
data, err := fs.ReadFile(distFS, "index.html")
if err != nil {
c.Status(500)
return
}
c.Data(200, "text/html; charset=utf-8", data)
})
t.Run("API 404", func(t *testing.T) {
req := httptest.NewRequest("GET", "/api/test", nil)
w := httptest.NewRecorder()
r.ServeHTTP(w, req)
if w.Code != 404 {
t.Errorf("期望状态码 404, 实际 %d", w.Code)
}
})
t.Run("SPA fallback", func(t *testing.T) {
req := httptest.NewRequest("GET", "/providers", nil)
w := httptest.NewRecorder()
r.ServeHTTP(w, req)
if w.Code != 200 {
t.Errorf("期望状态码 200, 实际 %d", w.Code)
}
})
t.Run("MIME type for JS", func(t *testing.T) {
req := httptest.NewRequest("GET", "/assets/test.js", nil)
w := httptest.NewRecorder()
r.ServeHTTP(w, req)
if w.Code == 200 {
expected := "application/javascript"
if w.Header().Get("Content-Type") != expected {
t.Errorf("期望 Content-Type %s, 实际 %s", expected, w.Header().Get("Content-Type"))
}
} else {
t.Log("文件不存在,跳过 MIME 类型验证")
}
})
t.Run("MIME type for CSS", func(t *testing.T) {
req := httptest.NewRequest("GET", "/assets/test.css", nil)
w := httptest.NewRecorder()
r.ServeHTTP(w, req)
if w.Code == 200 {
expected := "text/css"
if w.Header().Get("Content-Type") != expected {
t.Errorf("期望 Content-Type %s, 实际 %s", expected, w.Header().Get("Content-Type"))
}
} else {
t.Log("文件不存在,跳过 MIME 类型验证")
}
})
t.Log("静态文件服务测试通过")
}