check / check (push) Successful in 3m25s
Adding or editing a database target now offers the archive expiry choices of the new webhook page (never, 1h, 12h, 24h, 30d, 90d, 365d) in place of a text field. The list is defined once, in internal/handlers/archive_expiry.go, and all three forms render it. The edit form starts on the stored expiry; one that is not among the choices is listed first as its own entry, so saving unchanged keeps it. The target list shows the expiry in plain units, such as "30 days" or "12 hours", or "never". Model: opus-5-5
167 lines
4.4 KiB
Go
167 lines
4.4 KiB
Go
package handlers_test
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/url"
|
|
"regexp"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"sneak.berlin/go/webhooker/internal/database"
|
|
)
|
|
|
|
// expiryNever is the archive expiry that keeps archived events
|
|
// forever.
|
|
const expiryNever = "never"
|
|
|
|
// matched returns what the one group of pattern matched in page, at
|
|
// each match.
|
|
func matched(pattern, page string) []string {
|
|
matches := regexp.MustCompile(pattern).FindAllStringSubmatch(page, -1)
|
|
groups := make([]string, 0, len(matches))
|
|
|
|
for _, m := range matches {
|
|
groups = append(groups, m[1])
|
|
}
|
|
|
|
return groups
|
|
}
|
|
|
|
// expiryShown returns the archive expiries the webhook page's target
|
|
// list shows.
|
|
func expiryShown(
|
|
t *testing.T, env *sourceTestEnv, webhookID string,
|
|
) []string {
|
|
t.Helper()
|
|
|
|
w := httptest.NewRecorder()
|
|
env.handlers.HandleSourceDetail().ServeHTTP(w, getRequest(
|
|
t, "/hook/"+webhookID, env.cookies,
|
|
map[string]string{sourceIDParam: webhookID},
|
|
))
|
|
require.Equal(t, http.StatusOK, w.Code)
|
|
|
|
return matched(
|
|
`Archive Expiry:</span>\s*<span>([^<]*)</span>`, w.Body.String(),
|
|
)
|
|
}
|
|
|
|
// expirySelected returns the target edit page and the expiries its
|
|
// select starts on.
|
|
func expirySelected(
|
|
t *testing.T, env *sourceTestEnv, webhookID, targetID string,
|
|
) (string, []string) {
|
|
t.Helper()
|
|
|
|
w := serveTarget(
|
|
env, http.MethodGet,
|
|
"/hook/"+webhookID+"/targets/"+targetID+"/edit", nil,
|
|
)
|
|
require.Equal(t, http.StatusOK, w.Code)
|
|
|
|
page := w.Body.String()
|
|
|
|
return page, matched(`<option value="([^"]*)" selected>`, page)
|
|
}
|
|
|
|
// TestArchiveExpiryChoices adds a database target with each archive
|
|
// expiry the forms offer, and checks that it is stored as chosen,
|
|
// shown in plain units in the target list, and that the target edit
|
|
// form starts on it.
|
|
func TestArchiveExpiryChoices(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
env := setupSourceTest(t)
|
|
|
|
choices := []struct{ value, shown string }{
|
|
{expiryNever, expiryNever},
|
|
{"1h", "1 hour"},
|
|
{"12h", "12 hours"},
|
|
{"24h", "1 day"},
|
|
{"720h", "30 days"},
|
|
{"2160h", "90 days"},
|
|
{"8760h", "365 days"},
|
|
}
|
|
|
|
for _, choice := range choices {
|
|
t.Run(choice.value, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
webhook := seedWebhookWithRetention(t, env.db, 30)
|
|
|
|
form := url.Values{}
|
|
form.Set("name", "archive")
|
|
form.Set("type", string(database.TargetTypeDatabase))
|
|
form.Set("expiry", choice.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.JSONEq(
|
|
t, `{"expiry":"`+choice.value+`"}`, targets[0].Config,
|
|
)
|
|
|
|
assert.Equal(
|
|
t, []string{choice.shown},
|
|
expiryShown(t, env, webhook.ID),
|
|
)
|
|
|
|
_, selected := expirySelected(t, env, webhook.ID, targets[0].ID)
|
|
assert.Equal(t, []string{choice.value}, selected)
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestArchiveExpiryEditStartsOnStoredValue checks the edit form of a
|
|
// database target whose stored expiry is empty, which selects never,
|
|
// and of one whose expiry is not one of the choices, which is listed
|
|
// first as its own selected entry and saved unchanged.
|
|
func TestArchiveExpiryEditStartsOnStoredValue(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
env := setupSourceTest(t)
|
|
|
|
webhook := seedWebhookWithRetention(t, env.db, 30)
|
|
empty := seedConfiguredTarget(
|
|
t, env.db, webhook.ID, database.TargetTypeDatabase, "",
|
|
)
|
|
|
|
_, selected := expirySelected(t, env, webhook.ID, empty.ID)
|
|
assert.Equal(t, []string{expiryNever}, selected)
|
|
|
|
webhook = seedWebhookWithRetention(t, env.db, 30)
|
|
unlisted := seedConfiguredTarget(
|
|
t, env.db, webhook.ID, database.TargetTypeDatabase,
|
|
`{"expiry":"36h"}`,
|
|
)
|
|
|
|
assert.Equal(t, []string{"36 hours"}, expiryShown(t, env, webhook.ID))
|
|
|
|
page, selected := expirySelected(t, env, webhook.ID, unlisted.ID)
|
|
assert.Equal(t, []string{"36h"}, selected)
|
|
assert.Regexp(
|
|
t,
|
|
`<select id="expiry" name="expiry" class="input">\s*`+
|
|
`<option value="36h" selected>36h</option>\s*`+
|
|
`<option value="never">never</option>`,
|
|
page,
|
|
)
|
|
assert.Contains(t, page, `<option value="8760h">365d</option>`)
|
|
|
|
form := url.Values{}
|
|
form.Set("name", unlisted.Name)
|
|
form.Set("expiry", "36h")
|
|
|
|
w := submitTargetEdit(env, webhook.ID, unlisted.ID, form)
|
|
require.Equal(t, http.StatusSeeOther, w.Code, w.Body.String())
|
|
assert.JSONEq(
|
|
t, `{"expiry":"36h"}`, storedTarget(t, env, unlisted.ID).Config,
|
|
)
|
|
}
|