Skip to content

Commit 43de021

Browse files
authored
Add test for webhook (#29755)
Follow #29690
1 parent 83ba882 commit 43de021

File tree

2 files changed

+38
-49
lines changed

2 files changed

+38
-49
lines changed

modules/util/util.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,3 +212,12 @@ func ToFloat64(number any) (float64, error) {
212212
func ToPointer[T any](val T) *T {
213213
return &val
214214
}
215+
216+
// IfZero returns "def" if "v" is a zero value, otherwise "v"
217+
func IfZero[T comparable](v, def T) T {
218+
var zero T
219+
if v == zero {
220+
return def
221+
}
222+
return v
223+
}

services/webhook/deliver_test.go

Lines changed: 29 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
webhook_model "code.gitea.io/gitea/models/webhook"
1919
"code.gitea.io/gitea/modules/hostmatcher"
2020
"code.gitea.io/gitea/modules/setting"
21+
"code.gitea.io/gitea/modules/util"
2122
webhook_module "code.gitea.io/gitea/modules/webhook"
2223

2324
"github.com/stretchr/testify/assert"
@@ -226,69 +227,47 @@ func TestWebhookDeliverSpecificTypes(t *testing.T) {
226227
assert.NoError(t, unittest.PrepareTestDatabase())
227228

228229
type hookCase struct {
229-
gotBody chan []byte
230+
gotBody chan []byte
231+
httpMethod string // default to POST
230232
}
231233

232-
cases := map[string]hookCase{
233-
webhook_module.SLACK: {
234-
gotBody: make(chan []byte, 1),
235-
},
236-
webhook_module.DISCORD: {
237-
gotBody: make(chan []byte, 1),
238-
},
239-
webhook_module.DINGTALK: {
240-
gotBody: make(chan []byte, 1),
241-
},
242-
webhook_module.TELEGRAM: {
243-
gotBody: make(chan []byte, 1),
244-
},
245-
webhook_module.MSTEAMS: {
246-
gotBody: make(chan []byte, 1),
247-
},
248-
webhook_module.FEISHU: {
249-
gotBody: make(chan []byte, 1),
250-
},
251-
webhook_module.MATRIX: {
252-
gotBody: make(chan []byte, 1),
253-
},
254-
webhook_module.WECHATWORK: {
255-
gotBody: make(chan []byte, 1),
256-
},
257-
webhook_module.PACKAGIST: {
258-
gotBody: make(chan []byte, 1),
259-
},
234+
cases := map[string]*hookCase{
235+
webhook_module.SLACK: {},
236+
webhook_module.DISCORD: {},
237+
webhook_module.DINGTALK: {},
238+
webhook_module.TELEGRAM: {},
239+
webhook_module.MSTEAMS: {},
240+
webhook_module.FEISHU: {},
241+
webhook_module.MATRIX: {httpMethod: "PUT"},
242+
webhook_module.WECHATWORK: {},
243+
webhook_module.PACKAGIST: {},
260244
}
261245

262246
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
247+
typ := strings.Split(r.URL.Path, "/")[1] // URL: "/{webhook_type}/other-path"
263248
assert.Equal(t, "application/json", r.Header.Get("Content-Type"), r.URL.Path)
264-
265-
typ := strings.Split(r.URL.Path, "/")[1] // take first segment (after skipping leading slash)
266-
hc := cases[typ]
267-
require.NotNil(t, hc.gotBody, r.URL.Path)
268-
body, err := io.ReadAll(r.Body)
269-
assert.NoError(t, err)
270-
w.WriteHeader(200)
271-
hc.gotBody <- body
249+
assert.Equal(t, util.IfZero(cases[typ].httpMethod, "POST"), r.Method, "webhook test request %q", r.URL.Path)
250+
body, _ := io.ReadAll(r.Body) // read request and send it back to the test by testcase's chan
251+
cases[typ].gotBody <- body
252+
w.WriteHeader(http.StatusNoContent)
272253
}))
273254
t.Cleanup(s.Close)
274255

275256
p := pushTestPayload()
276257
data, err := p.JSONPayload()
277258
assert.NoError(t, err)
278259

279-
for typ, hc := range cases {
280-
typ := typ
281-
hc := hc
260+
for typ := range cases {
261+
cases[typ].gotBody = make(chan []byte, 1)
262+
typ := typ // TODO: remove this workaround when Go >= 1.22
282263
t.Run(typ, func(t *testing.T) {
283264
t.Parallel()
284265
hook := &webhook_model.Webhook{
285-
RepoID: 3,
286-
IsActive: true,
287-
Type: typ,
288-
URL: s.URL + "/" + typ,
289-
HTTPMethod: "POST",
290-
ContentType: 0, // set to 0 so that falling back to default request fails with "invalid content type"
291-
Meta: "{}",
266+
RepoID: 3,
267+
IsActive: true,
268+
Type: typ,
269+
URL: s.URL + "/" + typ,
270+
Meta: "{}",
292271
}
293272
assert.NoError(t, webhook_model.CreateWebhook(db.DefaultContext, hook))
294273

@@ -304,10 +283,11 @@ func TestWebhookDeliverSpecificTypes(t *testing.T) {
304283
assert.NotNil(t, hookTask)
305284

306285
assert.NoError(t, Deliver(context.Background(), hookTask))
286+
307287
select {
308-
case gotBody := <-hc.gotBody:
288+
case gotBody := <-cases[typ].gotBody:
309289
assert.NotEqual(t, string(data), string(gotBody), "request body must be different from the event payload")
310-
assert.Equal(t, hookTask.RequestInfo.Body, string(gotBody), "request body was not saved")
290+
assert.Equal(t, hookTask.RequestInfo.Body, string(gotBody), "delivered webhook payload doesn't match saved request")
311291
case <-time.After(5 * time.Second):
312292
t.Fatal("waited to long for request to happen")
313293
}

0 commit comments

Comments
 (0)