bluesky viewer in the terminal
1package ui
2
3import (
4 "fmt"
5 "os"
6 "strings"
7 "testing"
8
9 "github.com/stormlightlabs/skypanel/cli/internal/utils"
10)
11
12func TestSuccess(t *testing.T) {
13 result := success("test message")
14 if !strings.Contains(result, "✓") {
15 t.Errorf("success() should contain checkmark, got: %s", result)
16 }
17 if !strings.Contains(result, "test message") {
18 t.Errorf("success() should contain message, got: %s", result)
19 }
20}
21
22func TestErrorMsg(t *testing.T) {
23 result := errorMsg("test error")
24 if !strings.Contains(result, "✗") {
25 t.Errorf("errorMsg() should contain X mark, got: %s", result)
26 }
27 if !strings.Contains(result, "test error") {
28 t.Errorf("errorMsg() should contain message, got: %s", result)
29 }
30}
31
32func TestWarning(t *testing.T) {
33 result := warning("test warning")
34 if !strings.Contains(result, "⚠") {
35 t.Errorf("warning() should contain warning symbol, got: %s", result)
36 }
37 if !strings.Contains(result, "test warning") {
38 t.Errorf("warning() should contain message, got: %s", result)
39 }
40}
41
42func TestInfo(t *testing.T) {
43 result := info("test info")
44 if !strings.Contains(result, "ℹ") {
45 t.Errorf("info() should contain info symbol, got: %s", result)
46 }
47 if !strings.Contains(result, "test info") {
48 t.Errorf("info() should contain message, got: %s", result)
49 }
50}
51
52func TestTitle(t *testing.T) {
53 result := title("test title")
54 if !strings.Contains(result, "test title") {
55 t.Errorf("title() should contain message, got: %s", result)
56 }
57}
58
59func TestSubtitle(t *testing.T) {
60 result := subtitle("test subtitle")
61 if !strings.Contains(result, "test subtitle") {
62 t.Errorf("subtitle() should contain message, got: %s", result)
63 }
64}
65
66func TestBox(t *testing.T) {
67 result := box("test content")
68 if !strings.Contains(result, "test content") {
69 t.Errorf("box() should contain message, got: %s", result)
70 }
71}
72
73func TestErrorBox(t *testing.T) {
74 result := errorBox("test error content")
75 if !strings.Contains(result, "test error content") {
76 t.Errorf("errorBox() should contain message, got: %s", result)
77 }
78}
79
80func TestUnexportedFunctionsWithEmptyString(t *testing.T) {
81 tests := []struct {
82 name string
83 fn func(string) string
84 expectNonEmpty bool
85 }{
86 {"success", success, true}, // Has icon prefix
87 {"errorMsg", errorMsg, true}, // Has icon prefix
88 {"warning", warning, true}, // Has icon prefix
89 {"info", info, true}, // Has icon prefix
90 {"title", title, false}, // No icon, may return empty
91 {"subtitle", subtitle, false}, // No icon, may return empty
92 {"box", box, true}, // Has border
93 {"errorBox", errorBox, true}, // Has border
94 }
95
96 for _, tt := range tests {
97 t.Run(tt.name, func(t *testing.T) {
98 result := tt.fn("")
99 if tt.expectNonEmpty && result == "" {
100 t.Errorf("%s(\"\") returned empty string, expected styled content", tt.name)
101 }
102 })
103 }
104}
105
106func TestSuccessPrint(t *testing.T) {
107 output := utils.CaptureOutput(func() {
108 Success("test %s", "message")
109 })
110 if !strings.Contains(output, "test message") {
111 t.Errorf("Success() should print message, got: %s", output)
112 }
113 if !strings.Contains(output, "✓") {
114 t.Errorf("Success() should print checkmark, got: %s", output)
115 }
116}
117
118func TestSuccessln(t *testing.T) {
119 output := utils.CaptureOutput(func() {
120 Successln("test %s", "message")
121 })
122 if !strings.Contains(output, "test message") {
123 t.Errorf("Successln() should print message, got: %s", output)
124 }
125 if !strings.HasSuffix(output, "\n") {
126 t.Errorf("Successln() should end with newline, got: %s", output)
127 }
128}
129
130func TestErrorPrint(t *testing.T) {
131 output := utils.CaptureOutput(func() {
132 Error("test %s", "error")
133 })
134 if !strings.Contains(output, "test error") {
135 t.Errorf("Error() should print message, got: %s", output)
136 }
137 if !strings.Contains(output, "✗") {
138 t.Errorf("Error() should print X mark, got: %s", output)
139 }
140}
141
142func TestErrorln(t *testing.T) {
143 output := utils.CaptureOutput(func() {
144 Errorln("test %s", "error")
145 })
146 if !strings.Contains(output, "test error") {
147 t.Errorf("Errorln() should print message, got: %s", output)
148 }
149 if !strings.HasSuffix(output, "\n") {
150 t.Errorf("Errorln() should end with newline, got: %s", output)
151 }
152}
153
154func TestWarningPrint(t *testing.T) {
155 output := utils.CaptureOutput(func() {
156 Warning("test %s", "warning")
157 })
158 if !strings.Contains(output, "test warning") {
159 t.Errorf("Warning() should print message, got: %s", output)
160 }
161 if !strings.Contains(output, "⚠") {
162 t.Errorf("Warning() should print warning symbol, got: %s", output)
163 }
164}
165
166func TestWarningln(t *testing.T) {
167 output := utils.CaptureOutput(func() {
168 Warningln("test %s", "warning")
169 })
170 if !strings.Contains(output, "test warning") {
171 t.Errorf("Warningln() should print message, got: %s", output)
172 }
173 if !strings.HasSuffix(output, "\n") {
174 t.Errorf("Warningln() should end with newline, got: %s", output)
175 }
176}
177
178func TestInfoPrint(t *testing.T) {
179 output := utils.CaptureOutput(func() {
180 Info("test %s", "info")
181 })
182 if !strings.Contains(output, "test info") {
183 t.Errorf("Info() should print message, got: %s", output)
184 }
185 if !strings.Contains(output, "ℹ") {
186 t.Errorf("Info() should print info symbol, got: %s", output)
187 }
188}
189
190func TestInfoln(t *testing.T) {
191 output := utils.CaptureOutput(func() {
192 Infoln("test %s", "info")
193 })
194 if !strings.Contains(output, "test info") {
195 t.Errorf("Infoln() should print message, got: %s", output)
196 }
197 if !strings.HasSuffix(output, "\n") {
198 t.Errorf("Infoln() should end with newline, got: %s", output)
199 }
200}
201
202func TestTitlePrint(t *testing.T) {
203 output := utils.CaptureOutput(func() {
204 Title("test %s", "title")
205 })
206 if !strings.Contains(output, "test title") {
207 t.Errorf("Title() should print message, got: %s", output)
208 }
209}
210
211func TestTitleln(t *testing.T) {
212 output := utils.CaptureOutput(func() {
213 Titleln("test %s", "title")
214 })
215 if !strings.Contains(output, "test title") {
216 t.Errorf("Titleln() should print message, got: %s", output)
217 }
218 if !strings.HasSuffix(output, "\n") {
219 t.Errorf("Titleln() should end with newline, got: %s", output)
220 }
221}
222
223func TestSubtitlePrint(t *testing.T) {
224 output := utils.CaptureOutput(func() {
225 Subtitle("test %s", "subtitle")
226 })
227 if !strings.Contains(output, "test subtitle") {
228 t.Errorf("Subtitle() should print message, got: %s", output)
229 }
230}
231
232func TestSubtitleln(t *testing.T) {
233 output := utils.CaptureOutput(func() {
234 Subtitleln("test %s", "subtitle")
235 })
236 if !strings.Contains(output, "test subtitle") {
237 t.Errorf("Subtitleln() should print message, got: %s", output)
238 }
239 if !strings.HasSuffix(output, "\n") {
240 t.Errorf("Subtitleln() should end with newline, got: %s", output)
241 }
242}
243
244func TestBoxPrint(t *testing.T) {
245 output := utils.CaptureOutput(func() {
246 Box("test %s", "content")
247 })
248 if !strings.Contains(output, "test content") {
249 t.Errorf("Box() should print message, got: %s", output)
250 }
251}
252
253func TestBoxln(t *testing.T) {
254 output := utils.CaptureOutput(func() {
255 Boxln("test %s", "content")
256 })
257 if !strings.Contains(output, "test content") {
258 t.Errorf("Boxln() should print message, got: %s", output)
259 }
260 if !strings.HasSuffix(output, "\n") {
261 t.Errorf("Boxln() should end with newline, got: %s", output)
262 }
263}
264
265func TestErrorBoxPrint(t *testing.T) {
266 output := utils.CaptureOutput(func() {
267 ErrorBox("test %s", "error")
268 })
269 if !strings.Contains(output, "test error") {
270 t.Errorf("ErrorBox() should print message, got: %s", output)
271 }
272}
273
274func TestErrorBoxln(t *testing.T) {
275 output := utils.CaptureOutput(func() {
276 ErrorBoxln("test %s", "error")
277 })
278 if !strings.Contains(output, "test error") {
279 t.Errorf("ErrorBoxln() should print message, got: %s", output)
280 }
281 if !strings.HasSuffix(output, "\n") {
282 t.Errorf("ErrorBoxln() should end with newline, got: %s", output)
283 }
284}
285
286func TestPrintingFunctions(t *testing.T) {
287 t.Run("no args", func(t *testing.T) {
288 tests := []struct {
289 name string
290 fn func(string, ...any)
291 }{
292 {"Success", Success},
293 {"Error", Error},
294 {"Warning", Warning},
295 {"Info", Info},
296 {"Title", Title},
297 {"Subtitle", Subtitle},
298 {"Box", Box},
299 {"ErrorBox", ErrorBox},
300 }
301
302 for _, tt := range tests {
303 t.Run(tt.name, func(t *testing.T) {
304 output := utils.CaptureOutput(func() {
305 tt.fn("plain message")
306 })
307 if !strings.Contains(output, "plain message") {
308 t.Errorf("%s() should print plain message, got: %s", tt.name, output)
309 }
310 })
311 }
312 })
313
314 t.Run("with multiple args", func(t *testing.T) {
315 output := utils.CaptureOutput(func() {
316 Success("test %s %d %v", "message", 42, true)
317 })
318 if !strings.Contains(output, "test message 42 true") {
319 t.Errorf("Success() should handle multiple format args, got: %s", output)
320 }
321 })
322
323 t.Run("with empty string", func(t *testing.T) {
324 output := utils.CaptureOutput(func() {
325 Success("")
326 })
327
328 if len(output) == 0 {
329 t.Errorf("Success(\"\") should print something, got empty output")
330 }
331 })
332}
333
334func TestStyleHelperFunctions(t *testing.T) {
335 t.Run("NewStyle", func(t *testing.T) {
336 style := newStyle()
337 rendered := style.Render("test")
338 if rendered != "test" {
339 t.Errorf("newStyle() should render plain text, got: %s", rendered)
340 }
341 })
342
343 t.Run("NewPStyle", func(t *testing.T) {
344 style := newPStyle(1, 2)
345 rendered := style.Render("test")
346 if !strings.Contains(rendered, "test") {
347 t.Errorf("newPStyle() should render text, got: %s", rendered)
348 }
349 if len(rendered) <= len("test") {
350 t.Errorf("newPStyle() should add padding, got: %s", rendered)
351 }
352 })
353
354 t.Run("NewBoldStyle", func(t *testing.T) {
355 style := newBoldStyle()
356 rendered := style.Render("test")
357 if !strings.Contains(rendered, "test") {
358 t.Errorf("newBoldStyle() should render text, got: %s", rendered)
359 }
360 })
361
362 t.Run("NewPBoldStyle", func(t *testing.T) {
363 style := newPBoldStyle(1, 2)
364 rendered := style.Render("test")
365 if !strings.Contains(rendered, "test") {
366 t.Errorf("newPBoldStyle() should render text, got: %s", rendered)
367 }
368 if len(rendered) <= len("test") {
369 t.Errorf("newPBoldStyle() should add padding, got: %s", rendered)
370 }
371 })
372
373 t.Run("NewEmStyle", func(t *testing.T) {
374 style := newEmStyle()
375 rendered := style.Render("test")
376 if !strings.Contains(rendered, "test") {
377 t.Errorf("newEmStyle() should render text, got: %s", rendered)
378 }
379 })
380}
381
382func TestStyleVariables(t *testing.T) {
383 styles := []struct {
384 name string
385 style any
386 }{
387 {"PrimaryStyle", PrimaryStyle},
388 {"AccentStyle", AccentStyle},
389 {"ErrorStyle", ErrorStyle},
390 {"TextStyle", TextStyle},
391 {"TitleStyle", TitleStyle},
392 {"SubtitleStyle", SubtitleStyle},
393 {"SuccessStyle", SuccessStyle},
394 {"WarningStyle", WarningStyle},
395 {"InfoStyle", InfoStyle},
396 {"BoxStyle", BoxStyle},
397 {"ErrorBoxStyle", ErrorBoxStyle},
398 {"ListItemStyle", ListItemStyle},
399 {"SelectedItemStyle", SelectedItemStyle},
400 {"HeaderStyle", HeaderStyle},
401 {"CellStyle", CellStyle},
402 }
403
404 for _, s := range styles {
405 t.Run(s.name, func(t *testing.T) {
406 if s.style == nil {
407 t.Errorf("%s should be initialized", s.name)
408 }
409 })
410 }
411}
412
413func BenchmarkSuccess(b *testing.B) {
414 for b.Loop() {
415 success("test message")
416 }
417}
418
419func BenchmarkSuccessPrint(b *testing.B) {
420 old := os.Stdout
421 os.Stdout = nil
422 defer func() { os.Stdout = old }()
423
424 for b.Loop() {
425 fmt.Print(success(fmt.Sprintf("test %s", "message")))
426 }
427}
428
429func BenchmarkNewStyle(b *testing.B) {
430 for b.Loop() {
431 newStyle()
432 }
433}