返回 DeepSeek-Reasonix
theme_sweep_test.go
根目录 / internal / cli / theme_sweep_test.go
1 package cli
2
3 import (
4 "strings"
5 "testing"
6
7 "github.com/charmbracelet/colorprofile"
8 )
9
10 func testSweepRows(width int) (before, after []string) {
11 // mix wide runes, pre-styled text and plain text
12 for range 4 {
13 before = append(before, strings.Repeat("宽", width/2), strings.Repeat("a", width),
14 themeFg(activeCLITheme.warn, strings.Repeat("s", width)))
15 after = append(after, strings.Repeat("窄", width/2), strings.Repeat("b", width),
16 themeFg(activeCLITheme.info, strings.Repeat("t", width)))
17 }
18 return before, after
19 }
20
21 func TestThemeSweepHoldsExactRowWidth(t *testing.T) {
22 defer restoreThemeForTest(activeColorProfile, activeCLITheme)
23 configureCLIThemeWithStyle("dark", "graphite")
24
25 for _, profile := range []colorprofile.Profile{colorprofile.ANSI256, colorprofile.TrueColor} {
26 activeColorProfile = profile
27 const width = 40
28 before, after := testSweepRows(width)
29 s := &themeSweep{before: before, after: after, step: 3, width: width}
30 for s.col = 0; s.col <= width; s.col++ {
31 for i, row := range strings.Split(s.render(), "\n") {
32 if got := visibleWidth(row); got != width {
33 t.Fatalf("%v col=%d row=%d width=%d, want %d: %q", profile, s.col, i, got, width, row)
34 }
35 }
36 }
37 }
38 }
39
40 func TestThemeSweepAdvanceTerminates(t *testing.T) {
41 s := &themeSweep{before: []string{"a"}, after: []string{"b"}, step: 3, width: 80}
42 steps := 0
43 for s.advance() {
44 steps++
45 if steps > themeSweepFrames*4 {
46 t.Fatal("sweep never reached the right edge")
47 }
48 }
49 if s.col < s.width {
50 t.Fatalf("sweep stopped at col %d, want >= %d", s.col, s.width)
51 }
52 }
53
54 func TestThemeSweepSkippedWhenTerminalCannotCarryIt(t *testing.T) {
55 defer restoreThemeForTest(activeColorProfile, activeCLITheme)
56 configureCLIThemeWithStyle("dark", "graphite")
57 dark := activeCLITheme
58 light := resolveCLIThemeWithStyle("light", "sandstone")
59
60 for _, tt := range []struct {
61 name string
62 profile colorprofile.Profile
63 width int
64 state tuiState
65 from cliPalette
66 to cliPalette
67 }{
68 {name: "no colour", profile: colorprofile.NoTTY, width: 80, from: dark, to: light},
69 {name: "too narrow", profile: colorprofile.ANSI256, width: 8, from: dark, to: light},
70 {name: "turn running", profile: colorprofile.ANSI256, width: 80, state: tuiRunning, from: dark, to: light},
71 {name: "same theme", profile: colorprofile.ANSI256, width: 80, from: dark, to: dark},
72 } {
73 t.Run(tt.name, func(t *testing.T) {
74 activeColorProfile = tt.profile
75 m := newTestChatTUI()
76 m.width = tt.width
77 m.state = tt.state
78 if cmd := m.startThemeSweep(tt.from, tt.to); cmd != nil {
79 t.Fatal("sweep should be skipped, switch must stay instant")
80 }
81 if m.themeSweep != nil {
82 t.Fatal("skipped sweep must not freeze the frame")
83 }
84 })
85 }
86 }
87
87 lines GO