carlos / contra Public

Clone
git clone https://amadan.net/carlos/contra

Plain git — no account needed to clone.

Download

Download this file

1package contratest
2
3import (
4 "net/http"
5 "net/http/httptest"
6 "regexp"
7 "strings"
8 "testing"
9
10 contra "github.com/carlosframework/contra/internal/contra"
11)
12
13// hashedStylesheet is the fingerprinted URL shape the index page
14// links: /static/tokens.<16 hex>.css.
15var hashedStylesheet = regexp.MustCompile(`/static/tokens\.[0-9a-f]{16}\.css`)
16
17func TestIndexRenders(t *testing.T) {
18 rec := get(t, newApp(t), "/")
19 if rec.Code != http.StatusOK {
20 t.Fatalf("GET /: status %d, want 200", rec.Code)
21 }
22 if !strings.Contains(rec.Body.String(), "the server knows nothing about you") {
23 t.Errorf("GET /: page is missing its heading:\n%s", rec.Body.String())
24 }
25}
26
27func TestIndexLinksFingerprintedStylesheet(t *testing.T) {
28 h := newApp(t)
29 href := hashedStylesheet.FindString(get(t, h, "/").Body.String())
30 if href == "" {
31 t.Fatal("index page links no fingerprinted stylesheet")
32 }
33 rec := get(t, h, href)
34 if rec.Code != http.StatusOK {
35 t.Fatalf("GET %s: status %d, want 200", href, rec.Code)
36 }
37 if got := rec.Header().Get("Cache-Control"); got != "public, max-age=31536000, immutable" {
38 t.Errorf("GET %s: Cache-Control = %q, want immutable year", href, got)
39 }
40}
41
42// The bare name keeps working, just never long-cached — so a changed
43// file always shows on an ordinary reload.
44func TestBareAssetNameStaysFresh(t *testing.T) {
45 rec := get(t, newApp(t), "/static/tokens.css")
46 if rec.Code != http.StatusOK {
47 t.Fatalf("GET /static/tokens.css: status %d, want 200", rec.Code)
48 }
49 if got := rec.Header().Get("Cache-Control"); got != "no-cache" {
50 t.Errorf("Cache-Control = %q, want no-cache", got)
51 }
52}
53
54// ErrorPage is what main.go points Options.ErrorPage at (and the seam
55// to wire into Ctx.ErrorPage as handlers grow); called directly, it
56// pins that a panic's page is the framework's error-page partial, not
57// a stray net/http default.
58func TestErrorPageRendersFrameworkPartial(t *testing.T) {
59 rec := httptest.NewRecorder()
60 contra.ErrorPage(rec, httptest.NewRequest(http.MethodGet, "/", nil), http.StatusInternalServerError, "abc123")
61 if rec.Code != http.StatusInternalServerError {
62 t.Fatalf("ErrorPage: status %d, want %d", rec.Code, http.StatusInternalServerError)
63 }
64 body := rec.Body.String()
65 if !strings.Contains(body, "Something went wrong on our side") {
66 t.Errorf("ErrorPage body missing the 500 title:\n%s", body)
67 }
68 if !strings.Contains(body, "abc123") {
69 t.Errorf("ErrorPage body missing the ref:\n%s", body)
70 }
71}
72
73// The home page shipped for a while saying "there is no signup, no vault and
74// no stored data behind it" on a build that had all three. It was true when
75// it was written and nobody re-read it as the app grew.
76//
77// So: the claims on the front page are pinned against the routes that exist.
78// A page that says a thing does not exist, on a build where it does, is worse
79// than no page — this is a product whose entire pitch is that its statements
80// are literally true.
81func TestHomePageDoesNotContradictTheApp(t *testing.T) {
82 h := newApp(t)
83 body := get(t, h, "/").Body.String()
84
85 // If /signup answers, the home page must not claim there is no signup.
86 if get(t, h, "/signup").Code == http.StatusOK {
87 for _, lie := range []string{
88 "no signup", "no vault and no stored data", "not open yet",
89 } {
90 if strings.Contains(strings.ToLower(body), lie) {
91 t.Errorf("the home page still says %q, but /signup works", lie)
92 }
93 }
94 }
95}
96
97// Every page must offer a way onward. An empty navigation rail is how the
98// canary shipped, and a visitor who cannot reach signup from the front page
99// has been handed a dead end.
100func TestEveryPageOffersAWayOnward(t *testing.T) {
101 h := newApp(t)
102 for _, path := range []string{"/", "/signup", "/signin"} {
103 body := get(t, h, path).Body.String()
104 if !strings.Contains(body, `href="/signup"`) && !strings.Contains(body, `href="/vault"`) {
105 t.Errorf("%s offers no way onward: no link to signup or the vault", path)
106 }
107 if !strings.Contains(body, `href="/"`) {
108 t.Errorf("%s has no link home", path)
109 }
110 }
111}
112