2026-07-02 10:53:44 +08:00

126 lines
4.7 KiB
Go

package dashboard
import (
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"time"
"hyapp-admin-server/internal/config"
)
func TestAslanHTTPDashboardSourceStatisticsOverview(t *testing.T) {
requestedDates := map[string]bool{}
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("Authorization") != "" {
t.Fatalf("aslan dashboard request should not send authorization header")
}
if r.URL.Path != "/console/datav/aslan/region-country/statistics" {
t.Fatalf("unexpected path: %s", r.URL.Path)
}
statDay := r.URL.Query().Get("date")
requestedDates[statDay] = true
w.Header().Set("Content-Type", "application/json")
switch statDay {
case "2026-06-30":
_ = json.NewEncoder(w).Encode([]map[string]any{{
"date": "2026-06-30",
"regionId": "legacy-middle-east",
"regionCode": "MIDDLE_EAST",
"regionName": "中东区",
"dailyRecharge": "111.25",
"dailyActive": 14,
"dailyRegister": 4,
"goldBalance": 1300,
"hostSalaryBalance": "190.50",
"countries": []map[string]any{
{"countryCode": "SA", "countryName": "Saudi Arabia", "dailyRecharge": "100.25", "dailyActive": 12, "dailyRegister": 3, "goldBalance": 1000, "hostSalaryBalance": "150.50"},
{"countryCode": "AE", "countryName": "United Arab Emirates", "dailyRecharge": "11.00", "dailyActive": 2, "dailyRegister": 1, "goldBalance": 300, "hostSalaryBalance": "40.00"},
},
}})
case "2026-06-29":
_ = json.NewEncoder(w).Encode(map[string]any{"data": []map[string]any{{
"date": "2026-06-29",
"regionId": "legacy-middle-east",
"regionCode": "MIDDLE_EAST",
"regionName": "中东区",
"dailyRecharge": "50.00",
"dailyActive": 10,
"dailyRegister": 2,
"goldBalance": 800,
"hostSalaryBalance": "100.00",
"countries": []map[string]any{
{"countryCode": "SA", "countryName": "Saudi Arabia", "dailyRecharge": "50.00", "dailyActive": 10, "dailyRegister": 2, "goldBalance": 800, "hostSalaryBalance": "100.00"},
},
}}})
default:
t.Fatalf("unexpected date: %s", statDay)
}
}))
defer server.Close()
source, err := NewAslanHTTPDashboardSource(config.DashboardExternalSourceConfig{
Enabled: true,
SourceType: "aslan_http",
AppCode: "aslan",
AppName: "Aslan",
BaseURL: server.URL,
OverviewPath: "/console/datav/aslan/region-country/statistics",
StatTimezone: "Asia/Shanghai",
RequestTimeout: time.Second,
}, staticDashboardRegionResolver{appCode: "aslan", regionID: 1001, countryCodes: []string{"SA"}})
if err != nil {
t.Fatalf("build source: %v", err)
}
shanghai, err := time.LoadLocation("Asia/Shanghai")
if err != nil {
t.Fatalf("load location: %v", err)
}
start := time.Date(2026, 6, 30, 0, 0, 0, 0, shanghai)
overview, err := source.StatisticsOverview(context.Background(), StatisticsQuery{
AppCode: "aslan",
StatTZ: "Asia/Shanghai",
StartMS: start.UnixMilli(),
EndMS: start.AddDate(0, 0, 1).UnixMilli(),
RegionID: 1001,
})
if err != nil {
t.Fatalf("StatisticsOverview: %v", err)
}
if !requestedDates["2026-06-30"] || !requestedDates["2026-06-29"] {
t.Fatalf("date requests mismatch: %#v", requestedDates)
}
assertEqual(t, overview["app_code"], "aslan")
assertEqual(t, overview["stat_tz"], "Asia/Shanghai")
assertInt64(t, overview["recharge_usd_minor"], 10_025)
assertInt64(t, overview["active_users"], 12)
assertInt64(t, overview["new_users"], 3)
assertInt64(t, overview["registered_users"], 3)
assertInt64(t, overview["coin_total"], 1_000)
assertInt64(t, overview["salary_usd_minor"], 15_050)
assertInt64(t, overview["arpu_usd_minor"], 835)
if overview["paid_users"] != nil || overview["recharge_users"] != nil || overview["arppu_usd_minor"] != nil {
t.Fatalf("aslan payer fields should be nil when the remote API does not return payer counts: %#v", overview)
}
countries, ok := overview["country_breakdown"].([]map[string]any)
if !ok || len(countries) != 1 {
t.Fatalf("country_breakdown mismatch: %#v", overview["country_breakdown"])
}
assertEqual(t, countries[0]["country_code"], "SA")
assertEqual(t, countries[0]["region_id"], int64(1001))
assertInt64(t, countries[0]["recharge_usd_minor"], 10_025)
sources, ok := overview["report_metric_sources"].([]map[string]any)
if !ok {
t.Fatalf("report_metric_sources mismatch: %#v", overview["report_metric_sources"])
}
assertMetricSourceUnavailable(t, sources, "arppu_usd_minor")
assertMetricSourceUnavailable(t, sources, "paid_users")
assertMetricSourceUnavailable(t, sources, "recharge_users")
assertMetricSourceUnavailable(t, sources, "game_turnover")
assertMetricSourceUnavailable(t, sources, "retention.day1_rate")
}