from __future__ import annotations def _create_profile(client, display_name: str = "API Fan") -> str: response = client.post( "/profiles", json={ "display_name": display_name, "country_code": "GB", "favorite_team_id": "ALPHA", }, ) assert response.status_code == 201, response.text body = response.json() assert body["profile"]["display_name"] == display_name assert body["created"] is True assert body["completed_challenges"] return body["profile"]["id"] def test_primary_passport_api_flow(client) -> None: user_id = _create_profile(client) teams = client.get("/content/teams").json() assert {team["id"] for team in teams} >= {"ALPHA", "BETA"} collect = client.post( f"/users/{user_id}/collections", json={"item_type": "team", "item_id": "ALPHA", "source": "test"}, ) assert collect.status_code == 200, collect.text collect_body = collect.json() assert collect_body["duplicate"] is False assert collect_body["item"]["points_awarded"] == 20 duplicate = client.post( f"/users/{user_id}/collections", json={"item_type": "team", "item_id": "ALPHA", "source": "test"}, ) assert duplicate.status_code == 200, duplicate.text assert duplicate.json()["duplicate"] is True daily = client.get("/quiz/questions/daily?date=2026-06-01") assert daily.status_code == 200, daily.text question_id = daily.json()["id"] answer = client.post( f"/users/{user_id}/quiz/answers", json={"question_id": question_id, "selected_option": "B"}, ) assert answer.status_code == 200, answer.text assert answer.json()["correct"] is True prediction = client.post( f"/users/{user_id}/predictions", json={ "match_id": "MATCH-1", "predicted_home_score": 2, "predicted_away_score": 1, "giant_killing_pick": False, }, ) assert prediction.status_code == 200, prediction.text assert prediction.json()["prediction"]["match_id"] == "MATCH-1" result = client.put( "/admin/matches/MATCH-1/result", headers={"X-Fan-Admin-Key": "test-admin"}, json={ "status": "final", "home_score": 2, "away_score": 1, "is_giant_killing": False, }, ) assert result.status_code == 200, result.text assert result.json()["evaluated_predictions"] == 1 passport = client.get(f"/users/{user_id}/passport") assert passport.status_code == 200, passport.text passport_body = passport.json() assert passport_body["profile"]["points_total"] > 0 assert passport_body["collection_counts"]["team"] == 1 assert passport_body["quiz"]["correct"] == 1 assert passport_body["predictions"]["evaluated"] == 1 leaderboard = client.get("/leaderboards?metric=points_total&limit=5") assert leaderboard.status_code == 200, leaderboard.text assert leaderboard.json()[0]["user_id"] == user_id def test_me_profile_uses_dev_header_auth(client) -> None: response = client.post( "/me/profile", headers={"X-Fan-User": "subject-123", "X-Fan-Display-Name": "Header Fan"}, json={"country_code": "US"}, ) assert response.status_code == 200, response.text body = response.json() assert body["profile"]["external_subject"] == "subject-123" assert body["profile"]["display_name"] == "Header Fan" def test_admin_content_import_and_moderation_report(client) -> None: import_response = client.post( "/admin/content/import", headers={"X-Fan-Admin-Key": "test-admin"}, json={ "quiz_questions": [ { "id": "QUIZ-2", "competition_code": "test-cup", "slug": "second-question", "prompt": "Second?", "options_json": [{"id": "A", "text": "Yes"}], "correct_option": "A", "difficulty": "easy", } ] }, ) assert import_response.status_code == 200, import_response.text assert import_response.json()["counts"]["quiz_questions"] == 1 user_id = _create_profile(client, display_name="Reporter") report = client.post( "/moderation/reports", json={ "reporter_user_id": user_id, "target_type": "collection_item", "target_id": "fake-target", "reason": "Inappropriate memory text", }, ) assert report.status_code == 201, report.text admin_reports = client.get( "/admin/moderation/reports", headers={"X-Fan-Admin-Key": "test-admin"}, ) assert admin_reports.status_code == 200, admin_reports.text assert admin_reports.json()[0]["reason"] == "Inappropriate memory text"