Merge branch 'claude/host-connection-top-bar-25d04e'
ci / build and test (push) Successful in 1m23s
ci / android head (push) Failing after 5s
ci / api image (push) Successful in 23s

This commit is contained in:
2026-08-03 14:33:52 +02:00
9 changed files with 591 additions and 172 deletions
@@ -682,6 +682,82 @@ public sealed class ShellFlowTests : IAsyncLifetime
shell.Screen.ShouldBe(ShellScreen.Vault);
}
/// <remarks>
/// The phone's connect menu is drawn over the terminal's own rectangle, so it obeys the rule the palette
/// does: whatever covers the renderer collapses it instead. The surface stays, because the bar the menu
/// was raised from is part of it — see <c>MainWindowViewModel.IsTerminalShowing</c>.
/// </remarks>
[Fact]
public async Task TheConnectSheet_HidesTheRendererAndLeavesTheSurfaceUnderIt()
{
var vault = await ReadyToConnectAsync();
await using var renderer = await FakeRenderer.AttachAsync(workspace, Token);
await vault.ConnectCommand.ExecuteAsync(null);
shell.OpenConnectSheetCommand.Execute(null);
shell.IsConnectSheetOpen.ShouldBeTrue();
shell.IsTerminalShowing.ShouldBeFalse("the sheet draws over the renderer's rectangle");
shell.IsTerminalSurface.ShouldBeTrue("the bar the sheet was raised from is on that surface");
shell.CloseConnectSheetCommand.Execute(null);
shell.IsTerminalShowing.ShouldBeTrue();
}
/// <remarks>
/// The flag holds the renderer blank, so one set while a page was showing would be a sheet nobody can
/// see keeping a terminal hidden that nothing would put back.
/// </remarks>
[Fact]
public async Task TheConnectSheet_RefusesToOpenOverAPage()
{
var vault = await ReadyToConnectAsync();
await using var renderer = await FakeRenderer.AttachAsync(workspace, Token);
await vault.ConnectCommand.ExecuteAsync(null);
shell.ShowScreenCommand.Execute(ShellScreen.Vault);
shell.OpenConnectSheetCommand.Execute(null);
shell.IsConnectSheetOpen.ShouldBeFalse();
}
/// <remarks>
/// Every entry on the menu navigates, and none of them closes the sheet itself: leaving the terminal
/// surface is what lowers it. That is the guarantee worth a test — it is what makes routes nobody wrote
/// the sheet for, like closing the last tab or locking, safe.
/// </remarks>
[Fact]
public async Task LeavingTheTerminal_LowersTheConnectSheetHoweverItIsLeft()
{
var vault = await ReadyToConnectAsync();
await using var renderer = await FakeRenderer.AttachAsync(workspace, Token);
await vault.ConnectCommand.ExecuteAsync(null);
// The menu's own second entry: one screen, over one view model, with the kind of remote chosen by
// the thing that navigates.
shell.OpenConnectSheetCommand.Execute(null);
shell.ShowFilesCommand.Execute(RemoteKind.Bucket);
shell.IsConnectSheetOpen.ShouldBeFalse();
shell.IsBucketsShowing.ShouldBeTrue();
// And a route the sheet was never wired to: back to the terminal, open it, then end the only shell
// there is.
shell.ShowTerminalCommand.Execute(null);
shell.OpenConnectSheetCommand.Execute(null);
shell.IsConnectSheetOpen.ShouldBeTrue();
await shell.CloseTabCommand.ExecuteAsync(shell.Tabs[0]);
shell.IsConnectSheetOpen.ShouldBeFalse("closing the last tab returns the surface to a page");
shell.IsShowingPages.ShouldBeTrue();
}
/// <remarks>
/// A visible WebView with no pane in it reads as the application having broken, so this is the one
/// transition that moves the surface back on its own.