aboutsummaryrefslogtreecommitdiff
path: root/internal/readings/readings_test.go
blob: 1674d854acd6767b5d45ec0bc53f5d360fe46901 (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
package readings

import (
	"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)
	}
}

// TestLoadModern computes the Ordinary Form day offline: the gospel section is
// present and the header carries the celebration name (English by default,
// since the universal sanctoral is authored in English).
func TestLoadModern(t *testing.T) {
	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, "Mary Magdalene") {
		t.Errorf("DayInfo.Name = %q, want it to contain %q", info.Name, "Mary Magdalene")
	}
}

// TestSundayRankIsDisplayOnly guards the Ordinary Form's Sunday display rank.
// Sunday is its own category in the 1969 Universal Norms' Table of Liturgical
// Days -- never a solemnity -- so an ordinary "Nth Sunday of <season>" temporal
// day (Ordinary Time, Advent, Lent, the Easter season, Christmas time; this
// also covers Palm Sunday) must report "sunday". A NAMED solemnity of the Lord
// that happens to fall on a Sunday (Easter Sunday itself, Pentecost) is a
// genuine solemnity and must keep reporting "solemnity"; a feast of the Lord
// (Holy Family) must keep reporting "feast". This is display-only: it must
// never touch the engine's internal precedence, so the 1962 form (which has no
// such Sunday category -- Sundays report their class exactly as before) is
// asserted unchanged too. Dates are the ones from the original bug report,
// plus the Easter/Pentecost/Holy Family dates they imply for the same
// liturgical year.
func TestSundayRankIsDisplayOnly(t *testing.T) {
	cases := []struct {
		date, lect, wantRank, why string
	}{
		{"2026-08-09", "new", "sunday", "19th Sunday in Ordinary Time"},
		{"2026-11-29", "new", "sunday", "1st Sunday of Advent"},
		{"2027-03-28", "new", "solemnity", "Easter Sunday itself"},
		{"2027-05-16", "new", "solemnity", "Pentecost"},
		{"2026-12-27", "new", "feast", "Holy Family"},
		{"2026-08-09", "traditional", "class-2", "1962 Sunday after Pentecost"},
		{"2026-11-29", "traditional", "class-1", "1962 1st Sunday of Advent"},
	}
	for _, c := range cases {
		cfg := config.Config{Lectionary: c.lect}
		_, info, err := Load(cfg, Options{Date: c.date, All: true})
		if err != nil {
			t.Fatalf("%s (%s, %s): Load: %v", c.date, c.lect, c.why, err)
		}
		if info.Rank != c.wantRank {
			t.Errorf("%s (%s, %s): Rank = %q, want %q (name=%q)", c.date, c.lect, c.why, info.Rank, c.wantRank, info.Name)
		}
	}
}

// TestLoadTraditional computes the Extraordinary Form day offline: it never
// needs the network, and yields the EF epistle+gospel with a header name.
func TestLoadTraditional(t *testing.T) {
	cfg := config.Config{Lectionary: "traditional"}
	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 == "evangelium" {
			found = true
		}
	}
	if !found {
		t.Errorf("no EF gospel section (PartID=evangelium) found in %+v", secs)
	}
	if info.Name == "" {
		t.Error("DayInfo.Name empty for a traditional feast day")
	}
}