oficina / memoria Public

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

Plain git — no account needed to clone.

Download

Download this file

1package memoriatest
2
3import (
4 "html"
5 "net/http"
6 "net/url"
7 "regexp"
8 "strings"
9 "testing"
10
11 "amadan.net/oficina/estilo.git/sky"
12)
13
14// The sign-in page is the suite's door (estilo chrome, 2026-09-29): one
15// card on the team's sky with Memoria's mark and name at its head. Paul's
16// ruling is that every app's sign-in is "a version of the Oficina sign-in
17// screen", so this pins that the page IS the door rather than memoria's
18// old bare form — and that everything the door links is actually served:
19// a card whose stylesheet 404s, or a sky whose layers nothing mounts,
20// renders as a plain form with no error anywhere.
21//
22// And the door's form must still sign someone in. Its field is named by
23// estilo, not by this app, so the POST below uses the name the RENDERED
24// page carries, not one typed here: if the door ever renamed the field,
25// an owner's address would stop reaching the handler and this fails.
26//
27// MUTATION-TESTED 2026-09-29 by its author (so they prove consistency, not
28// coverage — AGENTS.md), each reverted: the sky mount removed from app.go
29// -> both served layers 404 here (and TestSkyRouteIsEstilosPrefix red);
30// the chrome.css link removed from signin.html -> "does not link chrome.css".
31func TestSigninPageIsTheDoor(t *testing.T) {
32 h, rec := signinApp(t)
33 rr := get(t, h, "/signin")
34 if rr.Code != http.StatusOK {
35 t.Fatalf("GET /signin = %d", rr.Code)
36 }
37 body := rr.Body.String()
38
39 for _, want := range []string{
40 "estilo-door",
41 `<span>Memoria</span>`,
42 `<h1>Sign in</h1>`,
43 // The suite's copy (shared chrome §9.2): the help under the field,
44 // and Open source reachable while signed out (§8.4).
45 "We’ll email you a link that signs you in. It works once and expires in 15 minutes.",
46 `href="/help/open-source"`,
47 `action="/auth/begin"`,
48 // Paul, 2026-10-01: the door's button says "Sign in".
49 `>Sign in</button>`,
50 // The door's tab title (estilo chrome.Title).
51 `<title>Sign in · Memoria</title>`,
52 } {
53 if !strings.Contains(html.UnescapeString(body), html.UnescapeString(want)) {
54 t.Errorf("the sign-in page lacks %q", want)
55 }
56 }
57 // Retired (§9.2): "Email me a link" (Paul, 2026-10-01), the lede
58 // "Memoria holds your team's work…", and the
59 // footer's egress claim, which is about searching and is said only to
60 // somebody signed in.
61 // And the old title, "Sign in — Memoria".
62 for _, gone := range []string{"Email me a link", "holds your team", "<footer", "leaves this instance", "Sign in — Memoria"} {
63 if strings.Contains(body, gone) {
64 t.Errorf("the sign-in page still carries %q", gone)
65 }
66 }
67
68 // Every sky layer the door links: the two inline placeholders (which
69 // is why CSP must allow img-src data:) and the served ones.
70 layers := regexp.MustCompile(`<img estilo-sky-layer="([a-z]+)"[^>]* src="([^"]+)"`).FindAllStringSubmatch(body, -1)
71 if len(layers) < 3 {
72 t.Fatalf("found %d sky layers on the sign-in page, want the placeholders and the served layers", len(layers))
73 }
74 served := 0
75 for _, m := range layers {
76 src := html.UnescapeString(m[2])
77 if strings.HasPrefix(src, "data:") {
78 continue
79 }
80 served++
81 if !strings.HasPrefix(src, sky.Prefix) {
82 t.Errorf("sky layer %s is %q, not under %s", m[1], src, sky.Prefix)
83 }
84 if got := get(t, h, src); got.Code != http.StatusOK || got.Header().Get("Content-Type") != "image/svg+xml" {
85 t.Errorf("GET %s = %d %q; the sky layer is linked but not served", src, got.Code, got.Header().Get("Content-Type"))
86 }
87 }
88 if served == 0 {
89 t.Error("no sky layer is served from the app; the served half of the sky was never checked")
90 }
91
92 // The door's stylesheets are linked and served.
93 for _, name := range []string{"chrome", "sky"} {
94 m := regexp.MustCompile(`href="(/static/` + name + `[^"]*\.css)"`).FindStringSubmatch(body)
95 if m == nil {
96 t.Errorf("the sign-in page does not link %s.css", name)
97 continue
98 }
99 if got := get(t, h, m[1]); got.Code != http.StatusOK || !strings.Contains(got.Body.String(), "estilo-") {
100 t.Errorf("GET %s = %d; the door's stylesheet is linked but not served", m[1], got.Code)
101 }
102 }
103
104 // The field name the door renders, read off the page.
105 field := regexp.MustCompile(`<input rst-input type="email" id="estilo-signin-address" name="([^"]+)"`).FindStringSubmatch(body)
106 if field == nil {
107 t.Fatalf("no email field on the door:\n%s", body)
108 }
109 if field[1] != "address" {
110 t.Errorf("the door's field is named %q; beginGuard and rastrillo read address", field[1])
111 }
112 rr = post(t, h, "/auth/begin", url.Values{field[1]: {dialTestOwner}})
113 if rr.Code != http.StatusSeeOther || rr.Header().Get("Location") != "/signin?sent=1" {
114 t.Errorf("an owner's POST from the door = %d %q, want 303 /signin?sent=1", rr.Code, rr.Header().Get("Location"))
115 }
116 // A stranger's POST answers the same, so the redirect alone cannot
117 // tell a read address from an ignored one. The classifier dialling is
118 // what proves the owner's address reached sign-in.
119 if !rec.dialed() {
120 t.Error("the owner's address never reached the sign-in classifier; the door's field is not what the handler reads")
121 }
122}
123