# retoor from devplacepy.database import get_table from tests.api.sync.conftest import post_record, sync_ok, unique, user_record def seed_author(client, admin, origin, uid="u1"): body = sync_ok(client, admin, "users", origin, [user_record(uid, unique("author"))]) return body["results"][0]["local_uid"] def test_unknown_author_is_rejected_with_reason(client, admin, origin): body = sync_ok(client, admin, "posts", origin, [post_record(author="missing")]) result = body["results"][0] assert result["status"] == "rejected" and result["reason"] == "unknown_author" assert get_table("sync_links").count(origin=origin) == 0 def test_create_normalizes_and_has_no_side_effects(client, admin, origin): author = seed_author(client, admin, origin) notifications_before = get_table("notifications").count() body = sync_ok( client, admin, "posts", origin, [post_record("p1", title=" Hello World ", content="line one\r\nline two ok", topic="nonsense", stars=50)], ) result = body["results"][0] assert result["status"] == "created" and result["ignored"] == ["stars"] row = get_table("posts").find_one(uid=result["local_uid"]) assert row["user_uid"] == author assert row["title"] == "Hello World" assert row["content"] == "line one\nline two ok" assert row["topic"] == "random" assert row["stars"] == 0 assert row["created_at"] == "2025-01-02T00:00:00+00:00" assert row["slug"].endswith("hello-world") assert row["deleted_at"] is None assert get_table("notifications").count() == notifications_before assert get_table("users").find_one(uid=author)["xp"] == 0 def test_replay_update_stale_and_tombstone(client, admin, origin): seed_author(client, admin, origin) created = sync_ok(client, admin, "posts", origin, [post_record("p1")])["results"][0] assert sync_ok(client, admin, "posts", origin, [post_record("p1")])["results"][0]["status"] == "unchanged" edited = sync_ok( client, admin, "posts", origin, [post_record("p1", content="edited synced content", updated_at="2025-03-01T00:00:00Z")], )["results"][0] assert edited["status"] == "updated" and edited["local_uid"] == created["local_uid"] assert get_table("posts").find_one(uid=created["local_uid"])["content"] == "edited synced content" stale = sync_ok( client, admin, "posts", origin, [post_record("p1", content="older content here", updated_at="2025-01-05T00:00:00Z")], )["results"][0] assert stale["status"] == "stale" deleted = sync_ok( client, admin, "posts", origin, [post_record("p1", content="edited synced content", updated_at="2025-04-01T00:00:00Z", deleted=True)], )["results"][0] assert deleted["status"] == "updated" row = get_table("posts").find_one(uid=created["local_uid"]) assert row["deleted_at"] and row["deleted_by"] == "sync" revived = sync_ok( client, admin, "posts", origin, [post_record("p1", content="edited synced content", updated_at="2025-05-01T00:00:00Z")], )["results"][0] assert revived["status"] == "updated" assert get_table("posts").find_one(uid=created["local_uid"])["deleted_at"] is None def test_locally_moderated_post_is_not_resurrected(client, admin, origin): seed_author(client, admin, origin) created = sync_ok(client, admin, "posts", origin, [post_record("p1")])["results"][0] get_table("posts").update( {"uid": created["local_uid"], "deleted_at": "2025-02-01T00:00:00+00:00", "deleted_by": admin["uid"]}, ["uid"], ) again = sync_ok( client, admin, "posts", origin, [post_record("p1", content="remote edit arrives", updated_at="2025-03-01T00:00:00Z")], )["results"][0] assert again["status"] == "unchanged" and again["reason"] == "locally_deleted" assert get_table("posts").find_one(uid=created["local_uid"])["content"] != "remote edit arrives" def test_purged_local_copy_is_not_recreated(client, admin, origin): seed_author(client, admin, origin) created = sync_ok(client, admin, "posts", origin, [post_record("p1")])["results"][0] get_table("posts").delete(uid=created["local_uid"]) again = sync_ok( client, admin, "posts", origin, [post_record("p1", content="changed after purge", updated_at="2025-03-01T00:00:00Z")], )["results"][0] assert again["status"] == "rejected" and again["reason"] == "purged_locally" assert get_table("posts").count(uid=created["local_uid"]) == 0 def test_invalid_post_reports_field_errors(client, admin, origin): seed_author(client, admin, origin) body = sync_ok(client, admin, "posts", origin, [post_record("p1", content="short")]) result = body["results"][0] assert result["status"] == "rejected" and result["reason"] == "invalid" assert any(error.startswith("content:") for error in result["errors"]) def test_future_timestamps_are_clamped(client, admin, origin): seed_author(client, admin, origin) body = sync_ok(client, admin, "posts", origin, [post_record("p1", created_at="2999-01-01T00:00:00Z")]) row = get_table("posts").find_one(uid=body["results"][0]["local_uid"]) assert row["created_at"] < "2100" def test_post_shows_up_on_its_detail_page(client, admin, origin): seed_author(client, admin, origin) body = sync_ok(client, admin, "posts", origin, [post_record("p1", title="Visible synced post")]) slug = get_table("posts").find_one(uid=body["results"][0]["local_uid"])["slug"] page = client.get(f"/posts/{slug}") assert page.status_code == 200 and "Visible synced post" in page.text