Resolve the operational/config sprawl (#10-#14 from the review): the app read NORMOGEN_*/MONGODB_* env vars but every env/compose file set SERVER_*/DATABASE_*, the ports were all over the place (8080/8000/6500/6800), there were 5 inconsistent Dockerfiles (rust:1.82 vs rust:1.93, missing curl), and an 18 MB binary was committed. Env-var names — standardize on what the code reads: * config/mod.rs: NORMOGEN_PORT default 8080 -> 6500 (avoid the over-common 8000/8080). * db/mod.rs: create_database() now reads MONGODB_DATABASE (was DATABASE_NAME). * .env.example, defaults.env, docker-compose.yml, docker-compose.dev.yml, DEPLOYMENT_GUIDE.md, deployment/README.md, deploy-and-test-solaria.sh, deploy-local-build.sh: use NORMOGEN_HOST/NORMOGEN_PORT/MONGODB_URI/ MONGODB_DATABASE/APP_ENVIRONMENT; drop the dead SERVER_*/DATABASE_URI/ DATABASE_NAME names. Ports — canonical container port 6500 everywhere: * Both Dockerfiles EXPOSE 6500; prod compose maps 6500:6500, dev 6501:6500. * Bulk-replaced the long tail of solaria:8000/localhost:8000/localhost:8080 in docs and test scripts -> 6500. Dockerfiles — 2 canonical, rust:latest, curl + healthcheck: * backend/Dockerfile (prod): rust:latest builder, debian runtime now installs curl (so the compose HEALTHCHECK actually works), EXPOSE 6500. * backend/docker/Dockerfile.dev (dev): rust:latest both stages, EXPOSE 6500. * Deleted 3 redundant Dockerfiles (Dockerfile.improved x2, docker/Dockerfile). * Deleted the committed 18 MB binary backend/docker/normogen-backend. * Deleted 2 stray fix-notes in backend/docker/. Compose: * docker-compose.yml: correct env names, 6500:6500, APP_ENVIRONMENT=production, JWT_SECRET/ENCRYPTION_KEY required via compose interpolation, dropped the obsolete top-level version: key. * docker-compose.dev.yml: correct env names, 6501:6500, mongo:7 (was 6.0), added a working backend healthcheck. * Deleted docker/docker-compose.improved.yml + backend/deploy-to-solaria-improved.sh (built around the now-deleted 'improved' Docker files). Verified: cargo fmt --check clean, build + clippy --all-targets clean, 18 unit tests pass; grep confirms no SERVER_*/DATABASE_* env names and no rust:1.x tags remain outside docs/archive and docs/adr (historical).
288 lines
9.4 KiB
Bash
288 lines
9.4 KiB
Bash
#!/bin/bash
|
|
|
|
API_URL="http://localhost:6500"
|
|
USER_EMAIL="med-test-${RANDOM}@example.com"
|
|
USER_NAME="medtest${RANDOM}"
|
|
|
|
echo "=========================================="
|
|
echo "Phase 2.7 - Comprehensive API Test Suite"
|
|
echo "=========================================="
|
|
echo ""
|
|
|
|
# Test 1: Health Check
|
|
echo "🔍 Test 1: Health Check"
|
|
echo "Endpoint: GET /health"
|
|
HEALTH=$(curl -s -w "\nHTTP_CODE:%{http_code}" ${API_URL}/health)
|
|
HTTP_CODE=$(echo "$HEALTH" | grep "HTTP_CODE" | cut -d: -f2)
|
|
BODY=$(echo "$HEALTH" | sed '/HTTP_CODE/d')
|
|
echo "Response: $BODY"
|
|
echo "HTTP Status: $HTTP_CODE"
|
|
if [ "$HTTP_CODE" = "200" ]; then
|
|
echo "✅ PASS"
|
|
else
|
|
echo "❌ FAIL - Backend not healthy"
|
|
exit 1
|
|
fi
|
|
echo ""
|
|
|
|
# Test 2: Register User
|
|
echo "🔍 Test 2: Register New User"
|
|
echo "Endpoint: POST /api/auth/register"
|
|
REGISTER=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X POST ${API_URL}/api/auth/register \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"email":"'${USER_EMAIL}'","username":"'${USER_NAME}'","password":"SecurePass123!","first_name":"Test","last_name":"User"}')
|
|
HTTP_CODE=$(echo "$REGISTER" | grep "HTTP_CODE" | cut -d: -f2)
|
|
BODY=$(echo "$REGISTER" | sed '/HTTP_CODE/d')
|
|
echo "Response: $BODY"
|
|
echo "HTTP Status: $HTTP_CODE"
|
|
if [ "$HTTP_CODE" = "201" ]; then
|
|
echo "✅ PASS"
|
|
USER_ID=$(echo "$BODY" | grep -o '"id":"[^"]*' | cut -d'"' -f4)
|
|
echo "User ID: $USER_ID"
|
|
else
|
|
echo "❌ FAIL"
|
|
fi
|
|
echo ""
|
|
|
|
# Test 3: Login
|
|
echo "🔍 Test 3: Login"
|
|
echo "Endpoint: POST /api/auth/login"
|
|
LOGIN=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X POST ${API_URL}/api/auth/login \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"email":"'${USER_EMAIL}'","password":"SecurePass123!"}')
|
|
HTTP_CODE=$(echo "$LOGIN" | grep "HTTP_CODE" | cut -d: -f2)
|
|
BODY=$(echo "$LOGIN" | sed '/HTTP_CODE/d')
|
|
echo "Response: $BODY"
|
|
echo "HTTP Status: $HTTP_CODE"
|
|
if [ "$HTTP_CODE" = "200" ]; then
|
|
echo "✅ PASS"
|
|
TOKEN=$(echo "$BODY" | grep -o '"access_token":"[^"]*' | cut -d'"' -f4)
|
|
echo "Token obtained: ${TOKEN:0:20}..."
|
|
else
|
|
echo "❌ FAIL - Cannot continue without token"
|
|
exit 1
|
|
fi
|
|
echo ""
|
|
|
|
# Test 4: Create Medication
|
|
echo "🔍 Test 4: Create Medication"
|
|
echo "Endpoint: POST /api/medications"
|
|
CREATE_MED=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X POST ${API_URL}/api/medications \
|
|
-H "Content-Type: application/json" \
|
|
-H "Authorization: Bearer $TOKEN" \
|
|
-d '{"profile_id":null,"name":"Lisinopril","dosage":"10mg","frequency":"once_daily","instructions":"Take with breakfast","start_date":"2026-03-01"}')
|
|
HTTP_CODE=$(echo "$CREATE_MED" | grep "HTTP_CODE" | cut -d: -f2)
|
|
BODY=$(echo "$CREATE_MED" | sed '/HTTP_CODE/d')
|
|
echo "Response: $BODY"
|
|
echo "HTTP Status: $HTTP_CODE"
|
|
if [ "$HTTP_CODE" = "201" ]; then
|
|
echo "✅ PASS"
|
|
MED_ID=$(echo "$BODY" | grep -o '"id":"[^"]*' | head -1 | cut -d'"' -f4)
|
|
echo "Medication ID: $MED_ID"
|
|
else
|
|
echo "❌ FAIL"
|
|
fi
|
|
echo ""
|
|
|
|
# Test 5: List Medications
|
|
echo "🔍 Test 5: List Medications"
|
|
echo "Endpoint: GET /api/medications"
|
|
LIST_MEDS=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X GET ${API_URL}/api/medications \
|
|
-H "Authorization: Bearer $TOKEN")
|
|
HTTP_CODE=$(echo "$LIST_MEDS" | grep "HTTP_CODE" | cut -d: -f2)
|
|
BODY=$(echo "$LIST_MEDS" | sed '/HTTP_CODE/d')
|
|
echo "Response: $BODY"
|
|
echo "HTTP Status: $HTTP_CODE"
|
|
if [ "$HTTP_CODE" = "200" ]; then
|
|
echo "✅ PASS"
|
|
MED_COUNT=$(echo "$BODY" | grep -o '"medications"' | wc -l)
|
|
echo "Medications in list: $MED_COUNT"
|
|
else
|
|
echo "❌ FAIL"
|
|
fi
|
|
echo ""
|
|
|
|
# Test 6: Get Specific Medication
|
|
echo "🔍 Test 6: Get Specific Medication"
|
|
echo "Endpoint: GET /api/medications/$MED_ID"
|
|
GET_MED=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X GET ${API_URL}/api/medications/$MED_ID \
|
|
-H "Authorization: Bearer $TOKEN")
|
|
HTTP_CODE=$(echo "$GET_MED" | grep "HTTP_CODE" | cut -d: -f2)
|
|
BODY=$(echo "$GET_MED" | sed '/HTTP_CODE/d')
|
|
echo "Response: $BODY"
|
|
echo "HTTP Status: $HTTP_CODE"
|
|
if [ "$HTTP_CODE" = "200" ]; then
|
|
echo "✅ PASS"
|
|
else
|
|
echo "❌ FAIL"
|
|
fi
|
|
echo ""
|
|
|
|
# Test 7: Update Medication
|
|
echo "🔍 Test 7: Update Medication"
|
|
echo "Endpoint: POST /api/medications/$MED_ID"
|
|
UPDATE_MED=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X POST ${API_URL}/api/medications/$MED_ID \
|
|
-H "Content-Type: application/json" \
|
|
-H "Authorization: Bearer $TOKEN" \
|
|
-d '{"dosage":"20mg","instructions":"Take with breakfast and dinner"}')
|
|
HTTP_CODE=$(echo "$UPDATE_MED" | grep "HTTP_CODE" | cut -d: -f2)
|
|
BODY=$(echo "$UPDATE_MED" | sed '/HTTP_CODE/d')
|
|
echo "Response: $BODY"
|
|
echo "HTTP Status: $HTTP_CODE"
|
|
if [ "$HTTP_CODE" = "200" ]; then
|
|
echo "✅ PASS"
|
|
else
|
|
echo "❌ FAIL"
|
|
fi
|
|
echo ""
|
|
|
|
# Test 8: Log Dose
|
|
echo "🔍 Test 8: Log Dose"
|
|
echo "Endpoint: POST /api/medications/$MED_ID/log"
|
|
LOG_DOSE=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X POST ${API_URL}/api/medications/$MED_ID/log \
|
|
-H "Content-Type: application/json" \
|
|
-H "Authorization: Bearer $TOKEN" \
|
|
-d '{"taken":true,"scheduled_time":"2026-03-08T08:00:00Z","notes":"Taken with breakfast"}')
|
|
HTTP_CODE=$(echo "$LOG_DOSE" | grep "HTTP_CODE" | cut -d: -f2)
|
|
BODY=$(echo "$LOG_DOSE" | sed '/HTTP_CODE/d')
|
|
echo "Response: $BODY"
|
|
echo "HTTP Status: $HTTP_CODE"
|
|
if [ "$HTTP_CODE" = "201" ]; then
|
|
echo "✅ PASS"
|
|
else
|
|
echo "❌ FAIL"
|
|
fi
|
|
echo ""
|
|
|
|
# Test 9: Get Adherence
|
|
echo "🔍 Test 9: Get Adherence"
|
|
echo "Endpoint: GET /api/medications/$MED_ID/adherence"
|
|
ADHERENCE=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X GET ${API_URL}/api/medications/$MED_ID/adherence \
|
|
-H "Authorization: Bearer $TOKEN")
|
|
HTTP_CODE=$(echo "$ADHERENCE" | grep "HTTP_CODE" | cut -d: -f2)
|
|
BODY=$(echo "$ADHERENCE" | sed '/HTTP_CODE/d')
|
|
echo "Response: $BODY"
|
|
echo "HTTP Status: $HTTP_CODE"
|
|
if [ "$HTTP_CODE" = "200" ]; then
|
|
echo "✅ PASS"
|
|
ADH_PCT=$(echo "$BODY" | grep -o '"adherence_percentage":[0-9.]*' | cut -d: -f2)
|
|
echo "Adherence: $ADH_PCT%"
|
|
else
|
|
echo "❌ FAIL"
|
|
fi
|
|
echo ""
|
|
|
|
# Test 10: Create Health Stat
|
|
echo "🔍 Test 10: Create Health Stat"
|
|
echo "Endpoint: POST /api/health-stats"
|
|
CREATE_STAT=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X POST ${API_URL}/api/health-stats \
|
|
-H "Content-Type: application/json" \
|
|
-H "Authorization: Bearer $TOKEN" \
|
|
-d '{"profile_id":null,"stat_type":"blood_pressure","value":{"systolic":120,"diastolic":80},"unit":"mmHg","recorded_at":"2026-03-08T10:00:00Z"}')
|
|
HTTP_CODE=$(echo "$CREATE_STAT" | grep "HTTP_CODE" | cut -d: -f2)
|
|
BODY=$(echo "$CREATE_STAT" | sed '/HTTP_CODE/d')
|
|
echo "Response: $BODY"
|
|
echo "HTTP Status: $HTTP_CODE"
|
|
if [ "$HTTP_CODE" = "201" ]; then
|
|
echo "✅ PASS"
|
|
STAT_ID=$(echo "$BODY" | grep -o '"id":"[^"]*' | cut -d'"' -f4)
|
|
echo "Health Stat ID: $STAT_ID"
|
|
else
|
|
echo "❌ FAIL"
|
|
fi
|
|
echo ""
|
|
|
|
# Test 11: List Health Stats
|
|
echo "🔍 Test 11: List Health Stats"
|
|
echo "Endpoint: GET /api/health-stats"
|
|
LIST_STATS=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X GET ${API_URL}/api/health-stats \
|
|
-H "Authorization: Bearer $TOKEN")
|
|
HTTP_CODE=$(echo "$LIST_STATS" | grep "HTTP_CODE" | cut -d: -f2)
|
|
BODY=$(echo "$LIST_STATS" | sed '/HTTP_CODE/d')
|
|
echo "Response: $BODY"
|
|
echo "HTTP Status: $HTTP_CODE"
|
|
if [ "$HTTP_CODE" = "200" ]; then
|
|
echo "✅ PASS"
|
|
else
|
|
echo "❌ FAIL"
|
|
fi
|
|
echo ""
|
|
|
|
# Test 12: Get Health Trends
|
|
echo "🔍 Test 12: Get Health Trends"
|
|
echo "Endpoint: GET /api/health-stats/trends?stat_type=blood_pressure&period=7d"
|
|
TRENDS=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X GET "${API_URL}/api/health-stats/trends?stat_type=blood_pressure&period=7d" \
|
|
-H "Authorization: Bearer $TOKEN")
|
|
HTTP_CODE=$(echo "$TRENDS" | grep "HTTP_CODE" | cut -d: -f2)
|
|
BODY=$(echo "$TRENDS" | sed '/HTTP_CODE/d')
|
|
echo "Response: $BODY"
|
|
echo "HTTP Status: $HTTP_CODE"
|
|
if [ "$HTTP_CODE" = "200" ]; then
|
|
echo "✅ PASS"
|
|
else
|
|
echo "❌ FAIL"
|
|
fi
|
|
echo ""
|
|
|
|
# Test 13: Unauthorized Access
|
|
echo "🔍 Test 13: Unauthorized Access (No Token)"
|
|
echo "Endpoint: GET /api/medications"
|
|
UNAUTH=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X GET ${API_URL}/api/medications)
|
|
HTTP_CODE=$(echo "$UNAUTH" | grep "HTTP_CODE" | cut -d: -f2)
|
|
echo "HTTP Status: $HTTP_CODE"
|
|
if [ "$HTTP_CODE" = "401" ]; then
|
|
echo "✅ PASS - Correctly blocked unauthorized access"
|
|
else
|
|
echo "❌ FAIL - Should return 401"
|
|
fi
|
|
echo ""
|
|
|
|
# Test 14: Get User Profile
|
|
echo "🔍 Test 14: Get User Profile"
|
|
echo "Endpoint: GET /api/users/me"
|
|
PROFILE=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X GET ${API_URL}/api/users/me \
|
|
-H "Authorization: Bearer $TOKEN")
|
|
HTTP_CODE=$(echo "$PROFILE" | grep "HTTP_CODE" | cut -d: -f2)
|
|
BODY=$(echo "$PROFILE" | sed '/HTTP_CODE/d')
|
|
echo "Response: $BODY"
|
|
echo "HTTP Status: $HTTP_CODE"
|
|
if [ "$HTTP_CODE" = "200" ]; then
|
|
echo "✅ PASS"
|
|
else
|
|
echo "❌ FAIL"
|
|
fi
|
|
echo ""
|
|
|
|
# Test 15: Get Sessions
|
|
echo "🔍 Test 15: Get User Sessions"
|
|
echo "Endpoint: GET /api/sessions"
|
|
SESSIONS=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X GET ${API_URL}/api/sessions \
|
|
-H "Authorization: Bearer $TOKEN")
|
|
HTTP_CODE=$(echo "$SESSIONS" | grep "HTTP_CODE" | cut -d: -f2)
|
|
BODY=$(echo "$SESSIONS" | sed '/HTTP_CODE/d')
|
|
echo "Response: $BODY"
|
|
echo "HTTP Status: $HTTP_CODE"
|
|
if [ "$HTTP_CODE" = "200" ]; then
|
|
echo "✅ PASS"
|
|
else
|
|
echo "❌ FAIL"
|
|
fi
|
|
echo ""
|
|
|
|
# Test 16: Delete Medication
|
|
echo "🔍 Test 16: Delete Medication"
|
|
echo "Endpoint: POST /api/medications/$MED_ID/delete"
|
|
DELETE_MED=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X POST ${API_URL}/api/medications/$MED_ID/delete \
|
|
-H "Authorization: Bearer $TOKEN")
|
|
HTTP_CODE=$(echo "$DELETE_MED" | grep "HTTP_CODE" | cut -d: -f2)
|
|
echo "HTTP Status: $HTTP_CODE"
|
|
if [ "$HTTP_CODE" = "204" ]; then
|
|
echo "✅ PASS - No content (successful deletion)"
|
|
else
|
|
echo "❌ FAIL"
|
|
fi
|
|
echo ""
|
|
|
|
echo "=========================================="
|
|
echo "✅ All Tests Complete!"
|
|
echo "=========================================="
|