aboutsummaryrefslogtreecommitdiff
path: root/internal/tui/tui_test.go
blob: 85a8175f95217b1cc474b3f5442a303340d624db (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
package tui

import (
	"errors"
	"strings"
	"testing"

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

func TestVersionCycle(t *testing.T) {
	m := New(config.Config{Versions: []string{"bt", "wuj", "vul"}, DefaultVersion: "bt"}, "", "")
	if m.version() != "bt" {
		t.Fatalf("start = %q", m.version())
	}
	m = m.cycleVersion(+1)
	if m.version() != "wuj" {
		t.Errorf("after tab = %q", m.version())
	}
	m = m.cycleVersion(-1)
	if m.version() != "bt" {
		t.Errorf("after shift-tab = %q", m.version())
	}
}

func TestOfflineDropsBT(t *testing.T) {
	m := New(config.Config{Versions: []string{"bt", "wuj", "vul"}, DefaultVersion: "bt", Offline: true}, "", "")
	for _, v := range m.versions {
		if v == "bt" {
			t.Error("offline model kept bt")
		}
	}
}

// TestBodyLinesLocalisesMessages checks that the loading/no-readings/error
// messages follow cfg.UILanguage.
func TestBodyLinesLocalisesMessages(t *testing.T) {
	en := Model{cfg: config.Config{UILanguage: "en"}, loading: true}
	if lines := en.bodyLines(80); len(lines) == 0 || !strings.Contains(lines[0], "loading") {
		t.Errorf("en loading bodyLines = %v, want it to contain %q", lines, "loading")
	}

	pl := Model{cfg: config.Config{UILanguage: "pl"}, loading: true}
	if lines := pl.bodyLines(80); len(lines) == 0 || !strings.Contains(lines[0], "ładowanie") {
		t.Errorf("pl loading bodyLines = %v, want it to contain %q", lines, "ładowanie")
	}

	enEmpty := Model{cfg: config.Config{UILanguage: "en"}, date: "2026-07-22"}
	if lines := enEmpty.bodyLines(80); len(lines) == 0 || !strings.Contains(lines[0], "no readings for") {
		t.Errorf("en no-readings bodyLines = %v, want it to contain %q", lines, "no readings for")
	}
}

// TestBodyLinesSingleSpaceConcatenation is a regression test for the
// i18n-migration whitespace bug: i18n.UI.NoReadingsFor/ErrorPrefix must
// carry exactly one trailing space, since bodyLines concatenates the date/
// error string directly onto them with no separator of its own -- the
// pre-i18n TUI code produced "błąd: " + err / "brak czytań na " + date (one
// space), and the i18n fields regressed to two.
func TestBodyLinesSingleSpaceConcatenation(t *testing.T) {
	enEmpty := Model{cfg: config.Config{UILanguage: "en"}, date: "2026-07-22"}
	lines := enEmpty.bodyLines(80)
	if len(lines) == 0 || !strings.Contains(lines[0], "no readings for 2026-07-22") {
		t.Errorf("en no-readings bodyLines[0] = %q, want it to contain %q (single space)", lines[0], "no readings for 2026-07-22")
	}
	if strings.Contains(lines[0], "for  2026") {
		t.Errorf("en no-readings bodyLines[0] = %q, has 2+ spaces before the date", lines[0])
	}

	plEmpty := Model{cfg: config.Config{UILanguage: "pl"}, date: "2026-07-22"}
	lines = plEmpty.bodyLines(80)
	if len(lines) == 0 || !strings.Contains(lines[0], "brak czytań na 2026-07-22") {
		t.Errorf("pl no-readings bodyLines[0] = %q, want it to contain %q (single space)", lines[0], "brak czytań na 2026-07-22")
	}

	errText := "boom"
	enErr := Model{cfg: config.Config{UILanguage: "en"}, err: errors.New(errText)}
	lines = enErr.bodyLines(80)
	if len(lines) == 0 || !strings.Contains(lines[0], "error: "+errText) {
		t.Errorf("en error bodyLines[0] = %q, want it to contain %q (single space)", lines[0], "error: "+errText)
	}
	if strings.Contains(lines[0], "error:  ") {
		t.Errorf("en error bodyLines[0] = %q, has 2+ spaces after \"error:\"", lines[0])
	}

	plErr := Model{cfg: config.Config{UILanguage: "pl"}, err: errors.New(errText)}
	lines = plErr.bodyLines(80)
	if len(lines) == 0 || !strings.Contains(lines[0], "błąd: "+errText) {
		t.Errorf("pl error bodyLines[0] = %q, want it to contain %q (single space)", lines[0], "błąd: "+errText)
	}
	if strings.Contains(lines[0], "błąd:  ") {
		t.Errorf("pl error bodyLines[0] = %q, has 2+ spaces after \"błąd:\"", lines[0])
	}
}

// TestBodyLinesLocalisesHeading checks that a modern-lectionary section
// heading's label word follows cfg.UILanguage while the citation stays
// exactly as scraped (render.LocalizeHeading, brief §3b).
func TestBodyLinesLocalisesHeading(t *testing.T) {
	sec := liturgy.Section{Heading: "Ewangelia (J 20, 1. 11-18)", PartID: "ewangelia"}

	en := Model{cfg: config.Config{UILanguage: "en", Lectionary: "new"}, sections: []liturgy.Section{sec}}
	body := strings.Join(en.bodyLines(80), "\n")
	if !strings.Contains(body, "Gospel (J 20, 1. 11-18)") {
		t.Errorf("en bodyLines missing localised heading: %q", body)
	}

	pl := Model{cfg: config.Config{UILanguage: "pl", Lectionary: "new"}, sections: []liturgy.Section{sec}}
	body = strings.Join(pl.bodyLines(80), "\n")
	if !strings.Contains(body, "Ewangelia (J 20, 1. 11-18)") {
		t.Errorf("pl bodyLines missing unchanged heading: %q", body)
	}
}

// TestFooterKeysLocalised checks the footer keybar text follows
// cfg.UILanguage.
func TestFooterKeysLocalised(t *testing.T) {
	en := Model{cfg: config.Config{UILanguage: "en"}, date: "2026-07-22"}
	if out := en.View(); !strings.Contains(out, "q quit") {
		t.Errorf("en View() footer missing %q: %q", "q quit", out)
	}

	pl := Model{cfg: config.Config{UILanguage: "pl"}, date: "2026-07-22"}
	if out := pl.View(); !strings.Contains(out, "q wyjście") {
		t.Errorf("pl View() footer missing %q: %q", "q wyjście", out)
	}
}