forked from retoor/devplacepy
Update
This commit is contained in:
@@ -3,12 +3,13 @@
|
||||
from datetime import datetime, timedelta, timezone
|
||||
|
||||
import pytest
|
||||
from devplacepy.db_client import get_table, init_db
|
||||
from devplacepy.db_client import (
|
||||
from devplacepy.database import (
|
||||
can_give_award,
|
||||
can_receive_award,
|
||||
get_table,
|
||||
has_giver_cooldown,
|
||||
has_receiver_cooldown,
|
||||
init_db,
|
||||
recompute_user_award_stats,
|
||||
revoke_award,
|
||||
)
|
||||
|
||||
@@ -6,8 +6,12 @@ from datetime import datetime, timezone
|
||||
|
||||
import pytest
|
||||
from PIL import Image
|
||||
from devplacepy.db_client import get_award_usage, get_table, init_db
|
||||
from devplacepy.db_client import recompute_user_award_stats
|
||||
from devplacepy.database import (
|
||||
get_award_usage,
|
||||
get_table,
|
||||
init_db,
|
||||
recompute_user_award_stats,
|
||||
)
|
||||
from devplacepy.services.jobs.award_service import AwardService
|
||||
from devplacepy.utils import generate_uid, make_combined_slug
|
||||
from tests.conftest import run_async
|
||||
|
||||
@@ -1,212 +0,0 @@
|
||||
# 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,args,expected_keys",
|
||||
[
|
||||
("build_messages_page", ("u1",), {"threads", "unread", "partners"}),
|
||||
("build_notifications_page", ("u1",), {"notifications", "actors", "unread_count"}),
|
||||
("build_game_state", (), {"store", "leaderboard"}),
|
||||
("build_admin_dashboard", (), {"stats", "service_states"}),
|
||||
],
|
||||
)
|
||||
def test_stub_compounds_documented(local_db, fn_name, args, expected_keys):
|
||||
import devplacepy_services.database.compounds_page as compounds_page
|
||||
|
||||
fn = getattr(compounds_page, fn_name)
|
||||
result = fn(*args)
|
||||
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"
|
||||
)
|
||||
@@ -1,56 +0,0 @@
|
||||
# retoor <retoor@molodetz.nl>
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
from devplacepy_services.base.config import PROFILES
|
||||
|
||||
SERVICE_MODULES = (
|
||||
"devplacepy_services.database.main",
|
||||
"devplacepy_services.pubsub.main",
|
||||
"devplacepy_services.web.main",
|
||||
"devplacepy_services.gateway.main",
|
||||
"devplacepy_services.jobs.main",
|
||||
"devplacepy_services.devii.main",
|
||||
"devplacepy_services.bot.main",
|
||||
"devplacepy_services.backup.main",
|
||||
"devplacepy_services.containers.main",
|
||||
"devplacepy_services.telegram.main",
|
||||
"devplacepy_services.email.main",
|
||||
"devplacepy_services.news.main",
|
||||
"devplacepy_services.gitea.main",
|
||||
"devplacepy_services.audit.main",
|
||||
"devplacepy_services.xmlrpc.main",
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("module_name", SERVICE_MODULES)
|
||||
def test_service_imports(module_name):
|
||||
env = os.environ.copy()
|
||||
env["DEVPLACE_DISABLE_SERVICES"] = "1"
|
||||
env["DEVPLACE_DATABASE_URL"] = "sqlite:///:memory:"
|
||||
env.pop("DEVPLACE_REMOTE_DB", None)
|
||||
env.pop("DEVPLACE_DB_SERVICE", None)
|
||||
script = (
|
||||
f"import importlib; m = importlib.import_module('{module_name}'); "
|
||||
"assert hasattr(m, 'app')"
|
||||
)
|
||||
result = subprocess.run(
|
||||
[sys.executable, "-c", script],
|
||||
env=env,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=30,
|
||||
check=False,
|
||||
)
|
||||
assert result.returncode == 0, result.stderr or result.stdout
|
||||
|
||||
|
||||
def test_port_profiles_complete():
|
||||
for profile in ("micro-dev", "micro-test", "micro-prod"):
|
||||
ports = PROFILES[profile]
|
||||
assert "web" in ports
|
||||
assert ports["web"] in (10500, 20500)
|
||||
Reference in New Issue
Block a user