One run, watched as it happens.
Async-iterable over RunEvent: runStart, one test per finished test, notice and
browserLog as they arrive, and runEnd carrying the complete RunResult. The same
event shape a WatchSession produces, so a progress display written against one works
against the other.
The run does not start until you consume it. Not an optimization — the correctness property that makes the feed lossless. A browser cannot be told to slow down, so a run started before anyone was reading would either drop events or buffer them all; starting on the first read means the producer never outruns the consumer by more than one scheduling turn. Awaiting TestSession.result counts as consuming, so a caller that only wants the answer still gets one without iterating.
// Defined, not invoked: a real session launches a browser. async function progress(session: TestSession) { for await (const event of session) { if (event.kind === 'test') process.stdout.write('.'); } return (await session.result()).counts; }
droppedEvents: number
How many events the feed dropped because a consumer fell behind. 0 in every ordinary run.
The feed is capped, so a consumer that stalls under a flood of page output loses the oldest events. That has to be visible: RunResult.browserLogsDropped already keeps the result path honest about the same trade, and a silent gap in the event path would be the one kind of loss a consumer cannot detect for itself.
The finished run. Starts it if nothing has yet, and resolves with the same
RunResult the final runEnd event carries — never undefined, which is the whole
reason this is a session rather than a bare event stream.
Awaiting it twice is free: the second call returns the first's result.
abort(): Promise<void>
Cuts the run short. The browser drops the rest of its queue and the run ends where it is,
with aborted: true on the result — which TestSession.result still resolves with, so
an aborted run is answered rather than left hanging.
Resolves once the run has finished unwinding. Aborting before the run starts makes it a no-op that ends the session immediately.
The same events as iterating the session, as a Stream — so the combinators are
there without a Stream.from wrapper.
The session stays a HANDLE rather than becoming a Stream: every combinator returns a new
Stream, so session.filter(…) would hand back an object with no close() and a live
browser with no owner.
// Defined, not invoked: a real session launches a browser. async function firstTen(session: TestSession) { return await session.events().filter((e) => e.kind === 'test').take(10).collect(); }
close(): Promise<void>
Closes the session, ending iteration. Idempotent; implied by await using.
[[Symbol.asyncDispose]](): Promise<void>
Closes the session at the end of an await using block.