Files
cms-server/server/server_test.go
Asai Neko 82c412d839
All checks were successful
Server Check Build (NixCN CMS) TeamCity build finished
Add more tests for modules co worked by claude
Signed-off-by: Asai Neko <sugar@sne.moe>
2026-03-26 23:36:40 +08:00

120 lines
3.1 KiB
Go

package server
import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin"
"nixcn-cms/api"
"nixcn-cms/middleware"
"nixcn-cms/testutil"
)
func init() { gin.SetMode(gin.TestMode) }
// buildRouter mirrors the engine setup inside Start() without blocking on
// ListenAndServe, making it possible to use httptest.
func buildRouter() *gin.Engine {
r := gin.New()
r.Use(otelgin.Middleware(viper.GetString("server.service_name")))
r.Use(middleware.GinLogger())
r.Use(gin.Recovery())
api.Handler(r.Group("/app/api/v1"))
return r
}
func TestServerRouterResponds(t *testing.T) {
testutil.Setup(t)
testutil.SeedClient(t)
r := buildRouter()
srv := httptest.NewServer(r)
defer srv.Close()
// POST /auth/magic exists — any response other than 404 confirms routing.
resp, err := http.Post(srv.URL+"/app/api/v1/auth/magic", "application/json", nil)
require.NoError(t, err)
defer resp.Body.Close()
assert.NotEqual(t, http.StatusNotFound, resp.StatusCode)
}
func TestServerRouterNotFound(t *testing.T) {
testutil.Setup(t)
r := buildRouter()
req := httptest.NewRequest(http.MethodGet, "/app/api/v1/nonexistent", nil)
w := httptest.NewRecorder()
r.ServeHTTP(w, req)
assert.Equal(t, http.StatusNotFound, w.Code)
}
func TestServerRouterRecovery(t *testing.T) {
testutil.Setup(t)
r := gin.New()
r.Use(gin.Recovery())
r.GET("/panic", func(c *gin.Context) { panic("test panic") })
req := httptest.NewRequest(http.MethodGet, "/panic", nil)
w := httptest.NewRecorder()
r.ServeHTTP(w, req)
// Recovery middleware must catch the panic and return 500.
assert.Equal(t, http.StatusInternalServerError, w.Code)
}
func TestServerModeRelease(t *testing.T) {
viper.Set("server.debug_mode", false)
viper.Set("server.service_name", "test-svc")
defer viper.Reset()
// Calling Start() would block, so we replicate only the mode-setting logic.
if !viper.GetBool("server.debug_mode") {
gin.SetMode(gin.ReleaseMode)
}
assert.Equal(t, gin.ReleaseMode, gin.Mode())
gin.SetMode(gin.TestMode) // restore
}
func TestServerHealthEndpoints(t *testing.T) {
testutil.Setup(t)
testutil.SeedClient(t)
r := buildRouter()
endpoints := []struct {
method string
path string
}{
{http.MethodPost, "/app/api/v1/auth/magic"},
{http.MethodPost, "/app/api/v1/auth/exchange"},
{http.MethodGet, "/app/api/v1/event/list"},
{http.MethodGet, "/app/api/v1/user/info"},
}
for _, ep := range endpoints {
t.Run(ep.method+" "+ep.path, func(t *testing.T) {
req := httptest.NewRequest(ep.method, ep.path, nil)
w := httptest.NewRecorder()
r.ServeHTTP(w, req)
// Route must be registered — anything other than 404 is fine.
assert.NotEqual(t, http.StatusNotFound, w.Code,
"route %s %s should be registered", ep.method, ep.path)
// Response must be valid JSON.
var body map[string]any
err := json.Unmarshal(w.Body.Bytes(), &body)
assert.NoError(t, err, "response must be valid JSON for %s %s", ep.method, ep.path)
})
}
}