fix(ui): surface worker connect/restart failures instead of no-opting
WorkerConnectionModalViewModel's StartWorker/RerunInstaller swallowed missing-exe and Process.Start failures behind an empty catch and closed the dialog anyway, looking like success. Now both show an inline error and keep the dialog open; only a real launch closes it. IslandsShellViewModel.RestartWorkerAsync never checked whether the relaunched worker actually stayed up, and its status property was never bound in any view. RestartWorkerService now fails if the new process exits within a short survival window, and the outcome routes through the footer error/success strip instead of the dead RestartWorkerStatus. InstallArtifactLocator.Find() is now virtual and its two subclasses unsealed so tests can fake exe resolution without touching the real filesystem/registry.
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using ClaudeDo.Data.Models;
|
||||
using ClaudeDo.Ui.ViewModels;
|
||||
|
||||
namespace ClaudeDo.Ui.Tests;
|
||||
|
||||
// Covers the "restart worker" footer feedback fix: RestartWorkerStatus used to be set but was
|
||||
// never bound in any view, so a died-on-launch worker (e.g. a port conflict, see #292) restarted
|
||||
// silently. RestartWorkerOperation is a test seam standing in for the real kill-and-relaunch +
|
||||
// short-timeout survival check, so these tests only assert the success/failure routing to the
|
||||
// shared footer strip (WorkerLogText/WorkerLogLevel), not real process spawning.
|
||||
public class IslandsShellViewModelRestartWorkerTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task ProcessSurvives_FlashesFooterSuccess()
|
||||
{
|
||||
var vm = new IslandsShellViewModel { RestartWorkerOperation = () => Task.CompletedTask };
|
||||
|
||||
await vm.RestartWorkerCommand.ExecuteAsync(null);
|
||||
|
||||
Assert.Equal(WorkerLogLevel.Success, vm.WorkerLogLevel);
|
||||
Assert.Contains("restarted", vm.WorkerLogText);
|
||||
Assert.True(vm.IsWorkerLogVisible);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ProcessDiesWithinTimeout_FlashesFooterError()
|
||||
{
|
||||
var vm = new IslandsShellViewModel
|
||||
{
|
||||
RestartWorkerOperation = () => throw new InvalidOperationException("worker process exited immediately (code 1)")
|
||||
};
|
||||
|
||||
await vm.RestartWorkerCommand.ExecuteAsync(null);
|
||||
|
||||
Assert.Equal(WorkerLogLevel.Error, vm.WorkerLogLevel);
|
||||
Assert.Contains("worker process exited immediately", vm.WorkerLogText);
|
||||
Assert.True(vm.IsWorkerLogVisible);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user