The module's bundle (the one process with the bus) serves the page on the port its manifest declares under listens, from: machine, and requires a route that reaches it. No form, no script, no verb behind it; any method but GET is 405. A source that does not answer is said on the page, never shown as an empty list. Issue 1968. Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
70 lines
2.8 KiB
Go
70 lines
2.8 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"slices"
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// The page's handler answers GET and nothing else; its manifest declares the port for this machine only and requires a route
|
|
// (ADR 0616 §4, AC P2).
|
|
func TestThePageAnswersGetOnlyAndTheManifestKeepsItToThisMachine(t *testing.T) {
|
|
w := newOverviewWorld(t)
|
|
w.entries = []*Entry{recordEntry(301, StatusAccepted, "2026-11-02", w.now.Add(-24*time.Hour), nil)}
|
|
w.o.Start()
|
|
h := PageHandler(w.o)
|
|
rec := httptest.NewRecorder()
|
|
h.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/", nil))
|
|
body := rec.Body.String()
|
|
if rec.Code != 200 || !strings.Contains(body, "Design 47, milestone 1") || !strings.Contains(body, "ADR 0301") || !strings.Contains(body, "Approve ADR 0301") ||
|
|
!strings.Contains(body, "fix/a") {
|
|
t.Fatalf("%d\n%.600s", rec.Code, body)
|
|
}
|
|
if strings.Contains(body, "<form") || strings.Contains(body, "<script") || !strings.Contains(rec.Header().Get("Content-Security-Policy"), "default-src 'none'") {
|
|
t.Fatalf("the page carries a form or a script, or no policy: %v", rec.Header())
|
|
}
|
|
for _, method := range []string{http.MethodPost, http.MethodPut, http.MethodDelete, http.MethodPatch, http.MethodHead, http.MethodOptions} {
|
|
rec := httptest.NewRecorder()
|
|
h.ServeHTTP(rec, httptest.NewRequest(method, "/", strings.NewReader("x")))
|
|
if rec.Code != http.StatusMethodNotAllowed || rec.Header().Get("Allow") != http.MethodGet {
|
|
t.Errorf("%s answered %d", method, rec.Code)
|
|
}
|
|
}
|
|
if rec := httptest.NewRecorder(); func() int { h.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/other", nil)); return rec.Code }() != 404 {
|
|
t.Error("another path answered")
|
|
}
|
|
// A source that does not answer is said on the page, never shown as an empty list.
|
|
w.fail[AsksVerb] = true
|
|
w.o.Rebuild(SourceAsks)
|
|
rec = httptest.NewRecorder()
|
|
h.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/", nil))
|
|
if !strings.Contains(rec.Body.String(), "The operator channel does not answer") || !strings.Contains(rec.Body.String(), "verb: no answer in time") {
|
|
t.Fatalf("%.1500s", rec.Body.String())
|
|
}
|
|
// The manifest: the port listens from this machine, the route is required and the page is the one the code serves.
|
|
_, raw := readManifest(t)
|
|
var m struct {
|
|
Requires []any `json:"requires"`
|
|
Listens []struct {
|
|
Name string `json:"name"`
|
|
Port int `json:"port"`
|
|
From string `json:"from"`
|
|
} `json:"listens"`
|
|
Contributes map[string]map[string]string `json:"contributes"`
|
|
}
|
|
if err := json.Unmarshal([]byte(raw), &m); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(m.Listens) != 1 || m.Listens[0].From != "machine" || ":"+strconv.Itoa(m.Listens[0].Port) != PageAddress || m.Contributes["route"]["endpoint"] != m.Listens[0].Name {
|
|
t.Fatalf("%+v", m)
|
|
}
|
|
if !slices.Contains(m.Requires, any("route")) {
|
|
t.Fatal("the route is not required")
|
|
}
|
|
}
|