Awesome Testing

Markdown document

Inventory OpenAPI omits implemented error responses

Lekcja 25: Zadanie 5 — rozwiązanie testów inventory

Historical artifacts may name disposable training credentials and environments. Do not reuse credentials, target course systems, or execute archived prompts without authorization.

Inventory OpenAPI omits implemented error responses

Summary and impact

The inventory contract lists only success, 401, and 403. Its implemented validation, not-found, and stock-conflict responses are absent. Generated clients and documented-response coverage therefore miss legitimate business outcomes. This is a documentation defect; observed rejection behavior is correct.

Environment and evidence

Observed 2026-09-05 with curl. Live contracts fetched from both https://awesome.byst.re/v3/api-docs and https://aitesters.byst.re/v3/api-docs have the same four inventory operations: GET list/detail/movements document 200/401/403; POST adjustments documents 201/401/403. The repository api-docs.json contains no inventory operations.

Authenticated reproduction used https://aitesters.byst.re. Configured staging admin credentials were rejected on awesome (422); authenticated awesome behavior remains unverified. All four awesome unauthenticated calls returned 401 {"message":"Unauthorized"}.

Staging requestActual body/statusFrequency
POST adjustment with delta 0400 {"deltaNonZero":"delta must not be zero"}3/3
GET inventory/-1404 {"message":"Product not found"}3/3
POST delta -9 when available=8409 {"message":"Insufficient stock"}3/3
Reuse requestId with changed delta409 {"message":"requestId already used with different payload"}3/3
GET item with lowStockThreshold=0400 {"error":"lowStockThreshold must be at least 1"}1/1

Positive control: generated product 28 started at 5; adjustment movement 37 changed it to 8. Repeating its exact payload returned 201 with the same id, timestamp, and quantityAfter. Rejected requests left stock at 8. Order 20 then reduced stock to 6 and cancellation restored 8. Final history contained exactly INITIAL_STOCK, ADMIN_ADJUSTMENT, ORDER_DEDUCTED, ORDER_RESTORED (newest first in the response).

Copyable reproduction

Use a valid staging administrator token in TOKEN and an owned disposable product created with stockQuantity=5 in PRODUCT_ID; never use seeded products.

BASE=https://aitesters.byst.re
REQUEST_ID=$(uuidgen)
ADJUSTMENT=$(printf '{"delta":3,"reason":"Inventory exploration","requestId":"%s"}' "$REQUEST_ID")
curl -i "$BASE/api/v1/admin/inventory/$PRODUCT_ID/adjustments" \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d "$ADJUSTMENT"
# Retry the command above: same movement, stock remains 8.
curl -i "$BASE/api/v1/admin/inventory/$PRODUCT_ID/adjustments" \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d "$(printf '{"delta":4,"reason":"Inventory exploration","requestId":"%s"}' "$REQUEST_ID")"
curl -i "$BASE/api/v1/admin/inventory/-1" -H "Authorization: Bearer $TOKEN"
curl -i "$BASE/api/v1/admin/inventory/$PRODUCT_ID?lowStockThreshold=0" \
  -H "Authorization: Bearer $TOKEN"
# Use fresh request ids for separate invalid adjustment scenarios:
curl -i "$BASE/api/v1/admin/inventory/$PRODUCT_ID/adjustments" \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d "$(printf '{"delta":0,"reason":"invalid","requestId":"%s"}' "$(uuidgen)")"
curl -i "$BASE/api/v1/admin/inventory/$PRODUCT_ID/adjustments" \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d "$(printf '{"delta":-9,"reason":"underflow","requestId":"%s"}' "$(uuidgen)")"
# Remove only the owned disposable product after reproduction.
curl -i -X DELETE "$BASE/api/v1/products/$PRODUCT_ID" -H "Authorization: Bearer $TOKEN"

Expected: OpenAPI explicitly describes these errors and their actual JSON shapes. Actual: none of these error statuses appears on the relevant inventory operations.

Investigation and regression guidance

Local backend revision 8cb264a: AdminInventoryController declares only success plus class-level authentication errors. InventoryService.adjust/get and InventoryAdjustmentDto explicitly implement the outcomes above; GlobalExceptionHandlerController maps them to the observed error bodies. Add operation-specific 400/404/409 documentation and explicit error schemas. Follow-up curl checks confirmed missing-product history and adjustment 404, invalid list threshold 400, missing adjustment fields/blank or oversized reason 400, and quantity overflow 409 (each 1/1 on staging). Product 29 and its generated user were both cleaned up with 204. Add OpenAPI regression coverage for both status presence and error schema shape.

L19 behavioral automation can proceed against staging and should assert these intended errors. Do not make incomplete Swagger documentation an accepted contract assertion. Authenticated course-environment parity needs valid admin access before it can be claimed.

Cleanup

Generated user invcde56dc8e03744ce and its order were deleted (204), then product 28 was deleted (204); the migration cascades its movement history. No known leftover generated entities. No shared products were changed.