Quick reference for manually testing each endpoint in the smoke test checklist using curl.
# Set environment variables for convenience
export BACKEND_URL="http://localhost:5000"
export FRONTEND_URL="http://localhost:3000"curl -X GET "$BACKEND_URL/" \
-H "Content-Type: application/json" \
-w "\nStatus: %{http_code}\n"Expected: HTTP 200, response like {"message":"Hello, world!"}
curl -X GET "$BACKEND_URL/health/live" \
-H "Content-Type: application/json" \
-w "\nStatus: %{http_code}\n"Expected: HTTP 200, response: {"status":"ok"}
curl -X GET "$BACKEND_URL/health/ready" \
-H "Content-Type: application/json" \
-w "\nStatus: %{http_code}\n" | jq .Expected: HTTP 200 (all deps up) or HTTP 503 (one or more failed)
Sample success response:
{
"status": "ok",
"checks": {
"database": { "status": "up" },
"redis": { "status": "up" },
"queues": { "status": "up" },
"schema": { "status": "up" }
}
}curl -X GET "$BACKEND_URL/confessions?page=1&limit=20" \
-H "Content-Type: application/json" \
-w "\nStatus: %{http_code}\n" | jq .Expected: HTTP 200 with paginated list
Sample response:
{
"data": [
{
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"message": "I secretly enjoy watching reality TV shows.",
"gender": "female",
"tags": ["humor"],
"view_count": 42,
"created_at": "2026-04-25T10:00:00.000Z"
}
],
"total": 150,
"page": 1,
"limit": 20
}curl -X POST "$BACKEND_URL/confessions" \
-H "Content-Type: application/json" \
-d '{
"message": "This is a test confession for smoke testing",
"gender": "female",
"tags": ["test"]
}' \
-w "\nStatus: %{http_code}\n" | jq .Expected: HTTP 201, response includes id and created_at
Save the returned id for use in section 3 tests
# Replace {confessionId} with an actual ID from section 2.1 or 2.2
CONFESSION_ID="f47ac10b-58cc-4372-a567-0e02b2c3d479"
curl -X GET "$BACKEND_URL/confessions/$CONFESSION_ID" \
-H "Content-Type: application/json" \
-w "\nStatus: %{http_code}\n" | jq .Expected: HTTP 200 with full confession detail
Sample response:
{
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"message": "I secretly enjoy watching reality TV shows.",
"gender": "female",
"tags": ["humor"],
"view_count": 43,
"created_at": "2026-04-25T10:00:00.000Z",
"reactions": [
{ "emoji": "❤️", "count": 5 }
],
"comments": []
}# Replace {confessionId} with an actual ID
CONFESSION_ID="f47ac10b-58cc-4372-a567-0e02b2c3d479"
# Replace {authToken} with a valid JWT token
AUTH_TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
curl -X POST "$BACKEND_URL/confessions/$CONFESSION_ID/comments" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $AUTH_TOKEN" \
-d '{
"message": "Test comment from smoke test"
}' \
-w "\nStatus: %{http_code}\n" | jq .Expected: HTTP 201 with comment object
# Replace {confessionId} with an actual ID
CONFESSION_ID="f47ac10b-58cc-4372-a567-0e02b2c3d479"
curl -X POST "$BACKEND_URL/reports" \
-H "Content-Type: application/json" \
-d "{
\"confessionId\": \"$CONFESSION_ID\",
\"type\": \"offensive\",
\"reason\": \"Contains hate speech (test report)\"
}" \
-w "\nStatus: %{http_code}\n" | jq .Expected: HTTP 201 with report object
Sample response:
{
"id": "report-uuid-12345",
"confessionId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"type": "offensive",
"reason": "Contains hate speech (test report)",
"status": "pending",
"createdAt": "2026-05-29T10:00:00.000Z"
}# Test spam report
curl -X POST "$BACKEND_URL/reports" \
-H "Content-Type: application/json" \
-d "{
\"confessionId\": \"$CONFESSION_ID\",
\"type\": \"spam\",
\"reason\": \"Duplicate post (test)\"
}" \
-w "\nStatus: %{http_code}\n" | jq .
# Test inappropriate report
curl -X POST "$BACKEND_URL/reports" \
-H "Content-Type: application/json" \
-d "{
\"confessionId\": \"$CONFESSION_ID\",
\"type\": \"inappropriate\",
\"reason\": \"Sexually explicit (test)\"
}" \
-w "\nStatus: %{http_code}\n" | jq .
# Test other report
curl -X POST "$BACKEND_URL/reports" \
-H "Content-Type: application/json" \
-d "{
\"confessionId\": \"$CONFESSION_ID\",
\"type\": \"other\",
\"reason\": \"Other issue (test)\"
}" \
-w "\nStatus: %{http_code}\n" | jq .Expected: All return HTTP 201
curl -X GET "$BACKEND_URL/diagnostics/notifications" \
-H "Content-Type: application/json" \
-w "\nStatus: %{http_code}\n" | jq .Expected: HTTP 401 or 403 (Unauthorized/Forbidden)
Sample error response:
{
"message": "Unauthorized",
"statusCode": 401
}curl -X GET "$BACKEND_URL/diagnostics/notifications" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer invalid.token.here" \
-w "\nStatus: %{http_code}\n" | jq .Expected: HTTP 401 (Unauthorized)
# Replace {adminToken} with a valid JWT token for an admin user
ADMIN_TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
curl -X GET "$BACKEND_URL/diagnostics/notifications" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-w "\nStatus: %{http_code}\n" | jq .Expected: HTTP 200 with queue diagnostics
Sample success response:
{
"queueDepth": 5,
"dlqDepth": 0,
"activeJobs": 3,
"completedJobs": 127,
"failedJobs": 2,
"delayedJobs": 1,
"queues": [
{ "name": "notifications", "status": "active" },
{ "name": "notifications-dlq", "status": "active" }
]
}Open: http://localhost:3000/auth/login
Expected: Login form, link to register, no errors
Open: http://localhost:3000/
Prerequisites: Must be logged in
Expected: Confession cards, pagination, reactions, comments
Open: http://localhost:3000/confessions/{confessionId}
Prerequisites: Must be logged in, confessionId must exist
Expected: Full confession, reactions, comments section
Open: http://localhost:3000/admin/dashboard
Prerequisites: Must be logged in as admin
Expected: Admin panel, navigation, dashboard metrics
Open: http://localhost:3000/admin/reports
Prerequisites: Must be logged in as admin
Expected: List of reports, filtering/search, action buttons
To run all curl tests at once:
#!/bin/bash
BACKEND_URL="http://localhost:5000"
export CONFESSION_ID=""
echo "=== Health Checks ==="
curl -s -X GET "$BACKEND_URL/" -H "Content-Type: application/json" | jq .
echo -e "\n=== Liveness ==="
curl -s -X GET "$BACKEND_URL/health/live" -H "Content-Type: application/json" | jq .
echo -e "\n=== Readiness ==="
curl -s -X GET "$BACKEND_URL/health/ready" -H "Content-Type: application/json" | jq .
echo -e "\n=== List Confessions ==="
confessions=$(curl -s -X GET "$BACKEND_URL/confessions?limit=1" -H "Content-Type: application/json")
echo "$confessions" | jq .
CONFESSION_ID=$(echo "$confessions" | jq -r '.data[0].id // empty')
if [ -n "$CONFESSION_ID" ]; then
echo -e "\n=== Get Confession Detail (ID: $CONFESSION_ID) ==="
curl -s -X GET "$BACKEND_URL/confessions/$CONFESSION_ID" -H "Content-Type: application/json" | jq .
echo -e "\n=== Submit Report ==="
curl -s -X POST "$BACKEND_URL/reports" \
-H "Content-Type: application/json" \
-d "{\"confessionId\":\"$CONFESSION_ID\",\"type\":\"offensive\",\"reason\":\"test\"}" | jq .
fi
echo -e "\n=== Admin Endpoint (No Auth - Should Fail) ==="
curl -s -X GET "$BACKEND_URL/diagnostics/notifications" -H "Content-Type: application/json" -w "\nStatus: %{http_code}\n"
echo -e "\n✓ Smoke test complete!"- Ensure backend is running:
npm run dev --workspace=xconfess-backend - Verify port 5000 is correct:
lsof -i :5000
- Use
| jq .to format responses - Check backend logs for errors:
docker logs <container>
- Ensure you have a valid JWT token
- Login via
POST /users/loginor/auth/loginfirst - Pass token in header:
Authorization: Bearer {token}
- Ensure Postgres is running:
docker ps | grep postgres - Verify database is seeded: Check via psql or frontend
- Run
npm run devfrom repo root to compile controllers - Check OpenAPI docs:
http://localhost:5000/docs(if available)
Record these response times for regression detection:
| Endpoint | Method | Expected Time | Actual |
|---|---|---|---|
/ |
GET | < 100ms | ___ |
/health/live |
GET | < 100ms | ___ |
/health/ready |
GET | < 500ms | ___ |
/confessions |
GET | < 500ms | ___ |
/confessions/:id |
GET | < 200ms | ___ |
/reports |
POST | < 500ms | ___ |