# retoor from devplacepy.database import get_table from tests.api.sync.conftest import poll_record, seed_world, sync_ok def options_of(poll_uid): return {row["label"]: row for row in get_table("poll_options").find(poll_uid=poll_uid)} def test_a_poll_is_created_with_its_options(client, admin, origin): seed_world(client, admin, origin) result = sync_ok(client, admin, "polls", origin, [poll_record()])["results"][0] assert result["status"] == "created" poll = get_table("polls").find_one(uid=result["local_uid"]) assert poll["question"] == "Tabs or spaces?" and poll["deleted_at"] is None assert sorted(options_of(poll["uid"])) == ["Spaces", "Tabs"] assert sorted(row["position"] for row in options_of(poll["uid"]).values()) == [0, 1] def test_option_validation(client, admin, origin): seed_world(client, admin, origin) one = poll_record(options=[{"origin_uid": "a", "label": "Only"}]) dup = poll_record(options=[{"origin_uid": "a", "label": "X"}, {"origin_uid": "a", "label": "Y"}]) many = poll_record(options=[{"origin_uid": str(index), "label": f"o{index}"} for index in range(7)]) body = sync_ok(client, admin, "polls", origin, [one, dup, many]) assert [item["status"] for item in body["results"]] == ["rejected"] * 3 def test_edit_adds_renames_and_removes_options(client, admin, origin): seed_world(client, admin, origin) created = sync_ok(client, admin, "polls", origin, [poll_record()])["results"][0] edited = poll_record( question="Tabs, spaces or both?", options=[{"origin_uid": "a", "label": "Tabs!"}, {"origin_uid": "c", "label": "Both"}], updated_at="2025-02-01T00:00:00Z", ) assert sync_ok(client, admin, "polls", origin, [edited])["results"][0]["status"] == "updated" rows = list(get_table("poll_options").find(poll_uid=created["local_uid"])) live = sorted(row["label"] for row in rows if not row["deleted_at"]) assert live == ["Both", "Tabs!"] assert [row["label"] for row in rows if row["deleted_at"]] == ["Spaces"] assert get_table("polls").find_one(uid=created["local_uid"])["question"] == "Tabs, spaces or both?" def test_one_poll_per_post(client, admin, origin): seed_world(client, admin, origin) sync_ok(client, admin, "polls", origin, [poll_record("po1")]) second = sync_ok(client, admin, "polls", origin, [poll_record("po2")])["results"][0] assert second["status"] == "rejected" and "already has a poll" in second["errors"][0] assert get_table("sync_links").count(origin=origin, kind="polls") == 1 def test_a_tombstone_removes_poll_options_and_votes_together_and_restores(client, admin, origin): seed_world(client, admin, origin) created = sync_ok(client, admin, "polls", origin, [poll_record()])["results"][0] from tests.api.sync.conftest import poll_vote_record sync_ok(client, admin, "poll_votes", origin, [poll_vote_record()]) gone = poll_record(updated_at="2025-02-01T00:00:00Z", deleted=True) sync_ok(client, admin, "polls", origin, [gone]) uid = created["local_uid"] assert get_table("polls").find_one(uid=uid)["deleted_at"] assert all(row["deleted_at"] for row in get_table("poll_options").find(poll_uid=uid)) assert all(row["deleted_at"] for row in get_table("poll_votes").find(poll_uid=uid)) back = poll_record(updated_at="2025-03-01T00:00:00Z") sync_ok(client, admin, "polls", origin, [back]) assert get_table("polls").find_one(uid=uid)["deleted_at"] is None assert all(row["deleted_at"] is None for row in get_table("poll_options").find(poll_uid=uid)) def test_an_unknown_post_waits(client, admin, origin): seed_world(client, admin, origin) result = sync_ok(client, admin, "polls", origin, [poll_record(post="nope")])["results"][0] assert result["status"] == "deferred" and result["reason"] == "unknown_post"