package gog import ( "context" "net/http" "net/http/httptest" "os" "strings" "testing" ) // QUIRK — GOG has NO public giveaways API (api.gog.com/v1/giveaways and the // storefront-path variants all 404). The giveaway widget on the homepage is // Angular-rendered, BUT the page embeds its full section data server-side as // JSON in ) would swallow the whole rest of // the page. Pinned: exact slice, no trailing HTML. func TestExtractStoreStateTrimsScript(t *testing.T) { html := `` state := extractStoreState(html) if strings.TrimSpace(state) != `{"a":1}` { t.Fatalf("state = %q", state) } } // QUIRK (end-to-end) — the whole chain must hold together: homepage HTML → // store-state script → giveaway section → game.Game. Pinned invariants: // exactly ONE giveaway (GOG runs one at a time), store/kind correct, ID // carries the gog- prefix (namespace isolation against other providers' // IDs), URL built from the slug. func TestGetFreeGamesEndToEnd(t *testing.T) { html, err := os.ReadFile("testdata/home.html") if err != nil { t.Fatal(err) } srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.Write(html) })) t.Cleanup(srv.Close) c := NewClient() c.HTTP = srv.Client() c.HomeURL = srv.URL games, err := c.GetFreeGames(context.Background()) if err != nil { t.Fatal(err) } if len(games) != 1 { t.Fatalf("want exactly 1 giveaway, got %d", len(games)) } g := games[0] if g.Store != "gog" || g.Kind != "free-now" { t.Errorf("store/kind = %s/%s, want gog/free-now", g.Store, g.Kind) } if !strings.HasPrefix(g.ID, "gog-") { t.Errorf("id = %q, want gog- prefix", g.ID) } if g.URL == "" { t.Error("url missing") } }