1package theme
2
3import (
4 "image/color"
5 "testing"
6)
7
8func TestNewDark(t *testing.T) {
9 s := New(true)
10
11 if !s.Dark {
12 t.Error("New(true).Dark = false, want true")
13 }
14}
15
16func TestNewLight(t *testing.T) {
17 s := New(false)
18
19 if s.Dark {
20 t.Error("New(false).Dark = true, want false")
21 }
22}
23
24func TestSemanticColoursNotNil(t *testing.T) {
25 t.Parallel()
26
27 for _, isDark := range []bool{true, false} {
28 name := "dark"
29 if !isDark {
30 name = "light"
31 }
32
33 t.Run(name, func(t *testing.T) {
34 t.Parallel()
35
36 s := New(isDark)
37 colours := map[string]color.Color{
38 "Accent": s.Accent,
39 "Secondary": s.Secondary,
40 "Warning": s.Warning,
41 "Confirm": s.Confirm,
42 }
43 for label, c := range colours {
44 if c == nil {
45 t.Errorf("%s is nil", label)
46 }
47 }
48 })
49 }
50}
51
52func TestHuhThemeReturnsBothPalettes(t *testing.T) {
53 t.Parallel()
54
55 for _, isDark := range []bool{true, false} {
56 name := "dark"
57 if !isDark {
58 name = "light"
59 }
60 t.Run(name, func(t *testing.T) {
61 t.Parallel()
62
63 s := New(isDark)
64 // The ThemeFunc is called with an arbitrary bool; it
65 // should always use the isDark captured at build time.
66 styles := s.Huh.Theme(isDark)
67 if styles == nil {
68 t.Fatal("Theme() returned nil Styles")
69 }
70 })
71 }
72}
73
74func TestHuhThemeIgnoresCallbackParameter(t *testing.T) {
75 t.Parallel()
76
77 // Build a dark theme, then call the ThemeFunc with isDark=false.
78 // The returned styles should still reflect the dark palette
79 // because the callback parameter is intentionally ignored.
80 dark := New(true)
81 light := New(false)
82
83 fromDark := dark.Huh.Theme(false) // pass false, should still get dark
84 fromLight := light.Huh.Theme(true) // pass true, should still get light
85
86 if fromDark == nil {
87 t.Fatal("Theme(false) on dark Styles returned nil")
88 }
89 if fromLight == nil {
90 t.Fatal("Theme(true) on light Styles returned nil")
91 }
92
93 // Verify the title colour matches the expected palette accent,
94 // not the opposite palette. We compare the rendered output of
95 // the title style — if huh's isDark parameter were used instead
96 // of ours, the foreground colour would differ.
97 //
98 // Skip when lipgloss strips ANSI (e.g. TERM=dumb, NO_COLOR),
99 // because both renders would collapse to plain "x".
100 darkTitle := fromDark.Focused.Title.Render("x")
101 lightTitle := fromLight.Focused.Title.Render("x")
102 if darkTitle == "x" && lightTitle == "x" {
103 t.Skip("colour output unavailable; cannot compare palette rendering")
104 }
105 if darkTitle == lightTitle {
106 t.Error("dark and light huh themes produced identical title rendering; isDark parameter may not be ignored")
107 }
108}
109
110func TestPickerStylesEmptyDirectoryMessage(t *testing.T) {
111 t.Parallel()
112
113 s := New(true)
114 got := s.Picker.EmptyDirectory.Value()
115 want := "No files in this directory."
116 if got != want {
117 t.Errorf("EmptyDirectory string = %q, want %q", got, want)
118 }
119}
120
121func TestHelpStylesNoDimText(t *testing.T) {
122 t.Parallel()
123
124 s := New(true)
125
126 // ShortDesc and FullDesc should have no foreground set (they
127 // inherit the terminal default). We verify by checking that the
128 // style renders without injecting a colour sequence.
129 plain := "test"
130 if got := s.Help.ShortDesc.Render(plain); got != plain {
131 t.Errorf("ShortDesc styled unexpectedly: got %q, want %q", got, plain)
132 }
133 if got := s.Help.FullDesc.Render(plain); got != plain {
134 t.Errorf("FullDesc styled unexpectedly: got %q, want %q", got, plain)
135 }
136}
137
138func TestCursorConstant(t *testing.T) {
139 t.Parallel()
140
141 if Cursor != "▸ " {
142 t.Errorf("Cursor = %q, want %q", Cursor, "▸ ")
143 }
144}