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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
package tradlit
import (
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"strings"
"testing"
"github.com/lukaszkasprzak/lectio/internal/liturgy"
)
// TestLoadOnlineCachesRawBody exercises Load's online path: a successful
// fetch is cached verbatim (the raw response body, not the parsed
// sections) at tradlit's cache path, and parses the same way a cached read
// would.
func TestLoadOnlineCachesRawBody(t *testing.T) {
body, err := os.ReadFile("testdata/2026-07-22.json")
if err != nil {
t.Fatal(err)
}
hits := 0
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
hits++
w.Write(body)
}))
defer srv.Close()
orig := baseURL
baseURL = srv.URL + "/%s/api/v5/proper/%s"
defer func() { baseURL = orig }()
t.Setenv("XDG_CACHE_HOME", t.TempDir())
secs, err := Load("2026-07-22", "en", false)
if err != nil {
t.Fatalf("Load: %v", err)
}
if len(secs) == 0 {
t.Fatal("Load returned no sections")
}
if hits != 1 {
t.Errorf("server hit %d times, want 1", hits)
}
cached, err := os.ReadFile(filepath.Join(liturgy.CacheDir(), "2026-07-22.trad.en.json"))
if err != nil {
t.Fatalf("cache file not written: %v", err)
}
if string(cached) != string(body) {
t.Error("cached content does not match the raw response body")
}
}
// TestLoadOnline404WritesNoCache checks the documented invariant: a 404 (no
// propers published for that date) returns an error and leaves the cache
// directory untouched.
func TestLoadOnline404WritesNoCache(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound)
}))
defer srv.Close()
orig := baseURL
baseURL = srv.URL + "/%s/api/v5/proper/%s"
defer func() { baseURL = orig }()
t.Setenv("XDG_CACHE_HOME", t.TempDir())
_, err := Load("2026-07-22", "en", false)
if err == nil {
t.Fatal("expected error on 404, got nil")
}
cachePath := filepath.Join(liturgy.CacheDir(), "2026-07-22.trad.en.json")
if _, statErr := os.Stat(cachePath); !os.IsNotExist(statErr) {
t.Errorf("cache file should not exist after a 404 (stat err = %v)", statErr)
}
}
// TestLoadOfflineReadsCache exercises Load's offline path against a
// pre-written cache file (as an earlier online Load, or 'lectio update',
// would have left behind) -- no network access at all.
func TestLoadOfflineReadsCache(t *testing.T) {
body, err := os.ReadFile("testdata/2026-07-22.json")
if err != nil {
t.Fatal(err)
}
dir := t.TempDir()
t.Setenv("XDG_CACHE_HOME", dir)
cacheDir := filepath.Join(dir, "lectio")
if err := os.MkdirAll(cacheDir, 0o755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(cacheDir, "2026-07-22.trad.pl.json"), body, 0o644); err != nil {
t.Fatal(err)
}
secs, err := Load("2026-07-22", "pl", true)
if err != nil {
t.Fatalf("Load offline: %v", err)
}
if len(secs) == 0 {
t.Fatal("Load offline returned no sections")
}
}
// TestLoadOfflineMissingCacheErrors checks Load's offline path errors
// clearly (mentioning the missing cache) rather than trying the network,
// when nothing has been cached yet for that (date, lang).
func TestLoadOfflineMissingCacheErrors(t *testing.T) {
t.Setenv("XDG_CACHE_HOME", t.TempDir())
_, err := Load("2026-07-22", "pl", true)
if err == nil {
t.Fatal("expected error for missing cache, got nil")
}
msg := strings.ToLower(err.Error())
if !strings.Contains(msg, "no cached") {
t.Errorf("error %q should mention no cached propers", err.Error())
}
}
|