# retoor from datetime import datetime, timezone import pytest from devplacepy.db_client import get_table from devplacepy.utils import generate_uid def _now(): return datetime.now(timezone.utc).isoformat() def _make_user(local_db, **overrides): uid = generate_uid() row = { "uid": uid, "username": f"cpd_{uid[:8]}", "email": f"cpd_{uid[:8]}@t.dev", "api_key": generate_uid(), "role": "Member", "is_active": True, "created_at": _now(), "bio": "", } row.update(overrides) get_table("users").insert(row) return row def _make_post(local_db, user, **overrides): from devplacepy.utils import make_combined_slug uid = generate_uid() row = { "uid": uid, "user_uid": user["uid"], "title": "Compound test post", "content": "Body of the compound test post.", "topic": "devlog", "slug": make_combined_slug("Compound test post", uid), "stars": 0, "created_at": _now(), "deleted_at": None, "deleted_by": None, } row.update(overrides) get_table("posts").insert(row) return row def _make_project(local_db, user, **overrides): from devplacepy.utils import make_combined_slug uid = generate_uid() row = { "uid": uid, "user_uid": user["uid"], "title": "Compound test project", "description": "", "slug": make_combined_slug("Compound test project", uid), "stars": 0, "is_private": 0, "created_at": _now(), "deleted_at": None, "deleted_by": None, } row.update(overrides) get_table("projects").insert(row) return row def _make_gist(local_db, user, **overrides): from devplacepy.utils import make_combined_slug uid = generate_uid() row = { "uid": uid, "user_uid": user["uid"], "title": "Compound test gist", "description": "", "source_code": "print('hi')", "language": "python", "slug": make_combined_slug("Compound test gist", uid), "stars": 0, "created_at": _now(), "deleted_at": None, "deleted_by": None, } row.update(overrides) get_table("gists").insert(row) return row # Section 5.3 page compounds actually wired to a caller (db_client.build_*) # and consumed by a real web route. Each assertion checks the template # context keys the corresponding route/schema depends on. def test_build_feed_page_shape(local_db): from devplacepy_services.database.compounds_page import build_feed_page user = _make_user(local_db) post = _make_post(local_db, user) result = build_feed_page(user=user) for key in ("posts", "next_cursor", "stats", "top_authors", "daily_topic", "current_tab"): assert key in result uids = [item["post"]["uid"] for item in result["posts"]] assert post["uid"] in uids item = next(i for i in result["posts"] if i["post"]["uid"] == post["uid"]) for key in ("attachments", "recent_comments", "reactions", "bookmarked", "poll"): assert key in item def test_build_post_detail_shape(local_db): from devplacepy_services.database.compounds_page import build_post_detail user = _make_user(local_db) post = _make_post(local_db, user) result = build_post_detail(post["uid"], user=user) assert result["post"]["uid"] == post["uid"] assert result["author"]["uid"] == user["uid"] assert isinstance(result["comments"], list) assert isinstance(result["attachments"], list) def test_build_post_detail_missing_post(local_db): from devplacepy_services.database.compounds_page import build_post_detail result = build_post_detail("does-not-exist") assert result["post"] is None def test_build_profile_bundle_shape(local_db): from devplacepy_services.database.compounds_page import build_profile_bundle user = _make_user(local_db) result = build_profile_bundle(user["uid"]) assert result["user"]["uid"] == user["uid"] assert "followers" in result["follow_counts"] assert "following" in result["follow_counts"] def test_build_leaderboard_page_shape(local_db): from devplacepy_services.database.compounds_page import build_leaderboard_page user = _make_user(local_db) result = build_leaderboard_page(viewer_uid=user["uid"]) assert "leaderboard" in result assert isinstance(result["leaderboard"], list) def test_build_project_detail_shape(local_db): from devplacepy_services.database.compounds_page import build_project_detail user = _make_user(local_db) project = _make_project(local_db, user) result = build_project_detail(project["uid"]) assert result["project"]["uid"] == project["uid"] assert result["owner"]["uid"] == user["uid"] def test_build_gist_detail_shape(local_db): from devplacepy_services.database.compounds_page import build_gist_detail user = _make_user(local_db) gist = _make_gist(local_db, user) result = build_gist_detail(gist["uid"], user=user) assert result["gist"]["uid"] == gist["uid"] assert result["author"]["uid"] == user["uid"] assert isinstance(result["comments"], list) # Section 5.3 rows registered as HTTP endpoints (devplacepy_services/database/routes.py) # but not yet called by any web route (routers/messages.py, notifications.py, # game/, admin/index.py all still do their own direct db_client calls) - these # four builders are unfinished stubs, tracked here so a real implementation # lands as a visible test change rather than silently. @pytest.mark.parametrize( "fn_name,expected_keys", [ ("build_messages_page", {"threads", "unread", "partners"}), ("build_notifications_page", {"notifications", "actors", "unread_count"}), ("build_game_state", {"store", "leaderboard"}), ("build_admin_dashboard", {"stats", "service_states"}), ], ) def test_stub_compounds_documented(local_db, fn_name, expected_keys): import devplacepy_services.database.compounds_page as compounds_page fn = getattr(compounds_page, fn_name) result = fn() if fn_name != "build_admin_dashboard" else fn() assert set(result.keys()) == expected_keys, ( f"{fn_name} shape changed - if this is a real implementation now, " "replace this stub-tracking test with a real assertion and update " "splitup.md Section 17.2" )