What the tester does to verify the API end to end: sign up → get a JWT → add items → check out.
A minimal shopping API with JWT bearer auth. Test it two ways:
The database is db.sqlite in the project root. For a clean slate, stop the
server, delete db.sqlite*, and start again — products are re-seeded.
flowchart TD
A([Tester opens http://localhost:3000]) --> B[Static page loads
GET /products shows catalog]
B --> C{Have an account?}
C -- No --> D[Enter email + password
click Sign up]
C -- Yes --> E[Enter email + password
click Sign in]
D --> F[POST /auth/signup
returns JWT]
E --> G[POST /auth/signin
returns JWT]
F --> H[Page stores token
status = signed in]
G --> H
H --> I[Click Add on a product
POST /cart/items + Bearer token]
I --> J[GET /cart shows line items + total]
J --> K{Add more?}
K -- Yes --> I
K -- No --> L[Click Checkout
POST /cart/checkout + Bearer token]
L --> M[201 returns order_id + total
cart is emptied]
M --> N([Test passes])
I -. without token .-> X[401 Missing Bearer token]
L -. empty cart .-> Y[400 Cart is empty]
Do these in order. The client shows the raw API response for every action, so you can confirm each status code.
| # | What you do | Expected result |
|---|---|---|
| 1 | Open http://localhost:3000 | Page loads; Products lists 4 items with prices; auth badge says signed out. |
| 2 | Look at cart actions while signed out | The Add buttons and Checkout are disabled. |
| 3 | Enter email + password (≥ 6 chars), click Sign up | 201 with { id, email, token }; badge flips to signed in; Add/Checkout enable. |
| 4 | Click Add on two different products | Each returns 200; the Cart list and Total update. |
| 5 | Click Add on a product already in the cart | Its quantity increments (no duplicate line). |
| 6 | Click Checkout | 201 with { order_id, total_cents }; cart empties; Total back to $0.00. |
| 7 | Click Checkout again (empty cart) | 400 Cart is empty. |
| 8 | Click Sign out | Badge says signed out; cart actions disabled again. |
| 9 | Reload the page after signing in | You stay signed in (token in localStorage) and the cart reloads. |
| # | What you do | Expected result |
|---|---|---|
| 10 | Sign in with a wrong password | 401 Invalid credentials; stays signed out. |
| 11 | Sign up with the same email twice | Second attempt returns 409 Email already registered. |
| 12 | Sign up with a 3-char password | 400 validation error. |
A run is successful when steps 1–12 all match their expected results.
This part is not built. You implement it yourself. There is no walkthrough, no starter code, and no hints about how — those design decisions are yours. Only the requirements and what we check are below.
No further direction will be given. Make reasonable design choices and justify them if asked.
BASE=http://localhost:3000
# 1. sign up and capture the JWT
TOKEN=$(curl -s -X POST $BASE/auth/signup \
-H 'content-type: application/json' \
-d '{"email":"curl@example.com","password":"hunter2pw"}' \
| node -pe 'JSON.parse(require("fs").readFileSync(0)).token')
# 2. a cart call without the token must be rejected (expect 401)
curl -s $BASE/cart
# 3. add an item, then view the cart (expect the line + total)
curl -s -X POST $BASE/cart/items -H "Authorization: Bearer $TOKEN" \
-H 'content-type: application/json' -d '{"productId":1,"quantity":2}'
curl -s $BASE/cart -H "Authorization: Bearer $TOKEN"
# 4. check out (expect 201 with order_id + total_cents)
curl -s -X POST $BASE/cart/checkout -H "Authorization: Bearer $TOKEN"