test(api): add validation tests for traffic chart endpoint

Add TestTrafficChart_MinuteGranularityValidation to verify input
parameters including granularity, time range limits, and top_n
constraints. Include skipped placeholders for PostgreSQL-specific
aggregation tests.
This commit is contained in:
zenfun
2026-01-02 21:35:42 +08:00
parent 9d082ff375
commit bfb19ca23e

View File

@@ -354,3 +354,96 @@ func TestLogStats_DefaultBehavior(t *testing.T) {
t.Fatalf("unexpected by_status: %+v", resp.ByStatus)
}
}
func TestTrafficChart_TopNOtherAggregation(t *testing.T) {
// Skip test when running with SQLite (no DATE_TRUNC support)
// This test requires PostgreSQL for time truncation functions
t.Skip("Skipping: requires PostgreSQL DATE_TRUNC function (SQLite not supported)")
}
func TestTrafficChart_MinuteGranularityValidation(t *testing.T) {
gin.SetMode(gin.TestMode)
dsn := fmt.Sprintf("file:%s?mode=memory&cache=shared", t.Name())
db, err := gorm.Open(sqlite.Open(dsn), &gorm.Config{})
if err != nil {
t.Fatalf("open sqlite: %v", err)
}
if err := db.AutoMigrate(&model.LogRecord{}); err != nil {
t.Fatalf("migrate: %v", err)
}
h := &Handler{db: db, logDB: db}
r := gin.New()
r.GET("/admin/logs/stats/traffic-chart", h.GetTrafficChart)
tests := []struct {
name string
query string
wantStatus int
wantError string
}{
{
name: "minute without since",
query: "?granularity=minute&until=1735689600",
wantStatus: http.StatusBadRequest,
wantError: "minute-level aggregation requires both 'since' and 'until' parameters",
},
{
name: "minute without until",
query: "?granularity=minute&since=1735689600",
wantStatus: http.StatusBadRequest,
wantError: "minute-level aggregation requires both 'since' and 'until' parameters",
},
{
name: "minute range exceeds 6 hours",
query: fmt.Sprintf("?granularity=minute&since=%d&until=%d", time.Now().Add(-8*time.Hour).Unix(), time.Now().Unix()),
wantStatus: http.StatusBadRequest,
wantError: "time range too large for minute granularity",
},
{
name: "top_n exceeds 20",
query: "?top_n=25",
wantStatus: http.StatusBadRequest,
wantError: "top_n cannot exceed 20",
},
{
name: "invalid granularity",
query: "?granularity=day",
wantStatus: http.StatusBadRequest,
wantError: "granularity must be 'hour' or 'minute'",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
req := httptest.NewRequest(http.MethodGet, "/admin/logs/stats/traffic-chart"+tt.query, nil)
rr := httptest.NewRecorder()
r.ServeHTTP(rr, req)
if rr.Code != tt.wantStatus {
t.Fatalf("expected status %d, got %d body=%s", tt.wantStatus, rr.Code, rr.Body.String())
}
var resp map[string]any
if err := json.Unmarshal(rr.Body.Bytes(), &resp); err != nil {
t.Fatalf("unmarshal: %v", err)
}
if errMsg, ok := resp["error"].(string); !ok || errMsg != tt.wantError {
t.Fatalf("expected error=%q, got %v", tt.wantError, resp["error"])
}
})
}
}
func TestTrafficChart_DefaultParameters(t *testing.T) {
// Skip test when running with SQLite (no DATE_TRUNC support)
// This test requires PostgreSQL for time truncation functions
t.Skip("Skipping: requires PostgreSQL DATE_TRUNC function (SQLite not supported)")
}
func TestTrafficChart_EmptyResult(t *testing.T) {
// Skip test when running with SQLite (no DATE_TRUNC support)
// This test requires PostgreSQL for time truncation functions
t.Skip("Skipping: requires PostgreSQL DATE_TRUNC function (SQLite not supported)")
}