package main import ( "encoding/json" "net/http" "testing" ) // The public price book (#1374): CORS-open pass-through of the provisioner's // tiers, cached, empty when no provisioner is configured. func TestPricebookServesTiersCORSOpenAndCached(t *testing.T) { tiers := []map[string]any{{"key": "family", "name": "Family", "label": "€5.50 a year"}} cloud, _, _ := fakeCloud(t, http.StatusOK, map[string]any{ "billing": map[string]any{"tiers": tiers}, }) ts, s := newTestServer(t) s.cloud = newCloudProvisioner(cloud.URL, "caller-token") resp, err := http.Get(ts.URL + "/api/pricebook") if err != nil { t.Fatal(err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { t.Fatalf("status %d", resp.StatusCode) } // The caller is a SPACE origin's browser JS — the endpoint must be open. if got := resp.Header.Get("Access-Control-Allow-Origin"); got != "*" { t.Errorf("Access-Control-Allow-Origin = %q, want *", got) } var body struct { Tiers []map[string]any `json:"tiers"` } if err := json.NewDecoder(resp.Body).Decode(&body); err != nil { t.Fatal(err) } if len(body.Tiers) != 1 || body.Tiers[0]["key"] != "family" { t.Fatalf("tiers = %v, want the fake cloud's family tier", body.Tiers) } // Cached: kill the upstream; the answer must not change within the TTL. cloud.Close() resp2, err := http.Get(ts.URL + "/api/pricebook") if err != nil { t.Fatal(err) } defer resp2.Body.Close() var body2 struct { Tiers []map[string]any `json:"tiers"` } if err := json.NewDecoder(resp2.Body).Decode(&body2); err != nil { t.Fatal(err) } if len(body2.Tiers) != 1 { t.Fatalf("cached tiers = %v, want the earlier copy", body2.Tiers) } } func TestPricebookEmptyWithoutProvisioner(t *testing.T) { ts, _ := newTestServer(t) resp, err := http.Get(ts.URL + "/api/pricebook") if err != nil { t.Fatal(err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { t.Fatalf("status %d", resp.StatusCode) } var body struct { Tiers []map[string]any `json:"tiers"` } if err := json.NewDecoder(resp.Body).Decode(&body); err != nil { t.Fatal(err) } if len(body.Tiers) != 0 { t.Fatalf("tiers = %v, want empty (no provisioner)", body.Tiers) } }