package handlers_test import ( "html" "net/http" "net/url" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "sneak.berlin/go/webhooker/internal/database" ) // TestHandleTargetCreate_EveryType adds a target of each type. Each // submission carries a url: only the http and slack types store one. func TestHandleTargetCreate_EveryType(t *testing.T) { t.Parallel() env := setupSourceTest(t) // fields is the rest of each submission, as a query string. cases := []struct { targetType database.TargetType fields string wantConfig string wantRetries int }{ { database.TargetTypeHTTP, "timeout=12&max_retries=3", `{"url":"` + editOriginalURL + `","timeout":12}`, 3, }, { database.TargetTypeSlack, "max_retries=4", `{"webhookUrl":"` + editOriginalURL + `"}`, 4, }, { database.TargetTypeDatabase, "expiry=720h", `{"expiry":"720h"}`, 0, }, {database.TargetTypeLog, "", "", 0}, } for _, tc := range cases { t.Run(string(tc.targetType), func(t *testing.T) { t.Parallel() webhook := seedWebhookWithRetention(t, env.db, 30) form, err := url.ParseQuery(tc.fields) require.NoError(t, err) form.Set("name", "every-type") form.Set("type", string(tc.targetType)) form.Set("url", editOriginalURL) w := serveTarget( env, http.MethodPost, "/hook/"+webhook.ID+"/targets", form, ) require.Equal(t, http.StatusSeeOther, w.Code, w.Body.String()) targets := targetsForWebhook(t, env.db, webhook.ID) require.Len(t, targets, 1) assert.Equal(t, tc.targetType, targets[0].Type) assert.Equal(t, tc.wantRetries, targets[0].MaxRetries) if tc.wantConfig == "" { assert.Empty(t, targets[0].Config) } else { assert.JSONEq(t, tc.wantConfig, targets[0].Config) } }) } } // TestHandleTargetCreate_RefusedFormComesBack refuses a target of each // type and checks that the webhook page comes back with the add target // form open on that type, the values entered, and the reason. func TestHandleTargetCreate_RefusedFormComesBack(t *testing.T) { t.Parallel() env := setupSourceTest(t) // fields is what the operator typed, as a query string. cases := []struct { targetType database.TargetType fields string reason string }{ { database.TargetTypeHTTP, "name=private&url=" + editBlockedURL + "&timeout=12&max_retries=3", "Invalid target URL", }, { database.TargetTypeSlack, "name=no-url&max_retries=4", "Webhook URL is required for Slack targets", }, { database.TargetTypeDatabase, "name=archive&expiry=7d", "Invalid archive expiry", }, {database.TargetTypeLog, "name=", "Name is required"}, } for _, tc := range cases { t.Run(string(tc.targetType), func(t *testing.T) { t.Parallel() webhook := seedWebhookWithRetention(t, env.db, 30) typed, err := url.ParseQuery(tc.fields) require.NoError(t, err) form := url.Values{} form.Set("type", string(tc.targetType)) for field := range typed { form.Set(field, typed.Get(field)) } w := serveTarget( env, http.MethodPost, "/hook/"+webhook.ID+"/targets", form, ) assert.Equal(t, http.StatusBadRequest, w.Code) page := w.Body.String() assert.Contains( t, page, `data-type="`+string(tc.targetType)+`"`, ) assert.Contains(t, page, html.EscapeString(tc.reason)) for field := range typed { assert.Contains( t, page, `name="`+field+`" value="`+ html.EscapeString(typed.Get(field))+`"`, ) } assert.Empty(t, targetsForWebhook(t, env.db, webhook.ID)) }) } }