import datetime
import re
import pytest
TODAY = datetime.date.today().isoformat()
@pytest.fixture
def instructor(dev_client):
dev_client.post("/dev/launch/dev-instructor")
return dev_client
def test_home_page(instructor):
page = instructor.get("/instructor/").get_data(as_text=True)
assert "8 active students" in page
assert "Live cold call" in page
def test_live_flow_records_outcome(instructor):
resp = instructor.post(
"/instructor/live/next", data={"date": TODAY}, follow_redirects=True
)
page = resp.get_data(as_text=True)
match = re.search(r'/instructor/call/(\d+)/outcome', page)
assert match, "live page should show outcome buttons for the call"
assert "GOOD" in page
call_id = match.group(1)
resp = instructor.post(
f"/instructor/call/{call_id}/outcome",
data={"action": "GOOD"},
follow_redirects=True,
)
page = resp.get_data(as_text=True)
assert "Calls so far today" in page
assert "GOOD" in page
# The call is resolved, so the next-student button is back.
assert "Call next student" in page
def test_live_requires_resolution_before_next(instructor):
instructor.post("/instructor/live/next", data={"date": TODAY})
page = instructor.get(f"/instructor/live?date={TODAY}").get_data(as_text=True)
first_call = re.search(r'/instructor/call/(\d+)/outcome', page).group(1)
# Pressing next again does not create a second pending call.
instructor.post("/instructor/live/next", data={"date": TODAY})
page = instructor.get(f"/instructor/live?date={TODAY}").get_data(as_text=True)
assert re.findall(r'/instructor/call/(\d+)/outcome', page) == [first_call]
def test_generate_and_print(instructor):
resp = instructor.post(
f"/instructor/day/{TODAY}/generate",
data={"n": "12"},
follow_redirects=True,
)
page = resp.get_data(as_text=True)
assert page.count("
") == 13 # header + 12 rows
def test_regenerate_replaces_pending(instructor):
instructor.post(f"/instructor/day/{TODAY}/generate", data={"n": "12"})
resp = instructor.post(
f"/instructor/day/{TODAY}/generate",
data={"n": "5"},
follow_redirects=True,
)
assert resp.get_data(as_text=True).count("
") == 6
def test_day_edit_saves_outcomes(instructor):
instructor.post(f"/instructor/day/{TODAY}/generate", data={"n": "2"})
page = instructor.get(f"/instructor/day/{TODAY}").get_data(as_text=True)
ids = re.findall(r'name="status-(\d+)"', page)
assert len(ids) == 2
resp = instructor.post(
f"/instructor/day/{TODAY}",
data={
f"status-{ids[0]}": "answered",
f"assessment-{ids[0]}": "POOR",
f"note-{ids[0]}": "rough day",
f"status-{ids[1]}": "pending",
f"delete-{ids[1]}": "on",
},
follow_redirects=True,
)
page = resp.get_data(as_text=True)
assert 'value="rough day"' in page
assert len(re.findall(r'name="status-(\d+)"', page)) == 1
def test_outcome_rejects_bad_action_and_foreign_call(instructor):
instructor.post("/instructor/live/next", data={"date": TODAY})
page = instructor.get(f"/instructor/live?date={TODAY}").get_data(as_text=True)
call_id = re.search(r'/instructor/call/(\d+)/outcome', page).group(1)
resp = instructor.post(
f"/instructor/call/{call_id}/outcome", data={"action": "nonsense"}
)
assert resp.status_code == 400
resp = instructor.post(
"/instructor/call/99999/outcome", data={"action": "GOOD"}
)
assert resp.status_code == 404
def test_settings_roundtrip(instructor):
resp = instructor.post(
"/instructor/settings",
data={"selection_mode": "cycle", "weight_factor": "3.0"},
follow_redirects=True,
)
page = resp.get_data(as_text=True)
assert '