Louis Mazin 4db822aebe big maj
2026-10-05 17:52:28 +02:00

124 lines
7.0 KiB
Python

from django.contrib.auth import get_user_model
from rest_framework.test import APITestCase
from .models import Note, Poll, PollVote
class PollAPITests(APITestCase):
def setUp(self):
self.author = get_user_model().objects.create_user(username='author')
self.voter = get_user_model().objects.create_user(username='voter')
self.other = get_user_model().objects.create_user(username='other')
self.admin = get_user_model().objects.create_user(username='admin', is_staff=True)
self.client.force_authenticate(self.author)
def create_poll(self, **settings):
payload = dict(title='Question ?', content='', kind='poll', is_public=True, recipient_ids=[],
poll_settings=dict(vote_mode='single', exact_choices=1, is_anonymous=True, closes_at=None, options=['A', 'B', 'C']))
payload['poll_settings'].update(settings)
response = self.client.post('/api/notes/', payload, format='json')
self.assertEqual(response.status_code, 201, response.data)
return response.data
def vote(self, note, choices, user=None):
self.client.force_authenticate(user or self.voter)
return self.client.put(f"/api/notes/{note['id']}/vote/", {'option_ids': [note['poll']['options'][i]['id'] for i in choices]}, format='json')
def test_single_vote_is_replaced_and_results_stay_anonymous(self):
note = self.create_poll()
self.assertEqual(self.vote(note, [0, 1]).status_code, 400)
result = self.vote(note, [0])
self.assertEqual(result.status_code, 200, result.data)
result = self.vote(note, [1])
self.assertEqual(result.data['poll']['total_voters'], 1)
self.assertEqual([o['count'] for o in result.data['poll']['options']], [0, 1, 0])
for viewer in [self.author, self.admin, self.other]:
self.client.force_authenticate(viewer)
data = self.client.get(f"/api/notes/{note['id']}/").data['poll']
self.assertEqual(data['total_voters'], 1)
self.assertFalse(any('voters' in option for option in data['options']))
def test_anonymous_api_never_contains_voter_identity(self):
note = self.create_poll()
self.vote(note, [0])
for viewer in [self.author, self.admin, self.other]:
self.client.force_authenticate(viewer)
poll = self.client.get(f"/api/notes/{note['id']}/").data['poll']
self.assertEqual(poll['my_option_ids'], [])
for option in poll['options']:
self.assertNotIn('voters', option)
self.assertNotIn('user', option)
self.assertNotIn('username', str(poll))
def test_named_multiple_votes(self):
note = self.create_poll(vote_mode='multiple', is_anonymous=False)
result = self.vote(note, [0, 2])
self.assertEqual(result.status_code, 200, result.data)
self.assertEqual(result.data['poll']['options'][0]['voters'][0]['id'], self.voter.pk)
self.assertEqual(result.data['poll']['options'][0]['percent'], 100)
self.assertEqual(result.data['poll']['total_voters'], 1)
def test_exact_count_and_cross_poll_option_validation(self):
note = self.create_poll(vote_mode='exact', exact_choices=2)
self.assertEqual(self.vote(note, [0]).status_code, 400)
self.assertEqual(self.vote(note, [0, 1, 2]).status_code, 400)
self.assertEqual(self.vote(note, [0, 1]).status_code, 200)
self.client.force_authenticate(self.author)
other = self.create_poll()
self.client.force_authenticate(self.voter)
result = self.client.put(f"/api/notes/{note['id']}/vote/", {'option_ids': [note['poll']['options'][0]['id'], other['poll']['options'][0]['id']]}, format='json')
self.assertEqual(result.status_code, 400)
def test_rules_question_and_visibility_lock_after_first_vote(self):
note = self.create_poll()
self.vote(note, [0])
self.client.force_authenticate(self.author)
for payload in [dict(kind='info'), dict(title='Autre question'),
dict(poll_settings=dict(vote_mode='single', exact_choices=1, is_anonymous=False, closes_at=None, options=['A', 'B', 'C']))]:
result = self.client.patch(f"/api/notes/{note['id']}/", payload, format='json')
self.assertEqual(result.status_code, 400, result.data)
self.assertTrue(Poll.objects.get().is_anonymous)
self.assertEqual(Note.objects.get().kind, 'poll')
self.assertEqual(self.client.patch(f"/api/notes/{note['id']}/", {'content': 'Précision'}, format='json').status_code, 200)
def test_closed_and_deadline_polls_reject_votes(self):
note = self.create_poll()
self.client.force_authenticate(self.other)
self.assertEqual(self.client.post(f"/api/notes/{note['id']}/close/").status_code, 403)
self.client.force_authenticate(self.author)
self.assertEqual(self.client.post(f"/api/notes/{note['id']}/close/").status_code, 200)
self.assertEqual(self.vote(note, [0]).status_code, 400)
self.client.force_authenticate(self.author)
expired = self.create_poll(closes_at='2020-01-01T00:00:00Z')
self.assertEqual(self.vote(expired, [0]).status_code, 200)
def test_poll_scope_and_recipients_are_always_public_for_everyone(self):
note = self.create_poll()
response = self.client.patch(f"/api/notes/{note['id']}/", {'is_public': False, 'recipient_ids': [self.voter.pk]}, format='json')
self.assertEqual(response.status_code, 200, response.data)
self.assertTrue(response.data['is_public'])
self.assertEqual(response.data['recipients'], [])
self.client.force_authenticate(self.other)
self.assertEqual(self.client.get(f"/api/notes/{note['id']}/").status_code, 200)
self.assertEqual(self.vote(note, [0], self.other).status_code, 200)
def test_new_user_can_participate_in_public_poll_for_everyone(self):
note = self.create_poll()
new_user = get_user_model().objects.create_user(username='new')
self.assertEqual(self.vote(note, [1], new_user).status_code, 200)
def test_convert_existing_memo_to_poll_and_back_before_votes(self):
note = Note.objects.create(author=self.author, title='Mémo')
result = self.client.patch(f'/api/notes/{note.pk}/', dict(kind='poll', poll_settings=dict(options=['Oui', 'Non'])), format='json')
self.assertEqual(result.status_code, 200, result.data)
self.assertEqual(len(result.data['poll']['options']), 2)
result = self.client.patch(f'/api/notes/{note.pk}/', dict(kind='memo'), format='json')
self.assertEqual(result.status_code, 200)
self.assertIsNone(result.data['poll'])
self.assertFalse(Poll.objects.exists())
def test_invalid_poll_does_not_leave_note_behind(self):
result = self.client.post('/api/notes/', dict(kind='poll', title='Test', poll_settings=dict(options=['A', 'A'])), format='json')
self.assertEqual(result.status_code, 400)
self.assertFalse(Note.objects.exists())