OpenSlides/tests/integration/assignments/test_polls.py
Sean 97c2299aec Implement vote weight in client
Implements vote weight in client
The user detail page has a new property
change deserialize to parse floats
change "yes"-voting to send "Y" and "0" instead of "1" and "0"
add vote weight to user list, filter, sort
add vote weight to single voting result
votesvalid and votescast respect the individual vote weight
fix parse-poll pipe and null in pdf
2020-04-22 16:54:50 +02:00

2309 lines
92 KiB
Python

import random
from decimal import Decimal
from typing import Any
import pytest
from django.conf import settings
from django.contrib.auth import get_user_model
from django.urls import reverse
from rest_framework import status
from rest_framework.test import APIClient
from openslides.assignments.models import (
Assignment,
AssignmentOption,
AssignmentPoll,
AssignmentVote,
)
from openslides.core.config import config
from openslides.poll.models import BasePoll
from openslides.utils.auth import get_group_model
from openslides.utils.autoupdate import inform_changed_data
from tests.common_groups import GROUP_ADMIN_PK, GROUP_DELEGATE_PK
from tests.count_queries import count_queries
from tests.test_case import TestCase
@pytest.mark.django_db(transaction=False)
def test_assignment_poll_db_queries():
"""
Tests that only the following db queries are done:
* 1 request to get the polls,
* 1 request to get all options for all polls,
* 1 request to get all users for all options (candidates),
* 1 request to get all votes for all options,
* 1 request to get all users for all votes,
* 1 request to get all poll groups,
= 6 queries
"""
create_assignment_polls()
assert count_queries(AssignmentPoll.get_elements)() == 6
@pytest.mark.django_db(transaction=False)
def test_assignment_vote_db_queries():
"""
Tests that only 1 query is done when fetching AssignmentVotes
"""
create_assignment_polls()
assert count_queries(AssignmentVote.get_elements)() == 1
@pytest.mark.django_db(transaction=False)
def test_assignment_option_db_queries():
"""
Tests that only the following db queries are done:
* 1 request to get the options,
* 1 request to get all votes for all options,
= 2 queries
"""
create_assignment_polls()
assert count_queries(AssignmentOption.get_elements)() == 2
def create_assignment_polls():
"""
Creates 1 assignment with 3 candidates which has 5 polls in which each candidate got a random amount of votes between 0 and 10 from 3 users
"""
assignment = Assignment(title="test_assignment_ohneivoh9caiB8Yiungo", open_posts=1)
assignment.save(skip_autoupdate=True)
group1 = get_group_model().objects.get(pk=1)
group2 = get_group_model().objects.get(pk=2)
for i in range(3):
user = get_user_model().objects.create_user(
username=f"test_username_{i}", password="test_password_UOrnlCZMD0lmxFGwEj54"
)
assignment.add_candidate(user)
for i in range(5):
poll = AssignmentPoll(
assignment=assignment,
title="test_title_UnMiGzEHmwqplmVBPNEZ",
pollmethod=AssignmentPoll.POLLMETHOD_YN,
type=AssignmentPoll.TYPE_NAMED,
)
poll.save(skip_autoupdate=True)
poll.create_options(skip_autoupdate=True)
poll.groups.add(group1)
poll.groups.add(group2)
for j in range(3):
user = get_user_model().objects.create_user(
username=f"test_username_{i}{j}",
password="test_password_kbzj5L8ZtVxBllZzoW6D",
)
poll.voted.add(user)
for option in poll.options.all():
weight = random.randint(0, 10)
if weight > 0:
AssignmentVote.objects.create(
user=user, option=option, value="Y", weight=Decimal(weight)
)
class CreateAssignmentPoll(TestCase):
def advancedSetUp(self):
self.assignment = Assignment.objects.create(
title="test_assignment_ohneivoh9caiB8Yiungo", open_posts=1,
)
self.assignment.add_candidate(self.admin)
def test_simple(self):
with self.assertNumQueries(40):
response = self.client.post(
reverse("assignmentpoll-list"),
{
"title": "test_title_ailai4toogh3eefaa2Vo",
"pollmethod": AssignmentPoll.POLLMETHOD_YNA,
"type": "named",
"assignment_id": self.assignment.id,
"onehundred_percent_base": AssignmentPoll.PERCENT_BASE_YN,
"majority_method": AssignmentPoll.MAJORITY_SIMPLE,
},
)
self.assertHttpStatusVerbose(response, status.HTTP_201_CREATED)
self.assertTrue(AssignmentPoll.objects.exists())
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.title, "test_title_ailai4toogh3eefaa2Vo")
self.assertEqual(poll.pollmethod, AssignmentPoll.POLLMETHOD_YNA)
self.assertEqual(poll.type, "named")
# Check defaults
self.assertTrue(poll.global_no)
self.assertTrue(poll.global_abstain)
self.assertEqual(poll.amount_global_no, None)
self.assertEqual(poll.amount_global_abstain, None)
self.assertFalse(poll.allow_multiple_votes_per_candidate)
self.assertEqual(poll.votes_amount, 1)
self.assertEqual(poll.assignment.id, self.assignment.id)
self.assertEqual(poll.description, "")
self.assertTrue(poll.options.exists())
option = AssignmentOption.objects.get()
self.assertTrue(option.user.id, self.admin.id)
def test_all_fields(self):
response = self.client.post(
reverse("assignmentpoll-list"),
{
"title": "test_title_ahThai4pae1pi4xoogoo",
"pollmethod": AssignmentPoll.POLLMETHOD_YN,
"type": "pseudoanonymous",
"assignment_id": self.assignment.id,
"onehundred_percent_base": AssignmentPoll.PERCENT_BASE_YNA,
"majority_method": AssignmentPoll.MAJORITY_THREE_QUARTERS,
"global_no": False,
"global_abstain": False,
"allow_multiple_votes_per_candidate": True,
"votes_amount": 5,
"description": "test_description_ieM8ThuasoSh8aecai8p",
},
)
self.assertHttpStatusVerbose(response, status.HTTP_201_CREATED)
self.assertTrue(AssignmentPoll.objects.exists())
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.title, "test_title_ahThai4pae1pi4xoogoo")
self.assertEqual(poll.pollmethod, AssignmentPoll.POLLMETHOD_YN)
self.assertEqual(poll.type, "pseudoanonymous")
self.assertFalse(poll.global_no)
self.assertFalse(poll.global_abstain)
self.assertTrue(poll.allow_multiple_votes_per_candidate)
self.assertEqual(poll.votes_amount, 5)
self.assertEqual(poll.description, "test_description_ieM8ThuasoSh8aecai8p")
def test_no_candidates(self):
self.assignment.remove_candidate(self.admin)
response = self.client.post(
reverse("assignmentpoll-list"),
{
"title": "test_title_eing5eipue5cha2Iefai",
"pollmethod": AssignmentPoll.POLLMETHOD_YNA,
"type": "named",
"assignment_id": self.assignment.id,
"onehundred_percent_base": AssignmentPoll.PERCENT_BASE_YN,
"majority_method": AssignmentPoll.MAJORITY_SIMPLE,
},
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.exists())
def test_missing_keys(self):
complete_request_data = {
"title": "test_title_keugh8Iu9ciyooGaevoh",
"pollmethod": AssignmentPoll.POLLMETHOD_YNA,
"type": "named",
"assignment_id": self.assignment.id,
"onehundred_percent_base": AssignmentPoll.PERCENT_BASE_YN,
"majority_method": AssignmentPoll.MAJORITY_SIMPLE,
}
for key in complete_request_data.keys():
request_data = {
_key: value
for _key, value in complete_request_data.items()
if _key != key
}
response = self.client.post(reverse("assignmentpoll-list"), request_data)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.exists())
def test_with_groups(self):
group1 = get_group_model().objects.get(pk=1)
group2 = get_group_model().objects.get(pk=2)
response = self.client.post(
reverse("assignmentpoll-list"),
{
"title": "test_title_Thoo2eiphohhi1eeXoow",
"pollmethod": AssignmentPoll.POLLMETHOD_YNA,
"type": "named",
"assignment_id": self.assignment.id,
"onehundred_percent_base": AssignmentPoll.PERCENT_BASE_YN,
"majority_method": AssignmentPoll.MAJORITY_SIMPLE,
"groups_id": [1, 2],
},
)
self.assertHttpStatusVerbose(response, status.HTTP_201_CREATED)
poll = AssignmentPoll.objects.get()
self.assertTrue(group1 in poll.groups.all())
self.assertTrue(group2 in poll.groups.all())
def test_with_empty_groups(self):
response = self.client.post(
reverse("assignmentpoll-list"),
{
"title": "test_title_Thoo2eiphohhi1eeXoow",
"pollmethod": AssignmentPoll.POLLMETHOD_YNA,
"type": "named",
"assignment_id": self.assignment.id,
"onehundred_percent_base": AssignmentPoll.PERCENT_BASE_YN,
"majority_method": AssignmentPoll.MAJORITY_SIMPLE,
"groups_id": [],
},
)
self.assertHttpStatusVerbose(response, status.HTTP_201_CREATED)
poll = AssignmentPoll.objects.get()
self.assertFalse(poll.groups.exists())
def test_not_supported_type(self):
response = self.client.post(
reverse("assignmentpoll-list"),
{
"title": "test_title_yaiyeighoh0Iraet3Ahc",
"pollmethod": AssignmentPoll.POLLMETHOD_YNA,
"type": "not_existing",
"assignment_id": self.assignment.id,
"onehundred_percent_base": AssignmentPoll.PERCENT_BASE_YN,
"majority_method": AssignmentPoll.MAJORITY_SIMPLE,
},
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.exists())
def test_not_allowed_type(self):
setattr(settings, "ENABLE_ELECTRONIC_VOTING", False)
response = self.client.post(
reverse("assignmentpoll-list"),
{
"title": "test_title_yaiyeighoh0Iraet3Ahc",
"pollmethod": AssignmentPoll.POLLMETHOD_YNA,
"type": AssignmentPoll.TYPE_NAMED,
"assignment_id": self.assignment.id,
"onehundred_percent_base": AssignmentPoll.PERCENT_BASE_YN,
"majority_method": AssignmentPoll.MAJORITY_SIMPLE,
},
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.exists())
setattr(settings, "ENABLE_ELECTRONIC_VOTING", True)
def test_not_supported_pollmethod(self):
response = self.client.post(
reverse("assignmentpoll-list"),
{
"title": "test_title_SeVaiteYeiNgie5Xoov8",
"pollmethod": "not_existing",
"type": "named",
"assignment_id": self.assignment.id,
"onehundred_percent_base": AssignmentPoll.PERCENT_BASE_YN,
"majority_method": AssignmentPoll.MAJORITY_SIMPLE,
},
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.exists())
def test_not_supported_onehundred_percent_base(self):
response = self.client.post(
reverse("assignmentpoll-list"),
{
"title": "test_title_Thoo2eiphohhi1eeXoow",
"pollmethod": AssignmentPoll.POLLMETHOD_YNA,
"type": "named",
"assignment_id": self.assignment.id,
"onehundred_percent_base": "invalid base",
"majority_method": AssignmentPoll.MAJORITY_SIMPLE,
},
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.exists())
def test_not_supported_majority_method(self):
response = self.client.post(
reverse("assignmentpoll-list"),
{
"title": "test_title_Thoo2eiphohhi1eeXoow",
"pollmethod": AssignmentPoll.POLLMETHOD_YNA,
"type": "named",
"assignment_id": self.assignment.id,
"onehundred_percent_base": AssignmentPoll.PERCENT_BASE_YN,
"majority_method": "invalid majority method",
},
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.exists())
def test_wrong_pollmethod_onehundred_percent_base_combination_1(self):
response = self.client.post(
reverse("assignmentpoll-list"),
{
"title": "test_title_Thoo2eiphohhi1eeXoow",
"pollmethod": AssignmentPoll.POLLMETHOD_YNA,
"type": "named",
"assignment_id": self.assignment.id,
"onehundred_percent_base": AssignmentPoll.PERCENT_BASE_VOTES,
"majority_method": AssignmentPoll.MAJORITY_SIMPLE,
},
)
self.assertHttpStatusVerbose(response, status.HTTP_201_CREATED)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.onehundred_percent_base, AssignmentPoll.PERCENT_BASE_YNA)
def test_wrong_pollmethod_onehundred_percent_base_combination_2(self):
response = self.client.post(
reverse("assignmentpoll-list"),
{
"title": "test_title_Thoo2eiphohhi1eeXoow",
"pollmethod": AssignmentPoll.POLLMETHOD_YN,
"type": "named",
"assignment_id": self.assignment.id,
"onehundred_percent_base": AssignmentPoll.PERCENT_BASE_VOTES,
"majority_method": AssignmentPoll.MAJORITY_SIMPLE,
},
)
self.assertHttpStatusVerbose(response, status.HTTP_201_CREATED)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.onehundred_percent_base, AssignmentPoll.PERCENT_BASE_YN)
def test_wrong_pollmethod_onehundred_percent_base_combination_3(self):
response = self.client.post(
reverse("assignmentpoll-list"),
{
"title": "test_title_Thoo2eiphohhi1eeXoow",
"pollmethod": AssignmentPoll.POLLMETHOD_VOTES,
"type": "named",
"assignment_id": self.assignment.id,
"onehundred_percent_base": AssignmentPoll.PERCENT_BASE_YNA,
"majority_method": AssignmentPoll.MAJORITY_SIMPLE,
},
)
self.assertHttpStatusVerbose(response, status.HTTP_201_CREATED)
poll = AssignmentPoll.objects.get()
self.assertEqual(
poll.onehundred_percent_base, AssignmentPoll.PERCENT_BASE_VOTES
)
def test_create_with_votes(self):
response = self.client.post(
reverse("assignmentpoll-list"),
{
"title": "test_title_dKbv5tV47IzY1oGHXdSz",
"pollmethod": AssignmentPoll.POLLMETHOD_VOTES,
"type": AssignmentPoll.TYPE_ANALOG,
"assignment_id": self.assignment.id,
"onehundred_percent_base": AssignmentPoll.PERCENT_BASE_YNA,
"majority_method": AssignmentPoll.MAJORITY_SIMPLE,
"votes": {
"options": {"1": {"Y": 1}},
"votesvalid": "-2",
"votesinvalid": "-2",
"votescast": "-2",
},
},
)
self.assertHttpStatusVerbose(response, status.HTTP_201_CREATED)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.state, AssignmentPoll.STATE_FINISHED)
self.assertTrue(AssignmentVote.objects.exists())
def test_create_with_votes2(self):
user, _ = self.create_user()
self.assignment.add_candidate(user)
self.assignment.remove_candidate(self.admin)
response = self.client.post(
reverse("assignmentpoll-list"),
{
"title": "test_title_dKbv5tV47IzY1oGHXdSz",
"pollmethod": AssignmentPoll.POLLMETHOD_VOTES,
"type": AssignmentPoll.TYPE_ANALOG,
"assignment_id": self.assignment.id,
"onehundred_percent_base": AssignmentPoll.PERCENT_BASE_YNA,
"majority_method": AssignmentPoll.MAJORITY_SIMPLE,
"votes": {
"options": {"2": {"Y": 1}},
"votesvalid": "-2",
"votesinvalid": "-2",
"votescast": "-2",
},
},
)
self.assertHttpStatusVerbose(response, status.HTTP_201_CREATED)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.state, AssignmentPoll.STATE_FINISHED)
self.assertTrue(AssignmentVote.objects.exists())
def test_create_with_votes_publish_immediately(self):
response = self.client.post(
reverse("assignmentpoll-list"),
{
"title": "test_title_dKbv5tV47IzY1oGHXdSz",
"pollmethod": AssignmentPoll.POLLMETHOD_VOTES,
"type": AssignmentPoll.TYPE_ANALOG,
"assignment_id": self.assignment.id,
"onehundred_percent_base": AssignmentPoll.PERCENT_BASE_YNA,
"majority_method": AssignmentPoll.MAJORITY_SIMPLE,
"votes": {
"options": {"1": {"Y": 1}},
"votesvalid": "-2",
"votesinvalid": "-2",
"votescast": "-2",
},
"publish_immediately": "1",
},
)
self.assertHttpStatusVerbose(response, status.HTTP_201_CREATED)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.state, AssignmentPoll.STATE_PUBLISHED)
self.assertTrue(AssignmentVote.objects.exists())
def test_create_with_invalid_votes(self):
response = self.client.post(
reverse("assignmentpoll-list"),
{
"title": "test_title_dKbv5tV47IzY1oGHXdSz",
"pollmethod": AssignmentPoll.POLLMETHOD_VOTES,
"type": AssignmentPoll.TYPE_ANALOG,
"assignment_id": self.assignment.id,
"onehundred_percent_base": AssignmentPoll.PERCENT_BASE_YNA,
"majority_method": AssignmentPoll.MAJORITY_SIMPLE,
"votes": {
"options": {"1": {"Y": 1}},
"votesvalid": "-2",
"votesinvalid": "-2",
},
},
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.exists())
self.assertFalse(AssignmentVote.objects.exists())
def test_create_with_votes_wrong_type(self):
response = self.client.post(
reverse("assignmentpoll-list"),
{
"title": "test_title_dKbv5tV47IzY1oGHXdSz",
"pollmethod": AssignmentPoll.POLLMETHOD_VOTES,
"type": AssignmentPoll.TYPE_NAMED,
"assignment_id": self.assignment.id,
"onehundred_percent_base": AssignmentPoll.PERCENT_BASE_YNA,
"majority_method": AssignmentPoll.MAJORITY_SIMPLE,
"votes": {
"options": {"1": {"Y": 1}},
"votesvalid": "-2",
"votesinvalid": "-2",
"votescast": "-2",
},
},
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.exists())
self.assertFalse(AssignmentVote.objects.exists())
class UpdateAssignmentPoll(TestCase):
"""
Tests updating polls of assignments.
"""
def advancedSetUp(self):
self.assignment = Assignment.objects.create(
title="test_assignment_ohneivoh9caiB8Yiungo", open_posts=1
)
self.assignment.add_candidate(self.admin)
self.group = get_group_model().objects.get(pk=1)
self.poll = AssignmentPoll.objects.create(
assignment=self.assignment,
title="test_title_beeFaihuNae1vej2ai8m",
pollmethod=AssignmentPoll.POLLMETHOD_VOTES,
type=BasePoll.TYPE_NAMED,
onehundred_percent_base=AssignmentPoll.PERCENT_BASE_VOTES,
majority_method=AssignmentPoll.MAJORITY_SIMPLE,
)
self.poll.create_options()
self.poll.groups.add(self.group)
def test_patch_title(self):
response = self.client.patch(
reverse("assignmentpoll-detail", args=[self.poll.pk]),
{"title": "test_title_Aishohh1ohd0aiSut7gi"},
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.title, "test_title_Aishohh1ohd0aiSut7gi")
def test_prevent_patching_assignment(self):
assignment = Assignment(title="test_title_phohdah8quukooHeetuz", open_posts=1)
assignment.save()
response = self.client.patch(
reverse("assignmentpoll-detail", args=[self.poll.pk]),
{"assignment_id": assignment.id},
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.assignment.id, self.assignment.id) # unchanged
def test_patch_pollmethod(self):
response = self.client.patch(
reverse("assignmentpoll-detail", args=[self.poll.pk]),
{"pollmethod": AssignmentPoll.POLLMETHOD_YNA},
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.pollmethod, AssignmentPoll.POLLMETHOD_YNA)
self.assertEqual(poll.onehundred_percent_base, AssignmentPoll.PERCENT_BASE_YNA)
def test_patch_invalid_pollmethod(self):
response = self.client.patch(
reverse("assignmentpoll-detail", args=[self.poll.pk]),
{"pollmethod": "invalid"},
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.pollmethod, AssignmentPoll.POLLMETHOD_VOTES)
def test_patch_type(self):
response = self.client.patch(
reverse("assignmentpoll-detail", args=[self.poll.pk]), {"type": "analog"}
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.type, "analog")
def test_patch_invalid_type(self):
response = self.client.patch(
reverse("assignmentpoll-detail", args=[self.poll.pk]), {"type": "invalid"}
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.type, "named")
def test_patch_not_allowed_type(self):
setattr(settings, "ENABLE_ELECTRONIC_VOTING", False)
response = self.client.patch(
reverse("assignmentpoll-detail", args=[self.poll.pk]),
{"type": BasePoll.TYPE_NAMED},
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.type, BasePoll.TYPE_NAMED)
setattr(settings, "ENABLE_ELECTRONIC_VOTING", True)
def test_patch_groups_to_empty(self):
response = self.client.patch(
reverse("assignmentpoll-detail", args=[self.poll.pk]), {"groups_id": []},
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
poll = AssignmentPoll.objects.get()
self.assertFalse(poll.groups.exists())
def test_patch_groups(self):
group2 = get_group_model().objects.get(pk=2)
response = self.client.patch(
reverse("assignmentpoll-detail", args=[self.poll.pk]),
{"groups_id": [group2.id]},
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.groups.count(), 1)
self.assertEqual(poll.groups.get(), group2)
def test_patch_title_started(self):
self.poll.state = 2
self.poll.save()
response = self.client.patch(
reverse("assignmentpoll-detail", args=[self.poll.pk]),
{"title": "test_title_Oophah8EaLaequu3toh8"},
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.title, "test_title_Oophah8EaLaequu3toh8")
def test_patch_wrong_state(self):
self.poll.state = 2
self.poll.save()
response = self.client.patch(
reverse("assignmentpoll-detail", args=[self.poll.pk]),
{"type": BasePoll.TYPE_NAMED},
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.type, BasePoll.TYPE_NAMED)
def test_patch_100_percent_base(self):
response = self.client.patch(
reverse("assignmentpoll-detail", args=[self.poll.pk]),
{"onehundred_percent_base": "cast"},
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.onehundred_percent_base, "cast")
def test_patch_wrong_100_percent_base(self):
response = self.client.patch(
reverse("assignmentpoll-detail", args=[self.poll.pk]),
{"onehundred_percent_base": "invalid"},
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
poll = AssignmentPoll.objects.get()
self.assertEqual(
poll.onehundred_percent_base, AssignmentPoll.PERCENT_BASE_VOTES
)
def test_patch_majority_method(self):
response = self.client.patch(
reverse("assignmentpoll-detail", args=[self.poll.pk]),
{"majority_method": AssignmentPoll.MAJORITY_TWO_THIRDS},
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.majority_method, AssignmentPoll.MAJORITY_TWO_THIRDS)
def test_patch_wrong_majority_method(self):
response = self.client.patch(
reverse("assignmentpoll-detail", args=[self.poll.pk]),
{"majority_method": "invalid majority method"},
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.majority_method, AssignmentPoll.MAJORITY_SIMPLE)
def test_patch_multiple_fields(self):
response = self.client.patch(
reverse("assignmentpoll-detail", args=[self.poll.pk]),
{
"title": "test_title_ees6Tho8ahheen4cieja",
"pollmethod": AssignmentPoll.POLLMETHOD_VOTES,
"global_no": True,
"global_abstain": False,
"allow_multiple_votes_per_candidate": True,
"votes_amount": 42,
},
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.title, "test_title_ees6Tho8ahheen4cieja")
self.assertEqual(poll.pollmethod, AssignmentPoll.POLLMETHOD_VOTES)
self.assertTrue(poll.global_no)
self.assertFalse(poll.global_abstain)
self.assertEqual(poll.amount_global_no, Decimal("0"))
self.assertEqual(poll.amount_global_abstain, None)
self.assertTrue(poll.allow_multiple_votes_per_candidate)
self.assertEqual(poll.votes_amount, 42)
def test_patch_majority_method_state_not_created(self):
self.poll.state = 2
self.poll.save()
response = self.client.patch(
reverse("assignmentpoll-detail", args=[self.poll.pk]),
{"majority_method": "two_thirds"},
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.majority_method, "two_thirds")
def test_patch_100_percent_base_state_not_created(self):
self.poll.state = 2
self.poll.save()
response = self.client.patch(
reverse("assignmentpoll-detail", args=[self.poll.pk]),
{"onehundred_percent_base": "cast"},
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.onehundred_percent_base, "cast")
def test_patch_wrong_100_percent_base_state_not_created(self):
self.poll.state = 2
self.poll.pollmethod = AssignmentPoll.POLLMETHOD_YN
self.poll.save()
response = self.client.patch(
reverse("assignmentpoll-detail", args=[self.poll.pk]),
{"onehundred_percent_base": AssignmentPoll.PERCENT_BASE_YNA},
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.onehundred_percent_base, "YN")
class VoteAssignmentPollBaseTestClass(TestCase):
def advancedSetUp(self):
self.assignment = Assignment.objects.create(
title="test_assignment_tcLT59bmXrXif424Qw7K", open_posts=1
)
self.assignment.add_candidate(self.admin)
self.poll = self.create_poll()
self.admin.is_present = True
self.admin.save()
self.poll.groups.add(GROUP_ADMIN_PK)
self.poll.create_options()
inform_changed_data(self.poll)
def create_poll(self):
# has to be implemented by subclasses
raise NotImplementedError()
def start_poll(self):
self.poll.state = AssignmentPoll.STATE_STARTED
self.poll.save()
def add_candidate(self):
user, _ = self.create_user()
AssignmentOption.objects.create(user=user, poll=self.poll)
class VoteAssignmentPollAnalogYNA(VoteAssignmentPollBaseTestClass):
def create_poll(self):
return AssignmentPoll.objects.create(
assignment=self.assignment,
title="test_title_04k0y4TwPLpJKaSvIGm1",
pollmethod=AssignmentPoll.POLLMETHOD_YNA,
type=BasePoll.TYPE_ANALOG,
)
def test_start_poll(self):
response = self.client.post(
reverse("assignmentpoll-start", args=[self.poll.pk])
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.state, AssignmentPoll.STATE_STARTED)
self.assertEqual(poll.votesvalid, None)
self.assertEqual(poll.votesinvalid, None)
self.assertEqual(poll.votescast, None)
self.assertFalse(poll.get_votes().exists())
def test_stop_poll(self):
self.start_poll()
response = self.client.post(reverse("assignmentpoll-stop", args=[self.poll.pk]))
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertEqual(self.poll.state, AssignmentPoll.STATE_STARTED)
def test_vote(self):
self.add_candidate()
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{
"options": {
"1": {"Y": "1", "N": "2.35", "A": "-1"},
"2": {"Y": "30", "N": "-2", "A": "8.93"},
},
"votesvalid": "4.64",
"votesinvalid": "-2",
"votescast": "-2",
},
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
self.assertEqual(AssignmentVote.objects.count(), 6)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.votesvalid, Decimal("4.64"))
self.assertEqual(poll.votesinvalid, Decimal("-2"))
self.assertEqual(poll.votescast, Decimal("-2"))
self.assertEqual(poll.state, AssignmentPoll.STATE_FINISHED)
option1 = poll.options.get(pk=1)
option2 = poll.options.get(pk=2)
self.assertEqual(option1.yes, Decimal("1"))
self.assertEqual(option1.no, Decimal("2.35"))
self.assertEqual(option1.abstain, Decimal("-1"))
self.assertEqual(option2.yes, Decimal("30"))
self.assertEqual(option2.no, Decimal("-2"))
self.assertEqual(option2.abstain, Decimal("8.93"))
def test_vote_fractional_negative_values(self):
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{
"options": {"1": {"Y": "1", "N": "1", "A": "1"}},
"votesvalid": "-1.5",
"votesinvalid": "-2",
"votescast": "-2",
},
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.get().get_votes().exists())
def test_too_many_options(self):
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{
"options": {
"1": {"Y": "1", "N": "2.35", "A": "-1"},
"2": {"Y": "1", "N": "2.35", "A": "-1"},
}
},
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.get().get_votes().exists())
def test_too_few_options(self):
self.add_candidate()
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"options": {"1": {"Y": "1", "N": "2.35", "A": "-1"}}},
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.get().get_votes().exists())
def test_wrong_options(self):
self.add_candidate()
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{
"options": {
"1": {"Y": "1", "N": "2.35", "A": "-1"},
"3": {"Y": "1", "N": "2.35", "A": "-1"},
}
},
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.get().get_votes().exists())
def test_no_permissions(self):
self.start_poll()
self.make_admin_delegate()
response = self.client.post(reverse("assignmentpoll-vote", args=[self.poll.pk]))
self.assertHttpStatusVerbose(response, status.HTTP_403_FORBIDDEN)
self.assertFalse(AssignmentVote.objects.exists())
def test_wrong_state(self):
response = self.client.post(reverse("assignmentpoll-vote", args=[self.poll.pk]))
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentVote.objects.exists())
def test_missing_data(self):
self.start_poll()
response = self.client.post(reverse("assignmentpoll-vote", args=[self.poll.pk]))
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentVote.objects.exists())
def test_wrong_data_format(self):
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]), [1, 2, 5],
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentVote.objects.exists())
def test_wrong_option_format(self):
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"options": [1, "string"]},
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.get().get_votes().exists())
def test_wrong_option_id_type(self):
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"options": {"string": "some_other_string"}},
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentVote.objects.exists())
def test_wrong_vote_data(self):
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"options": {"1": [None]}},
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentVote.objects.exists())
def test_missing_vote_value(self):
self.start_poll()
for value in "YNA":
data = {"options": {"1": {"Y": "1", "N": "3", "A": "-1"}}}
del data["options"]["1"][value]
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]), data
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentVote.objects.exists())
def test_vote_state_finished(self):
self.start_poll()
self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{
"options": {"1": {"Y": 5, "N": 0, "A": 1}},
"votesvalid": "-2",
"votesinvalid": "1",
"votescast": "-1",
},
)
self.poll.state = 3
self.poll.save()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{
"options": {"1": {"Y": 2, "N": 2, "A": 2}},
"votesvalid": "4.64",
"votesinvalid": "-2",
"votescast": "3",
},
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.votesvalid, Decimal("4.64"))
self.assertEqual(poll.votesinvalid, Decimal("-2"))
self.assertEqual(poll.votescast, Decimal("3"))
self.assertEqual(poll.get_votes().count(), 3)
option = poll.options.get()
self.assertEqual(option.yes, Decimal("2"))
self.assertEqual(option.no, Decimal("2"))
self.assertEqual(option.abstain, Decimal("2"))
class VoteAssignmentPollNamedYNA(VoteAssignmentPollBaseTestClass):
def create_poll(self):
return AssignmentPoll.objects.create(
assignment=self.assignment,
title="test_title_OkHAIvOSIcpFnCxbaL6v",
pollmethod=AssignmentPoll.POLLMETHOD_YNA,
type=BasePoll.TYPE_NAMED,
)
def test_start_poll(self):
response = self.client.post(
reverse("assignmentpoll-start", args=[self.poll.pk])
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.state, AssignmentPoll.STATE_STARTED)
self.assertEqual(poll.votesvalid, Decimal("0"))
self.assertEqual(poll.votesinvalid, Decimal("0"))
self.assertEqual(poll.votescast, Decimal("0"))
self.assertFalse(poll.get_votes().exists())
def test_vote(self):
self.add_candidate()
self.add_candidate()
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": "Y", "2": "N", "3": "A"},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
self.assertEqual(AssignmentVote.objects.count(), 3)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.votesvalid, Decimal("1"))
self.assertEqual(poll.votesinvalid, Decimal("0"))
self.assertEqual(poll.votescast, Decimal("1"))
self.assertEqual(poll.state, AssignmentPoll.STATE_STARTED)
self.assertEqual(poll.amount_users_voted_with_individual_weight(), Decimal("1"))
option1 = poll.options.get(pk=1)
option2 = poll.options.get(pk=2)
option3 = poll.options.get(pk=3)
self.assertEqual(option1.yes, Decimal("1"))
self.assertEqual(option1.no, Decimal("0"))
self.assertEqual(option1.abstain, Decimal("0"))
self.assertEqual(option2.yes, Decimal("0"))
self.assertEqual(option2.no, Decimal("1"))
self.assertEqual(option2.abstain, Decimal("0"))
self.assertEqual(option3.yes, Decimal("0"))
self.assertEqual(option3.no, Decimal("0"))
self.assertEqual(option3.abstain, Decimal("1"))
def test_vote_with_voteweight(self):
config["users_activate_vote_weight"] = True
self.admin.vote_weight = weight = Decimal("4.2")
self.admin.save()
self.add_candidate()
self.add_candidate()
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": "Y", "2": "N", "3": "A"},
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
self.assertEqual(AssignmentVote.objects.count(), 3)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.votesvalid, weight)
self.assertEqual(poll.votesinvalid, Decimal("0"))
self.assertEqual(poll.votescast, weight)
self.assertEqual(poll.state, AssignmentPoll.STATE_STARTED)
self.assertEqual(poll.amount_users_voted_with_individual_weight(), weight)
option1 = poll.options.get(pk=1)
option2 = poll.options.get(pk=2)
option3 = poll.options.get(pk=3)
self.assertEqual(option1.yes, weight)
self.assertEqual(option1.no, Decimal("0"))
self.assertEqual(option1.abstain, Decimal("0"))
self.assertEqual(option2.yes, Decimal("0"))
self.assertEqual(option2.no, weight)
self.assertEqual(option2.abstain, Decimal("0"))
self.assertEqual(option3.yes, Decimal("0"))
self.assertEqual(option3.no, Decimal("0"))
self.assertEqual(option3.abstain, weight)
def test_vote_without_voteweight(self):
self.admin.vote_weight = Decimal("4.2")
self.admin.save()
self.test_vote()
def test_change_vote(self):
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": "Y"},
format="json",
)
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": "N"},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertEqual(AssignmentVote.objects.count(), 1)
vote = AssignmentVote.objects.get()
self.assertEqual(vote.value, "Y")
def test_too_many_options(self):
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": "Y", "2": "N"},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.get().get_votes().exists())
def test_partial_vote(self):
self.add_candidate()
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": "Y"},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
self.assertTrue(AssignmentPoll.objects.get().get_votes().exists())
def test_wrong_options(self):
self.add_candidate()
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": "Y", "3": "N"},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.get().get_votes().exists())
def test_no_permissions(self):
self.start_poll()
self.make_admin_delegate()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": "Y"},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_403_FORBIDDEN)
self.assertFalse(AssignmentVote.objects.exists())
def test_anonymous(self):
self.start_poll()
gclient = self.create_guest_client()
response = gclient.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": "Y"},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_403_FORBIDDEN)
self.assertFalse(AssignmentVote.objects.exists())
def test_vote_not_present(self):
self.start_poll()
self.admin.is_present = False
self.admin.save()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": "Y"},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_403_FORBIDDEN)
self.assertFalse(AssignmentPoll.objects.get().get_votes().exists())
def test_wrong_state(self):
response = self.client.post(reverse("assignmentpoll-vote", args=[self.poll.pk]))
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentVote.objects.exists())
def test_missing_data(self):
self.start_poll()
response = self.client.post(reverse("assignmentpoll-vote", args=[self.poll.pk]))
self.assertHttpStatusVerbose(
response, status.HTTP_200_OK
) # new "feature" because of partial requests: empty requests work!
self.assertFalse(AssignmentVote.objects.exists())
def test_wrong_data_format(self):
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
[1, 2, 5],
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentVote.objects.exists())
def test_wrong_option_format(self):
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": "string"},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.get().get_votes().exists())
def test_wrong_option_id_type(self):
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"id": "Y"},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentVote.objects.exists())
def test_wrong_vote_data(self):
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": [None]},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentVote.objects.exists())
class VoteAssignmentPollNamedVotes(VoteAssignmentPollBaseTestClass):
def create_poll(self):
return AssignmentPoll.objects.create(
assignment=self.assignment,
title="test_title_Zrvh146QAdq7t6iSDwZk",
pollmethod=AssignmentPoll.POLLMETHOD_VOTES,
type=BasePoll.TYPE_NAMED,
)
def setup_for_multiple_votes(self):
self.poll.allow_multiple_votes_per_candidate = True
self.poll.votes_amount = 3
self.poll.save()
self.add_candidate()
def test_start_poll(self):
response = self.client.post(
reverse("assignmentpoll-start", args=[self.poll.pk])
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.state, AssignmentPoll.STATE_STARTED)
self.assertEqual(poll.votesvalid, Decimal("0"))
self.assertEqual(poll.votesinvalid, Decimal("0"))
self.assertEqual(poll.votescast, Decimal("0"))
self.assertFalse(poll.get_votes().exists())
def test_vote(self):
self.add_candidate()
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": 1, "2": 0},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
self.assertEqual(AssignmentVote.objects.count(), 1)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.votesvalid, Decimal("1"))
self.assertEqual(poll.votesinvalid, Decimal("0"))
self.assertEqual(poll.votescast, Decimal("1"))
self.assertEqual(poll.state, AssignmentPoll.STATE_STARTED)
option1 = poll.options.get(pk=1)
option2 = poll.options.get(pk=2)
self.assertEqual(option1.yes, Decimal("1"))
self.assertEqual(option1.no, Decimal("0"))
self.assertEqual(option1.abstain, Decimal("0"))
self.assertEqual(option2.yes, Decimal("0"))
self.assertEqual(option2.no, Decimal("0"))
self.assertEqual(option2.abstain, Decimal("0"))
def test_change_vote(self):
self.add_candidate()
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": 1, "2": 0},
format="json",
)
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": 0, "2": 1},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
poll = AssignmentPoll.objects.get()
option1 = poll.options.get(pk=1)
option2 = poll.options.get(pk=2)
self.assertEqual(option1.yes, Decimal("1"))
self.assertEqual(option1.no, Decimal("0"))
self.assertEqual(option1.abstain, Decimal("0"))
self.assertEqual(option2.yes, Decimal("0"))
self.assertEqual(option2.no, Decimal("0"))
self.assertEqual(option2.abstain, Decimal("0"))
def test_global_no(self):
self.poll.votes_amount = 2
self.poll.save()
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]), "N"
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
poll = AssignmentPoll.objects.get()
option = poll.options.get(pk=1)
self.assertEqual(option.yes, Decimal("0"))
self.assertEqual(option.no, Decimal("1"))
self.assertEqual(option.abstain, Decimal("0"))
self.assertEqual(poll.amount_global_no, Decimal("1"))
self.assertEqual(poll.amount_global_abstain, Decimal("0"))
def test_global_no_forbidden(self):
self.poll.global_no = False
self.poll.save()
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]), "N"
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.get().get_votes().exists())
self.assertEqual(AssignmentPoll.objects.get().amount_global_no, None)
def test_global_abstain(self):
self.poll.votes_amount = 2
self.poll.save()
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]), "A"
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
poll = AssignmentPoll.objects.get()
option = poll.options.get(pk=1)
self.assertEqual(option.yes, Decimal("0"))
self.assertEqual(option.no, Decimal("0"))
self.assertEqual(option.abstain, Decimal("1"))
self.assertEqual(poll.amount_global_no, Decimal("0"))
self.assertEqual(poll.amount_global_abstain, Decimal("1"))
def test_global_abstain_forbidden(self):
self.poll.global_abstain = False
self.poll.save()
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]), "A"
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.get().get_votes().exists())
self.assertEqual(AssignmentPoll.objects.get().amount_global_abstain, None)
def test_negative_vote(self):
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": -1},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.get().get_votes().exists())
def test_multiple_votes(self):
self.setup_for_multiple_votes()
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": 2, "2": 1},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
poll = AssignmentPoll.objects.get()
option1 = poll.options.get(pk=1)
option2 = poll.options.get(pk=2)
self.assertEqual(option1.yes, Decimal("2"))
self.assertEqual(option1.no, Decimal("0"))
self.assertEqual(option1.abstain, Decimal("0"))
self.assertEqual(option2.yes, Decimal("1"))
self.assertEqual(option2.no, Decimal("0"))
self.assertEqual(option2.abstain, Decimal("0"))
def test_multiple_votes_wrong_amount(self):
self.setup_for_multiple_votes()
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": 2, "2": 2},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.get().get_votes().exists())
def test_too_many_options(self):
self.setup_for_multiple_votes()
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": 1, "2": 1, "3": 1},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.get().get_votes().exists())
def test_wrong_options(self):
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]), {"2": 1}, format="json"
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.get().get_votes().exists())
def test_no_permissions(self):
self.start_poll()
self.make_admin_delegate()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]), {"1": 1}, format="json"
)
self.assertHttpStatusVerbose(response, status.HTTP_403_FORBIDDEN)
self.assertFalse(AssignmentVote.objects.exists())
def test_anonymous(self):
self.start_poll()
gclient = self.create_guest_client()
response = gclient.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]), {"1": 1}, format="json"
)
self.assertHttpStatusVerbose(response, status.HTTP_403_FORBIDDEN)
self.assertFalse(AssignmentVote.objects.exists())
def test_vote_not_present(self):
self.start_poll()
self.admin.is_present = False
self.admin.save()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]), {"1": 1}, format="json"
)
self.assertHttpStatusVerbose(response, status.HTTP_403_FORBIDDEN)
self.assertFalse(AssignmentPoll.objects.get().get_votes().exists())
def test_wrong_state(self):
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]), {"1": 1}, format="json"
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentVote.objects.exists())
def test_missing_data(self):
self.start_poll()
response = self.client.post(reverse("assignmentpoll-vote", args=[self.poll.pk]))
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
self.assertFalse(AssignmentVote.objects.exists())
def test_wrong_data_format(self):
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
[1, 2, 5],
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentVote.objects.exists())
def test_wrong_option_format(self):
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": "string"},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.get().get_votes().exists())
def test_wrong_option_id_type(self):
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"id": 1},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentVote.objects.exists())
def test_wrong_vote_data(self):
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": [None]},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentVote.objects.exists())
class VoteAssignmentPollPseudoanonymousYNA(VoteAssignmentPollBaseTestClass):
def create_poll(self):
return AssignmentPoll.objects.create(
assignment=self.assignment,
title="test_title_OkHAIvOSIcpFnCxbaL6v",
pollmethod=AssignmentPoll.POLLMETHOD_YNA,
type=BasePoll.TYPE_PSEUDOANONYMOUS,
)
def test_start_poll(self):
response = self.client.post(
reverse("assignmentpoll-start", args=[self.poll.pk])
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.state, AssignmentPoll.STATE_STARTED)
self.assertEqual(poll.votesvalid, Decimal("0"))
self.assertEqual(poll.votesinvalid, Decimal("0"))
self.assertEqual(poll.votescast, Decimal("0"))
self.assertFalse(poll.get_votes().exists())
def test_vote(self):
self.add_candidate()
self.add_candidate()
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": "Y", "2": "N", "3": "A"},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
self.assertEqual(AssignmentVote.objects.count(), 3)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.votesvalid, Decimal("1"))
self.assertEqual(poll.votesinvalid, Decimal("0"))
self.assertEqual(poll.votescast, Decimal("1"))
self.assertEqual(poll.state, AssignmentPoll.STATE_STARTED)
option1 = poll.options.get(pk=1)
option2 = poll.options.get(pk=2)
option3 = poll.options.get(pk=3)
self.assertEqual(option1.yes, Decimal("1"))
self.assertEqual(option1.no, Decimal("0"))
self.assertEqual(option1.abstain, Decimal("0"))
self.assertEqual(option2.yes, Decimal("0"))
self.assertEqual(option2.no, Decimal("1"))
self.assertEqual(option2.abstain, Decimal("0"))
self.assertEqual(option3.yes, Decimal("0"))
self.assertEqual(option3.no, Decimal("0"))
self.assertEqual(option3.abstain, Decimal("1"))
def test_change_vote(self):
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": "Y"},
format="json",
)
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": "N"},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
poll = AssignmentPoll.objects.get()
option1 = poll.options.get(pk=1)
self.assertEqual(option1.yes, Decimal("1"))
self.assertEqual(option1.no, Decimal("0"))
self.assertEqual(option1.abstain, Decimal("0"))
def test_too_many_options(self):
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": "Y", "2": "N"},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.get().get_votes().exists())
def test_partial_vote(self):
self.add_candidate()
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": "Y"},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
self.assertTrue(AssignmentPoll.objects.get().get_votes().exists())
def test_wrong_options(self):
self.add_candidate()
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": "Y", "3": "N"},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.get().get_votes().exists())
def test_no_permissions(self):
self.start_poll()
self.make_admin_delegate()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": "Y"},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_403_FORBIDDEN)
self.assertFalse(AssignmentVote.objects.exists())
def test_anonymous(self):
self.start_poll()
gclient = self.create_guest_client()
response = gclient.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": "Y"},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_403_FORBIDDEN)
self.assertFalse(AssignmentVote.objects.exists())
def test_vote_not_present(self):
self.start_poll()
self.admin.is_present = False
self.admin.save()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": "Y"},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_403_FORBIDDEN)
self.assertFalse(AssignmentPoll.objects.get().get_votes().exists())
def test_wrong_state(self):
response = self.client.post(reverse("assignmentpoll-vote", args=[self.poll.pk]))
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentVote.objects.exists())
def test_missing_data(self):
self.start_poll()
response = self.client.post(reverse("assignmentpoll-vote", args=[self.poll.pk]))
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
self.assertFalse(AssignmentVote.objects.exists())
def test_wrong_data_format(self):
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
[1, 2, 5],
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentVote.objects.exists())
def test_wrong_option_format(self):
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": "string"},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.get().get_votes().exists())
def test_wrong_option_id_type(self):
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"id": "Y"},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentVote.objects.exists())
def test_wrong_vote_data(self):
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": [None]},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentVote.objects.exists())
class VoteAssignmentPollPseudoanonymousVotes(VoteAssignmentPollBaseTestClass):
def create_poll(self):
return AssignmentPoll.objects.create(
assignment=self.assignment,
title="test_title_Zrvh146QAdq7t6iSDwZk",
pollmethod=AssignmentPoll.POLLMETHOD_VOTES,
type=BasePoll.TYPE_PSEUDOANONYMOUS,
)
def setup_for_multiple_votes(self):
self.poll.allow_multiple_votes_per_candidate = True
self.poll.votes_amount = 3
self.poll.save()
self.add_candidate()
def test_start_poll(self):
response = self.client.post(
reverse("assignmentpoll-start", args=[self.poll.pk])
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.state, AssignmentPoll.STATE_STARTED)
self.assertEqual(poll.votesvalid, Decimal("0"))
self.assertEqual(poll.votesinvalid, Decimal("0"))
self.assertEqual(poll.votescast, Decimal("0"))
self.assertFalse(poll.get_votes().exists())
def test_vote(self):
self.add_candidate()
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": 1, "2": 0},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
self.assertEqual(AssignmentVote.objects.count(), 1)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.votesvalid, Decimal("1"))
self.assertEqual(poll.votesinvalid, Decimal("0"))
self.assertEqual(poll.votescast, Decimal("1"))
self.assertEqual(poll.state, AssignmentPoll.STATE_STARTED)
option1 = poll.options.get(pk=1)
option2 = poll.options.get(pk=2)
self.assertEqual(option1.yes, Decimal("1"))
self.assertEqual(option1.no, Decimal("0"))
self.assertEqual(option1.abstain, Decimal("0"))
self.assertEqual(option2.yes, Decimal("0"))
self.assertEqual(option2.no, Decimal("0"))
self.assertEqual(option2.abstain, Decimal("0"))
def test_change_vote(self):
self.add_candidate()
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": 1, "2": 0},
format="json",
)
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": 0, "2": 1},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
poll = AssignmentPoll.objects.get()
option1 = poll.options.get(pk=1)
option2 = poll.options.get(pk=2)
self.assertEqual(option1.yes, Decimal("1"))
self.assertEqual(option1.no, Decimal("0"))
self.assertEqual(option1.abstain, Decimal("0"))
self.assertEqual(option2.yes, Decimal("0"))
self.assertEqual(option2.no, Decimal("0"))
self.assertEqual(option2.abstain, Decimal("0"))
def test_negative_vote(self):
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": -1},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.get().get_votes().exists())
def test_multiple_votes(self):
self.setup_for_multiple_votes()
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": 2, "2": 1},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
poll = AssignmentPoll.objects.get()
option1 = poll.options.get(pk=1)
option2 = poll.options.get(pk=2)
self.assertEqual(option1.yes, Decimal("2"))
self.assertEqual(option1.no, Decimal("0"))
self.assertEqual(option1.abstain, Decimal("0"))
self.assertEqual(option2.yes, Decimal("1"))
self.assertEqual(option2.no, Decimal("0"))
self.assertEqual(option2.abstain, Decimal("0"))
def test_multiple_votes_wrong_amount(self):
self.setup_for_multiple_votes()
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": 2, "2": 2},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.get().get_votes().exists())
def test_too_many_options(self):
self.setup_for_multiple_votes()
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": 1, "2": 1, "3": 1},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.get().get_votes().exists())
def test_wrong_options(self):
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]), {"2": 1}, format="json"
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.get().get_votes().exists())
def test_no_permissions(self):
self.start_poll()
self.make_admin_delegate()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]), {"1": 1}, format="json"
)
self.assertHttpStatusVerbose(response, status.HTTP_403_FORBIDDEN)
self.assertFalse(AssignmentVote.objects.exists())
def test_anonymous(self):
self.start_poll()
gclient = self.create_guest_client()
response = gclient.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]), {"1": 1}, format="json"
)
self.assertHttpStatusVerbose(response, status.HTTP_403_FORBIDDEN)
self.assertFalse(AssignmentVote.objects.exists())
def test_vote_not_present(self):
self.start_poll()
self.admin.is_present = False
self.admin.save()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]), {"1": 1}, format="json"
)
self.assertHttpStatusVerbose(response, status.HTTP_403_FORBIDDEN)
self.assertFalse(AssignmentPoll.objects.get().get_votes().exists())
def test_wrong_state(self):
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]), {"1": 1}, format="json"
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentVote.objects.exists())
def test_missing_data(self):
self.start_poll()
response = self.client.post(reverse("assignmentpoll-vote", args=[self.poll.pk]))
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
self.assertFalse(AssignmentVote.objects.exists())
def test_wrong_data_format(self):
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
[1, 2, 5],
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentVote.objects.exists())
def test_wrong_option_format(self):
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": "string"},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentPoll.objects.get().get_votes().exists())
def test_wrong_option_id_type(self):
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"id": 1},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentVote.objects.exists())
def test_wrong_vote_data(self):
self.start_poll()
response = self.client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]),
{"1": [None]},
format="json",
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
self.assertFalse(AssignmentVote.objects.exists())
# test autoupdates
class VoteAssignmentPollAutoupdatesBaseClass(TestCase):
poll_type = "" # set by subclass, defines which poll type we use
"""
3 important users:
self.admin: manager, has can_see, can_manage, can_manage_polls (in admin group)
self.user: votes, has can_see perms and in in delegate group
self.other_user: Just has can_see perms and is NOT in the delegate group.
"""
def advancedSetUp(self):
self.delegate_group = get_group_model().objects.get(pk=GROUP_DELEGATE_PK)
self.other_user, _ = self.create_user()
inform_changed_data(self.other_user)
self.user, user_password = self.create_user()
self.user.groups.add(self.delegate_group)
self.user.is_present = True
self.user.save()
self.user_client = APIClient()
self.user_client.login(username=self.user.username, password=user_password)
self.assignment = Assignment.objects.create(
title="test_assignment_" + self._get_random_string(), open_posts=1
)
self.assignment.add_candidate(self.admin)
self.description = "test_description_paiquei5ahpie1wu8ohW"
self.poll = AssignmentPoll.objects.create(
assignment=self.assignment,
title="test_title_" + self._get_random_string(),
pollmethod=AssignmentPoll.POLLMETHOD_YNA,
type=self.poll_type,
state=AssignmentPoll.STATE_STARTED,
onehundred_percent_base=AssignmentPoll.PERCENT_BASE_CAST,
majority_method=AssignmentPoll.MAJORITY_TWO_THIRDS,
description=self.description,
)
self.poll.create_options()
self.poll.groups.add(self.delegate_group)
class VoteAssignmentPollNamedAutoupdates(VoteAssignmentPollAutoupdatesBaseClass):
poll_type = AssignmentPoll.TYPE_NAMED
def test_vote(self):
response = self.user_client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]), {"1": "A"}
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
poll = AssignmentPoll.objects.get()
vote = AssignmentVote.objects.get()
# Expect the admin to see the full data in the autoupdate
autoupdate = self.get_last_autoupdate(user=self.admin)
self.assertEqual(
autoupdate[0],
{
"assignments/assignment-poll:1": {
"allow_multiple_votes_per_candidate": False,
"assignment_id": 1,
"global_abstain": True,
"global_no": True,
"amount_global_abstain": None,
"amount_global_no": None,
"groups_id": [GROUP_DELEGATE_PK],
"id": 1,
"options_id": [1],
"pollmethod": AssignmentPoll.POLLMETHOD_YNA,
"state": AssignmentPoll.STATE_STARTED,
"title": self.poll.title,
"description": self.description,
"type": AssignmentPoll.TYPE_NAMED,
"onehundred_percent_base": AssignmentPoll.PERCENT_BASE_CAST,
"majority_method": AssignmentPoll.MAJORITY_TWO_THIRDS,
"votes_amount": 1,
"votescast": "1.000000",
"votesinvalid": "0.000000",
"votesvalid": "1.000000",
"user_has_voted": False,
"voted_id": [self.user.id],
},
"assignments/assignment-option:1": {
"abstain": "1.000000",
"id": 1,
"no": "0.000000",
"poll_id": 1,
"pollstate": AssignmentPoll.STATE_STARTED,
"yes": "0.000000",
"user_id": 1,
"weight": 1,
},
"assignments/assignment-vote:1": {
"id": 1,
"option_id": 1,
"pollstate": AssignmentPoll.STATE_STARTED,
"user_id": self.user.id,
"value": "A",
"weight": "1.000000",
},
},
)
self.assertEqual(autoupdate[1], [])
# Expect user to receive his vote
autoupdate = self.get_last_autoupdate(user=self.user)
self.assertEqual(
autoupdate[0]["assignments/assignment-vote:1"],
{
"id": 1,
"option_id": 1,
"pollstate": AssignmentPoll.STATE_STARTED,
"user_id": self.user.id,
"value": "A",
"weight": "1.000000",
},
)
self.assertEqual(autoupdate[1], [])
# Expect non-admins to get a restricted poll update
for user in (self.user, self.other_user):
self.assertAutoupdate(poll, user=user)
autoupdate = self.get_last_autoupdate(user=user)
self.assertEqual(
autoupdate[0]["assignments/assignment-poll:1"],
{
"allow_multiple_votes_per_candidate": False,
"assignment_id": 1,
"global_abstain": True,
"global_no": True,
"pollmethod": AssignmentPoll.POLLMETHOD_YNA,
"state": AssignmentPoll.STATE_STARTED,
"type": AssignmentPoll.TYPE_NAMED,
"onehundred_percent_base": AssignmentPoll.PERCENT_BASE_CAST,
"majority_method": AssignmentPoll.MAJORITY_TWO_THIRDS,
"title": self.poll.title,
"description": self.description,
"groups_id": [GROUP_DELEGATE_PK],
"options_id": [1],
"id": 1,
"votes_amount": 1,
"user_has_voted": user == self.user,
},
)
# Other users should not get a vote autoupdate
self.assertNoAutoupdate(vote, user=self.other_user)
self.assertNoDeletedAutoupdate(vote, user=self.other_user)
def test_publish(self):
option = self.poll.options.get()
vote = AssignmentVote.objects.create(user=self.user, option=option)
vote.value = "A"
vote.weight = Decimal("1")
vote.save(no_delete_on_restriction=True, skip_autoupdate=True)
self.poll.voted.add(self.user.id)
self.poll.state = AssignmentPoll.STATE_FINISHED
self.poll.save(skip_autoupdate=True)
response = self.client.post(
reverse("assignmentpoll-publish", args=[self.poll.pk])
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
poll = AssignmentPoll.objects.get()
vote = AssignmentVote.objects.get()
# Everyone should get the whole data
for user in (
self.admin,
self.user,
self.other_user,
):
self.assertAutoupdate(poll, user=user)
autoupdate = self.get_last_autoupdate(user=user)
self.assertEqual(
autoupdate[0]["assignments/assignment-poll:1"],
{
"allow_multiple_votes_per_candidate": False,
"amount_global_abstain": None,
"amount_global_no": None,
"assignment_id": 1,
"description": "test_description_paiquei5ahpie1wu8ohW",
"global_abstain": True,
"global_no": True,
"groups_id": [GROUP_DELEGATE_PK],
"id": 1,
"majority_method": "two_thirds",
"onehundred_percent_base": "cast",
"options_id": [1],
"pollmethod": "YNA",
"state": 4,
"title": self.poll.title,
"type": "named",
"votes_amount": 1,
"votescast": "1.000000",
"votesinvalid": "0.000000",
"votesvalid": "1.000000",
"user_has_voted": user == self.user,
"voted_id": [self.user.id],
},
)
self.assertEqual(
autoupdate[0]["assignments/assignment-vote:1"],
{
"pollstate": AssignmentPoll.STATE_PUBLISHED,
"id": 1,
"weight": "1.000000",
"value": "A",
"user_id": 3,
"option_id": 1,
},
)
self.assertEqual(
autoupdate[0]["assignments/assignment-option:1"],
{
"abstain": "1.000000",
"id": 1,
"no": "0.000000",
"poll_id": 1,
"pollstate": AssignmentPoll.STATE_PUBLISHED,
"yes": "0.000000",
"user_id": 1,
"weight": 1,
},
)
self.assertIn("users/user:3", autoupdate[0])
class VoteAssignmentPollPseudoanonymousAutoupdates(
VoteAssignmentPollAutoupdatesBaseClass
):
poll_type = AssignmentPoll.TYPE_PSEUDOANONYMOUS
def test_vote(self):
response = self.user_client.post(
reverse("assignmentpoll-vote", args=[self.poll.pk]), {"1": "A"}
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
poll = AssignmentPoll.objects.get()
vote = AssignmentVote.objects.get()
# Expect the admin to see the full data in the autoupdate
autoupdate = self.get_last_autoupdate(user=self.admin)
# TODO: mypy complains without the Any type; check why and fix it
should_be: Any = {
"assignments/assignment-poll:1": {
"allow_multiple_votes_per_candidate": False,
"assignment_id": 1,
"global_abstain": True,
"global_no": True,
"amount_global_abstain": None,
"amount_global_no": None,
"groups_id": [GROUP_DELEGATE_PK],
"id": 1,
"options_id": [1],
"pollmethod": AssignmentPoll.POLLMETHOD_YNA,
"state": AssignmentPoll.STATE_STARTED,
"title": self.poll.title,
"description": self.description,
"type": AssignmentPoll.TYPE_PSEUDOANONYMOUS,
"user_has_voted": False,
"voted_id": [self.user.id],
"onehundred_percent_base": AssignmentPoll.PERCENT_BASE_CAST,
"majority_method": AssignmentPoll.MAJORITY_TWO_THIRDS,
"votes_amount": 1,
"votescast": "1.000000",
"votesinvalid": "0.000000",
"votesvalid": "1.000000",
},
"assignments/assignment-option:1": {
"abstain": "1.000000",
"id": 1,
"no": "0.000000",
"poll_id": 1,
"pollstate": AssignmentPoll.STATE_STARTED,
"yes": "0.000000",
"user_id": 1,
"weight": 1,
},
"assignments/assignment-vote:1": {
"id": 1,
"option_id": 1,
"pollstate": AssignmentPoll.STATE_STARTED,
"user_id": None,
"value": "A",
"weight": "1.000000",
},
}
self.assertEqual(autoupdate[0], should_be)
self.assertEqual(autoupdate[1], [])
# Expect non-admins to get a restricted poll update and no autoupdate
# for a changed vote nor a deleted one
for user in (self.user, self.other_user):
self.assertAutoupdate(poll, user=user)
autoupdate = self.get_last_autoupdate(user=user)
self.assertEqual(
autoupdate[0]["assignments/assignment-poll:1"],
{
"allow_multiple_votes_per_candidate": False,
"assignment_id": 1,
"global_abstain": True,
"global_no": True,
"pollmethod": AssignmentPoll.POLLMETHOD_YNA,
"state": AssignmentPoll.STATE_STARTED,
"type": AssignmentPoll.TYPE_PSEUDOANONYMOUS,
"onehundred_percent_base": AssignmentPoll.PERCENT_BASE_CAST,
"majority_method": AssignmentPoll.MAJORITY_TWO_THIRDS,
"title": self.poll.title,
"description": self.description,
"groups_id": [GROUP_DELEGATE_PK],
"options_id": [1],
"id": 1,
"votes_amount": 1,
"user_has_voted": user == self.user,
},
)
self.assertNoAutoupdate(vote, user=user)
self.assertNoDeletedAutoupdate(vote, user=user)
def test_publish(self):
option = self.poll.options.get()
vote = AssignmentVote.objects.create(option=option)
vote.value = "A"
vote.weight = Decimal("1")
vote.save(no_delete_on_restriction=True, skip_autoupdate=True)
self.poll.voted.add(self.user.id)
self.poll.state = AssignmentPoll.STATE_FINISHED
self.poll.save(skip_autoupdate=True)
response = self.client.post(
reverse("assignmentpoll-publish", args=[self.poll.pk])
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
poll = AssignmentPoll.objects.get()
vote = AssignmentVote.objects.get()
# Everyone should get the whole data
for user in (
self.admin,
self.user,
self.other_user,
):
self.assertAutoupdate(poll, user=user)
autoupdate = self.get_last_autoupdate(user=user)
self.assertEqual(
autoupdate[0],
{
"assignments/assignment-poll:1": {
"allow_multiple_votes_per_candidate": False,
"amount_global_abstain": None,
"amount_global_no": None,
"assignment_id": 1,
"description": "test_description_paiquei5ahpie1wu8ohW",
"global_abstain": True,
"global_no": True,
"groups_id": [GROUP_DELEGATE_PK],
"id": 1,
"majority_method": "two_thirds",
"onehundred_percent_base": "cast",
"options_id": [1],
"pollmethod": "YNA",
"state": 4,
"title": self.poll.title,
"type": AssignmentPoll.TYPE_PSEUDOANONYMOUS,
"votes_amount": 1,
"votescast": "1.000000",
"votesinvalid": "0.000000",
"votesvalid": "1.000000",
"user_has_voted": user == self.user,
"voted_id": [self.user.id],
},
"assignments/assignment-vote:1": {
"pollstate": AssignmentPoll.STATE_PUBLISHED,
"id": 1,
"weight": "1.000000",
"value": "A",
"user_id": None,
"option_id": 1,
},
"assignments/assignment-option:1": {
"abstain": "1.000000",
"id": 1,
"no": "0.000000",
"poll_id": 1,
"pollstate": AssignmentPoll.STATE_PUBLISHED,
"yes": "0.000000",
"user_id": 1,
"weight": 1,
},
},
)
class PseudoanonymizeAssignmentPoll(TestCase):
def advancedSetUp(self):
self.assignment = Assignment.objects.create(
title="test_assignment_QLydMOqkyOHG68yZFJxl", open_posts=1
)
self.assignment.add_candidate(self.admin)
self.poll = AssignmentPoll.objects.create(
assignment=self.assignment,
title="test_title_3LbUCNirKirpJhRHRxzW",
pollmethod=AssignmentPoll.POLLMETHOD_YNA,
type=BasePoll.TYPE_NAMED,
state=AssignmentPoll.STATE_FINISHED,
)
self.poll.groups.add(GROUP_ADMIN_PK)
self.poll.create_options()
self.option = self.poll.options.get()
self.user1, _ = self.create_user()
self.vote1 = AssignmentVote.objects.create(
user=self.user1, option=self.option, value="Y", weight=Decimal(1)
)
self.poll.voted.add(self.user1)
self.user2, _ = self.create_user()
self.vote2 = AssignmentVote.objects.create(
user=self.user2, option=self.option, value="N", weight=Decimal(1)
)
self.poll.voted.add(self.user2)
def test_pseudoanonymize_poll(self):
response = self.client.post(
reverse("assignmentpoll-pseudoanonymize", args=[self.poll.pk])
)
self.assertHttpStatusVerbose(response, status.HTTP_200_OK)
poll = AssignmentPoll.objects.get()
self.assertEqual(poll.get_votes().count(), 2)
self.assertEqual(poll.amount_users_voted_with_individual_weight(), 2)
self.assertEqual(poll.votesvalid, Decimal("2"))
self.assertEqual(poll.votesinvalid, Decimal("0"))
self.assertEqual(poll.votescast, Decimal("2"))
option = poll.options.get()
self.assertEqual(option.yes, Decimal("1"))
self.assertEqual(option.no, Decimal("1"))
self.assertEqual(option.abstain, Decimal("0"))
self.assertTrue(self.user1 in poll.voted.all())
self.assertTrue(self.user2 in poll.voted.all())
for vote in poll.get_votes().all():
self.assertTrue(vote.user is None)
def test_pseudoanonymize_wrong_state(self):
self.poll.state = AssignmentPoll.STATE_CREATED
self.poll.save()
response = self.client.post(
reverse("assignmentpoll-pseudoanonymize", args=[self.poll.pk])
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
poll = AssignmentPoll.objects.get()
self.assertTrue(poll.get_votes().filter(user=self.user1).exists())
self.assertTrue(poll.get_votes().filter(user=self.user2).exists())
def test_pseudoanonymize_wrong_type(self):
self.poll.type = AssignmentPoll.TYPE_ANALOG
self.poll.save()
response = self.client.post(
reverse("assignmentpoll-pseudoanonymize", args=[self.poll.pk])
)
self.assertHttpStatusVerbose(response, status.HTTP_400_BAD_REQUEST)
poll = AssignmentPoll.objects.get()
self.assertTrue(poll.get_votes().filter(user=self.user1).exists())
self.assertTrue(poll.get_votes().filter(user=self.user2).exists())