This commit is contained in:
root
2026-10-01 22:16:48 +02:00
parent b6d1909d7f
commit 9dfdf79fa7
39 changed files with 4560 additions and 181 deletions
+34 -4
View File
@@ -20,13 +20,13 @@ import (
)
// newSite starts the API with the web front end mounted, as cmd/server does.
func newSite(t *testing.T, manualPDF string) (*httptest.Server, config.Config) {
srv, cfg, _ := newSiteStore(t, manualPDF)
func newSite(t *testing.T, manualPDF string, opts ...api.Option) (*httptest.Server, config.Config) {
srv, cfg, _ := newSiteStore(t, manualPDF, opts...)
return srv, cfg
}
// newSiteStore is newSite, also returning the database so tests can run a simulated day.
func newSiteStore(t *testing.T, manualPDF string) (*httptest.Server, config.Config, *store.Store) {
func newSiteStore(t *testing.T, manualPDF string, opts ...api.Option) (*httptest.Server, config.Config, *store.Store) {
t.Helper()
cfg := config.Default()
dsn := "sqlite:" + filepath.Join(t.TempDir(), "t.db")
@@ -49,7 +49,7 @@ func newSiteStore(t *testing.T, manualPDF string) (*httptest.Server, config.Conf
if err := st.Migrate(context.Background()); err != nil {
t.Fatal(err)
}
mux := api.New(st, cfg)
mux := api.New(st, cfg, opts...)
mux.Handle("/", web.Handler(manualPDF))
srv := httptest.NewServer(mux)
t.Cleanup(srv.Close)
@@ -182,3 +182,33 @@ func TestManualPDFServedFromFileAndPickedUpLive(t *testing.T) {
t.Fatalf("range: %d %q", rr.StatusCode, part)
}
}
func TestAdminPageIsServedWithSafeHeaders(t *testing.T) {
srv, _ := newSite(t, "")
resp, body := get(t, srv.URL+"/admin/")
if resp.StatusCode != 200 || !strings.Contains(body, "Halcyon Admin") {
t.Fatalf("/admin/: %d", resp.StatusCode)
}
if !strings.Contains(resp.Header.Get("Content-Security-Policy"), "default-src 'self'") {
t.Error("the admin page needs the site's Content-Security-Policy")
}
if !strings.Contains(resp.Header.Get("X-Robots-Tag"), "noindex") || resp.Header.Get("Cache-Control") != "no-store" {
t.Errorf("admin page headers: robots=%q cache=%q", resp.Header.Get("X-Robots-Tag"), resp.Header.Get("Cache-Control"))
}
for _, path := range []string{"/admin/admin.js", "/admin/admin.css"} {
if r, _ := get(t, srv.URL+path); r.StatusCode != 200 {
t.Errorf("%s: %d", path, r.StatusCode)
}
}
// /admin (no slash) reaches the same page.
client := &http.Client{CheckRedirect: func(*http.Request, []*http.Request) error { return http.ErrUseLastResponse }}
r, err := client.Get(srv.URL + "/admin")
if err != nil {
t.Fatal(err)
}
r.Body.Close()
// The Location is relative ("admin/"), which a browser resolves to /admin/.
if loc := r.Header.Get("Location"); r.StatusCode != 301 || (loc != "admin/" && loc != "/admin/") {
t.Errorf("/admin: %d -> %q, want a redirect to /admin/", r.StatusCode, loc)
}
}