============================================================ Smoke test: enrollment workflow + bulk marks CSV upload Time: 2026-06-25T22:29:40.126Z ============================================================ [1] Student student5@school.com self-enrols in class_id=2 (Grade 2) student token len: 201 HTTP 201 -> {"id":6,"uid":"96d52c5a-411f-44ce-86ff-c79ebb1573bf","student_id":10,"class_id":2,"section":"A","roll_number":null,"admission_date":"2026-06-26","academic_year":"2026","status":"inactive","created_at":"2026-06-26 00:29:40","updated_at":"2026-06-26 00:29:40","last_synced_at":null,"sync_status":"pending","is_deleted":0,"request_status":"pending","requested_at":"2026-06-25T22:29:40.424Z","approved_by":null,"approved_at":null,"rejection_reason":null} PASS: request_status=pending, status=inactive [2] Admin GET /api/enrollments/pending HTTP 200, 1 rows PASS: enrollment 6 visible to admin [3] Admin POST /api/enrollments/:id/approve HTTP 200 -> {"id":6,"uid":"96d52c5a-411f-44ce-86ff-c79ebb1573bf","student_id":10,"class_id":2,"section":"A","roll_number":null,"admission_date":"2026-06-26","academic_year":"2026","status":"active","created_at":"2026-06-26 00:29:40","updated_at":"2026-06-26 00:29:40","last_synced_at":null,"sync_status":"pending","is_deleted":0,"request_status":"approved","requested_at":"2026-06-25T22:29:40.424Z","approved_by":2,"approved_at":"2026-06-26 00:29:40","rejection_reason":null} PASS: request_status=approved, approved_by=2 [4] Teacher uploads evidence/valid.csv (3 rows, all valid) HTTP 200 -> {"inserted":3,"updated":0,"errors":[],"total_rows":3} PASS: inserted=3, updated=0, errors=[] [5] Teacher uploads evidence/mixed.csv (4 rows: 2 valid, 2 invalid) HTTP 200 -> {"inserted":1,"updated":1,"errors":[{"row":4,"reason":"score is not numeric: not_a_number","data":{"assignment_id":"1","student_id":"10","score":"not_a_number","feedback":"Bad"}},{"row":5,"reason":"score 150 exceeds assignment.max_score 100","data":{"assignment_id":"2","student_id":"7","score":"150","feedback":"Score too high"}}],"total_rows":4} PASS: inserted=1, updated=1, errors=2 [score is not numeric: not_a_number | score 150 exceeds assignment.max_score 100] [6] Student attempts POST /api/marks/bulk (should be 403) HTTP 403 -> {"error":"Admin or Teacher access required"} PASS: student correctly blocked from /marks/bulk [7] GET /api/marks?assignment_id=1 HTTP 200, 2 rows PASS: returned 2 submission rows for assignment 1 ============================================================ SMOKE: PASS ============================================================