aboutsummaryrefslogtreecommitdiff
path: root/internal/readings/readings_test.go
blob: c9e92cd0d9c0237ebc0a2a34cdf125b037b16298 (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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package readings

import (
	"net/http"
	"net/http/httptest"
	"os"
	"path/filepath"
	"strings"
	"testing"

	"github.com/lukaszkasprzak/lectio/internal/config"
	"github.com/lukaszkasprzak/lectio/internal/liturgy"
)

func sectionsForFilterTests() []liturgy.Section {
	return []liturgy.Section{
		{PartID: "pierwsze_czytanie", Heading: "1. czytanie"},
		{PartID: "psalm", Heading: "Psalm"},
		{PartID: "ewangelia", Heading: "Ewangelia"},
	}
}

func TestFilterPartsGospelOnly(t *testing.T) {
	secs := sectionsForFilterTests()
	got := filterParts(secs, config.Config{}, false)

	if len(got) != 1 {
		t.Fatalf("got %d sections, want 1: %+v", len(got), got)
	}
	if got[0].PartID != "ewangelia" {
		t.Errorf("got PartID %q, want ewangelia", got[0].PartID)
	}
}

func TestFilterPartsAll(t *testing.T) {
	secs := sectionsForFilterTests()
	cfg := config.Config{
		Lectionary: "new",
		Parts: map[string]map[string]bool{
			"new": {"psalm": false},
		},
	}
	got := filterParts(secs, cfg, true)

	if len(got) != 2 {
		t.Fatalf("got %d sections, want 2: %+v", len(got), got)
	}
	for _, s := range got {
		if s.PartID == "psalm" {
			t.Errorf("psalm should have been filtered out: %+v", got)
		}
	}
	ids := map[string]bool{got[0].PartID: true, got[1].PartID: true}
	if !ids["pierwsze_czytanie"] || !ids["ewangelia"] {
		t.Errorf("got %+v, want pierwsze_czytanie and ewangelia", got)
	}
}

func TestFilterPartsTraditionalAllReadingsOnly(t *testing.T) {
	secs := []liturgy.Section{
		{PartID: "introitus", Heading: "Introit"},
		{PartID: "oratio", Heading: "Kolekta"},
		{PartID: "lectio", Heading: "Lekcja"},
		{PartID: "graduale", Heading: "Graduał"},
		{PartID: "evangelium", Heading: "Ewangelia"},
		{PartID: "offertorium", Heading: "Ofiarowanie"},
		{PartID: "secreta", Heading: "Sekreta"},
		{PartID: "communio", Heading: "Komunia"},
		{PartID: "postcommunio", Heading: "Pokomunia"},
	}
	cfg := config.Config{Lectionary: "traditional"}
	got := filterParts(secs, cfg, true)

	if len(got) != 2 {
		t.Fatalf("got %d sections, want 2: %+v", len(got), got)
	}
	if got[0].PartID != "lectio" || got[1].PartID != "evangelium" {
		t.Errorf("got %+v, want [lectio evangelium] in order", got)
	}
}

func TestLoadModernRoutes(t *testing.T) {
	html, err := os.ReadFile("../liturgy/testdata/2026-07-22.html")
	if err != nil {
		t.Fatal(err)
	}
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Write(html)
	}))
	defer srv.Close()
	liturgy.SetBaseURL(srv.URL + "/liturgia/%s/Ewangelia")
	t.Setenv("XDG_CACHE_HOME", t.TempDir())

	cfg := config.Config{Lectionary: "new"}
	secs, info, err := Load(cfg, Options{Date: "2026-07-22", All: true})
	if err != nil {
		t.Fatalf("Load: %v", err)
	}

	found := false
	for _, s := range secs {
		if s.PartID == "ewangelia" {
			found = true
		}
	}
	if !found {
		t.Errorf("no gospel section (PartID=ewangelia) found in %+v", secs)
	}
	if !strings.Contains(info.Name, "Marii Magdaleny") {
		t.Errorf("DayInfo.Name = %q, want it to contain %q", info.Name, "Marii Magdaleny")
	}
}

// TestLoadTraditionalOfflineErrorsWithoutCache exercises the (formerly
// unsupported) traditional+offline path when nothing has been cached yet
// for that date/lang: it must fail clearly rather than silently falling
// back to the network or to the modern lectionary's sigla store.
func TestLoadTraditionalOfflineErrorsWithoutCache(t *testing.T) {
	t.Setenv("XDG_CACHE_HOME", t.TempDir())

	cfg := config.Config{Lectionary: "traditional", TraditionalLang: "pl"}
	_, _, err := Load(cfg, Options{Date: "2026-07-22", Offline: true})
	if err == nil {
		t.Fatal("expected error, got nil")
	}
	msg := strings.ToLower(err.Error())
	if !strings.Contains(msg, "no cached") {
		t.Errorf("error %q should mention no cached propers", err.Error())
	}
}

// TestLoadTraditionalOfflineReadsCache is the positive counterpart: once a
// prior online Load (or 'lectio update') has cached a date's traditional
// propers, Load(offline=true) must serve them from disk, no network
// involved.
func TestLoadTraditionalOfflineReadsCache(t *testing.T) {
	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)
	}
	body, err := os.ReadFile("../tradlit/testdata/2026-07-22.json")
	if 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)
	}

	cfg := config.Config{Lectionary: "traditional", TraditionalLang: "pl"}
	secs, info, err := Load(cfg, Options{Date: "2026-07-22", Offline: true, All: true})
	if err != nil {
		t.Fatalf("Load: %v", err)
	}
	if len(secs) == 0 {
		t.Error("expected traditional offline sections, got none")
	}
	if info.Name != "St. Mary Magdalene" {
		t.Errorf("DayInfo.Name = %q, want %q", info.Name, "St. Mary Magdalene")
	}
}