rastrillo / abono Public

Clone
git clone https://amadan.net/rastrillo/abono

Plain git — no account needed to clone.

Download

Download this file

1package abono_test
2
3import (
4 "context"
5 "testing"
6 "time"
7
8 "amadan.net/rastrillo/abono"
9)
10
11// TestMembersListsEveryHolding: the owner's members screen sees every
12// subject's holdings, subscriptions and comps, ended ones included, by
13// subject and then newest first, and never an unclaimed or unrecognised
14// row (neither has anyone to show, and neither grants).
15func TestMembersListsEveryHolding(t *testing.T) {
16 now := t0
17 d := newStripeDouble(t)
18 s, _ := d.service(t, &now, abono.Config{})
19 seedPlans(t, s)
20 ctx := context.Background()
21
22 end := t0.AddDate(1, 0, 0)
23 for _, sp := range []subSpec{
24 {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"}},
25 {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"}},
26 {ID: "sub_u", Status: "active", Price: "price_A", Customer: "cus_u", Email: "u@example.com", Start: t0, End: end},
27 } {
28 if err := s.Sync(ctx, d.put(t, sp), abono.Hint{Subject: sp.Metadata["abono_subject"], Email: sp.Email}); err != nil {
29 t.Fatalf("Sync %s: %v", sp.ID, err)
30 }
31 }
32 // The unclaimed one: no Holder, so sub_u has an address and nobody.
33 id, err := s.Comp(ctx, "a", "monthly", nil, "")
34 if err != nil {
35 t.Fatal(err)
36 }
37 now = t0.Add(time.Minute)
38 ended, err := s.Comp(ctx, "b", "monthly", nil, "")
39 if err != nil {
40 t.Fatal(err)
41 }
42 if err := s.EndComp(ctx, ended); err != nil {
43 t.Fatal(err)
44 }
45
46 ms, err := s.Members(ctx)
47 if err != nil {
48 t.Fatalf("Members: %v", err)
49 }
50 type row struct {
51 subject, plan string
52 source abono.Source
53 grants bool
54 comp int64
55 }
56 var got []row
57 for _, m := range ms {
58 got = append(got, row{m.Subject, m.Plan, m.Source, m.Grants, m.CompID})
59 }
60 want := []row{
61 {"a", "monthly", abono.SourceComp, true, id},
62 {"b", "monthly", abono.SourceComp, false, ended},
63 {"b", "annual", abono.SourceSubscription, true, 0},
64 }
65 if len(got) != len(want) {
66 t.Fatalf("Members = %+v, want %+v", got, want)
67 }
68 for i := range want {
69 if got[i] != want[i] {
70 t.Errorf("Members[%d] = %+v, want %+v", i, got[i], want[i])
71 }
72 }
73}
74
75func TestMembersIsEmptyOnAFreshSite(t *testing.T) {
76 now := t0
77 s, _ := newService(t, &now, abono.Config{})
78 ms, err := s.Members(context.Background())
79 if err != nil || len(ms) != 0 {
80 t.Errorf("Members = %v, %v; want none", ms, err)
81 }
82}
83
84// TestModeAccessors are what the owner's Stripe page reads (ruling R8):
85// test or live from the key's prefix, the sandbox, the origin the
86// webhook address is built on, and the clock holdings are judged by.
87func TestModeAccessors(t *testing.T) {
88 now := t0
89 for _, c := range []struct {
90 name string
91 cfg abono.Config
92 on, test, sandbox bool
93 }{
94 {"off", abono.Config{Origin: "https://site.example"}, false, false, false},
95 {"restricted test key", abono.Config{Origin: "https://site.example", Key: "rk_test_x", WebhookSecrets: []string{"whsec_x"}}, true, true, false},
96 {"secret test key", abono.Config{Origin: "https://site.example", Key: "sk_test_x", WebhookSecrets: []string{"whsec_x"}}, true, true, false},
97 {"live key", abono.Config{Origin: "https://site.example", Key: "rk_live_x", WebhookSecrets: []string{"whsec_x"}}, true, false, false},
98 {"sandbox", abono.Config{Origin: "http://localhost:8080", Sandbox: true}, true, false, true},
99 } {
100 t.Run(c.name, func(t *testing.T) {
101 s, _ := newService(t, &now, c.cfg)
102 if s.On() != c.on || s.TestMode() != c.test || s.Sandbox() != c.sandbox {
103 t.Errorf("On, TestMode, Sandbox = %v, %v, %v; want %v, %v, %v",
104 s.On(), s.TestMode(), s.Sandbox(), c.on, c.test, c.sandbox)
105 }
106 if s.Origin() != c.cfg.Origin {
107 t.Errorf("Origin = %q, want %q", s.Origin(), c.cfg.Origin)
108 }
109 if !s.Now().Equal(t0) {
110 t.Errorf("Now = %v, want the service's clock, %v", s.Now(), t0)
111 }
112 })
113 }
114}
115