From f33028892f6eea62543cf9f990676b837a40a7c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?= Date: Thu, 3 Aug 2017 12:21:37 +0200 Subject: [PATCH] Add API tests for Event/Place/ActivityTag/ActivityTemplate models This tests mainly cover cases whose API user is friendly. Should be extended with illegal things. ActivityTag, ActivityTemplate and Place models got tests for root and specific-event instance. --- api/event/tests.py | 566 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 533 insertions(+), 33 deletions(-) diff --git a/api/event/tests.py b/api/event/tests.py index 147b185..ed748e1 100644 --- a/api/event/tests.py +++ b/api/event/tests.py @@ -1,56 +1,556 @@ +from datetime import datetime, timedelta + from django.contrib.auth import get_user_model +from django.utils import timezone from rest_framework.test import APITestCase from event.models import Event, Place, ActivityTag, ActivityTemplate -from api.event.serializers import ActivityTemplateSerializer, EventSerializer -from api.testcases import EventBasedModelTestMixin, EventSpecificTestMixin,\ - ModelTestMixin +from api.test.testcases import ModelAPITestCaseMixin +from api.test.utils import json_format User = get_user_model() -class EventTest(ModelTestMixin, APITestCase): +class EventAPITests(ModelAPITestCaseMixin, APITestCase): model = Event - base_name = 'event' - tested_fields = {'title': "I'm a test", } - # Création - data_creation = 'event2_data' - # Update/Delete - instance_name = 'event1' - serializer = EventSerializer + url_label = 'event' + + list_ordering = 'beginning_date' + + @property + def user_auth_mapping(self): + return { + 'create': self.user, + } + + def get_expected_data(self, instance): + return json_format({ + 'url': ( + 'http://testserver/api/event/{pk}/' + .format(pk=instance.pk) + ), + 'id': instance.id, + 'title': instance.title, + 'slug': instance.slug, + 'description': instance.description, + 'beginning_date': instance.beginning_date, + 'ending_date': instance.ending_date, + 'created_by': instance.created_by.get_full_name(), + 'created_at': self.now, + }) + + @property + def instances_data(self): + return [ + { + 'title': "A first event", + 'slug': 'first-event', + 'description': "It's the first event.", + 'beginning_date': self.now + timedelta(days=100), + 'ending_date': self.now + timedelta(days=120), + 'created_by': self.user, + }, + { + 'title': "Another event", + 'slug': 'another-event', + 'description': "It's another event.", + 'beginning_date': self.now + timedelta(days=50), + 'ending_date': self.now + timedelta(days=60), + 'created_by': self.user, + }, + ] + + @property + def create_data(self): + return { + 'title': "An Event", + 'slug': 'event', + 'description': "I am an event.", + 'beginning_date': '2017-08-10 05:30:00', + 'ending_date': '2017-10-21 17:16:20', + } + + @property + def create_expected(self): + return { + **self.create_data, + 'beginning_date': timezone.make_aware( + datetime(2017, 8, 10, 5, 30, 0)), + 'ending_date': timezone.make_aware( + datetime(2017, 10, 21, 17, 16, 20)), + 'id': 1, + 'created_by': self.user, + 'created_at': self.now, + } + + @property + def update_data(self): + return { + 'title': "An updated event.", + 'slug': 'first-event', + 'description': "It's the first updated event.", + 'beginning_date': '2017-08-10 05:30:00', + 'ending_date': '2017-10-21 17:16:20', + 'created_by': 1, + } + + @property + def update_expected(self): + return { + **self.update_data, + 'beginning_date': timezone.make_aware( + datetime(2017, 8, 10, 5, 30, 0)), + 'ending_date': timezone.make_aware( + datetime(2017, 10, 21, 17, 16, 20)), + 'id': 1, + 'created_by': self.user, + 'created_at': self.now, + } -class ActivityTemplateTest(EventBasedModelTestMixin, APITestCase): +class ActivityTemplateAPITests(ModelAPITestCaseMixin, APITestCase): model = ActivityTemplate - base_name = 'event-activitytemplate' - initial_count = 1 - # Creation - data_creation = 'act_temp2_data' - # Update/Delete - instance_name = 'act_temp1' - field_tested = 'title' - serializer = ActivityTemplateSerializer + url_label = 'activitytemplate' - def test_create_extra(self): - self.assertEqual(self.model.objects.get(id=1).tags.count(), 1) + list_ordering = 'title' - def pre_update_extra(self, data): - data['tags'].append(self.tag2_data) + def setUp(self): + super().setUp() + + self.event = Event.objects.create(**{ + 'title': "event1", + 'slug': "slug1", + 'beginning_date': self.now + timedelta(days=30), + 'description': "C'est trop cool !", + 'ending_date': self.now + timedelta(days=31), + 'created_by': self.user, + }) + + self.activity_tag = ActivityTag.objects.create(**{ + 'name': "tag2", + 'is_public': False, + 'color': "#222", + }) + + def get_url_model(self, *args, **kwargs): + kwargs['event_pk'] = 1 + return super().get_url_model(*args, **kwargs) + + def get_url_object(self, *args, **kwargs): + kwargs['event_pk'] = 1 + return super().get_url_object(*args, **kwargs) + + def get_expected_data(self, instance): + return json_format({ + 'url': ( + 'http://testserver/api/event/{event_pk}/template/{pk}/' + .format(event_pk=instance.event.pk, pk=instance.pk) + ), + 'id': instance.id, + 'title': instance.title, + 'is_public': instance.is_public, + 'remarks': instance.remarks, + 'event': instance.event.pk, + 'tags': [ + { + **(tag.event and { + 'url': ( + 'http://testserver/api/event/{event_pk}/' + 'tag/{tag_pk}/' + .format(event_pk=tag.event.pk, tag_pk=tag.pk) + ), + 'event': tag.event.pk, + } or { + 'url': ( + 'http://testserver/api/tag/{tag_pk}/' + .format(tag_pk=tag.pk) + ), + 'event': None, + }), + 'id': tag.id, + 'name': tag.name, + 'is_public': tag.is_public, + 'color': tag.color, + } + for tag in instance.tags.all() + ], + 'has_perm': instance.has_perm, + 'min_perm': instance.min_perm, + 'max_perm': instance.max_perm, + 'description': instance.description, + }) + + @property + def instances_data(self): + return [ + { + 'title': "act temp1", + 'is_public': True, + 'remarks': "test remark", + 'event': self.event, + }, + { + 'title': "act temp2", + 'is_public': False, + 'remarks': "test remark", + 'event': self.event, + 'tags': [self.activity_tag] + }, + ] + + @property + def create_data(self): + return { + 'title': "act temp2", + 'is_public': False, + 'remarks': "test remark", + 'tags': [ + { + 'name': "tag2", + 'is_public': False, + 'color': '#222', + }, + ], + } + + @property + def create_expected(self): + return { + **self.create_data, + 'tags': [ActivityTag.objects.get(name='tag2')], + } + + @property + def update_data(self): + return { + 'title': "act temp3", + 'is_public': False, + 'remarks': "another test remark", + 'tags': [ + { + 'name': "tag2", + 'is_public': False, + 'color': '#222', + }, + { + 'name': "body", + 'is_public': True, + 'color': '#555', + }, + ], + } + + @property + def update_expected(self): + tag_root = ActivityTag.objects.get(name='tag2') + self.assertIsNone(tag_root.event) + + tag_bound = ActivityTag.objects.get(name='body') + self.assertEqual(tag_bound.event, self.event) + + return { + 'title': "act temp3", + 'is_public': False, + 'remarks': "another test remark", + 'tags': [tag_root, tag_bound] + } + + +class BaseActivityTagAPITests: + model = ActivityTag + url_label = 'activitytag' + + list_ordering = ('is_public', 'name') + + def setUp(self): + super().setUp() + + self.event = Event.objects.create(**{ + 'title': "event1", + 'slug': "slug1", + 'beginning_date': self.now + timedelta(days=30), + 'description': "C'est trop cool !", + 'ending_date': self.now + timedelta(days=31), + 'created_by': self.user, + }) + + def get_expected_data(self, instance): + return { + **(instance.event and { + 'url': ( + 'http://testserver/api/event/{event_pk}/tag/{pk}/' + .format(event_pk=instance.event.pk, pk=instance.pk) + ), + 'event': instance.event.pk, + } or { + 'url': ( + 'http://testserver/api/tag/{pk}/' + .format(pk=instance.pk) + ), + 'event': None, + }), + 'id': instance.id, + 'name': instance.name, + 'is_public': instance.is_public, + 'color': instance.color, + } + + @property + def instances_data(self): + return [ + { + 'name': 'a tag', + 'is_public': False, + 'color': '#222', + 'event': None, + }, + { + 'name': 'another tag', + 'is_public': True, + 'color': '#555', + 'event': self.event, + } + ] + + @property + def create_data(self): + return { + 'name': 'plop tag', + 'is_public': True, + 'color': '#888999', + } + + @property + def update_data(self): + return { + 'name': 'this is the tag', + 'is_public': True, + 'color': '#333', + } + + +class RootActivityTagAPITests( + BaseActivityTagAPITests, + ModelAPITestCaseMixin, + APITestCase + ): + + @property + def list_expected(self): + return [ActivityTag.objects.get(name='a tag')] + + @property + def create_expected(self): + return { + **self.create_data, + 'event': None, + } + + @property + def instance_data(self): + data = self.instances_data[0] + self.assertIsNone( + data['event'], + msg="This test should use a tag unbound to any event.", + ) return data - def post_update_extra(self, instance): - self.assertEqual(instance.tags.count(), 2) + @property + def update_expected(self): + return { + **self.update_data, + 'event': None, + } -class EventSpecficTagTest(EventSpecificTestMixin, APITestCase): - model = ActivityTag - root_base_name = 'activitytag' - event_base_name = 'event-activitytag' +class EventActivityTagAPITests( + BaseActivityTagAPITests, + ModelAPITestCaseMixin, + APITestCase + ): + + def get_url_model(self, *args, **kwargs): + kwargs['event_pk'] = 1 + return super().get_url_model(*args, **kwargs) + + def get_url_object(self, *args, **kwargs): + kwargs['event_pk'] = 1 + return super().get_url_object(*args, **kwargs) + + @property + def list_expected(self): + return [ + ActivityTag.objects.get(name='a tag'), + ActivityTag.objects.get(name='another tag'), + ] + + @property + def create_expected(self): + return { + **self.create_data, + 'event': self.event, + } + + @property + def instance_data(self): + data = self.instances_data[1] + self.assertIsNotNone( + data['event'], + msg="This test should use an event-bound tag.", + ) + return data + + @property + def update_expected(self): + return { + **self.update_data, + 'event': self.event, + } -class EventSpecficPlaceTest(EventSpecificTestMixin, APITestCase): +class BasePlaceAPITests: model = Place - root_base_name = 'place' - event_base_name = 'event-place' + url_label = 'place' + + list_ordering = 'name' + + def setUp(self): + super().setUp() + + self.event = Event.objects.create(**{ + 'title': "event1", + 'slug': "slug1", + 'beginning_date': self.now + timedelta(days=30), + 'description': "C'est trop cool !", + 'ending_date': self.now + timedelta(days=31), + 'created_by': self.user, + }) + + def get_expected_data(self, instance): + return { + **(instance.event and { + 'url': ( + 'http://testserver/api/event/{event_pk}/place/{pk}/' + .format(event_pk=instance.event.pk, pk=instance.pk) + ), + 'event': instance.event.pk, + } or { + 'url': ( + 'http://testserver/api/place/{pk}/' + .format(pk=instance.pk) + ), + 'event': None, + }), + 'id': instance.id, + 'name': instance.name, + 'description': instance.description, + } + + @property + def instances_data(self): + return [ + { + 'name': 'a place', + 'event': None, + 'description': 'a description', + }, + { + 'name': 'another place', + 'event': self.event, + } + ] + + @property + def create_data(self): + return { + 'name': 'plop place', + 'description': 'the couro is a chill place', + } + + @property + def update_data(self): + return { + 'name': 'this is the place', + 'description': 'to be', + } + + +class RootPlaceAPITests( + BasePlaceAPITests, + ModelAPITestCaseMixin, + APITestCase + ): + + @property + def list_expected(self): + return [Place.objects.get(name='a place')] + + @property + def create_expected(self): + return { + **self.create_data, + 'event': None, + } + + @property + def instance_data(self): + data = self.instances_data[0] + self.assertIsNone( + data['event'], + msg="This test should use a place unbound to any event.", + ) + return data + + @property + def update_expected(self): + return { + **self.update_data, + 'event': None, + } + + +class EventPlaceTagAPITests( + BasePlaceAPITests, + ModelAPITestCaseMixin, + APITestCase + ): + + def get_url_model(self, *args, **kwargs): + kwargs['event_pk'] = 1 + return super().get_url_model(*args, **kwargs) + + def get_url_object(self, *args, **kwargs): + kwargs['event_pk'] = 1 + return super().get_url_object(*args, **kwargs) + + @property + def list_expected(self): + return [ + Place.objects.get(name='a place'), + Place.objects.get(name='another place'), + ] + + @property + def create_expected(self): + return { + **self.create_data, + 'event': self.event, + } + + @property + def instance_data(self): + data = self.instances_data[1] + self.assertIsNotNone( + data['event'], + msg="This test should use an event-bound place.", + ) + return data + + @property + def update_expected(self): + return { + **self.update_data, + 'event': self.event, + }