oficina / meet Public

Clone
git clone https://amadan.net/oficina/meet

Plain git — no account needed to clone.

Download

Download this file

1package calls
2
3import (
4 "bytes"
5 "log/slog"
6 "net/http"
7 "net/http/httptest"
8 "strings"
9 "testing"
10 "time"
11)
12
13// A panic inside the router is the 500 page with a reference and the
14// viewer's chrome for a browser, and plain text for a fetch (spec §3.3).
15func TestAPanicIsTheErrorPageWithAReference(t *testing.T) {
16 f := newHomeRouterFixture(t)
17 boom := f.app.recoverToErrorPage(http.HandlerFunc(func(http.ResponseWriter, *http.Request) { panic("boom") }))
18 r := httptest.NewRequest("GET", homeTestOrigin+"/m/x", nil)
19 r.Header.Set("Accept", "text/html")
20 w := httptest.NewRecorder()
21 boom.ServeHTTP(w, r)
22 body := w.Body.String()
23 if w.Code != 500 || !strings.Contains(body, "<title>Something went wrong · Calls</title>") || !strings.Contains(body, "Reference:") ||
24 !strings.Contains(body, "<header estilo-bar>") || !strings.Contains(body, `href="/m/x">Try again</a>`) {
25 t.Fatalf("panic page: %d\n%s", w.Code, body)
26 }
27 r = httptest.NewRequest("GET", homeTestOrigin+"/m/x/info", nil)
28 w = httptest.NewRecorder()
29 boom.ServeHTTP(w, r)
30 if w.Code != 500 || !strings.HasPrefix(w.Header().Get("Content-Type"), "text/plain") {
31 t.Fatalf("panic for a fetch: %d %q", w.Code, w.Header().Get("Content-Type"))
32 }
33}
34
35// Astra on #24, finding 3 (Memoria #21's shape): the test above builds
36// recoverToErrorPage by hand, so taking it out of the router left it
37// green. This one panics inside a REAL route — the return cookie's clock,
38// read by /signin/local?return_to= — through the production router,
39// signed in and out, and checks the 500 page with a reference, the
40// viewer's own chrome, and that the panic's value reaches neither the
41// page nor the log.
42func TestARoutePanicIsTheErrorPageThroughTheRouter(t *testing.T) {
43 const sentinel = "secret-sentinel-title"
44 for _, signed := range []bool{true, false} {
45 f := newHomeRouterFixture(t)
46 if signed {
47 f.local(t)
48 }
49 var logs bytes.Buffer
50 f.app.logger = slog.New(slog.NewTextHandler(&logs, nil))
51 f.app.store.clk.set(func() time.Time { panic(sentinel) })
52 r := httptest.NewRequest("GET", homeTestOrigin+"/signin/local?return_to=%2Fsettings", nil)
53 r.Header.Set("Accept", "text/html")
54 for _, c := range f.cookies {
55 r.AddCookie(c)
56 }
57 w := httptest.NewRecorder()
58 func() {
59 defer func() {
60 if v := recover(); v != nil {
61 t.Fatalf("signed in=%v: the panic escaped the router: %v", signed, v)
62 }
63 }()
64 f.handler.ServeHTTP(w, r)
65 }()
66 b := w.Body.String()
67 if w.Code != http.StatusInternalServerError || !strings.Contains(b, "<title>Something went wrong · Calls</title>") || !strings.Contains(b, "rst-error-ref") {
68 t.Errorf("signed in=%v: %d, want the 500 page with a reference:\n%s", signed, w.Code, b)
69 }
70 if strings.Contains(b, "estilo-account") != signed {
71 t.Errorf("signed in=%v: the 500 page's chrome is not the viewer's", signed)
72 }
73 if strings.Contains(b, sentinel) || strings.Contains(logs.String(), sentinel) {
74 t.Errorf("signed in=%v: the panic's value reached the page or the log", signed)
75 }
76 if !strings.Contains(logs.String(), "ref=") {
77 t.Errorf("signed in=%v: no reference in the log: %s", signed, logs.String())
78 }
79 }
80}
81