group_stats_unavailable_test.go 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. package admin
  2. import (
  3. "context"
  4. "github.com/Wei-Shaw/sub2api/internal/config"
  5. "github.com/Wei-Shaw/sub2api/internal/service"
  6. "github.com/gin-gonic/gin"
  7. "github.com/stretchr/testify/require"
  8. "net/http"
  9. "net/http/httptest"
  10. "testing"
  11. "time"
  12. )
  13. func TestGroupStatsUnavailableDoesNotReportInventedZeroTotals(t *testing.T) {
  14. h := NewGroupHandlerWithConfig(&stubAdminService{}, nil, nil, &config.Config{})
  15. r := gin.New()
  16. r.GET("/groups/:id/stats", h.GetStats)
  17. w := httptest.NewRecorder()
  18. r.ServeHTTP(w, httptest.NewRequest(http.MethodGet, "/groups/1/stats", nil))
  19. require.Equal(t, http.StatusServiceUnavailable, w.Code)
  20. require.Contains(t, w.Body.String(), "GROUP_STATS_UNAVAILABLE")
  21. require.NotContains(t, w.Body.String(), "total_cost")
  22. w = httptest.NewRecorder()
  23. r.ServeHTTP(w, httptest.NewRequest(http.MethodGet, "/groups/-1/stats", nil))
  24. require.Equal(t, http.StatusBadRequest, w.Code)
  25. }
  26. type groupDetailStatsStub struct {
  27. service.UsageLogRepository
  28. calls int
  29. }
  30. func (s *groupDetailStatsStub) GetGroupDetailStats(_ context.Context, id int64, from, to *time.Time) (*service.GroupDetailStats, error) {
  31. s.calls++
  32. return &service.GroupDetailStats{GroupID: id, TotalCost: 32, TotalActualCost: 16, TotalAccountCost: 13, From: from, To: to}, nil
  33. }
  34. func TestGroupStatsReportsDistinctCostsAndRejectsInvalidDates(t *testing.T) {
  35. for _, mode := range []string{"", config.RunModeSimple} {
  36. repo := &groupDetailStatsStub{}
  37. dashboard := service.NewDashboardService(repo, nil, nil, nil)
  38. h := NewGroupHandlerWithConfig(&stubAdminService{}, dashboard, nil, &config.Config{RunMode: mode})
  39. r := gin.New()
  40. r.GET("/groups/:id/stats", h.GetStats)
  41. w := httptest.NewRecorder()
  42. r.ServeHTTP(w, httptest.NewRequest("GET", "/groups/42/stats", nil))
  43. require.Equal(t, 200, w.Code)
  44. require.Contains(t, w.Body.String(), `"total_cost":32`)
  45. require.Contains(t, w.Body.String(), `"total_actual_cost":16`)
  46. require.Contains(t, w.Body.String(), `"total_account_cost":13`)
  47. for _, query := range []string{"?from=bad", "?from=2026-09-14T00:00:00Z&to=2026-09-13T00:00:00Z"} {
  48. w = httptest.NewRecorder()
  49. r.ServeHTTP(w, httptest.NewRequest("GET", "/groups/42/stats"+query, nil))
  50. require.Equal(t, 400, w.Code)
  51. }
  52. require.Equal(t, 1, repo.calls)
  53. }
  54. }