package arr import ( "context" "encoding/json" "io" "net/http" "net/http/httptest" "testing" ) func TestUpdateKeepsUnknownFields(t *testing.T) { var put map[string]any srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/api/v3/movie/7" { t.Errorf("path %s", r.URL.Path) } switch r.Method { case http.MethodGet: io.WriteString(w, `{"id":7,"monitored":true,"customThing":{"a":[1,2]},"seasons":[{"seasonNumber":1,"monitored":true,"x":1},{"seasonNumber":2,"monitored":true}]}`) case http.MethodPut: json.NewDecoder(r.Body).Decode(&put) } })) defer srv.Close() err := NewClient(srv.URL, "k").Update(context.Background(), "movie", 7, func(o map[string]json.RawMessage) error { SetBool(o, "monitored", false) return SetSeasonMonitored(o, 2, false) }) if err != nil { t.Fatal(err) } if put["monitored"] != false || put["customThing"] == nil { t.Errorf("put = %v", put) } seasons := put["seasons"].([]any) if seasons[0].(map[string]any)["monitored"] != true || seasons[1].(map[string]any)["monitored"] != false || seasons[0].(map[string]any)["x"] == nil { t.Errorf("seasons = %v", seasons) } } func TestSetSeasonMonitoredUnknownSeason(t *testing.T) { obj := map[string]json.RawMessage{"seasons": json.RawMessage(`[{"seasonNumber":1,"monitored":true}]`)} if err := SetSeasonMonitored(obj, 5, true); err == nil { t.Error("want error") } } func TestReconfigureSwitchesInstanceAndKey(t *testing.T) { var gotKey, gotHost string mk := func(host string) *httptest.Server { return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { gotKey, gotHost = r.Header.Get("X-Api-Key"), host io.WriteString(w, `{"version":"1"}`) })) } a, b := mk("a"), mk("b") defer a.Close() defer b.Close() c := NewClient(a.URL, "key-a") var out struct{ Version string } if err := c.Do(context.Background(), http.MethodGet, "system/status", nil, nil, &out); err != nil || gotHost != "a" || gotKey != "key-a" { t.Fatalf("before: host=%q key=%q err=%v", gotHost, gotKey, err) } c.Reconfigure(b.URL+"/", "key-b") // a trailing slash is trimmed like in NewClient if err := c.Do(context.Background(), http.MethodGet, "system/status", nil, nil, &out); err != nil || gotHost != "b" || gotKey != "key-b" { t.Fatalf("after: host=%q key=%q err=%v", gotHost, gotKey, err) } // Used from many goroutines while being changed (run with -race to see it matter). done := make(chan bool) go func() { for i := 0; i < 50; i++ { c.Reconfigure(a.URL, "k") c.Reconfigure(b.URL, "k") } done <- true }() for i := 0; i < 50; i++ { _ = c.Do(context.Background(), http.MethodGet, "system/status", nil, nil, &out) } <-done }