test: updated colorscheme related tests. tested loader
All checks were successful
Run Test Suite / test (push) Successful in 35s

This commit is contained in:
Hayden Hargreaves 2026-04-08 12:57:33 -07:00
parent 197cc7681d
commit 4d96c0a531
2 changed files with 170 additions and 10 deletions

View File

@ -9,6 +9,7 @@ import (
"git.gophernest.net/azpect/TextEditor/internal/action"
"git.gophernest.net/azpect/TextEditor/internal/core"
"git.gophernest.net/azpect/TextEditor/internal/theme"
tea "github.com/charmbracelet/bubbletea"
)
@ -5506,6 +5507,12 @@ func TestCmdDeleteBuffer(t *testing.T) {
// ==================================================
func TestCmdColorscheme(t *testing.T) {
pickTheme := func(m *action.MockModel) string {
for name := range m.Themes() {
return name
}
return ""
}
// --------------------------------------------------
// Group 1: Valid name — styles are updated
@ -5540,8 +5547,12 @@ func TestCmdColorscheme(t *testing.T) {
t.Run("valid name sets no error output", func(t *testing.T) {
m := action.NewMockModel()
name := pickTheme(m)
if name == "" {
t.Fatal("expected at least one theme in mock")
}
cmdColorscheme(m, []string{"default"}, false)
cmdColorscheme(m, []string{name}, false)
if m.CommandOutputVal != nil && m.CommandOutputVal.IsError {
t.Error("expected no error output for a valid colorscheme name")
@ -5550,8 +5561,12 @@ func TestCmdColorscheme(t *testing.T) {
t.Run("valid name returns nil tea.Cmd", func(t *testing.T) {
m := action.NewMockModel()
name := pickTheme(m)
if name == "" {
t.Fatal("expected at least one theme in mock")
}
cmd := cmdColorscheme(m, []string{"default"}, false)
cmd := cmdColorscheme(m, []string{name}, false)
if cmd != nil {
t.Error("expected nil tea.Cmd for colorscheme command")
@ -5650,8 +5665,12 @@ func TestCmdColorscheme(t *testing.T) {
t.Run("extra args beyond name do not panic", func(t *testing.T) {
m := action.NewMockModel()
name := pickTheme(m)
if name == "" {
t.Fatal("expected at least one theme in mock")
}
cmdColorscheme(m, []string{"default", "extra", "args"}, false)
cmdColorscheme(m, []string{name, "extra", "args"}, false)
})
// --------------------------------------------------
@ -5660,8 +5679,12 @@ func TestCmdColorscheme(t *testing.T) {
t.Run("force flag with valid name still sets styles", func(t *testing.T) {
m := action.NewMockModel()
name := pickTheme(m)
if name == "" {
t.Fatal("expected at least one theme in mock")
}
cmdColorscheme(m, []string{"default"}, true)
cmdColorscheme(m, []string{name}, true)
if m.CommandOutputVal != nil && m.CommandOutputVal.IsError {
t.Error("expected styles to change with force=true and valid name")
@ -5737,11 +5760,17 @@ func TestCmdListColorschemes(t *testing.T) {
t.Run("commandOutput lines contains known built-in styles", func(t *testing.T) {
m := action.NewMockModel()
m.SetThemes(map[string]theme.EditorTheme{
"kanagawa": {},
"kanagawa-dragon": {},
"kanagawa-lotus": {},
"tokyonight-storm": {},
})
cmdListColorschemes(m, []string{}, false)
lines := m.CommandOutputVal.Lines
known := []string{"default"}
known := []string{"kanagawa", "kanagawa-dragon", "kanagawa-lotus", "tokyonight-storm"}
for _, name := range known {
found := false
for _, l := range lines {
@ -5756,14 +5785,18 @@ func TestCmdListColorschemes(t *testing.T) {
}
})
t.Run("commandOutput lines matches styles.Names()", func(t *testing.T) {
t.Run("commandOutput lines matches themes map size", func(t *testing.T) {
m := action.NewMockModel()
m.SetThemes(map[string]theme.EditorTheme{
"kanagawa": {},
"kanagawa-dragon": {},
"kanagawa-lotus": {},
})
cmdListColorschemes(m, []string{}, false)
expected := []string{"default"}
if len(m.CommandOutputVal.Lines) != len(expected) {
t.Errorf("expected %d colorschemes, got %d", len(expected), len(m.CommandOutputVal.Lines))
if len(m.CommandOutputVal.Lines) != len(m.Themes()) {
t.Errorf("expected %d colorschemes, got %d", len(m.Themes()), len(m.CommandOutputVal.Lines))
}
})
@ -5782,9 +5815,19 @@ func TestCmdListColorschemes(t *testing.T) {
t.Run("args and force are ignored", func(t *testing.T) {
m1 := action.NewMockModel()
m2 := action.NewMockModel()
m1.SetThemes(map[string]theme.EditorTheme{
"kanagawa": {},
"kanagawa-dragon": {},
"kanagawa-lotus": {},
})
m2.SetThemes(map[string]theme.EditorTheme{
"kanagawa": {},
"kanagawa-dragon": {},
"kanagawa-lotus": {},
})
cmdListColorschemes(m1, []string{}, false)
cmdListColorschemes(m2, []string{"default", "extra"}, true)
cmdListColorschemes(m2, []string{"kanagawa", "extra"}, true)
if len(m1.CommandOutputVal.Lines) != len(m2.CommandOutputVal.Lines) {
t.Error("expected args and force to have no effect on list output")

View File

@ -0,0 +1,117 @@
package theme
import (
"fmt"
"testing"
)
func TestLoadEmbeddedThemesJSON_LoadsExpectedThemes(t *testing.T) {
themesJSON, err := LoadEmbeddedThemesJSON()
if err != nil {
t.Fatalf("LoadEmbeddedThemesJSON returned error: %v", err)
}
want := []string{"kanagawa", "kanagawa-dragon", "kanagawa-lotus"}
for _, name := range want {
th, ok := themesJSON[name]
if !ok {
t.Fatalf("expected embedded theme %q to be loaded", name)
}
if th.Name == "" {
t.Fatalf("expected embedded theme %q to have a name", name)
}
if th.Line.BG == "" {
t.Fatalf("expected embedded theme %q to include line background", name)
}
}
}
func TestMapEmbeddedThemeToEditorTheme_MapsStylesAndNormalizesSyntaxKeys(t *testing.T) {
in := map[string]ThemeJSON{
"custom": {
Name: "custom",
Line: ColorStyleJSON{FG: "#dddddd", BG: "#101010"},
Background: ColorStyleJSON{BG: "#101010"},
VisualHighlight: ColorStyleJSON{BG: "#202020"},
Cursors: CursorJSON{
Normal: ColorStyleJSON{FG: "#101010", BG: "#dddddd"},
Insert: ColorStyleJSON{FG: "#101010", BG: "#cccccc"},
Command: ColorStyleJSON{FG: "#101010", BG: "#bbbbbb"},
Replace: ColorStyleJSON{FG: "#101010", BG: "#aaaaaa"},
},
Gutter: GutterJSON{
Default: ColorStyleJSON{FG: "#666666", BG: "#0a0a0a"},
CurrentLine: ColorStyleJSON{FG: "#eeeeee", BG: "#0a0a0a"},
},
StatusBar: StatusBarJSON{
Default: ColorStyleJSON{FG: "#cccccc", BG: "#0a0a0a"},
},
CommandLine: CommandLineJSON{
Error: ColorStyleJSON{FG: "#ff0000", BG: "#101010"},
OutputBorder: ColorStyleJSON{FG: "#dddddd", BG: "#0a0a0a"},
ContinueMessage: ColorStyleJSON{FG: "#00aaff", BG: "#101010"},
},
Syntax: SyntaxJSON{
Group: map[string]string{
" String ": "#00ff00",
},
Exact: map[string]string{
" @KEYWORD.Return ": "#ff00ff",
},
},
},
}
out := MapEmbeddedThemeToEditorTheme(in)
th, ok := out["custom"]
if !ok {
t.Fatalf("expected mapped theme with key %q", "custom")
}
if got := colorHex(th.Line.GetForeground()); got != "#dddddd" {
t.Fatalf("line fg mismatch: got %q want %q", got, "#dddddd")
}
if got := colorHex(th.Line.GetBackground()); got != "#101010" {
t.Fatalf("line bg mismatch: got %q want %q", got, "#101010")
}
if got := colorHex(th.Syntax.Exact["keyword.return"].GetForeground()); got != "#ff00ff" {
t.Fatalf("exact capture fg mismatch: got %q want %q", got, "#ff00ff")
}
if got := colorHex(th.Syntax.Exact["keyword.return"].GetBackground()); got != "#101010" {
t.Fatalf("exact capture bg mismatch: got %q want %q", got, "#101010")
}
if got := colorHex(th.Syntax.Group["string"].GetForeground()); got != "#00ff00" {
t.Fatalf("group capture fg mismatch: got %q want %q", got, "#00ff00")
}
if got := colorHex(th.CommandLine.Error.GetForeground()); got != "#ff0000" {
t.Fatalf("command error fg mismatch: got %q want %q", got, "#ff0000")
}
}
func TestMapEmbededThemeToEditorTheme_AliasMatchesPrimary(t *testing.T) {
in := map[string]ThemeJSON{
"x": {
Name: "x",
Line: ColorStyleJSON{FG: "#ffffff", BG: "#000000"},
Syntax: SyntaxJSON{
Group: map[string]string{"keyword": "#123456"},
},
},
}
a := MapEmbededThemeToEditorTheme(in)
b := MapEmbeddedThemeToEditorTheme(in)
if len(a) != len(b) {
t.Fatalf("alias map size mismatch: %d vs %d", len(a), len(b))
}
if colorHex(a["x"].Syntax.Group["keyword"].GetForeground()) != colorHex(b["x"].Syntax.Group["keyword"].GetForeground()) {
t.Fatalf("alias should produce identical mapped styles")
}
}
func colorHex(c any) string {
return fmt.Sprint(c)
}