fix(ui): show a banner when a ConPTY session dies after startup
InteractiveTerminalViewModel.HasExitedAfterStartup now covers every post-startup death that ExitedAfterStartup alone missed (crash, clean exit, quiet exit inside the grace window) -- previously the tile just stayed looking alive/thinking with zero signal. ConPtyPaneView binds a new banner to it (message + Retry + Close); CanRetry simplifies to "any HasExited state" since the same descriptor factory can relaunch either kind of death. HandlerRestartCoordinator's worker-side auto-restart path is untouched.
This commit is contained in:
@@ -151,6 +151,30 @@ public class ConPtyPaneViewModelTests
|
||||
Assert.True(pane.RetryCommand.CanExecute(null));
|
||||
}
|
||||
|
||||
// ── HasExitedAfterStartup banner (fix: a mid-run death used to leave a silent dead tile — no
|
||||
// StartError, no signal at all) ─────────────────────────────────────────────────────────
|
||||
|
||||
[Fact]
|
||||
public void RetryCommand_Enabled_AfterDeathAfterStartup()
|
||||
{
|
||||
using var pane = NewTaskPane(NeverCompletes);
|
||||
|
||||
DieAfterRunning(pane, exitCode: 1);
|
||||
|
||||
Assert.True(pane.Terminal.HasExitedAfterStartup);
|
||||
Assert.True(pane.RetryCommand.CanExecute(null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExitedBannerText_IncludesExitCode()
|
||||
{
|
||||
using var pane = NewTaskPane(NeverCompletes);
|
||||
|
||||
DieAfterRunning(pane, exitCode: 42);
|
||||
|
||||
Assert.Contains("42", pane.ExitedBannerText);
|
||||
}
|
||||
|
||||
// ── SessionDiedAfterStartup (feeds the worker's usage-limit auto-restart) ────────────────────
|
||||
|
||||
[Fact]
|
||||
|
||||
+25
@@ -36,6 +36,7 @@ public class InteractiveTerminalViewModelTests
|
||||
|
||||
Assert.True(terminal.HasExited);
|
||||
Assert.Null(terminal.StartError);
|
||||
Assert.True(terminal.HasExitedAfterStartup); // no StartError banner, so the host needs this signal instead
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -48,6 +49,30 @@ public class InteractiveTerminalViewModelTests
|
||||
|
||||
Assert.True(terminal.HasExited);
|
||||
Assert.Null(terminal.StartError);
|
||||
Assert.True(terminal.HasExitedAfterStartup);
|
||||
}
|
||||
|
||||
// ── HasExitedAfterStartup (drives the host's "session ended" banner — every death that
|
||||
// ISN'T already covered by StartError) ─────────────────────────────────────────────────
|
||||
|
||||
[Fact]
|
||||
public void FreshTerminal_HasExitedAfterStartupIsFalse()
|
||||
{
|
||||
using var terminal = new InteractiveTerminalViewModel(() => LaunchedAt);
|
||||
|
||||
Assert.False(terminal.HasExitedAfterStartup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessExitsNonzero_WithinGraceWindow_HasExitedAfterStartupIsFalse()
|
||||
{
|
||||
using var terminal = new InteractiveTerminalViewModel(() => LaunchedAt);
|
||||
terminal.IsRunning = true;
|
||||
|
||||
terminal.OnSessionProcessExited(null, 1); // startup failure — StartError covers it instead
|
||||
|
||||
Assert.NotNull(terminal.StartError);
|
||||
Assert.False(terminal.HasExitedAfterStartup);
|
||||
}
|
||||
|
||||
// ── ExitedAfterStartup (a session that ran, then broke -- used to be a silent dead tile;
|
||||
|
||||
Reference in New Issue
Block a user