1 package color
2
3 import (
4 "bytes"
5 "fmt"
6 "io"
7 "os"
8 "testing"
9
10 "github.com/mattn/go-colorable"
11 )
12
13
14
15
16 func TestColor(t *testing.T) {
17 rb := new(bytes.Buffer)
18 Output = rb
19
20 NoColor = false
21
22 testColors := []struct {
23 text string
24 code Attribute
25 }{
26 {text: "black", code: FgBlack},
27 {text: "red", code: FgRed},
28 {text: "green", code: FgGreen},
29 {text: "yellow", code: FgYellow},
30 {text: "blue", code: FgBlue},
31 {text: "magent", code: FgMagenta},
32 {text: "cyan", code: FgCyan},
33 {text: "white", code: FgWhite},
34 {text: "hblack", code: FgHiBlack},
35 {text: "hred", code: FgHiRed},
36 {text: "hgreen", code: FgHiGreen},
37 {text: "hyellow", code: FgHiYellow},
38 {text: "hblue", code: FgHiBlue},
39 {text: "hmagent", code: FgHiMagenta},
40 {text: "hcyan", code: FgHiCyan},
41 {text: "hwhite", code: FgHiWhite},
42 }
43
44 for _, c := range testColors {
45 New(c.code).Print(c.text)
46
47 line, _ := rb.ReadString('\n')
48 scannedLine := fmt.Sprintf("%q", line)
49 colored := fmt.Sprintf("\x1b[%dm%s\x1b[0m", c.code, c.text)
50 escapedForm := fmt.Sprintf("%q", colored)
51
52 fmt.Printf("%s\t: %s\n", c.text, line)
53
54 if scannedLine != escapedForm {
55 t.Errorf("Expecting %s, got '%s'\n", escapedForm, scannedLine)
56 }
57 }
58
59 for _, c := range testColors {
60 line := New(c.code).Sprintf("%s", c.text)
61 scannedLine := fmt.Sprintf("%q", line)
62 colored := fmt.Sprintf("\x1b[%dm%s\x1b[0m", c.code, c.text)
63 escapedForm := fmt.Sprintf("%q", colored)
64
65 fmt.Printf("%s\t: %s\n", c.text, line)
66
67 if scannedLine != escapedForm {
68 t.Errorf("Expecting %s, got '%s'\n", escapedForm, scannedLine)
69 }
70 }
71 }
72
73 func TestColorEquals(t *testing.T) {
74 fgblack1 := New(FgBlack)
75 fgblack2 := New(FgBlack)
76 bgblack := New(BgBlack)
77 fgbgblack := New(FgBlack, BgBlack)
78 fgblackbgred := New(FgBlack, BgRed)
79 fgred := New(FgRed)
80 bgred := New(BgRed)
81
82 if !fgblack1.Equals(fgblack2) {
83 t.Error("Two black colors are not equal")
84 }
85
86 if fgblack1.Equals(bgblack) {
87 t.Error("Fg and bg black colors are equal")
88 }
89
90 if fgblack1.Equals(fgbgblack) {
91 t.Error("Fg black equals fg/bg black color")
92 }
93
94 if fgblack1.Equals(fgred) {
95 t.Error("Fg black equals Fg red")
96 }
97
98 if fgblack1.Equals(bgred) {
99 t.Error("Fg black equals Bg red")
100 }
101
102 if fgblack1.Equals(fgblackbgred) {
103 t.Error("Fg black equals fg black bg red")
104 }
105 }
106
107 func TestNoColor(t *testing.T) {
108 rb := new(bytes.Buffer)
109 Output = rb
110
111 testColors := []struct {
112 text string
113 code Attribute
114 }{
115 {text: "black", code: FgBlack},
116 {text: "red", code: FgRed},
117 {text: "green", code: FgGreen},
118 {text: "yellow", code: FgYellow},
119 {text: "blue", code: FgBlue},
120 {text: "magent", code: FgMagenta},
121 {text: "cyan", code: FgCyan},
122 {text: "white", code: FgWhite},
123 {text: "hblack", code: FgHiBlack},
124 {text: "hred", code: FgHiRed},
125 {text: "hgreen", code: FgHiGreen},
126 {text: "hyellow", code: FgHiYellow},
127 {text: "hblue", code: FgHiBlue},
128 {text: "hmagent", code: FgHiMagenta},
129 {text: "hcyan", code: FgHiCyan},
130 {text: "hwhite", code: FgHiWhite},
131 }
132
133 for _, c := range testColors {
134 p := New(c.code)
135 p.DisableColor()
136 p.Print(c.text)
137
138 line, _ := rb.ReadString('\n')
139 if line != c.text {
140 t.Errorf("Expecting %s, got '%s'\n", c.text, line)
141 }
142 }
143
144
145 NoColor = true
146 t.Cleanup(func() {
147 NoColor = false
148 })
149
150 for _, c := range testColors {
151 p := New(c.code)
152 p.Print(c.text)
153
154 line, _ := rb.ReadString('\n')
155 if line != c.text {
156 t.Errorf("Expecting %s, got '%s'\n", c.text, line)
157 }
158 }
159 }
160
161 func TestNoColor_Env(t *testing.T) {
162 rb := new(bytes.Buffer)
163 Output = rb
164
165 testColors := []struct {
166 text string
167 code Attribute
168 }{
169 {text: "black", code: FgBlack},
170 {text: "red", code: FgRed},
171 {text: "green", code: FgGreen},
172 {text: "yellow", code: FgYellow},
173 {text: "blue", code: FgBlue},
174 {text: "magent", code: FgMagenta},
175 {text: "cyan", code: FgCyan},
176 {text: "white", code: FgWhite},
177 {text: "hblack", code: FgHiBlack},
178 {text: "hred", code: FgHiRed},
179 {text: "hgreen", code: FgHiGreen},
180 {text: "hyellow", code: FgHiYellow},
181 {text: "hblue", code: FgHiBlue},
182 {text: "hmagent", code: FgHiMagenta},
183 {text: "hcyan", code: FgHiCyan},
184 {text: "hwhite", code: FgHiWhite},
185 }
186
187 os.Setenv("NO_COLOR", "1")
188 t.Cleanup(func() {
189 os.Unsetenv("NO_COLOR")
190 })
191
192 for _, c := range testColors {
193 p := New(c.code)
194 p.Print(c.text)
195
196 line, _ := rb.ReadString('\n')
197 if line != c.text {
198 t.Errorf("Expecting %s, got '%s'\n", c.text, line)
199 }
200 }
201 }
202
203 func Test_noColorIsSet(t *testing.T) {
204 tests := []struct {
205 name string
206 act func()
207 want bool
208 }{
209 {
210 name: "default",
211 act: func() {},
212 want: false,
213 },
214 {
215 name: "NO_COLOR=1",
216 act: func() { os.Setenv("NO_COLOR", "1") },
217 want: true,
218 },
219 {
220 name: "NO_COLOR=",
221 act: func() { os.Setenv("NO_COLOR", "") },
222 want: false,
223 },
224 }
225 for _, tt := range tests {
226 t.Run(tt.name, func(t *testing.T) {
227 t.Cleanup(func() {
228 os.Unsetenv("NO_COLOR")
229 })
230 tt.act()
231 if got := noColorIsSet(); got != tt.want {
232 t.Errorf("noColorIsSet() = %v, want %v", got, tt.want)
233 }
234 })
235 }
236 }
237
238 func TestColorVisual(t *testing.T) {
239
240 Output = colorable.NewColorableStdout()
241
242 New(FgRed).Printf("red\t")
243 New(BgRed).Print(" ")
244 New(FgRed, Bold).Println(" red")
245
246 New(FgGreen).Printf("green\t")
247 New(BgGreen).Print(" ")
248 New(FgGreen, Bold).Println(" green")
249
250 New(FgYellow).Printf("yellow\t")
251 New(BgYellow).Print(" ")
252 New(FgYellow, Bold).Println(" yellow")
253
254 New(FgBlue).Printf("blue\t")
255 New(BgBlue).Print(" ")
256 New(FgBlue, Bold).Println(" blue")
257
258 New(FgMagenta).Printf("magenta\t")
259 New(BgMagenta).Print(" ")
260 New(FgMagenta, Bold).Println(" magenta")
261
262 New(FgCyan).Printf("cyan\t")
263 New(BgCyan).Print(" ")
264 New(FgCyan, Bold).Println(" cyan")
265
266 New(FgWhite).Printf("white\t")
267 New(BgWhite).Print(" ")
268 New(FgWhite, Bold).Println(" white")
269 fmt.Println("")
270
271
272 Black("black")
273 Red("red")
274 Green("green")
275 Yellow("yellow")
276 Blue("blue")
277 Magenta("magenta")
278 Cyan("cyan")
279 White("white")
280 HiBlack("hblack")
281 HiRed("hred")
282 HiGreen("hgreen")
283 HiYellow("hyellow")
284 HiBlue("hblue")
285 HiMagenta("hmagenta")
286 HiCyan("hcyan")
287 HiWhite("hwhite")
288
289
290 fmt.Println()
291 Set(FgBlue)
292 fmt.Println("is this blue?")
293 Unset()
294
295 Set(FgMagenta)
296 fmt.Println("and this magenta?")
297 Unset()
298
299
300 fmt.Println()
301 blue := New(FgBlue).PrintlnFunc()
302 blue("blue text with custom print func")
303
304 red := New(FgRed).PrintfFunc()
305 red("red text with a printf func: %d\n", 123)
306
307 put := New(FgYellow).SprintFunc()
308 warn := New(FgRed).SprintFunc()
309
310 fmt.Fprintf(Output, "this is a %s and this is %s.\n", put("warning"), warn("error"))
311
312 info := New(FgWhite, BgGreen).SprintFunc()
313 fmt.Fprintf(Output, "this %s rocks!\n", info("package"))
314
315 notice := New(FgBlue).FprintFunc()
316 notice(os.Stderr, "just a blue notice to stderr")
317
318
319 fmt.Println()
320
321 fmt.Fprintln(Output, BlackString("black"))
322 fmt.Fprintln(Output, RedString("red"))
323 fmt.Fprintln(Output, GreenString("green"))
324 fmt.Fprintln(Output, YellowString("yellow"))
325 fmt.Fprintln(Output, BlueString("blue"))
326 fmt.Fprintln(Output, MagentaString("magenta"))
327 fmt.Fprintln(Output, CyanString("cyan"))
328 fmt.Fprintln(Output, WhiteString("white"))
329 fmt.Fprintln(Output, HiBlackString("hblack"))
330 fmt.Fprintln(Output, HiRedString("hred"))
331 fmt.Fprintln(Output, HiGreenString("hgreen"))
332 fmt.Fprintln(Output, HiYellowString("hyellow"))
333 fmt.Fprintln(Output, HiBlueString("hblue"))
334 fmt.Fprintln(Output, HiMagentaString("hmagenta"))
335 fmt.Fprintln(Output, HiCyanString("hcyan"))
336 fmt.Fprintln(Output, HiWhiteString("hwhite"))
337 }
338
339 func TestNoFormat(t *testing.T) {
340 fmt.Printf("%s %%s = ", BlackString("Black"))
341 Black("%s")
342
343 fmt.Printf("%s %%s = ", RedString("Red"))
344 Red("%s")
345
346 fmt.Printf("%s %%s = ", GreenString("Green"))
347 Green("%s")
348
349 fmt.Printf("%s %%s = ", YellowString("Yellow"))
350 Yellow("%s")
351
352 fmt.Printf("%s %%s = ", BlueString("Blue"))
353 Blue("%s")
354
355 fmt.Printf("%s %%s = ", MagentaString("Magenta"))
356 Magenta("%s")
357
358 fmt.Printf("%s %%s = ", CyanString("Cyan"))
359 Cyan("%s")
360
361 fmt.Printf("%s %%s = ", WhiteString("White"))
362 White("%s")
363
364 fmt.Printf("%s %%s = ", HiBlackString("HiBlack"))
365 HiBlack("%s")
366
367 fmt.Printf("%s %%s = ", HiRedString("HiRed"))
368 HiRed("%s")
369
370 fmt.Printf("%s %%s = ", HiGreenString("HiGreen"))
371 HiGreen("%s")
372
373 fmt.Printf("%s %%s = ", HiYellowString("HiYellow"))
374 HiYellow("%s")
375
376 fmt.Printf("%s %%s = ", HiBlueString("HiBlue"))
377 HiBlue("%s")
378
379 fmt.Printf("%s %%s = ", HiMagentaString("HiMagenta"))
380 HiMagenta("%s")
381
382 fmt.Printf("%s %%s = ", HiCyanString("HiCyan"))
383 HiCyan("%s")
384
385 fmt.Printf("%s %%s = ", HiWhiteString("HiWhite"))
386 HiWhite("%s")
387 }
388
389 func TestNoFormatString(t *testing.T) {
390 tests := []struct {
391 f func(string, ...interface{}) string
392 format string
393 args []interface{}
394 want string
395 }{
396 {BlackString, "%s", nil, "\x1b[30m%s\x1b[0m"},
397 {RedString, "%s", nil, "\x1b[31m%s\x1b[0m"},
398 {GreenString, "%s", nil, "\x1b[32m%s\x1b[0m"},
399 {YellowString, "%s", nil, "\x1b[33m%s\x1b[0m"},
400 {BlueString, "%s", nil, "\x1b[34m%s\x1b[0m"},
401 {MagentaString, "%s", nil, "\x1b[35m%s\x1b[0m"},
402 {CyanString, "%s", nil, "\x1b[36m%s\x1b[0m"},
403 {WhiteString, "%s", nil, "\x1b[37m%s\x1b[0m"},
404 {HiBlackString, "%s", nil, "\x1b[90m%s\x1b[0m"},
405 {HiRedString, "%s", nil, "\x1b[91m%s\x1b[0m"},
406 {HiGreenString, "%s", nil, "\x1b[92m%s\x1b[0m"},
407 {HiYellowString, "%s", nil, "\x1b[93m%s\x1b[0m"},
408 {HiBlueString, "%s", nil, "\x1b[94m%s\x1b[0m"},
409 {HiMagentaString, "%s", nil, "\x1b[95m%s\x1b[0m"},
410 {HiCyanString, "%s", nil, "\x1b[96m%s\x1b[0m"},
411 {HiWhiteString, "%s", nil, "\x1b[97m%s\x1b[0m"},
412 }
413
414 for i, test := range tests {
415 s := test.f(test.format, test.args...)
416
417 if s != test.want {
418 t.Errorf("[%d] want: %q, got: %q", i, test.want, s)
419 }
420 }
421 }
422
423 func TestColor_Println_Newline(t *testing.T) {
424 rb := new(bytes.Buffer)
425 Output = rb
426
427 c := New(FgRed)
428 c.Println("foo")
429
430 got := readRaw(t, rb)
431 want := "\x1b[31mfoo\x1b[0m\n"
432
433 if want != got {
434 t.Errorf("Println newline error\n\nwant: %q\n got: %q", want, got)
435 }
436 }
437
438 func TestColor_Sprintln_Newline(t *testing.T) {
439 c := New(FgRed)
440
441 got := c.Sprintln("foo")
442 want := "\x1b[31mfoo\x1b[0m\n"
443
444 if want != got {
445 t.Errorf("Println newline error\n\nwant: %q\n got: %q", want, got)
446 }
447 }
448
449 func TestColor_Fprintln_Newline(t *testing.T) {
450 rb := new(bytes.Buffer)
451 c := New(FgRed)
452 c.Fprintln(rb, "foo")
453
454 got := readRaw(t, rb)
455 want := "\x1b[31mfoo\x1b[0m\n"
456
457 if want != got {
458 t.Errorf("Println newline error\n\nwant: %q\n got: %q", want, got)
459 }
460 }
461
462 func readRaw(t *testing.T, r io.Reader) string {
463 t.Helper()
464
465 out, err := io.ReadAll(r)
466 if err != nil {
467 t.Fatal(err)
468 }
469
470 return string(out)
471 }
472
473 func TestIssue206_1(t *testing.T) {
474
475
476 var underline = New(Underline).Sprint
477
478 var line = fmt.Sprintf("%s %s %s %s", "word1", underline("word2"), "word3", underline("word4"))
479
480 line = CyanString(line)
481
482 fmt.Println(line)
483
484 var result = fmt.Sprintf("%v", line)
485 const expectedResult = "\x1b[36mword1 \x1b[4mword2\x1b[24m word3 \x1b[4mword4\x1b[24m\x1b[0m"
486
487 if !bytes.Equal([]byte(result), []byte(expectedResult)) {
488 t.Errorf("Expecting %v, got '%v'\n", expectedResult, result)
489 }
490 }
491
492 func TestIssue206_2(t *testing.T) {
493 var underline = New(Underline).Sprint
494 var bold = New(Bold).Sprint
495
496 var line = fmt.Sprintf("%s %s", GreenString(underline("underlined regular green")), RedString(bold("bold red")))
497
498 fmt.Println(line)
499
500 var result = fmt.Sprintf("%v", line)
501 const expectedResult = "\x1b[32m\x1b[4munderlined regular green\x1b[24m\x1b[0m \x1b[31m\x1b[1mbold red\x1b[22m\x1b[0m"
502
503 if !bytes.Equal([]byte(result), []byte(expectedResult)) {
504 t.Errorf("Expecting %v, got '%v'\n", expectedResult, result)
505 }
506 }
507
View as plain text