check / check (push) Successful in 3m31s
The database target type is called an archive on its badge, in the add target form's type list and on its edit page, and its settings read "Archive expiry" and "Archive rotation" everywhere, the new webhook page included. The retry field is labelled "Delivery attempts", with its help text and error messages to match, on both target forms and in the target list, where a stored 0 shows as one attempt. The target list's other labels take the same capitalisation. The navbar says "Sign out" and the sign-in page "Sign in", and the README follows. The resubmit notice says "webhook". The stored values (`database`, `max_retries`) and their meaning are unchanged. Model: opus-5-5
112 行
2.9 KiB
Go
112 行
2.9 KiB
Go
package handlers_test
|
|
|
|
import (
|
|
"html/template"
|
|
"net/http"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"sneak.berlin/go/webhooker/internal/database"
|
|
"sneak.berlin/go/webhooker/internal/handlers"
|
|
"sneak.berlin/go/webhooker/internal/session"
|
|
"sneak.berlin/go/webhooker/templates"
|
|
)
|
|
|
|
// TestEveryPageRendersItsOwnTitle renders each page template and checks
|
|
// the browser tab title is the one the page declares, not the
|
|
// "Webhooker" fallback in htmlheader.html. A page that fails to render
|
|
// shows the error page's title instead, and fails here too.
|
|
func TestEveryPageRendersItsOwnTitle(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var h *handlers.Handlers
|
|
|
|
var sess *session.Session
|
|
|
|
app := newTestApp(t, &h, &sess)
|
|
app.RequireStart()
|
|
|
|
t.Cleanup(app.RequireStop)
|
|
|
|
// A pointer, as in the handlers: some pages call
|
|
// Webhook.RetentionLabel, a pointer method.
|
|
webhook := &database.Webhook{Name: "orders", RetentionDays: 14}
|
|
webhook.ID = testWebhookID
|
|
|
|
pages := []struct {
|
|
page string
|
|
data map[string]any
|
|
title string
|
|
}{
|
|
{"login.html", map[string]any{}, "Sign in - Webhooker"},
|
|
{"profile.html", map[string]any{}, "Profile - Webhooker"},
|
|
{"settings.html", map[string]any{}, "Settings - Webhooker"},
|
|
{"sources_list.html", map[string]any{}, "Webhooks - Webhooker"},
|
|
{"sources_new.html", map[string]any{}, "New Webhook - Webhooker"},
|
|
{
|
|
"source_detail.html",
|
|
map[string]any{dataKeyWebhook: webhook},
|
|
"orders - Webhooker",
|
|
},
|
|
{
|
|
"source_edit.html",
|
|
map[string]any{dataKeyWebhook: webhook},
|
|
"Edit orders - Webhooker",
|
|
},
|
|
{
|
|
"source_logs.html",
|
|
map[string]any{
|
|
dataKeyWebhook: webhook,
|
|
dataKeyEvents: []handlers.EventLogView{},
|
|
"TotalEvents": int64(0),
|
|
},
|
|
"Full Event Log - orders - Webhooker",
|
|
},
|
|
{
|
|
"event_detail.html",
|
|
map[string]any{dataKeyWebhook: webhook},
|
|
"Event - orders - Webhooker",
|
|
},
|
|
{
|
|
"target_edit.html",
|
|
map[string]any{
|
|
dataKeyWebhook: webhook,
|
|
"Target": map[string]any{"Name": "alerts", "Type": "slack"},
|
|
},
|
|
"Edit alerts - Webhooker",
|
|
},
|
|
{
|
|
"error.html",
|
|
map[string]any{"StatusText": http.StatusText(http.StatusNotFound)},
|
|
"Not Found - Webhooker",
|
|
},
|
|
}
|
|
|
|
for _, p := range pages {
|
|
body := renderPage(t, h, sess, p.page, p.data)
|
|
|
|
_, afterOpen, _ := strings.Cut(body, "<title>")
|
|
title, _, _ := strings.Cut(afterOpen, "</title>")
|
|
|
|
assert.Equal(t, p.title, title, p.page)
|
|
}
|
|
}
|
|
|
|
// TestTitleFallbackIsWebhooker checks the title htmlheader.html gives a
|
|
// page that declares none. Every page declares one, so it is checked on
|
|
// htmlheader.html alone.
|
|
func TestTitleFallbackIsWebhooker(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
header := template.Must(
|
|
template.ParseFS(templates.Templates, "htmlheader.html"),
|
|
)
|
|
|
|
var buf strings.Builder
|
|
|
|
require.NoError(t, header.ExecuteTemplate(&buf, "htmlheader", nil))
|
|
assert.Contains(t, buf.String(), "<title>Webhooker</title>")
|
|
}
|