package fa import ( "net/url" "strings" "testing" "time" ) // TestBuildSearchURL_DefaultsSendAllRatingsAndTypes asserts that an empty // SearchOptions encodes every rating and every type as enabled, matching // FA's web-form default state. func TestBuildSearchURL_DefaultsSendAllRatingsAndTypes(t *testing.T) { got := buildSearchURL("dragon", 1, SearchOptions{}) u, err := url.Parse(got) if err != nil { t.Fatalf("parse: %v", err) } q := u.Query() if q.Get("q") != "dragon" { t.Errorf("q = %q", q.Get("q")) } for _, k := range []string{"rating-general", "rating-mature", "rating-adult"} { if q.Get(k) != "1" { t.Errorf("%s = %q; want 1", k, q.Get(k)) } } for _, k := range []string{"type-art", "type-music", "type-flash", "type-story", "type-photo", "type-poetry"} { if q.Get(k) != "1" { t.Errorf("%s = %q; want 1", k, q.Get(k)) } } if q.Get("page") != "" { t.Errorf("page should be unset on page 1, got %q", q.Get("page")) } } func TestBuildSearchURL_RatingsSubsetEncodesOnlyRequested(t *testing.T) { got := buildSearchURL("x", 1, SearchOptions{Ratings: []Rating{RatingGeneral}}) q := mustQuery(t, got) if q.Get("rating-general") != "1" { t.Errorf("rating-general missing") } if q.Get("rating-mature") != "" || q.Get("rating-adult") != "" { t.Errorf("non-requested ratings should be unset; got mature=%q adult=%q", q.Get("rating-mature"), q.Get("rating-adult")) } } func TestBuildSearchURL_TypesSubsetEncodesOnlyRequested(t *testing.T) { got := buildSearchURL("x", 1, SearchOptions{Types: []SearchType{SearchTypeArt, SearchTypeStory}}) q := mustQuery(t, got) for _, k := range []string{"type-art", "type-story"} { if q.Get(k) != "1" { t.Errorf("%s should be set", k) } } for _, k := range []string{"type-music", "type-flash", "type-photo", "type-poetry"} { if q.Get(k) != "" { t.Errorf("%s should be unset; got %q", k, q.Get(k)) } } } func TestBuildSearchURL_ManualRangeFormatsDates(t *testing.T) { from := time.Date(2024, 1, 15, 0, 0, 0, 0, time.UTC) to := time.Date(2024, 6, 30, 0, 0, 0, 0, time.UTC) got := buildSearchURL("x", 1, SearchOptions{ Range: SearchRangeManual, RangeFrom: from, RangeTo: to, }) q := mustQuery(t, got) if q.Get("range") != "manual" { t.Errorf("range = %q", q.Get("range")) } if q.Get("range_from") != "2024-01-15" { t.Errorf("range_from = %q", q.Get("range_from")) } if q.Get("range_to") != "2024-06-30" { t.Errorf("range_to = %q", q.Get("range_to")) } } func TestBuildSearchURL_OrderAndPage(t *testing.T) { got := buildSearchURL("x", 3, SearchOptions{ OrderBy: SearchOrderDate, OrderAsc: true, PerPage: 48, }) q := mustQuery(t, got) if q.Get("page") != "3" { t.Errorf("page = %q", q.Get("page")) } if q.Get("order-by") != "date" { t.Errorf("order-by = %q", q.Get("order-by")) } if q.Get("order-direction") != "asc" { t.Errorf("order-direction = %q", q.Get("order-direction")) } if q.Get("perpage") != "48" { t.Errorf("perpage = %q", q.Get("perpage")) } } func TestBuildSearchURL_RootPath(t *testing.T) { got := buildSearchURL("x", 1, SearchOptions{}) if !strings.HasPrefix(got, "https://www.furaffinity.net/search/?") { t.Errorf("URL prefix wrong: %s", got) } } func mustQuery(t *testing.T, raw string) url.Values { t.Helper() u, err := url.Parse(raw) if err != nil { t.Fatalf("parse %q: %v", raw, err) } return u.Query() }