package abono_test import ( "context" "testing" "time" "amadan.net/rastrillo/abono" ) // TestMembersListsEveryHolding: the owner's members screen sees every // subject's holdings, subscriptions and comps, ended ones included, by // subject and then newest first, and never an unclaimed or unrecognised // row (neither has anyone to show, and neither grants). func TestMembersListsEveryHolding(t *testing.T) { now := t0 d := newStripeDouble(t) s, _ := d.service(t, &now, abono.Config{}) seedPlans(t, s) ctx := context.Background() end := t0.AddDate(1, 0, 0) for _, sp := range []subSpec{ {ID: "sub_b", Status: "active", Price: "price_A", Customer: "cus_b", Email: "b@example.com", Start: t0, End: end, Metadata: map[string]string{"abono_subject": "b"}}, {ID: "sub_x", Status: "active", Price: "price_unknown", Customer: "cus_x", Email: "x@example.com", Start: t0, End: end, Metadata: map[string]string{"abono_subject": "x"}}, {ID: "sub_u", Status: "active", Price: "price_A", Customer: "cus_u", Email: "u@example.com", Start: t0, End: end}, } { if err := s.Sync(ctx, d.put(t, sp), abono.Hint{Subject: sp.Metadata["abono_subject"], Email: sp.Email}); err != nil { t.Fatalf("Sync %s: %v", sp.ID, err) } } // The unclaimed one: no Holder, so sub_u has an address and nobody. id, err := s.Comp(ctx, "a", "monthly", nil, "") if err != nil { t.Fatal(err) } now = t0.Add(time.Minute) ended, err := s.Comp(ctx, "b", "monthly", nil, "") if err != nil { t.Fatal(err) } if err := s.EndComp(ctx, ended); err != nil { t.Fatal(err) } ms, err := s.Members(ctx) if err != nil { t.Fatalf("Members: %v", err) } type row struct { subject, plan string source abono.Source grants bool comp int64 } var got []row for _, m := range ms { got = append(got, row{m.Subject, m.Plan, m.Source, m.Grants, m.CompID}) } want := []row{ {"a", "monthly", abono.SourceComp, true, id}, {"b", "monthly", abono.SourceComp, false, ended}, {"b", "annual", abono.SourceSubscription, true, 0}, } if len(got) != len(want) { t.Fatalf("Members = %+v, want %+v", got, want) } for i := range want { if got[i] != want[i] { t.Errorf("Members[%d] = %+v, want %+v", i, got[i], want[i]) } } } func TestMembersIsEmptyOnAFreshSite(t *testing.T) { now := t0 s, _ := newService(t, &now, abono.Config{}) ms, err := s.Members(context.Background()) if err != nil || len(ms) != 0 { t.Errorf("Members = %v, %v; want none", ms, err) } } // TestModeAccessors are what the owner's Stripe page reads (ruling R8): // test or live from the key's prefix, the sandbox, the origin the // webhook address is built on, and the clock holdings are judged by. func TestModeAccessors(t *testing.T) { now := t0 for _, c := range []struct { name string cfg abono.Config on, test, sandbox bool }{ {"off", abono.Config{Origin: "https://site.example"}, false, false, false}, {"restricted test key", abono.Config{Origin: "https://site.example", Key: "rk_test_x", WebhookSecrets: []string{"whsec_x"}}, true, true, false}, {"secret test key", abono.Config{Origin: "https://site.example", Key: "sk_test_x", WebhookSecrets: []string{"whsec_x"}}, true, true, false}, {"live key", abono.Config{Origin: "https://site.example", Key: "rk_live_x", WebhookSecrets: []string{"whsec_x"}}, true, false, false}, {"sandbox", abono.Config{Origin: "http://localhost:8080", Sandbox: true}, true, false, true}, } { t.Run(c.name, func(t *testing.T) { s, _ := newService(t, &now, c.cfg) if s.On() != c.on || s.TestMode() != c.test || s.Sandbox() != c.sandbox { t.Errorf("On, TestMode, Sandbox = %v, %v, %v; want %v, %v, %v", s.On(), s.TestMode(), s.Sandbox(), c.on, c.test, c.sandbox) } if s.Origin() != c.cfg.Origin { t.Errorf("Origin = %q, want %q", s.Origin(), c.cfg.Origin) } if !s.Now().Equal(t0) { t.Errorf("Now = %v, want the service's clock, %v", s.Now(), t0) } }) } }