package environment import ( "context" "fmt" "math" "net/http" "net/http/httptest" "sync/atomic" "testing" ) func TestLookupMunicipalityAndCache(t *testing.T) { var calls atomic.Int32 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { calls.Add(1) if r.URL.Query().Get("key") != "test-key" { t.Error("key missing") } switch r.URL.Path { case "/v3/geocode/regeo": if r.URL.Query().Get("location") != "121.473700,31.230400" { t.Errorf("wrong coordinate order: %s", r.URL.Query().Get("location")) } fmt.Fprint(w, `{"status":"1","regeocode":{"addressComponent":{"province":"上海市","city":[],"district":"黄浦区","adcode":"310101"}}}`) case "/v3/weather/weatherInfo": if r.URL.Query().Get("city") != "310101" { t.Error("weather must use adcode") } fmt.Fprint(w, `{"status":"1","lives":[{"weather":"晴","temperature":"24","reporttime":"2026-10-04 10:00:00"}]}`) default: t.Error("unexpected path") } })) defer srv.Close() client := New("test-key") client.baseURL = srv.URL for range 2 { result, err := client.Lookup(context.Background(), 31.2304, 121.4737) if err != nil { t.Fatal(err) } if result.LocationName != "上海市 · 黄浦区" || result.Weather == nil || result.Weather.Temperature != "24" { t.Fatalf("unexpected result: %+v", result) } } if calls.Load() != 2 { t.Errorf("cache did not reduce calls: %d", calls.Load()) } } func TestPartialWeatherFailure(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/v3/geocode/regeo" { fmt.Fprint(w, `{"status":"1","regeocode":{"addressComponent":{"province":"浙江省","city":"杭州市","district":"西湖区","adcode":"330106"}}}`) } else { fmt.Fprint(w, `{"status":"0","info":"INVALID_USER_KEY"}`) } })) defer srv.Close() client := New("test-key") client.baseURL = srv.URL result, err := client.Lookup(context.Background(), 30.2, 120.1) if err != nil || result.LocationName != "杭州市 · 西湖区" || result.Weather != nil { t.Fatalf("must retain city without fabricated weather: %+v %v", result, err) } } func TestInvalidInputsAndProviderError(t *testing.T) { client := New("") if _, err := client.Lookup(context.Background(), 30, 120); err != ErrNotConfigured { t.Fatal(err) } for _, latitude := range []float64{91, math.NaN(), math.Inf(1)} { if _, err := client.Lookup(context.Background(), latitude, 120); err != ErrCoordinates { t.Fatal(err) } } srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, `{"status":"0","info":"INVALID_USER_KEY"}`) })) defer srv.Close() client = New("secret-key") client.baseURL = srv.URL if _, err := client.Lookup(context.Background(), 30, 120); err == nil { t.Fatal("provider rejection accepted") } }