package view import ( "net/http" "net/http/httptest" "regexp" "strconv" "strings" "testing" "time" ) // renderSignedIn renders a page of the kit through the engine, as a handler // would, with the inbound relay and DMARC switched on. func renderSignedIn(t *testing.T, page string, data any) string { t.Helper() engine := newGuardEngine(t) rec := httptest.NewRecorder() engine.Render(rec, http.StatusOK, page, data) if rec.Code != http.StatusOK { t.Fatalf("render %s: status %d: %s", page, rec.Code, rec.Body.String()) } return rec.Body.String() } func renderFragment(t *testing.T, name string, data any) string { t.Helper() engine := newGuardEngine(t) rec := httptest.NewRecorder() engine.RenderFragment(rec, http.StatusOK, name, data) if rec.Code != http.StatusOK { t.Fatalf("render fragment %s: status %d: %s", name, rec.Code, rec.Body.String()) } return rec.Body.String() } func pageHas(t *testing.T, page, out string, wants ...string) { t.Helper() for _, want := range wants { if !strings.Contains(out, want) { t.Errorf("%s is missing %q", page, want) } } } func pageLacks(t *testing.T, page, out string, gones ...string) { t.Helper() for _, gone := range gones { if strings.Contains(out, gone) { t.Errorf("%s carries %q", page, gone) } } } // ---- Overview // The stamp, the sentence and the cards say the same thing: the worst card // colours the stamp, the number counts the cards that are not fine, and the // lead names them with their detail and a way to the table behind each. func TestOverviewHeadFollowsTheCards(t *testing.T) { out := renderSignedIn(t, "overview", overviewFixture()) pageHas(t, "Overview", out, `

Running, with warnings.

`, `class="sp-postmark sp-warn"`, `WARN`, `1 OF 6 CHECKS`, `Needs attention: TLS certificate (Expires in 12 days).`, `Updated 14:02:31
refreshes on its own`, `

mail.example.org

`, `class="sp-warn"`, // the certificate card `href="/server/health"`, `>All details`, ) cards := overviewFixture().Cards for i := range cards { cards[i].Level = "" } ok := NewOverview(admin(), "mail.example.org", cards, time.Now(), 30, true) if p := ok.Head.Postmark; p.Level != LevelOK || p.Word != "OK" || p.Bottom != "6 OF 6 CHECKS" { t.Errorf("a healthy panel is stamped %+v", *p) } if ok.Head.Lead != nil { t.Errorf("a healthy panel names something that needs attention: %v", ok.Head.Lead) } cards[1].Level, cards[2].Level = LevelWarn, LevelFail bad := NewOverview(admin(), "", cards, time.Now(), 30, true) if p := bad.Head.Postmark; p.Level != LevelFail || p.Word != "FAIL" || p.Bottom != "2 OF 6 CHECKS" { t.Errorf("a failing card does not make the stamp FAIL: %+v", *p) } if bad.Head.Kicker != "" { t.Errorf("kicker %q without a host name", bad.Head.Kicker) } } func TestOverviewListsBothKindsOfDomain(t *testing.T) { out := renderSignedIn(t, "overview", overviewFixture()) pageHas(t, "Overview", out, `

Outbound domains

`, `

Inbound domains

`, `30 days`, "1 284 msg", "18 920 msg", `example.org`, `SPF`, `DMARC`, `acme.io`, `10.0.4.12:2525`, `href="/outbound/domains">Manage`, `href="/inbound/domains">Manage`, ) } // With the inbound relay off the page neither draws nor links the inbound box. func TestOverviewWithoutInboundHasNoInboundBox(t *testing.T) { o := NewOverview(admin(), "mail.example.org", overviewFixture().Cards, time.Now(), 30, false) out := renderSignedIn(t, "overview", o) pageHas(t, "Overview", out, `

Outbound domains

`) pageLacks(t, "Overview", out, `Inbound domains`, `MX`) if got := strings.Count(out, `>Manage`); got != 1 { t.Errorf("%d Manage links, want the outbound one only", got) } if strings.Contains(out, `class="column is-7"`) { t.Error("the outbound box is squeezed into a column with nothing beside it") } } func TestOverviewEmptyTablesSayWhatIsAbsent(t *testing.T) { o := NewOverview(admin(), "mail.example.org", overviewFixture().Cards, time.Now(), 30, true) out := renderSignedIn(t, "overview", o) pageHas(t, "Overview", out, `No outbound domains yet.`, `No inbound domains yet.`) pageLacks(t, "Overview", out, `alert(1)` o.InboundRows[0].Upstream = `">` out := renderSignedIn(t, "overview", o) pageLacks(t, "Overview", out, ``, `a"onfocus="x` out := renderSignedIn(t, "account", a) pageLacks(t, "Account", out, `