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)
|
Speaker.objects.add(user, item)
|
||||||
except OpenSlidesError as e:
|
except OpenSlidesError as e:
|
||||||
raise ValidationError({'detail': 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:
|
else:
|
||||||
# request.method == 'DELETE'
|
# request.method == 'DELETE'
|
||||||
@ -286,13 +286,63 @@ class ItemViewSet(ModelViewSet):
|
|||||||
if not self.request.user.has_perm('agenda.can_manage'):
|
if not self.request.user.has_perm('agenda.can_manage'):
|
||||||
self.permission_denied(request)
|
self.permission_denied(request)
|
||||||
try:
|
try:
|
||||||
speaker = Speaker.objects.get(pk=speaker_id)
|
speaker = Speaker.objects.get(pk=int(speaker_id))
|
||||||
except Speaker.DoesNotExist:
|
except (ValueError, Speaker.DoesNotExist):
|
||||||
raise ValidationError({'detail': _('Speaker does not exist.')})
|
raise ValidationError({'detail': _('Speaker does not exist.')})
|
||||||
|
|
||||||
# Delete the speaker.
|
# Delete the speaker.
|
||||||
speaker.delete()
|
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.
|
# Initiate response.
|
||||||
return Response({'detail': message})
|
return Response({'detail': message})
|
||||||
|
@ -104,6 +104,12 @@ class ManageSpeaker(TestCase):
|
|||||||
{'speaker': '1'})
|
{'speaker': '1'})
|
||||||
self.assertEqual(response.status_code, 400)
|
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):
|
def test_remove_someone_else_non_admin(self):
|
||||||
admin = get_user_model().objects.get(username='admin')
|
admin = get_user_model().objects.get(username='admin')
|
||||||
group_staff = admin.groups.get(name='Staff')
|
group_staff = admin.groups.get(name='Staff')
|
||||||
@ -115,3 +121,59 @@ class ManageSpeaker(TestCase):
|
|||||||
reverse('item-manage-speaker', args=[self.item.pk]),
|
reverse('item-manage-speaker', args=[self.item.pk]),
|
||||||
{'speaker': speaker.pk})
|
{'speaker': speaker.pk})
|
||||||
self.assertEqual(response.status_code, 403)
|
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.user.has_perm.return_value = True
|
||||||
self.request.data = {'speaker': '1'}
|
self.request.data = {'speaker': '1'}
|
||||||
self.view_instance.manage_speaker(self.request)
|
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()
|
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