Name the item and what is lost in each delete prompt (closes #400)
check / check (push) Successful in 3m21s

The webhook, entrypoint and target delete prompts on the webhook page
now name the item and say what deleting it loses: the webhook's stored
events (with the count from the statistics pane) and their deliveries,
while its archive files are kept; an entrypoint's URL, which stops
working for good; a target's future deliveries, while its past ones
stay in the event log. They stay the browser's own prompts, so they
work without the page's scripts, and each name is escaped for the
script so quotes and backslashes show as typed.

Model: opus-5-5
This commit is contained in:
2026-10-03 00:33:48 +00:00
parent f1da5e73dd
commit 8adb7cd043
3 changed files with 101 additions and 5 deletions
+91
View File
@@ -275,3 +275,94 @@ func TestHandleSourceDetail_FitsWideAndNarrowWindows(t *testing.T) {
`<div class="flex flex-wrap justify-between items-center gap-2 mt-2">`,
)
}
// TestHandleSourceDetail_DeletePromptsNameWhatIsLost checks that each
// delete prompt on the webhook page names the webhook, entrypoint or
// target and says what deleting it loses, that the webhook's gives its
// number of stored events, and that an entrypoint with no description
// is named by its URL. The template writes the slashes after http: as
// \/, which the browser reads as /.
func TestHandleSourceDetail_DeletePromptsNameWhatIsLost(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)
webhookDB, err := dbMgr.GetDB(wh.ID)
require.NoError(t, err)
require.NoError(t, database.AddEventTotals(
webhookDB, database.EventTotals{Events: 3},
))
unnamed := seedEntrypoint(t, db, wh.ID)
require.NoError(t, db.DB().Omit(clause.Associations).Create(
&database.Entrypoint{
WebhookID: wh.ID,
Path: "described-" + wh.ID,
Description: "Stripe",
Active: true,
},
).Error)
seedTarget(t, db, wh.ID, database.TargetTypeLog)
body := renderSourceDetailPage(t, h, sess, wh.ID)
assert.Contains(t, body,
`Delete webhook &quot;delete-me&quot;?\n\n`+
`This deletes its stored events (3) and their deliveries. `+
`Any archive files it wrote are kept.`)
assert.Contains(t, body,
`Delete entrypoint &quot;Stripe&quot;?\n\n`+
`Senders using its URL get an error from now on, `+
`and the URL cannot be restored.`)
assert.Contains(t, body,
`Delete entrypoint &quot;http:\/\/example.com/h/`+
unnamed.Path+`&quot;?`)
assert.Contains(t, body,
`Delete target &quot;t-log&quot;?\n\n`+
`Nothing more is delivered to it. `+
`Its past deliveries stay in the event log.`)
}
// TestHandleSourceDetail_DeletePromptKeepsQuotesInName checks that a
// webhook name with quotes and a backslash reaches its delete prompt
// escaped for the script, each quote as a \u escape and the backslash
// doubled, which the browser reads back as the name typed.
func TestHandleSourceDetail_DeletePromptKeepsQuotesInName(t *testing.T) {
t.Parallel()
var (
h *handlers.Handlers
sess *session.Session
db *database.Database
)
app := newTestApp(t, &h, &sess, &db)
app.RequireStart()
t.Cleanup(app.RequireStop)
wh := &database.Webhook{
UserID: deleteTestUserID,
Name: `Bob's "best" \ hook`,
}
require.NoError(
t, db.DB().Omit(clause.Associations).Create(wh).Error,
)
body := renderSourceDetailPage(t, h, sess, wh.ID)
assert.Contains(t, body,
"Delete webhook &quot;Bob\\u0027s \\u0022best\\u0022 \\\\ hook&quot;?")
}