using System.Text;
using DodoSSH.Client.Ssh;
using NSubstitute;
namespace DodoSSH.Client.Terminal.Tests;
///
/// The renderer gate: the one place the workspace waits on something outside the process.
///
///
/// The gate itself is not in question. drops frames when nothing
/// is attached, so a session opened before the renderer arrives loses its SessionOpened frame and
/// streams output at a terminal that was never created — and that it opens when a renderer does attach is
/// covered by . What is worth a test here is the
/// half that used to be missing: waiting for a renderer that never arrives has to end.
///
public sealed class TerminalWorkspaceTests
{
[Fact]
public async Task WaitingForARendererThatNeverAttaches_GivesUp()
{
// The shipped failure this stands in for is a WebView2 that never initialises — no Evergreen
// runtime, an install blocked by policy, an AppContainer that cannot reach loopback. From this
// side they are identical and all look like the listener being up with nothing ever connecting
// to it. Before the wait was bounded this test would have hung instead of failing.
await using var workspace = CreateWorkspace(TimeSpan.FromMilliseconds(250));
workspace.Start();
await Should.ThrowAsync(async () =>
await workspace.WaitForRendererAsync(TestContext.Current.CancellationToken));
}
[Fact]
public async Task WaitingForARenderer_ObeysItsCancellationToken()
{
// The timeout is the backstop; the caller's token is what makes a Connect the user gave up on
// return at once rather than sitting out the rest of the wait. The timeout here is long enough
// that only cancellation can end this.
await using var workspace = CreateWorkspace(TimeSpan.FromMinutes(5));
workspace.Start();
using var cancellation = new CancellationTokenSource();
var wait = workspace.WaitForRendererAsync(cancellation.Token);
await cancellation.CancelAsync();
await Should.ThrowAsync(async () => await wait);
}
///
/// The connection factory is never reached: every test here stops at the gate, and reaching a real
/// host would make this a network test.
///
private static TerminalWorkspace CreateWorkspace(TimeSpan rendererTimeout) =>
new(
new InMemoryTerminalAssetProvider(
new Dictionary(StringComparer.Ordinal)
{
[TerminalDataPlane.PagePath] = new(
"text/html; charset=utf-8",
Encoding.UTF8.GetBytes("")),
}),
Substitute.For(),
TimeProvider.System,
new TerminalWorkspaceOptions { RendererTimeout = rendererTimeout });
}