aboutsummaryrefslogtreecommitdiff
path: root/internal/tradlit/tradlit_test.go
blob: 8aa46eba0789dae73473751a4867dfd559296a3f (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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
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, info, 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 info.Name != "St. Mary Magdalene" {
		t.Errorf("Load DayInfo.Name = %q, want %q", info.Name, "St. Mary Magdalene")
	}
	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, info, 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")
	}
	if info.Name != "St. Mary Magdalene" {
		t.Errorf("Load offline DayInfo.Name = %q, want %q", info.Name, "St. Mary Magdalene")
	}
}

// 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())
	}
}