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
|
package cli
import (
"bytes"
"testing"
"github.com/lukaszkasprzak/lectio/internal/config"
)
// TestPagerRequested exercises pagerRequested's precedence: --no-pager beats
// -P beats a non-empty cfg.Pager; with nothing set, paging is off.
func TestPagerRequested(t *testing.T) {
cases := []struct {
name string
pagerFlag, noPager bool
cfgPager string
want bool
}{
{"nothing set", false, false, "", false},
{"cfg.Pager set alone", false, false, "less -R", true},
{"-P alone", true, false, "", true},
{"-P overrides empty cfg", true, false, "", true},
{"--no-pager beats -P", true, true, "", false},
{"--no-pager beats cfg.Pager", false, true, "less -R", false},
{"--no-pager beats both", true, true, "less -R", false},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
cfg := config.Config{Pager: c.cfgPager}
got := pagerRequested(c.pagerFlag, c.noPager, cfg)
if got != c.want {
t.Errorf("pagerRequested(%v, %v, Pager=%q) = %v, want %v",
c.pagerFlag, c.noPager, c.cfgPager, got, c.want)
}
})
}
}
// TestPagerCommand exercises pagerCommand's fallback chain: cfg.Pager wins,
// then $PAGER, then the "less -R" built-in default. No exec happens here.
func TestPagerCommand(t *testing.T) {
t.Run("cfg.Pager set", func(t *testing.T) {
t.Setenv("PAGER", "most")
cfg := config.Config{Pager: "more -c"}
got := pagerCommand(cfg)
want := []string{"more", "-c"}
if !equalStrings(got, want) {
t.Errorf("pagerCommand = %v, want %v", got, want)
}
})
t.Run("cfg empty, PAGER set", func(t *testing.T) {
t.Setenv("PAGER", "most")
cfg := config.Config{}
got := pagerCommand(cfg)
want := []string{"most"}
if !equalStrings(got, want) {
t.Errorf("pagerCommand = %v, want %v", got, want)
}
})
t.Run("both empty falls back to less -R", func(t *testing.T) {
t.Setenv("PAGER", "")
cfg := config.Config{}
got := pagerCommand(cfg)
want := []string{"less", "-R"}
if !equalStrings(got, want) {
t.Errorf("pagerCommand = %v, want %v", got, want)
}
})
}
func equalStrings(a, b []string) bool {
if len(a) != len(b) {
return false
}
for i := range a {
if a[i] != b[i] {
return false
}
}
return true
}
// TestIsTerminalWriterBuffer confirms a bytes.Buffer (what every test uses
// for stdout) is never treated as a terminal, so Run never pages in tests.
func TestIsTerminalWriterBuffer(t *testing.T) {
if isTerminalWriter(&bytes.Buffer{}) {
t.Error("isTerminalWriter(&bytes.Buffer{}) = true, want false")
}
}
// TestPagerFlagDoesNotBreakBufferOutput confirms -P set against a
// bytes.Buffer stdout (non-TTY) still writes plainly -- pagerRequested may
// be true, but isTerminalWriter gates it off, so Run's existing dispatch
// runs unchanged.
func TestPagerFlagDoesNotBreakBufferOutput(t *testing.T) {
t.Setenv("XDG_CONFIG_HOME", t.TempDir())
var out, errb bytes.Buffer
// (The former -o/--offline flag is gone: the daily view is always offline.)
code := Run([]string{"-P", "-l", "trad", "2026-07-22"}, nil, &out, &errb)
if code != 0 && code != 1 {
t.Fatalf("-P run code=%d (stderr=%q)", code, errb.String())
}
// The key assertion: no hang, no panic, output goes to the buffer
// directly (a real pager exec would have blocked/failed differently).
if out.Len() == 0 && code == 0 {
t.Errorf("-P run produced no stdout output on success")
}
}
|