A target's settings move from the per-type JSON string in targets.config to columns: url, headers, timeout_seconds, forward_query, archive_expiry and archive_rotation. A column a type does not use stays empty. headers holds the header map as JSON text through GORM's JSON serializer, and archive_expiry holds a time.Duration, 0 meaning never. The forms check each setting once, with the same refusals and messages, and the edit form is filled from the columns, so the per-type config structs, their parsers and the "could not be read" branches are gone. A delivery task carries the six settings in place of the JSON string; tests check that each copy into a task, and back out of one, keeps all six. Model: opus-5-5
This commit was merged in pull request #554.
This commit is contained in:
@@ -6,73 +6,114 @@ import (
|
||||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"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.
|
||||
// TestHandleTargetCreate_EveryType adds a target of each type and
|
||||
// checks the settings it stores. Each submission carries a url and an
|
||||
// expiry: only the http and slack types store the url, only the
|
||||
// database type the expiry, and every setting a type does not use
|
||||
// stays empty.
|
||||
func TestHandleTargetCreate_EveryType(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
env := setupSourceTest(t)
|
||||
|
||||
// fields is the rest of each submission, as a query string.
|
||||
// fields is the rest of each submission, as a query string, and
|
||||
// want holds the settings stored.
|
||||
cases := []struct {
|
||||
targetType database.TargetType
|
||||
fields string
|
||||
wantConfig string
|
||||
want database.Target
|
||||
wantAttempts int
|
||||
}{
|
||||
{
|
||||
database.TargetTypeHTTP, "timeout=12&max_attempts=3",
|
||||
`{"url":"` + editOriginalURL + `","timeout":12}`, 3,
|
||||
database.TargetTypeHTTP,
|
||||
"timeout=12&max_attempts=3&forward_query=on",
|
||||
database.Target{
|
||||
URL: editOriginalURL,
|
||||
Headers: map[string]string{},
|
||||
TimeoutSeconds: 12,
|
||||
ForwardQuery: true,
|
||||
}, 3,
|
||||
},
|
||||
{
|
||||
database.TargetTypeSlack, "max_attempts=4",
|
||||
`{"webhookUrl":"` + editOriginalURL + `"}`, 4,
|
||||
database.Target{URL: editOriginalURL}, 4,
|
||||
},
|
||||
{
|
||||
database.TargetTypeDatabase, "expiry=720h",
|
||||
`{"expiry":"720h"}`, 1,
|
||||
database.TargetTypeDatabase, "rotation=daily",
|
||||
database.Target{
|
||||
ArchiveExpiry: 720 * time.Hour,
|
||||
ArchiveRotation: rotationDaily,
|
||||
}, 1,
|
||||
},
|
||||
{database.TargetTypeLog, "", "", 1},
|
||||
{database.TargetTypeLog, "", database.Target{}, 1},
|
||||
}
|
||||
|
||||
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,
|
||||
_, got := addTargetThroughForm(
|
||||
t, env, tc.targetType,
|
||||
"url="+editOriginalURL+"&expiry=720h&"+tc.fields,
|
||||
)
|
||||
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.wantAttempts, targets[0].MaxAttempts)
|
||||
|
||||
if tc.wantConfig == "" {
|
||||
assert.Empty(t, targets[0].Config)
|
||||
} else {
|
||||
assert.JSONEq(t, tc.wantConfig, targets[0].Config)
|
||||
}
|
||||
assert.Equal(t, tc.targetType, got.Type)
|
||||
assert.Equal(t, tc.wantAttempts, got.MaxAttempts)
|
||||
assert.Equal(t, tc.want, targetSettingsOf(got))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// addTargetThroughForm adds a target of targetType named every-type to
|
||||
// a new webhook through the add target form, with the rest of the form
|
||||
// given as a query string, and returns the webhook and the target the
|
||||
// form stored.
|
||||
func addTargetThroughForm(
|
||||
t *testing.T,
|
||||
env *sourceTestEnv,
|
||||
targetType database.TargetType,
|
||||
fields string,
|
||||
) (database.Webhook, database.Target) {
|
||||
t.Helper()
|
||||
|
||||
webhook := seedWebhookWithRetention(t, env.db, 30)
|
||||
|
||||
form, err := url.ParseQuery(fields)
|
||||
require.NoError(t, err)
|
||||
form.Set("name", "every-type")
|
||||
form.Set("type", string(targetType))
|
||||
|
||||
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)
|
||||
|
||||
return webhook, targets[0]
|
||||
}
|
||||
|
||||
// targetSettingsOf returns a target's settings, URL to
|
||||
// ArchiveRotation, and nothing else, for comparing with the settings a
|
||||
// test expects.
|
||||
func targetSettingsOf(target database.Target) database.Target {
|
||||
return database.Target{
|
||||
URL: target.URL,
|
||||
Headers: target.Headers,
|
||||
TimeoutSeconds: target.TimeoutSeconds,
|
||||
ForwardQuery: target.ForwardQuery,
|
||||
ArchiveExpiry: target.ArchiveExpiry,
|
||||
ArchiveRotation: target.ArchiveRotation,
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
||||
Reference in New Issue
Block a user