mirror of
https://github.com/hanzoai/commerce.git
synced 2026-10-30 15:08:42 +00:00
108 lines
4.0 KiB
Go
108 lines
4.0 KiB
Go
package billing
|
|
|
|
import (
|
|
"bytes"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/zap-proto/zip"
|
|
|
|
"github.com/hanzoai/commerce/util/test/ae"
|
|
)
|
|
|
|
// TestReadPlansSellsOnlyOnTheSellersHosts: GET /v1/billing/plans answers the
|
|
// catalog of the brand the host resolves to. Every brand's pay host reads it,
|
|
// and each listed Hanzo's ladder under its own name — pay.lux.cloud and
|
|
// pay.zoo.cloud offered Pro and Max as if Lux and Zoo sold them.
|
|
func TestReadPlansSellsOnlyOnTheSellersHosts(t *testing.T) {
|
|
c := ae.NewContext()
|
|
defer c.Close()
|
|
if _, _, err := SeedPlans(c); err != nil {
|
|
t.Fatalf("seed: %v", err)
|
|
}
|
|
|
|
// Hanzo's hosts, and a caller that names no host (the deployment default).
|
|
for _, host := range []string{"pay.hanzo.ai", "api.hanzo.ai", "PAY.HANZO.AI:443", ""} {
|
|
rows, err := ReadPlans(c, host, "", nil)
|
|
if err != nil {
|
|
t.Fatalf("%q: %v", host, err)
|
|
}
|
|
if len(rows) != len(listedCatalog()) {
|
|
t.Errorf("%q lists %d plans, the catalog puts %d on sale", host, len(rows), len(listedCatalog()))
|
|
}
|
|
}
|
|
|
|
// Every other brand's pay host sells none — an empty list, never Hanzo's, and
|
|
// never nil, which a JSON reader would take for a failure.
|
|
for _, host := range []string{"pay.lux.cloud", "pay.lux.tel", "pay.zoo.cloud", "Pay.Zoo.Cloud:443", "pay.pars.network"} {
|
|
rows, err := ReadPlans(c, host, "", nil)
|
|
if err != nil {
|
|
t.Fatalf("%q: %v", host, err)
|
|
}
|
|
if rows == nil || len(rows) != 0 {
|
|
t.Errorf("%q lists %v, want an empty list", host, rows)
|
|
}
|
|
if dns, _ := ReadPlans(c, host, "dns", nil); len(dns) != 0 {
|
|
t.Errorf("%q lists %d dns plans, want none", host, len(dns))
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestSellsFollowsTheOrgEndpointsTable: the catalog's seller is decided by the
|
|
// same host→brand table the org endpoint wears, so a spoof suffix is not Hanzo.
|
|
func TestSellsFollowsTheOrgEndpointsTable(t *testing.T) {
|
|
for host, want := range map[string]bool{
|
|
"pay.hanzo.ai": true,
|
|
"hanzo.ai": true,
|
|
"pay.lux.cloud": false,
|
|
"lux.id": false,
|
|
"zoo.ngo": false,
|
|
"pay.hanzo.ai.lux.tel": false,
|
|
"pay.lux.cloud.hanzo.ai": true,
|
|
} {
|
|
if got := Sells(host); got != want {
|
|
t.Errorf("Sells(%q) = %v, want %v", host, got, want)
|
|
}
|
|
}
|
|
}
|
|
|
|
// The purchase doors ask the same question as the list. A plan bought on a
|
|
// brand's host that sells no catalog is a plan that is not there — refused with
|
|
// the same 404 as a slug that never existed, before anything is charged.
|
|
func TestPurchaseDoorsSellOnlyOnTheSellersHosts(t *testing.T) {
|
|
ctx := ae.NewContext()
|
|
defer ctx.Close()
|
|
if _, _, err := SeedPlans(ctx); err != nil {
|
|
t.Fatalf("seed: %v", err)
|
|
}
|
|
org := moneyOrg("acme")
|
|
|
|
at := func(host, method, path, pattern, body string, h zip.Handler) int {
|
|
req := httptest.NewRequest(method, path, bytes.NewBufferString(body))
|
|
req.Host = host
|
|
req.Header.Set("Content-Type", "application/json")
|
|
return driveSeeded(func(c *zip.Ctx) {
|
|
c.Locals("organization", org)
|
|
c.SetContext(ctx)
|
|
c1MintPrincipal(c)
|
|
}, pattern, req, h).StatusCode
|
|
}
|
|
|
|
for _, host := range []string{"pay.lux.cloud", "pay.lux.tel", "pay.zoo.cloud", "pay.pars.network"} {
|
|
if got := at(host, http.MethodPost, "/v1/billing/subscribe/card", "/v1/billing/subscribe/card",
|
|
`{"sourceId":"cnon:card-nonce-ok","planId":"pro"}`, SubscribeWithCard); got != http.StatusNotFound {
|
|
t.Errorf("subscribe/card on %s = %d, want 404", host, got)
|
|
}
|
|
if got := at(host, http.MethodPost, "/v1/billing/subscriptions", "/v1/billing/subscriptions",
|
|
`{"userId":"acme","planId":"free"}`, CreateBillingSubscription); got != http.StatusNotFound {
|
|
t.Errorf("create subscription on %s = %d, want 404", host, got)
|
|
}
|
|
}
|
|
// The seller's own host is not refused by this gate.
|
|
if got := at("pay.hanzo.ai", http.MethodPost, "/v1/billing/subscriptions", "/v1/billing/subscriptions",
|
|
`{"userId":"acme","planId":"free"}`, CreateBillingSubscription); got == http.StatusNotFound {
|
|
t.Errorf("create subscription on pay.hanzo.ai = 404, the seller's own host")
|
|
}
|
|
}
|