Skip to content

Commit

Permalink
Add test for webhook (#29755)
Browse files Browse the repository at this point in the history
Follow #29690
  • Loading branch information
wxiaoguang authored Mar 14, 2024
1 parent 83ba882 commit 43de021
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 49 deletions.
9 changes: 9 additions & 0 deletions modules/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,12 @@ func ToFloat64(number any) (float64, error) {
func ToPointer[T any](val T) *T {
return &val
}

// IfZero returns "def" if "v" is a zero value, otherwise "v"
func IfZero[T comparable](v, def T) T {
var zero T
if v == zero {
return def
}
return v
}
78 changes: 29 additions & 49 deletions services/webhook/deliver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
webhook_model "code.gitea.io/gitea/models/webhook"
"code.gitea.io/gitea/modules/hostmatcher"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
webhook_module "code.gitea.io/gitea/modules/webhook"

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

type hookCase struct {
gotBody chan []byte
gotBody chan []byte
httpMethod string // default to POST
}

cases := map[string]hookCase{
webhook_module.SLACK: {
gotBody: make(chan []byte, 1),
},
webhook_module.DISCORD: {
gotBody: make(chan []byte, 1),
},
webhook_module.DINGTALK: {
gotBody: make(chan []byte, 1),
},
webhook_module.TELEGRAM: {
gotBody: make(chan []byte, 1),
},
webhook_module.MSTEAMS: {
gotBody: make(chan []byte, 1),
},
webhook_module.FEISHU: {
gotBody: make(chan []byte, 1),
},
webhook_module.MATRIX: {
gotBody: make(chan []byte, 1),
},
webhook_module.WECHATWORK: {
gotBody: make(chan []byte, 1),
},
webhook_module.PACKAGIST: {
gotBody: make(chan []byte, 1),
},
cases := map[string]*hookCase{
webhook_module.SLACK: {},
webhook_module.DISCORD: {},
webhook_module.DINGTALK: {},
webhook_module.TELEGRAM: {},
webhook_module.MSTEAMS: {},
webhook_module.FEISHU: {},
webhook_module.MATRIX: {httpMethod: "PUT"},
webhook_module.WECHATWORK: {},
webhook_module.PACKAGIST: {},
}

s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
typ := strings.Split(r.URL.Path, "/")[1] // URL: "/{webhook_type}/other-path"
assert.Equal(t, "application/json", r.Header.Get("Content-Type"), r.URL.Path)

typ := strings.Split(r.URL.Path, "/")[1] // take first segment (after skipping leading slash)
hc := cases[typ]
require.NotNil(t, hc.gotBody, r.URL.Path)
body, err := io.ReadAll(r.Body)
assert.NoError(t, err)
w.WriteHeader(200)
hc.gotBody <- body
assert.Equal(t, util.IfZero(cases[typ].httpMethod, "POST"), r.Method, "webhook test request %q", r.URL.Path)
body, _ := io.ReadAll(r.Body) // read request and send it back to the test by testcase's chan
cases[typ].gotBody <- body
w.WriteHeader(http.StatusNoContent)
}))
t.Cleanup(s.Close)

p := pushTestPayload()
data, err := p.JSONPayload()
assert.NoError(t, err)

for typ, hc := range cases {
typ := typ
hc := hc
for typ := range cases {
cases[typ].gotBody = make(chan []byte, 1)
typ := typ // TODO: remove this workaround when Go >= 1.22
t.Run(typ, func(t *testing.T) {
t.Parallel()
hook := &webhook_model.Webhook{
RepoID: 3,
IsActive: true,
Type: typ,
URL: s.URL + "/" + typ,
HTTPMethod: "POST",
ContentType: 0, // set to 0 so that falling back to default request fails with "invalid content type"
Meta: "{}",
RepoID: 3,
IsActive: true,
Type: typ,
URL: s.URL + "/" + typ,
Meta: "{}",
}
assert.NoError(t, webhook_model.CreateWebhook(db.DefaultContext, hook))

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

assert.NoError(t, Deliver(context.Background(), hookTask))

select {
case gotBody := <-hc.gotBody:
case gotBody := <-cases[typ].gotBody:
assert.NotEqual(t, string(data), string(gotBody), "request body must be different from the event payload")
assert.Equal(t, hookTask.RequestInfo.Body, string(gotBody), "request body was not saved")
assert.Equal(t, hookTask.RequestInfo.Body, string(gotBody), "delivered webhook payload doesn't match saved request")
case <-time.After(5 * time.Second):
t.Fatal("waited to long for request to happen")
}
Expand Down

0 comments on commit 43de021

Please sign in to comment.