A Landing Sim That Flies Its Own QA
Final Approach is a browser landing simulator I built for a friend who flies for an airline. Six approaches, from a calm dawn to a microburst on short final. It runs in a tab and keeps working with the network dead.
The interesting part is not the game. I never tested it by playing it. I wrote a harness that flies it.
Try it live
Pick a scenario and fly it. First Light is the gentle one. CAT II Fog gives you needles and nothing out the window until about 400 feet.
Every landing gets scored against the same gates a real crew is held to, and the debrief tells you which one you missed.
The six scenarios
- First Light. Calm dawn air, unlimited visibility. Learn the airplane here.
- Crosswind Kick. Twenty two gusting thirty four, sixty degrees off the nose.
- CAT II Fog. Night, low visibility, decision height 100 feet. Instruments only.
- Valley Circle. A high field at dusk with an offset final and a late alignment turn.
- Engine Out. One engine failed and secured. Constant rudder, asymmetric thrust.
- Frontal Windshear. A microburst on short final, where leaving is the right answer.
Why a harness instead of playing it
A person testing a flight sim can only tell you it felt wrong. That is not a bug report, and it does not catch the thing that quietly broke last week.
So the sim exposes a debug contract, and the harness drives it in headless Chrome. It steps the physics with no rendering, which flies a four minute approach in well under a second.
98 passed, one warning, zero failures, run against the live deployment on August 21 2026. A regression here gets caught by a machine rather than by my friend hitting it mid landing.
What it actually checks
The flight model assertions are the ones that matter, because the audience is a type-rated pilot who will notice if any of them are wrong. Straight from the run:
- Vref at 62 tonnes, flaps 30. Measured 137.00 kt, within the 128 to 152 kt band.
- Critical angle of attack. 15.00 degrees, within 11 to 19 degrees.
- Config drag is real. Holding level took 44.4% N1 clean, 52.5% with the gear out, 60.5% with flaps, 54.2% on the boards.
- Ground effect. 61.2% N1 at 400 feet against 36.0% at 25 feet.
- PAPI geometry. Four white when high, one white on path, zero white when low.
- ILS needles. Glideslope at 0.99 dots when flown high, localizer at 1.39 dots after 18 seconds of aileron and rudder.
- Asymmetric thrust. 5.8 degrees of drift in 12 seconds with feet on the floor.
- The microburst. A 44 kt headwind at 900 feet became 3 kt by 200 feet.
The six suites and what each one covers
- Boot health, 8 checks. First frame, no console errors, no failed requests, six scenarios exposed, fonts actually loaded.
- Flight model correctness, 29 checks. The aerodynamics above, plus stall break, true airspeed at altitude, and the briefed crosswind component.
- Full auto-flown approaches, 40 checks. All six scenarios flown end to end.
- Rendering and responsive layout, 11 checks. No horizontal overflow at four widths, a non-blank scene per scenario, frame rate in heavy weather.
- Offline resilience, 3 checks. Boots, plays and scores with the network dead.
- Logbook API contract, 8 checks. The endpoints answer in the shape the client expects.
It adjudicates the flight, not just the crash
Each auto-flown approach has to reach a conclusion, take at least two minutes, produce a scorecard with every required field, give coaching lines, and rule on the stabilized approach gates at 1000 and 500 feet.
The windshear run is my favorite result. The harness flew a go-around, and the game scored it 96 with the verdict "CORRECT DECISION". Leaving is a pass, not a consolation prize, and the test proves the game still believes that.
Why the bounds never get loosened
Every physics bound encodes something true about a real airplane. If an assertion fails, the sim is wrong, not the test.
The temptation on a red build is to widen the band until it goes green. That turns the harness into decoration. The rule in the repo is to fix the model instead.
Offline is a requirement, not a nice-to-have
Somebody should be able to fly this on a plane. So every logbook call is wrapped with a short timeout and falls back to local storage, and nothing in the interface waits on a network request.
The harness proves it by cutting the network, booting the game, flying a full approach and confirming it still scores.
the whole simulator is one self-contained HTML file. No bundler, no framework, no build step. The only outside request is the font.
What I would take from this into a work setting
This is a game, and the QA thinking is not. Anything with a physics model, a pricing model, or a scoring rule has the same problem: you cannot tell by looking whether it is still right.
The move is to expose a contract, drive it with a machine, and assert on numbers you can defend to the person who knows the domain. That transfers to anything.