diff --git a/openslides/core/serializers.py b/openslides/core/serializers.py index c72b4afd1..2f5faa379 100644 --- a/openslides/core/serializers.py +++ b/openslides/core/serializers.py @@ -101,12 +101,6 @@ class ProjectorSerializer(ModelSerializer): ) read_only_fields = ("scale", "scroll") - def validate_elements_history(self, value): - """ - Validates the value of the element field of the projector model. - """ - self.validate_elements_preview(value) - class TagSerializer(ModelSerializer): """ diff --git a/openslides/core/views.py b/openslides/core/views.py index 2270f1e88..ae1661519 100644 --- a/openslides/core/views.py +++ b/openslides/core/views.py @@ -127,9 +127,9 @@ class ProjectorViewSet(ModelViewSet): "partial_update", "destroy", "control_view", - "set_resolution", "set_scroll", "set_projectiondefault", + "project", ): result = has_perm(self.request.user, "core.can_see_projector") and has_perm( self.request.user, "core.can_manage_projector" @@ -152,6 +152,39 @@ class ProjectorViewSet(ModelViewSet): projection_default.save() return super(ProjectorViewSet, self).destroy(*args, **kwargs) + @detail_route(methods=["post"]) + def project(self, request, pk): + """ + Sets the `elements` and `elements_preview` and adds one item to the + `elements_history`. + + `request.data` can have three arguments: `append_to_history`, `elements` + and `preview`. Non of them is required. + + `append_to_history` adds one element to the end of the history_elements. + `elements` and `preview` preplaces the coresponding fields in the + database. + """ + projector = self.get_object() + elements = request.data.get("elements") + preview = request.data.get("preview") + history_element = request.data.get("append_to_history") + + changed_data = {} + if elements is not None: + changed_data["elements"] = elements + if preview is not None: + changed_data["elements_preview"] = preview + if history_element is not None: + history = projector.elements_history + [history_element] + changed_data["elements_history"] = history + + serializer = self.get_serializer(projector, data=changed_data, partial=True) + serializer.is_valid(raise_exception=True) + self.perform_update(serializer) + + return Response() + @detail_route(methods=["post"]) def control_view(self, request, pk): """ diff --git a/tests/integration/core/test_views.py b/tests/integration/core/test_views.py index a9d7cf6f3..850c0ae3c 100644 --- a/tests/integration/core/test_views.py +++ b/tests/integration/core/test_views.py @@ -1,71 +1,108 @@ import json +import pytest from django.urls import reverse from rest_framework import status from rest_framework.test import APIClient from openslides import __license__ as license, __url__ as url, __version__ as version from openslides.core.config import ConfigVariable, config +from openslides.core.models import Projector from openslides.utils.rest_api import ValidationError from openslides.utils.test import TestCase -class ProjectorAPI(TestCase): - def test_slide_on_default_projector(self): - self.client.login(username="admin", password="admin") - self.client.put( - reverse("projector-detail", args=["1"]), - {"elements": [{"name": "topics/topic", "id": 1}]}, - content_type="application/json", - ) +@pytest.mark.django_db(transaction=False) +def test_slide_on_default_projector(client): + client.login(username="admin", password="admin") + client.put( + reverse("projector-detail", args=["1"]), + {"elements": [{"name": "topics/topic", "id": 1}]}, + content_type="application/json", + ) - response = self.client.get(reverse("projector-detail", args=["1"])) + response = client.get(reverse("projector-detail", args=["1"])) - self.assertEqual(response.status_code, status.HTTP_200_OK) + assert response.status_code == 200 - def test_invalid_element_non_existing_slide(self): - self.client.login(username="admin", password="admin") - response = self.client.put( - reverse("projector-detail", args=["1"]), - {"elements": [{"name": "invalid_slide_name", "id": 1}]}, - content_type="application/json", - ) +@pytest.mark.django_db(transaction=False) +def test_invalid_element_non_existing_slide(client): + client.login(username="admin", password="admin") - self.assertEqual(response.status_code, 400) + response = client.put( + reverse("projector-detail", args=["1"]), + {"elements": [{"name": "invalid_slide_name", "id": 1}]}, + content_type="application/json", + ) - def test_invalid_element_no_name_attribute(self): - self.client.login(username="admin", password="admin") + assert response.status_code == 400 - response = self.client.put( - reverse("projector-detail", args=["1"]), - {"elements": [{"id": 1}]}, - content_type="application/json", - ) - self.assertEqual(response.status_code, 400) +@pytest.mark.django_db(transaction=False) +def test_invalid_element_no_name_attribute(client): + client.login(username="admin", password="admin") - def test_invalid_element_not_a_inner_dict(self): - self.client.login(username="admin", password="admin") + response = client.put( + reverse("projector-detail", args=["1"]), + {"elements": [{"id": 1}]}, + content_type="application/json", + ) - response = self.client.put( - reverse("projector-detail", args=["1"]), - {"elements": ["not a dict"]}, - content_type="application/json", - ) + assert response.status_code == 400 - self.assertEqual(response.status_code, 400) - def test_invalid_element_a_list(self): - self.client.login(username="admin", password="admin") +@pytest.mark.django_db(transaction=False) +def test_invalid_element_not_a_inner_dict(client): + client.login(username="admin", password="admin") - response = self.client.put( - reverse("projector-detail", args=["1"]), - {"elements": {"name": "invalid_slide_name", "id": 1}}, - content_type="application/json", - ) + response = client.put( + reverse("projector-detail", args=["1"]), + {"elements": ["not a dict"]}, + content_type="application/json", + ) - self.assertEqual(response.status_code, 400) + assert response.status_code == 400 + + +@pytest.mark.django_db(transaction=False) +def test_invalid_element_a_list(client): + client.login(username="admin", password="admin") + + response = client.put( + reverse("projector-detail", args=["1"]), + {"elements": {"name": "invalid_slide_name", "id": 1}}, + content_type="application/json", + ) + + assert response.status_code == 400 + + +@pytest.mark.django_db(transaction=False) +def test_project_view(client): + client.login(username="admin", password="admin") + projector = Projector.objects.get(pk=1) + projector.elements_history = [[{"name": "topics/topic", "id": 3}]] + projector.save() + + response = client.post( + reverse("projector-project", args=["1"]), + { + "append_to_history": [{"name": "topics/topic", "id": 1}], + "elements": [{"name": "topics/topic", "id": 2}], + "preview": [[{"name": "topics/topic", "id": 3}]], + }, + content_type="application/json", + ) + + projector.refresh_from_db() + assert response.status_code == 200 + assert projector.elements == [{"name": "topics/topic", "id": 2}] + assert projector.elements_history == [ + [{"name": "topics/topic", "id": 3}], + [{"name": "topics/topic", "id": 1}], + ] + assert projector.elements_preview == [[{"name": "topics/topic", "id": 3}]] class VersionView(TestCase):