import time import requests from tests.conftest import BASE_URL from devplacepy.database import get_table _counter = [0] AJAX = {"X-Requested-With": "fetch"} def _session(): _counter[0] += 1 name = f"pol{int(time.time() * 1000)}{_counter[0]}" s = requests.Session() s.post(f"{BASE_URL}/auth/signup", data={ "username": name, "email": f"{name}@t.dev", "password": "secret123", "confirm_password": "secret123", }, allow_redirects=True) return s, name def _create_post(session, title, question, options): fields = [ ("content", "Poll host post content for tests."), ("title", title), ("topic", "question"), ("poll_question", question), ] fields.extend(("poll_options", option) for option in options) r = session.post(f"{BASE_URL}/posts/create", data=fields, allow_redirects=False) slug = r.headers["location"].split("/posts/")[-1] return get_table("posts").find_one(slug=slug)["uid"] def _poll_for(post_uid): poll = get_table("polls").find_one(post_uid=post_uid) options = list(get_table("poll_options").find(poll_uid=poll["uid"], order_by=["position"])) return poll, options def test_valid_poll_persists(app_server): s, _ = _session() title = f"valid-poll-{int(time.time() * 1000)}" post_uid = _create_post(s, title, "Tabs or spaces?", ["Tabs", "Spaces", "Both"]) poll, options = _poll_for(post_uid) assert poll is not None assert len(options) == 3 def test_poll_dropped_with_one_option(app_server): s, _ = _session() title = f"one-option-{int(time.time() * 1000)}" post_uid = _create_post(s, title, "Only one?", ["Solo"]) assert get_table("polls").find_one(post_uid=post_uid) is None def test_poll_dropped_without_question(app_server): s, _ = _session() title = f"no-question-{int(time.time() * 1000)}" post_uid = _create_post(s, title, "", ["Tabs", "Spaces"]) assert get_table("polls").find_one(post_uid=post_uid) is None def test_vote_records_choice(app_server): s, _ = _session() title = f"vote-{int(time.time() * 1000)}" post_uid = _create_post(s, title, "Pick one", ["A", "B"]) poll, options = _poll_for(post_uid) r = s.post(f"{BASE_URL}/polls/{poll['uid']}/vote", data={"option_uid": options[0]["uid"]}, headers=AJAX) payload = r.json() assert payload["total"] == 1 assert payload["my_choice"] == options[0]["uid"] assert get_table("poll_votes").count(poll_uid=poll["uid"]) == 1 def test_switch_vote_moves_choice(app_server): s, _ = _session() title = f"switch-{int(time.time() * 1000)}" post_uid = _create_post(s, title, "Pick one", ["A", "B"]) poll, options = _poll_for(post_uid) s.post(f"{BASE_URL}/polls/{poll['uid']}/vote", data={"option_uid": options[0]["uid"]}, headers=AJAX) r = s.post(f"{BASE_URL}/polls/{poll['uid']}/vote", data={"option_uid": options[1]["uid"]}, headers=AJAX) payload = r.json() assert payload["my_choice"] == options[1]["uid"] assert payload["total"] == 1 def test_repeat_same_option_retracts(app_server): s, _ = _session() title = f"retract-{int(time.time() * 1000)}" post_uid = _create_post(s, title, "Pick one", ["A", "B"]) poll, options = _poll_for(post_uid) s.post(f"{BASE_URL}/polls/{poll['uid']}/vote", data={"option_uid": options[0]["uid"]}, headers=AJAX) r = s.post(f"{BASE_URL}/polls/{poll['uid']}/vote", data={"option_uid": options[0]["uid"]}, headers=AJAX) payload = r.json() assert payload["my_choice"] is None assert payload["total"] == 0 assert get_table("poll_votes").count(poll_uid=poll["uid"]) == 0 def test_vote_invalid_option_returns_400(app_server): s, _ = _session() title = f"badopt-{int(time.time() * 1000)}" post_uid = _create_post(s, title, "Pick one", ["A", "B"]) poll, _ = _poll_for(post_uid) r = s.post(f"{BASE_URL}/polls/{poll['uid']}/vote", data={"option_uid": "not-a-real-option"}, headers=AJAX) assert r.status_code == 400 def test_vote_requires_login(app_server): s, _ = _session() title = f"authvote-{int(time.time() * 1000)}" post_uid = _create_post(s, title, "Pick one", ["A", "B"]) poll, options = _poll_for(post_uid) anon = requests.Session() r = anon.post(f"{BASE_URL}/polls/{poll['uid']}/vote", data={"option_uid": options[0]["uid"]}, headers=AJAX, allow_redirects=False) assert r.status_code == 303 assert get_table("poll_votes").count(poll_uid=poll["uid"]) == 0 def test_feed_shows_poll_results_without_voting(app_server): s, _ = _session() title = f"feedpoll-{int(time.time() * 1000)}" _create_post(s, title, "Visible results question?", ["Yes", "No"]) html = s.get(f"{BASE_URL}/feed").text assert "Visible results question?" in html assert "poll-option-bar" in html