feat: Expose level progress percentage in profile API response #144
@@ -407,3 +407,96 @@ def test_viewing_profile_marks_notification_read(app_server):
|
|||||||
|
|
||||||
refresh_snapshot()
|
refresh_snapshot()
|
||||||
assert bool(get_table("notifications").find_one(uid=notif_uid)["read"]) is True
|
assert bool(get_table("notifications").find_one(uid=notif_uid)["read"]) is True
|
||||||
|
|
||||||
|
|
||||||
|
def test_own_profile_json_exposes_xp_fields(app_server, seeded_db):
|
||||||
|
"""GET /profile (own) with Accept: application/json includes xp_next_level and xp_progress_pct."""
|
||||||
|
import requests
|
||||||
|
|
||||||
|
session = requests.Session()
|
||||||
|
session.post(
|
||||||
|
f"{BASE_URL}/auth/login",
|
||||||
|
data={
|
||||||
|
"username": seeded_db["alice"]["username"],
|
||||||
|
"password": seeded_db["alice"]["password"],
|
||||||
|
},
|
||||||
|
allow_redirects=True,
|
||||||
|
)
|
||||||
|
r = session.get(f"{BASE_URL}/profile", headers={"Accept": "application/json"})
|
||||||
|
assert r.status_code == 200
|
||||||
|
data = r.json()
|
||||||
|
pu = data["profile_user"]
|
||||||
|
assert "xp_next_level" in pu, "xp_next_level missing from own profile JSON"
|
||||||
|
assert "xp_progress_pct" in pu, "xp_progress_pct missing from own profile JSON"
|
||||||
|
assert isinstance(pu["xp_next_level"], int)
|
||||||
|
assert isinstance(pu["xp_progress_pct"], int)
|
||||||
|
|
||||||
|
|
||||||
|
def test_other_profile_json_exposes_xp_fields(app_server):
|
||||||
|
"""GET /profile/{username} with Accept: application/json includes xp_next_level and xp_progress_pct."""
|
||||||
|
from devplacepy.database import get_table, refresh_snapshot
|
||||||
|
|
||||||
|
owner = _seed_owner()
|
||||||
|
username = get_table("users").find_one(uid=owner)["username"]
|
||||||
|
refresh_snapshot()
|
||||||
|
|
||||||
|
r = requests.get(
|
||||||
|
f"{BASE_URL}/profile/{username}", headers={"Accept": "application/json"}
|
||||||
|
)
|
||||||
|
assert r.status_code == 200
|
||||||
|
data = r.json()
|
||||||
|
pu = data["profile_user"]
|
||||||
|
assert "xp_next_level" in pu, "xp_next_level missing from other profile JSON"
|
||||||
|
assert "xp_progress_pct" in pu, "xp_progress_pct missing from other profile JSON"
|
||||||
|
assert isinstance(pu["xp_next_level"], int)
|
||||||
|
assert isinstance(pu["xp_progress_pct"], int)
|
||||||
|
|
||||||
|
|
||||||
|
def test_profile_json_xp_fields_zero_xp(app_server):
|
||||||
|
"""User with 0 XP returns xp_next_level=100 (level 1) and xp_progress_pct=0."""
|
||||||
|
from devplacepy.database import get_table, refresh_snapshot
|
||||||
|
from devplacepy.utils.rewards import LEVEL_XP
|
||||||
|
|
||||||
|
owner = _seed_owner()
|
||||||
|
username = get_table("users").find_one(uid=owner)["username"]
|
||||||
|
refresh_snapshot()
|
||||||
|
|
||||||
|
r = requests.get(
|
||||||
|
f"{BASE_URL}/profile/{username}", headers={"Accept": "application/json"}
|
||||||
|
)
|
||||||
|
assert r.status_code == 200
|
||||||
|
pu = r.json()["profile_user"]
|
||||||
|
assert pu["xp"] == 0 or pu["xp"] is None, f"expected 0 xp, got {pu['xp']}"
|
||||||
|
assert pu["xp_next_level"] == LEVEL_XP, (
|
||||||
|
f"expected xp_next_level={LEVEL_XP} for level 1, got {pu['xp_next_level']}"
|
||||||
|
)
|
||||||
|
assert pu["xp_progress_pct"] == 0, (
|
||||||
|
f"expected xp_progress_pct=0 for 0 XP, got {pu['xp_progress_pct']}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_profile_json_xp_fields_boundary_xp(app_server):
|
||||||
|
"""User with exactly 100 XP (level 2) returns xp_next_level=200 and xp_progress_pct=0."""
|
||||||
|
from devplacepy.database import get_table, refresh_snapshot
|
||||||
|
from devplacepy.utils.rewards import award_xp
|
||||||
|
|
||||||
|
owner = _seed_owner()
|
||||||
|
username = get_table("users").find_one(uid=owner)["username"]
|
||||||
|
award_xp(owner, 100)
|
||||||
|
refresh_snapshot()
|
||||||
|
|
||||||
|
r = requests.get(
|
||||||
|
f"{BASE_URL}/profile/{username}", headers={"Accept": "application/json"}
|
||||||
|
)
|
||||||
|
assert r.status_code == 200
|
||||||
|
pu = r.json()["profile_user"]
|
||||||
|
assert pu["xp"] == 100, f"expected 100 xp, got {pu['xp']}"
|
||||||
|
assert pu["level"] == 2, f"expected level 2, got {pu['level']}"
|
||||||
|
assert pu["xp_next_level"] == 200, (
|
||||||
|
f"expected xp_next_level=200 for level 2, got {pu['xp_next_level']}"
|
||||||
|
)
|
||||||
|
assert pu["xp_progress_pct"] == 0, (
|
||||||
|
f"expected xp_progress_pct=0 at boundary, got {pu['xp_progress_pct']}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user