package view import ( "strings" "testing" "time" ) // ---- The log // The log is the whole of what the journal holds about the viewer's mail: the // filters offer what the viewer reaches, the head says how long rows live and // where to change it, and every row leads to its own page. func TestOutLogShowsTheRowsAndTheirFilters(t *testing.T) { out := renderSignedIn(t, "out-log", outLogFixture()) pageHas(t, "Outbound log", out, `

Outbound log

`, `Rows older than 30 days are deleted — change that in Settings.`, `
`, ``, `Time, UTC`, `09-21 14:01:52`, `shop@shop.example.org`, `m.keller@gmx.de`, `title="[FIRING] disk usage above 90 % on db-2"`, `sent`, `deferred`, `bounced`, `rate-limited`, `wrong From`, `href="/outbound/log/184220">Details`, `Page 1 of 412`, `Older →`, `New rows appear on their own`, ) pageLacks(t, "Outbound log", out, `← Newer`) // Without the global role there is nowhere to change the retention. p := NewOutLog(Meta{User: "ops", HasOutbound: true}, 7, false, []string{"example.org"}, nil, OutLogFilter{}) out = renderSignedIn(t, "out-log", p.WithRows(nil, 1, 1)) pageHas(t, "Outbound log", out, `Rows older than 7 days are deleted.`) pageLacks(t, "Outbound log", out, `/server/settings`) pageLacks(t, "Outbound log", renderSignedIn(t, "out-log", NewOutLog(Meta{User: "ops", HasOutbound: true}, 1, false, nil, nil, OutLogFilter{}).WithRows(nil, 1, 1)), `older than 1 days`) } // The filter in force is the one selected, and the poll, the paging and the // links of the rows all carry it — and say nothing for a filter that is not set. func TestOutLogCarriesItsFilters(t *testing.T) { p := NewOutLog(admin(), 30, true, []string{"example.org", "shop.example.org"}, []string{"alerts"}, OutLogFilter{Domain: "shop.example.org", App: "alerts", Status: "rejected", From: "2026-09-14", To: "2026-09-21"}) p.WithRows([]OutLogRow{{Time: "09-21 14:01:52", From: "a@example.org", To: "b@example.org", Subject: "Hi", Status: Tag{Status: "sent"}, Href: p.DetailHref(7, 3)}}, 3, 5) out := renderSignedIn(t, "out-log", p) // The keys in order (url.Values.Encode sorts them), the page among them. q := func(page string) string { return `app=alerts&domain=shop.example.org&from=2026-09-14&p=` + page + `&status=rejected&to=2026-09-21` } pageHas(t, "Outbound log", out, ``, ``, ``, ``, `name="from" value="2026-09-14"`, `name="to" value="2026-09-21"`, `hx-get="/outbound/log/fragment?`+q("3")+`"`, `href="/outbound/log/7?`+q("3")+`"`, `Page 3 of 5 · ← Newer`, `Older →`, ) // The status list is the statuses of a row, rejected the three refusals // together; a reason is not a status (owner, 2026-10-13). pageLacks(t, "Outbound log", out, `