feat(ui): richer diff viewer + surface child roadblocks on parents
- UnifiedDiffParser detects added/deleted/renamed/binary files; diff modal shows a file list, binary/empty placeholders, and can diff a merged task by commit range after its worktree is gone - DetailsIslandViewModel flags children needing attention (failed, cancelled, awaiting review, or with roadblocks) on the parent - GitService gains worktree head-commit/range support; planning chain, merge orchestration, and session manager tweaks with updated tests - refresh app/installer/worker icons Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
109
tests/ClaudeDo.Ui.Tests/ViewModels/UnifiedDiffParserTests.cs
Normal file
109
tests/ClaudeDo.Ui.Tests/ViewModels/UnifiedDiffParserTests.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
using System.Linq;
|
||||
using ClaudeDo.Ui.ViewModels.Modals;
|
||||
|
||||
namespace ClaudeDo.Ui.Tests.ViewModels;
|
||||
|
||||
public class UnifiedDiffParserTests
|
||||
{
|
||||
[Fact]
|
||||
public void Modified_file_counts_additions_and_deletions()
|
||||
{
|
||||
const string raw =
|
||||
"diff --git a/src/Foo.cs b/src/Foo.cs\n" +
|
||||
"index 111..222 100644\n" +
|
||||
"--- a/src/Foo.cs\n" +
|
||||
"+++ b/src/Foo.cs\n" +
|
||||
"@@ -1,3 +1,3 @@\n" +
|
||||
" ctx\n" +
|
||||
"-old\n" +
|
||||
"+new\n";
|
||||
|
||||
var file = Assert.Single(UnifiedDiffParser.Parse(raw));
|
||||
Assert.Equal("src/Foo.cs", file.Path);
|
||||
Assert.Equal(DiffFileStatus.Modified, file.Status);
|
||||
Assert.Equal("M", file.StatusCode);
|
||||
Assert.Equal(1, file.Additions);
|
||||
Assert.Equal(1, file.Deletions);
|
||||
Assert.True(file.HasLines);
|
||||
Assert.False(file.IsBinary);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void New_file_is_marked_added()
|
||||
{
|
||||
const string raw =
|
||||
"diff --git a/New.cs b/New.cs\n" +
|
||||
"new file mode 100644\n" +
|
||||
"index 000..abc\n" +
|
||||
"--- /dev/null\n" +
|
||||
"+++ b/New.cs\n" +
|
||||
"@@ -0,0 +1,1 @@\n" +
|
||||
"+hello\n";
|
||||
|
||||
var file = Assert.Single(UnifiedDiffParser.Parse(raw));
|
||||
Assert.Equal(DiffFileStatus.Added, file.Status);
|
||||
Assert.Equal("A", file.StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Deleted_file_is_marked_deleted()
|
||||
{
|
||||
const string raw =
|
||||
"diff --git a/Gone.cs b/Gone.cs\n" +
|
||||
"deleted file mode 100644\n" +
|
||||
"index abc..000\n" +
|
||||
"--- a/Gone.cs\n" +
|
||||
"+++ /dev/null\n" +
|
||||
"@@ -1,1 +0,0 @@\n" +
|
||||
"-bye\n";
|
||||
|
||||
var file = Assert.Single(UnifiedDiffParser.Parse(raw));
|
||||
Assert.Equal(DiffFileStatus.Deleted, file.Status);
|
||||
Assert.Equal("D", file.StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Rename_captures_old_and_new_path()
|
||||
{
|
||||
const string raw =
|
||||
"diff --git a/Old.cs b/New.cs\n" +
|
||||
"similarity index 100%\n" +
|
||||
"rename from Old.cs\n" +
|
||||
"rename to New.cs\n";
|
||||
|
||||
var file = Assert.Single(UnifiedDiffParser.Parse(raw));
|
||||
Assert.Equal(DiffFileStatus.Renamed, file.Status);
|
||||
Assert.Equal("R", file.StatusCode);
|
||||
Assert.Equal("Old.cs", file.OldPath);
|
||||
Assert.Equal("New.cs", file.Path);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Binary_file_is_flagged_with_no_lines()
|
||||
{
|
||||
const string raw =
|
||||
"diff --git a/img.png b/img.png\n" +
|
||||
"new file mode 100644\n" +
|
||||
"index 000..abc\n" +
|
||||
"Binary files /dev/null and b/img.png differ\n";
|
||||
|
||||
var file = Assert.Single(UnifiedDiffParser.Parse(raw));
|
||||
Assert.True(file.IsBinary);
|
||||
Assert.False(file.HasLines);
|
||||
Assert.False(file.IsEmptyContent);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Empty_new_file_reports_empty_content()
|
||||
{
|
||||
const string raw =
|
||||
"diff --git a/Empty.txt b/Empty.txt\n" +
|
||||
"new file mode 100644\n" +
|
||||
"index 000..000\n";
|
||||
|
||||
var file = Assert.Single(UnifiedDiffParser.Parse(raw));
|
||||
Assert.Equal(DiffFileStatus.Added, file.Status);
|
||||
Assert.False(file.HasLines);
|
||||
Assert.True(file.IsEmptyContent);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user