1
0
Files
coldcall_lti/tests/test_grades_ui.py
Benjamin Mako Hill 49d037692b Speak of the LMS generically, not Canvas specifically
The tool targets any LTI 1.3 platform; Canvas is the primary target
but nothing outside the Canvas-specific custom variable substitutions
depends on it. User-facing strings and the README now say "LMS"
except where a mechanism genuinely is Canvas's (the $Canvas.* /
com.instructure.* substitutions and their handling), and the README
states plainly that the tool has so far been exercised only against
the saltire emulator, not yet a production LMS.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-03 16:03:18 -07:00

124 lines
4.3 KiB
Python

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 the gradebook" 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 "<strong>A</strong>" in page