Testing
Unit tests cover the pure logic and run on Node 18+ with no dependencies to install.
npm test # or: node --test
What is covered
Unit conversions in both directions and on both scales, heading and climb rate readouts, the low altitude warning, the artificial horizon's angles and ladder, the minimap's projection, its behaviour at the world's edge, and the course it draws on the chart, the keybinding map, the on-screen pads a machine with no keys is flown from and the question that decides whether it wants them, the device tilt those same machines open in and the sensor that reports it, control rates at every sensitivity, the configured start state and the attitude that holds its climb, a start edited to any other condition and the attitude that holds that one, throttle and lift math, the engine and wind mix and its mute, the crash threshold and countdown, the touchdown rules that tell a landing from a crash, the geometry of a runway and the search that sites one, the takeoff a flight is held at, the crossing that carries a bounded world round at its edges, the grid the endless ground is laid on and the promise it makes that no position can see the end of it, the record a terrain keeps of the world it built and the copy that keeps a caller's own edits visible to it, photo mode's state and the names it writes, camera damping, pause toggling, the start screen's rules, start-up progress, menu selection by key and by pointer and the one cursor they share, a list drawn again from a menu whose rows have come and gone, the keys a menu takes back off the flight, the settings panel with its options, its start state fields, its radio group and its held box, and their stored choices, the game modes with their stages, their runs, their courses, the gate test and the gate gone past, the shape a gate is laid as and the angle it has to be flown at, the guidance an approach is given and the stages it is withdrawn over, the reading taken of a landing and the marks it comes to, the rollout it is held for, the stage clock and the board it is recorded on, and the pointer that finds a gate off the screen, the element editor's rows, its steps, and the ground the placements it hands out generate, terrain noise and the mountain formula, the element registry and every generator it holds, the assembled environments, a world laid as one tile of an assembly and the pass that settles what its elements drew at the joins, the day cycle and the light and the sun's place at every hour of it, the wave and the sheen the water is drawn with and the surface they are applied to, the API's option defaults and contract checks, the API document against the surface it describes and that surface against every export the document claims, the example host page against both halves it is meant to prove, page metadata, this documentation site against the pages it claims to have and against the code its pages list - the start fields, the worlds, and the game modes - the API reference page against the document it is built from, the addresses that page hands its headings and the sample markup it prints rather than carries, the one id per address every page is held to, every anchor read against the addresses a page offers rather than against an id it only prints and against the page it points at rather than the page that links it, the converter that builds it and the line it has no rule for, the link check that tells a page the browser opens from a file it downloads, and the static server's path and content type rules.
The suite reads the API reference, the README, and the pages of this site, and fails when one of them has drifted from the code or from the others. A document that has gone stale is a bug the tests catch rather than one a reader finds. The reference page is built from docs/api.md by npm run docs:api rather than written beside it, and the suite renders it again and compares, so what is published is always what the document now says.