package ui import ( "image/color" "testing" "github.com/gdamore/tcell/v2" "github.com/rivo/tview" ) func TestParseTerminalAnswers(t *testing.T) { for _, tc := range []struct { name string got string graphics bool bg color.RGBA hasBG bool }{ {"ghostty", "\x1b_Gi=31;OK\x1b\\\x1b]11;rgb:1e1e/1e1e/2e2e\x1b\\\x1b[?62;22c", true, color.RGBA{30, 30, 46, 255}, true}, {"text color too", "\x1b]10;rgb:4c4c/4f4f/6969\x1b\\\x1b]11;rgb:efef/f1f1/f5f5\x1b\\\x1b[?62c", false, color.RGBA{239, 241, 245, 255}, true}, {"bel and two digits", "\x1b]11;rgb:ff/80/00\a\x1b[?1;2c", false, color.RGBA{255, 128, 0, 255}, true}, {"one digit", "\x1b]11;rgb:f/0/8\x1b\\\x1b[?6c", false, color.RGBA{255, 0, 136, 255}, true}, {"only device attributes", "\x1b[?1;2c", false, color.RGBA{}, false}, {"garbage", "\x1b]11;rgb:zz/00/00\x1b\\\x1b[?6c", false, color.RGBA{}, false}, {"nothing", "", false, color.RGBA{}, false}, } { info := parseTerminalAnswers([]byte(tc.got)) if info.graphics != tc.graphics || info.hasBG != tc.hasBG || info.bg != tc.bg { t.Errorf("%s: %+v", tc.name, info) } } } func TestChooseTheme(t *testing.T) { dark := terminalInfo{bg: color.RGBA{30, 30, 46, 255}, hasBG: true} light := terminalInfo{bg: color.RGBA{239, 241, 245, 255}, hasBG: true} for _, tc := range []struct { setting string info terminalInfo want string }{ {"", light, "light"}, {"auto", dark, "dark"}, {"auto", terminalInfo{}, "dark"}, {"dark", light, "dark"}, {"light", dark, "light"}, } { if th, note := chooseTheme(tc.setting, tc.info); th.name != tc.want { t.Errorf("%q with %+v: %s (%s)", tc.setting, tc.info, th.name, note) } } } func TestThemeApply(t *testing.T) { oldStyles, oldCurrent := tview.Styles, current oldNames := map[string]tcell.Color{} for k, v := range tcell.ColorNames { oldNames[k] = v } defer func() { tview.Styles, current = oldStyles, oldCurrent for k, v := range oldNames { tcell.ColorNames[k] = v } }() lightTheme.apply() if tview.Styles.PrimitiveBackgroundColor != lightTheme.bg || tview.Styles.PrimaryTextColor != lightTheme.text { t.Error("tview styles not set") } // Color names in texts mean the theme's colors. if named("yellow") != lightTheme.yellow || tcell.GetColor("black") != lightTheme.bg || tcell.GetColor("white") != lightTheme.text { t.Error("color names not set") } if current.name != "light" { t.Error("current theme not set") } } func TestThemeColorsSurvive256Colors(t *testing.T) { // Every theme color is its own nearest match in the 256-color palette, so // a terminal without 24-bit color shows it exactly and never picks one of // the first 16 colors, which color themes change. palette := make([]tcell.Color, 256) for i := range palette { palette[i] = tcell.PaletteColor(i) } for _, th := range []theme{darkTheme, lightTheme} { for _, c := range []tcell.Color{th.bg, th.text, th.border, th.field, th.fieldMuted, th.list, th.pressed, th.toast, th.gray, th.yellow, th.green, th.red, th.blue, th.purple} { if got := tcell.FindColor(c, palette); got < tcell.PaletteColor(16) { t.Errorf("%s theme: %v maps to palette color %d", th.name, c, got-tcell.ColorValid) } } } }