282 lines
11 KiB
Python
282 lines
11 KiB
Python
from datetime import timedelta
|
|
from django.contrib.auth import get_user_model
|
|
from django.db.models import Q
|
|
from django.utils import timezone
|
|
from django.urls import reverse
|
|
|
|
from rest_framework.test import APIRequestFactory
|
|
from rest_framework import status
|
|
|
|
from event.models import Event, Place, ActivityTag, ActivityTemplate
|
|
|
|
|
|
User = get_user_model()
|
|
|
|
|
|
class DataBaseMixin(object):
|
|
"""
|
|
provides a datatabse for API tests
|
|
"""
|
|
@classmethod
|
|
def setUpTestData(cls):
|
|
# Users
|
|
cls.user1_data = {'username': "user1", 'password': "pass1"}
|
|
cls.user1 = User.objects.create_user(**cls.user1_data)
|
|
|
|
def setUp(self):
|
|
# Events
|
|
self.event1_data = {'title': "event1", 'slug': "slug1",
|
|
'beginning_date': timezone.now()
|
|
+ timedelta(days=30),
|
|
"description": "C'est trop cool !",
|
|
'ending_date': timezone.now()+timedelta(days=31),
|
|
'created_by': self.user1, }
|
|
self.event2_data = {"title": "test event", "slug": "test-event",
|
|
"description": "C'est trop cool !",
|
|
"beginning_date": "2017-07-18T18:05:00Z",
|
|
"ending_date": "2017-07-19T18:05:00Z", }
|
|
self.event1 = Event.objects.create(**self.event1_data)
|
|
|
|
# ActivityTags
|
|
self.tag1_data = {"name": "tag1", "is_public": False, "color": "#111"}
|
|
self.tag2_data = {"name": "tag2", "is_public": False, "color": "#222"}
|
|
self.tag3_data = {"name": "tag3", "is_public": False, "color": "#333"}
|
|
self.tag1 = ActivityTag.objects.create(**self.tag1_data)
|
|
|
|
self.act_temp1_data = {'title': "act temp1", 'is_public': True,
|
|
'remarks': "test remark", 'event': self.event1}
|
|
self.act_temp2_data = {'title': "act temp2", 'is_public': False,
|
|
'remarks': "test remark",
|
|
'tags': [self.tag2_data, ]}
|
|
self.act_temp1 = ActivityTemplate.objects.create(**self.act_temp1_data)
|
|
self.act_temp1.tags.add(self.tag1)
|
|
|
|
|
|
class EventBasedModelTestMixin(DataBaseMixin):
|
|
"""
|
|
Note : need to define : `model`, `base_name`, `initial_count`,
|
|
`data_creation`, `instance_name`, `field_tested`, `serializer`
|
|
|
|
tests for models served by the API that are related to an event
|
|
and whose API urls are nested under ../event/<event_id>/%model
|
|
"""
|
|
def user_create_extra(self):
|
|
"""
|
|
extra test in creation by a permited user
|
|
"""
|
|
pass
|
|
|
|
def pre_update_extra(self, data):
|
|
"""
|
|
extra modification for the data sent for update
|
|
"""
|
|
return data
|
|
|
|
def post_update_extra(self):
|
|
"""
|
|
extra test for updated model
|
|
"""
|
|
pass
|
|
|
|
def test_user_create(self):
|
|
"""
|
|
ensure a permited user can create a new %model object using API
|
|
"""
|
|
data = getattr(self, self.data_creation)
|
|
|
|
event_id = self.event1.id
|
|
url = reverse('{base_name}-list'.format(base_name=self.base_name),
|
|
kwargs={'event_pk': event_id})
|
|
self.client.force_authenticate(user=self.user1)
|
|
response = self.client.post(url, data,
|
|
format='json')
|
|
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
|
self.assertEqual(self.model.objects.count(), self.initial_count + 1)
|
|
self.assertEqual(self.model.objects.get(id=self.initial_count+1).event,
|
|
self.event1)
|
|
|
|
self.user_create_extra()
|
|
|
|
def test_user_update(self):
|
|
"""
|
|
ensure a permited user can update a new %model object using API
|
|
"""
|
|
instance = getattr(self, self.instance_name)
|
|
factory = APIRequestFactory()
|
|
|
|
instance_id = instance.id
|
|
event_id = self.event1.id
|
|
url = reverse('{base_name}-list'.format(base_name=self.base_name),
|
|
kwargs={'event_pk': event_id})
|
|
url = "%s%d/" % (url, instance_id)
|
|
|
|
request = factory.get(url)
|
|
data = self.serializer(instance, context={'request': request}).data
|
|
|
|
newvalue = "I'm a test"
|
|
data[self.field_tested] = newvalue
|
|
|
|
data = self.pre_update_extra(data)
|
|
|
|
self.client.force_authenticate(user=self.user1)
|
|
response = self.client.patch(url, data, format='json')
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
|
|
instance.refresh_from_db()
|
|
self.assertEqual(getattr(instance, self.field_tested), newvalue)
|
|
|
|
self.post_update_extra(instance)
|
|
|
|
def test_user_delete(self):
|
|
"""
|
|
ensure a permited user can delete a new %model object using API
|
|
"""
|
|
instance = getattr(self, self.instance_name)
|
|
|
|
instance_id = instance.id
|
|
event_id = self.event1.id
|
|
url = reverse('{base_name}-list'.format(base_name=self.base_name),
|
|
kwargs={'event_pk': event_id})
|
|
url = "%s%d/" % (url, instance_id)
|
|
|
|
self.client.force_authenticate(user=self.user1)
|
|
response = self.client.delete(url)
|
|
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
|
|
self.assertEqual(self.model.objects.count(), self.initial_count - 1)
|
|
|
|
|
|
# TODO rajouter la gestion des permissions dans le Mixin
|
|
# TODO rajouter un test pour s'assurer que les personnes non
|
|
# connectées ne peuvent pas create/update/delete
|
|
class EventSpecificTestMixin(object):
|
|
"""
|
|
Tests is the EventSpecifics querysets are rendered correctly
|
|
using the API
|
|
Note : need to define : `model`, `root_base_name` and `event_base_name`
|
|
|
|
tests for models served by the API that inherit EventSpecificMixin
|
|
"""
|
|
@classmethod
|
|
def setUpTestData(cls):
|
|
# Users
|
|
cls.user1_data = {'username': "user1", 'password': "pass1"}
|
|
cls.user1 = User.objects.create_user(**cls.user1_data)
|
|
# Events
|
|
cls.event1_data = {'title': "event1", 'slug': "slug1",
|
|
'beginning_date': timezone.now()
|
|
+ timedelta(days=30),
|
|
'ending_date': timezone.now()+timedelta(days=31),
|
|
'created_by': cls.user1, }
|
|
cls.event1 = Event.objects.create(**cls.event1_data)
|
|
|
|
def setUp(self):
|
|
# Tag
|
|
self.tag_root_data = {"name": "tag2", "is_public": False,
|
|
"color": "#222"}
|
|
self.tag_event_data = {"name": "tag3", "is_public": False,
|
|
"color": "#333", 'event': self.event1}
|
|
self.tag_root = ActivityTag.objects.create(**self.tag_root_data)
|
|
self.tag_event = ActivityTag.objects.create(**self.tag_event_data)
|
|
|
|
# Places
|
|
self.place_root_data = {'name': "place1", 'event': None, }
|
|
self.place_event_data = {'name': "place2", 'event': self.event1, }
|
|
self.place_root = Place.objects.create(**self.place_root_data)
|
|
self.place_event = Place.objects.create(**self.place_event_data)
|
|
|
|
def test_lists(self):
|
|
"""
|
|
ensure that only root-level models are served under
|
|
api/%root_base_name/
|
|
and that root-level and event-level models are served under
|
|
api/event/<event_id>/%event_base_name/
|
|
"""
|
|
event_id = self.event1.id
|
|
root_count = self.model.objects.filter(event=None).count()
|
|
event_count = (self.model.objects
|
|
.filter(Q(event=self.event1) | Q(event=None)).count())
|
|
|
|
self.client.force_authenticate(user=self.user1)
|
|
|
|
url = reverse('{base}-list'.format(base=self.root_base_name))
|
|
response = self.client.get(url, format='json')
|
|
self.assertEqual(response.json()['count'], root_count)
|
|
|
|
event_id = self.event1.id
|
|
url = reverse('{base}-list'.format(base=self.event_base_name),
|
|
kwargs={'event_pk': event_id})
|
|
response = self.client.get(url, format='json')
|
|
self.assertEqual(response.json()['count'], event_count)
|
|
|
|
|
|
# TODO rajouter la gestion des permissions dans le Mixin
|
|
# TODO rajouter un test pour s'assurer que les personnes non
|
|
# connectées ne peuvent pas create/update/delete
|
|
# TODO? essayer de factoriser avec EventBasedMixin ?
|
|
# FIXME not working, peut être que le problème vient
|
|
# du fait que les dates sont mal envoyées dans le data ? A voir.
|
|
class ModelTestMixin(DataBaseMixin):
|
|
"""
|
|
Note : need to define : `model`, `base_name`,
|
|
`instance_name`, `field_tested`, `serializer`
|
|
|
|
generic mixin for testing creation/update/delete
|
|
of models served by the API
|
|
"""
|
|
def test_user_create(self):
|
|
"""
|
|
ensure a permited user can create a new %model object using API
|
|
"""
|
|
data = getattr(self, self.data_creation)
|
|
initial_count = self.model.objects.count()
|
|
|
|
url = reverse('{base_name}-list'.format(base_name=self.base_name))
|
|
self.client.force_authenticate(user=self.user1)
|
|
response = self.client.post(url, data)
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
|
self.assertEqual(self.model.objects.count(), initial_count + 1)
|
|
|
|
instance = self.model.objects.get(id=initial_count+1)
|
|
for field in self.tested_fields.keys():
|
|
self.assertEqual(getattr(instance, field), data[field])
|
|
|
|
def test_user_update(self):
|
|
"""
|
|
ensure a permited user can update a new %model object using API
|
|
"""
|
|
instance = getattr(self, self.instance_name)
|
|
factory = APIRequestFactory()
|
|
|
|
instance_id = instance.id
|
|
url = reverse('{base_name}-detail'.format(base_name=self.base_name),
|
|
kwargs={'pk': instance_id})
|
|
|
|
request = factory.get(url)
|
|
data = self.serializer(instance, context={'request': request}).data
|
|
for field, value in self.tested_fields.items():
|
|
data[field] = value
|
|
|
|
self.client.force_authenticate(user=self.user1)
|
|
response = self.client.put(url, data, format='json')
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
|
|
instance.refresh_from_db()
|
|
for field, value in self.tested_fields.items():
|
|
self.assertEqual(getattr(instance, field), value)
|
|
|
|
def test_user_delete(self):
|
|
"""
|
|
ensure a permited user can delete a new %model object using API
|
|
"""
|
|
instance = getattr(self, self.instance_name)
|
|
initial_count = self.model.objects.count()
|
|
|
|
instance_id = instance.id
|
|
url = reverse('{base_name}-detail'.format(base_name=self.base_name),
|
|
kwargs={'pk': instance_id})
|
|
|
|
self.client.force_authenticate(user=self.user1)
|
|
response = self.client.delete(url)
|
|
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
|
|
self.assertEqual(self.model.objects.count(), initial_count - 1)
|