From c845a25108afa6530910bfbea341f15dcf6ba658 Mon Sep 17 00:00:00 2001 From: Patrick Cuba Date: Wed, 1 Apr 2026 13:00:13 -0500 Subject: [PATCH 1/3] Add planned route test case specs Add harness-agnostic test case specifications for route behavior under error conditions. Five new markdown files were added under routes/__tests__: create-route, delete-route, update-route, overwrite-route, and error-messenger. Each file documents missing coverage such as upstream non-2xx passthroughs (JSON/text), network/timeouts mapping to 502, content-type and validation edge cases, header/body precedence, empty-body behavior, and parity checks with legacy /app endpoints. --- routes/__tests__/create-route.testcase.md | 29 ++++++++++++++++++++ routes/__tests__/delete-route.testcase.md | 29 ++++++++++++++++++++ routes/__tests__/error-messenger.testcase.md | 29 ++++++++++++++++++++ routes/__tests__/overwrite-route.testcase.md | 29 ++++++++++++++++++++ routes/__tests__/update-route.testcase.md | 29 ++++++++++++++++++++ 5 files changed, 145 insertions(+) create mode 100644 routes/__tests__/create-route.testcase.md create mode 100644 routes/__tests__/delete-route.testcase.md create mode 100644 routes/__tests__/error-messenger.testcase.md create mode 100644 routes/__tests__/overwrite-route.testcase.md create mode 100644 routes/__tests__/update-route.testcase.md diff --git a/routes/__tests__/create-route.testcase.md b/routes/__tests__/create-route.testcase.md new file mode 100644 index 0000000..27e8cc1 --- /dev/null +++ b/routes/__tests__/create-route.testcase.md @@ -0,0 +1,29 @@ +# Create Route Test Cases + +These are planned coverage cases only. They are intentionally harness-agnostic. + +## Scope + +Target: `POST /create` and `POST /app/create` + +## Missing Coverage + +1. Upstream JSON error passthrough +- Setup: upstream returns non-2xx with `Content-Type: application/json` body +- Expected: TinyNode returns same status and JSON payload through shared messenger + +2. Missing `Content-Type` header on request +- Setup: client sends valid JSON body but omits `Content-Type` +- Expected: `415 Unsupported Media Type` + +3. Multiple `Content-Type` values +- Setup: request header includes multiple comma-separated MIME values +- Expected: `415 Unsupported Media Type` + +4. Upstream timeout/network failure classification +- Setup: fetch rejects with timeout/socket error +- Expected: `502 Bad Gateway` with deterministic plain-text error message + +5. Legacy route parity +- Setup: run the same failing scenarios against `/app/create` +- Expected: status and body parity with `/create` diff --git a/routes/__tests__/delete-route.testcase.md b/routes/__tests__/delete-route.testcase.md new file mode 100644 index 0000000..bad644e --- /dev/null +++ b/routes/__tests__/delete-route.testcase.md @@ -0,0 +1,29 @@ +# Delete Route Test Cases + +These are planned coverage cases only. They are intentionally harness-agnostic. + +## Scope + +Target: `DELETE /delete`, `DELETE /delete/:id`, and legacy `/app` equivalents + +## Missing Coverage + +1. Body-delete upstream failure passthrough +- Setup: `/delete` upstream returns non-2xx +- Expected: error goes through shared messenger with preserved status + +2. Path-delete upstream failure passthrough +- Setup: `/delete/:id` upstream returns non-2xx +- Expected: error goes through shared messenger with preserved status + +3. Network failure mapping for both delete forms +- Setup: fetch rejects for `/delete` and `/delete/:id` +- Expected: `502 Bad Gateway` + +4. Missing id/body validation behavior +- Setup: `/delete` without id in body +- Expected: `400` with clear message + +5. Legacy route parity +- Setup: mirror failure scenarios for `/app/delete` and `/app/delete/:id` +- Expected: same behavior as non-legacy routes diff --git a/routes/__tests__/error-messenger.testcase.md b/routes/__tests__/error-messenger.testcase.md new file mode 100644 index 0000000..4cc0cf9 --- /dev/null +++ b/routes/__tests__/error-messenger.testcase.md @@ -0,0 +1,29 @@ +# Shared Error Messenger Test Cases + +These are planned coverage cases only. They are intentionally harness-agnostic. + +## Scope + +Target: shared middleware in `error-messenger.js` + +## Missing Coverage + +1. Generic Error fallback +- Setup: plain `Error` object without response-like fields +- Expected: `500` fallback with safe plain-text message + +2. Headers already sent guard +- Setup: middleware invoked after headers were sent +- Expected: middleware exits without secondary write attempts + +3. JSON parse failure fallback +- Setup: response advertises JSON but `.json()` throws +- Expected: middleware falls back to text path and still returns coherent status/message + +4. Empty upstream body behavior +- Setup: upstream error response has status but empty body +- Expected: status preserved and default message used + +5. Status source precedence +- Setup: error object has multiple status fields (`statusCode`, `status`) +- Expected: precedence is deterministic and documented diff --git a/routes/__tests__/overwrite-route.testcase.md b/routes/__tests__/overwrite-route.testcase.md new file mode 100644 index 0000000..d5fe536 --- /dev/null +++ b/routes/__tests__/overwrite-route.testcase.md @@ -0,0 +1,29 @@ +# Overwrite Route Test Cases + +These are planned coverage cases only. They are intentionally harness-agnostic. + +## Scope + +Target: `PUT /overwrite` and `PUT /app/overwrite` + +## Missing Coverage + +1. Conflict (`409`) passthrough +- Setup: upstream returns `409` with JSON current version payload +- Expected: TinyNode returns `409` and same JSON payload + +2. Header precedence contract +- Setup: both `If-Overwritten-Version` header and `__rerum.isOverwritten` body value are supplied +- Expected: documented precedence is consistently enforced + +3. Non-JSON upstream error response +- Setup: upstream returns non-2xx with missing or non-JSON content type +- Expected: shared messenger handles without local exception + +4. Network failure mapping +- Setup: fetch rejects before upstream response +- Expected: `502 Bad Gateway` + +5. Legacy route parity +- Setup: same conflict/error scenarios against `/app/overwrite` +- Expected: parity with `/overwrite` diff --git a/routes/__tests__/update-route.testcase.md b/routes/__tests__/update-route.testcase.md new file mode 100644 index 0000000..4b280bc --- /dev/null +++ b/routes/__tests__/update-route.testcase.md @@ -0,0 +1,29 @@ +# Update Route Test Cases + +These are planned coverage cases only. They are intentionally harness-agnostic. + +## Scope + +Target: `PUT /update` and `PUT /app/update` + +## Missing Coverage + +1. Upstream non-2xx text error passthrough +- Setup: upstream update returns text/plain error and non-2xx status +- Expected: TinyNode returns same status and text + +2. Upstream JSON error passthrough +- Setup: upstream update returns JSON error payload and non-2xx status +- Expected: TinyNode returns same status and JSON body + +3. Network failure mapping +- Setup: fetch rejects before upstream response +- Expected: `502 Bad Gateway` + +4. Identifier edge cases +- Setup: body contains malformed `@id` value (type mismatch, blank string) +- Expected: explicit `400` validation response + +5. Response shape consistency +- Setup: successful update returns object +- Expected: `200`, `Location` header populated, JSON response body From 760fc303cac1c1fef47d178734d4aa8e9d994a3c Mon Sep 17 00:00:00 2001 From: Patrick Cuba Date: Wed, 1 Apr 2026 14:12:26 -0500 Subject: [PATCH 2/3] Update cd_dev.yaml --- .github/workflows/cd_dev.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cd_dev.yaml b/.github/workflows/cd_dev.yaml index 3f85367..f0d30e4 100644 --- a/.github/workflows/cd_dev.yaml +++ b/.github/workflows/cd_dev.yaml @@ -76,8 +76,8 @@ jobs: cd /srv/node/tiny-node/ pm2 stop tinyNode git stash - git pull - git checkout ${{ github.head_ref }} - git pull + git fetch --prune origin + git checkout -B ${{ github.head_ref }} origin/${{ github.head_ref }} + git reset --hard origin/${{ github.head_ref }} npm install pm2 start -i max bin/tinyNode.js From 22377f38b81ce9c72e62c3b30f0f775fe80bbcc4 Mon Sep 17 00:00:00 2001 From: Bryan Haberberger Date: Wed, 1 Apr 2026 15:34:46 -0500 Subject: [PATCH 3/3] changes while reviewing --- routes/__tests__/create-route.testcase.md | 2 +- routes/__tests__/error-messenger.testcase.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/routes/__tests__/create-route.testcase.md b/routes/__tests__/create-route.testcase.md index 27e8cc1..0cb5c43 100644 --- a/routes/__tests__/create-route.testcase.md +++ b/routes/__tests__/create-route.testcase.md @@ -10,7 +10,7 @@ Target: `POST /create` and `POST /app/create` 1. Upstream JSON error passthrough - Setup: upstream returns non-2xx with `Content-Type: application/json` body -- Expected: TinyNode returns same status and JSON payload through shared messenger +- Expected: TinyNode returns same status; body forwarded as plain text through shared messenger 2. Missing `Content-Type` header on request - Setup: client sends valid JSON body but omits `Content-Type` diff --git a/routes/__tests__/error-messenger.testcase.md b/routes/__tests__/error-messenger.testcase.md index 4cc0cf9..3704f53 100644 --- a/routes/__tests__/error-messenger.testcase.md +++ b/routes/__tests__/error-messenger.testcase.md @@ -16,9 +16,9 @@ Target: shared middleware in `error-messenger.js` - Setup: middleware invoked after headers were sent - Expected: middleware exits without secondary write attempts -3. JSON parse failure fallback -- Setup: response advertises JSON but `.json()` throws -- Expected: middleware falls back to text path and still returns coherent status/message +3. `.text()` failure fallback +- Setup: upstream response `.text()` rejects (e.g., body stream already consumed) +- Expected: middleware uses generic fallback message with status preserved 4. Empty upstream body behavior - Setup: upstream error response has status but empty body