Files
ez-api/internal/api/apikey_stats_handler_test.go
zenfun 33838b1e2c feat(api): wrap JSON responses in envelope
Add response envelope middleware to standardize JSON responses as
`{code,data,message}` with consistent business codes across endpoints.
Update Swagger annotations and tests to reflect the new response shape.

BREAKING CHANGE: API responses are now wrapped in a response envelope; clients must read payloads from `data` and handle `code`/`message` fields.
2026-01-10 00:15:08 +08:00

71 lines
1.8 KiB
Go

package api
import (
"math"
"net/http"
"net/http/httptest"
"testing"
"github.com/ez-api/ez-api/internal/middleware"
"github.com/ez-api/ez-api/internal/model"
"github.com/gin-gonic/gin"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
func TestAdminHandler_GetAPIKeyStatsSummary(t *testing.T) {
gin.SetMode(gin.TestMode)
db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{})
if err != nil {
t.Fatalf("open sqlite: %v", err)
}
if err := db.AutoMigrate(&model.APIKey{}); err != nil {
t.Fatalf("migrate: %v", err)
}
if err := db.Create(&model.APIKey{
GroupID: 1,
APIKey: "k1",
TotalRequests: 10,
SuccessRequests: 7,
FailureRequests: 3,
}).Error; err != nil {
t.Fatalf("create key1: %v", err)
}
if err := db.Create(&model.APIKey{
GroupID: 1,
APIKey: "k2",
TotalRequests: 5,
SuccessRequests: 5,
FailureRequests: 0,
}).Error; err != nil {
t.Fatalf("create key2: %v", err)
}
handler := &AdminHandler{db: db}
r := gin.New()
r.Use(middleware.ResponseEnvelope())
r.GET("/admin/apikey-stats/summary", handler.GetAPIKeyStatsSummary)
req := httptest.NewRequest(http.MethodGet, "/admin/apikey-stats/summary", nil)
rec := httptest.NewRecorder()
r.ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("unexpected status: got=%d body=%s", rec.Code, rec.Body.String())
}
var resp APIKeyStatsSummaryResponse
env := decodeEnvelope(t, rec, &resp)
if env.Code != "ok" {
t.Fatalf("expected code=ok, got %q", env.Code)
}
if resp.TotalRequests != 15 || resp.SuccessRequests != 12 || resp.FailureRequests != 3 {
t.Fatalf("totals mismatch: %+v", resp)
}
if math.Abs(resp.SuccessRate-0.8) > 1e-6 || math.Abs(resp.FailureRate-0.2) > 1e-6 {
t.Fatalf("rates mismatch: success=%f failure=%f", resp.SuccessRate, resp.FailureRate)
}
}