The map had no memory. Every visit started at the same overview, and a system worth returning to had to be found again by name each time. A mark on the readout and on a body's panel now keeps it, a Bookmarks tab lists what has been kept, and choosing one goes there — a star by flying into its system, a body by opening its page. Local storage, not an account. This map asks nobody to sign in, and a list of stars somebody liked is not worth a server. Every read of that store is defensive, because it is a string a person can edit, another tab can write, and a browser can refuse to hand over at all: a bad entry is skipped rather than losing the rest, duplicates are collapsed since two entries for one place would each toggle the other's control, the list is bounded so a hand-edited store cannot decide how much this renders, and where storage is denied outright the bookmarks still work for the visit — they just do not outlive it. The name is stored alongside the id rather than looked up. That way the list reads before the catalogues have loaded, and a bookmark to something a later catalogue no longer holds still says what it was instead of decaying into a bare number. The tab is offered even when it is empty, and says what the mark does. A tab that appears only once you have already found the feature is a tab that never taught anyone anything. Choosing a kept place hands the panel back to the readout, which is the same move as choosing a search result and for the same reason: the panel has done its job and the thing to look at is now the scene. That behaviour is what the end-to-end spec caught missing — the readout it asserted on did not exist, because the panel that had just been used was still covering it. Verified: build clean, 587/587 unit, 11/11 end-to-end including a spec that keeps Earth, leaves the page, comes back to it from the list and forgets it, and one that keeps Proxima Centauri, flies out to the field and flies back in by what was kept. Design detector clean, screenshots at 1440x900 and 390x844. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016jxMkwA2rbicdGxHosecYi
End-to-end tests (Playwright)
These tests run the real Angular dev server in a real Chromium browser, covering interactions
that unit/component tests (under src/**/*.spec.ts, run via npm test) can only approximate
under jsdom — most importantly the galaxy↔system camera-flight transitions (real WebGPU/
WebGL2 initialization + raycaster picking) and cross-view search navigation.
Running
npm run e2e # headless run against a freshly started dev server
npx playwright test --ui # interactive UI mode
npx playwright show-report
playwright.config.ts starts npm run start -- --port=4300 automatically and waits for it to
respond before running the suite (webServer.reuseExistingServer is true outside CI, so an
already-running ng serve on port 4300 is reused instead of starting a second one). Port 4300
is used instead of the Angular CLI's conventional 4200 to avoid colliding with an unrelated
server a developer might already have running there.
Notes
- The Sun (
Sol) is always placed at the coordinate-system origin (x=0,y=0,z=0), which is exactly where the default galaxy-view camera looks.camera-flight.spec.tsrelies on this to reliably click-select it by clicking the center of the canvas, without needing pixel-perfect knowledge of the star field's on-screen layout. - Data (bootstrap fetch of
stars.bin/stars-index.json/bodies.json/exoplanets.json/deepsky.json) loads asynchronously after the page loads, so tests poll (re-click/re-check) rather than assume the scene is interactive immediately afterpage.goto(). deepsky.jsonis the one dataset the scene treats as optional: it only feeds the decorative backdrop, so a failure to load it is logged and the star field comes up regardless.