package internal import ( "net/http" "net/http/httptest" "os" "sync/atomic" "testing" "time" ) func TestRefreshLibraryDebouncesBurst(t *testing.T) { defer safeClearTimer() var calls atomic.Int32 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { calls.Add(1) if r.Method != http.MethodPost { t.Fatalf("expected POST, got %s", r.Method) } if r.URL.Path != "/Library/Refresh" { t.Fatalf("unexpected path %q", r.URL.Path) } if token := r.Header.Get("X-Emby-Token"); token != "admin-token" { t.Fatalf("expected API token header, got %q", token) } w.WriteHeader(http.StatusNoContent) })) defer srv.Close() t.Setenv("JELLYFIN_URL", srv.URL) t.Setenv("JELLYFIN_API_KEY", "admin-token") j := &Jellyfin{Client: srv.Client()} j.RefreshLibrary("fallback-user-token") j.RefreshLibrary("fallback-user-token") j.RefreshLibrary("fallback-user-token") time.Sleep(2500 * time.Millisecond) if got := calls.Load(); got != 1 { t.Fatalf("expected one debounced refresh request, got %d", got) } } func TestRefreshLibrarySkipsWithoutToken(t *testing.T) { defer safeClearTimer() var calls atomic.Int32 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { calls.Add(1) w.WriteHeader(http.StatusNoContent) })) defer srv.Close() t.Setenv("JELLYFIN_URL", srv.URL) t.Setenv("JELLYFIN_API_KEY", "") j := &Jellyfin{Client: srv.Client()} j.RefreshLibrary("") time.Sleep(2500 * time.Millisecond) if got := calls.Load(); got != 0 { t.Fatalf("expected zero refresh requests without token, got %d", got) } } func TestRefreshLibrarySkipsWithoutURL(t *testing.T) { defer safeClearTimer() orig := os.Getenv("JELLYFIN_URL") if err := os.Unsetenv("JELLYFIN_URL"); err != nil { t.Fatalf("unset env failed: %v", err) } t.Cleanup(func() { _ = os.Setenv("JELLYFIN_URL", orig) }) t.Setenv("JELLYFIN_API_KEY", "admin-token") j := &Jellyfin{Client: &http.Client{Timeout: 200 * time.Millisecond}} j.RefreshLibrary("fallback-user-token") time.Sleep(2500 * time.Millisecond) if refreshTimer != nil { t.Fatalf("expected timer to self-clear after skip") } } func TestRefreshLibraryUsesFallbackClientAndHandlesServerError(t *testing.T) { defer safeClearTimer() var calls atomic.Int32 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { calls.Add(1) w.WriteHeader(http.StatusInternalServerError) })) defer srv.Close() t.Setenv("JELLYFIN_URL", srv.URL) t.Setenv("JELLYFIN_API_KEY", "admin-token") j := &Jellyfin{} j.RefreshLibrary("fallback-user-token") time.Sleep(2500 * time.Millisecond) if got := calls.Load(); got != 1 { t.Fatalf("expected one refresh request, got %d", got) } }