Files
ng-eventually/.project/concepts/e2e-harness/ng-e2e-helpers/usage_polyfill-e2e.md

5.7 KiB

type, summary, against
type summary against
usage What the polyfill's own end-to-end suites call from ng-e2e-helpers, under which constraints, and where the fit still costs them code ng-e2e-helpers@1.0.0-dev.2

usage_polyfill-e2e — the polyfill's end-to-end suites

The consumer is the end-to-end suite of @ng-eventually/polyfill: four entry points under that package's e2e/ — a batch of SDK checks against the broker, an applicative suite driving the example application, a reactivity probe, and a cold-start reproduction — plus the page module they share.

This consumer lives in the same repository as the provider. That changes nothing about what is declared here: the engagement is what these suites are written against, and anything they call that is NOT listed below is theirs to fix if it moves.

Consumed surface

Boundswithin, armSuiteDeadline, closeQuietly, enclosingBound, firstLine. within is the most-called entry of the whole package here: every bridge call into the application iframe goes through it.

Measurementmeasured. Nothing reads record, timingsWanted or printTimings directly; the E2E_TIMINGS=1 output is consumed as printed output, not as a call.

Browser and profileslaunchWatchedContext, closeContext, newPage, and the type RunProfile. newRunProfile and isAlive are never called: profiles are always obtained through a wallet call.

WalletmintWalletProfile (the batch wallet, minted once per run), mintWalletProfileKeepingContext (the cold-start reproduction, which needs the very first application session over a never-used wallet), emptyProfileContext + importWalletFile (the reconnection journey), exportWalletBytes (serving the wallet from the application's own bundle), and the type WalletCredentials.

Broker crossingsetupBrokerPage in all four suites, completeBrokerLogin in the applicative one.

ServingserveOnEphemeralPort, for both the SDK page and the example application's bundle.

Known failure modesbrowserTrouble, frameTrouble.

ReportdeclareSuite and the types JourneyDeclaration, Prerequisite. Used by the applicative suite only.

ConstantsBROKER_ROUND_TRIP_MS, NEW_PAGE_MS, both as inputs to enclosingBound rather than as waits of their own.

Everything else the package exports is offered and NOT consumed here — the screen inventory (BROKER_SCREENS, WALLET_APP, WALLET_CREATION, WALLET_IMPORT, brokerRedirectFor, and the screen types), createWalletInContext, exportWalletFile, mintWalletBytes, DEFAULT_WALLET_NAME, browserLost, lossDeclared, the exported error classes, and the remaining *_MS constants. It is safely evolvable as far as these suites are concerned.

Constraints

The browser types come from the helpers. Frame, Page and BrowserContext are taken from ng-e2e-helpers, which re-exports them, rather than from playwright directly — so these suites never depend on resolving the same copy of it, which is the position a consumer in another repository is in anyway.

Every suite mints its own physical wallet, per run. Nothing is carried between runs and no wallet is reused, so a run's result never depends on a previous one. The batch wallet's NAME is stable and its identity is not: two runs sharing the name share nothing else.

The password is supplied, never defaulted. These suites also read the barrier's displayed password back off its own screen and pass it to importWalletFile, which is the only way to prove that what the barrier shows is what opens the file. A defaulted password would make that check vacuous.

An enclosing bound is at least the sum of what it encloses. These suites compute every enclosure with enclosingBound rather than picking a round number, because an enclosure that fires first reports "the journey timed out" and never names the step that hung.

A wait must not be entered unbounded. Playwright's frame.evaluate waits forever, so no bridge call is made outside within.

Frictions

frame.evaluate has no bound, and three suites each wrote the same wrapper. A sdk(frame, method, …args) helper — within(…, BRIDGE_MS, () => frame.evaluate(…)) — is duplicated verbatim in three of the four entry points. The bound is the single most important one in each of them, and the package offers nothing to obtain it from. A bounded evaluate helper here would delete the duplication and stop each new suite re-deriving it.

"Measured and bounded" is one intent and two calls. Sizing a bound from its own measurement is the discipline this package prescribes, yet the applicative suite composes measured(what, ms, (bound) => within(what, bound, task)) by hand — and the indexing layer's suite, in another repository, wrote the same line byte for byte. A helper that pairs them belongs on the engagement.

declareSuite fits a journey suite and not a check batch. Only the applicative suite uses it; the other three declare a local record/check pair and print their own summary, because their shape is a flat list of checks discovered as the run goes rather than named journeys declared up front. The up-front declaration is exactly what makes the report bounded, so this is not a request to relax it — but three of four suites falling outside it suggests the package covers one of two real shapes.

The screen inventory is exported and unreachable in practice. BROKER_SCREENS and the WALLET_* page descriptions are published, but a suite that crosses the broker with setupBrokerPage never needs them, and one that wanted to extend the crossing has no supported way to hand a modified inventory back in. As it stands they read as internals that happen to be exported.