返回 DeepSeek-Reasonix
diffview_test.go
根目录 / internal / cli / diffview_test.go
1 package cli
2
3 import (
4 "strings"
5 "testing"
6
7 "github.com/charmbracelet/colorprofile"
8 "github.com/charmbracelet/x/ansi"
9
10 "reasonix/internal/event"
11 )
12
13 func TestDiffBodyDropsHeadersKeepsLineNumbers(t *testing.T) {
14 d := event.FileDiff{Diff: "--- a/x.go\n+++ b/x.go\n@@ -7 +7 @@\n-old\n+new\n", Added: 1, Removed: 1}
15 joined := strings.Join(diffBody(d, "x.go", 80, 40), "\n")
16 if strings.Contains(joined, "--- a/") || strings.Contains(joined, "+++ b/") || strings.Contains(joined, "@@") {
17 t.Fatalf("file/hunk headers should be dropped, got:\n%s", joined)
18 }
19 for _, want := range []string{"old", "new", "7"} {
20 if !strings.Contains(joined, want) {
21 t.Fatalf("missing %q (code or line number) in:\n%s", want, joined)
22 }
23 }
24 }
25
26 func TestDiffBodyFolds(t *testing.T) {
27 var b strings.Builder
28 b.WriteString("--- a/x\n+++ b/x\n@@ -1,8 +1,8 @@\n")
29 for i := 0; i < 8; i++ {
30 b.WriteString("+line\n")
31 }
32 body := diffBody(event.FileDiff{Diff: b.String()}, "x", 80, 5)
33 if len(body) != 5 {
34 t.Fatalf("want 5 rows (4 content + footer), got %d:\n%s", len(body), strings.Join(body, "\n"))
35 }
36 // 8 rendered add rows minus the 4 kept = 4 folded.
37 if !strings.Contains(body[len(body)-1], "4") {
38 t.Fatalf("footer should report 4 folded lines, got %q", body[len(body)-1])
39 }
40 }
41
42 func TestDiffBodyNoFoldWhenShort(t *testing.T) {
43 d := event.FileDiff{Diff: "@@ -1 +1 @@\n+a\n"}
44 if got := len(diffBody(d, "x", 80, 40)); got != 1 {
45 t.Fatalf("want 1 unfolded row, got %d", got)
46 }
47 }
48
49 func TestDiffBlockHeader(t *testing.T) {
50 d := event.FileDiff{Diff: "@@ -1 +1 @@\n-a\n+b\n", Added: 1, Removed: 1}
51 block := diffBlock("edit_file", `{"path":"pkg/x.go"}`, d, 80, 40)
52 if len(block) == 0 || !strings.Contains(block[0], "Update") || !strings.Contains(block[0], "pkg/x.go") {
53 t.Fatalf("header should name verb + path, got %q", block[0])
54 }
55 }
56
57 func TestDiffBlockNilWithoutDiff(t *testing.T) {
58 if diffBlock("write_file", `{"path":"x"}`, event.FileDiff{}, 80, 40) != nil {
59 t.Fatal("no diff should yield no block")
60 }
61 }
62
63 func TestDiffPath(t *testing.T) {
64 if got := diffPath(`{"path":"a/b.go","old_string":"x"}`); got != "a/b.go" {
65 t.Fatalf("got %q", got)
66 }
67 if got := diffPath(`not json`); got != "" {
68 t.Fatalf("malformed args should yield empty path, got %q", got)
69 }
70 }
71
72 func TestDiffBarReappliesBackground(t *testing.T) {
73 defer func(prev colorprofile.Profile) { activeColorProfile = prev }(activeColorProfile)
74 activeColorProfile = colorprofile.ANSI256
75
76 line := diffBar('+', "a + b", "x.go", 40, bgDiffAdd, fgDiffAdd, 12, 3)
77 // Syntax highlighting emits multiple \033[0m resets; each must re-arm the bar
78 // background, so the bg sequence appears more than once and the row ends reset.
79 if strings.Count(line, bgDiffAdd) < 2 {
80 t.Fatalf("background not re-applied after chroma resets: %q", line)
81 }
82 if !strings.HasSuffix(line, ansiReset) {
83 t.Fatalf("row should end with a reset: %q", line)
84 }
85 }
86
87 func TestActiveDiffChromaStyleFollowsCLITheme(t *testing.T) {
88 previous := activeCLITheme
89 defer func() { activeCLITheme = previous }()
90
91 tests := []struct {
92 name string
93 theme cliPalette
94 want string
95 }{
96 {name: "dark", theme: cliDarkTheme, want: "github-dark"},
97 {name: "light", theme: cliLightTheme, want: "github"},
98 }
99 for _, tt := range tests {
100 t.Run(tt.name, func(t *testing.T) {
101 activeCLITheme = tt.theme
102 if got := activeDiffChromaStyle().Name; got != tt.want {
103 t.Fatalf("diff syntax style = %q, want %q", got, tt.want)
104 }
105 })
106 }
107 }
108
109 func TestHighlightCodeUpdatesOnThemeSwitch(t *testing.T) {
110 previousTheme := activeCLITheme
111 previousProfile := activeColorProfile
112 defer func() {
113 activeCLITheme = previousTheme
114 activeColorProfile = previousProfile
115 }()
116 activeColorProfile = colorprofile.ANSI256
117
118 code := `const answer = "value"`
119 activeCLITheme = cliLightTheme
120 light := highlightCode("example.ts", code)
121 activeCLITheme = cliDarkTheme
122 dark := highlightCode("example.ts", code)
123
124 if light == dark {
125 t.Fatalf("light and dark themes produced identical highlighting: %q", light)
126 }
127 for name, got := range map[string]string{"light": light, "dark": dark} {
128 if plain := ansi.Strip(got); plain != code {
129 t.Fatalf("%s theme changed code text: got %q, want %q", name, plain, code)
130 }
131 }
132 }
133
133 lines GO