# retoor import requests from tests.conftest import BASE_URL def _seed_news_seo(): from datetime import datetime, timezone from devplacepy.database import get_table from devplacepy.utils import generate_uid, make_combined_slug uid = generate_uid() title = f"SEO Test News Article {uid.split('-')[-1]}" slug = make_combined_slug(title, uid) get_table("news").insert( { "deleted_at": None, "deleted_by": None, "uid": uid, "slug": slug, "title": title, "description": "A seeded news article for SEO tests.", "content": "Body content for the seeded article.", "url": "https://example.com/article", "source_name": "ExampleSource", "status": "published", "synced_at": datetime.now(timezone.utc).isoformat(), "show_on_landing": 0, "grade": 8, } ) return slug, uid def _seed_owner(): from datetime import datetime, timezone from uuid import uuid4 from devplacepy.database import get_table uid = str(uuid4()) get_table("users").insert( { "uid": uid, "username": f"seo_{uid[:8]}", "email": f"{uid[:8]}@seo.test", "password_hash": "x", "role": "Member", "is_active": True, "created_at": datetime.now(timezone.utc).isoformat(), } ) return uid def _seed_post_seo(image=None): from datetime import datetime, timezone from uuid import uuid4 from devplacepy.database import get_table from devplacepy.utils import make_combined_slug owner = _seed_owner() uid = str(uuid4()) slug = make_combined_slug("SEO Detail Post", uid) get_table("posts").insert( { "deleted_at": None, "deleted_by": None, "uid": uid, "user_uid": owner, "slug": slug, "title": "SEO Detail Post", "content": "Body text for the SEO detail post.", "topic": "general", "project_uid": None, "image": image, "stars": 0, "created_at": datetime.now(timezone.utc).isoformat(), } ) return slug, uid def _seed_gist(): from datetime import datetime, timezone from uuid import uuid4 from devplacepy.database import get_table from devplacepy.utils import make_combined_slug owner = _seed_owner() uid = str(uuid4()) slug = make_combined_slug("SEO Detail Gist", uid) get_table("gists").insert( { "deleted_at": None, "deleted_by": None, "uid": uid, "user_uid": owner, "slug": slug, "title": "SEO Detail Gist", "description": "Gist description for SEO tests.", "source_code": "print('seo')", "language": "python", "stars": 0, "created_at": datetime.now(timezone.utc).isoformat(), } ) return slug, uid def _seed_project(): from datetime import datetime, timezone from uuid import uuid4 from devplacepy.database import get_table from devplacepy.utils import make_combined_slug owner = _seed_owner() uid = str(uuid4()) slug = make_combined_slug("SEO Detail Project", uid) get_table("projects").insert( { "deleted_at": None, "deleted_by": None, "uid": uid, "user_uid": owner, "slug": slug, "title": "SEO Detail Project", "description": "Project description for SEO tests.", "project_type": "software", "platforms": "Linux", "status": "Released", "stars": 0, "created_at": datetime.now(timezone.utc).isoformat(), } ) return slug, uid def _seed_news_image(news_uid): from devplacepy.database import get_table get_table("news_images").insert( { "deleted_at": None, "deleted_by": None, "news_uid": news_uid, "url": "https://example.com/seo-news-image.jpg", } ) def _seed_feed_posts(count): from datetime import datetime, timezone, timedelta from uuid import uuid4 from devplacepy.database import get_table from devplacepy.utils import make_combined_slug owner = _seed_owner() topic = f"seopag{owner[:8]}" base = datetime(2026, 1, 1, tzinfo=timezone.utc) posts = get_table("posts") for i in range(count): uid = str(uuid4()) posts.insert( { "deleted_at": None, "deleted_by": None, "uid": uid, "user_uid": owner, "slug": make_combined_slug(f"seo pag {i}", uid), "title": None, "content": f"seo pag post {i}", "topic": topic, "project_uid": None, "image": None, "stars": 0, "created_at": (base - timedelta(seconds=i)).isoformat(), } ) return topic def test_missing_profile_returns_404(app_server): r = requests.get(f"{BASE_URL}/profile/no-such-user-xyz", allow_redirects=False) assert r.status_code == 404 def _seed_comment_on_post(commenter_uid): from datetime import datetime, timezone from uuid import uuid4 from devplacepy.database import get_table post_slug, post_uid = _seed_post_seo() comment_uid = str(uuid4()) get_table("comments").insert( { "deleted_at": None, "deleted_by": None, "uid": comment_uid, "target_type": "post", "target_uid": post_uid, "post_uid": post_uid, "user_uid": commenter_uid, "content": "Activity tab link comment body", "parent_uid": None, "created_at": datetime.now(timezone.utc).isoformat(), } ) return post_slug, post_uid, comment_uid def test_activity_comment_exposes_parent_post_url(app_server): from devplacepy.database import get_table, refresh_snapshot commenter = _seed_owner() username = get_table("users").find_one(uid=commenter)["username"] post_slug, _post_uid, comment_uid = _seed_comment_on_post(commenter) refresh_snapshot() r = requests.get( f"{BASE_URL}/profile/{username}?tab=activity", headers={"Accept": "application/json"}, ) assert r.status_code == 200 activities = r.json()["activities"] comment_acts = [a for a in activities if a.get("type") == "comment"] assert comment_acts, "expected a comment activity" act = comment_acts[0] assert act["url"] == f"/posts/{post_slug}#comment-{comment_uid}" assert act["target_type"] == "post" def test_activity_comment_url_matches_notification_target(app_server): from devplacepy.database import get_table, refresh_snapshot, resolve_object_url commenter = _seed_owner() username = get_table("users").find_one(uid=commenter)["username"] _post_slug, post_uid, comment_uid = _seed_comment_on_post(commenter) refresh_snapshot() expected = f"{resolve_object_url('post', post_uid)}#comment-{comment_uid}" r = requests.get( f"{BASE_URL}/profile/{username}?tab=activity", headers={"Accept": "application/json"}, ) act = [a for a in r.json()["activities"] if a.get("type") == "comment"][0] assert act["url"] == expected def test_activity_post_exposes_url(app_server): from datetime import datetime, timezone from devplacepy.database import get_table, refresh_snapshot owner = _seed_owner() username = get_table("users").find_one(uid=owner)["username"] post_slug, post_uid = _seed_post_seo() get_table("posts").update({"uid": post_uid, "user_uid": owner}, ["uid"]) refresh_snapshot() r = requests.get( f"{BASE_URL}/profile/{username}?tab=activity", headers={"Accept": "application/json"}, ) assert r.status_code == 200 post_acts = [a for a in r.json()["activities"] if a.get("type") == "post"] assert post_acts, "expected a post activity" assert post_acts[0]["url"] == f"/posts/{post_slug}" def test_activity_comment_card_renders_overlay_link(app_server): from devplacepy.database import get_table, refresh_snapshot commenter = _seed_owner() username = get_table("users").find_one(uid=commenter)["username"] post_slug, _post_uid, comment_uid = _seed_comment_on_post(commenter) refresh_snapshot() r = requests.get(f"{BASE_URL}/profile/{username}?tab=activity") assert r.status_code == 200 assert "activity-card card-link-host" in r.text assert f'class="card-link" href="/posts/{post_slug}#comment-{comment_uid}"' in r.text def test_viewing_profile_marks_notification_read(app_server): import time from datetime import datetime, timezone from devplacepy.database import get_table, refresh_snapshot from devplacepy.utils import generate_uid name = f"nmark{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) notif_uid = generate_uid() get_table("notifications").insert( { "uid": notif_uid, "user_uid": user["uid"], "type": "follow", "message": "someone followed you", "related_uid": generate_uid(), "target_url": f"/profile/{name}", "read": False, "created_at": datetime.now(timezone.utc).isoformat(), } ) refresh_snapshot() r = session.get(f"{BASE_URL}/profile/{name}", allow_redirects=True) assert r.status_code == 200 refresh_snapshot() assert bool(get_table("notifications").find_one(uid=notif_uid)["read"]) is True