aboutsummaryrefslogtreecommitdiff
path: root/internal/web/server_test.go
blob: 9e37177e0676ecee3f8019625dcd543d97ef01bb (plain) (blame)
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")
		}
	})
}