Shared browser drive with a gated login
Browser scenarios share one implementation of signing in, and a repository check refuses any browser wait that neither gates on the backend being up nor says in writing why it does not need to.
- What it is
- Guarantee — a guarantee that holds on its own.
- What it does
- The login every browser scenario performs is defined once — so there is no ungated path left to author for those steps.
- Where it stops
- One wait is deliberately not shared.
Every browser scenario signs in through one implementation, and that implementation gates each wait that cannot succeed while the backend is away. A repository check enforces the same rule on waits a scenario writes for itself: a browser wait is either inside the gate or carries a comment saying why it does not need to be, and anything else fails the check.
The problem it solves
A browser wait absorbs a slow backend; it does not absorb an absent one. A development stack restarts under compile churn, and when it does, a wait for a password field expires with a message naming a locator. That message is indistinguishable from a genuinely broken form, and it was reported as a product failure. The investigation cost more than the outage.
Widening the timeout does not fix it, and that was measured rather than assumed. Outages were timed at sixty-eight seconds, about a hundred, and two hundred and seventeen. The distribution is long-tailed because recompiles stack, so any fixed number is eventually walked through. Gating costs nothing when the stack is up and absorbs the whole outage when it is not.
The deeper problem is that this rule was already written down, already understood, and applied to one of four scenario files. The other three each carried their own copy of the login, one of them waiting on the identical locator on the identical form, because the incident named one scenario and nobody asked which other files contained the same wait.
What it does
The login every browser scenario performs is defined once — so there is no ungated path left to author for those steps.
It owns the wait for the form to paint, the two-phase login where an address is submitted and the form then swaps to a password method, the reload that returns a fresh unauthenticated form, and the second-factor variant. Where the application lands afterwards is left to the scenario, because that is the scenario’s subject.
The gate waits for health within the readiness ceiling, runs the step, and then does the one thing that makes the whole mechanism worth having: if the step failed AND the backend is not answering, it raises an error naming the infrastructure while preserving the original as its cause. If the backend IS answering, the original error is rethrown completely untouched — because then it is a real product failure and must read as one.
It deliberately does not retry. An adapter subcommand is replayable and a browser step is not: re-running a click that already created a row would corrupt the scenario’s own state and could manufacture a pass. The gate is side-effect-free in both directions.
What the shared drive cannot cover is covered by a check. It scans every file that imports the browser surface, finds each wait, and requires it to be either inside the gate or carrying an explicit declaration with a reason. Files are discovered by IMPORT rather than by filename, so a browser scenario named anything at all is covered the day it is written. The check does not decide which waits need the gate; it refuses to let the answer stay implicit — the guarantee that was actually available.
The declaration is a decision rather than a suppression, and the distinction earns its keep: a pure client render after an already-gated navigation genuinely should not be gated, and reflexively gating everything would blur which waits depend on the backend at all.
Limits
One wait is deliberately not shared. Asserting that the authenticated shell has painted looks duplicated and is not: the password scenarios wait on a client render after an already-gated navigation, while the single-sign-on scenario has no preceding gate and its one wait absorbs the entire return leg, two backend round trips. Same locator, materially different dependency.
One scenario keeps a private copy of the second-factor drive on purpose, because its subject is the challenge screen itself rather than passing through it — there, the waits ARE the assertions.
The gate does not rescue a step that fails while a restart lands in the middle of it. The step still fails; it just fails saying the right thing.
The check is lexical rather than a full parse, over a tokeniser that tracks strings, templates and comments, covering a fixed list of wait calls. Its search roots are named in the file — if browser scenarios ever move outside them, it would inspect nothing and report success, which is why the file says so at its own failure message.