//go:build test package square import ( "context" "net/http" "net/http/httptest" "strings" "testing" ) // TestGetCardsOnFileHTTP_MultiPage_Combined verifies cursor-based pagination of // the saved-cards list: multiple pages are fetched and combined into one // result, with the cursor threaded through to each subsequent request. This // mirrors the ListRefunds two-page test — a regression dropping the cursor loop // would silently return only the first 25-card page for a user with more. func TestGetCardsOnFileHTTP_MultiPage_Combined(t *testing.T) { var paths []string srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { paths = append(paths, r.URL.RawQuery) w.Header().Set("Content-Type", "application/json") if strings.Contains(r.URL.RawQuery, "cursor=page2") { _, _ = w.Write([]byte(`{"cards":[{"id":"ccof_3","card_brand":"VISA","last_4":"9999","exp_month":12,"exp_year":2030,"fingerprint":"fp3","reference_id":"user_1","enabled":true,"version":1,"created_at":"2026-07-31T00:00:00Z"}],"cursor":""}`)) return } _, _ = w.Write([]byte(`{"cards":[{"id":"ccof_1","card_brand":"VISA","last_4":"4242","exp_month":12,"exp_year":2030,"fingerprint":"fp1","reference_id":"user_1","enabled":true,"version":1,"created_at":"2026-07-31T00:00:00Z"},{"id":"ccof_2","card_brand":"MASTERCARD","last_4":"1111","exp_month":6,"exp_year":2029,"fingerprint":"fp2","reference_id":"user_1","enabled":true,"version":1,"created_at":"2026-07-31T00:00:00Z"}],"cursor":"page2"}`)) })) defer srv.Close() hc := &httpClient{baseURL: srv.URL, token: "t", http: srv.Client()} cards, err := getCardsOnFileHTTPWithClient(context.Background(), "user_1", hc) if err != nil { t.Fatalf("getCardsOnFileHTTP failed: %v", err) } if len(paths) != 2 { t.Fatalf("expected 2 pages fetched, got %d: %v", len(paths), paths) } if !strings.Contains(paths[0], "reference_id=user_1") { t.Errorf("expected reference_id filter on the first request, got %q", paths[0]) } if !strings.Contains(paths[1], "cursor=page2") { t.Errorf("expected the cursor threaded into the second request, got %q", paths[1]) } if len(cards) != 3 { t.Fatalf("expected 3 cards combined across pages, got %d: %+v", len(cards), cards) } // Page 1's cards must come first, page 2's appended after. if cards[0].CardID != "ccof_1" || cards[2].CardID != "ccof_3" { t.Errorf("unexpected combined card order: %+v", cards) } } // TestGetCardsOnFileHTTP_NoCards_EmptySlice verifies the empty case returns a // non-nil empty slice (callers range over the result without a nil guard). func TestGetCardsOnFileHTTP_NoCards_EmptySlice(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") _, _ = w.Write([]byte(`{"cards":[],"cursor":""}`)) })) defer srv.Close() hc := &httpClient{baseURL: srv.URL, token: "t", http: srv.Client()} cards, err := getCardsOnFileHTTPWithClient(context.Background(), "user_none", hc) if err != nil { t.Fatalf("getCardsOnFileHTTP failed: %v", err) } if cards == nil { t.Fatal("expected a non-nil empty slice for a user with no cards") } if len(cards) != 0 { t.Errorf("expected 0 cards, got %d", len(cards)) } }