Files
tokens-reef/backend/internal/server/routes/common_test.go
User c9992af876
Some checks failed
CI / test (push) Has been cancelled
CI / golangci-lint (push) Has been cancelled
Security Scan / backend-security (push) Has been cancelled
Security Scan / frontend-security (push) Has been cancelled
test: add tests for prommetrics, common routes, and Sora admin page
- Add prommetrics package tests (12 tests covering all metric functions)
- Add routes/common_test.go with health check, readiness, liveness tests
- Add SoraAdminView.spec.ts with 11 component tests
2026-04-16 13:04:03 +08:00

242 lines
6.2 KiB
Go

package routes
import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
)
func TestRegisterCommonRoutes(t *testing.T) {
gin.SetMode(gin.TestMode)
r := gin.New()
RegisterCommonRoutes(r)
// Test /health
w := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/health", nil)
r.ServeHTTP(w, req)
assert.Equal(t, http.StatusOK, w.Code)
// Test /live
w = httptest.NewRecorder()
req = httptest.NewRequest(http.MethodGet, "/live", nil)
r.ServeHTTP(w, req)
assert.Equal(t, http.StatusOK, w.Code)
// Test /ready (no health checker set)
w = httptest.NewRecorder()
req = httptest.NewRequest(http.MethodGet, "/ready", nil)
r.ServeHTTP(w, req)
assert.Equal(t, http.StatusOK, w.Code)
// Test /metrics
w = httptest.NewRecorder()
req = httptest.NewRequest(http.MethodGet, "/metrics", nil)
r.ServeHTTP(w, req)
assert.Equal(t, http.StatusOK, w.Code)
// Test /setup/status
w = httptest.NewRecorder()
req = httptest.NewRequest(http.MethodGet, "/setup/status", nil)
r.ServeHTTP(w, req)
assert.Equal(t, http.StatusOK, w.Code)
var setupResp map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &setupResp)
assert.NoError(t, err)
assert.Equal(t, float64(0), setupResp["code"])
// Test POST /api/event_logging/batch
w = httptest.NewRecorder()
req = httptest.NewRequest(http.MethodPost, "/api/event_logging/batch", nil)
r.ServeHTTP(w, req)
assert.Equal(t, http.StatusOK, w.Code)
}
func TestHealthHandler_NoHealthChecker(t *testing.T) {
gin.SetMode(gin.TestMode)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest(http.MethodGet, "/health", nil)
healthHandler(c)
assert.Equal(t, http.StatusOK, w.Code)
var resp map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &resp)
assert.NoError(t, err)
assert.Equal(t, "ok", resp["status"])
components, ok := resp["components"].(map[string]interface{})
assert.True(t, ok)
db, ok := components["database"].(map[string]interface{})
assert.True(t, ok)
assert.Equal(t, "unknown", db["status"])
}
func TestReadinessHandler_NoHealthChecker(t *testing.T) {
gin.SetMode(gin.TestMode)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest(http.MethodGet, "/ready", nil)
readinessHandler(c)
assert.Equal(t, http.StatusOK, w.Code)
var resp map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &resp)
assert.NoError(t, err)
assert.Equal(t, "ready", resp["status"])
}
func TestLivenessHandler(t *testing.T) {
gin.SetMode(gin.TestMode)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest(http.MethodGet, "/live", nil)
livenessHandler(c)
assert.Equal(t, http.StatusOK, w.Code)
var resp map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &resp)
assert.NoError(t, err)
assert.Equal(t, "alive", resp["status"])
// Verify timestamp is valid
ts, ok := resp["timestamp"].(string)
assert.True(t, ok)
_, err = time.Parse(time.RFC3339, ts)
assert.NoError(t, err)
}
// mockHealthChecker implements HealthChecker for testing
type mockHealthChecker struct {
dbHealthy bool
redisHealthy bool
}
func (m *mockHealthChecker) CheckDatabase() bool { return m.dbHealthy }
func (m *mockHealthChecker) CheckRedis() bool { return m.redisHealthy }
func TestHealthHandler_WithHealthyChecker(t *testing.T) {
gin.SetMode(gin.TestMode)
// Reset the healthChecker for test
healthChecker = &mockHealthChecker{dbHealthy: true, redisHealthy: true}
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest(http.MethodGet, "/health", nil)
healthHandler(c)
assert.Equal(t, http.StatusOK, w.Code)
var resp map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &resp)
assert.NoError(t, err)
assert.Equal(t, "ok", resp["status"])
}
func TestHealthHandler_WithUnhealthyDB(t *testing.T) {
gin.SetMode(gin.TestMode)
healthChecker = &mockHealthChecker{dbHealthy: false, redisHealthy: true}
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest(http.MethodGet, "/health", nil)
healthHandler(c)
assert.Equal(t, http.StatusServiceUnavailable, w.Code)
var resp map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &resp)
assert.NoError(t, err)
assert.Equal(t, "degraded", resp["status"])
}
func TestHealthHandler_WithUnhealthyRedis(t *testing.T) {
gin.SetMode(gin.TestMode)
healthChecker = &mockHealthChecker{dbHealthy: true, redisHealthy: false}
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest(http.MethodGet, "/health", nil)
healthHandler(c)
assert.Equal(t, http.StatusServiceUnavailable, w.Code)
var resp map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &resp)
assert.NoError(t, err)
assert.Equal(t, "degraded", resp["status"])
}
func TestReadinessHandler_AllHealthy(t *testing.T) {
gin.SetMode(gin.TestMode)
healthChecker = &mockHealthChecker{dbHealthy: true, redisHealthy: true}
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest(http.MethodGet, "/ready", nil)
readinessHandler(c)
assert.Equal(t, http.StatusOK, w.Code)
var resp map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &resp)
assert.NoError(t, err)
assert.Equal(t, "ready", resp["status"])
}
func TestReadinessHandler_NotReady(t *testing.T) {
gin.SetMode(gin.TestMode)
healthChecker = &mockHealthChecker{dbHealthy: true, redisHealthy: false}
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest(http.MethodGet, "/ready", nil)
readinessHandler(c)
assert.Equal(t, http.StatusServiceUnavailable, w.Code)
var resp map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &resp)
assert.NoError(t, err)
assert.Equal(t, "not_ready", resp["status"])
}
func TestDelegatedMetricFunctions(t *testing.T) {
// These should not panic - they delegate to prommetrics package
RecordHTTPRequest("GET", "/test", 200, 100*time.Millisecond)
SetDBConnections(5, 3)
SetRedisConnections(10, 4)
SetActiveAccounts(50)
SetRequestQueueDepth(5)
SetOpsHealthScore(90)
SetErrorRate(0.1)
SetSuccessRate(0.9)
SetQPS(100.0)
SetTPS(500.0)
}