From 2dbbe23332f98e727774148be9e55e49518e98bd Mon Sep 17 00:00:00 2001 From: fireshaper Date: Mon, 5 Oct 2026 19:37:16 -0400 Subject: [PATCH] Step 12.4: end-to-end: offline progress Co-Authored-By: Claude Opus 5.5 --- DECISIONS.md | 4 ++++ apps/web/e2e/12-4-offline-progress.e2e.ts | 27 +++++++++++++++++++++++ memory-bank/progress.md | 2 +- 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 apps/web/e2e/12-4-offline-progress.e2e.ts diff --git a/DECISIONS.md b/DECISIONS.md index 1716e52..1298155 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -1277,3 +1277,7 @@ Implementation decisions not spelled out in `memory-bank/implementation-plan.md` - **The end-to-end tests drive the real UI for the steps the plan names** (start, tutorial board, deal, dispatch sheet, logbook, Locations, Pilots) and use the API, with the browser's own session, to fast-forward the clock and read state. CR-011 allows the developer routes for this. - **They share the server unit tests' database** (`TEST_DATABASE_URL`); each test signs up its own guest, so nothing needs resetting. Don't run them at the same time as the server tests, which truncate it. - **The test's expected state follows CR-013**: two ships after the deal, not the one the plan's 12.3 text lists. + +## Step 12.4 + +- **"Close the page" is a real page close**; the return is a fresh page in the same browser session, as when reopening the installed app. diff --git a/apps/web/e2e/12-4-offline-progress.e2e.ts b/apps/web/e2e/12-4-offline-progress.e2e.ts new file mode 100644 index 0000000..ff3bd68 --- /dev/null +++ b/apps/web/e2e/12-4-offline-progress.e2e.ts @@ -0,0 +1,27 @@ +import { expect, test } from "@playwright/test"; +import { advanceTo, dispatchFromEarthBoard, logbook, playToDeal, state } from "./support"; + +test.describe("end to end (Phase 12)", () => { + test("12.4: a delivery that lands while the app is closed shows on return", async ({ + page, + context, + }) => { + await playToDeal(page); + const dispatchId = await dispatchFromEarthBoard(page); + const before = await state(page); + const flight = before.activeDispatches.find((d) => d.id === dispatchId)!; + + // Close the app, let the server clock pass the arrival, come back. + await page.close(); + const later = await context.newPage(); + await advanceTo(later, flight.arrivalAt); + await later.goto("/"); + + const summary = (await state(later)).summaries.find((s) => s.dispatchId === dispatchId)!; + await expect(logbook(later)).toContainText(`Delivered ${summary.massTonnes} t`); + const after = await state(later); + // Credits went up by the delivery's net payout; the ship is at the destination. + expect(after.company.credits).toBe(before.company.credits + summary.credits); + expect(after.ships.find((s) => s.id === flight.shipId)!.locationId).toBe(flight.destinationId); + }); +}); diff --git a/memory-bank/progress.md b/memory-bank/progress.md index 4056c37..b5947c6 100644 --- a/memory-bank/progress.md +++ b/memory-bank/progress.md @@ -309,6 +309,6 @@ Spec: `memory-bank/change-requests/CR-013-veterans-clipper.md` (received as "CR- - [x] **Step 12.1 — Balance simulation script.** `packages/sim/balance/simulate.ts`: a pure, deterministic simulated player that plays from the start using only sim and content functions the way the server applies them (tutorial runs, deal, boards per period, dispatch, deadhead, rest, resolution, goals, skill points, Market purchases with a hired pilot, upgrades from spare cash), with a trip log for tracing. Reports milestones (deal, first Market purchase, first discovery, loan paid off, four ships), credits/loan/ships/pilot levels every 10 minutes, and breaches of the invariants (soft-lock, idle ship with no work and no way out, dispatch while resting). `pnpm --filter @deadhead/sim balance [seed] [hours]` prints both policies. **Design changes (user-approved):** pay and fuel use economic distance (decision 0.5.84), and boards offer a first contact the fleet can fly (0.5.85). **Tuning:** economic-distance exponent 0.65, Clipper fuel 600 → 450 cr/M km, loan repayment share 0.3 → 0.25. Medians over 7 seeds (Lighter-first): deal 2.9 min, first purchase 66, first discovery 33, loan paid off 188, four ships 170 (Freighter-first 201); no breaches in any run. Test: `test/balance.test.ts` (determinism, each target on the median, four-ship comparison, invariants in every run, veteran contract in the first session, samples reported). - [x] **Step 12.2 — Revisit the tutorial economy test.** The amended Step 2.5 check ("the tutorial share plus starting credits covers fuel for three Courier Earth→Moon runs") no longer assumes the lowest-paying tutorial contract: the simulator records the tutorial share actually earned and the credits at the deal, and `packages/sim/test/balance.test.ts` checks, in every seeded run, four tutorial runs, credits at the deal = starting credits + share earned, and at least three Courier Earth→Moon fuel loads. The placeholder test left `packages/content/test/config.test.ts` (content can't import the sim). Also added `test/first-contact-fit.test.ts` for decision 0.5.85 (Step 12.1): every Earth board over four hours offers a first contact to Mars that the deal's Clipper crew can take, and none once Mars is discovered. - [x] **Step 12.3 — End-to-end: tutorial to first ship.** Playwright now also starts the real API server (port 3135) on `TEST_DATABASE_URL`, migrated first, next to the production web build with `/api` proxied to it; tests run one at a time because the developer clock is shared. `e2e/support.ts` drives play: start a company, fly the tutorial board, shake on the deal, dispatch from a board through the sheet, dismiss the logbook, and fast-forward with the developer routes (CR-011). Test (`e2e/12-3-first-ship.e2e.ts`): guest → four tutorial runs in the UI → deal → the state has the Courier (avatar) and Clipper (veteran) at Earth, one Earth bay, the 66,600 cr loan and no tutorial → one contract dispatched in the dispatch sheet and resolved, its logbook entry shows the repayment and the loan went down. -- [ ] Step 12.4 — End-to-end: offline progress +- [x] **Step 12.4 — End-to-end: offline progress.** Test (`e2e/12-4-offline-progress.e2e.ts`): dispatch a contract, close the page, move the server clock past the arrival, open a new page: the logbook shows the delivery, credits went up by exactly the delivery's net payout, and the ship is at the destination. - [ ] Step 12.5 — End-to-end: discovery - [ ] Step 12.6 — End-to-end: pilot progression