The form's reason and values now come from the targetForm component, loaded from the section's data attributes after a refusal and emptied by Cancel, which also resets the form. Each type's fields used to be recreated with the refused values written into the markup, so they came back after Cancel. The browser test checks this after a refusal. A target configuration that cannot be encoded is again a logged 500 with the generic error page, on the add and the edit path; only refusals of submitted values come back on the form. The README paragraph on the browser test is re-wrapped at 80 columns and names Cancel at the type step. Model: opus-5-5
168 lines
5.1 KiB
Go
168 lines
5.1 KiB
Go
package handlers
|
|
|
|
import (
|
|
"context"
|
|
"html/template"
|
|
"log/slog"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"time"
|
|
|
|
"gorm.io/gorm"
|
|
"sneak.berlin/go/webhooker/internal/database"
|
|
)
|
|
|
|
// SetLogForTest replaces the handler's logger, so the handlers_test
|
|
// package can assert on what a log line actually contains rather than
|
|
// on what it is meant to contain.
|
|
func (s *Handlers) SetLogForTest(log *slog.Logger) {
|
|
s.log = log
|
|
}
|
|
|
|
// MaxRenderedBodyBytesForTest exposes the event log's body cap
|
|
// to the handlers_test package.
|
|
const MaxRenderedBodyBytesForTest = maxRenderedBodyBytes
|
|
|
|
// MaxRenderedResponseBytesForTest exposes the event log's
|
|
// delivery response cap to the handlers_test package.
|
|
const MaxRenderedResponseBytesForTest = maxRenderedResponseBytes
|
|
|
|
// MaxRenderedAttemptsForTest exposes the event log's
|
|
// per-delivery attempt ceiling to the handlers_test package.
|
|
const MaxRenderedAttemptsForTest = maxRenderedAttempts
|
|
|
|
// MaxTargetRetriesForTest exposes the target max_retries ceiling to
|
|
// the handlers_test package, so the tests assert against the constant
|
|
// the handlers enforce rather than a number copied beside it.
|
|
const MaxTargetRetriesForTest = maxTargetRetries
|
|
|
|
// EventDBLeftMsgForTest and SidecarLeftMsgForTest expose the two
|
|
// messages the webhook delete handler logs when a file of the event
|
|
// database is left on disk, so a test checking that one is absent
|
|
// checks for the handler's own wording.
|
|
const (
|
|
EventDBLeftMsgForTest = eventDBLeftMsg
|
|
SidecarLeftMsgForTest = sidecarLeftMsg
|
|
)
|
|
|
|
// PageOrFirstForTest exposes pageOrFirst for use in the handlers_test
|
|
// package.
|
|
func PageOrFirstForTest(s string) int {
|
|
return pageOrFirst(s)
|
|
}
|
|
|
|
// DummyVerificationsForTest reports how many equivalent-cost
|
|
// verifications were charged for usernames that do not exist. It
|
|
// lets a test prove the anti-enumeration path ran without timing
|
|
// anything.
|
|
func (s *Handlers) DummyVerificationsForTest() uint64 {
|
|
return s.dummyVerifications.Load()
|
|
}
|
|
|
|
// TrimPartialRuneForTest exposes trimPartialRune for use in the
|
|
// handlers_test package.
|
|
func TrimPartialRuneForTest(b []byte) []byte {
|
|
return trimPartialRune(b)
|
|
}
|
|
|
|
// LoadEventLogViewsForTest exposes loadEventsWithDeliveries for
|
|
// use in the handlers_test package. Assertions on the projected
|
|
// body need the bytes as loaded: html/template rewrites invalid
|
|
// UTF-8 on the way out, so the rendered page cannot show whether
|
|
// a binary body survived the projection intact.
|
|
func (s *Handlers) LoadEventLogViewsForTest(
|
|
w http.ResponseWriter,
|
|
webhook database.Webhook,
|
|
page int,
|
|
) []EventLogView {
|
|
views, _, _ := s.loadEventsWithDeliveries(
|
|
w, newRequestForTest(), webhook, nil, page,
|
|
)
|
|
|
|
return views
|
|
}
|
|
|
|
// WebhookStatsForTest returns the figures the statistics pane on a
|
|
// webhook's page shows, from the webhook's entrypoints and targets
|
|
// loaded as that page loads them.
|
|
func (s *Handlers) WebhookStatsForTest(webhookID string) *WebhookStats {
|
|
var entrypoints []database.Entrypoint
|
|
|
|
s.db.DB().Where("webhook_id = ?", webhookID).Find(&entrypoints)
|
|
|
|
var targets []database.Target
|
|
|
|
s.db.DB().Where("webhook_id = ?", webhookID).Find(&targets)
|
|
|
|
return s.loadWebhookStats(webhookID, entrypoints, targets)
|
|
}
|
|
|
|
// FinishedByTargetForTest exposes finishedByTarget for use in the
|
|
// handlers_test package.
|
|
func FinishedByTargetForTest(
|
|
webhookDB *gorm.DB, since time.Time,
|
|
) ([]TargetFinished, error) {
|
|
return finishedByTarget(webhookDB, since)
|
|
}
|
|
|
|
// newRequestForTest is the request the helpers here pass on for
|
|
// callers that have none: it is used only to render the error page.
|
|
func newRequestForTest() *http.Request {
|
|
return httptest.NewRequestWithContext(
|
|
context.Background(), http.MethodGet, "/", nil,
|
|
)
|
|
}
|
|
|
|
// AddTemplateForTest registers a template under a page name so that
|
|
// the handlers_test package can drive the render path with a
|
|
// template of its own.
|
|
func (s *Handlers) AddTemplateForTest(
|
|
pageTemplate string,
|
|
tmpl *template.Template,
|
|
) {
|
|
s.templates[pageTemplate] = tmpl
|
|
}
|
|
|
|
// RenderTemplateForTest exposes renderTemplate for use in the
|
|
// handlers_test package.
|
|
func (s *Handlers) RenderTemplateForTest(
|
|
w http.ResponseWriter,
|
|
r *http.Request,
|
|
pageTemplate string,
|
|
data any,
|
|
) {
|
|
s.renderTemplate(w, r, pageTemplate, data)
|
|
}
|
|
|
|
// BuildSlackTargetConfigForTest exposes
|
|
// buildSlackTargetConfig for use in the handlers_test package.
|
|
func (s *Handlers) BuildSlackTargetConfigForTest(
|
|
ctx context.Context,
|
|
targetURL string,
|
|
) (string, string, error) {
|
|
return s.buildSlackTargetConfig(ctx, targetURL)
|
|
}
|
|
|
|
// BuildHTTPTargetConfigForTest exposes buildHTTPTargetConfig
|
|
// for use in the handlers_test package, taking the form fields
|
|
// an HTTP target's configuration is built from.
|
|
func (s *Handlers) BuildHTTPTargetConfigForTest(
|
|
ctx context.Context,
|
|
targetURL, headers, timeout string,
|
|
) (string, string, error) {
|
|
return s.buildHTTPTargetConfig(ctx, targetFormInput{
|
|
URL: targetURL,
|
|
Headers: headers,
|
|
Timeout: timeout,
|
|
})
|
|
}
|
|
|
|
// BuildDatabaseTargetConfigForTest exposes
|
|
// buildDatabaseTargetConfig for use in the handlers_test
|
|
// package.
|
|
func BuildDatabaseTargetConfigForTest(
|
|
expiry string,
|
|
) (string, string, error) {
|
|
return buildDatabaseTargetConfig(expiry)
|
|
}
|