# retoor <retoor@molodetz.nl>
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"
)