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)
cases := []struct {
targetType database.TargetType
fields map[string]string
wantConfig string
wantRetries int
}{
{
database.TargetTypeHTTP,
map[string]string{"timeout": "12", "max_retries": "3"},
`{"url":"` + editOriginalURL + `","timeout":12}`, 3,
},
{
database.TargetTypeSlack,
map[string]string{"max_retries": "4"},
`{"webhookUrl":"` + editOriginalURL + `"}`, 4,
},
{
database.TargetTypeDatabase,
map[string]string{"expiry": "720h"},
`{"expiry":"720h"}`, 0,
},
{database.TargetTypeLog, nil, "", 0},
}
for _, tc := range cases {
t.Run(string(tc.targetType), func(t *testing.T) {
t.Parallel()
webhook := seedWebhookWithRetention(t, env.db, 30)
form := url.Values{}
form.Set("name", "every-type")
form.Set("type", string(tc.targetType))
form.Set("url", editOriginalURL)
for field, value := range tc.fields {
form.Set(field, value)
}
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)
cases := []struct {
targetType database.TargetType
fields map[string]string
reason string
}{
{
database.TargetTypeHTTP,
map[string]string{
"name": "private", "url": editBlockedURL,
"timeout": "12", "max_retries": "3",
},
"Invalid target URL",
},
{
database.TargetTypeSlack,
map[string]string{"name": "no-url", "max_retries": "4"},
"Webhook URL is required for Slack targets",
},
{
database.TargetTypeDatabase,
map[string]string{"name": "archive", "expiry": "7d"},
"Invalid archive expiry",
},
{
database.TargetTypeLog,
map[string]string{"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)
form := url.Values{}
form.Set("type", string(tc.targetType))
for field, value := range tc.fields {
form.Set(field, value)
}
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, value := range tc.fields {
assert.Contains(
t, page,
`name="`+field+`" value="`+html.EscapeString(value)+`"`,
)
}
assert.Empty(t, targetsForWebhook(t, env.db, webhook.ID))
})
}
}