package web // Issue 1859/AC6, AC7 (novox/hq ADR 0515 §5, §6; issue 1850): the reading pane shows one mail as escaped // text, with its corrections, each calling correct; a sender with no display name is named by its address. import ( "context" "encoding/json" "net/http" "net/url" "strings" "testing" "time" ) // paneEntry is mail-reading.entries' answer for one entry (mesh-mail-reader tools.go entryOut). func paneEntry() map[string]any { return map[string]any{ "id": 3, "account": "work", "message-id": "", "date": "2026-10-21T08:00:00Z", "sender-name": "", "sender-address": "lena@harbor.example", "subject": "Hostco renewal", "group": "suppliers", "summary": "Hostco renews on 1 November", "mark": "matters", "why": "a contract to approve", "due-date": "", "folder": "INBOX", "uid": 103, "read-later": false, "tasks": []any{map[string]any{"n": 1, "line": "Approve the Hostco renewal", "due-date": "2026-10-24"}, map[string]any{"n": 2, "line": "Forward the invoice", "due-date": ""}}, "promises": []any{map[string]any{"n": 1, "kind": "on its way", "line": "The new contract", "who": "Hostco", "date": ""}}, } } func paneBundle(t *testing.T) (*readingStandIn, *Bundle) { t.Helper() reading := &readingStandIn{list: fullList(), entry: paneEntry()} b := reading.bundle(time.Now()) b.Read = func(_ context.Context, args map[string]any) (json.RawMessage, error) { reading.mu.Lock() reading.calls = append(reading.calls, readingCall{"read", args}) reading.mu.Unlock() return json.Marshal(map[string]any{"account": "work", "folder": "INBOX", "uid": 103, "date": "2026-10-21T08:00:00Z", "from": []any{map[string]any{"address": "lena@harbor.example"}}, "to": []any{map[string]any{"address": "op@work.example"}}, "subject": "Hostco renewal", "text": "Hi,\n the renewal is attached.", "attachments": []any{map[string]any{"key": "att1", "name": "renewal.pdf", "size": 2048, "type": "application/pdf"}}}) } return reading, b } // 1859/AC7: the pane shows one mail as escaped text with its corrections, and records it opened. func TestTheReadingPaneShowsOneMailWithItsCorrections(t *testing.T) { reading, b := paneBundle(t) s, cookie, _ := signedIn(t, b) r := newGet("/read?id=3&mode=work", cookie) w := serve(s, r) body := w.Body.String() if w.Code != http.StatusOK { t.Fatalf("status %d:\n%s", w.Code, body) } for _, want := range []string{`id="pane"`, "Hostco renewal", "<script>alert(1)</script>", "renewal.pdf", "Approve the Hostco renewal", `name="not-a-task" value="2"`, `name="remove-promise" value="1"`, `name="read-later" value="on"`, `name="mark"`, `name="group"`, `id="today"`} { if !strings.Contains(body, want) { t.Fatalf("the pane does not show %q:\n%s", want, body) } } if strings.Contains(body, "