Add test for webhook (#29755)

Follow #29690
This commit is contained in:
wxiaoguang 2024-03-14 09:10:51 +08:00 committed by GitHub
parent 83ba882bab
commit 43de021ac1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 38 additions and 49 deletions

View File

@ -212,3 +212,12 @@ func ToFloat64(number any) (float64, error) {
func ToPointer[T any](val T) *T { func ToPointer[T any](val T) *T {
return &val 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
}

View File

@ -18,6 +18,7 @@ import (
webhook_model "code.gitea.io/gitea/models/webhook" webhook_model "code.gitea.io/gitea/models/webhook"
"code.gitea.io/gitea/modules/hostmatcher" "code.gitea.io/gitea/modules/hostmatcher"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
webhook_module "code.gitea.io/gitea/modules/webhook" webhook_module "code.gitea.io/gitea/modules/webhook"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -226,49 +227,29 @@ func TestWebhookDeliverSpecificTypes(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase()) assert.NoError(t, unittest.PrepareTestDatabase())
type hookCase struct { type hookCase struct {
gotBody chan []byte gotBody chan []byte
httpMethod string // default to POST
} }
cases := map[string]hookCase{ cases := map[string]*hookCase{
webhook_module.SLACK: { webhook_module.SLACK: {},
gotBody: make(chan []byte, 1), webhook_module.DISCORD: {},
}, webhook_module.DINGTALK: {},
webhook_module.DISCORD: { webhook_module.TELEGRAM: {},
gotBody: make(chan []byte, 1), webhook_module.MSTEAMS: {},
}, webhook_module.FEISHU: {},
webhook_module.DINGTALK: { webhook_module.MATRIX: {httpMethod: "PUT"},
gotBody: make(chan []byte, 1), webhook_module.WECHATWORK: {},
}, webhook_module.PACKAGIST: {},
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),
},
} }
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 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) assert.Equal(t, "application/json", r.Header.Get("Content-Type"), r.URL.Path)
assert.Equal(t, util.IfZero(cases[typ].httpMethod, "POST"), r.Method, "webhook test request %q", r.URL.Path)
typ := strings.Split(r.URL.Path, "/")[1] // take first segment (after skipping leading slash) body, _ := io.ReadAll(r.Body) // read request and send it back to the test by testcase's chan
hc := cases[typ] cases[typ].gotBody <- body
require.NotNil(t, hc.gotBody, r.URL.Path) w.WriteHeader(http.StatusNoContent)
body, err := io.ReadAll(r.Body)
assert.NoError(t, err)
w.WriteHeader(200)
hc.gotBody <- body
})) }))
t.Cleanup(s.Close) t.Cleanup(s.Close)
@ -276,19 +257,17 @@ func TestWebhookDeliverSpecificTypes(t *testing.T) {
data, err := p.JSONPayload() data, err := p.JSONPayload()
assert.NoError(t, err) assert.NoError(t, err)
for typ, hc := range cases { for typ := range cases {
typ := typ cases[typ].gotBody = make(chan []byte, 1)
hc := hc typ := typ // TODO: remove this workaround when Go >= 1.22
t.Run(typ, func(t *testing.T) { t.Run(typ, func(t *testing.T) {
t.Parallel() t.Parallel()
hook := &webhook_model.Webhook{ hook := &webhook_model.Webhook{
RepoID: 3, RepoID: 3,
IsActive: true, IsActive: true,
Type: typ, Type: typ,
URL: s.URL + "/" + typ, URL: s.URL + "/" + typ,
HTTPMethod: "POST", Meta: "{}",
ContentType: 0, // set to 0 so that falling back to default request fails with "invalid content type"
Meta: "{}",
} }
assert.NoError(t, webhook_model.CreateWebhook(db.DefaultContext, hook)) assert.NoError(t, webhook_model.CreateWebhook(db.DefaultContext, hook))
@ -304,10 +283,11 @@ func TestWebhookDeliverSpecificTypes(t *testing.T) {
assert.NotNil(t, hookTask) assert.NotNil(t, hookTask)
assert.NoError(t, Deliver(context.Background(), hookTask)) assert.NoError(t, Deliver(context.Background(), hookTask))
select { 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.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): case <-time.After(5 * time.Second):
t.Fatal("waited to long for request to happen") t.Fatal("waited to long for request to happen")
} }