misc: split api tests (#54461)

This commit is contained in:
Lauréline Guérin 2021-06-01 10:41:09 +02:00
parent d51cd7c14a
commit 31bc67fcde
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
7 changed files with 6025 additions and 5943 deletions

100
tests/api/conftest.py Normal file
View File

@ -0,0 +1,100 @@
# -*- coding: utf-8 -*-
import datetime
import pytest
from django.contrib.auth import get_user_model
from django.utils.timezone import localtime, make_aware, now
from chrono.agendas.models import Agenda, Desk, Event, MeetingType, TimePeriod, VirtualMember
@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(params=['Europe/Brussels', 'Asia/Kolkata', 'Brazil/East'])
def time_zone(request, settings):
settings.TIME_ZONE = request.param
# 2017-05-20 -> saturday
@pytest.fixture(
params=[
datetime.datetime(year=2017, month=5, day=20, hour=1, minute=12),
datetime.datetime(year=2017, month=5, day=20, hour=11, minute=42),
datetime.datetime(year=2017, month=5, day=20, hour=23, minute=17),
]
)
def mock_now(request, freezer, time_zone):
aware_datetime = make_aware(request.param)
freezer.move_to(aware_datetime)
return aware_datetime
@pytest.fixture
def some_data(mock_now):
agenda = Agenda(label=u'Foo bar')
agenda.save()
first_date = localtime(now()).replace(hour=17, minute=0, second=0, microsecond=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 bar 2')
agenda2.save()
first_date = localtime(now()).replace(hour=20, minute=0, second=0, microsecond=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()
@pytest.fixture
def meetings_agenda(mock_now):
agenda = Agenda(
label=u'Foo bar Meeting', kind='meetings', minimal_booking_delay=1, maximal_booking_delay=56
)
agenda.save()
meeting_type = MeetingType(agenda=agenda, label='Blah', duration=30)
meeting_type.save()
test_1st_weekday = (localtime(now()).weekday() + 2) % 7
test_2nd_weekday = (localtime(now()).weekday() + 3) % 7
default_desk, created = Desk.objects.get_or_create(agenda=agenda, label='Desk 1')
time_period = TimePeriod(
weekday=test_1st_weekday,
start_time=datetime.time(10, 0),
end_time=datetime.time(12, 0),
desk=default_desk,
)
time_period.save()
time_period = TimePeriod(
weekday=test_2nd_weekday,
start_time=datetime.time(10, 0),
end_time=datetime.time(17, 0),
desk=default_desk,
)
time_period.save()
return agenda
@pytest.fixture
def virtual_meetings_agenda(meetings_agenda):
agenda = Agenda.objects.create(label='Virtual Agenda', kind='virtual')
VirtualMember.objects.create(virtual_agenda=agenda, real_agenda=meetings_agenda)
return agenda

File diff suppressed because it is too large Load Diff

1128
tests/api/test_booking.py Normal file

File diff suppressed because it is too large Load Diff

629
tests/api/test_datetimes.py Normal file
View File

@ -0,0 +1,629 @@
# -*- coding: utf-8 -*-
import datetime
import urllib.parse as urlparse
import pytest
from django.test import override_settings
from django.utils.timezone import localtime, make_aware, now
from chrono.agendas.models import Agenda, Booking, Event, TimePeriodException
pytestmark = pytest.mark.django_db
def test_datetimes_api(app, some_data):
agenda = Agenda.objects.filter(label=u'Foo bar')[0]
def check_bookability(data):
for event in data:
assert Event.objects.get(slug=event['id']).in_bookable_period()
for event in agenda.event_set.all():
if not event.in_bookable_period():
assert event.slug not in [x['id'] for x in data]
resp = app.get('/api/agenda/xxx/datetimes/', status=404)
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
assert 'data' in resp.json
assert len(resp.json['data']) == 3
check_bookability(resp.json['data'])
assert app.get('/api/agenda/%s/datetimes/' % agenda.id).json == resp.json
agenda.minimal_booking_delay = 5
agenda.save()
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
assert len(resp.json['data']) == 0
check_bookability(resp.json['data'])
agenda.minimal_booking_delay = 2
agenda.save()
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
assert len(resp.json['data']) == 2
check_bookability(resp.json['data'])
agenda.minimal_booking_delay = 0
agenda.maximal_booking_delay = 3
agenda.save()
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
assert len(resp.json['data']) == 2
check_bookability(resp.json['data'])
assert resp.json['data'][0]['description'] is None
agenda.event_set.update(publication_date=localtime(now()).date() + datetime.timedelta(days=1))
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
assert len(resp.json['data']) == 0
check_bookability(resp.json['data'])
agenda.event_set.update(publication_date=localtime(now()).date())
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
assert len(resp.json['data']) == 2
check_bookability(resp.json['data'])
# add description, URL and pricing to events
for i, event in enumerate(agenda.event_set.all()):
event.description = 'Description %s' % i
event.url = 'https://www.example.net/%s' % i
event.pricing = '%s' % i
event.save()
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
assert resp.json['data'][0]['description']
def test_datetimes_api_wrong_kind(app):
agenda = Agenda.objects.create(label='Foo bar', kind='meetings')
app.get('/api/agenda/%s/datetimes/' % agenda.slug, status=404)
def test_datetime_api_fr(app):
agenda = Agenda.objects.create(label='Foo bar', kind='events', minimal_booking_delay=0)
Event.objects.create(
slug='event-slug',
start_datetime=localtime((now() + datetime.timedelta(days=5))).replace(hour=17, minute=0),
places=5,
agenda=agenda,
)
with override_settings(LANGUAGE_CODE='fr-fr'):
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
# no seconds, hh:mm in 24-hour formats
assert resp.json['data'][0]['text'].endswith(' 17:00')
assert resp.json['data'][0]['datetime'].endswith(' 17:00:00')
assert 'data' in resp.json
@pytest.mark.freeze_time('2021-05-06 14:00')
def test_datetime_api_label(app):
agenda = Agenda.objects.create(label='Foo bar', kind='events', minimal_booking_delay=0)
event = Event.objects.create(
label='Hello world',
slug='event-slug',
start_datetime=(now() + datetime.timedelta(days=1)),
places=5,
agenda=agenda,
)
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
assert 'Hello world' == resp.json['data'][0]['text']
agenda.event_display_template = '{{ event.label }} - {{ event.start_datetime }}'
agenda.save()
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
assert resp.json['data'][0]['text'] == 'Hello world - May 7, 2021, 4 p.m.'
Booking.objects.create(event=event)
agenda.event_display_template = (
'{{ event.label }} ({{ event.remaining_places }}/{{ event.places }} places remaining)'
)
agenda.save()
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
assert resp.json['data'][0]['text'] == 'Hello world (4/5 places remaining)'
def test_datetime_api_urls(app):
agenda = Agenda.objects.create(label='Foo bar', kind='events', minimal_booking_delay=0)
event = Event.objects.create(
slug='event-slug',
start_datetime=(now() + datetime.timedelta(days=5)).replace(hour=10, minute=0),
places=5,
waiting_list_places=5,
agenda=agenda,
)
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
for datum in resp.json['data']:
assert urlparse.urlparse(datum['api']['bookings_url']).path == '/api/agenda/%s/bookings/%s/' % (
agenda.slug,
event.slug,
)
assert urlparse.urlparse(datum['api']['fillslot_url']).path == '/api/agenda/%s/fillslot/%s/' % (
agenda.slug,
event.slug,
)
assert urlparse.urlparse(datum['api']['status_url']).path == '/api/agenda/%s/status/%s/' % (
agenda.slug,
event.slug,
)
def test_datetime_api_min_places(app):
agenda = Agenda.objects.create(label='Foo bar', kind='events')
event = Event.objects.create(start_datetime=now() + datetime.timedelta(days=7), places=5, agenda=agenda)
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
assert not resp.json['data'][0]['disabled']
resp = app.get('/api/agenda/%s/datetimes/?min_places=5' % agenda.slug)
assert not resp.json['data'][0]['disabled']
Booking.objects.create(event=event)
resp = app.get('/api/agenda/%s/datetimes/?min_places=5' % agenda.slug)
assert resp.json['data'][0]['disabled']
resp = app.get('/api/agenda/%s/datetimes/?min_places=wrong' % agenda.slug, status=400)
assert resp.json['err'] == 1
resp = app.get('/api/agenda/%s/datetimes/?min_places=' % agenda.slug, status=400)
assert resp.json['err'] == 1
@pytest.mark.freeze_time('2021-02-23')
def test_datetimes_api_exclude_slots(app):
agenda = Agenda.objects.create(
label='Foo bar', kind='events', minimal_booking_delay=0, maximal_booking_delay=7
)
event = Event.objects.create(
slug='event-slug',
start_datetime=localtime().replace(hour=10, minute=0),
places=5,
agenda=agenda,
)
Booking.objects.create(event=event, user_external_id='42')
cancelled = Booking.objects.create(event=event, user_external_id='35')
cancelled.cancel()
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
assert resp.json['data'][0]['disabled'] is False
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug, params={'exclude_user_external_id': '35'})
assert resp.json['data'][0]['disabled'] is False
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug, params={'exclude_user_external_id': '42'})
assert resp.json['data'][0]['disabled'] is True
assert resp.json['meta']['first_bookable_slot'] is None
assert resp.json['meta']['no_bookable_datetimes'] is True
event.delete()
# recurrent event
event = Event.objects.create(
slug='recurrent',
start_datetime=localtime().replace(hour=12, minute=0),
repeat='weekly',
places=2,
agenda=agenda,
)
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
assert resp.json['data'][0]['id'] == 'recurrent:2021-02-23-1200'
assert resp.json['data'][0]['places']['full'] is False
assert resp.json['data'][0]['disabled'] is False
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug, params={'exclude_user_external_id': '42'})
assert resp.json['data'][0]['id'] == 'recurrent:2021-02-23-1200'
assert resp.json['data'][0]['places']['full'] is False
assert resp.json['data'][0]['disabled'] is False
first_recurrence = event.get_or_create_event_recurrence(event.start_datetime)
Booking.objects.create(event=first_recurrence, user_external_id='42')
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
assert resp.json['data'][0]['id'] == 'recurrent--2021-02-23-1200'
assert resp.json['data'][0]['places']['full'] is False
assert resp.json['data'][0]['disabled'] is False
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug, params={'exclude_user_external_id': '42'})
assert resp.json['data'][0]['id'] == 'recurrent--2021-02-23-1200'
assert resp.json['data'][0]['places']['full'] is False
assert resp.json['data'][0]['disabled'] is True
Booking.objects.create(event=first_recurrence)
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
assert resp.json['data'][0]['id'] == 'recurrent--2021-02-23-1200'
assert resp.json['data'][0]['places']['full'] is True
assert resp.json['data'][0]['disabled'] is True
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug, params={'exclude_user_external_id': '42'})
assert resp.json['data'][0]['id'] == 'recurrent--2021-02-23-1200'
assert resp.json['data'][0]['places']['full'] is True
assert resp.json['data'][0]['disabled'] is True
def test_datetimes_api_hide_disabled(app):
agenda = Agenda.objects.create(
label='Foo bar', kind='events', minimal_booking_delay=0, maximal_booking_delay=7
)
event = Event.objects.create(
slug='event-slug',
start_datetime=now() + datetime.timedelta(days=3),
places=1,
agenda=agenda,
)
Booking.objects.create(event=event)
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
assert resp.json['data'][0]['id'] == 'event-slug'
assert resp.json['data'][0]['disabled'] is True
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug, params={'hide_disabled': True})
assert resp.json['data'] == []
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([x for x in resp.json['data'] if not x.get('disabled')]) == 3
assert event.slug 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([x for x in resp.json['data'] if not x.get('disabled')]) == 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([x for x in resp.json['data'] if not x.get('disabled')]) == 2
assert event.slug not in [x['id'] for x in resp.json['data'] if not x.get('disabled')]
assert event.slug in [x['id'] for x in resp.json['data'] if x.get('disabled')]
@pytest.mark.freeze_time('2017-05-20')
def test_agenda_api_date_range(app):
# test range limitation
agenda = Agenda.objects.create(label='Foo bar', kind='events', minimal_booking_delay=0)
first_datetime = localtime(now()).replace(hour=20, minute=0, second=0, microsecond=0)
first_datetime += datetime.timedelta(days=1)
for i in range(2):
event = Event.objects.create(
start_datetime=first_datetime + datetime.timedelta(days=i), places=20, agenda=agenda
)
base_datetime = agenda.event_set.last().start_datetime
base_datetime = base_datetime + datetime.timedelta(days=1)
for idx in range(7, 10):
if idx == 7:
day_events = ['9:00', '10:00', '11:00']
elif idx == 8:
day_events = ['13:00', '14:00']
else:
day_events = ['8:00']
day = base_datetime.date() + datetime.timedelta(days=idx)
for event in day_events:
event_dt = datetime.datetime.combine(day, datetime.datetime.strptime(event, '%H:%M').time())
Event.objects.create(agenda=agenda, start_datetime=make_aware(event_dt), places=2)
for value in ['foo', '2017-05-42']:
params = {'date_start': value}
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug, params=params, status=400)
assert resp.json['err'] == 1
assert resp.json['err_class'] == 'date_start format must be YYYY-MM-DD or YYYY-MM-DD HH:MM'
assert resp.json['err_desc'] == 'date_start format must be YYYY-MM-DD or YYYY-MM-DD HH:MM'
for value in ['foo', '2017-05-42']:
params = {'date_end': value}
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug, params=params, status=400)
assert resp.json['err'] == 1
assert resp.json['err_class'] == 'date_end format must be YYYY-MM-DD or YYYY-MM-DD HH:MM'
assert resp.json['err_desc'] == 'date_end format must be YYYY-MM-DD or YYYY-MM-DD HH:MM'
params = {'date_start': base_datetime.date().isoformat()}
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug, params=params)
assert len(resp.json['data']) == 6
date_endtime = base_datetime + datetime.timedelta(days=7)
params = {'date_end': date_endtime.date().isoformat()}
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug, params=params)
assert len(resp.json['data']) == 2
assert resp.json['data'][0]['datetime'] == '2017-05-21 20:00:00'
assert resp.json['data'][-1]['datetime'] == '2017-05-22 20:00:00'
params = {
'date_start': base_datetime.date() + datetime.timedelta(days=8),
'date_end': base_datetime.date() + datetime.timedelta(days=10),
}
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug, params=params)
assert len(resp.json['data']) == 3
assert resp.json['data'][0]['datetime'] == '2017-05-31 13:00:00'
assert resp.json['data'][-1]['datetime'] == '2017-06-01 08:00:00'
# with minimal booking delay changed
agenda.minimal_booking_delay = 3
agenda.save()
params = {'date_start': '2017-05-21'}
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug, params=params)
assert len(resp.json['data']) == 6
assert resp.json['data'][0]['datetime'] == '2017-05-30 09:00:00'
assert resp.json['data'][-1]['datetime'] == '2017-06-01 08:00:00'
# with maximal booking delay changed
agenda.maximal_booking_delay = 11
agenda.save()
params = {'date_end': '2017-06-01'}
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug, params=params)
assert len(resp.json['data']) == 3
assert resp.json['data'][0]['datetime'] == '2017-05-30 09:00:00'
assert resp.json['data'][-1]['datetime'] == '2017-05-30 11:00:00'
# with time
params = {'date_start': '2017-05-21 foo'}
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug, params=params, status=400)
assert resp.json['err'] == 1
assert resp.json['err_class'] == 'date_start format must be YYYY-MM-DD or YYYY-MM-DD HH:MM'
assert resp.json['err_desc'] == 'date_start format must be YYYY-MM-DD or YYYY-MM-DD HH:MM'
for start in ['2017-05-30 09:00', '2017-05-30 09:00:00']:
params = {'date_start': start}
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug, params=params)
assert len(resp.json['data']) == 3
assert resp.json['data'][0]['datetime'] == '2017-05-30 09:00:00'
assert resp.json['data'][-1]['datetime'] == '2017-05-30 11:00:00'
for start in ['2017-05-30 09:01', '2017-05-30 09:00:01', '2017-05-30 09:00:01+02:00']:
params = {'date_start': start}
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug, params=params)
assert len(resp.json['data']) == 2
assert resp.json['data'][0]['datetime'] == '2017-05-30 10:00:00'
assert resp.json['data'][-1]['datetime'] == '2017-05-30 11:00:00'
params = {'date_end': '2017-06-01 foo'}
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug, params=params, status=400)
assert resp.json['err'] == 1
assert resp.json['err_class'] == 'date_end format must be YYYY-MM-DD or YYYY-MM-DD HH:MM'
assert resp.json['err_desc'] == 'date_end format must be YYYY-MM-DD or YYYY-MM-DD HH:MM'
for end in ['2017-05-30 11:01', '2017-05-30 11:00:01']:
params = {'date_end': end}
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug, params=params)
assert len(resp.json['data']) == 3
assert resp.json['data'][0]['datetime'] == '2017-05-30 09:00:00'
assert resp.json['data'][-1]['datetime'] == '2017-05-30 11:00:00'
for end in ['2017-05-30 11:00', '2017-05-30 11:00:00', '2017-05-30 11:00:00+02:00']:
params = {'date_end': end}
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug, params=params)
assert len(resp.json['data']) == 2
assert resp.json['data'][0]['datetime'] == '2017-05-30 09:00:00'
assert resp.json['data'][-1]['datetime'] == '2017-05-30 10:00:00'
def test_datetimes_api_meta(app, freezer):
# 2017-05-20 -> saturday
freezer.move_to(make_aware(datetime.datetime(year=2017, month=5, day=20, hour=1, minute=12)))
agenda = Agenda.objects.create(label=u'Foo bar')
first_date = localtime(now()).replace(hour=17, minute=0, second=0, microsecond=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()
# a date in the past
event = Event(start_datetime=first_date - datetime.timedelta(days=10), places=10, agenda=agenda)
event.save()
events = Event.objects.filter(agenda_id=agenda.id).exclude(start_datetime__lt=now())
assert len(events) == 3
api_url = '/api/agenda/%s/datetimes/' % agenda.slug
resp = app.get(api_url)
assert len(resp.json['data']) == 3
assert resp.json['meta'] == {
'no_bookable_datetimes': False,
'bookable_datetimes_number_total': 3,
'bookable_datetimes_number_available': 3,
'first_bookable_slot': resp.json['data'][0],
}
def simulate_booking(event, nb_places):
for i in range(nb_places):
Booking(event=event, user_external_id='42').save()
simulate_booking(events[0], 10)
resp = app.get(api_url)
assert len(resp.json['data']) == 3
assert resp.json['meta'] == {
'no_bookable_datetimes': False,
'bookable_datetimes_number_total': 3,
'bookable_datetimes_number_available': 3,
'first_bookable_slot': resp.json['data'][0],
}
resp = app.get(api_url, params={'exclude_user_external_id': '42'})
assert len(resp.json['data']) == 3
assert resp.json['meta'] == {
'no_bookable_datetimes': False,
'bookable_datetimes_number_total': 3,
'bookable_datetimes_number_available': 2,
'first_bookable_slot': resp.json['data'][1],
}
resp = app.get(api_url + '?min_places=11')
assert len(resp.json['data']) == 3
assert resp.json['meta'] == {
'no_bookable_datetimes': False,
'bookable_datetimes_number_total': 3,
'bookable_datetimes_number_available': 2,
'first_bookable_slot': resp.json['data'][1],
}
simulate_booking(events[0], 10)
resp = app.get(api_url)
assert len(resp.json['data']) == 3
assert resp.json['meta'] == {
'no_bookable_datetimes': False,
'bookable_datetimes_number_total': 3,
'bookable_datetimes_number_available': 2,
'first_bookable_slot': resp.json['data'][1],
}
simulate_booking(events[1], 20)
simulate_booking(events[2], 20)
resp = app.get(api_url)
assert len(resp.json['data']) == 3
assert resp.json['meta'] == {
'no_bookable_datetimes': True,
'bookable_datetimes_number_total': 3,
'bookable_datetimes_number_available': 0,
'first_bookable_slot': None,
}
# recurring event
Event.objects.all().delete()
Event.objects.create(
slug='abc', label='Test', start_datetime=localtime(), repeat='weekly', places=5, agenda=agenda
)
resp = app.get(api_url)
assert resp.json['meta']['first_bookable_slot']['text'] == 'Test (May 27, 2017, 1:12 a.m.)'
def test_recurring_events_api(app, user, freezer):
freezer.move_to('2021-01-12 12:05') # Tuesday
agenda = Agenda.objects.create(
label='Foo bar', kind='events', minimal_booking_delay=1, maximal_booking_delay=30
)
base_event = Event.objects.create(
slug='abc', label='Test', start_datetime=localtime(), repeat='weekly', places=5, agenda=agenda
)
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
data = resp.json['data']
assert len(data) == 4
assert data[0]['id'] == 'abc:2021-01-19-1305'
assert data[0]['datetime'] == '2021-01-19 13:05:00'
assert data[0]['text'] == 'Test (Jan. 19, 2021, 1:05 p.m.)'
assert data[3]['id'] == 'abc:2021-02-09-1305'
assert Event.objects.count() == 1
fillslot_url = data[0]['api']['fillslot_url']
app.authorization = ('Basic', ('john.doe', 'password'))
# book first event
resp = app.post(fillslot_url)
assert resp.json['err'] == 0
assert Event.objects.count() == 2
event = Booking.objects.get(pk=resp.json['booking_id']).event
assert event.slug == 'abc--2021-01-19-1305'
# first event is now a real event in datetimes
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
data = resp.json['data']
assert len(data) == 4
assert data[0]['id'] == event.slug
new_fillslot_url = data[0]['api']['fillslot_url']
# booking again with both old and new urls works
resp = app.post(fillslot_url)
assert resp.json['err'] == 0
resp = app.post(new_fillslot_url)
assert resp.json['err'] == 0
assert Event.objects.count() == 2
assert event.booking_set.count() == 3
# status and bookings api also create a real event
status_url = data[1]['api']['status_url']
resp = app.get(status_url)
assert resp.json['places']['total'] == 5
assert Event.objects.count() == 3
bookings_url = data[2]['api']['bookings_url']
resp = app.get(bookings_url, params={'user_external_id': '42'})
assert resp.json['data'] == []
assert Event.objects.count() == 4
# cancelled recurrences do not appear
event.cancel()
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
assert len(resp.json['data']) == 3
assert resp.json['data'][0]['id'] == 'abc--2021-01-26-1305'
# publication date is accounted for
Event.objects.filter(primary_event=base_event).delete()
base_event.publication_date = now().replace(day=27)
base_event.save()
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
assert len(resp.json['data']) == 0
# events follow agenda display template
Event.objects.all().update(publication_date=None)
agenda.event_display_template = '{{ event.label }} - {{ event.start_datetime }}'
agenda.save()
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
assert resp.json['data'][0]['text'] == 'Test - Jan. 19, 2021, 1:05 p.m.'
def test_recurring_events_api_various_times(app, user, mock_now):
agenda = Agenda.objects.create(
label='Foo bar', kind='events', minimal_booking_delay=0, maximal_booking_delay=30
)
event = Event.objects.create(
slug='abc', start_datetime=localtime(), repeat='weekly', places=5, agenda=agenda
)
event.refresh_from_db()
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
assert len(resp.json['data']) == 5
fillslot_url = resp.json['data'][0]['api']['fillslot_url']
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.post(fillslot_url)
assert resp.json['err'] == 0
new_event = Booking.objects.get(pk=resp.json['booking_id']).event
assert event.start_datetime == new_event.start_datetime
def test_datetimes_dst(app, freezer):
agenda = Agenda.objects.create(
label='Foo bar', kind='events', minimal_booking_delay=0, maximal_booking_delay=10
)
event = Event.objects.create(
slug='event-slug',
start_datetime=make_aware(datetime.datetime(2021, 3, 28, 12, 30)),
places=5,
agenda=agenda,
)
freezer.move_to('Fri, 18 Mar 2021 23:59:39 +0100')
# maximal_booking_delay is 10days so last bookable event is on
# 2021-03-28T00:00, so event should not be bookable
assert not event.in_bookable_period()
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
assert len(resp.json['data']) == 0
def test_recurring_events_api_exceptions(app, user, freezer):
freezer.move_to('2021-01-12 12:05') # Tuesday
agenda = Agenda.objects.create(
label='Foo bar', kind='events', minimal_booking_delay=1, maximal_booking_delay=30
)
Event.objects.create(slug='abc', start_datetime=localtime(), repeat='weekly', places=5, agenda=agenda)
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
data = resp.json['data']
assert len(data) == 4
assert data[0]['datetime'] == '2021-01-19 13:05:00'
TimePeriodException.objects.create(
desk=agenda.desk_set.get(),
start_datetime=datetime.date(year=2021, month=1, day=18),
end_datetime=datetime.date(year=2021, month=1, day=20),
)
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
assert len(resp.json['data']) == 3
assert resp.json['data'][0]['datetime'] == '2021-01-26 13:05:00'
# try to book excluded event
fillslot_url = data[0]['api']['fillslot_url']
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.post(fillslot_url, status=400)
assert resp.json['err'] == 1

1892
tests/api/test_fillslot.py Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,87 @@
# -*- coding: utf-8 -*-
import pytest
from django.utils.timezone import now
from chrono.agendas.models import Agenda, Booking, Category, Event
pytestmark = pytest.mark.django_db
def test_statistics_list(app, user):
Category.objects.create(label='Category A')
Category.objects.create(label='Category B')
# unauthorized
app.get('/api/statistics/', status=401)
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.get('/api/statistics/')
category_filter = [x for x in resp.json['data'][0]['filters'] if x['id'] == 'category'][0]
assert len(category_filter['options']) == 3
def test_statistics_bookings(app, user, freezer):
agenda = Agenda.objects.create(label='Foo bar', kind='events')
event = Event.objects.create(start_datetime=now(), places=5, agenda=agenda)
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.get('/api/statistics/')
url = [x for x in resp.json['data'] if x['id'] == 'bookings_count'][0]['url']
resp = app.get(url)
assert len(resp.json['data']['series']) == 0
freezer.move_to('2020-10-10')
for _ in range(10):
Booking.objects.create(event=event)
freezer.move_to('2020-10-15')
Booking.objects.create(event=event)
resp = app.get(url + '?time_interval=day')
assert resp.json['data'] == {
'x_labels': ['2020-10-10', '2020-10-15'],
'series': [{'label': 'Bookings Count', 'data': [10, 1]}],
}
# period filter
resp = app.get(url + '?start=2020-10-14&end=2020-10-16')
assert resp.json['data'] == {
'x_labels': ['2020-10-15'],
'series': [{'label': 'Bookings Count', 'data': [1]}],
}
category = Category.objects.create(label='Category A', slug='category-a')
agenda = Agenda.objects.create(label='Foo bar', kind='events', category=category)
event = Event.objects.create(start_datetime=now(), places=5, agenda=agenda)
freezer.move_to('2020-10-25')
Booking.objects.create(event=event)
# category filter
resp = app.get(url + '?category=category-a')
assert resp.json['data'] == {
'x_labels': ['2020-10-25'],
'series': [{'label': 'Bookings Count', 'data': [1]}],
}
# invalid time_interval
resp = app.get(url + '?time_interval=month', status=400)
assert resp.json['err'] == 1
assert 'time_interval' in resp.json['errors']
# absence/presence
for i in range(10):
Booking.objects.create(event=event, user_was_present=bool(i % 2))
freezer.move_to('2020-11-01')
Booking.objects.create(event=event, user_was_present=True)
resp = app.get(url)
assert resp.json['data'] == {
'x_labels': ['2020-10-10', '2020-10-15', '2020-10-25', '2020-11-01'],
'series': [
{'label': 'Unknown', 'data': [10, 1, 1, None]},
{'label': 'Present', 'data': [None, None, 5, 1]},
{'label': 'Absent', 'data': [None, None, 5, None]},
],
}