diff --git a/devplacepy/schemas/content.py b/devplacepy/schemas/content.py index 14ef907a..a5d15b88 100644 --- a/devplacepy/schemas/content.py +++ b/devplacepy/schemas/content.py @@ -4,6 +4,8 @@ from __future__ import annotations from typing import Any, Optional +from pydantic import ConfigDict, Field + from devplacepy.schemas.base import _Out @@ -64,8 +66,9 @@ class PollOut(_Out): class BadgeOut(_Out): - name: Optional[str] = None + name: Optional[str] = Field(None, alias="badge_name") created_at: Optional[str] = None + model_config = ConfigDict(populate_by_name=True) class PostOut(_Out): diff --git a/tests/api/profile/search.py b/tests/api/profile/search.py index 3115a2cb..01333631 100644 --- a/tests/api/profile/search.py +++ b/tests/api/profile/search.py @@ -271,3 +271,43 @@ def test_profile_renders_heatmap_and_streak(app_server): html = s.get(f"{BASE_URL}/profile/{name}").text assert "heatmap-grid" in html assert "1 day streak" in html + + +def test_profile_badges_json_has_non_null_names(app_server): + import time + from devplacepy.database import get_table, refresh_snapshot + from devplacepy.utils import award_badge + + name = f"bdg{int(time.time() * 1000)}" + session = requests.Session() + session.post( + f"{BASE_URL}/auth/signup", + data={ + "username": name, + "email": f"{name}@t.dev", + "password": "secret123", + "confirm_password": "secret123", + }, + allow_redirects=True, + ) + refresh_snapshot() + user = get_table("users").find_one(username=name) + assert user, f"user {name} not found after signup" + award_badge(user["uid"], "First Post") + award_badge(user["uid"], "Member") + refresh_snapshot() + r = session.get( + f"{BASE_URL}/profile/{name}", headers={"Accept": "application/json"} + ) + assert r.status_code == 200 + body = r.json() + assert "badges" in body, "badges key missing from profile JSON" + assert isinstance(body["badges"], list), "badges is not a list" + assert len(body["badges"]) >= 2, f"expected at least 2 badges, got {len(body['badges'])}" + for badge in body["badges"]: + assert "name" in badge, f"badge missing name key: {badge}" + assert badge["name"] is not None, f"badge name is null: {badge}" + assert isinstance(badge["name"], str), f"badge name is not a string: {badge}" + assert len(badge["name"]) > 0, f"badge name is empty: {badge}" + +