diff --git a/src/core/fixtures/anhalter.json b/src/core/fixtures/anhalter.json index 2d1840f5cf031ad8fee2864762e77a99d15312e7..4b2e4914e16b37045f4948a51633d2353280de81 100644 --- a/src/core/fixtures/anhalter.json +++ b/src/core/fixtures/anhalter.json @@ -74,6 +74,28 @@ "model": "core.conferencetag", "pk": 3 }, + { + "fields": { + "conference": "017c0749-a2ea-4f86-92cd-e60b4508dd98", + "slug": "guter Geschmack", + "value_type": "boolean", + "is_public": true, + "description": null + }, + "model": "core.conferencetag", + "pk": 4 + }, + { + "fields": { + "conference": "017c0749-a2ea-4f86-92cd-e60b4508dd98", + "slug": "Autor des besten Gedichts", + "value_type": "string", + "is_public": true, + "description": null + }, + "model": "core.conferencetag", + "pk": 5 + }, { "fields": { "conference": "017c0749-a2ea-4f86-92cd-e60b4508dd98", @@ -164,4 +186,4 @@ "model": "core.event", "pk": "35e10dfc-11c2-475b-b682-da1ddd291770" } -] \ No newline at end of file +] diff --git a/src/core/models/tags.py b/src/core/models/tags.py index 96368d7c2a7779c9384a83f48edab681b3c7bbab..c2d7272009ea5c91966e103302845d2cbaddf0b7 100644 --- a/src/core/models/tags.py +++ b/src/core/models/tags.py @@ -66,7 +66,7 @@ class TagItem(models.Model): return self._value_int == 0 @value.setter - def _set_value(self, new_value): + def value(self, new_value): self.set_value(new_value) def set_value(self, new_value): diff --git a/src/core/tests/tags.py b/src/core/tests/tags.py index 30f196a3239ddf2bf9c0393af87b65a7447451d4..cad9f4da24b0379bb336f4548c8b7a7f8dd51536 100644 --- a/src/core/tests/tags.py +++ b/src/core/tests/tags.py @@ -1,10 +1,11 @@ from django.contrib.auth.models import AnonymousUser +from django.contrib.contenttypes.models import ContentType from django.test import TestCase from ..models.assemblies import Assembly from ..models.conference import Conference from ..models.events import Event -from ..models.tags import ConferenceTag, TaggedItemMixin +from ..models.tags import ConferenceTag, TaggedItemMixin, TagItem class TaggingTests(TestCase): @@ -90,3 +91,127 @@ class TaggingTests(TestCase): def testAssemblyTagging(self): assembly = Assembly.objects.filter(conference=self.conference).first() self._testTagManagement(assembly) + + +class TagItemTests(TestCase): + fixtures = ['anhalter.json'] + + def setUp(self): + self.conference = Conference.objects.get(slug='vogc') + self.user = AnonymousUser() + self.event = Event.objects.filter(conference=self.conference).first() + self.tag_items = self._createTagItems() + + def _createTagItem(self, tag_slug:str) -> TagItem: + tag = ConferenceTag.objects.get(conference=self.conference, slug=tag_slug) + return TagItem(tag=tag, target_type=ContentType.objects.get_for_model(type(self.event)), target_id=self.event.id) + + def _createTagItems(self): + result = {} + for tag_slug in ['foo', 'bar', 'michelinstars', 'guter Geschmack', 'Autor des besten Gedichts']: + result[tag_slug] = self._createTagItem(tag_slug) + + return result + + def _validate_value_type(self, tag_item: TagItem): + value_type = tag_item.tag.value_type + value = tag_item.value + if value is None: + return + if value_type == ConferenceTag.Type.SIMPLE: + self.fail("Simple tag item did not return None as value") + if value_type == ConferenceTag.Type.STRING: + self.assertTrue(isinstance(value, str), "String tag item did not return None or a string as value") + if value_type == ConferenceTag.Type.INT: + self.assertTrue(isinstance(value, int), "Int tag item did not return None or an int as value") + if value_type == ConferenceTag.Type.BOOL: + self.assertTrue(isinstance(value, bool), "Bool tag item did not return None or a bool as value") + + def test_get_value_check_type_uninitialized(self): + for tag_item in self.tag_items.values(): + self._validate_value_type(tag_item) + + def test_get_value_check_type_after_set(self): + for tag_item in self.tag_items.values(): + value_type = tag_item.tag.value_type + if value_type == ConferenceTag.Type.STRING: + tag_item.value = "Test" + if value_type == ConferenceTag.Type.INT: + tag_item.value = 42 + if value_type == ConferenceTag.Type.BOOL: + tag_item.value = True + self._validate_value_type(tag_item) + + def test_value_check_get_after_set_intended(self): + for tag_item in self.tag_items.values(): + value_type = tag_item.tag.value_type + value = None + if value_type == ConferenceTag.Type.STRING: + value = "Test" + if value_type == ConferenceTag.Type.INT: + value = 42 + if value_type == ConferenceTag.Type.BOOL: + value = True + tag_item.value = value + self.assertEqual(tag_item.value, value) + + def test_value_check_boolean_coerce(self): + tag = self.tag_items["guter Geschmack"] + for v in [False, 0, 'n', 'no', 'nein', 'false', 'off']: + tag.value = True + self.assertTrue(tag.value) + tag.value = v + self.assertFalse(tag.value, "Value {} did not yield false".format(v)) + + for v in [True, -2, -1, 1, 2, 3, 'y', 'j', 'yes', 'ja', 'true', 'on']: + tag.value = False + self.assertFalse(tag.value) + tag.value = v + self.assertTrue(tag.value, "Value {} did not yield true".format(v)) + + def test_value_set_check_simple_with_wrong_argument(self): + tag = self.tag_items["foo"] + with self.assertRaises(ValueError): + tag.value = self.user + with self.assertRaises(ValueError): + tag.value = "Test" + with self.assertRaises(ValueError): + tag.value = 42 + with self.assertRaises(ValueError): + tag.value = True + + def test_value_set_check_string_with_wrong_argument(self): + tag = self.tag_items["Autor des besten Gedichts"] + with self.assertRaises(ValueError): + tag.value = None + with self.assertRaises(ValueError): + tag.value = self.user + with self.assertRaises(ValueError): + tag.value = 42 + with self.assertRaises(ValueError): + tag.value = True + + def test_value_set_check_int_with_wrong_argument(self): + tag = self.tag_items["michelinstars"] + with self.assertRaises(ValueError): + tag.value = None + with self.assertRaises(ValueError): + tag.value = self.user + with self.assertRaises(ValueError): + tag.value = "Test" + # Python coerces bool to int by itself + + def test_value_set_check_bool_with_wrong_argument(self): + tag = self.tag_items["guter Geschmack"] + with self.assertRaises(ValueError): + tag.value = None + with self.assertRaises(ValueError): + tag.value = self.user + with self.assertRaises(ValueError): + tag.value = "Test" + with self.assertRaises(ValueError): + tag.value = "foo" + with self.assertRaises(ValueError): + tag.value = "" + with self.assertRaises(ValueError): + tag.value = "bar"