The six Lifecycle/*Recovery hosted services now broadcast one
OperationProgress("startup-recovery", <phase>, current, total) message each
after they finish, instead of leaving the UI on a bare "connecting" text
during worker startup. IslandsShellViewModel subscribes and swaps in
"Recovering... (i/n)" (existing ops.worker.startupRecovery key, no locale
changes) while Worker.IsReconnecting is true, and clears it once actually
connected so a later transient reconnect doesn't replay stale text.
OperationProgress broadcasts to Clients.All with no replay-on-connect, so a
UI that hasn't finished its SignalR handshake yet can miss some or all of
these messages and simply keep showing "connecting" as before -- accepted
rather than adding a cached-state + reconnect-replay path (mirroring
RefreshExternalMergeConflictsAsync) for what is a fast, best-effort,
local-only startup sweep with no UI-visible failure mode beyond that.
57 lines
1.8 KiB
C#
57 lines
1.8 KiB
C#
using ClaudeDo.Ui.ViewModels;
|
|
using Xunit;
|
|
|
|
namespace ClaudeDo.Ui.Tests;
|
|
|
|
// Covers C2: the six Lifecycle/*Recovery startup sweeps broadcast OperationProgress under the
|
|
// stable "startup-recovery" opKey; the shell replaces the generic "connecting" text with it
|
|
// while the worker is reconnecting.
|
|
public class IslandsShellViewModelStartupRecoveryTests
|
|
{
|
|
private sealed class ReconnectingWorkerClient : StubWorkerClient
|
|
{
|
|
public override bool IsReconnecting => true;
|
|
}
|
|
|
|
[Fact]
|
|
public void StartupRecoveryProgress_ReplacesConnectingText()
|
|
{
|
|
var vm = new IslandsShellViewModel();
|
|
var worker = new ReconnectingWorkerClient();
|
|
vm.Worker = worker;
|
|
worker.OperationProgressEvent += vm.OnOperationProgress;
|
|
|
|
worker.RaiseOperationProgress("startup-recovery", "attachments", 3, 6);
|
|
|
|
Assert.Contains("3/6", vm.ConnectionText);
|
|
}
|
|
|
|
[Fact]
|
|
public void StartupRecoveryProgress_WithoutTotal_ShowsLabelOnly()
|
|
{
|
|
var vm = new IslandsShellViewModel();
|
|
var worker = new ReconnectingWorkerClient();
|
|
vm.Worker = worker;
|
|
worker.OperationProgressEvent += vm.OnOperationProgress;
|
|
|
|
worker.RaiseOperationProgress("startup-recovery", "stale-tasks", 0, 0);
|
|
|
|
Assert.DoesNotContain("/", vm.ConnectionText);
|
|
Assert.NotEqual(string.Empty, vm.ConnectionText);
|
|
}
|
|
|
|
[Fact]
|
|
public void ForeignOpKey_DoesNotChangeConnectionText()
|
|
{
|
|
var vm = new IslandsShellViewModel();
|
|
var worker = new ReconnectingWorkerClient();
|
|
vm.Worker = worker;
|
|
worker.OperationProgressEvent += vm.OnOperationProgress;
|
|
var before = vm.ConnectionText;
|
|
|
|
worker.RaiseOperationProgress("merge:task-123", "merging", 0, 0);
|
|
|
|
Assert.Equal(before, vm.ConnectionText);
|
|
}
|
|
}
|