diff options
author | mjarkk <mkopenga@gmail.com> | 2021-07-31 20:48:40 +0200 |
---|---|---|
committer | mjarkk <mkopenga@gmail.com> | 2021-07-31 20:53:49 +0200 |
commit | 0662733ad95583c5ec2fb701f2b5bbcaf54d5e86 (patch) | |
tree | 4a7d9c5543c020480be0e2a24dd5a635f169e93f /pkg/gui/style | |
parent | 3c78ba7ed3dbaf912417b11269a4b8a21f256145 (diff) |
add tests for color changes
Diffstat (limited to 'pkg/gui/style')
-rw-r--r-- | pkg/gui/style/color.go | 9 | ||||
-rw-r--r-- | pkg/gui/style/decoration.go | 6 | ||||
-rw-r--r-- | pkg/gui/style/style_test.go | 339 | ||||
-rw-r--r-- | pkg/gui/style/text_style.go | 6 |
4 files changed, 96 insertions, 264 deletions
diff --git a/pkg/gui/style/color.go b/pkg/gui/style/color.go index b2df21bbf..2b13c9236 100644 --- a/pkg/gui/style/color.go +++ b/pkg/gui/style/color.go @@ -23,10 +23,17 @@ func (c Color) IsRGB() bool { return c.rgb != nil } -func (c Color) ToRGB() Color { +func (c Color) ToRGB(isBg bool) Color { if c.IsRGB() { return c } + if isBg { + // We need to convert bg color to fg color + // This is a gookit/color bug, + // https://github.com/gookit/color/issues/39 + return NewRGBColor((*c.basic - 10).RGB()) + } + return NewRGBColor(c.basic.RGB()) } diff --git a/pkg/gui/style/decoration.go b/pkg/gui/style/decoration.go index 51887fbdd..f6fedb879 100644 --- a/pkg/gui/style/decoration.go +++ b/pkg/gui/style/decoration.go @@ -8,15 +8,15 @@ type Decoration struct { reverse bool } -func (d Decoration) SetBold() { +func (d *Decoration) SetBold() { d.bold = true } -func (d Decoration) SetUnderline() { +func (d *Decoration) SetUnderline() { d.underline = true } -func (d Decoration) SetReverse() { +func (d *Decoration) SetReverse() { d.reverse = true } diff --git a/pkg/gui/style/style_test.go b/pkg/gui/style/style_test.go index 669bd4db5..3b301d160 100644 --- a/pkg/gui/style/style_test.go +++ b/pkg/gui/style/style_test.go @@ -7,308 +7,131 @@ import ( "github.com/stretchr/testify/assert" ) -func TestNewStyle(t *testing.T) { +func TestMerge(t *testing.T) { type scenario struct { name string - fg, bg color.Color - expectedStyle color.Style + toMerge []TextStyle + expectedStyle TextStyle } + 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) + scenarios := []scenario{ { "no color", - 0, 0, - color.Style{}, + nil, + TextStyle{style: color.Style{}}, }, { "only fg color", - color.FgRed, 0, - color.Style{color.FgRed}, + []TextStyle{FgRed}, + TextStyle{fg: &Color{basic: &fgRed}, style: color.Style{fgRed}}, }, { "only bg color", - 0, color.BgRed, - color.Style{color.BgRed}, + []TextStyle{BgRed}, + TextStyle{bg: &Color{basic: &bgRed}, style: color.Style{bgRed}}, }, { "fg and bg color", - color.FgBlue, color.BgRed, - color.Style{color.FgBlue, color.BgRed}, - }, - } - - for _, s := range scenarios { - t.Run(s.name, func(t *testing.T) { - style := New(s.fg, s.bg) - basicStyle, ok := style.(BasicTextStyle) - assert.True(t, ok, "New(..) should return a interface of type BasicTextStyle") - assert.Equal(t, s.fg, basicStyle.fg) - assert.Equal(t, s.bg, basicStyle.bg) - assert.Equal(t, []color.Color(nil), basicStyle.opts) - assert.Equal(t, s.expectedStyle, basicStyle.style) - }) - } -} - -func TestBasicSetColor(t *testing.T) { - type scenario struct { - name string - colorToSet TextStyle - expect TextStyle - } - - scenarios := []scenario{ - { - "empty color", - TextStyle{}, - TextStyle{fg: color.FgRed, bg: color.BgBlue, opts: []color.Color{color.OpBold}}}, - { - "set new fg color", - TextStyle{fg: color.FgCyan}, - TextStyle{fg: color.FgCyan, bg: color.BgBlue, opts: []color.Color{color.OpBold}}, - }, - { - "set new bg color", - TextStyle{bg: color.BgGray}, - TextStyle{fg: color.FgRed, bg: color.BgGray, opts: []color.Color{color.OpBold}}, - }, - { - "set new fg and bg color", - TextStyle{fg: color.FgCyan, bg: color.BgGray}, - TextStyle{fg: color.FgCyan, bg: color.BgGray, opts: []color.Color{color.OpBold}}, - }, - { - "add options", - TextStyle{opts: []color.Color{color.OpUnderscore}}, - TextStyle{fg: color.FgRed, bg: color.BgBlue, opts: []color.Color{color.OpBold, color.OpUnderscore}}, - }, - { - "add options that already exists", - TextStyle{opts: []color.Color{color.OpBold}}, - TextStyle{fg: color.FgRed, bg: color.BgBlue, opts: []color.Color{color.OpBold}}, - }, - } - - for _, s := range scenarios { - t.Run(s.name, func(t *testing.T) { - style, ok := New(color.FgRed, color.BgBlue). - SetBold(true). - SetColor(s.colorToSet).(BasicTextStyle) - assert.True(t, ok, "SetColor should return a interface of type BasicTextStyle if the input was also BasicTextStyle") - - style.style = nil - assert.Equal(t, s.expect, style) - }) - } -} - -func TestRGBSetColor(t *testing.T) { - type scenario struct { - name string - colorToSet TextStyle - expect RGBTextStyle - } - - red := color.FgRed.RGB() - cyan := color.FgCyan.RGB() - blue := color.FgBlue.RGB() - gray := color.FgGray.RGB() - - toBg := func(c color.RGBColor) *color.RGBColor { - c[3] = 1 - return &c - } - - scenarios := []scenario{ - { - "empty RGBTextStyle input", - RGBTextStyle{}, - RGBTextStyle{fgSet: true, fg: red, bg: toBg(blue), opts: []color.Color{color.OpBold}}, - }, - { - "empty BasicTextStyle input", - TextStyle{}, - RGBTextStyle{fgSet: true, fg: red, bg: toBg(blue), opts: []color.Color{color.OpBold}}, - }, - { - "set fg and bg color using BasicTextStyle", - TextStyle{fg: color.FgCyan, bg: color.BgGray}, - RGBTextStyle{fgSet: true, fg: cyan, bg: toBg(gray), opts: []color.Color{color.OpBold}}, - }, - { - "set fg and bg color using RGBTextStyle", - RGBTextStyle{fgSet: true, fg: cyan, bg: toBg(gray)}, - RGBTextStyle{fgSet: true, fg: cyan, bg: toBg(gray), opts: []color.Color{color.OpBold}}, - }, - { - "add options", - RGBTextStyle{opts: []color.Color{color.OpUnderscore}}, - RGBTextStyle{fgSet: true, fg: red, bg: toBg(blue), opts: []color.Color{color.OpBold, color.OpUnderscore}}, - }, - { - "add options using BasicTextStyle", - TextStyle{opts: []color.Color{color.OpUnderscore}}, - RGBTextStyle{fgSet: true, fg: red, bg: toBg(blue), opts: []color.Color{color.OpBold, color.OpUnderscore}}, - }, - { - "add options that already exists", - RGBTextStyle{opts: []color.Color{color.OpBold}}, - RGBTextStyle{fgSet: true, fg: red, bg: toBg(blue), opts: []color.Color{color.OpBold}}, - }, - } - - for _, s := range scenarios { - t.Run(s.name, func(t *testing.T) { - style, ok := New(color.FgRed, color.BgBlue).SetBold().(BasicTextStyle) - assert.True(t, ok, "SetBold should return a interface of type BasicTextStyle") - - rgbStyle, ok := style.convertToRGB().MergeStyle(s.colorToSet).(RGBTextStyle) - assert.True(t, ok, "SetColor should return a interface of type RGBTextColor") - - rgbStyle.style = color.RGBStyle{} - assert.Equal(t, s.expect, rgbStyle) - }) - } -} - -func TestConvertBasicToRGB(t *testing.T) { - type scenario struct { - name string - test func(*testing.T) - } - - scenarios := []scenario{ - { - "convert to rgb with fg", - func(t *testing.T) { - basicStyle, ok := New(color.FgRed, 0).(BasicTextStyle) - assert.True(t, ok, "New(..) should return a interface of type BasicTextStyle") - - rgbStyle := basicStyle.convertToRGB() - assert.True(t, rgbStyle.fgSet) - assert.Equal(t, color.RGB(197, 30, 20), rgbStyle.fg) - assert.Nil(t, rgbStyle.bg) + []TextStyle{FgBlue, BgRed}, + TextStyle{ + fg: &Color{basic: &fgBlue}, + bg: &Color{basic: &bgRed}, + style: color.Style{fgBlue, bgRed}, }, }, { - "convert to rgb with fg and bg", - func(t *testing.T) { - basicStyle, ok := New(color.FgRed, color.BgRed).(BasicTextStyle) - assert.True(t, ok, "New(..) should return a interface of type BasicTextStyle") - - rgbStyle := basicStyle.convertToRGB() - assert.True(t, rgbStyle.fgSet) - assert.Equal(t, color.RGB(197, 30, 20), rgbStyle.fg) - assert.Equal(t, color.RGB(197, 30, 20, true), *rgbStyle.bg) + "single attribute", + []TextStyle{AttrBold}, + TextStyle{ + decoration: Decoration{bold: true}, + style: color.Style{color.OpBold}, }, }, { - "convert to rgb using SetRGBColor", - func(t *testing.T) { - style := New(color.FgRed, 0) - rgbStyle, ok := style.SetRGBColor(255, 00, 255, true).(RGBTextStyle) - assert.True(t, ok, "SetRGBColor should return a interface of type RGBTextStyle") - - assert.True(t, rgbStyle.fgSet) - assert.Equal(t, color.RGB(197, 30, 20), rgbStyle.fg) - assert.Equal(t, color.RGB(255, 0, 255, true), *rgbStyle.bg) + "multiple attributes", + []TextStyle{AttrBold, AttrUnderline}, + TextStyle{ + decoration: Decoration{ + bold: true, + underline: true, + }, + style: color.Style{color.OpBold, color.OpUnderscore}, }, }, { - "convert to rgb using SetRGBColor multiple times", - func(t *testing.T) { - style := New(color.FgRed, 0) - rgbStyle, ok := style.SetRGBColor(00, 255, 255, false).SetRGBColor(255, 00, 255, true).(RGBTextStyle) - assert.True(t, ok, "SetRGBColor should return a interface of type RGBTextStyle") - - assert.True(t, rgbStyle.fgSet) - assert.Equal(t, color.RGB(0, 255, 255), rgbStyle.fg) - assert.Equal(t, color.RGB(255, 0, 255, true), *rgbStyle.bg) + "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}, }, }, - } - - for _, s := range scenarios { - t.Run(s.name, s.test) - } -} - -func TestSettingAtributes(t *testing.T) { - type scenario struct { - name string - test func(s TextStyle) TextStyle - expectedOpts []color.Color - } - - scenarios := []scenario{ - { - "no attributes", - func(s TextStyle) TextStyle { - return s - }, - []color.Color{}, - }, { - "set single attribute", - func(s TextStyle) TextStyle { - return s.SetBold(true) + "rgb fg color", + []TextStyle{New().SetFg(rgbPink)}, + TextStyle{ + fg: &rgbPink, + style: color.NewRGBStyle(rgbPinkLib).SetOpts(color.Opts{}), }, - []color.Color{color.OpBold}, }, { - "set multiple attributes", - func(s TextStyle) TextStyle { - return s.SetBold(true).SetUnderline(true) + "rgb fg and bg color", + []TextStyle{New().SetFg(rgbPink).SetBg(rgbYellow)}, + TextStyle{ + fg: &rgbPink, + bg: &rgbYellow, + style: color.NewRGBStyle(rgbPinkLib, rgbYellowLib).SetOpts(color.Opts{}), }, - []color.Color{color.OpBold, color.OpUnderscore}, }, { - "unset a attributes", - func(s TextStyle) TextStyle { - return s.SetBold(true).SetBold(false) + "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}), }, - []color.Color{}, }, { - "unset a attributes with multiple attributes", - func(s TextStyle) TextStyle { - return s.SetBold(true).SetUnderline(true).SetBold(false) + "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{}), }, - []color.Color{color.OpUnderscore}, - }, - { - "unset all attributes with multiple attributes", - func(s TextStyle) TextStyle { - return s.SetBold(true).SetUnderline(true).SetBold(false).SetUnderline(false) - }, - []color.Color{}, }, } for _, s := range scenarios { t.Run(s.name, func(t *testing.T) { - // Test basic style - style := New(color.FgRed, 0) - basicStyle, ok := style.(BasicTextStyle) - assert.True(t, ok, "New(..) should return a interface of type BasicTextStyle") - basicStyle, ok = s.test(basicStyle).(BasicTextStyle) - assert.True(t, ok, "underlaying type should not be changed after test") - assert.Len(t, basicStyle.opts, len(s.expectedOpts)) - for _, opt := range basicStyle.opts { - assert.Contains(t, s.expectedOpts, opt) - } - for _, opt := range s.expectedOpts { - assert.Contains(t, basicStyle.style, opt) - } - - // Test RGB style - rgbStyle := New(color.FgRed, 0).(BasicTextStyle).convertToRGB() - rgbStyle, ok = s.test(rgbStyle).(RGBTextStyle) - assert.True(t, ok, "underlaying type should not be changed after test") - assert.Len(t, rgbStyle.opts, len(s.expectedOpts)) - for _, opt := range rgbStyle.opts { - assert.Contains(t, s.expectedOpts, opt) + style := New() + for _, other := range s.toMerge { + style = style.MergeStyle(other) } + assert.Equal(t, s.expectedStyle, style) }) } } diff --git a/pkg/gui/style/text_style.go b/pkg/gui/style/text_style.go index d2bfccaeb..fd893a2be 100644 --- a/pkg/gui/style/text_style.go +++ b/pkg/gui/style/text_style.go @@ -134,11 +134,13 @@ func (b TextStyle) deriveRGBStyle() *color.RGBStyle { style := &color.RGBStyle{} if b.fg != nil { - style.SetFg(*b.fg.ToRGB().rgb) + style.SetFg(*b.fg.ToRGB(false).rgb) } if b.bg != nil { - style.SetBg(*b.bg.ToRGB().rgb) + // We need to convert the bg firstly to a foreground color, + // For more info see + style.SetBg(*b.bg.ToRGB(true).rgb) } style.SetOpts(b.decoration.ToOpts()) |