trymeapp/tests/test_auth_and_keys.py

97 lines
3.3 KiB
Python
Raw Permalink Normal View History

2026-11-11 22:06:26 +00:00
from __future__ import annotations
from fastapi.testclient import TestClient
def test_profile_onboarding_consent_gender_age_no_birthday(client: TestClient) -> None:
login = client.post("/api/v1/auth/dev-login", json={"nickname": "koala_kid"})
assert login.status_code == 200
token = login.json()["access_token"]
headers = {"Authorization": f"Bearer {token}"}
# Without public_website_consent, creating a quiz is blocked
blocked = client.post(
"/api/v1/quizzes",
headers=headers,
json={"title": "Early Quiz", "description": "Test", "is_public": True, "questions": []},
)
assert blocked.status_code == 403
# Update profile with stylized animal, color, inclusive gender, age (no birthday) & consent
updated = client.patch(
"/api/v1/users/me",
headers=headers,
json={
"nickname": "koala_kid",
"first_name": "Sam",
"last_name": "Chen",
"age": 16,
"gender": "other",
"gender_custom": "Demiboy",
"avatar_animal": "koala",
"avatar_color": "avatar-5",
"public_website_consent": True,
},
)
assert updated.status_code == 200
profile = updated.json()
assert profile["onboarded"] is True
assert profile["age"] == 16
assert "birthday" not in profile
assert "birth_date" not in profile
assert profile["gender"] == "other"
assert profile["gender_custom"] == "Demiboy"
assert profile["avatar_animal"] == "koala"
assert profile["avatar_color"] == "avatar-5"
assert profile["public_website_consent"] is True
def test_api_key_lifecycle_and_expiration(client: TestClient) -> None:
login = client.post("/api/v1/auth/dev-login", json={"nickname": "key_tester"})
token = login.json()["access_token"]
headers = {"Authorization": f"Bearer {token}"}
client.patch(
"/api/v1/users/me",
headers=headers,
json={"public_website_consent": True},
)
# Create API key
create_resp = client.post(
"/api/v1/users/me/api-keys",
headers=headers,
json={"name": "CLI Study Bot", "expires_in_days": 30},
)
assert create_resp.status_code == 201
key_data = create_resp.json()
raw_key = key_data["raw_key"]
key_id = key_data["id"]
assert raw_key.startswith("tm_live_")
assert key_data["is_active"] is True
# Authenticate using X-API-Key header
me_via_key = client.get("/api/v1/users/me", headers={"X-API-Key": raw_key})
assert me_via_key.status_code == 200
assert me_via_key.json()["nickname"] == "key_tester"
# List keys should not leak raw_key
list_resp = client.get("/api/v1/users/me/api-keys", headers=headers)
assert list_resp.status_code == 200
listed = list_resp.json()
assert len(listed) == 1
assert "raw_key" not in listed[0]
assert listed[0]["last_used_at"] is not None
# Expire old key
expire_resp = client.post(
f"/api/v1/users/me/api-keys/{key_id}/expire",
headers=headers,
)
assert expire_resp.status_code == 200
assert expire_resp.json()["is_active"] is False
# Subsequent calls with the expired API key must fail with 401
revoked_check = client.get("/api/v1/users/me", headers={"X-API-Key": raw_key})
assert revoked_check.status_code == 401