gapguide-api / tests /manual_e2e.sh
arifRB's picture
Deploy GapGuide backend (Docker)
ffd36e0 verified
Raw
History Blame Contribute Delete
7.07 kB
#!/usr/bin/env bash
# Manual E2E run against a live server on :8765.
# Exercises the entire student happy path: register → skills → target role →
# analyze → recommendations → checkpoint toggle → upgrade suggestions → apply
# → re-analyze, plus the claim checks that live HTTP can see.
set -u
API="http://127.0.0.1:8765/api"
say() { printf '\n\033[1;36m== %s ==\033[0m\n' "$*"; }
ok() { printf '\033[32m[ok]\033[0m %s\n' "$*"; }
fail(){ printf '\033[31m[FAIL]\033[0m %s\n' "$*"; }
# Unique email so re-runs don't collide with the previous state.
TAG="e2e$RANDOM"
# ---------------------------------------------------------------------------
# CLAIM #2 (weak password accepted) — live HTTP verification
# ---------------------------------------------------------------------------
say "CLAIM #2: weak password accepted at /register/"
R=$(curl -s -o /tmp/r.json -w '%{http_code}' \
-H 'Content-Type: application/json' \
-d "{\"name\":\"w\",\"email\":\"weak_${TAG}@x.com\",\"password\":\"abc\",\"password_confirm\":\"abc\"}" \
"$API/auth/register/")
[ "$R" = "201" ] && ok "weak password 'abc' was accepted (HTTP 201) — CLAIM CONFIRMED" \
|| fail "unexpected HTTP $R"
# ---------------------------------------------------------------------------
# CLAIM #3 (email case-sensitive uniqueness) — live HTTP
# ---------------------------------------------------------------------------
say "CLAIM #3: email uniqueness is case-sensitive"
UPPER="Case_${TAG}@x.com"
LOWER="case_${TAG}@x.com"
R1=$(curl -s -o /dev/null -w '%{http_code}' \
-H 'Content-Type: application/json' \
-d "{\"name\":\"u\",\"email\":\"$UPPER\",\"password\":\"StrongPass123!\",\"password_confirm\":\"StrongPass123!\"}" \
"$API/auth/register/")
R2=$(curl -s -o /dev/null -w '%{http_code}' \
-H 'Content-Type: application/json' \
-d "{\"name\":\"l\",\"email\":\"$LOWER\",\"password\":\"StrongPass123!\",\"password_confirm\":\"StrongPass123!\"}" \
"$API/auth/register/")
[ "$R1" = "201" ] && [ "$R2" = "201" ] && ok "Both $UPPER and $LOWER registered — CLAIM CONFIRMED" \
|| fail "upper=$R1 lower=$R2"
# ---------------------------------------------------------------------------
# Full student happy path
# ---------------------------------------------------------------------------
say "REGISTER student"
REG=$(curl -s -H 'Content-Type: application/json' \
-d "{\"name\":\"Student\",\"email\":\"student_${TAG}@x.com\",\"password\":\"StrongPass123!\",\"password_confirm\":\"StrongPass123!\"}" \
"$API/auth/register/")
ACCESS=$(echo "$REG" | python -c "import json,sys;print(json.load(sys.stdin)['access'])")
[ -n "$ACCESS" ] && ok "got JWT access token" || { fail "no access token"; exit 1; }
H=(-H "Authorization: Bearer $ACCESS" -H 'Content-Type: application/json')
say "LIST skills catalog"
N_SKILLS=$(curl -s "${H[@]}" "$API/skills/?page_size=200" \
| python -c "import json,sys;d=json.load(sys.stdin);print(d['count'])")
ok "skills count = $N_SKILLS"
say "LIST roles"
N_ROLES=$(curl -s "${H[@]}" "$API/roles/" \
| python -c "import json,sys;print(len(json.load(sys.stdin)))")
ok "roles count = $N_ROLES"
say "Pick Data Scientist role"
DS_ID=$(curl -s "${H[@]}" "$API/roles/" \
| python -c "import json,sys;print(next(r['id'] for r in json.load(sys.stdin) if r['role_name']=='Data Scientist'))")
ok "DS role_id = $DS_ID"
say "SET TARGET ROLE -> Data Scientist"
curl -s "${H[@]}" -d "{\"role_id\":$DS_ID}" "$API/target-role/" > /dev/null
ok "target role set"
say "SET USER SKILLS (Python=70, SQL=90)"
PY_ID=$(curl -s "${H[@]}" "$API/skills/?page_size=200" \
| python -c "import json,sys;print(next(s['id'] for s in json.load(sys.stdin)['results'] if s['skill_name']=='Python'))")
SQL_ID=$(curl -s "${H[@]}" "$API/skills/?page_size=200" \
| python -c "import json,sys;print(next(s['id'] for s in json.load(sys.stdin)['results'] if s['skill_name']=='SQL'))")
curl -s "${H[@]}" -d "{\"skill_id\":$PY_ID,\"proficiency\":70}" "$API/user-skills/" > /dev/null
curl -s "${H[@]}" -d "{\"skill_id\":$SQL_ID,\"proficiency\":90}" "$API/user-skills/" > /dev/null
ok "Python=70, SQL=90 set"
say "GAP ANALYSIS"
GAP=$(curl -s "${H[@]}" "$API/analysis/")
R=$(echo "$GAP" | python -c "import json,sys;d=json.load(sys.stdin);print(d['readiness'],d['band'],d['mandatory_cap_applied'])")
ok "readiness/band/cap = $R"
say "RECOMMENDATIONS"
REC=$(curl -s "${H[@]}" "$API/recommendations/")
N_GAPS=$(echo "$REC" | python -c "import json,sys;d=json.load(sys.stdin);print(len(d['recommendations']))")
ok "gap-skill keys in recs = $N_GAPS"
# Pick any skill that has recommendations for the checkpoint-toggle test.
RES_TITLE=$(echo "$REC" | python -c "
import json,sys
d = json.load(sys.stdin)
for sid, items in d['recommendations'].items():
if items:
print(items[0]['resource_id'], items[0]['title']); break
")
RES_ID=$(echo "$RES_TITLE" | awk '{print $1}')
ok "top rec resource_id = $RES_ID"
say "GET resource detail (checkpoints?)"
DET=$(curl -s "${H[@]}" "$API/resources/$RES_ID/")
N_CP=$(echo "$DET" | python -c "import json,sys;print(len(json.load(sys.stdin)['checkpoints']))")
ok "checkpoints = $N_CP"
if [ "$N_CP" -gt 0 ]; then
say "TOGGLE all checkpoints"
for CP in $(echo "$DET" | python -c "import json,sys;print(*(c['id'] for c in json.load(sys.stdin)['checkpoints']))"); do
curl -s "${H[@]}" -X POST "$API/progress/checkpoint/$CP/toggle/" -d '{"completed":true}' > /dev/null
done
PROG=$(curl -s "${H[@]}" "$API/progress/resource/$RES_ID/" \
| python -c "import json,sys;d=json.load(sys.stdin);print(d['status'], d['progress'])")
ok "resource status/progress after all toggles = $PROG"
else
say "MANUAL slider to 100 (no checkpoints on this resource)"
curl -s "${H[@]}" -X POST "$API/progress/resource/$RES_ID/" -d '{"progress":100}' > /dev/null
ok "marked COMPLETED via slider"
fi
say "UPGRADE SUGGESTIONS"
SUG=$(curl -s "${H[@]}" "$API/progress/upgrade-suggestions/")
N_SUG=$(echo "$SUG" | python -c "import json,sys;print(len(json.load(sys.stdin)['suggestions']))")
ok "pending suggestions = $N_SUG"
if [ "$N_SUG" -gt 0 ]; then
FIRST_SKILL=$(echo "$SUG" | python -c "import json,sys;print(json.load(sys.stdin)['suggestions'][0]['skill_id'])")
say "CLAIM #1: apply the upgrade THREE TIMES in a row on the same completion"
for i in 1 2 3 4; do
R=$(curl -s "${H[@]}" -X POST "$API/progress/upgrade-suggestions/$FIRST_SKILL/apply/")
APPLIED=$(echo "$R" | python -c "import json,sys;d=json.load(sys.stdin);print(d.get('applied'), d.get('already_applied'), d.get('user_skill',{}).get('proficiency'))")
ok "call #$i applied/already/prof = $APPLIED"
done
echo "→ If the spec held, only call #1 would show 'applied=True'."
fi
say "POST-UPGRADE GAP ANALYSIS"
GAP2=$(curl -s "${H[@]}" "$API/analysis/")
R2=$(echo "$GAP2" | python -c "import json,sys;d=json.load(sys.stdin);print(d['readiness'],d['band'],d['mandatory_cap_applied'])")
ok "readiness/band/cap = $R2"