internal/store/reactions_test.go
112 lines · 3187 bytes
2 symbols in this file
1package store
2
3import (
4 "errors"
5 "testing"
6)
7
8func TestReactions(t *testing.T) {
9 s, repoID, uid := mrFixture(t)
10 bob, err := s.CreateUser("bob", false)
11 if err != nil {
12 t.Fatal(err)
13 }
14 num, err := s.CreateIssue(repoID, uid, "t", "b", "md")
15 if err != nil {
16 t.Fatal(err)
17 }
18 iss, err := s.IssueByNumber(repoID, num)
19 if err != nil {
20 t.Fatal(err)
21 }
22 if err := s.AddIssueComment(iss.ID, uid, "c", "md"); err != nil {
23 t.Fatal(err)
24 }
25 if err := s.AddIssueSystemComment(iss.ID, uid, "sys"); err != nil {
26 t.Fatal(err)
27 }
28 cs, _ := s.ListIssueComments(iss.ID)
29 if len(cs) != 2 || cs[0].ID == 0 {
30 t.Fatalf("comments: %+v", cs)
31 }
32 cid, sysID := cs[0].ID, cs[1].ID
33
34 if err := s.ReactionTarget("issue", iss.ID, cid); err != nil {
35 t.Fatal(err)
36 }
37 if err := s.ReactionTarget("issue", iss.ID, sysID); !errors.Is(err, ErrNotFound) {
38 t.Fatalf("system comment: %v", err)
39 }
40 if err := s.ReactionTarget("issue", iss.ID+1, cid); !errors.Is(err, ErrNotFound) {
41 t.Fatalf("comment of another thread: %v", err)
42 }
43
44 for i := 0; i < 2; i++ { // idempotent
45 if err := s.SetReaction("issue", iss.ID, 0, uid, "+1", true); err != nil {
46 t.Fatal(err)
47 }
48 if err := s.SetReaction("issue", iss.ID, cid, uid, "+1", true); err != nil {
49 t.Fatal(err)
50 }
51 }
52 s.SetReaction("issue", iss.ID, 0, bob, "+1", true)
53 s.SetReaction("issue", iss.ID, 0, bob, "eyes", true)
54 got, err := s.ReactionCounts("issue", iss.ID, uid)
55 if err != nil {
56 t.Fatal(err)
57 }
58 if b := got[0]; len(b) != 2 || b[0] != (ReactionCount{"+1", 2, true}) || b[1] != (ReactionCount{"eyes", 1, false}) {
59 t.Errorf("body: %+v", b)
60 }
61 if c := got[cid]; len(c) != 1 || c[0] != (ReactionCount{"+1", 1, true}) {
62 t.Errorf("comment: %+v", c)
63 }
64 anon, _ := s.ReactionCounts("issue", iss.ID, 0)
65 if anon[0][0].Me {
66 t.Errorf("anonymous viewer marked: %+v", anon[0])
67 }
68
69 // Removing is scoped to the item and idempotent.
70 for i := 0; i < 2; i++ {
71 if err := s.SetReaction("issue", iss.ID, 0, uid, "+1", false); err != nil {
72 t.Fatal(err)
73 }
74 }
75 got, _ = s.ReactionCounts("issue", iss.ID, uid)
76 if got[0][0] != (ReactionCount{"+1", 1, false}) || len(got[cid]) != 1 {
77 t.Errorf("after remove: %+v", got)
78 }
79
80 // Deleting the issue takes its reactions with it.
81 if _, err := s.DB.Exec("DELETE FROM issues WHERE id = ?", iss.ID); err != nil {
82 t.Fatal(err)
83 }
84 var n int
85 s.DB.QueryRow("SELECT COUNT(*) FROM issue_reactions").Scan(&n)
86 if n != 0 {
87 t.Errorf("%d reactions left after issue delete", n)
88 }
89
90 mr, _ := s.MRByNumber(repoID, 1)
91 if err := s.SetReaction("mr", mr.ID, 0, uid, "rocket", true); err != nil {
92 t.Fatal(err)
93 }
94 m, _ := s.ReactionCounts("mr", mr.ID, uid)
95 if len(m[0]) != 1 || m[0][0].Reaction != "rocket" {
96 t.Errorf("mr: %+v", m)
97 }
98 if err := s.SetReaction("issue", 1, 0, uid, "bogus", true); err == nil {
99 t.Error("unknown reaction stored")
100 }
101}
102
103func TestParseReaction(t *testing.T) {
104 for in, want := range map[string]string{"+1": "+1", "👍": "+1", "❤️": "heart", "❤": "heart", "eyes": "eyes"} {
105 if got, ok := ParseReaction(in); !ok || got != want {
106 t.Errorf("%q: %q %v", in, got, ok)
107 }
108 }
109 if _, ok := ParseReaction("thumbsup"); ok {
110 t.Error("accepted an unknown name")
111 }
112}