trymeapp/tests/test_quizzes_and_scores.py

114 lines
3.9 KiB
Python
Raw Permalink Normal View History

2026-11-11 22:06:26 +00:00
from __future__ import annotations
from fastapi.testclient import TestClient
from tests.conftest import create_onboarded_student
def test_zero_to_forty_question_limit_and_mixed_grading(client: TestClient) -> None:
token_a, _ = create_onboarded_student(client, "author_owl", "owl", "avatar-2")
headers_a = {"Authorization": f"Bearer {token_a}"}
# 0 questions is valid on free tier
zero_resp = client.post(
"/api/v1/quizzes",
headers=headers_a,
json={
"title": "Draft Empty Quiz",
"description": "Zero questions allowed",
"is_public": True,
"questions": [],
},
)
assert zero_resp.status_code == 201
assert zero_resp.json()["question_count"] == 0
assert zero_resp.json()["quiz_mode"] == "empty"
# 41 questions is rejected on free tier
too_many = [
{
"question_type": "write_in",
"prompt": f"Question {i}",
"correct_answer": str(i),
}
for i in range(41)
]
over_limit = client.post(
"/api/v1/quizzes",
headers=headers_a,
json={"title": "41 Questions", "is_public": True, "questions": too_many},
)
assert over_limit.status_code == 422
# Create mixed Multiple-Choice + Write-In quiz
quiz_resp = client.post(
"/api/v1/quizzes",
headers=headers_a,
json={
"title": "Science Sprint",
"description": "Test MC and write-in",
"is_public": True,
"questions": [
{
"question_type": "multiple_choice",
"prompt": "What is H2O?",
"options": [
{"id": "a", "text": "Water"},
{"id": "b", "text": "Helium"},
],
"correct_answer": "a",
},
{
"question_type": "write_in",
"prompt": "How many planets orbit the Sun?",
"correct_answer": "8",
"accepted_answers": ["eight"],
},
],
},
)
assert quiz_resp.status_code == 201
quiz = quiz_resp.json()
quiz_id = quiz["id"]
share_slug = quiz["share_slug"]
q1_id = str(quiz["questions"][0]["id"])
q2_id = str(quiz["questions"][1]["id"])
# Fetch via share_slug as unauthenticated visitor (clear session cookie first)
client.cookies.clear()
by_slug = client.get(f"/api/v1/quizzes/{share_slug}")
assert by_slug.status_code == 200
assert by_slug.json()["editable_questions"] is None
# Player B plays twice: first 100%, then 50% -> latest is 50%, all-time best stays 100%!
token_b, _ = create_onboarded_student(client, "speedy_otter", "otter", "avatar-4")
headers_b = {"Authorization": f"Bearer {token_b}"}
sub1 = client.post(
f"/api/v1/quizzes/{quiz_id}/submit",
headers=headers_b,
json={"answers": {q1_id: "a", q2_id: " EIGHT "}},
)
assert sub1.status_code == 200
assert sub1.json()["score_percent"] == 100.0
sub2 = client.post(
f"/api/v1/quizzes/{quiz_id}/submit",
headers=headers_b,
json={"answers": {q1_id: "a", q2_id: "nine"}},
)
assert sub2.status_code == 200
s2 = sub2.json()
assert s2["my_latest_score"]["score_percent"] == 50.0
assert s2["my_best_score"]["score_percent"] == 100.0
assert s2["global_best_score"]["score_percent"] == 100.0
assert s2["global_best_score"]["holder_nickname"] == "speedy_otter"
# Thumbs up and down voting
v_up = client.post(f"/api/v1/quizzes/{quiz_id}/vote", headers=headers_a, json={"value": 1})
assert v_up.status_code == 200
v_down = client.post(f"/api/v1/quizzes/{quiz_id}/vote", headers=headers_b, json={"value": -1})
assert v_down.status_code == 200
assert v_down.json()["upvotes"] == 1
assert v_down.json()["downvotes"] == 1