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
|
package render
import (
"fmt"
"strings"
"testing"
"github.com/charmbracelet/lipgloss"
"github.com/muesli/termenv"
"github.com/humdrum-tiv/dots-cli/internal/api"
"github.com/humdrum-tiv/dots-cli/internal/day"
)
func TestGridStructure(t *testing.T) {
rowLabels := []string{"0:00", "4:00", "8:00", "12:00", "16:00", "20:00"}
for _, blockSize := range []int{15, 30, 60} {
t.Run(fmt.Sprintf("blockSize=%d", blockSize), func(t *testing.T) {
d := &api.DayData{
BlockSize: blockSize,
Types: []day.ActivityType{
{ID: "t1", Name: "archer", Color: "#c04000"},
},
Blocks: map[int]string{0: "t1"},
PlanBlocks: map[int]string{1: "t1"},
}
out := Grid(d, 0)
for _, label := range rowLabels {
if !strings.Contains(out, label) {
t.Errorf("blockSize %d: missing row label %q in output:\n%s", blockSize, label, out)
}
}
if !strings.Contains(out, "archer") {
t.Errorf("blockSize %d: missing legend entry for %q in output:\n%s", blockSize, "archer", out)
}
gotRows := strings.Count(strings.TrimRight(out, "\n"), "\n") - 1 // minus blank line before legend
if gotRows != 6 {
t.Errorf("blockSize %d: expected 6 rows, got %d", blockSize, gotRows)
}
})
}
}
// TestGridCurrentSlotNoAnsiLeak guards against nested lipgloss.Render calls
// mangling inner ANSI escape sequences (the current-slot underline used to
// re-render an already-styled glyph, corrupting its color code).
func TestGridCurrentSlotNoAnsiLeak(t *testing.T) {
orig := lipgloss.ColorProfile()
lipgloss.SetColorProfile(termenv.TrueColor)
defer lipgloss.SetColorProfile(orig)
d := &api.DayData{
BlockSize: 60,
Types: []day.ActivityType{
{ID: "t1", Name: "archer", Color: "#008cb3"},
},
Blocks: map[int]string{0: "t1"},
}
out := Grid(d, 0)
needle := "[38;2"
for i := 0; i+len(needle) <= len(out); i++ {
if out[i:i+len(needle)] == needle {
if i == 0 || out[i-1] != '\x1b' {
t.Fatalf("found unescaped %q at byte %d (not preceded by ESC) in output:\n%q", needle, i, out)
}
}
}
}
|