Something went wrong. Try again.
changelog generator & diff tool stormlightlabs.github.io/git-storm
changelog changeset markdown golang git
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388package diff
import ( "strings" "testing")
func TestSplitDiff_Diff(t *testing.T) { tests := []struct { name string oldContent string newContent string width int showLineNum bool expectFunc func(result DiffResult) bool }{ { name: "empty files", oldContent: "", newContent: "", width: 80, showLineNum: true, expectFunc: func(result DiffResult) bool { return result.View == ViewSplit && strings.Contains(result.Content, "No changes") }, }, { name: "identical files", oldContent: "line1\nline2\nline3", newContent: "line1\nline2\nline3", width: 100, showLineNum: true, expectFunc: func(result DiffResult) bool { return result.View == ViewSplit && strings.Contains(result.Content, "line1") && strings.Contains(result.Content, "line2") && strings.Contains(result.Content, "line3") }, }, { name: "simple insertion", oldContent: "line1\nline3", newContent: "line1\nline2\nline3", width: 100, showLineNum: true, expectFunc: func(result DiffResult) bool { return result.View == ViewSplit && strings.Contains(result.Content, "line1") && strings.Contains(result.Content, "line2") && strings.Contains(result.Content, "line3") && strings.Contains(result.Content, SymbolAdd) }, }, { name: "simple deletion", oldContent: "line1\nline2\nline3", newContent: "line1\nline3", width: 100, showLineNum: true, expectFunc: func(result DiffResult) bool { return result.View == ViewSplit && strings.Contains(result.Content, "line1") && strings.Contains(result.Content, "line2") && strings.Contains(result.Content, "line3") && strings.Contains(result.Content, SymbolDeleteLine) }, }, { name: "replacement", oldContent: "github.com/foo/bar v1.0.0", newContent: "github.com/foo/bar v2.0.0", width: 120, showLineNum: true, expectFunc: func(result DiffResult) bool { return result.View == ViewSplit && strings.Contains(result.Content, "v1.0.0") && strings.Contains(result.Content, "v2.0.0") && strings.Contains(result.Content, SymbolChange) }, }, { name: "without line numbers", oldContent: "old line", newContent: "new line", width: 100, showLineNum: false, expectFunc: func(result DiffResult) bool { return result.View == ViewSplit && strings.Contains(result.Content, "old line") && strings.Contains(result.Content, "new line") }, }, }
for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { splitter := &SplitDiff{ TerminalWidth: tt.width, ShowLineNumbers: tt.showLineNum, Expanded: true, }
result, err := splitter.Diff( strings.NewReader(tt.oldContent), strings.NewReader(tt.newContent), ViewSplit, )
if err != nil { t.Fatalf("unexpected error: %v", err) }
if !tt.expectFunc(result) { t.Errorf("result did not meet expectations.\nGot:\n%s", result.Content) } }) }}
func TestUnifiedDiff_Diff(t *testing.T) { tests := []struct { name string oldContent string newContent string width int showLineNum bool expectFunc func(result DiffResult) bool }{ { name: "empty files", oldContent: "", newContent: "", width: 80, showLineNum: true, expectFunc: func(result DiffResult) bool { return result.View == ViewUnified && strings.Contains(result.Content, "No changes") }, }, { name: "identical files", oldContent: "line1\nline2\nline3", newContent: "line1\nline2\nline3", width: 100, showLineNum: true, expectFunc: func(result DiffResult) bool { return result.View == ViewUnified && strings.Contains(result.Content, "line1") && strings.Contains(result.Content, "line2") && strings.Contains(result.Content, "line3") }, }, { name: "simple insertion", oldContent: "line1\nline3", newContent: "line1\nline2\nline3", width: 100, showLineNum: true, expectFunc: func(result DiffResult) bool { return result.View == ViewUnified && strings.Contains(result.Content, "line1") && strings.Contains(result.Content, "+line2") && strings.Contains(result.Content, "line3") }, }, { name: "simple deletion", oldContent: "line1\nline2\nline3", newContent: "line1\nline3", width: 100, showLineNum: true, expectFunc: func(result DiffResult) bool { return result.View == ViewUnified && strings.Contains(result.Content, "line1") && strings.Contains(result.Content, "-line2") && strings.Contains(result.Content, "line3") }, }, { name: "replacement", oldContent: "github.com/foo/bar v1.0.0", newContent: "github.com/foo/bar v2.0.0", width: 120, showLineNum: true, expectFunc: func(result DiffResult) bool { return result.View == ViewUnified && strings.Contains(result.Content, "-github.com/foo/bar v1.0.0") && strings.Contains(result.Content, "+github.com/foo/bar v2.0.0") }, }, { name: "without line numbers", oldContent: "old line", newContent: "new line", width: 100, showLineNum: false, expectFunc: func(result DiffResult) bool { return result.View == ViewUnified && strings.Contains(result.Content, "-old line") && strings.Contains(result.Content, "+new line") }, }, }
for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { unifier := &UnifiedDiff{ TerminalWidth: tt.width, ShowLineNumbers: tt.showLineNum, Expanded: true, }
result, err := unifier.Diff( strings.NewReader(tt.oldContent), strings.NewReader(tt.newContent), ViewUnified, )
if err != nil { t.Fatalf("unexpected error: %v", err) }
if !tt.expectFunc(result) { t.Errorf("result did not meet expectations.\nGot:\n%s", result.Content) } }) }}
func TestSplitLines(t *testing.T) { tests := []struct { name string input string expected []string }{ { name: "empty string", input: "", expected: []string{}, }, { name: "single line no newline", input: "hello", expected: []string{"hello"}, }, { name: "single line with newline", input: "hello\n", expected: []string{"hello"}, }, { name: "multiple lines", input: "line1\nline2\nline3", expected: []string{"line1", "line2", "line3"}, }, { name: "multiple lines with trailing newline", input: "line1\nline2\nline3\n", expected: []string{"line1", "line2", "line3"}, }, { name: "empty lines preserved", input: "line1\n\nline3", expected: []string{"line1", "", "line3"}, }, { name: "only newlines", input: "\n\n\n", expected: []string{"", "", ""}, }, }
for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := splitLines(tt.input)
if len(result) != len(tt.expected) { t.Fatalf("expected %d lines, got %d", len(tt.expected), len(result)) }
for i := range result { if result[i] != tt.expected[i] { t.Errorf("line %d: expected %q, got %q", i, tt.expected[i], result[i]) } } }) }}
func TestDiffViewKind_String(t *testing.T) { tests := []struct { kind DiffViewKind expected string }{ {ViewUnified, "Unified"}, {ViewSplit, "Split"}, {ViewHunk, "Hunk"}, {ViewInline, "Inline"}, {ViewRich, "Rich"}, {ViewSource, "Source"}, {DiffViewKind(999), "Unknown"}, }
for _, tt := range tests { t.Run(tt.expected, func(t *testing.T) { result := tt.kind.String() if result != tt.expected { t.Errorf("expected %q, got %q", tt.expected, result) } }) }}
func TestSplitDiff_CompressedView(t *testing.T) { oldLines := make([]string, 50) newLines := make([]string, 50) for i := range 50 { oldLines[i] = "unchanged line" newLines[i] = "unchanged line" }
newLines[25] = "changed line"
oldContent := strings.Join(oldLines, "\n") newContent := strings.Join(newLines, "\n")
splitter := &SplitDiff{ TerminalWidth: 100, ShowLineNumbers: true, Expanded: false, }
result, err := splitter.Diff( strings.NewReader(oldContent), strings.NewReader(newContent), ViewSplit, )
if err != nil { t.Fatalf("unexpected error: %v", err) }
if !strings.Contains(result.Content, "unchanged lines") { t.Errorf("expected compression indicator in output") }
if !strings.Contains(result.Content, "changed line") { t.Errorf("expected changed line in output") }}
func TestUnifiedDiff_CompressedView(t *testing.T) { oldLines := make([]string, 50) newLines := make([]string, 50) for i := range 50 { oldLines[i] = "unchanged line" newLines[i] = "unchanged line" }
newLines[25] = "changed line"
oldContent := strings.Join(oldLines, "\n") newContent := strings.Join(newLines, "\n")
unifier := &UnifiedDiff{ TerminalWidth: 100, ShowLineNumbers: true, Expanded: false, // Enable compression }
result, err := unifier.Diff( strings.NewReader(oldContent), strings.NewReader(newContent), ViewUnified, )
if err != nil { t.Fatalf("unexpected error: %v", err) }
if !strings.Contains(result.Content, "unchanged lines") { t.Errorf("expected compression indicator in output") }
if !strings.Contains(result.Content, "+changed line") { t.Errorf("expected changed line with + prefix in output") }}