From 2bcde45891161052c6bb3f752145ec6ead518e8e Mon Sep 17 00:00:00 2001 From: VinPropane Date: Wed, 6 May 2026 22:20:14 -0400 Subject: [PATCH] NEO-38: add curl examples to manual QA --- docs/manual-qa/NEO-38.md | 56 +++++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 9 deletions(-) diff --git a/docs/manual-qa/NEO-38.md b/docs/manual-qa/NEO-38.md index 72e4a80..e8576d8 100644 --- a/docs/manual-qa/NEO-38.md +++ b/docs/manual-qa/NEO-38.md @@ -7,20 +7,58 @@ Reference: [implementation plan](../plans/NEO-38-implementation-plan.md), [serve - Run `NeonSprawl.Server` from `server/NeonSprawl.Server` (`dotnet run`; default `http://localhost:5253`). - Use a **known** player id (e.g. `dev-local-1`, present in position state). +Use a shell variable so you only change the base URL once: + +```bash +BASE=http://localhost:5253 +ID=dev-local-1 +``` + ## Happy path — grant + read back -1. `POST /game/players/dev-local-1/skill-progression` with JSON: - - `schemaVersion` **1** - - `skillId` **`salvage`** - - `amount` **10** - - `sourceKind` **`activity`** -2. Expect **HTTP 200**, body `granted` **true**, `progression.skills` contains `salvage` with increased `xp` vs a prior `GET`. -3. `GET /game/players/dev-local-1/skill-progression` — **`salvage.xp`** matches the POST `progression`. +1. **Baseline read** (optional): note `salvage.xp` before the grant (usually **0** on a fresh store). + +```bash +curl -sS "${BASE}/game/players/${ID}/skill-progression" +``` + +2. **Grant** — `schemaVersion` **1**, `skillId` **`salvage`**, `amount` **10**, `sourceKind` **`activity`**. + +```bash +curl -sS -i -X POST "${BASE}/game/players/${ID}/skill-progression" \ + -H "Content-Type: application/json" \ + -d '{"schemaVersion":1,"skillId":"salvage","amount":10,"sourceKind":"activity"}' +``` + +Expect **HTTP 200**, JSON `granted` **true**, `levelUps` may be empty if no level boundary crossed (10 XP stays at level 1 with the prototype curve). + +3. **Read back**: `salvage.xp` in the snapshot should reflect the persisted total (baseline + **10**, or cumulative if you repeated the POST). + +```bash +curl -sS "${BASE}/game/players/${ID}/skill-progression" +``` ## Deny — source not allowed -1. `POST` same path with `skillId` **`salvage`**, `sourceKind` **`trainer`** (not in prototype catalog for salvage). -2. Expect **HTTP 200**, `granted` **false**, **`reasonCode`** **`source_kind_not_allowed`**, and `progression` still present. +`skillId` **`salvage`** does **not** allow **`trainer`** in the prototype catalog; the server still returns **200** with structured deny. + +```bash +curl -sS -i -X POST "${BASE}/game/players/${ID}/skill-progression" \ + -H "Content-Type: application/json" \ + -d '{"schemaVersion":1,"skillId":"salvage","amount":10,"sourceKind":"trainer"}' +``` + +Expect **HTTP 200**, `granted` **false**, **`reasonCode`** **`source_kind_not_allowed`**, and `progression` present (snapshot unchanged except what other requests already applied). + +## Bonus — observe a level-up in one response + +With the prototype curve `level = 1 + floor(xp / 100)`, a grant of **100** XP from **0** on `intrusion` should set `granted` **true** and include **`levelUps`** (`previousLevel` **1**, `newLevel` **2**). + +```bash +curl -sS -i -X POST "${BASE}/game/players/${ID}/skill-progression" \ + -H "Content-Type: application/json" \ + -d '{"schemaVersion":1,"skillId":"intrusion","amount":100,"sourceKind":"activity"}' +``` ## Bruno