Approval-based snapshot testing library for Go (mirror)
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: diff view styling fixes

+165 -34
+3 -3
__snapshots__/test_complex_nested_structure.snap
··· 24 24 "user", 25 25 }, 26 26 Metadata: map[string]interface{}{ 27 - "language": "en", 27 + "language": "en-utf-8", 28 28 "notifications": true, 29 29 "preferences": map[string]interface{}{ 30 - "email_frequency": "weekly", 30 + "email_frequency": "bi-weekly", 31 31 "notifications": true, 32 32 }, 33 - "theme": "dark", 33 + "theme": "darker", 34 34 }, 35 35 }, 36 36 Tags: []string{
+3 -3
__snapshots__/test_complex_nested_structure.snap.new
··· 24 24 "user", 25 25 }, 26 26 Metadata: map[string]interface{}{ 27 - "language": "en-utf-8", 27 + "language": "en", 28 28 "notifications": true, 29 29 "preferences": map[string]interface{}{ 30 - "email_frequency": "bi-weekly", 30 + "email_frequency": "weekly", 31 31 "notifications": true, 32 32 }, 33 - "theme": "darker", 33 + "theme": "dark", 34 34 }, 35 35 }, 36 36 Tags: []string{
+2 -2
cmd/tui/main.go
··· 17 17 var ( 18 18 titleStyle = lipgloss.NewStyle(). 19 19 Bold(true). 20 - Foreground(lipgloss.AdaptiveColor{Light: "8", Dark: "8"}). 20 + Foreground(lipgloss.AdaptiveColor{Light: "5", Dark: "5"}). 21 21 Padding(0, 1) 22 22 23 23 counterStyle = lipgloss.NewStyle(). 24 - Foreground(lipgloss.AdaptiveColor{Light: "5", Dark: "5"}). 24 + Foreground(lipgloss.AdaptiveColor{Light: "8", Dark: "8"}). 25 25 Padding(0, 1) 26 26 27 27 helpStyle = lipgloss.NewStyle().
+3 -3
freeze_test.go
··· 258 258 CreatedAt: time.Date(2023, 1, 15, 10, 30, 0, 0, time.UTC), 259 259 Roles: []string{"admin", "moderator", "user"}, 260 260 Metadata: map[string]any{ 261 - "theme": "darker", 261 + "theme": "dark", 262 262 "notifications": true, 263 - "language": "en-utf-8", 263 + "language": "en", 264 264 "preferences": map[string]any{ 265 - "email_frequency": "bi-weekly", 265 + "email_frequency": "weekly", 266 266 "notifications": true, 267 267 }, 268 268 },
+48 -23
internal/pretty/boxes.go
··· 18 18 snapshotFileName := files.SnapshotFileName(newSnapshot.Test) + ".snap" 19 19 20 20 var sb strings.Builder 21 - sb.WriteString("─── " + "Review Snapshot " + strings.Repeat("─", width-20) + "\n\n") 21 + sb.WriteString("─── " + "Snapshot Diff " + strings.Repeat("─", width-15) + "\n\n") 22 22 23 23 // TODO: maybe make helper functions for this, swap coloring between the key and the value 24 24 // TODO: maybe show the snapshot file name in gray next to the "a/r/s" options ··· 29 29 sb.WriteString(Blue(" test: ") + newSnapshot.Test + "\n") 30 30 sb.WriteString(Blue(" file: ") + snapshotFileName + "\n") 31 31 sb.WriteString("\n") 32 - sb.WriteString(strings.Repeat("─", width) + "\n") 32 + // sb.WriteString(Red(" - old snapshot\n")) 33 + // sb.WriteString(Green(" + new snapshot\n")) 34 + // sb.WriteString("\n") 33 35 34 36 // Calculate max line numbers for proper spacing 35 - maxOldNum, maxNewNum := 0, 0 37 + maxOldNum := 0 38 + maxNewNum := 0 36 39 for _, dl := range diffLines { 37 40 if dl.OldNumber > maxOldNum { 38 41 maxOldNum = dl.OldNumber ··· 41 44 maxNewNum = dl.NewNumber 42 45 } 43 46 } 44 - oldWidth := len(fmt.Sprintf("%d", maxOldNum)) 45 - newWidth := len(fmt.Sprintf("%d", maxNewNum)) 47 + // Use the larger of the two for consistent column width 48 + maxLineNum := maxOldNum 49 + if maxNewNum > maxLineNum { 50 + maxLineNum = maxNewNum 51 + } 52 + lineNumWidth := len(fmt.Sprintf("%d", maxLineNum)) 53 + 54 + // Top bar with corner (account for both line number columns) 55 + topBar := strings.Repeat("─", (lineNumWidth*2)+4) + "┬" + 56 + strings.Repeat("─", width-(lineNumWidth*2)-1) + "\n" 57 + sb.WriteString(topBar) 46 58 47 59 for _, dl := range diffLines { 48 - var oldNumStr, newNumStr string 49 - var prefix string 50 - var formatted string 60 + var leftNum, rightNum, prefix, formatted string 51 61 62 + // FIX: line number coloring is the same between old and new lines 52 63 switch dl.Kind { 53 64 case diff.DiffOld: 54 - oldNumStr = fmt.Sprintf("%*d", oldWidth, dl.OldNumber) 55 - newNumStr = strings.Repeat(" ", newWidth) 56 - prefix = Red("−") 65 + // For removed lines: show old line number on left, space on right, red - 66 + leftNum = Red(fmt.Sprintf("%*d", lineNumWidth, dl.OldNumber)) 67 + rightNum = strings.Repeat(" ", lineNumWidth) 68 + prefix = Red("-") 57 69 formatted = Red(dl.Line) 58 70 case diff.DiffNew: 59 - oldNumStr = strings.Repeat(" ", oldWidth) 60 - newNumStr = fmt.Sprintf("%*d", newWidth, dl.NewNumber) 71 + // For added lines: space on left, new line number on right, green + 72 + leftNum = strings.Repeat(" ", lineNumWidth) 73 + rightNum = Green(fmt.Sprintf("%*d", lineNumWidth, dl.NewNumber)) 61 74 prefix = Green("+") 62 75 formatted = Green(dl.Line) 63 76 case diff.DiffShared: 64 - oldNumStr = fmt.Sprintf("%*d", oldWidth, dl.OldNumber) 65 - newNumStr = fmt.Sprintf("%*d", newWidth, dl.NewNumber) 66 - prefix = " " 77 + // For shared lines: show line number centered, │ separator (not gray) 78 + leftNum = strings.Repeat(" ", lineNumWidth) 79 + rightNum = Gray(fmt.Sprintf("%*d", lineNumWidth, dl.NewNumber)) 80 + prefix = "│" 67 81 formatted = dl.Line 68 82 } 69 83 70 - linePrefix := fmt.Sprintf("%s %s %s", Gray(oldNumStr), Gray(newNumStr), prefix) 71 - display := fmt.Sprintf("%s %s", linePrefix, formatted) 72 - 73 84 // Adjust for actual display length considering ANSI codes 74 - if len(dl.Line) > width-oldWidth-newWidth-8 { 75 - formatted = formatted[:width-oldWidth-newWidth-11] + "..." 76 - display = fmt.Sprintf("%s %s", linePrefix, formatted) 85 + // Account for: 2 spaces padding + 2 line number columns + 2 spaces between + prefix + space 86 + maxContentWidth := width - (lineNumWidth * 2) - 8 87 + if len(dl.Line) > maxContentWidth { 88 + truncated := dl.Line[:maxContentWidth-3] + "..." 89 + switch dl.Kind { 90 + case diff.DiffOld: 91 + formatted = Red(truncated) 92 + case diff.DiffNew: 93 + formatted = Green(truncated) 94 + case diff.DiffShared: 95 + formatted = truncated 96 + } 77 97 } 78 98 99 + display := fmt.Sprintf("%s %s %s %s", leftNum, rightNum, prefix, formatted) 79 100 sb.WriteString(fmt.Sprintf(" %s\n", display)) 80 101 } 81 102 82 - sb.WriteString(strings.Repeat("─", width) + "\n") 103 + // Bottom bar with corner (account for both line number columns) 104 + bottomBar := strings.Repeat("─", (lineNumWidth*2)+4) + "┴" + 105 + strings.Repeat("─", width-(lineNumWidth*2)-1) + "\n" 106 + sb.WriteString(bottomBar) 107 + 83 108 return sb.String() 84 109 } 85 110
+106
internal/pretty/pretty_test.go
··· 1 1 package pretty_test 2 2 3 3 import ( 4 + "fmt" 4 5 "os" 6 + "strings" 5 7 "testing" 6 8 9 + "github.com/ptdewey/freeze/internal/diff" 10 + "github.com/ptdewey/freeze/internal/files" 7 11 "github.com/ptdewey/freeze/internal/pretty" 8 12 ) 9 13 ··· 156 160 } 157 161 return false 158 162 } 163 + 164 + func TestDiffSnapshotBox(t *testing.T) { 165 + os.Unsetenv("NO_COLOR") 166 + os.Setenv("COLUMNS", "100") 167 + defer os.Unsetenv("COLUMNS") 168 + 169 + oldContent := `line1 170 + line2 171 + line3` 172 + 173 + newContent := `line1 174 + modified 175 + line3` 176 + 177 + oldSnap := &files.Snapshot{ 178 + Title: "Test Snapshot", 179 + Test: "TestExample", 180 + Content: oldContent, 181 + } 182 + 183 + newSnap := &files.Snapshot{ 184 + Title: "Test Snapshot", 185 + Test: "TestExample", 186 + Content: newContent, 187 + } 188 + 189 + diffLines := diff.Histogram(oldContent, newContent) 190 + result := pretty.DiffSnapshotBox(oldSnap, newSnap, diffLines) 191 + 192 + // Check that result is not empty 193 + if result == "" { 194 + t.Error("DiffSnapshotBox returned empty string") 195 + } 196 + 197 + // Check for header elements 198 + if !strings.Contains(result, "Snapshot Diff") { 199 + t.Error("Result should contain 'Snapshot Diff' header") 200 + } 201 + if !strings.Contains(result, "Test Snapshot") { 202 + t.Error("Result should contain title") 203 + } 204 + if !strings.Contains(result, "TestExample") { 205 + t.Error("Result should contain test name") 206 + } 207 + 208 + // Check for diff content 209 + if !strings.Contains(result, "line1") { 210 + t.Error("Result should contain 'line1'") 211 + } 212 + if !strings.Contains(result, "modified") { 213 + t.Error("Result should contain 'modified'") 214 + } 215 + if !strings.Contains(result, "line3") { 216 + t.Error("Result should contain 'line3'") 217 + } 218 + 219 + // Print the result for visual inspection 220 + t.Logf("\n%s", result) 221 + } 222 + 223 + func TestDiffSnapshotBoxLargeLineNumbers(t *testing.T) { 224 + os.Unsetenv("NO_COLOR") 225 + os.Setenv("COLUMNS", "120") 226 + defer os.Unsetenv("COLUMNS") 227 + 228 + // Create content with more than 10 lines to test multi-digit line numbers 229 + oldLines := make([]string, 15) 230 + newLines := make([]string, 15) 231 + for i := 0; i < 15; i++ { 232 + oldLines[i] = fmt.Sprintf("line %d", i+1) 233 + newLines[i] = fmt.Sprintf("line %d", i+1) 234 + } 235 + // Modify line 10 236 + oldLines[9] = "line 10 old" 237 + newLines[9] = "line 10 new" 238 + 239 + oldContent := strings.Join(oldLines, "\n") 240 + newContent := strings.Join(newLines, "\n") 241 + 242 + oldSnap := &files.Snapshot{ 243 + Title: "Large Diff Test", 244 + Test: "TestLargeDiff", 245 + Content: oldContent, 246 + } 247 + 248 + newSnap := &files.Snapshot{ 249 + Title: "Large Diff Test", 250 + Test: "TestLargeDiff", 251 + Content: newContent, 252 + } 253 + 254 + diffLines := diff.Histogram(oldContent, newContent) 255 + result := pretty.DiffSnapshotBox(oldSnap, newSnap, diffLines) 256 + 257 + // Check that result is not empty 258 + if result == "" { 259 + t.Error("DiffSnapshotBox returned empty string") 260 + } 261 + 262 + // Print the result for visual inspection 263 + t.Logf("\n%s", result) 264 + }