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) } } } }