Files
devplacepy/tests/api/sync/posts.py
T
retoorandClaude Sonnet 5.5 02ab747cd0
DevPlace CI / test (push) Failing after 44m45s
Code Farm: per-plot auto-replant pause and crop-lock check; community sync and node work
Continuous Delivery could never be turned off once a crop was planted. Add a
one-shot per-plot "stop after harvest" flag (POST /game/plot/stop, Devii tool
game_plot_stop, game_plots.stop_after_harvest), cleared by the next plant,
autoreplant claim or Refactor. Autoreplant now also respects crop locks through
the shared _crop_lock predicate. Plan and measurements in happyplanting.md.

Also includes the pending community sync, node network and related work in the
tree; the full suite passed (4999) with all of it.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-17 02:23:43 +02:00

121 lines
5.7 KiB
Python

# retoor <retoor@molodetz.nl>
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_deferred_with_the_reason_and_what_it_waits_for(client, admin, origin):
body = sync_ok(client, admin, "posts", origin, [post_record(author="missing")])
result = body["results"][0]
assert result["status"] == "deferred" and result["reason"] == "unknown_author"
assert (result["needs_kind"], result["needs_uid"]) == ("users", "missing")
assert get_table("sync_links").count(origin=origin) == 0
assert get_table("sync_pending").count(origin=origin) == 1
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