No ToTask, ever — the test exemption is retracted

The guidance used to say tests were the one sanctioned place to bridge an observable to a Task. That exemption never held: a Task completed from inside an Rx pipeline resumes its awaiter inline, on the signalling thread, still inside Rx's trampoline, and everything the continuation does inherits that — so a bridge written "only in a test" changes how the code under test runs.

⚠️ Corrected 2026-09-18 — the paragraph below was wrong, and this is where the mistake started. It recommended awaiting the observable directly. That is the same defect in fewer characters: Rx's own awaiter is an AsyncSubject<T> that completes its continuation from inside OnCompleted, so it resumes inline on the signalling thread exactly as .ToTask() does. What a test should write instead is an assertion on the stream — await x.Should().Within(TestTimeouts.Convergence).Emit("because") — or, where an async Task signature genuinely must take a value out of one, .Await(ct) / .ObserveCompletion(reportLateFault, ct). The original text is kept below so the record of what was recommended, and for how long, stays readable. See In-mesh test cases no longer continue on the portal's own threads (2026-09-18).

A test now awaits the observable directly under a timeout (await hub.DisposalCompleted.FirstOrDefaultAsync().Timeout(30.Seconds())), exactly as production code composes and subscribes. The only place a bridge may still work is inside an activity, where nothing mesh-side runs after the await — and even there the reactive shape is preferred.

Reconnecting…
The connection to the server was interrupted. Trying to restore it…
Trying again…
The connection could not be restored. Reloading the page…
The server was updated. Reloading the page to pick up the latest version.