# crate e2e Real end-to-end tests against a fully local, deterministic atproto network (a PDS, jetstream, Constellation, Slingshot, Caddy for TLS on the test handles) — not the public network, so no indexing lag and no dependency on real accounts. These exist for what the unit tests structurally can't cover: the real OAuth wire flow (PAR/PKCE/DPoP against a real PDS), and cross-account behavior that depends on real Constellation indexing (adoption, the edit-inbox). Business logic itself is already covered fast and in isolation by `server/test/promotion_test.gleam` and friends via injected `Deps` stubs — don't duplicate that here. ## One-time setup ```sh make e2e-setup # clones jetstream + microcosm-rs at pinned commits, generates devnet secrets ``` ## Running Three things need to be running: 1. The devnet: `make e2e-up` (wipes any previous devnet state for a clean slate, boots fresh, waits for the PDS to be healthy, seeds the fixed `alice.test`/`bob.test` accounts). 2. crate's own dev server, pointed at the devnet: ```sh SLINGSHOT_URL=http://localhost:6790 \ CONSTELLATION_URL=http://localhost:6789 \ JETSTREAM_URL=http://localhost:8090/subscribe \ UNSAFE_ALLOW_PRIVATE_ENDPOINTS=1 \ ./scripts/dev.sh ``` `JETSTREAM_URL` matters since the appview-first cutover: the shelf and edit-inbox reads are served from our own index, which the consumer fills from the devnet firehose. `UNSAFE_ALLOW_PRIVATE_ENDPOINTS` disables the outbound-endpoint SSRF guard, which otherwise (correctly) rejects the devnet's loopback-http PDS; never set it outside a local devnet. 3. The test suite: `make e2e` (this also does step 1 for you — running it standalone is only useful if you want to poke at the devnet by hand first). `make e2e-down` tears the devnet down and wipes its volumes when you're done. ## Why fixed test handles, not generated per run Caddy's TLS termination and the PDS's network alias are declared per-handle in `devnet/docker-compose.yml` and `devnet/Caddyfile` (atproto's bidirectional handle verification needs a real, if locally-CA-signed, TLS endpoint for each handle — see the devnet's own README for why). Adding a handle means declaring it in both places, not just calling `create-test-accounts.sh` with a new name. `make e2e-up` wipes and reseeds the same two accounts fresh each run instead, which is enough isolation for now — revisit if tests start needing more than two accounts at once. ## Pinned dependencies `devnet/setup.sh` clones `bluesky-social/jetstream` and `microcosm.blue/microcosm-rs` at specific commits, not `main`. Both are under active, fast-moving development with no published container image matching their current `main` — pinning is what keeps this reproducible. Re-pin deliberately (edit the SHAs in `setup.sh`, `rm -rf` the old clones, re-run `make e2e-setup`) when there's a reason to, not by accident.