package style import ( "testing" "github.com/gookit/color" "github.com/stretchr/testify/assert" "github.com/xo/terminfo" ) func TestMerge(t *testing.T) { type scenario struct { name string toMerge []TextStyle expectedStyle TextStyle expectedStr string } // on CI we've got no color capability so we're forcing it here color.ForceSetColorLevel(terminfo.ColorLevelMillions) fgRed := color.FgRed bgRed := color.BgRed fgBlue := color.FgBlue rgbPinkLib := color.Rgb(0xFF, 0x00, 0xFF) rgbPink := NewRGBColor(rgbPinkLib) rgbYellowLib := color.Rgb(0xFF, 0xFF, 0x00) rgbYellow := NewRGBColor(rgbYellowLib) strToPrint := "foo" scenarios := []scenario{ { "no color", nil, TextStyle{style: color.Style{}}, "foo", }, { "only fg color", []TextStyle{FgRed}, TextStyle{fg: &Color{basic: &fgRed}, style: color.Style{fgRed}}, "\x1b[31mfoo\x1b[0m", }, { "only bg color", []TextStyle{BgRed}, TextStyle{bg: &Color{basic: &bgRed}, style: color.Style{bgRed}}, "\x1b[41mfoo\x1b[0m", }, { "fg and bg color", []TextStyle{FgBlue, BgRed}, TextStyle{ fg: &Color{basic: &fgBlue}, bg: &Color{basic: &bgRed}, style: color.Style{fgBlue, bgRed}, }, "\x1b[34;41mfoo\x1b[0m", }, { "single attribute", []TextStyle{AttrBold}, TextStyle{ decoration: Decoration{bold: true}, style: color.Style{color.OpBold}, }, "\x1b[1mfoo\x1b[0m", }, { "multiple attributes", []TextStyle{AttrBold, AttrUnderline}, TextStyle{ decoration: Decoration{ bold: true, underline: true, }, style: color.Style{color.OpBold, color.OpUnderscore}, }, "\x1b[1;4mfoo\x1b[0m", }, { "multiple attributes and colors", []TextStyle{AttrBold, FgBlue, AttrUnderline, BgRed}, TextStyle{ fg: &Color{basic: &fgBlue}, bg: &Color{basic: &bgRed}, decoration: Decoration{ bold: true, underline: true, }, style: color.Style{fgBlue, bgRed, color.OpBold, color.OpUnderscore}, }, "\x1b[34;41;1;4mfoo\x1b[0m", }, { "rgb fg color", []TextStyle{New().SetFg(rgbPink)}, TextStyle{ fg: &rgbPink, style: color.NewRGBStyle(rgbPinkLib).SetOpts(color.Opts{}), }, // '38;2' qualifies an RGB foreground color "\x1b[38;2;255;0;255mfoo\x1b[0m", }, { "rgb fg and bg color", []TextStyle{New().SetFg(rgbPink).SetBg(rgbYellow)}, TextStyle{ fg: &rgbPink, bg: &rgbYellow, style: color.NewRGBStyle(rgbPinkLib, rgbYellowLib).SetOpts(color.Opts{}), }, // '48;2' qualifies an RGB background color "\x1b[38;2;255;0;255;48;2;255;255;0mfoo\x1b[0m", }, { "rgb fg and bg color with opts", []TextStyle{AttrBold, New().SetFg(rgbPink).SetBg(rgbYellow), AttrUnderline}, TextStyle{ fg: &rgbPink, bg: &rgbYellow, decoration: Decoration{ bold: true, underline: true, }, style: color.NewRGBStyle(rgbPinkLib, rgbYellowLib).SetOpts(color.Opts{color.OpBold, color.OpUnderscore}), }, "\x1b[38;2;255;0;255;48;2;255;255;0;1;4mfoo\x1b[0m", }, { "mix color-16 with rgb colors", []TextStyle{New().SetFg(rgbYellow), BgRed}, TextStyle{ fg: &rgbYellow, bg: &Color{basic: &bgRed}, style: color.NewRGBStyle( rgbYellowLib, fgRed.RGB(), // We need to use FG here, https://github.com/gookit/color/issues/39 ).SetOpts(color.Opts{}), }, "\x1b[38;2;255;255;0;48;2;197;30;20mfoo\x1b[0m", }, } for _, s := range scenarios { s := s t.Run(s.name, func(t *testing.T) { style := New() for _, other := range s.toMerge { style = style.MergeStyle(other) } assert.Equal(t, s.expectedStyle, style) assert.Equal(t, s.expectedStr, style.Sprint(strToPrint)) }) } }