aboutsummaryrefslogtreecommitdiff
path: root/internal/tradlit/tradlit_test.go
blob: cd2cc837e321f23e8d1056c6695e53c4e4953760 (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
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())
	}
}