combo/tests/test_calendar.py

240 lines
7.2 KiB
Python

import json
import urlparse
import datetime
import pytest
import mock
from django.utils.dateparse import parse_time
from django.contrib.auth.models import User
from combo.data.models import Page
from combo.apps.calendar.models import BookingCalendar
from combo.apps.calendar.utils import get_calendar, get_chrono_service
pytestmark = pytest.mark.django_db
CHRONO_EVENTS = {
"data": [
{
"disabled": False,
"text": "13 juin 2017 08:00",
"api": {
"fillslot_url": "http://example.net/api/agenda/whatever/fillslot/86/"
},
"id": 86,
"datetime": "2017-06-13 08:00:00"
},
{
"disabled": False,
"text": "13 juin 2017 08:30",
"api": {
"fillslot_url": "http://example.net/api/agenda/whatever/fillslot/87/"
},
"id": 87,
"datetime": "2017-06-13 08:30:00"
},
{
"disabled": False,
"text": "13 juin 2017 09:00",
"api": {
"fillslot_url": "http://example.net/api/agenda/whatever/fillslot/88/"
},
"id": 88,
"datetime": "2017-06-13 09:00:00"
},
{
"disabled": False,
"text": "13 juin 2017 09:30",
"api": {
"fillslot_url": "http://example.net/api/agenda/whatever/fillslot/89/"
},
"id": 89,
"datetime": "2017-06-13 09:30:00"
},
{
"disabled": False,
"text": "14 juin 2017 09:30",
"api": {
"fillslot_url": "http://example.net/api/agenda/whatever/fillslot/89/"
},
"id": 90,
"datetime": "2017-06-14 09:30:00"
},
{
"disabled": False,
"text": "14 juin 2017 10:00",
"api": {
"fillslot_url": "http://example.net/api/agenda/whatever/fillslot/89/"
},
"id": 91,
"datetime": "2017-06-14 10:00:00"
},
{
"disabled": True,
"text": "14 juin 2017 15:00",
"api": {
"fillslot_url": "http://example.net/api/agenda/whatever/fillslot/89/"
},
"id": 91,
"datetime": "2017-06-14 15:00:00"
},
{
"disabled": True,
"text": "15 juin 2017 10:00",
"api": {
"fillslot_url": "http://example.net/api/agenda/whatever/fillslot/89/"
},
"id": 92,
"datetime": "2017-06-15 10:00:00"
}
]
}
WCS_FORMDEFS = [
{
"count": 12,
"category": "common",
"functions": {
"_receiver": {
"label": "Recipient"
},
},
"authentication_required": False,
"description": "",
"title": "Demande de place en creche",
"url": "http://example.net/demande-de-place-en-creche/",
"category_slug": "common",
"redirection": False,
"keywords": [],
"slug": "demande-de-place-en-creche"
}
]
def login(app, username='admin', password='admin'):
login_page = app.get('/login/')
login_form = login_page.forms[0]
login_form['username'] = username
login_form['password'] = password
resp = login_form.submit()
assert resp.status_int == 302
return app
def str2datetime(sdt):
return datetime.datetime.strptime(sdt, '%Y-%m-%dT%H:%M:%S')
class MockedRequestResponse(mock.Mock):
def json(self):
return json.loads(self.content)
def mocked_requests_get(*args, **kwargs):
remote_service = kwargs.get('remote_service')
if 'chrono' in remote_service['url']:
return MockedRequestResponse(
content=json.dumps(CHRONO_EVENTS))
else:
return MockedRequestResponse(
content=json.dumps(WCS_FORMDEFS))
@pytest.fixture
def admin(db):
return User.objects.create_superuser(username='admin', password='admin', email=None)
@pytest.fixture
def anonymous(app):
return app
@pytest.fixture
def connected(app, admin):
return login(app)
@pytest.fixture(params=['anonymous', 'connected'])
def client(request, anonymous, connected):
return locals().get(request.param)
@pytest.fixture
def cell(db):
page = Page.objects.create(title='whatever', slug='booking', template_name='standard')
cell = BookingCalendar(
page=page, title='Example Of Calendar',
agenda_reference='default:test',
formdef_reference='default:test',
slot_duration=datetime.timedelta(minutes=30),
minimal_booking_duration=datetime.timedelta(hours=1),
placeholder='content', order=0
)
cell.save()
return cell
def test_get_chrono_service(settings):
service = get_chrono_service()
assert service['title'] == 'test'
assert service['url'] == 'http://chrono.example.org'
assert service['secondary'] is False
@mock.patch('combo.apps.calendar.utils.requests.get', side_effect=mocked_requests_get)
def test_cell_rendering(mocked_get, client, cell):
page = client.get('/booking/')
# test without selecting slots
resp = page.form.submit().follow()
assert 'Please select slots' in resp.content
# test with slots from different day
resp.form.set('slots', True, 0)
resp.form.set('slots', True, 1)
resp.form.set('slots', True, 4)
resp = resp.form.submit().follow()
# test with non contiguous slots
assert 'Please select slots of the same day' in resp.content
resp.form.set('slots', True, 0)
resp.form.set('slots', True, 2)
resp = resp.form.submit().follow()
assert 'Please select contiguous slots' in resp.content
# test with invalid booking duration
resp.form.set('slots', True, 0)
resp = resp.form.submit().follow()
assert 'Minimal booking duration is 01:00' in resp.content
# test with valid selected slots
resp.form.set('slots', True, 0)
resp.form.set('slots', True, 1)
resp.form.set('slots', True, 2)
resp = resp.form.submit()
parsed = urlparse.urlparse(resp.url)
assert parsed.path == '/test/'
qs = urlparse.parse_qs(parsed.query)
assert qs['session_var_booking_agenda_slug'] == ['test']
assert qs['session_var_booking_start'] == ['2017-06-13T08:00:00']
assert qs['session_var_booking_end'] == ['2017-06-13T09:30:00']
@mock.patch('combo.apps.calendar.utils.requests.get', side_effect=mocked_requests_get)
def test_calendar(mocked_get, cell):
cal = get_calendar('default:whatever', cell.slot_duration)[0]
assert len(cal.days) == 3
for day in cal.get_days():
assert day in [
str2datetime('2017-06-12T08:00:00').date() + datetime.timedelta(days=i)
for i in range(0, 5)]
min_slot = str2datetime('2017-06-13T08:00:00')
max_slot = str2datetime('2017-06-14T15:00:00')
for slot in cal.get_slots():
assert (min_slot.time() <= slot <= max_slot.time()) is True
assert cal.has_day(min_slot.date()) is True
assert cal.get_availability(str2datetime('2017-06-14T15:00:00')).available is False
assert cal.get_minimum_slot() == min_slot.time()
assert cal.get_maximum_slot() == max_slot.time()
assert cal.get_day(max_slot.date()).slots[-1].available is False