3a19218bd5
Refactored user creation and update via REST API. Used new serializer. Cleaned up management commands, signals and imports. Moved code from 'api.py' to 'models.py'. Changed usage of group 'Registered'. Now the users don't have to be members to gain its permissions. Used customized auth backend for this. Added and changed some tests.
388 lines
17 KiB
Python
388 lines
17 KiB
Python
from unittest.mock import patch, MagicMock
|
|
|
|
from django.contrib.auth.models import Permission
|
|
from django.test.client import Client
|
|
|
|
from openslides.agenda.models import Item, Speaker
|
|
from openslides.agenda.signals import agenda_list_of_speakers
|
|
from openslides.config.api import config
|
|
from openslides.users.models import User
|
|
from openslides.projector.api import set_active_slide, register_slide_model
|
|
from openslides.utils.exceptions import OpenSlidesError
|
|
from openslides.utils.test import TestCase
|
|
|
|
from .models import RelatedItem
|
|
|
|
|
|
class ListOfSpeakerModelTests(TestCase):
|
|
def setUp(self):
|
|
self.item1 = Item.objects.create(title='item1')
|
|
self.item2 = Item.objects.create(title='item2')
|
|
self.speaker1 = User.objects.create(username='user1')
|
|
self.speaker2 = User.objects.create(username='user2')
|
|
|
|
def test_append_speaker(self):
|
|
# Append speaker1 to the list of item1
|
|
speaker1_item1 = Speaker.objects.add(self.speaker1, self.item1)
|
|
self.assertTrue(Speaker.objects.filter(user=self.speaker1, item=self.item1).exists())
|
|
|
|
# Append speaker1 to the list of item2
|
|
speaker1_item2 = Speaker.objects.add(self.speaker1, self.item2)
|
|
self.assertTrue(Speaker.objects.filter(user=self.speaker1, item=self.item2).exists())
|
|
|
|
# Append speaker2 to the list of item1
|
|
speaker2_item1 = Speaker.objects.add(self.speaker2, self.item1)
|
|
self.assertTrue(Speaker.objects.filter(user=self.speaker2, item=self.item1).exists())
|
|
|
|
# Try to append speaker 1 again to the list of item1
|
|
with self.assertRaises(OpenSlidesError):
|
|
Speaker.objects.add(self.speaker1, self.item1)
|
|
|
|
# Check time and weight
|
|
for object in (speaker1_item1, speaker2_item1, speaker1_item2):
|
|
self.assertIsNone(object.begin_time)
|
|
self.assertIsNone(object.end_time)
|
|
self.assertEqual(speaker1_item1.weight, 1)
|
|
self.assertEqual(speaker1_item2.weight, 1)
|
|
self.assertEqual(speaker2_item1.weight, 2)
|
|
|
|
def test_open_close_list_of_speaker(self):
|
|
self.assertFalse(Item.objects.get(pk=self.item1.pk).speaker_list_closed)
|
|
self.item1.speaker_list_closed = True
|
|
self.item1.save()
|
|
self.assertTrue(Item.objects.get(pk=self.item1.pk).speaker_list_closed)
|
|
|
|
def test_speak_and_finish(self):
|
|
speaker1_item1 = Speaker.objects.add(self.speaker1, self.item1)
|
|
self.assertIsNone(speaker1_item1.begin_time)
|
|
self.assertIsNone(speaker1_item1.end_time)
|
|
speaker1_item1.begin_speach()
|
|
self.assertIsNotNone(Speaker.objects.get(pk=speaker1_item1.pk).begin_time)
|
|
self.assertIsNone(Speaker.objects.get(pk=speaker1_item1.pk).weight)
|
|
speaker1_item1.end_speach()
|
|
self.assertIsNotNone(Speaker.objects.get(pk=speaker1_item1.pk).end_time)
|
|
|
|
def test_finish_when_other_speaker_begins(self):
|
|
speaker1_item1 = Speaker.objects.add(self.speaker1, self.item1)
|
|
speaker2_item1 = Speaker.objects.add(self.speaker2, self.item1)
|
|
speaker1_item1.begin_speach()
|
|
self.assertIsNone(speaker1_item1.end_time)
|
|
self.assertIsNone(speaker2_item1.begin_time)
|
|
speaker2_item1.begin_speach()
|
|
self.assertIsNotNone(Speaker.objects.get(user=self.speaker1, item=self.item1).end_time)
|
|
self.assertIsNotNone(speaker2_item1.begin_time)
|
|
|
|
def test_speach_coupled_with_countdown(self):
|
|
config['agenda_couple_countdown_and_speakers'] = True
|
|
speaker1_item1 = Speaker.objects.add(self.speaker1, self.item1)
|
|
self.item1.is_active_slide = MagicMock(return_value=True)
|
|
|
|
speaker1_item1.begin_speach()
|
|
self.assertEqual(config['countdown_state'], 'active')
|
|
|
|
speaker1_item1.end_speach()
|
|
self.assertEqual(config['countdown_state'], 'paused')
|
|
|
|
def test_begin_speach_not_coupled_with_countdown(self):
|
|
config['agenda_couple_countdown_and_speakers'] = False
|
|
speaker1_item1 = Speaker.objects.add(self.speaker1, self.item1)
|
|
|
|
speaker1_item1.begin_speach()
|
|
self.assertEqual(config['countdown_state'], 'inactive')
|
|
|
|
config['countdown_state'] = 'active'
|
|
speaker1_item1.end_speach()
|
|
self.assertEqual(config['countdown_state'], 'active')
|
|
|
|
|
|
class SpeakerViewTestCase(TestCase):
|
|
def setUp(self):
|
|
# Admin
|
|
self.admin = User.objects.get(pk=1)
|
|
self.admin_client = Client()
|
|
self.admin_client.login(username='admin', password='admin')
|
|
|
|
# Speaker1
|
|
self.speaker1 = User.objects.create_user('speaker1', 'speaker')
|
|
self.speaker1_client = Client()
|
|
self.speaker1_client.login(username='speaker1', password='speaker')
|
|
|
|
# Speaker2
|
|
self.speaker2 = User.objects.create_user('speaker2', 'speaker')
|
|
self.speaker2_client = Client()
|
|
self.speaker2_client.login(username='speaker2', password='speaker')
|
|
|
|
# Items
|
|
self.item1 = Item.objects.create(title='item1')
|
|
self.item2 = Item.objects.create(title='item2')
|
|
|
|
def check_url(self, url, test_client, response_code):
|
|
response = test_client.get(url)
|
|
self.assertEqual(response.status_code, response_code)
|
|
return response
|
|
|
|
def assertMessage(self, response, message):
|
|
self.assertTrue(message in response.cookies['messages'].value,
|
|
'"%s" is not a message of the response. (But: %s)'
|
|
% (message, response.cookies['messages'].value))
|
|
|
|
|
|
class TestSpeakerAppendView(SpeakerViewTestCase):
|
|
def test_get(self):
|
|
self.assertFalse(Speaker.objects.filter(user=self.speaker1, item=self.item1).exists())
|
|
self.assertEqual(Speaker.objects.filter(item=self.item1).count(), 0)
|
|
|
|
# Set speaker1 to item1
|
|
response = self.check_url('/agenda/1/speaker/', self.speaker1_client, 302)
|
|
self.assertTrue(Speaker.objects.filter(user=self.speaker1, item=self.item1).exists())
|
|
self.assertEqual(Speaker.objects.filter(item=self.item1).count(), 1)
|
|
self.assertMessage(response, 'You were successfully added to the list of speakers.')
|
|
|
|
# Try to set speaker 1 to item 1 again
|
|
response = self.check_url('/agenda/1/speaker/', self.speaker1_client, 302)
|
|
self.assertEqual(Speaker.objects.filter(item=self.item1).count(), 1)
|
|
self.assertMessage(response, 'speaker1 is already on the list of speakers of item 1.')
|
|
|
|
def test_closed_list(self):
|
|
self.item1.speaker_list_closed = True
|
|
self.item1.save()
|
|
|
|
response = self.check_url('/agenda/1/speaker/', self.speaker1_client, 302)
|
|
self.assertEqual(Speaker.objects.filter(item=self.item1).count(), 0)
|
|
self.assertMessage(response, 'The list of speakers is closed.')
|
|
|
|
|
|
class TestAgendaItemView(SpeakerViewTestCase):
|
|
def test_post(self):
|
|
# Set speaker1 to item1
|
|
response = self.admin_client.post(
|
|
'/agenda/1/', {'speaker': self.speaker1.id})
|
|
self.assertTrue(Speaker.objects.filter(user=self.speaker1, item=self.item1).exists())
|
|
|
|
# Try it again
|
|
response = self.admin_client.post(
|
|
'/agenda/1/', {'speaker': self.speaker1.id})
|
|
self.assertFormError(response, 'form', 'speaker', 'speaker1 is already on the list of speakers.')
|
|
|
|
|
|
class TestSpeakerDeleteView(SpeakerViewTestCase):
|
|
def test_get(self):
|
|
self.check_url('/agenda/1/speaker/del/', self.speaker1_client, 302)
|
|
|
|
def test_post_as_admin(self):
|
|
speaker = Speaker.objects.add(self.speaker1, self.item1)
|
|
|
|
response = self.admin_client.post(
|
|
'/agenda/1/speaker/%d/del/' % speaker.pk, {'yes': 'yes'})
|
|
self.assertEqual(response.status_code, 302)
|
|
self.assertFalse(Speaker.objects.filter(user=self.speaker1, item=self.item1).exists())
|
|
|
|
def test_post_as_user(self):
|
|
Speaker.objects.add(self.speaker1, self.item1)
|
|
|
|
response = self.speaker1_client.post(
|
|
'/agenda/1/speaker/del/', {'yes': 'yes'})
|
|
self.assertEqual(response.status_code, 302)
|
|
self.assertFalse(Speaker.objects.filter(user=self.speaker1, item=self.item1).exists())
|
|
|
|
|
|
class TestSpeakerSpeakView(SpeakerViewTestCase):
|
|
def test_get(self):
|
|
url = '/agenda/1/speaker/%s/speak/' % self.speaker1.pk
|
|
response = self.check_url(url, self.admin_client, 302)
|
|
self.assertMessage(response, '2 is not on the list of item1.')
|
|
|
|
speaker = Speaker.objects.add(self.speaker1, self.item1)
|
|
response = self.check_url(url, self.admin_client, 302)
|
|
speaker = Speaker.objects.get(pk=speaker.pk)
|
|
self.assertIsNotNone(speaker.begin_time)
|
|
self.assertIsNone(speaker.weight)
|
|
|
|
|
|
class TestSpeakerEndSpeachView(SpeakerViewTestCase):
|
|
def test_get(self):
|
|
url = '/agenda/1/speaker/end_speach/'
|
|
response = self.check_url(url, self.admin_client, 302)
|
|
self.assertMessage(response, 'There is no one speaking at the moment according to item1.')
|
|
speaker = Speaker.objects.add(self.speaker1, self.item1)
|
|
speaker.begin_speach()
|
|
response = self.check_url(url, self.admin_client, 302)
|
|
speaker = Speaker.objects.get(pk=speaker.pk)
|
|
self.assertIsNotNone(speaker.begin_time)
|
|
self.assertIsNotNone(speaker.end_time)
|
|
self.assertIsNone(speaker.weight)
|
|
|
|
|
|
class SpeakerListOpenView(SpeakerViewTestCase):
|
|
def test_get(self):
|
|
self.check_url('/agenda/1/speaker/close/', self.admin_client, 302)
|
|
item = Item.objects.get(pk=self.item1.pk)
|
|
self.assertTrue(item.speaker_list_closed)
|
|
|
|
self.check_url('/agenda/1/speaker/reopen/', self.admin_client, 302)
|
|
item = Item.objects.get(pk=self.item1.pk)
|
|
self.assertFalse(item.speaker_list_closed)
|
|
|
|
|
|
class GlobalListOfSpeakersLinks(SpeakerViewTestCase):
|
|
def test_global_redirect_url(self):
|
|
response = self.speaker1_client.get('/agenda/list_of_speakers/')
|
|
self.assertRedirects(response, '/dashboard/')
|
|
self.assertMessage(response, 'There is no list of speakers for the current slide. Please choose the agenda item manually from the agenda.')
|
|
|
|
set_active_slide('agenda', pk=1)
|
|
response = self.speaker1_client.get('/agenda/list_of_speakers/')
|
|
self.assertRedirects(response, '/agenda/1/')
|
|
|
|
def test_global_add_url(self):
|
|
response = self.speaker1_client.get('/agenda/list_of_speakers/add/')
|
|
self.assertRedirects(response, '/dashboard/')
|
|
self.assertMessage(response, 'There is no list of speakers for the current slide. Please choose the agenda item manually from the agenda.')
|
|
|
|
set_active_slide('agenda', pk=1)
|
|
response = self.speaker1_client.get('/agenda/list_of_speakers/add/')
|
|
self.assertRedirects(response, '/agenda/1/')
|
|
self.assertEqual(Speaker.objects.get(item__pk='1').user, self.speaker1)
|
|
self.assertMessage(response, 'You were successfully added to the list of speakers.')
|
|
|
|
perm = Permission.objects.filter(name='Can see agenda').get()
|
|
self.speaker2.groups.model.objects.get(name='Registered').permissions.remove(perm)
|
|
response = self.speaker2_client.get('/agenda/list_of_speakers/add/')
|
|
self.assertMessage(response, 'You were successfully added to the list of speakers.')
|
|
|
|
@patch('openslides.projector.api.slide_callback', {})
|
|
@patch('openslides.projector.api.slide_model', {})
|
|
def test_next_speaker_on_related_item(self):
|
|
"""
|
|
Test to add a speaker on a related item.
|
|
|
|
The patching of slide_callback and slide_model is needed to cleanup the
|
|
call of register_slide_model after the test is run.
|
|
"""
|
|
register_slide_model(RelatedItem, 'some/template.html')
|
|
related_item = RelatedItem.objects.create()
|
|
agenda_item = Item.objects.create(content_object=related_item)
|
|
config['projector_active_slide'] = {'callback': 'test_related_item', 'pk': 1}
|
|
response = self.speaker1_client.get('/agenda/list_of_speakers/add/')
|
|
|
|
self.assertRedirects(response, '/agenda/%d/' % agenda_item.pk)
|
|
self.assertEqual(Speaker.objects.get(item__pk=agenda_item.pk).user, self.speaker1)
|
|
self.assertMessage(response, 'You were successfully added to the list of speakers.')
|
|
|
|
def test_global_next_speaker_url(self):
|
|
response = self.admin_client.get('/agenda/list_of_speakers/next/')
|
|
self.assertRedirects(response, '/dashboard/')
|
|
self.assertMessage(response, 'There is no list of speakers for the current slide. Please choose the agenda item manually from the agenda.')
|
|
|
|
set_active_slide('agenda', pk=1)
|
|
response = self.admin_client.get('/agenda/list_of_speakers/next/')
|
|
self.assertRedirects(response, '/dashboard/')
|
|
self.assertMessage(response, 'The list of speakers is empty.')
|
|
|
|
response = self.speaker1_client.get('/agenda/list_of_speakers/add/')
|
|
self.assertTrue(Speaker.objects.get(item__pk='1').begin_time is None)
|
|
response = self.admin_client.get('/agenda/list_of_speakers/next/')
|
|
self.assertRedirects(response, '/dashboard/')
|
|
self.assertTrue(Speaker.objects.get(item__pk='1').begin_time is not None)
|
|
|
|
def test_global_end_speach_url(self):
|
|
response = self.admin_client.get('/agenda/list_of_speakers/end_speach/')
|
|
self.assertRedirects(response, '/dashboard/')
|
|
self.assertMessage(response, 'There is no list of speakers for the current slide. Please choose the agenda item manually from the agenda.')
|
|
|
|
set_active_slide('agenda', pk=1)
|
|
response = self.admin_client.get('/agenda/list_of_speakers/end_speach/')
|
|
self.assertRedirects(response, '/dashboard/')
|
|
self.assertMessage(response, 'There is no one speaking at the moment.')
|
|
|
|
response = self.speaker1_client.get('/agenda/list_of_speakers/add/')
|
|
self.assertTrue(Speaker.objects.get(item__pk='1').begin_time is None)
|
|
response = self.admin_client.get('/agenda/list_of_speakers/end_speach/')
|
|
self.assertRedirects(response, '/dashboard/')
|
|
self.assertMessage(response, 'There is no one speaking at the moment.')
|
|
|
|
response = self.admin_client.get('/agenda/list_of_speakers/next/')
|
|
self.assertTrue(Speaker.objects.get(item__pk='1').end_time is None)
|
|
response = self.admin_client.get('/agenda/list_of_speakers/end_speach/')
|
|
self.assertRedirects(response, '/dashboard/')
|
|
self.assertTrue(Speaker.objects.get(item__pk='1').end_time is not None)
|
|
|
|
|
|
class TestOverlay(TestCase):
|
|
def test_overlay_with_no_model_slide(self):
|
|
"""
|
|
When a slide is active, that is not a model (for example the agenda)
|
|
an Attribute Error was raised.
|
|
"""
|
|
config['projector_active_slide'] = {'callback': None}
|
|
|
|
value = agenda_list_of_speakers(sender='test').get_projector_html()
|
|
|
|
self.assertEqual(value, '')
|
|
|
|
|
|
class TestCurrentListOfSpeakersOnProjectorView(SpeakerViewTestCase):
|
|
"""
|
|
Test the view with the current list of speakers depending on the actual
|
|
slide.
|
|
"""
|
|
def test_get_none(self):
|
|
response = self.admin_client.get('/agenda/list_of_speakers/projector/')
|
|
self.assertContains(response, 'List of speakers</h1><i>Not available')
|
|
|
|
def test_get_normal(self):
|
|
self.item1.title = 'title_gupooDee8ahahnaxoo2a'
|
|
self.item1.save()
|
|
Speaker.objects.add(self.speaker1, self.item1)
|
|
config['projector_active_slide'] = {'callback': 'agenda', 'pk': self.item1.pk}
|
|
response = self.admin_client.get('/agenda/list_of_speakers/projector/')
|
|
self.assertContains(response, 'List of speakers')
|
|
self.assertContains(response, 'title_gupooDee8ahahnaxoo2a')
|
|
self.assertContains(response, 'speaker1')
|
|
|
|
|
|
class TestSpeakerChangeOrderView(SpeakerViewTestCase):
|
|
def setUp(self):
|
|
super().setUp()
|
|
Speaker.objects.add(self.speaker1, self.item1)
|
|
Speaker.objects.add(self.speaker2, self.item1)
|
|
|
|
def test_post(self):
|
|
"""
|
|
Tests to change the order of two speakers.
|
|
"""
|
|
data = {'sort_order': 'speaker_2,speaker_1'}
|
|
self.admin_client.post('/agenda/1/speaker/change_order/',
|
|
data)
|
|
|
|
self.assertEqual(Speaker.objects.get(pk=1).weight, 2)
|
|
self.assertEqual(Speaker.objects.get(pk=2).weight, 1)
|
|
|
|
def test_invalid_data1(self):
|
|
"""
|
|
Tests to send invalid data.
|
|
|
|
The order should not change.
|
|
"""
|
|
data = {'sort_order': 'speaker_2,speaker:1'}
|
|
response = self.admin_client.post('/agenda/1/speaker/change_order/',
|
|
data)
|
|
|
|
self.assertEqual(Speaker.objects.get(pk=1).weight, 1)
|
|
self.assertEqual(Speaker.objects.get(pk=2).weight, 2)
|
|
self.assertMessage(response, 'Could not change order. Invalid data.')
|
|
|
|
def test_invalid_data2(self):
|
|
"""
|
|
Tests to send a speaker that does not exist.
|
|
|
|
The order should not change.
|
|
"""
|
|
data = {'sort_order': 'speaker_2,speaker_10'}
|
|
response = self.admin_client.post('/agenda/1/speaker/change_order/',
|
|
data)
|
|
|
|
self.assertEqual(Speaker.objects.get(pk=1).weight, 1)
|
|
self.assertEqual(Speaker.objects.get(pk=2).weight, 2)
|
|
self.assertMessage(response, 'Could not change order. Invalid data.')
|