1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package disapproval
16
17 import (
18 "context"
19 "os"
20 "regexp"
21 "testing"
22 "time"
23
24 "github.com/rs/zerolog"
25 "github.com/stretchr/testify/assert"
26 "github.com/stretchr/testify/require"
27
28 "edge-infra.dev/pkg/f8n/devinfra/repo/owners/policybot/pull"
29 "edge-infra.dev/pkg/f8n/devinfra/repo/owners/policybot/pull/pulltest"
30
31 "edge-infra.dev/pkg/f8n/devinfra/repo/owners/policybot/policy/common"
32 "edge-infra.dev/pkg/f8n/devinfra/repo/owners/policybot/policy/predicate"
33 )
34
35 func TestIsDisapproved(t *testing.T) {
36 logger := zerolog.New(os.Stdout)
37 ctx := logger.WithContext(context.Background())
38
39 prctx := &pulltest.Context{
40 TitleValue: "test: add disapproval predicate test",
41 CommentsValue: []*pull.Comment{
42 {
43 Author: "disapprover-1",
44 Body: "me no like :-1:",
45 CreatedAt: date(0),
46 },
47 {
48 Author: "disapprover-1",
49 Body: "nah, is fine :+1:",
50 CreatedAt: date(1),
51 },
52 {
53 Author: "disapprover-2",
54 Body: "me also no like :-1:",
55 CreatedAt: date(2),
56 },
57 {
58 Author: "disapprover-3",
59 Body: "and me :-1:",
60 CreatedAt: date(3),
61 },
62 {
63 Author: "revoker-1",
64 Body: "you all wrong :+1:",
65 CreatedAt: date(4),
66 },
67 },
68 ReviewsValue: []*pull.Review{
69 {
70 Author: "disapprover-4",
71 State: pull.ReviewChangesRequested,
72 CreatedAt: date(5),
73 },
74 {
75 Author: "revoker-2",
76 State: pull.ReviewApproved,
77 CreatedAt: date(6),
78 },
79 },
80 }
81
82 assertDisapproved := func(t *testing.T, p *Policy, expected string) {
83 res := p.Evaluate(ctx, prctx)
84
85 require.NoError(t, res.Error)
86
87 if assert.Equal(t, common.StatusDisapproved, res.Status, "pull request was not disapproved") {
88 assert.Equal(t, expected, res.StatusDescription)
89 }
90 }
91
92 assertSkipped := func(t *testing.T, p *Policy, expected string) {
93 res := p.Evaluate(ctx, prctx)
94
95 require.NoError(t, res.Error)
96
97 if assert.Equal(t, common.StatusSkipped, res.Status, "pull request was incorrectly disapproved") {
98 assert.Equal(t, expected, res.StatusDescription)
99 }
100 }
101
102 t.Run("skippedWithNoRequires", func(t *testing.T) {
103 p := &Policy{}
104 assertSkipped(t, p, "No disapproval policy is specified or the policy is empty")
105 })
106
107 t.Run("singleUserDisapproves", func(t *testing.T) {
108 p := &Policy{}
109 p.Requires.Users = []string{"disapprover-2"}
110
111 assertDisapproved(t, p, "Disapproved by disapprover-2")
112 })
113
114 t.Run("singleUserDisapprovesAndRevokes", func(t *testing.T) {
115 p := &Policy{}
116 p.Requires.Users = []string{"disapprover-1"}
117
118 assertSkipped(t, p, "Disapproval revoked by disapprover-1")
119 })
120
121 t.Run("multipleUsersDisapprove", func(t *testing.T) {
122 p := &Policy{}
123 p.Requires.Users = []string{"disapprover-2", "disapprover-3"}
124
125 assertDisapproved(t, p, "Disapproved by disapprover-3")
126 })
127
128 t.Run("otherUserRevokes", func(t *testing.T) {
129 p := &Policy{}
130 p.Requires.Users = []string{"disapprover-2", "disapprover-3", "revoker-1"}
131
132 assertSkipped(t, p, "Disapproval revoked by revoker-1")
133 })
134
135 t.Run("singleUserDisapprovesWithReview", func(t *testing.T) {
136 p := &Policy{}
137 p.Requires.Users = []string{"disapprover-4"}
138
139 assertDisapproved(t, p, "Disapproved by disapprover-4")
140 })
141
142 t.Run("otherUserRevokesWithReview", func(t *testing.T) {
143 p := &Policy{}
144 p.Requires.Users = []string{"disapprover-4", "revoker-2"}
145
146 assertSkipped(t, p, "Disapproval revoked by revoker-2")
147 })
148
149 t.Run("reviewsInteractWithComments", func(t *testing.T) {
150 p := &Policy{}
151 p.Requires.Users = []string{"disapprover-1", "revoker-1", "disapprover-4"}
152
153 assertDisapproved(t, p, "Disapproved by disapprover-4")
154 })
155
156 t.Run("predicateDisapproves", func(t *testing.T) {
157 p := &Policy{}
158 p.Predicates = predicate.Predicates{
159 Title: &predicate.Title{
160 NotMatches: []common.Regexp{
161 common.NewCompiledRegexp(regexp.MustCompile("^(fix|feat|docs)")),
162 },
163 },
164 }
165
166 assertDisapproved(t, p, "PR Title doesn't match a NotMatch pattern")
167 })
168
169 t.Run("predicateDoesNotDisapprove", func(t *testing.T) {
170 p := &Policy{}
171 p.Predicates = predicate.Predicates{
172 Title: &predicate.Title{
173 NotMatches: []common.Regexp{
174 common.NewCompiledRegexp(regexp.MustCompile("^(fix|feat|docs|test)")),
175 },
176 },
177 }
178
179 assertSkipped(t, p, "No disapproval policy is specified or the policy is empty")
180 })
181 }
182
183 func date(hour int) time.Time {
184 return time.Date(2018, 6, 29, hour, 0, 0, 0, time.UTC)
185 }
186
View as plain text