123 lines
4.3 KiB
Python
123 lines
4.3 KiB
Python
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
from fastapi.testclient import TestClient
|
|
from sqlalchemy.orm import Session, sessionmaker
|
|
|
|
from app.config import Settings, get_settings
|
|
from app.database import Base, build_engine, get_db
|
|
from app.main import app
|
|
from tests.conftest import create_onboarded_student
|
|
|
|
|
|
def test_favourites_add_reorder_and_delete(client: TestClient) -> None:
|
|
token, _ = create_onboarded_student(client, "fav_tiger", "tiger", "avatar-3")
|
|
headers = {"Authorization": f"Bearer {token}"}
|
|
|
|
quiz_ids: list[int] = []
|
|
for title in ("Quiz Alpha", "Quiz Beta", "Quiz Gamma"):
|
|
r = client.post(
|
|
"/api/v1/quizzes",
|
|
headers=headers,
|
|
json={"title": title, "is_public": True, "questions": []},
|
|
)
|
|
assert r.status_code == 201
|
|
quiz_ids.append(r.json()["id"])
|
|
|
|
for qid in quiz_ids:
|
|
add_r = client.post("/api/v1/favourites", headers=headers, json={"quiz_id": qid})
|
|
assert add_r.status_code == 201
|
|
|
|
# Reorder to Gamma, Alpha, Beta
|
|
reordered = [quiz_ids[2], quiz_ids[0], quiz_ids[1]]
|
|
put_r = client.put(
|
|
"/api/v1/favourites/reorder",
|
|
headers=headers,
|
|
json={"quiz_ids": reordered},
|
|
)
|
|
assert put_r.status_code == 200
|
|
assert [item["quiz"]["id"] for item in put_r.json()] == reordered
|
|
|
|
# Delete Alpha (simulating recycle bin drop)
|
|
del_r = client.delete(f"/api/v1/favourites/{quiz_ids[0]}", headers=headers)
|
|
assert del_r.status_code == 200
|
|
assert [item["quiz"]["id"] for item in del_r.json()] == [quiz_ids[2], quiz_ids[1]]
|
|
|
|
|
|
def test_moderator_claim_ban_and_remove_quiz(client: TestClient) -> None:
|
|
mod_token, _ = create_onboarded_student(client, "chief_mod", "bear", "avatar-6")
|
|
mod_headers = {"Authorization": f"Bearer {mod_token}"}
|
|
|
|
bad_token, bad_user = create_onboarded_student(client, "spammer_99", "frog", "avatar-7")
|
|
bad_headers = {"Authorization": f"Bearer {bad_token}"}
|
|
|
|
quiz_r = client.post(
|
|
"/api/v1/quizzes",
|
|
headers=bad_headers,
|
|
json={"title": "Unwanted Quiz", "is_public": True, "questions": []},
|
|
)
|
|
assert quiz_r.status_code == 201
|
|
quiz_id = quiz_r.json()["id"]
|
|
|
|
# Claim initial moderator when ADMIN_USER env var is unset
|
|
claim_r = client.post("/api/v1/admin/claim", headers=mod_headers)
|
|
assert claim_r.status_code == 200
|
|
assert claim_r.json()["is_admin"] is True
|
|
|
|
# Second claim must fail with 409
|
|
second_claim = client.post("/api/v1/admin/claim", headers=bad_headers)
|
|
assert second_claim.status_code == 409
|
|
|
|
# Moderator removes quiz
|
|
rem_r = client.delete(f"/api/v1/admin/quizzes/{quiz_id}", headers=mod_headers)
|
|
assert rem_r.status_code == 204
|
|
assert client.get(f"/api/v1/quizzes/{quiz_id}").status_code == 404
|
|
|
|
# Moderator bans spammer
|
|
ban_r = client.post(
|
|
f"/api/v1/admin/users/{bad_user['id']}/ban",
|
|
headers=mod_headers,
|
|
json={"reason": "Posting spam quizzes"},
|
|
)
|
|
assert ban_r.status_code == 200
|
|
assert ban_r.json()["is_banned"] is True
|
|
|
|
# Banned user cannot create quizzes
|
|
blocked = client.post(
|
|
"/api/v1/quizzes",
|
|
headers=bad_headers,
|
|
json={"title": "Blocked Quiz", "is_public": True, "questions": []},
|
|
)
|
|
assert blocked.status_code == 403
|
|
|
|
|
|
def test_admin_user_container_env_var(tmp_path: Path) -> None:
|
|
env_settings = Settings(
|
|
database_url=f"sqlite:///{(tmp_path / 'env_admin.db').as_posix()}",
|
|
dev_auth_enabled=True,
|
|
admin_user="launch_moderator",
|
|
session_secret="env-admin-secret",
|
|
)
|
|
eng = build_engine(env_settings.database_url)
|
|
Base.metadata.create_all(bind=eng)
|
|
LocalSession = sessionmaker(bind=eng, autoflush=False, autocommit=False, expire_on_commit=False)
|
|
|
|
def _override_db():
|
|
db: Session = LocalSession()
|
|
try:
|
|
yield db
|
|
finally:
|
|
db.close()
|
|
|
|
app.dependency_overrides[get_db] = _override_db
|
|
app.dependency_overrides[get_settings] = lambda: env_settings
|
|
try:
|
|
with TestClient(app) as c:
|
|
login_r = c.post("/api/v1/auth/dev-login", json={"nickname": "launch_moderator"})
|
|
assert login_r.status_code == 200
|
|
assert login_r.json()["user"]["is_admin"] is True
|
|
finally:
|
|
app.dependency_overrides.clear()
|
|
eng.dispose()
|