2015-10-20 09:16:58 +00:00
|
|
|
|
# -*- coding: utf-8
|
2015-10-20 14:26:25 +00:00
|
|
|
|
"""
|
|
|
|
|
Test cases for API calls
|
|
|
|
|
"""
|
|
|
|
|
|
2015-01-22 15:22:57 +00:00
|
|
|
|
from django.conf import settings
|
2015-10-20 15:13:07 +00:00
|
|
|
|
from django.contrib.auth.models import User
|
|
|
|
|
from django.core.exceptions import ImproperlyConfigured
|
2015-10-21 09:46:45 +00:00
|
|
|
|
from django.test import TestCase, RequestFactory
|
2015-10-19 13:04:15 +00:00
|
|
|
|
from django_webtest import WebTest
|
2014-12-23 08:56:04 +00:00
|
|
|
|
|
2015-01-22 15:22:57 +00:00
|
|
|
|
import json
|
|
|
|
|
|
2015-10-20 15:13:07 +00:00
|
|
|
|
from .serializers import NamespacedSerializer
|
2015-01-22 15:22:57 +00:00
|
|
|
|
from booking.ducklevel import level_to_up_minutes
|
2014-12-23 08:56:04 +00:00
|
|
|
|
from booking.models import Species, Location, Duck, Competence, DuckCompetence
|
2015-01-05 15:12:33 +00:00
|
|
|
|
|
2015-10-20 15:13:07 +00:00
|
|
|
|
class MetalessNamespacedSerializer(NamespacedSerializer):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
class MissingNamespacedSerializer(NamespacedSerializer):
|
|
|
|
|
class Meta:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
class NoneNamespacedSerializer(NamespacedSerializer):
|
|
|
|
|
class Meta:
|
|
|
|
|
url_namespace = None
|
|
|
|
|
|
|
|
|
|
class EmptyNamespacedSerializer(NamespacedSerializer):
|
|
|
|
|
class Meta:
|
|
|
|
|
url_namespace = ''
|
|
|
|
|
|
|
|
|
|
class TestNamespacedSerializer(TestCase):
|
|
|
|
|
"""
|
|
|
|
|
Test namespaced Serializer
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
def test_no_namespace(self):
|
|
|
|
|
with self.assertRaises(ImproperlyConfigured):
|
|
|
|
|
serializer = MetalessNamespacedSerializer()
|
|
|
|
|
|
|
|
|
|
with self.assertRaises(ImproperlyConfigured):
|
|
|
|
|
serializer = MissingNamespacedSerializer()
|
|
|
|
|
|
|
|
|
|
with self.assertRaises(ImproperlyConfigured):
|
|
|
|
|
serializer = NoneNamespacedSerializer()
|
|
|
|
|
|
|
|
|
|
with self.assertRaises(ImproperlyConfigured):
|
|
|
|
|
serializer = EmptyNamespacedSerializer()
|
|
|
|
|
|
2015-10-21 09:46:45 +00:00
|
|
|
|
def test_namespacing(self):
|
|
|
|
|
class MySerializer(NamespacedSerializer):
|
|
|
|
|
class Meta:
|
|
|
|
|
model = Competence
|
|
|
|
|
fields = ('url',)
|
|
|
|
|
url_namespace = 'api'
|
|
|
|
|
|
|
|
|
|
competence = Competence.objects.create(
|
|
|
|
|
added_by=User.objects.create())
|
|
|
|
|
serializer = MySerializer(competence,
|
|
|
|
|
context={
|
|
|
|
|
'request': RequestFactory().get('/')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
self.assertIsNotNone(serializer.data['url'])
|
|
|
|
|
|
2015-10-19 13:04:15 +00:00
|
|
|
|
class DuckClassTest(WebTest):
|
2015-10-20 14:26:25 +00:00
|
|
|
|
"""
|
|
|
|
|
Test case for duck related API calls
|
|
|
|
|
"""
|
|
|
|
|
|
2015-10-19 13:04:15 +00:00
|
|
|
|
csrf_checks = False
|
2015-01-22 15:22:57 +00:00
|
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
|
good_minutes = level_to_up_minutes(settings.COMP_WARN_LEVEL + 1)
|
|
|
|
|
bad_minutes = level_to_up_minutes(settings.COMP_WARN_LEVEL)
|
|
|
|
|
|
2015-10-19 13:04:15 +00:00
|
|
|
|
self.user = User.objects.create_user(username='test',
|
|
|
|
|
password='test')
|
2015-01-22 15:22:57 +00:00
|
|
|
|
|
2015-10-21 13:04:53 +00:00
|
|
|
|
self.species = Species.objects.create(name='duck')
|
|
|
|
|
self.location = Location.objects.create(name='temp')
|
2015-10-20 09:16:58 +00:00
|
|
|
|
self.comp_bad = Competence.objects.create(name='test1',
|
|
|
|
|
added_by=self.user)
|
|
|
|
|
self.comp_good = Competence.objects.create(name='test2',
|
|
|
|
|
added_by=self.user)
|
2015-10-21 13:04:53 +00:00
|
|
|
|
self.duck = Duck.objects.create(species=self.species,
|
2015-10-19 15:08:44 +00:00
|
|
|
|
name='test duck',
|
2015-10-21 13:04:53 +00:00
|
|
|
|
location=self.location,
|
2015-10-20 09:16:58 +00:00
|
|
|
|
donated_by=self.user,
|
2015-10-19 15:08:44 +00:00
|
|
|
|
color='123456')
|
2015-01-22 15:22:57 +00:00
|
|
|
|
|
2015-10-20 09:16:58 +00:00
|
|
|
|
DuckCompetence.objects.create(duck=self.duck,
|
|
|
|
|
comp=self.comp_bad,
|
|
|
|
|
up_minutes=bad_minutes,
|
|
|
|
|
down_minutes=0)
|
2015-01-22 15:22:57 +00:00
|
|
|
|
|
2015-10-20 09:16:58 +00:00
|
|
|
|
DuckCompetence.objects.create(duck=self.duck,
|
|
|
|
|
comp=self.comp_good,
|
|
|
|
|
up_minutes=good_minutes,
|
|
|
|
|
down_minutes=0)
|
2015-01-22 15:22:57 +00:00
|
|
|
|
|
|
|
|
|
def test_book_nonlogged(self):
|
2015-10-20 14:26:25 +00:00
|
|
|
|
"""
|
|
|
|
|
Test booking without logging in
|
|
|
|
|
"""
|
|
|
|
|
|
2015-10-19 13:04:15 +00:00
|
|
|
|
page = self.app.post('/api/v1/ducks/1/book/', expect_errors=True)
|
|
|
|
|
self.assertEqual(page.status_code, 403)
|
2015-01-22 15:22:57 +00:00
|
|
|
|
|
|
|
|
|
def test_book_nonexist(self):
|
2015-10-20 14:26:25 +00:00
|
|
|
|
"""
|
|
|
|
|
Test booking a non-existing duck
|
|
|
|
|
"""
|
|
|
|
|
|
2015-10-19 13:04:15 +00:00
|
|
|
|
# Try to book a non-existing duck
|
|
|
|
|
page = self.app.post(
|
|
|
|
|
'/api/v1/ducks/9999/book/',
|
|
|
|
|
params={
|
|
|
|
|
'competence': self.comp_good.pk,
|
|
|
|
|
},
|
|
|
|
|
user=self.user,
|
|
|
|
|
expect_errors=True)
|
|
|
|
|
self.assertEqual(404, page.status_code)
|
2015-01-22 15:22:57 +00:00
|
|
|
|
|
|
|
|
|
# Try to book an existing Duck for a non-existing competence
|
2015-10-19 13:04:15 +00:00
|
|
|
|
page = self.app.post(
|
|
|
|
|
'/api/v1/ducks/%d/book/' % self.duck.pk,
|
|
|
|
|
params={
|
|
|
|
|
'competence': 9999
|
|
|
|
|
},
|
|
|
|
|
user=self.user,
|
|
|
|
|
expect_errors=True)
|
|
|
|
|
self.assertEqual(404, page.status_code)
|
2015-01-22 15:22:57 +00:00
|
|
|
|
|
|
|
|
|
def test_book_warn(self):
|
2015-10-20 14:26:25 +00:00
|
|
|
|
"""
|
|
|
|
|
Test duck booking for a competence the duck is not good at
|
|
|
|
|
"""
|
|
|
|
|
|
2015-10-20 09:16:58 +00:00
|
|
|
|
url = '/api/v1/ducks/%d/book/' % self.duck.pk
|
|
|
|
|
comp_none = Competence.objects.create(name='test3',
|
|
|
|
|
added_by=self.user)
|
|
|
|
|
|
|
|
|
|
# Book for a competence the duck doesn’t have at all
|
|
|
|
|
test_data = {
|
|
|
|
|
'competence': comp_none.pk,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
page = self.app.post(url, params=test_data, user=self.user)
|
|
|
|
|
self.assertEquals(200, page.status_code)
|
|
|
|
|
|
|
|
|
|
page_json = json.loads(page.content)
|
|
|
|
|
self.assertEquals(page_json['status'], 'bad-comp')
|
|
|
|
|
|
|
|
|
|
# Book for a competence with low level
|
2015-01-22 15:22:57 +00:00
|
|
|
|
test_data = {
|
2015-10-19 13:04:15 +00:00
|
|
|
|
'competence': self.comp_bad.pk,
|
2015-01-22 15:22:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-10-19 13:04:15 +00:00
|
|
|
|
page = self.app.post(url, params=test_data, user=self.user)
|
|
|
|
|
self.assertEquals(200, page.status_code)
|
2015-01-22 15:22:57 +00:00
|
|
|
|
|
2015-10-19 13:04:15 +00:00
|
|
|
|
page_json = json.loads(page.content)
|
|
|
|
|
self.assertEquals(page_json['status'], 'bad-comp')
|
2015-01-22 15:22:57 +00:00
|
|
|
|
|
2015-10-20 09:16:58 +00:00
|
|
|
|
# Forcibly book for a competence with low level
|
2015-01-22 15:22:57 +00:00
|
|
|
|
test_data['force'] = 1
|
|
|
|
|
|
2015-10-19 13:04:15 +00:00
|
|
|
|
page = self.app.post(url, params=test_data, user=self.user)
|
|
|
|
|
self.assertEqual(200, page.status_code)
|
2015-01-22 15:22:57 +00:00
|
|
|
|
|
2015-10-19 13:04:15 +00:00
|
|
|
|
page_json = json.loads(page.content)
|
|
|
|
|
self.assertEquals(page_json['status'], 'ok')
|
2015-01-22 15:22:57 +00:00
|
|
|
|
|
|
|
|
|
def test_book_good(self):
|
2015-10-20 14:26:25 +00:00
|
|
|
|
"""
|
|
|
|
|
Test duck booking for a competence the duck is good at
|
|
|
|
|
"""
|
|
|
|
|
|
2015-01-22 15:22:57 +00:00
|
|
|
|
test_data = {
|
2015-10-19 13:04:15 +00:00
|
|
|
|
"competence": self.comp_good.pk
|
2015-01-22 15:22:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-10-19 13:04:15 +00:00
|
|
|
|
url = '/api/v1/ducks/%d/book/' % self.duck.pk
|
2015-01-22 15:22:57 +00:00
|
|
|
|
# Book the duck
|
2015-10-19 13:04:15 +00:00
|
|
|
|
page = self.app.post(url, params=test_data, user=self.user)
|
|
|
|
|
self.assertEquals(200, page.status_code)
|
2015-01-22 15:22:57 +00:00
|
|
|
|
|
2015-10-19 13:04:15 +00:00
|
|
|
|
page_json = json.loads(page.content)
|
|
|
|
|
self.assertEqual(page_json['status'], 'ok')
|
2015-01-22 15:22:57 +00:00
|
|
|
|
|
|
|
|
|
# Try to book again, it should fail
|
2015-10-19 13:04:15 +00:00
|
|
|
|
page = self.app.post(url, params=test_data, user=self.user)
|
|
|
|
|
self.assertEqual(200, page.status_code)
|
|
|
|
|
|
|
|
|
|
page_json = json.loads(page.content)
|
|
|
|
|
self.assertEqual('already-booked', page_json['status'])
|
|
|
|
|
|
2015-10-21 13:04:53 +00:00
|
|
|
|
def test_incomplete_donation(self):
|
|
|
|
|
"""
|
|
|
|
|
Test duck donation with incomplete data
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
params = {
|
|
|
|
|
# No parameters
|
|
|
|
|
'none': '',
|
|
|
|
|
# Empty parameter set
|
|
|
|
|
'empty': {},
|
|
|
|
|
# Species omitted
|
|
|
|
|
'species-omit': {
|
|
|
|
|
'location': self.location.pk,
|
|
|
|
|
'color': '123456',
|
|
|
|
|
},
|
|
|
|
|
# Missing species
|
|
|
|
|
'species-notfound': {
|
|
|
|
|
'location': self.location.pk,
|
|
|
|
|
'species': 9999,
|
|
|
|
|
'color': '123456',
|
|
|
|
|
'expected-code': 404,
|
|
|
|
|
'expected-error': 'bad-species',
|
|
|
|
|
},
|
|
|
|
|
# Location omitted
|
|
|
|
|
'location-omit': {
|
|
|
|
|
'species': self.species.pk,
|
|
|
|
|
'color': '123456',
|
|
|
|
|
},
|
|
|
|
|
# Missing location
|
|
|
|
|
'location-notfound': {
|
|
|
|
|
'location': 9999,
|
|
|
|
|
'species': self.species.pk,
|
|
|
|
|
'color': '123456',
|
|
|
|
|
'expected-code': 404,
|
|
|
|
|
'expected-error': 'bad-location',
|
|
|
|
|
},
|
|
|
|
|
# Color omitted
|
|
|
|
|
'color-omit': {
|
|
|
|
|
'location': self.location.pk,
|
|
|
|
|
'species': self.species.pk,
|
|
|
|
|
},
|
|
|
|
|
# Invalid color
|
|
|
|
|
'color-invalid': {
|
|
|
|
|
'location': self.location.pk,
|
|
|
|
|
'species': self.species.pk,
|
|
|
|
|
'color': 'red',
|
|
|
|
|
'expected-error': 'bad-color',
|
|
|
|
|
'expected-code': 400,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
url = '/api/v1/ducks/donate/'
|
|
|
|
|
|
|
|
|
|
for name, param in params.items():
|
|
|
|
|
if param == '':
|
|
|
|
|
expected_code = 400
|
|
|
|
|
expected_error = 'incomplete-request'
|
|
|
|
|
else:
|
|
|
|
|
expected_code = param.pop('expected-code', 400)
|
|
|
|
|
expected_error = param.pop('expected-error',
|
|
|
|
|
'incomplete-request')
|
|
|
|
|
|
|
|
|
|
page = self.app.post(url,
|
|
|
|
|
params=param,
|
|
|
|
|
expect_errors=True,
|
|
|
|
|
user=self.user)
|
|
|
|
|
|
|
|
|
|
self.assertEquals(
|
|
|
|
|
expected_code,
|
|
|
|
|
page.status_code,
|
|
|
|
|
msg="Got unexpected status code ({}) for parameter set {}".format(
|
|
|
|
|
page.status_code,
|
|
|
|
|
name))
|
|
|
|
|
page_json = json.loads(page.content)
|
|
|
|
|
|
|
|
|
|
self.assertEquals(
|
|
|
|
|
expected_error,
|
|
|
|
|
page_json['status'],
|
|
|
|
|
msg="Got unexpected status code ({}) for parameter set {}".format(
|
|
|
|
|
page.status_code,
|
|
|
|
|
name))
|
|
|
|
|
|
2015-10-19 13:04:15 +00:00
|
|
|
|
def test_duck_donation(self):
|
2015-10-20 14:26:25 +00:00
|
|
|
|
"""
|
|
|
|
|
Test duck donating functionality
|
|
|
|
|
"""
|
|
|
|
|
|
2015-10-19 13:04:15 +00:00
|
|
|
|
# Duck donation should not be allowed without logging in
|
|
|
|
|
page = self.app.get('/api/v1/ducks/donate/', expect_errors=True)
|
|
|
|
|
self.assertEquals(page.status_code, 403)
|
|
|
|
|
|
|
|
|
|
# Duck donation should not be allowed withoud logging in
|
|
|
|
|
page = self.app.post('/api/v1/ducks/donate/', expect_errors=True)
|
|
|
|
|
self.assertEquals(page.status_code, 403)
|
|
|
|
|
|
2015-10-21 13:04:53 +00:00
|
|
|
|
color = '123456'
|
|
|
|
|
page = self.app.post(
|
2015-10-19 13:04:15 +00:00
|
|
|
|
'/api/v1/ducks/donate/',
|
|
|
|
|
params={
|
2015-10-21 13:04:53 +00:00
|
|
|
|
'species': self.species.pk,
|
|
|
|
|
'location': self.location.pk,
|
|
|
|
|
'color': color,
|
2015-10-19 13:04:15 +00:00
|
|
|
|
},
|
|
|
|
|
user=self.user)
|
2015-10-21 13:04:53 +00:00
|
|
|
|
self.assertEquals(200, page.status_code)
|
|
|
|
|
page_json = json.loads(page.content)
|
|
|
|
|
|
|
|
|
|
self.assertIn('id', page_json)
|
|
|
|
|
|
|
|
|
|
duck = Duck.objects.get(pk=page_json['id'])
|
|
|
|
|
|
|
|
|
|
self.assertEquals(color, duck.color)
|
2015-10-19 13:04:15 +00:00
|
|
|
|
|
|
|
|
|
def test_duck_details(self):
|
2015-10-20 14:26:25 +00:00
|
|
|
|
"""
|
|
|
|
|
Test duck details view
|
|
|
|
|
"""
|
|
|
|
|
|
2015-10-19 13:04:15 +00:00
|
|
|
|
url = '/api/v1/ducks/%d/' % self.duck.pk
|
|
|
|
|
page = self.app.get(url)
|
|
|
|
|
self.assertEqual(200, page.status_code)
|
|
|
|
|
|
|
|
|
|
page_json = json.loads(page.content)
|
|
|
|
|
|
2015-10-19 15:08:44 +00:00
|
|
|
|
self.assertEquals('test duck', page_json['name'])
|
2015-10-19 13:04:15 +00:00
|
|
|
|
self.assertEquals('123456', page_json['color'])
|
2015-10-19 15:08:44 +00:00
|
|
|
|
self.assertEqual(2, len(page_json['competences']))
|