summaryrefslogtreecommitdiffstats
path: root/pkg/gui/style
diff options
context:
space:
mode:
authormjarkk <mkopenga@gmail.com>2021-07-31 20:48:40 +0200
committermjarkk <mkopenga@gmail.com>2021-07-31 20:53:49 +0200
commit0662733ad95583c5ec2fb701f2b5bbcaf54d5e86 (patch)
tree4a7d9c5543c020480be0e2a24dd5a635f169e93f /pkg/gui/style
parent3c78ba7ed3dbaf912417b11269a4b8a21f256145 (diff)
add tests for color changes
Diffstat (limited to 'pkg/gui/style')
-rw-r--r--pkg/gui/style/color.go9
-rw-r--r--pkg/gui/style/decoration.go6
-rw-r--r--pkg/gui/style/style_test.go339
-rw-r--r--pkg/gui/style/text_style.go6
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())