| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- package steam
- import (
- "encoding/json"
- "net/http"
- "net/http/httptest"
- "os"
- "testing"
- )
- // The live free-search page (maxprice=free&specials=1) contains rows whose
- // price text is "Free" — those must be extracted with title, appid and URL.
- func TestLiveFixture_FreeToKeepExtracted(t *testing.T) {
- // Use a server that serves the fixture for the search URL; GetFreeGames
- // also queries featuredcategories — serve an empty JSON there.
- srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- raw, err := os.ReadFile("testdata/search_free.html")
- if err != nil {
- t.Errorf("fixture: %v", err)
- return
- }
- w.Write(raw)
- }))
- t.Cleanup(srv.Close)
- c := NewClient()
- c.HTTP = srv.Client()
- // Redirect the client to the test server by rewriting the package-level
- // URLs through a custom transport? Simpler: the Client has fixed URLs, so
- // instead we test parseSearchRows directly on the fixture file.
- f, err := os.Open("testdata/search_free.html")
- if err != nil {
- t.Fatal(err)
- }
- defer f.Close()
- games, err := c.parseSearchRows(f, parseResultRow)
- if err != nil {
- t.Fatal(err)
- }
- if len(games) == 0 {
- t.Fatal("no free-to-keep games parsed from live fixture")
- }
- for _, g := range games {
- if g.ID == "" || g.Slug == "" || g.URL == "" {
- t.Errorf("game %+v missing id/slug/url", g.Title)
- }
- if g.Kind != "free-to-keep" {
- t.Errorf("game %q kind = %q, want free-to-keep", g.Title, g.Kind)
- }
- }
- }
- // The specials page (any discount) must yield rows with real prices and
- // percents — the deal data Paul asked for (e.g. "-60%", "19,99€", "7,99€").
- func TestLiveFixture_DealsHavePricesAndPercent(t *testing.T) {
- c := NewClient()
- f, err := os.Open("testdata/search_specials.html")
- if err != nil {
- t.Fatal(err)
- }
- defer f.Close()
- games, err := c.parseSearchRows(f, parseDealRow)
- if err != nil {
- t.Fatal(err)
- }
- if len(games) == 0 {
- t.Fatal("no deals parsed from live specials fixture")
- }
- for _, g := range games {
- if g.DiscountPct <= 0 {
- t.Errorf("deal %q has DiscountPct %d, want > 0", g.Title, g.DiscountPct)
- }
- if g.FinalPriceFmt == "" {
- t.Errorf("deal %q has no final price", g.Title)
- }
- if g.Kind != "deal" {
- t.Errorf("deal %q kind = %q", g.Title, g.Kind)
- }
- }
- // Sorted by discount (deepest first) is enforced by GetDeals.
- }
- // Regression: parseSearchRows must use the passed-in parse function, not
- // hardcode parseResultRow (the Oct 2026 bug that made GetDeals return 0).
- func TestParseSearchRowsUsesProvidedParseFn(t *testing.T) {
- f, err := os.Open("testdata/search_specials.html")
- if err != nil {
- t.Fatal(err)
- }
- defer f.Close()
- c := NewClient()
- deals, err := c.parseSearchRows(f, parseDealRow)
- if err != nil {
- t.Fatal(err)
- }
- if len(deals) == 0 {
- t.Fatal("parseDealRow was not applied — parse fn wiring broken (regression)")
- }
- }
- // Free rows on the free page must never carry a real price (they are free).
- func TestLiveFixture_FreeRowsHaveNoFinalPrice(t *testing.T) {
- c := NewClient()
- f, err := os.Open("testdata/search_free.html")
- if err != nil {
- t.Fatal(err)
- }
- defer f.Close()
- games, err := c.parseSearchRows(f, parseResultRow)
- if err != nil {
- t.Fatal(err)
- }
- for _, g := range games {
- if g.FinalPriceFmt != "" {
- t.Errorf("free game %q has final price %q", g.Title, g.FinalPriceFmt)
- }
- }
- }
- // The featured-categories API (free weekend) must parse without error on the
- // live fixture; free-weekend items carry kind "free-weekend".
- func TestLiveFixture_FeaturedCategoriesParses(t *testing.T) {
- raw, err := os.ReadFile("testdata/featured.json")
- if err != nil {
- t.Fatal(err)
- }
- srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
- w.Write(raw)
- }))
- t.Cleanup(srv.Close)
- sections, err := decodeFeaturedSections(raw)
- if err != nil {
- t.Fatalf("decode featured fixture: %v", err)
- }
- if len(sections) == 0 {
- t.Fatal("no sections in featured fixture")
- }
- }
- // decodeFeatured decodes the featuredcategories JSON the same way
- // getFreeWeekend does.
- func decodeFeatured(raw []byte) (map[string]featuredSection, error) {
- var sections map[string]featuredSection
- err := json.Unmarshal(raw, §ions)
- return sections, err
- }
|