duck-booking-tool/api/tests.py

327 lines
10 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8
"""
Test cases for API calls
"""
from django.conf import settings
from django.contrib.auth.models import User
from django.core.exceptions import ImproperlyConfigured
from django.test import TestCase, RequestFactory
from django_webtest import WebTest
import json
from .serializers import NamespacedSerializer
from booking.ducklevel import level_to_up_minutes
from booking.models import Species, Location, Duck, Competence, DuckCompetence
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()
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'])
class DuckClassTest(WebTest):
"""
Test case for duck related API calls
"""
csrf_checks = False
def setUp(self):
good_minutes = level_to_up_minutes(settings.COMP_WARN_LEVEL + 1)
bad_minutes = level_to_up_minutes(settings.COMP_WARN_LEVEL)
self.user = User.objects.create_user(username='test',
password='test')
self.species = Species.objects.create(name='duck')
self.location = Location.objects.create(name='temp')
self.comp_bad = Competence.objects.create(name='test1',
added_by=self.user)
self.comp_good = Competence.objects.create(name='test2',
added_by=self.user)
self.duck = Duck.objects.create(species=self.species,
name='test duck',
location=self.location,
donated_by=self.user,
color='123456')
DuckCompetence.objects.create(duck=self.duck,
comp=self.comp_bad,
up_minutes=bad_minutes,
down_minutes=0)
DuckCompetence.objects.create(duck=self.duck,
comp=self.comp_good,
up_minutes=good_minutes,
down_minutes=0)
def test_book_nonlogged(self):
"""
Test booking without logging in
"""
page = self.app.post('/api/v1/ducks/1/book/', expect_errors=True)
self.assertEqual(page.status_code, 403)
def test_book_nonexist(self):
"""
Test booking a non-existing duck
"""
# 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)
# Try to book an existing Duck for a non-existing competence
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)
def test_book_warn(self):
"""
Test duck booking for a competence the duck is not good at
"""
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 doesnt 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
test_data = {
'competence': self.comp_bad.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')
# Forcibly book for a competence with low level
test_data['force'] = 1
page = self.app.post(url, params=test_data, user=self.user)
self.assertEqual(200, page.status_code)
page_json = json.loads(page.content)
self.assertEquals(page_json['status'], 'ok')
def test_book_good(self):
"""
Test duck booking for a competence the duck is good at
"""
test_data = {
"competence": self.comp_good.pk
}
url = '/api/v1/ducks/%d/book/' % self.duck.pk
# Book the duck
page = self.app.post(url, params=test_data, user=self.user)
self.assertEquals(200, page.status_code)
page_json = json.loads(page.content)
self.assertEqual(page_json['status'], 'ok')
# Try to book again, it should fail
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'])
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))
def test_duck_donation(self):
"""
Test duck donating functionality
"""
# 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)
color = '123456'
page = self.app.post(
'/api/v1/ducks/donate/',
params={
'species': self.species.pk,
'location': self.location.pk,
'color': color,
},
user=self.user)
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)
def test_duck_details(self):
"""
Test duck details view
"""
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)
self.assertEquals('test duck', page_json['name'])
self.assertEquals('123456', page_json['color'])
self.assertEqual(2, len(page_json['competences']))