1package tui
2
3import (
4 "bytes"
5 "strings"
6 "testing"
7)
8
9func TestDetectTrueColor(t *testing.T) {
10 tests := []struct {
11 name string
12 term string
13 colorTerm string
14 want bool
15 }{
16 {name: "COLORTERM truecolor", term: "screen", colorTerm: "truecolor", want: true},
17 {name: "COLORTERM 24bit", term: "screen", colorTerm: "24bit", want: true},
18 {name: "direct TERM", term: "xterm-direct", want: true},
19 {name: "256 color TERM", term: "xterm-256color", want: false},
20 }
21 for _, tt := range tests {
22 t.Run(tt.name, func(t *testing.T) {
23 if got := DetectTrueColor(tt.term, tt.colorTerm); got != tt.want {
24 t.Fatalf("DetectTrueColor(%q, %q) = %v, want %v", tt.term, tt.colorTerm, got, tt.want)
25 }
26 })
27 }
28}
29
30func TestDetectColorDepth(t *testing.T) {
31 for _, tt := range []struct {
32 term, colorTerm string
33 want ColorDepth
34 }{
35 {"xterm", "", ColorDepthANSI16},
36 {"xterm-256color", "", ColorDepthIndexed256},
37 {"screen", "truecolor", ColorDepthTrueColor},
38 } {
39 if got := DetectColorDepth(tt.term, tt.colorTerm); got != tt.want {
40 t.Fatalf("DetectColorDepth(%q, %q) = %v, want %v", tt.term, tt.colorTerm, got, tt.want)
41 }
42 }
43}
44
45func terminalTestProfile(depth ColorDepth) TerminalProfile {
46 profile := TerminalProfile{
47 Foreground: ColorRGB(220, 210, 200),
48 Background: ColorRGB(12, 18, 24),
49 HasForeground: true,
50 HasBackground: true,
51 Depth: depth,
52 }
53 profile.Palette[10] = ColorRGB(20, 220, 80)
54 profile.Palette[12] = ColorRGB(40, 100, 240)
55 profile.Palette[13] = ColorRGB(220, 70, 210)
56 profile.PaletteKnown = 1<<10 | 1<<12 | 1<<13
57 return profile
58}
59
60func TestTerminalThemeUsesTerminalDefaultsAndPaletteSlots(t *testing.T) {
61 th := TerminalTheme(terminalTestProfile(ColorDepthTrueColor))
62 if th.Background != nil {
63 t.Fatal("terminal theme painted a full-row background")
64 }
65 if th.FG != TerminalDefault() || th.Accent != TerminalPaletteSlot(12) {
66 t.Fatalf("terminal roles = fg %#v accent %#v", th.FG, th.Accent)
67 }
68 if got := th.FGColor(th.FG, "x"); got != "\x1b[39mx\x1b[0m" {
69 t.Fatalf("default foreground = %q", got)
70 }
71 if got := th.FGColor(th.Accent, "x"); !strings.Contains(got, "\x1b[38;2;40;100;240m") {
72 t.Fatalf("accent did not use reported palette: %q", got)
73 }
74}
75
76func TestTerminalThemeUnknownProfileUsesANSI(t *testing.T) {
77 th := TerminalTheme(TerminalProfile{Depth: ColorDepthANSI16})
78 if th.FG == Dark.FG || th.FG == Light.FG {
79 t.Fatal("unknown auto profile selected a fixed built-in theme")
80 }
81 if got := th.FGColor(th.Accent, "x"); got != "\x1b[94mx\x1b[0m" {
82 t.Fatalf("terminal palette fallback = %q", got)
83 }
84}
85
86func TestTerminalPaletteSlotsDoNotAliasExplicitIndexedColors(t *testing.T) {
87 profile := terminalTestProfile(ColorDepthTrueColor)
88 th := TerminalTheme(profile)
89 if got := th.FGColor(TerminalPaletteSlot(12), "x"); !strings.Contains(got, "40;100;240") {
90 t.Fatalf("terminal slot = %q", got)
91 }
92 if got := th.FGColor(Color256(12), "x"); !strings.Contains(got, "0;0;255") {
93 t.Fatalf("explicit xterm index adopted terminal palette: %q", got)
94 }
95}
96
97func TestTerminalThemeRendererInvalidationDoesNotClearScrollback(t *testing.T) {
98 t.Setenv("TERM_PROGRAM", "")
99 var buf bytes.Buffer
100 r := NewRenderer(&buf)
101 r.Resize(20, 2)
102 buf.Reset()
103 r.SetTheme(TerminalTheme(terminalTestProfile(ColorDepthTrueColor)))
104 r.Invalidate()
105 if strings.Contains(buf.String(), SeqClearScrollback) {
106 t.Fatalf("theme invalidation cleared scrollback: %q", buf.String())
107 }
108}