feat(ui): confirm before closing a running ConPTY session

The tile's own X killed a live Claude session with no confirmation, unlike
the semantically similar Abandon-run action. Gate the close behind the same
ConfirmAsync mechanism, but only when Terminal.IsRunning -- a dead session
(StartError or exited-after-startup) still closes immediately since the X
there is pure cleanup.
This commit is contained in:
mika kuns
2026-09-10 13:52:36 +02:00
parent 395874d834
commit eb62371430
4 changed files with 76 additions and 3 deletions
@@ -1072,4 +1072,59 @@ public class MissionControlViewModelTests : IDisposable
Assert.Equal(new[] { "t1", "t2" }, worker.Cancelled);
Assert.Empty(vm.ConPtySessions);
}
// The tile's own X must not silently kill a live session -- a reflex click on a running pane
// has to go through the same confirm mechanism as Abandon Run.
[Fact]
public async Task Close_RunningSession_ConfirmDeclined_LeavesSessionOpen()
{
var worker = new FakeWorker();
using var vm = BuildVm(worker);
await vm.OpenConPtySessionAsync("t1");
var pane = vm.ConPtySessions[0];
pane.Terminal.IsRunning = true;
string? confirmMessage = null;
vm.ConfirmAsync = msg => { confirmMessage = msg; return Task.FromResult(false); };
pane.CloseCommand.Execute(null);
await Task.Delay(20);
Assert.NotNull(confirmMessage);
Assert.Single(vm.ConPtySessions);
}
[Fact]
public async Task Close_RunningSession_ConfirmAccepted_ClosesPane()
{
var worker = new FakeWorker();
using var vm = BuildVm(worker);
await vm.OpenConPtySessionAsync("t1");
var pane = vm.ConPtySessions[0];
pane.Terminal.IsRunning = true;
vm.ConfirmAsync = _ => Task.FromResult(true);
pane.CloseCommand.Execute(null);
await Task.Delay(20);
Assert.Empty(vm.ConPtySessions);
}
// A dead session (start failure or exited-after-startup) is pure cleanup -- no confirm needed.
[Fact]
public async Task Close_DeadSession_ClosesWithoutConfirming()
{
var worker = new FakeWorker();
using var vm = BuildVm(worker);
await vm.OpenConPtySessionAsync("t1");
var pane = vm.ConPtySessions[0];
pane.Terminal.ReportStartFailure("boom");
var confirmCalled = false;
vm.ConfirmAsync = _ => { confirmCalled = true; return Task.FromResult(true); };
pane.CloseCommand.Execute(null);
await Task.Delay(20);
Assert.False(confirmCalled);
Assert.Empty(vm.ConPtySessions);
}
}