chrono/tests/test_api.py

272 lines
11 KiB
Python

import datetime
import pytest
from webtest import TestApp
from django.contrib.auth import get_user_model
from django.test import override_settings
from django.utils.timezone import now
from chrono.agendas.models import Agenda, Event, Booking
pytestmark = pytest.mark.django_db
@pytest.fixture
def user():
User = get_user_model()
user = User.objects.create(username='john.doe',
first_name=u'John', last_name=u'Doe', email='john.doe@example.net')
user.set_password('password')
user.save()
return user
@pytest.fixture
def some_data():
agenda = Agenda(label=u'Foo bar')
agenda.save()
first_date = datetime.datetime.now().replace(hour=17, minute=0, second=0)
first_date += datetime.timedelta(days=1)
for i in range(3):
event = Event(start_datetime=first_date + datetime.timedelta(days=i),
places=20, agenda=agenda)
event.save()
agenda2 = Agenda(label=u'Foo bar2')
agenda2.save()
first_date = datetime.datetime.now().replace(hour=20, minute=0, second=0)
first_date += datetime.timedelta(days=1)
for i in range(2):
event = Event(start_datetime=first_date + datetime.timedelta(days=i),
places=20, agenda=agenda2)
event.save()
# a date in the past
event = Event(start_datetime=first_date - datetime.timedelta(days=10),
places=10, agenda=agenda)
event.save()
def test_agendas_api(app, some_data):
agenda_id = Agenda.objects.filter(label=u'Foo bar')[0].id
agenda2_id = Agenda.objects.filter(label=u'Foo bar2')[0].id
resp = app.get('/api/agenda/')
assert resp.json == {'data': [
{'text': 'Foo bar', 'id': agenda_id, 'slug': u'foo-bar',
'api': {'datetimes': 'http://localhost:80/api/agenda/%s/datetimes/' % agenda_id}},
{'text': 'Foo bar2', 'id': agenda2_id, 'slug': u'foo-bar2',
'api': {'datetimes': 'http://localhost:80/api/agenda/%s/datetimes/' % agenda2_id}}
]}
def test_datetimes_api(app, some_data):
agenda_id = Agenda.objects.filter(label=u'Foo bar')[0].id
resp = app.get('/api/agenda/%s/datetimes/' % agenda_id)
assert 'data' in resp.json
assert len(resp.json['data']) == 3
def test_datetime_api_fr(app, some_data):
agenda_id = Agenda.objects.filter(label=u'Foo bar')[0].id
with override_settings(LANGUAGE_CODE='fr-fr'):
resp = app.get('/api/agenda/%s/datetimes/' % agenda_id)
# no seconds, hh:mm in 24-hour formats
assert resp.json['data'][0]['text'].endswith(' 17:00')
assert 'data' in resp.json
def test_datetime_api_label(app, some_data):
agenda_id = Agenda.objects.filter(label=u'Foo bar2')[0].id
event = Event.objects.filter(agenda=agenda_id)[0]
event.label = 'Hello world'
event.save()
resp = app.get('/api/agenda/%s/datetimes/' % agenda_id)
assert 'Hello world' in [x['text'] for x in resp.json['data']]
def test_booking_api(app, some_data, user):
agenda_id = Agenda.objects.filter(label=u'Foo bar')[0].id
event = Event.objects.filter(agenda_id=agenda_id)[0]
# unauthenticated
resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda_id, event.id), status=403)
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda_id, event.id))
Booking.objects.get(id=resp.json['booking_id'])
assert Booking.objects.count() == 1
def test_booking_api_with_data(app, some_data, user):
agenda_id = Agenda.objects.filter(label=u'Foo bar')[0].id
event = Event.objects.filter(agenda_id=agenda_id)[0]
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.post_json('/api/agenda/%s/fillslot/%s/' % (agenda_id, event.id),
params={'hello': 'world'})
assert Booking.objects.count() == 1
assert Booking.objects.all()[0].extra_data == {'hello': 'world'}
def test_booking_cancellation_api(app, some_data, user):
agenda_id = Agenda.objects.filter(label=u'Foo bar')[0].id
event = Event.objects.filter(agenda_id=agenda_id)[0]
resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda_id, event.id), status=403)
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda_id, event.id))
booking_id = resp.json['booking_id']
assert Booking.objects.count() == 1
resp = app.delete('/api/booking/%s/' % booking_id)
assert Booking.objects.filter(cancellation_datetime__isnull=False).count() == 1
def test_booking_cancellation_post_api(app, some_data, user):
agenda_id = Agenda.objects.filter(label=u'Foo bar')[0].id
event = Event.objects.filter(agenda_id=agenda_id)[0]
resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda_id, event.id), status=403)
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda_id, event.id))
booking_id = resp.json['booking_id']
assert Booking.objects.count() == 1
resp = app.post('/api/booking/%s/cancel/' % booking_id)
assert Booking.objects.filter(cancellation_datetime__isnull=False).count() == 1
# cancel an object that doesn't exist
resp = app.post('/api/booking/%s/cancel/' % 9999, status=404)
# cancel an event that was already cancelled
resp = app.post('/api/booking/%s/cancel/' % booking_id, status=200)
assert resp.json['err'] == 1
def test_soldout(app, some_data, user):
agenda_id = Agenda.objects.filter(label=u'Foo bar')[0].id
event = Event.objects.filter(agenda_id=agenda_id).exclude(start_datetime__lt=now())[0]
resp = app.get('/api/agenda/%s/datetimes/' % agenda_id)
assert len(resp.json['data']) == 3
assert event.id in [x['id'] for x in resp.json['data']]
for i in range(event.places):
Booking(event=event).save()
resp = app.get('/api/agenda/%s/datetimes/' % agenda_id)
assert len(resp.json['data']) == 2
assert not event.id in [x['id'] for x in resp.json['data']]
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda_id, event.id), status=200)
assert resp.json['err'] == 1
assert resp.json['reason'] == 'sold out'
def test_status(app, some_data, user):
agenda_id = Agenda.objects.filter(label=u'Foo bar')[0].id
event = Event.objects.filter(agenda_id=agenda_id)[0]
Booking(event=event).save()
resp = app.get('/api/agenda/%s/status/%s/' % (agenda_id, event.id), status=403)
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.get('/api/agenda/%s/status/%s/' % (agenda_id, 9999), status=404)
resp = app.get('/api/agenda/%s/status/%s/' % (agenda_id, event.id))
assert resp.json['err'] == 0
assert resp.json['places']['total'] == 10
assert resp.json['places']['available'] == 9
assert resp.json['places']['reserved'] == 1
assert not 'waiting_list_total' in resp.json['places']
Booking(event=event, in_waiting_list=True).save()
event.waiting_list_places = 5
event.save()
resp = app.get('/api/agenda/%s/status/%s/' % (agenda_id, event.id))
assert resp.json['places']['waiting_list_total'] == 5
assert resp.json['places']['waiting_list_available'] == 4
assert resp.json['places']['waiting_list_reserved'] == 1
def test_waiting_list_datetimes(app, some_data, user):
agenda_id = Agenda.objects.filter(label=u'Foo bar')[0].id
event = Event.objects.filter(agenda_id=agenda_id).exclude(start_datetime__lt=now())[0]
event.waiting_list_places = 5
event.save()
resp = app.get('/api/agenda/%s/datetimes/' % agenda_id)
assert len(resp.json['data']) == 3
assert event.id in [x['id'] for x in resp.json['data']]
for i in range(event.places):
Booking(event=event).save()
# all places are booked but all the dates are still displayed as there is a
# waiting list.
resp = app.get('/api/agenda/%s/datetimes/' % agenda_id)
assert len(resp.json['data']) == 3
# fill the waiting list
for i in range(event.waiting_list_places):
Booking(event=event, in_waiting_list=True).save()
# the event datetime should no longer be returned
resp = app.get('/api/agenda/%s/datetimes/' % agenda_id)
assert len(resp.json['data']) == 2
assert not event.id in [x['id'] for x in resp.json['data']]
def test_waiting_list_booking(app, some_data, user):
agenda_id = Agenda.objects.filter(label=u'Foo bar')[0].id
event = Event.objects.filter(agenda_id=agenda_id).exclude(start_datetime__lt=now())[0]
event.waiting_list_places = 5
event.save()
for i in range(event.places):
Booking(event=event).save()
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda_id, event.id), status=200)
assert resp.json['err'] == 0
assert resp.json['in_waiting_list'] is True
# cancel a booking that was not on the waiting list
booking = Booking.objects.filter(event=event, in_waiting_list=False)[0]
booking.cancel()
# check new booking is still done on the waiting list
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda_id, event.id), status=200)
assert resp.json['err'] == 0
assert resp.json['in_waiting_list'] is True
# fill the waiting list
for i in range(event.waiting_list_places):
Booking(event=event, in_waiting_list=True).save()
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda_id, event.id), status=200)
assert resp.json['err'] == 1
assert resp.json['reason'] == 'sold out'
def test_accept_booking(app, some_data, user):
agenda_id = Agenda.objects.filter(label=u'Foo bar')[0].id
event = Event.objects.filter(agenda_id=agenda_id).exclude(start_datetime__lt=now())[0]
event.waiting_list_places = 5
event.save()
# create a booking on the waiting list
booking = Booking(event=event, in_waiting_list=True)
booking.save()
assert Booking.objects.filter(in_waiting_list=True).count() == 1
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.post('/api/booking/%s/accept/' % booking.id)
assert Booking.objects.filter(in_waiting_list=True).count() == 0
assert Booking.objects.filter(in_waiting_list=False).count() == 1
# accept a booking that doesn't exist
resp = app.post('/api/booking/%s/accept/' % 9999, status=404)
# accept a booking that was not in the waiting list
resp = app.post('/api/booking/%s/accept/' % booking.id, status=200)
assert resp.json['err'] == 2
# accept a booking that was cancelled before
booking = Booking.objects.get(id=booking.id)
booking.in_waiting_list = True
booking.cancel()
resp = app.post('/api/booking/%s/accept/' % booking.id, status=200)
assert resp.json['err'] == 1
assert Booking.objects.filter(in_waiting_list=True).count() == 1
assert Booking.objects.filter(in_waiting_list=False).count() == 0