diff --git a/contentcuration/contentcuration/tests/test_serializers.py b/contentcuration/contentcuration/tests/test_serializers.py index 2b71c291a6..25331a7daf 100644 --- a/contentcuration/contentcuration/tests/test_serializers.py +++ b/contentcuration/contentcuration/tests/test_serializers.py @@ -1,8 +1,8 @@ from __future__ import absolute_import -from django.core.exceptions import ValidationError from django.db.models.query import QuerySet from django.test.testcases import SimpleTestCase +from rest_framework import serializers from .base import BaseAPITestCase from contentcuration.models import Channel @@ -42,14 +42,14 @@ def test_completion_criteria__valid(self): serializer.is_valid() try: serializer.update({}, serializer.validated_data) - except ValidationError: + except serializers.ValidationError: self.fail("Completion criteria should be valid") def test_completion_criteria__invalid(self): self.data.update(completion_criteria={"model": "time", "threshold": "test"}) serializer = self.serializer serializer.is_valid() - with self.assertRaises(ValidationError): + with self.assertRaises(serializers.ValidationError): serializer.update({}, serializer.validated_data) diff --git a/contentcuration/contentcuration/tests/viewsets/test_contentnode.py b/contentcuration/contentcuration/tests/viewsets/test_contentnode.py index 74f784fdcf..ef2fb9ed4b 100644 --- a/contentcuration/contentcuration/tests/viewsets/test_contentnode.py +++ b/contentcuration/contentcuration/tests/viewsets/test_contentnode.py @@ -548,6 +548,22 @@ def test_update_contentnode(self): models.ContentNode.objects.get(id=contentnode.id).title, new_title ) + def test_cannot_update_contentnode_parent(self): + user = testdata.user() + contentnode = models.ContentNode.objects.create(**self.contentnode_db_metadata) + contentnode2 = models.ContentNode.objects.create(**self.contentnode_db_metadata) + + self.client.force_authenticate(user=user) + response = self.client.post( + self.sync_url, + [generate_update_event(contentnode.id, CONTENTNODE, {"parent": contentnode2.id})], + format="json", + ) + self.assertEqual(response.status_code, 400, response.content) + self.assertNotEqual( + models.ContentNode.objects.get(id=contentnode.id).parent_id, contentnode2.id + ) + def test_cannot_update_contentnode(self): user = testdata.user() channel = testdata.channel() @@ -742,6 +758,40 @@ def test_update_contentnode_update_options_completion_criteria_threshold_only(se self.assertEqual(c.extra_fields["options"]["completion_criteria"]["model"], completion_criteria.TIME) self.assertEqual(c.extra_fields["options"]["completion_criteria"]["threshold"], 10) + def test_update_contentnode_update_options_invalid_completion_criteria(self): + user = testdata.user() + metadata = self.contentnode_db_metadata + metadata["extra_fields"] = { + "options": { + "completion_criteria": { + "model": completion_criteria.REFERENCE, + "threshold": None, + } + }, + } + contentnode = models.ContentNode.objects.create(**metadata) + self.client.force_authenticate(user=user) + # Change extra_fields.options.completion_criteria.model + # and extra_fields.options.completion_criteria.threshold + response = self.client.post( + self.sync_url, + [ + generate_update_event( + contentnode.id, + CONTENTNODE, + { + "extra_fields.options.completion_criteria.model": completion_criteria.TIME, + } + ) + ], + format="json", + ) + self.assertEqual(response.status_code, 400, response.content) + c = models.ContentNode.objects.get(id=contentnode.id) + + self.assertEqual(c.extra_fields["options"]["completion_criteria"]["model"], completion_criteria.REFERENCE) + self.assertEqual(c.extra_fields["options"]["completion_criteria"]["threshold"], None) + def test_update_contentnode_add_multiple_metadata_labels(self): user = testdata.user() diff --git a/contentcuration/contentcuration/viewsets/contentnode.py b/contentcuration/contentcuration/viewsets/contentnode.py index 79676716a5..c7bb2e222a 100644 --- a/contentcuration/contentcuration/viewsets/contentnode.py +++ b/contentcuration/contentcuration/viewsets/contentnode.py @@ -3,6 +3,7 @@ from functools import reduce from django.conf import settings +from django.core.exceptions import ValidationError as DjangoValidationError from django.db import IntegrityError from django.db import models from django.db.models import Exists @@ -273,7 +274,10 @@ class CompletionCriteriaSerializer(JSONFieldDictSerializer): def update(self, instance, validated_data): instance = super(CompletionCriteriaSerializer, self).update(instance, validated_data) - completion_criteria_validator.validate(instance) + try: + completion_criteria_validator.validate(instance) + except DjangoValidationError as e: + raise ValidationError(e) return instance