1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
package web
import (
"net/http"
"net/http/httptest"
"os"
"strings"
"testing"
"github.com/lukaszkasprzak/lectio/internal/config"
"github.com/lukaszkasprzak/lectio/internal/liturgy"
)
// TestServer exercises NewServer's handler tree end to end via httptest,
// against the same fixture HTML/hook internal/readings uses (see
// readings_test.go TestLoadModernRoutes): no real network, no real browser.
func TestServer(t *testing.T) {
html, err := os.ReadFile("../liturgy/testdata/2026-07-22.html")
if err != nil {
t.Fatal(err)
}
fixtureServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write(html)
}))
defer fixtureServer.Close()
liturgy.SetBaseURL(fixtureServer.URL + "/liturgia/%s/Ewangelia")
t.Setenv("XDG_CACHE_HOME", t.TempDir())
srv := NewServer(config.Default())
t.Run("index page", func(t *testing.T) {
rec := httptest.NewRecorder()
srv.ServeHTTP(rec, httptest.NewRequest("GET", "/?date=2026-07-22&v=wuj", nil))
if rec.Code != http.StatusOK {
t.Fatalf("status = %d, want 200", rec.Code)
}
body := rec.Body.String()
if !strings.Contains(body, "Ewangelia") {
t.Errorf("body missing reading heading: %q", body)
}
if !strings.Contains(body, "htmx") {
t.Errorf("body missing htmx reference")
}
if !strings.Contains(body, `id="theme"`) {
t.Errorf("body missing theme <link>")
}
})
t.Run("readings partial", func(t *testing.T) {
rec := httptest.NewRecorder()
srv.ServeHTTP(rec, httptest.NewRequest("GET", "/readings?date=2026-07-22&v=wuj&all=1", nil))
if rec.Code != http.StatusOK {
t.Fatalf("status = %d, want 200", rec.Code)
}
body := rec.Body.String()
if strings.Contains(body, "<html") {
t.Errorf("partial is not a fragment: %q", body)
}
if !strings.Contains(body, "Ewangelia") {
t.Errorf("partial missing reading heading: %q", body)
}
})
t.Run("lookup", func(t *testing.T) {
rec := httptest.NewRecorder()
srv.ServeHTTP(rec, httptest.NewRequest("GET", "/lookup?ref=J+20:1&v=wuj", nil))
if rec.Code != http.StatusOK {
t.Fatalf("status = %d, want 200", rec.Code)
}
if !strings.Contains(rec.Body.String(), "20:1") {
t.Errorf("lookup result missing verse: %q", rec.Body.String())
}
})
t.Run("theme.css", func(t *testing.T) {
rec := httptest.NewRecorder()
srv.ServeHTTP(rec, httptest.NewRequest("GET", "/theme.css?name=benedictines", nil))
if rec.Code != http.StatusOK {
t.Fatalf("status = %d, want 200", rec.Code)
}
if !strings.Contains(rec.Header().Get("Content-Type"), "css") {
t.Errorf("Content-Type = %q, want it to contain css", rec.Header().Get("Content-Type"))
}
})
t.Run("static", func(t *testing.T) {
rec := httptest.NewRecorder()
srv.ServeHTTP(rec, httptest.NewRequest("GET", "/static/htmx.min.js", nil))
if rec.Code != http.StatusOK {
t.Fatalf("status = %d, want 200", rec.Code)
}
if rec.Body.Len() == 0 {
t.Error("static/htmx.min.js served empty body")
}
})
t.Run("theme.css unknown falls back", func(t *testing.T) {
rec := httptest.NewRecorder()
srv.ServeHTTP(rec, httptest.NewRequest("GET", "/theme.css?name=does-not-exist", nil))
if rec.Code != http.StatusOK {
t.Fatalf("status = %d, want 200 (fallback to cfg.WebTheme/default)", rec.Code)
}
if rec.Body.Len() == 0 {
t.Error("theme.css fallback served empty body")
}
})
}
|