check / check (push) In progress
The UI gave one thing several names. The `database` type is now Archive in the type list, on its badge and on the edit page, and its settings read "Archive expiry" and "Archive rotation" everywhere. The retry field is "Delivery attempts", with help text, errors and the target list saying it counts every attempt; a stored 0 shows as one attempt. The target list uses one capitalisation. The navbar says "Sign out", the sign-in page "Sign in", and the resubmit notice "webhook" instead of "source". The README follows. Stored values, their meaning, routes and form field names are unchanged. Model: opus-5-5
175 lines
5.6 KiB
Go
175 lines
5.6 KiB
Go
package handlers_test
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"regexp"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"sneak.berlin/go/webhooker/internal/database"
|
|
"sneak.berlin/go/webhooker/internal/delivery"
|
|
"sneak.berlin/go/webhooker/internal/handlers"
|
|
"sneak.berlin/go/webhooker/internal/logger"
|
|
"sneak.berlin/go/webhooker/internal/session"
|
|
)
|
|
|
|
// TestHandleSourceDetail_ShowsArchiveFile proves a database target's
|
|
// row names its archive file and says "not created yet" before the
|
|
// first write, adds the file's size and last write once it has one row,
|
|
// and says "not created yet" again once the file has been moved away.
|
|
// A target of another type shows no archive file.
|
|
func TestHandleSourceDetail_ShowsArchiveFile(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var (
|
|
h *handlers.Handlers
|
|
sess *session.Session
|
|
db *database.Database
|
|
dbMgr *database.WebhookDBManager
|
|
)
|
|
|
|
app := newTestApp(t, &h, &sess, &db, &dbMgr)
|
|
app.RequireStart()
|
|
|
|
t.Cleanup(app.RequireStop)
|
|
|
|
wh := seedWebhook(t, db)
|
|
archive := seedTarget(t, db, wh.ID, database.TargetTypeDatabase)
|
|
seedTarget(t, db, wh.ID, database.TargetTypeLog)
|
|
|
|
path := delivery.ArchivePath(dbMgr, wh, archive)
|
|
|
|
body := renderSourceDetailPage(t, h, sess, wh.ID)
|
|
assert.Equal(t, 1, strings.Count(body, "Archive file:"))
|
|
assert.Contains(t, body, filepath.Base(path))
|
|
assert.Contains(t, body, "not created yet")
|
|
assert.NotContains(t, body, "Archive size:")
|
|
|
|
seedArchive(t, path, 1, 100)
|
|
|
|
file, err := os.Stat(path)
|
|
require.NoError(t, err)
|
|
|
|
body = renderSourceDetailPage(t, h, sess, wh.ID)
|
|
assert.Contains(t, body, filepath.Base(path))
|
|
assert.NotContains(t, body, "not created yet")
|
|
assert.Regexp(t,
|
|
`Archive size:</span>\s*<span>[1-9][0-9.]* [kM]?B</span>`, body,
|
|
)
|
|
assert.Contains(t, body,
|
|
`title="`+file.ModTime().UTC().Format(time.DateTime)+` UTC"`,
|
|
)
|
|
|
|
require.NoError(t, os.Rename(path, filepath.Join(t.TempDir(), "moved.db")))
|
|
|
|
body = renderSourceDetailPage(t, h, sess, wh.ID)
|
|
assert.Contains(t, body, filepath.Base(path))
|
|
assert.Contains(t, body, "not created yet")
|
|
assert.NotContains(t, body, "Archive size:")
|
|
}
|
|
|
|
// targetList returns the text of the targets section in a rendered
|
|
// webhook page, from its heading to the next heading, with the markup
|
|
// taken out and each run of space made one space. Each target's row
|
|
// then reads as its name, type, state and buttons, followed by the
|
|
// lines below them.
|
|
func targetList(t *testing.T, page string) string {
|
|
t.Helper()
|
|
|
|
_, list, found := strings.Cut(page, ">Targets</h2>")
|
|
require.True(t, found, "the page has no targets section")
|
|
|
|
list, _, _ = strings.Cut(list, "<h2")
|
|
list = regexp.MustCompile(`<[^>]*>`).ReplaceAllString(list, " ")
|
|
|
|
return strings.Join(strings.Fields(list), " ")
|
|
}
|
|
|
|
// TestHandleSourceDetail_ShowsTargetDeliveries checks each target row's
|
|
// delivered and failed deliveries, in total and in the last 24 hours,
|
|
// for the history seedStatsHistory builds, before and after the real
|
|
// retention reaper removes the oldest event. The http target has one
|
|
// delivered, one of them in the last 24 hours, and three failed, one of
|
|
// them in the last 24 hours and one of them the oldest event's, which
|
|
// retention removes without changing the total. The active log target
|
|
// has two failed, both in the last 24 hours, and its pending and
|
|
// retrying deliveries count in neither. The four inactive log targets
|
|
// have none.
|
|
func TestHandleSourceDetail_ShowsTargetDeliveries(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var (
|
|
h *handlers.Handlers
|
|
sess *session.Session
|
|
db *database.Database
|
|
dbMgr *database.WebhookDBManager
|
|
log *logger.Logger
|
|
)
|
|
|
|
app := newTestApp(t, &h, &sess, &db, &dbMgr, &log)
|
|
app.RequireStart()
|
|
|
|
t.Cleanup(app.RequireStop)
|
|
|
|
hist := seedStatsHistory(t, h, sess, db, dbMgr)
|
|
|
|
const (
|
|
httpRow = "Delivered: 1 in total, 1 in the last 24 hours " +
|
|
"Failed: 3 in total, 1 in the last 24 hours"
|
|
activeLogRow = "t-log log Active Edit Deactivate Delete " +
|
|
"Delivered: 0 in total, 0 in the last 24 hours " +
|
|
"Failed: 2 in total, 2 in the last 24 hours"
|
|
inactiveLogRow = "t-log log Inactive Edit Activate Delete " +
|
|
"Delivered: 0 in total, 0 in the last 24 hours " +
|
|
"Failed: 0 in total, 0 in the last 24 hours"
|
|
)
|
|
|
|
list := targetList(t, renderSourceDetailPage(t, h, sess, hist.webhook.ID))
|
|
assert.Equal(t, 1, strings.Count(list, httpRow))
|
|
assert.Equal(t, 1, strings.Count(list, activeLogRow))
|
|
assert.Equal(t, 4, strings.Count(list, inactiveLogRow))
|
|
|
|
statsPrune(t, db, dbMgr, log, hist.webhookDB)
|
|
|
|
list = targetList(t, renderSourceDetailPage(t, h, sess, hist.webhook.ID))
|
|
assert.Equal(t, 1, strings.Count(list, httpRow))
|
|
assert.Equal(t, 1, strings.Count(list, activeLogRow))
|
|
assert.Equal(t, 4, strings.Count(list, inactiveLogRow))
|
|
}
|
|
|
|
// TestHandleSourceDetail_TargetDeliveriesUnreadable checks that when the
|
|
// webhook's event database cannot be read, each target's row says so
|
|
// instead of showing zeros.
|
|
func TestHandleSourceDetail_TargetDeliveriesUnreadable(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var (
|
|
h *handlers.Handlers
|
|
sess *session.Session
|
|
db *database.Database
|
|
dbMgr *database.WebhookDBManager
|
|
)
|
|
|
|
app := newTestApp(t, &h, &sess, &db, &dbMgr)
|
|
app.RequireStart()
|
|
|
|
t.Cleanup(app.RequireStop)
|
|
|
|
wh := seedWebhook(t, db)
|
|
seedTarget(t, db, wh.ID, database.TargetTypeLog)
|
|
|
|
webhookDB, err := dbMgr.GetDB(wh.ID)
|
|
require.NoError(t, err)
|
|
require.NoError(t,
|
|
webhookDB.Migrator().DropTable(&database.TargetTotals{}))
|
|
|
|
list := targetList(t, renderSourceDetailPage(t, h, sess, wh.ID))
|
|
assert.Contains(t, list, "t-log log Active Edit Deactivate Delete "+
|
|
"The delivery counts could not be read.")
|
|
assert.NotContains(t, list, "Delivered:")
|
|
}
|