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 "errors"
6 "testing"
7 "time"
8
9 "gorm.io/gorm"
10
11 "amadan.net/rastrillo/abono"
12)
13
14func TestCompAndEndCompCallOnChangeInTheSameTransaction(t *testing.T) {
15 now := t0
16 var calls []string
17 var seen int64 = -1
18 var failWith error
19 s, db := newService(t, &now, abono.Config{
20 OnChange: func(ctx context.Context, tx *gorm.DB, subject string) error {
21 calls = append(calls, subject)
22 // Same transaction: the comp written a moment ago is visible
23 // here, though it is not committed yet.
24 if err := tx.Table("abono_comps").Where("subject = ? AND status = 'active'", subject).Count(&seen).Error; err != nil {
25 return err
26 }
27 return failWith
28 },
29 })
30 ctx := context.Background()
31
32 id, err := s.Comp(ctx, "s1", "annual", nil, "for the editor")
33 if err != nil {
34 t.Fatalf("Comp: %v", err)
35 }
36 if id <= 0 {
37 t.Errorf("Comp id = %d", id)
38 }
39 if len(calls) != 1 || calls[0] != "s1" || seen != 1 {
40 t.Errorf("OnChange calls = %v, active comps seen inside = %d; want [s1] and 1", calls, seen)
41 }
42 if got := db.dump("SELECT subject, plan, status, ends_at, note FROM abono_comps"); got != "s1|annual|active||for the editor\n" {
43 t.Errorf("comps = %q", got)
44 }
45
46 // A hook error rolls Comp back.
47 failWith = errors.New("hook failed")
48 if _, err := s.Comp(ctx, "s2", "annual", nil, ""); !errors.Is(err, failWith) {
49 t.Errorf("Comp with a failing hook: %v, want the hook's error", err)
50 }
51 if got := db.dump("SELECT subject FROM abono_comps WHERE subject = 's2'"); got != "" {
52 t.Errorf("a comp survived its hook's failure: %q", got)
53 }
54
55 // And rolls EndComp back.
56 if err := s.EndComp(ctx, id); !errors.Is(err, failWith) {
57 t.Errorf("EndComp with a failing hook: %v, want the hook's error", err)
58 }
59 if got := db.dump("SELECT status FROM abono_comps WHERE id = ?", id); got != "active\n" {
60 t.Errorf("status after a rolled-back EndComp = %q", got)
61 }
62
63 failWith = nil
64 calls = nil
65 now = t0.Add(time.Hour)
66 if err := s.EndComp(ctx, id); err != nil {
67 t.Fatalf("EndComp: %v", err)
68 }
69 if len(calls) != 1 || calls[0] != "s1" {
70 t.Errorf("OnChange calls after EndComp = %v", calls)
71 }
72 if got := db.dump("SELECT status FROM abono_comps WHERE id = ?", id); got != "canceled\n" {
73 t.Errorf("status = %q", got)
74 }
75 if has, err := s.HasPlan(ctx, "s1", "annual"); err != nil || has {
76 t.Errorf("HasPlan after EndComp = %v, %v", has, err)
77 }
78
79 // Ending it again changes nothing, so tells nobody.
80 calls = nil
81 if err := s.EndComp(ctx, id); err != nil {
82 t.Errorf("EndComp again: %v", err)
83 }
84 if len(calls) != 0 {
85 t.Errorf("EndComp on an ended comp called OnChange: %v", calls)
86 }
87 if err := s.EndComp(ctx, id+100); !errors.Is(err, abono.ErrNotFound) {
88 t.Errorf("EndComp of a missing comp: %v, want ErrNotFound", err)
89 }
90}
91
92func TestCompRefusesNoSubjectOrPlan(t *testing.T) {
93 now := t0
94 s, _ := newService(t, &now, abono.Config{})
95 if _, err := s.Comp(context.Background(), "", "annual", nil, ""); err == nil {
96 t.Error("Comp with no subject succeeded")
97 }
98 if _, err := s.Comp(context.Background(), "s1", "", nil, ""); err == nil {
99 t.Error("Comp with no plan succeeded")
100 }
101}
102