Files
ClaudeDo/tests/ClaudeDo.Ui.Tests/ViewModels/PlanningDiffViewModelTests.cs
mika kuns 59d72635da test(ui): rebase IWorkerClient fakes onto shared StubWorkerClient base
Add a StubWorkerClient base implementing the full IWorkerClient surface so
the planning/conflict/diff test fakes only override the members they exercise.
Eliminates the constructor-drift duplication across the three fakes.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-30 09:39:12 +02:00

132 lines
4.4 KiB
C#

using ClaudeDo.Data.Models;
using ClaudeDo.Ui.Services;
using ClaudeDo.Ui.ViewModels.Planning;
namespace ClaudeDo.Ui.Tests.ViewModels;
public class PlanningDiffViewModelTests
{
private sealed class FakePlanningWorker : StubWorkerClient
{
public IReadOnlyList<SubtaskDiffDto> AggregateResult { get; set; } = Array.Empty<SubtaskDiffDto>();
public CombinedDiffResultDto? CombinedResult { get; set; }
public override Task<IReadOnlyList<SubtaskDiffDto>> GetPlanningAggregateAsync(string planningTaskId) =>
Task.FromResult(AggregateResult);
public override Task<CombinedDiffResultDto?> BuildPlanningIntegrationBranchAsync(string planningTaskId, string targetBranch) =>
Task.FromResult(CombinedResult);
}
[Fact]
public async Task InitializeAsync_PopulatesSubtasks()
{
var fake = new FakePlanningWorker
{
AggregateResult = new[]
{
new SubtaskDiffDto("s1", "First", "branch-1", "base1", "head1", "+1 -0", "diff1"),
new SubtaskDiffDto("s2", "Second", "branch-2", "base2", "head2", "+2 -1", "diff2"),
}
};
var vm = new PlanningDiffViewModel(fake, "plan-1", "main");
await vm.InitializeAsync();
Assert.Equal(2, vm.Subtasks.Count);
Assert.Equal(vm.Subtasks[0], vm.SelectedSubtask);
}
[Fact]
public async Task SelectingSubtask_InGroupedMode_SetsDisplayedDiff()
{
var fake = new FakePlanningWorker
{
AggregateResult = new[]
{
new SubtaskDiffDto("s1", "First", "b1", "base1", "head1", null, "DIFF-A"),
new SubtaskDiffDto("s2", "Second", "b2", "base2", "head2", null, "DIFF-B"),
}
};
var vm = new PlanningDiffViewModel(fake, "plan-1", "main");
await vm.InitializeAsync();
vm.SelectedSubtask = vm.Subtasks[1];
Assert.Equal("DIFF-B", vm.DisplayedDiff);
}
[Fact]
public async Task ToggleCombined_Success_DisplaysUnifiedDiff()
{
var fake = new FakePlanningWorker
{
AggregateResult = new[]
{
new SubtaskDiffDto("s1", "First", "b1", "base1", "head1", null, "DIFF-A"),
},
CombinedResult = new CombinedDiffResultDto(true, "integration-branch", "COMBINED-DIFF", null, null),
};
var vm = new PlanningDiffViewModel(fake, "plan-1", "main");
await vm.InitializeAsync();
vm.IsCombinedMode = true;
// Wait for the async toggle command to complete
var deadline = DateTime.UtcNow.AddSeconds(5);
while (DateTime.UtcNow < deadline && vm.IsLoadingCombined)
await Task.Delay(10);
Assert.Equal("COMBINED-DIFF", vm.DisplayedDiff);
Assert.Null(vm.CombinedWarning);
}
[Fact]
public async Task ToggleCombined_Conflict_ShowsWarning()
{
var fake = new FakePlanningWorker
{
AggregateResult = new[]
{
new SubtaskDiffDto("s1", "First", "b1", "base1", "head1", null, "DIFF-A"),
},
CombinedResult = new CombinedDiffResultDto(false, null, null, "subtask-42", new[] { "a.cs", "b.cs" }),
};
var vm = new PlanningDiffViewModel(fake, "plan-1", "main");
await vm.InitializeAsync();
vm.IsCombinedMode = true;
var deadline = DateTime.UtcNow.AddSeconds(5);
while (DateTime.UtcNow < deadline && vm.IsLoadingCombined)
await Task.Delay(10);
Assert.NotNull(vm.CombinedWarning);
Assert.Contains("subtask-42", vm.CombinedWarning);
Assert.Contains("2 files", vm.CombinedWarning);
}
[Fact]
public async Task ToggleCombined_HubReturnsNull_ShowsError()
{
var fake = new FakePlanningWorker
{
AggregateResult = new[]
{
new SubtaskDiffDto("s1", "First", "b1", "base1", "head1", null, "DIFF-A"),
},
CombinedResult = null,
};
var vm = new PlanningDiffViewModel(fake, "plan-1", "main");
await vm.InitializeAsync();
vm.IsCombinedMode = true;
var deadline = DateTime.UtcNow.AddSeconds(5);
while (DateTime.UtcNow < deadline && vm.IsLoadingCombined)
await Task.Delay(10);
Assert.NotNull(vm.CombinedWarning);
Assert.NotEmpty(vm.CombinedWarning!);
}
}