Files
Sith/election/tests/test_apply_result.py
T
imperosol 3711bb3959 add tests
2026-06-05 00:32:06 +02:00

192 lines
7.3 KiB
Python

import itertools
from datetime import timedelta
from bs4 import BeautifulSoup
from django.contrib.auth.models import Permission
from django.test import TestCase
from django.urls import reverse
from django.utils.timezone import localdate, now
from model_bakery import baker, seq
from model_bakery.recipe import Recipe
from pytest_django.asserts import assertRedirects
from club.models import Club, ClubRole, Membership
from core.baker_recipes import subscriber_user
from core.models import Group, User
from election.models import Candidature, Election, ElectionList, Role, Vote
class TestApplyResult(TestCase):
@classmethod
def setUpTestData(cls):
# setup is a little bit complicated, but we have to make a whole
# election to test result application, including the election,
# the lists, the roles, the candidates and the votes.
cls.club = baker.make(Club)
cls.club_roles = baker.make(
ClubRole,
club=cls.club,
is_presidency=iter([True, False, False]),
is_board=True,
_quantity=3,
_bulk_create=True,
)
cls.election = baker.make(
Election,
clubs=[cls.club],
edit_groups=[baker.make(Group)],
end_date=now() - timedelta(minutes=1),
)
lists = baker.make(
ElectionList, election=cls.election, _quantity=2, _bulk_create=True
)
role_recipe = Recipe(Role, election=cls.election, title=seq("election role "))
roles = [
*role_recipe.make(
club_role=iter(cls.club_roles), _quantity=len(cls.club_roles)
),
role_recipe.make(),
]
roles[1].max_choice = 2
roles[1].save()
cls.candidatures = baker.make(
Candidature,
election_list=itertools.chain(
itertools.repeat(lists[0], len(roles)),
itertools.repeat(lists[1], len(roles)),
),
role=itertools.cycle(roles),
user=iter(
baker.make(
User, username=seq("user "), _quantity=len(lists) * len(roles)
)
),
_quantity=len(lists) * len(roles),
_bulk_create=True,
)
votes = iter(
baker.make(
Vote,
role=itertools.cycle(roles),
_quantity=6 * len(roles),
_bulk_create=True,
)
)
through = []
for cand in cls.candidatures:
nb_voices = 4 if cand.election_list_id == lists[0].id else 2
through.extend(
[
Vote.candidature.through(candidature=cand, vote=v)
for v in itertools.islice(votes, nb_voices)
]
)
Vote.candidature.through.objects.bulk_create(through)
cls.election.voters.set(baker.make(User, _quantity=8, _bulk_create=True))
cls.url = reverse(
"election:apply_result", kwargs={"election_id": cls.election.id}
)
def test_election_result(self):
# we have made a complex setup, so testing the results is
# useful to be sure we didn't make mistake when generating data
assert self.election.results == {
"election role 1": {
"blank vote": {"percent": 25.0, "vote": 2},
"total vote": 8,
"user 1": {"percent": 50.0, "vote": 4},
"user 5": {"percent": 25.0, "vote": 2},
},
"election role 2": {
"blank vote": {"percent": 62.5, "vote": 10},
"total vote": 16,
"user 2": {"percent": 25.0, "vote": 4},
"user 6": {"percent": 12.5, "vote": 2},
},
"election role 3": {
"blank vote": {"percent": 25.0, "vote": 2},
"total vote": 8,
"user 3": {"percent": 50.0, "vote": 4},
"user 7": {"percent": 25.0, "vote": 2},
},
"election role 4": {
"blank vote": {"percent": 25.0, "vote": 2},
"total vote": 8,
"user 4": {"percent": 50.0, "vote": 4},
"user 8": {"percent": 25.0, "vote": 2},
},
}
def test_apply_result(self):
user = baker.make(
User, user_permissions=[Permission.objects.get(codename="add_membership")]
)
self.client.force_login(user)
response = self.client.get(self.url)
soup = BeautifulSoup(response.text, "lxml")
inputs = soup.find_all("input", attrs={"type": "checkbox"})
assert all("checked" in i.attrs for i in inputs)
ids = {int(i.attrs["value"]) for i in inputs}
assert ids == {
self.candidatures[0].id,
self.candidatures[1].id,
self.candidatures[2].id,
self.candidatures[5].id,
}
response = self.client.post(
self.url, data={"candidates": ids.difference({self.candidatures[5].id})}
)
assertRedirects(response, self.url)
for candidate in self.candidatures[0:3]:
assert Membership.objects.filter(
start_date=localdate(),
end_date=None,
user=candidate.user,
role=candidate.role.club_role,
).exists()
assert self.club.members_group.users.contains(candidate.user)
assert self.club.board_group.users.contains(candidate.user)
# candidatures[5] was unchecked, so it shouldn't receive a club role
assert not self.candidatures[5].user.memberships.exists()
# now that results are applied, it shouldn't be possible to replay the request
response = self.client.get(self.url)
assert "Les résultats de cette élection ont été appliqués" in response.text
response = self.client.post(self.url, data={"candidates": ids})
assert response.status_code == 403
def test_no_result_to_apply(self):
self.election.roles.update(club_role=None)
user = baker.make(
User, user_permissions=[Permission.objects.get(codename="add_membership")]
)
self.client.force_login(user)
response = self.client.get(self.url)
soup = BeautifulSoup(response.text, "lxml")
assert not soup.find("input", attrs={"type": "checkbox"})
assert "Pas de résultats à appliquer" in response.text
def test_access_denied(self):
user = subscriber_user.make()
self.client.force_login(user)
response = self.client.get(self.url)
assert response.status_code == 403
response = self.client.post(
self.url, data={"candidates": [self.candidatures[0].id]}
)
assert response.status_code == 403
def test_election_not_finished(self):
user = baker.make(
User, user_permissions=[Permission.objects.get(codename="add_membership")]
)
self.election.end_date = now() + timedelta(minutes=1)
self.election.save()
self.client.force_login(user)
response = self.client.get(self.url)
assert response.status_code == 403
response = self.client.post(
self.url, data={"candidates": [self.candidatures[0].id]}
)
assert response.status_code == 403