Added view to begin and end speach.
This commit is contained in:
parent
95be18b78e
commit
0853701cdd
@ -262,7 +262,7 @@ class ItemViewSet(ModelViewSet):
|
||||
Speaker.objects.add(user, item)
|
||||
except OpenSlidesError as e:
|
||||
raise ValidationError({'detail': e})
|
||||
message = _('User was successfully added to the list of speakers.')
|
||||
message = _('User %s was successfully added to the list of speakers.') % user
|
||||
|
||||
else:
|
||||
# request.method == 'DELETE'
|
||||
@ -286,13 +286,63 @@ class ItemViewSet(ModelViewSet):
|
||||
if not self.request.user.has_perm('agenda.can_manage'):
|
||||
self.permission_denied(request)
|
||||
try:
|
||||
speaker = Speaker.objects.get(pk=speaker_id)
|
||||
except Speaker.DoesNotExist:
|
||||
speaker = Speaker.objects.get(pk=int(speaker_id))
|
||||
except (ValueError, Speaker.DoesNotExist):
|
||||
raise ValidationError({'detail': _('Speaker does not exist.')})
|
||||
|
||||
# Delete the speaker.
|
||||
speaker.delete()
|
||||
message = _('Speaker was successfully removed from the list of speakers.')
|
||||
message = _('Speaker %s was successfully removed from the list of speakers.') % speaker
|
||||
|
||||
# Initiate response.
|
||||
return Response({'detail': message})
|
||||
|
||||
@detail_route(methods=['PUT', 'DELETE'])
|
||||
def speak(self, request, pk=None):
|
||||
"""
|
||||
Special view endpoint to begin and end speach of speakers. Send PUT
|
||||
{'speaker': <speaker_id>} to begin speach. Omit data to begin speach of
|
||||
the next speaker. Send DELETE to end speach of current speaker.
|
||||
|
||||
Checks also whether the requesting user can do this. He needs at
|
||||
least the permissions 'agenda.can_see' (see
|
||||
self.check_permission()). Also the permission 'agenda.can_manage'
|
||||
is required.
|
||||
"""
|
||||
# Check permission.
|
||||
if not self.request.user.has_perm('agenda.can_manage'):
|
||||
self.permission_denied(request)
|
||||
|
||||
# Retrieve item.
|
||||
item = self.get_object()
|
||||
|
||||
if request.method == 'PUT':
|
||||
# Retrieve speaker_id
|
||||
speaker_id = request.data.get('speaker')
|
||||
if speaker_id is None:
|
||||
speaker = item.get_next_speaker()
|
||||
if speaker is None:
|
||||
raise ValidationError({'detail': _('The list of speakers is empty.')})
|
||||
else:
|
||||
try:
|
||||
speaker = Speaker.objects.get(pk=int(speaker_id))
|
||||
except (ValueError, Speaker.DoesNotExist):
|
||||
raise ValidationError({'detail': _('Speaker does not exist.')})
|
||||
speaker.begin_speach()
|
||||
message = _('User is now speaking.')
|
||||
|
||||
else:
|
||||
# request.method == 'DELETE'
|
||||
try:
|
||||
# We assume that there aren't multiple entries because this
|
||||
# is forbidden by the Model's begin_speach method. We assume that
|
||||
# there is only one speaker instance or none.
|
||||
current_speaker = Speaker.objects.filter(item=item, end_time=None).exclude(begin_time=None).get()
|
||||
except Speaker.DoesNotExist:
|
||||
raise ValidationError(
|
||||
{'detail': _('There is no one speaking at the moment according to %(item)s.') % {'item': item}})
|
||||
current_speaker.end_speach()
|
||||
message = _('The speach is finished now.')
|
||||
|
||||
# Initiate response.
|
||||
return Response({'detail': message})
|
||||
|
@ -104,6 +104,12 @@ class ManageSpeaker(TestCase):
|
||||
{'speaker': '1'})
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_remove_someone_else_invalid_data(self):
|
||||
response = self.client.delete(
|
||||
reverse('item-manage-speaker', args=[self.item.pk]),
|
||||
{'speaker': 'invalid'})
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_remove_someone_else_non_admin(self):
|
||||
admin = get_user_model().objects.get(username='admin')
|
||||
group_staff = admin.groups.get(name='Staff')
|
||||
@ -115,3 +121,59 @@ class ManageSpeaker(TestCase):
|
||||
reverse('item-manage-speaker', args=[self.item.pk]),
|
||||
{'speaker': speaker.pk})
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
|
||||
class Speak(TestCase):
|
||||
"""
|
||||
Tests view to begin or end speach.
|
||||
"""
|
||||
def setUp(self):
|
||||
self.client = APIClient()
|
||||
self.client.login(username='admin', password='admin')
|
||||
self.item = Item.objects.create(title='test_title_KooDueco3zaiGhiraiho')
|
||||
self.user = get_user_model().objects.create_user(
|
||||
username='test_user_Aigh4vohb3seecha4aa4',
|
||||
password='test_password_eneupeeVo5deilixoo8j')
|
||||
|
||||
def test_begin_speach(self):
|
||||
Speaker.objects.add(self.user, self.item)
|
||||
speaker = Speaker.objects.add(get_user_model().objects.get(username='admin'), self.item)
|
||||
self.assertTrue(Speaker.objects.get(pk=speaker.pk).begin_time is None)
|
||||
response = self.client.put(
|
||||
reverse('item-speak', args=[self.item.pk]),
|
||||
{'speaker': speaker.pk})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertFalse(Speaker.objects.get(pk=speaker.pk).begin_time is None)
|
||||
|
||||
def test_begin_speach_next_speaker(self):
|
||||
speaker = Speaker.objects.add(self.user, self.item)
|
||||
Speaker.objects.add(get_user_model().objects.get(username='admin'), self.item)
|
||||
self.assertTrue(Speaker.objects.get(pk=speaker.pk).begin_time is None)
|
||||
response = self.client.put(reverse('item-speak', args=[self.item.pk]))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertFalse(Speaker.objects.get(pk=speaker.pk).begin_time is None)
|
||||
|
||||
def test_begin_speach_invalid_speaker_id(self):
|
||||
response = self.client.put(
|
||||
reverse('item-speak', args=[self.item.pk]),
|
||||
{'speaker': '1'})
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_begin_speach_invalid_data(self):
|
||||
response = self.client.put(
|
||||
reverse('item-speak', args=[self.item.pk]),
|
||||
{'speaker': 'invalid'})
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
def test_end_speach(self):
|
||||
speaker = Speaker.objects.add(get_user_model().objects.get(username='admin'), self.item)
|
||||
speaker.begin_speach()
|
||||
self.assertFalse(Speaker.objects.get(pk=speaker.pk).begin_time is None)
|
||||
self.assertTrue(Speaker.objects.get(pk=speaker.pk).end_time is None)
|
||||
response = self.client.delete(reverse('item-speak', args=[self.item.pk]))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertFalse(Speaker.objects.get(pk=speaker.pk).end_time is None)
|
||||
|
||||
def test_end_speach_no_current_speaker(self):
|
||||
response = self.client.delete(reverse('item-speak', args=[self.item.pk]))
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
@ -50,5 +50,42 @@ class ItemViewSetManageSpeaker(TestCase):
|
||||
self.request.user.has_perm.return_value = True
|
||||
self.request.data = {'speaker': '1'}
|
||||
self.view_instance.manage_speaker(self.request)
|
||||
mock_speaker.objects.get.assert_called_with(pk='1')
|
||||
mock_speaker.objects.get.assert_called_with(pk=1)
|
||||
mock_speaker.objects.get.return_value.delete.assert_called_with()
|
||||
|
||||
|
||||
class ItemViewSetSpeak(TestCase):
|
||||
"""
|
||||
Tests views of ItemViewSet to begin and end speach.
|
||||
"""
|
||||
def setUp(self):
|
||||
self.request = MagicMock()
|
||||
self.view_instance = ItemViewSet()
|
||||
self.view_instance.request = self.request
|
||||
self.view_instance.get_object = get_object_mock = MagicMock()
|
||||
get_object_mock.return_value = self.mock_item = MagicMock()
|
||||
|
||||
def test_begin_speach(self):
|
||||
self.request.method = 'PUT'
|
||||
self.request.user.has_perm.return_value = True
|
||||
self.request.data = {}
|
||||
self.mock_item.get_next_speaker.return_value = mock_next_speaker = MagicMock()
|
||||
self.view_instance.speak(self.request)
|
||||
mock_next_speaker.begin_speach.assert_called_with()
|
||||
|
||||
@patch('openslides.agenda.views.Speaker')
|
||||
def test_begin_speach_specific_speaker(self, mock_speaker):
|
||||
self.request.method = 'PUT'
|
||||
self.request.user.has_perm.return_value = True
|
||||
self.request.data = {'speaker': '1'}
|
||||
mock_speaker.objects.get.return_value = mock_next_speaker = MagicMock()
|
||||
self.view_instance.speak(self.request)
|
||||
mock_next_speaker.begin_speach.assert_called_with()
|
||||
|
||||
@patch('openslides.agenda.views.Speaker')
|
||||
def test_end_speach(self, mock_speaker):
|
||||
self.request.method = 'DELETE'
|
||||
self.request.user.has_perm.return_value = True
|
||||
mock_speaker.objects.filter.return_value.exclude.return_value.get.return_value = mock_speaker = MagicMock()
|
||||
self.view_instance.speak(self.request)
|
||||
mock_speaker.end_speach.assert_called_with()
|
||||
|
Loading…
Reference in New Issue
Block a user