import datetime import re import pytest from conftest import outcome_actions TODAY = datetime.date.today().isoformat() @pytest.fixture def instructor(dev_client): dev_client.post("/dev/launch/dev-instructor") # Speed: shrink the simulation for tests. dev_client.post( "/instructor/settings", data={"selection_mode": "weighted", "weight_factor": "2", "show_assessments": "on", "n_sims": "200", "sim_seed": "1"}, ) return dev_client def record_calls(client, n=6): for _ in range(n): client.post("/instructor/live/next", data={"date": TODAY}) page = client.get(f"/instructor/live?date={TODAY}").get_data(as_text=True) call_id = re.search(r"/instructor/call/(\d+)/outcome", page).group(1) client.post( f"/instructor/call/{call_id}/outcome", data={"action": outcome_actions(page)["GOOD"]}, ) def test_grades_page_before_compute(instructor): page = instructor.get("/instructor/grades/").get_data(as_text=True) assert "No grades computed yet" in page def test_compute_and_view_grades(instructor): record_calls(instructor) resp = instructor.post( "/instructor/grades/compute", follow_redirects=True ) page = resp.get_data(as_text=True) assert "SD of full-attendance counts" in page assert "4.00" in page # someone answered GOOD -> full marks assert "never answered" in page # not everyone got called resp = instructor.get("/instructor/grades/export.csv") assert resp.mimetype == "text/csv" assert "final_points" in resp.get_data(as_text=True) def test_student_report_and_publishing(instructor): record_calls(instructor) instructor.post("/instructor/grades/compute") page = instructor.get("/instructor/grades/").get_data(as_text=True) student_id = re.search(r"/instructor/grades/student/(\d+)", page).group(1) report = instructor.get( f"/instructor/grades/student/{student_id}" ).get_data(as_text=True) assert "How your grade was computed" in report # Unpublished: students see no report link and get 404. instructor.post("/dev/launch/dev-student-1") assert "participation grade report" not in instructor.get("/me").get_data(as_text=True) assert instructor.get("/me/report").status_code == 404 # Publish, and the student can read their own report. instructor.post("/dev/launch/dev-instructor") instructor.post( "/instructor/settings", data={"selection_mode": "weighted", "weight_factor": "2", "publish_grade_reports": "on"}, ) instructor.post("/dev/launch/dev-student-1") page = instructor.get("/me").get_data(as_text=True) assert "participation grade report" in page report = instructor.get("/me/report").get_data(as_text=True) assert "How your grade was computed" in report assert "Ada Lovelace" in report def test_push_flow_dev_mode(instructor): record_calls(instructor) instructor.post("/instructor/grades/compute") # Push pages don't exist until AGS is enabled. assert instructor.get("/instructor/grades/push").status_code == 404 instructor.post( "/instructor/settings", data={"selection_mode": "weighted", "weight_factor": "2", "ags_enabled": "on"}, ) page = instructor.get("/instructor/grades/push").get_data(as_text=True) assert "Review before pushing" in page assert "Push 8 grades to Canvas" in page resp = instructor.post("/instructor/grades/push") page = resp.get_data(as_text=True) assert "simulated (dev mode)" in page assert "8 of\n 8 pushed successfully" in page or "8 of" in page def test_grades_require_instructor(dev_client): dev_client.post("/dev/launch/dev-instructor") dev_client.post("/dev/launch/dev-student-1") assert dev_client.get("/instructor/grades/").status_code == 403 def test_scale_settings_and_canvas_import(instructor): # Threshold rows via the settings form. instructor.post( "/instructor/settings", data={"selection_mode": "weighted", "weight_factor": "2", "scale_type": "table", "scale_rows": "93 A\n90 A-\n0 F"}, ) record_calls(instructor, n=3) instructor.post("/instructor/grades/compute") page = instructor.get("/instructor/grades/").get_data(as_text=True) assert "A" in page