diff --git a/.cursor/rules/testing-expectations.md b/.cursor/rules/testing-expectations.md index 63a113e..673551e 100644 --- a/.cursor/rules/testing-expectations.md +++ b/.cursor/rules/testing-expectations.md @@ -1,5 +1,5 @@ --- -description: Unit vs integration tests; integration when data persistence/mutation exists; C# xUnit; Godot client unit tests with script changes (NEO-12 harness + gdscript.yml CI). +description: Unit vs integration tests; integration when data persistence/mutation exists; C# xUnit; Bruno .bru requests when server HTTP endpoints change; Godot client unit tests with script changes (NEO-12 harness + gdscript.yml CI). alwaysApply: true --- @@ -13,6 +13,7 @@ alwaysApply: true - **Names:** **`MethodName_ShouldExpectedOutcome_WhenScenario`**; see [C# style — Test method naming convention](csharp-style.md#test-method-naming-convention). - **No test project yet:** It is acceptable to ship a small change without a suite only while the server is mostly scaffolding. When you add the **first** testable module, **add a `NeonSprawl.Server.Tests` (or equivalent) project** and start covering that area; do not leave new core logic permanently untested. - **Bug fixes:** Prefer a **regression test** when the fix is non-obvious or has broken before. +- **HTTP endpoints:** Any change set that **adds or changes** a route or wire contract on **`NeonSprawl.Server`** (new `MapGet` / `MapPost`, path change, request/response JSON shape, status codes) must **add or update** the **Bruno** collection under **`bruno/neon-sprawl-server/`** so the API stays manually exercisable from the repo: at least one **.bru** request per new/changed route (happy path plus a representative **4xx/404** case when the server defines one). Prefer **Bruno `tests` blocks** on those requests for simple smoke checks (status + key JSON fields) when the behavior is stable enough not to churn every edit. If Bruno is unsuitable for a given endpoint (e.g. streaming-only), say so briefly in the PR or plan instead of silently omitting coverage. ## Integration testing (data manipulation) diff --git a/bruno/neon-sprawl-server/bruno.json b/bruno/neon-sprawl-server/bruno.json new file mode 100644 index 0000000..9535019 --- /dev/null +++ b/bruno/neon-sprawl-server/bruno.json @@ -0,0 +1,5 @@ +{ + "version": "1", + "name": "Neon Sprawl Server", + "type": "collection" +} diff --git a/bruno/neon-sprawl-server/core/Health.bru b/bruno/neon-sprawl-server/core/Health.bru new file mode 100644 index 0000000..b31f314 --- /dev/null +++ b/bruno/neon-sprawl-server/core/Health.bru @@ -0,0 +1,11 @@ +meta { + name: GET health + type: http + seq: 2 +} + +get { + url: {{baseUrl}}/health + body: none + auth: none +} diff --git a/bruno/neon-sprawl-server/core/Root.bru b/bruno/neon-sprawl-server/core/Root.bru new file mode 100644 index 0000000..6f4fc39 --- /dev/null +++ b/bruno/neon-sprawl-server/core/Root.bru @@ -0,0 +1,11 @@ +meta { + name: GET / + type: http + seq: 1 +} + +get { + url: {{baseUrl}}/ + body: none + auth: none +} diff --git a/bruno/neon-sprawl-server/environments/Local.bru b/bruno/neon-sprawl-server/environments/Local.bru new file mode 100644 index 0000000..bd622e2 --- /dev/null +++ b/bruno/neon-sprawl-server/environments/Local.bru @@ -0,0 +1,4 @@ +vars { + baseUrl: http://localhost:5253 + playerId: dev-local-1 +} diff --git a/bruno/neon-sprawl-server/interaction/Post interact prototype terminal.bru b/bruno/neon-sprawl-server/interaction/Post interact prototype terminal.bru new file mode 100644 index 0000000..8cbb028 --- /dev/null +++ b/bruno/neon-sprawl-server/interaction/Post interact prototype terminal.bru @@ -0,0 +1,22 @@ +meta { + name: POST interact - prototype_terminal + type: http + seq: 8 +} + +post { + url: {{baseUrl}}/game/players/{{playerId}}/interact + body: json + auth: none +} + +headers { + content-type: application/json +} + +body:json { + { + "schemaVersion": 1, + "interactableId": "prototype_terminal" + } +} diff --git a/bruno/neon-sprawl-server/interaction/Post interact unknown interactable.bru b/bruno/neon-sprawl-server/interaction/Post interact unknown interactable.bru new file mode 100644 index 0000000..bf3739a --- /dev/null +++ b/bruno/neon-sprawl-server/interaction/Post interact unknown interactable.bru @@ -0,0 +1,22 @@ +meta { + name: POST interact - unknown interactable + type: http + seq: 9 +} + +post { + url: {{baseUrl}}/game/players/{{playerId}}/interact + body: json + auth: none +} + +headers { + content-type: application/json +} + +body:json { + { + "schemaVersion": 1, + "interactableId": "not_in_registry" + } +} diff --git a/bruno/neon-sprawl-server/position/Get position 404.bru b/bruno/neon-sprawl-server/position/Get position 404.bru new file mode 100644 index 0000000..ea29819 --- /dev/null +++ b/bruno/neon-sprawl-server/position/Get position 404.bru @@ -0,0 +1,11 @@ +meta { + name: GET player position (unknown player) + type: http + seq: 4 +} + +get { + url: {{baseUrl}}/game/players/no-such-player-id/position + body: none + auth: none +} diff --git a/bruno/neon-sprawl-server/position/Get position.bru b/bruno/neon-sprawl-server/position/Get position.bru new file mode 100644 index 0000000..d2ac369 --- /dev/null +++ b/bruno/neon-sprawl-server/position/Get position.bru @@ -0,0 +1,11 @@ +meta { + name: GET player position + type: http + seq: 3 +} + +get { + url: {{baseUrl}}/game/players/{{playerId}}/position + body: none + auth: none +} diff --git a/bruno/neon-sprawl-server/position/Post move near prototype terminal.bru b/bruno/neon-sprawl-server/position/Post move near prototype terminal.bru new file mode 100644 index 0000000..1b3dca0 --- /dev/null +++ b/bruno/neon-sprawl-server/position/Post move near prototype terminal.bru @@ -0,0 +1,26 @@ +meta { + name: POST move - near prototype terminal (setup interact) + type: http + seq: 7 +} + +post { + url: {{baseUrl}}/game/players/{{playerId}}/move + body: json + auth: none +} + +headers { + content-type: application/json +} + +body:json { + { + "schemaVersion": 1, + "target": { + "x": 0.5, + "y": 0.9, + "z": 0.5 + } + } +} diff --git a/bruno/neon-sprawl-server/position/Post move-stream.bru b/bruno/neon-sprawl-server/position/Post move-stream.bru new file mode 100644 index 0000000..6f832da --- /dev/null +++ b/bruno/neon-sprawl-server/position/Post move-stream.bru @@ -0,0 +1,25 @@ +meta { + name: POST move-stream + type: http + seq: 6 +} + +post { + url: {{baseUrl}}/game/players/{{playerId}}/move-stream + body: json + auth: none +} + +headers { + content-type: application/json +} + +body:json { + { + "schemaVersion": 1, + "targets": [ + { "x": -4.8, "y": 0.9, "z": -5 }, + { "x": -4.2, "y": 0.9, "z": -5 } + ] + } +} diff --git a/bruno/neon-sprawl-server/position/Post move.bru b/bruno/neon-sprawl-server/position/Post move.bru new file mode 100644 index 0000000..129f5c1 --- /dev/null +++ b/bruno/neon-sprawl-server/position/Post move.bru @@ -0,0 +1,26 @@ +meta { + name: POST move + type: http + seq: 5 +} + +post { + url: {{baseUrl}}/game/players/{{playerId}}/move + body: json + auth: none +} + +headers { + content-type: application/json +} + +body:json { + { + "schemaVersion": 1, + "target": { + "x": -4.5, + "y": 0.9, + "z": -5 + } + } +} diff --git a/bruno/neon-sprawl-server/targeting/Get target.bru b/bruno/neon-sprawl-server/targeting/Get target.bru new file mode 100644 index 0000000..d681b18 --- /dev/null +++ b/bruno/neon-sprawl-server/targeting/Get target.bru @@ -0,0 +1,11 @@ +meta { + name: GET player target state + type: http + seq: 10 +} + +get { + url: {{baseUrl}}/game/players/{{playerId}}/target + body: none + auth: none +} diff --git a/bruno/neon-sprawl-server/targeting/Post target clear.bru b/bruno/neon-sprawl-server/targeting/Post target clear.bru new file mode 100644 index 0000000..c40b6f9 --- /dev/null +++ b/bruno/neon-sprawl-server/targeting/Post target clear.bru @@ -0,0 +1,22 @@ +meta { + name: POST target select - clear lock + type: http + seq: 12 +} + +post { + url: {{baseUrl}}/game/players/{{playerId}}/target/select + body: json + auth: none +} + +headers { + content-type: application/json +} + +body:json { + { + "schemaVersion": 1, + "targetId": null + } +} diff --git a/bruno/neon-sprawl-server/targeting/Post target select alpha.bru b/bruno/neon-sprawl-server/targeting/Post target select alpha.bru new file mode 100644 index 0000000..945ba25 --- /dev/null +++ b/bruno/neon-sprawl-server/targeting/Post target select alpha.bru @@ -0,0 +1,22 @@ +meta { + name: POST target select - prototype_target_alpha + type: http + seq: 11 +} + +post { + url: {{baseUrl}}/game/players/{{playerId}}/target/select + body: json + auth: none +} + +headers { + content-type: application/json +} + +body:json { + { + "schemaVersion": 1, + "targetId": "prototype_target_alpha" + } +} diff --git a/bruno/neon-sprawl-server/targeting/Post target select unknown.bru b/bruno/neon-sprawl-server/targeting/Post target select unknown.bru new file mode 100644 index 0000000..db8569f --- /dev/null +++ b/bruno/neon-sprawl-server/targeting/Post target select unknown.bru @@ -0,0 +1,22 @@ +meta { + name: POST target select - unknown target + type: http + seq: 13 +} + +post { + url: {{baseUrl}}/game/players/{{playerId}}/target/select + body: json + auth: none +} + +headers { + content-type: application/json +} + +body:json { + { + "schemaVersion": 1, + "targetId": "not_in_registry" + } +}