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