Files
ng-helpers/.project/concepts/indexing/ng-e2e-helpers/usage_ng-helpers.md
T
Sylvain Duchesne aeb8c7d157 docs: l'engagement de la couche d'indexation, et ses deux déclarations
Le dépôt gagne sa doctrine et ses contrats, dans le régime bidirectionnel.

Il publie son engagement — ce qu'un consommateur peut attendre de l'indexation —
et déclare ce qu'il consomme lui-même, du polyfill et de ng-e2e-helpers. Les
deux déclarations sont écrites depuis les appels réels, pas depuis ce que la
surface offre : un usage non déclaré est la faute du consommateur en cas de
rupture, et une surface offerte mais non déclarée reste librement modifiable.

Version 1.0.0, pas 0.1.0 : sous semver, 0.x ne promet rien du tout, donc le
majeur ne porte son signal qu'à partir de 1. Ce dépôt étant sur main, c'est une
version pleine et non une pré-version.
2026-08-17 10:10:23 +02:00

50 lines
4.0 KiB
Markdown

---
type: usage
summary: What this repo's end-to-end suite calls from ng-e2e-helpers, the peer-dependency constraint it must respect, and the gaps it fills itself
against: ng-e2e-helpers@1.0.0-dev.1
---
# usage_ng-helpers — `@ng-helpers/indexing`'s end-to-end suite on `ng-e2e-helpers`
The consumer is this repository's end-to-end suite: one run that builds a small indexing application, serves it, gets real people into it through the real broker, and drives depositing and curating between them.
Everything generic — the wallet lifecycle, the broker crossing, per-run profiles, bounds, the report shape, the recognition of the known browser failure modes — comes from the engagement and is **used, never reimplemented**. What is specific to this repository is the page that carries our application and the name its runs mint, and nothing else.
## Consumed surface
**Bounds**`within`, `armSuiteDeadline`, `closeQuietly`, `firstLine`.
**Measurement**`measured`.
**Browser and profiles**`launchWatchedContext`, `closeContext`, `newPage`, and the type `RunProfile`.
**Wallet**`mintWalletProfile` and the type `WalletCredentials`. Each run mints its own.
**Broker crossing**`setupBrokerPage`.
**Serving**`serveOnEphemeralPort`, for the application bundle.
**Known failure modes**`browserTrouble`, wired as the suite's `diagnose`.
**Report**`declareSuite` and the type `Prerequisite`.
**Constants**`BROKER_ROUND_TRIP_MS`, `NEW_PAGE_MS`.
Everything else the engagement offers is NOT consumed here: the screen inventory and its types, `completeBrokerLogin`, `emptyProfileContext`, `importWalletFile`, `exportWalletBytes`/`exportWalletFile`, `mintWalletBytes`, `mintWalletProfileKeepingContext`, `createWalletInContext`, `newRunProfile`, `isAlive`, `browserLost`, `lossDeclared`, `enclosingBound`, `frameTrouble`, the exported error classes, and the remaining `*_MS` constants. It is safely evolvable as far as this suite is concerned.
## Constraints
**The browser types are DERIVED from the helpers, never imported from `playwright` here.** The engagement declares Playwright a peer dependency, and this package reaches it as symlinked files — so TypeScript resolves the helpers' `playwright` from where those files really live. Importing the driver in this repository as well produced two structurally different copies of `BrowserContext`, and a context this suite had opened could not be handed back to the helper that opens contexts. Taking the types from the calls that return them leaves exactly one set, and a version skew can no longer express itself as a type error in code that is correct.
**One wallet per run, minted, never carried.** The run's wallet name is stable and its identity is not; nothing survives a run, and no result depends on a previous one.
**Nothing generic is reimplemented here.** Where a helper exists, it is called. That is a standing rule for this suite, not a preference — the crossing alone has cost days of misdiagnosis upstream, and a local copy of it would not carry those lessons.
**Every wait is entered bounded.** No page or frame operation runs outside `within` or a helper that bounds it itself.
## Frictions
**Nothing bounds a call into the application iframe.** `frame.evaluate` carries no timeout of its own, so this suite wraps every bridge call itself. The engagement offers no way to obtain that bound, so each consumer re-derives the same wrapper — and the derivation is not free: the calls this suite reached for outside its own wrapper are exactly the ones that can still hang it. A bounded `evaluate` here would delete the wrapper and close the gap in one move.
**"Measured and bounded" is one intent and two calls.** Sizing a bound from its own measurement is the discipline the engagement itself prescribes, yet every step in this suite has to compose `measured(what, ms, (bound) => within(what, bound, task))` by hand. Two consumers writing the same three-line helper is the tell that the pair belongs on the engagement.