Files
ng-eventually/examples/notebook
Sylvain Duchesne aa6bbc436e test(e2e): les parcours applicatifs passent par l'app d'exemple
Une seconde suite e2e, `packages/sdk/e2e/notebook.ts` (`test:e2e:app`), qui pilote
`examples/notebook` par le DOM — une page de navigateur par identité — contre le même
broker réel.

**Pourquoi une seconde suite plutôt qu'un ajout dans la première.** `run.ts` parle à un
sac de méthodes sur `window.__sdk` : cela prouve que les fonctions TOURNENT, jamais
qu'une application peut s'écrire avec. L'écart a déjà coûté un défaut livré — l'inbox
d'un document était verte ici et inutilisable en pratique, parce que le harnais pouvait
faire traverser une adresse d'une identité à l'autre par une variable, canal qu'aucune
application n'a. Ici, rien ne traverse que ce qui traverse dans la vie : la RÉFÉRENCE
d'une note, recopiée d'un écran, et un identifiant tapé dans un champ.

Quatre parcours, qui se lisent comme des parcours :

- Bob lit la note publique d'Alice depuis sa seule référence — la propriété pour
  laquelle l'émulation du store public existe, vérifiée bout en bout et sans qu'aucune
  clé ne circule ;
- la note protégée d'Alice reste fermée jusqu'à ce qu'elle la partage — même geste côté
  Bob, issue opposée, décidée par où la note se trouve ;
- Bob laisse un message sur la note d'Alice, et seule Alice le lit — il TROUVE l'adresse
  depuis la note, personne ne la lui donne ;
- la liste de chacun ne contient que ses notes.

**Deux étapes quittent `run.ts`** (`documentInboxDeposit`, `capsShareCap`), avec un
commentaire disant où elles sont parties : ce sont des parcours, et ils valent plus joués
sur deux écrans que sur deux appels d'une même page. Ce qui reste là-bas est ce qu'une
application ne fait pas : primitives, caractérisation, régressions de démarrage à froid.

**Trois défauts trouvés en écrivant la suite**, tous côté application et invisibles pour
le harnais : `connectedUser()` devait être attendu à la connexion (sinon une note qu'on
vient de vous partager se lit comme illisible — ce qui ressemble à un problème de droits
alors que c'est un problème de moment) ; une réponse périmée restait affichée à côté
d'une question fraîche ; et changer de portée ne rafraîchissait pas la liste. L'app
affiche désormais la référence de chaque note — ce qu'aucun écran ne montre, aucun
utilisateur ne peut le faire circuler.

Corrigé au passage : le `.gitignore` pointait encore `packages/client/`, si bien que le
commit de renommage a embarqué le profil Playwright de la suite e2e (226 fichiers). Les
chemins sont réalignés et le commit précédent a été amendé — rien n'était poussé.

179 tests unitaires, e2e 40/40 (3,2 min) et applicatif 10/10 (0,7 min).
2026-08-07 11:20:58 +02:00
..

Notebook — the library's example application

A minimal application written against @ng-eventually/sdk, in plain DOM.

It exists for two reasons, and the second is the one that matters.

It shows how to use the library. Every call in app.ts is what a real consumer writes. There is no test scaffolding, no privileged import, no reaching into the library's internals — it resolves @ng-eventually/sdk as an external consumer does. If something reads awkwardly here, it reads awkwardly for everyone.

It is what the applicative e2e suite drives (packages/sdk/e2e/notebook.ts, bun run test:e2e:app). The other suite talks to a bag of methods on window.__sdk, which proves the functions run but never that an application can be written with them — and that gap shipped a real defect once: a document's inbox was green in tests and unusable in practice, because the harness handed an address across an identity boundary through a variable, something no application can do. Here each identity is its own browser page, and the only values that cross between them are the ones that cross in life: a note's reference, copied off one screen, and an identifier typed into a field.

It has already paid for itself: writing it surfaced that UnionSubject returned string where the values are always document references (so a consumer had to cast whatever it had just read before passing it back), and that the access gate normalized what a user typed but not what the URL carried.

What it exercises

Signing in, writing notes by scope, listing one's own, reading a note from its bare reference, handing a reader the key to a protected note, opening a note for messages, leaving a message on someone else's note, and reacting to changes.

The four journeys the suite runs, and what each proves:

Journey What it proves
Bob reads Alice's PUBLIC note from its reference alone A public store serves its notes' keys — a bare reference is enough, and no key ever crosses
Alice's PROTECTED note stays shut until she shares it The same gesture, the opposite outcome, decided by where the note sits and not by what was sent
Bob leaves a message on Alice's note, and only Alice reads it A depositor FINDS the address from the note itself; depositing grants no reading
Each actor's list holds their own notes The boundary, seen from the only place that matters: the screen

It has also found three defects of its own, each an application-side one the harness could not see: connectedUser() had to be awaited at sign-in (a note just shared with you reads as unreadable otherwise), a stale answer stayed on screen beside a fresh question, and changing the scope did not refresh the list.

Running it

cd packages/sdk && bun run test:e2e:app builds it, serves it, and drives it against the real broker. To open it by hand you need a wallet: serve the folder with a bundled app.js and a /shared-wallet.ngw, and set __NOTEBOOK_WALLET_PASSWORD__.