3942 lines
165 KiB
Python
3942 lines
165 KiB
Python
import datetime
|
|
import json
|
|
from unittest import mock
|
|
|
|
import freezegun
|
|
import pytest
|
|
import requests
|
|
from django.contrib.auth.models import Group
|
|
from django.core.management import call_command
|
|
from django.db import connection
|
|
from django.test import override_settings
|
|
from django.test.utils import CaptureQueriesContext
|
|
from django.utils.timezone import localtime, make_aware, now
|
|
|
|
from chrono.agendas.models import (
|
|
Agenda,
|
|
AgendaReminderSettings,
|
|
Booking,
|
|
Desk,
|
|
Event,
|
|
EventsType,
|
|
MeetingType,
|
|
TimePeriod,
|
|
TimePeriodException,
|
|
UnavailabilityCalendar,
|
|
VirtualMember,
|
|
)
|
|
from chrono.utils.signature import check_query
|
|
from tests.utils import login
|
|
|
|
pytestmark = pytest.mark.django_db
|
|
|
|
|
|
def test_unlogged_access(app):
|
|
# connect while not being logged in
|
|
assert app.get('/manage/', status=302).location.endswith('/login/?next=/manage/')
|
|
|
|
|
|
def test_simple_user_access(app, simple_user):
|
|
# connect while being logged as a simple user, access should be forbidden
|
|
app = login(app, username='user', password='user')
|
|
resp = app.get('/manage/', status=403)
|
|
assert 'Unfortunately, there is still no agenda' in resp.html.find('div', {'class': 'big-msg-sorry'}).text
|
|
|
|
|
|
def test_manager_user_access(app, manager_user):
|
|
# connect while being logged as a manager user, access should be granted if
|
|
# there's at least an agenda that is viewable or editable.
|
|
app = login(app, username='manager', password='manager')
|
|
assert app.get('/manage/', status=403)
|
|
|
|
agenda = Agenda(label='Foo bar')
|
|
agenda.save()
|
|
assert app.get('/manage/', status=403)
|
|
|
|
agenda.view_role = manager_user.groups.all()[0]
|
|
agenda.edit_role = None
|
|
agenda.save()
|
|
assert app.get('/manage/', status=200)
|
|
|
|
agenda.edit_role = None
|
|
agenda.view_role = manager_user.groups.all()[0]
|
|
agenda.save()
|
|
assert app.get('/manage/', status=200)
|
|
|
|
|
|
def test_home_redirect(app):
|
|
assert app.get('/', status=302).location.endswith('/manage/')
|
|
|
|
|
|
def test_access(app, admin_user):
|
|
app = login(app)
|
|
resp = app.get('/manage/', status=200)
|
|
assert '<h2>Agendas</h2>' in resp.text
|
|
assert "This site doesn't have any agenda yet." in resp.text
|
|
|
|
|
|
def test_logout(app, admin_user):
|
|
app = login(app)
|
|
app.get('/logout/')
|
|
assert app.get('/manage/', status=302).location.endswith('/login/?next=/manage/')
|
|
|
|
|
|
def test_menu_json(app, admin_user):
|
|
app = login(app)
|
|
resp = app.get('/manage/menu.json', status=200)
|
|
assert resp.content_type == 'application/json'
|
|
assert resp.json[0]['url'] == 'http://testserver/manage/'
|
|
assert resp.json[0]['label'] == 'Agendas'
|
|
resp2 = app.get('/manage/menu.json?callback=Q', status=200)
|
|
assert resp2.text == 'Q(%s);' % resp.text
|
|
assert resp2.content_type == 'application/javascript'
|
|
|
|
|
|
def test_menu_json_manager(app, simple_user, manager_user):
|
|
app.get('/manage/menu.json', status=302) # redirect to login
|
|
|
|
app = login(app, username='user', password='user')
|
|
app.get('/manage/menu.json', status=403)
|
|
|
|
app = login(app, username='manager', password='manager')
|
|
app.get('/manage/menu.json', status=403)
|
|
|
|
agenda = Agenda(label='Foo bar')
|
|
agenda.view_role = manager_user.groups.all()[0]
|
|
agenda.save()
|
|
app.get('/manage/menu.json', status=200)
|
|
|
|
|
|
def test_events_agenda_redirect(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Foo Bar', kind='events')
|
|
|
|
app = login(app)
|
|
for agenda_id in [agenda.pk, agenda.slug]:
|
|
resp = app.get('/manage/agendas/%s/' % agenda_id, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/month/' % agenda.pk)
|
|
|
|
agenda.default_view = 'open_events'
|
|
agenda.save()
|
|
for agenda_id in [agenda.pk, agenda.slug]:
|
|
resp = app.get('/manage/agendas/%s/' % agenda_id, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/events/open/' % agenda.pk)
|
|
|
|
agenda.default_view = 'day'
|
|
agenda.save()
|
|
for agenda_id in [agenda.pk, agenda.slug]:
|
|
resp = app.get('/manage/agendas/%s/' % agenda_id, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/day/' % agenda.pk)
|
|
|
|
agenda.default_view = 'week'
|
|
agenda.save()
|
|
for agenda_id in [agenda.pk, agenda.slug]:
|
|
resp = app.get('/manage/agendas/%s/' % agenda_id, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/week/' % agenda.pk)
|
|
|
|
# old month/week/days views
|
|
resp = app.get('/manage/agendas/%s/2022/12/15/' % agenda.pk, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/' % agenda.pk)
|
|
resp = app.get('/manage/agendas/%s/2022/12/' % agenda.pk, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/' % agenda.pk)
|
|
resp = app.get('/manage/agendas/%s/2022/week/1/' % agenda.pk, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/' % agenda.pk)
|
|
|
|
|
|
@freezegun.freeze_time('2020-07-12')
|
|
def test_events_agenda_month_redirect(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Foo Bar', kind='events')
|
|
|
|
app = login(app)
|
|
# no event, redirect to current month
|
|
resp = app.get('/manage/agendas/%s/month/' % agenda.pk, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/month/2020/07/12/' % agenda.pk)
|
|
|
|
# only past events, redirect to last event month
|
|
Event.objects.create(
|
|
agenda=agenda,
|
|
places=1,
|
|
start_datetime=now() - datetime.timedelta(days=60),
|
|
)
|
|
resp = app.get('/manage/agendas/%s/month/' % agenda.pk, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/month/2020/05/13/' % agenda.pk)
|
|
Event.objects.create(
|
|
agenda=agenda,
|
|
places=1,
|
|
start_datetime=now() - datetime.timedelta(days=30),
|
|
)
|
|
resp = app.get('/manage/agendas/%s/month/' % agenda.pk, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/month/2020/06/12/' % agenda.pk)
|
|
|
|
# future events
|
|
Event.objects.create(
|
|
agenda=agenda,
|
|
places=1,
|
|
start_datetime=now() + datetime.timedelta(days=60),
|
|
)
|
|
resp = app.get('/manage/agendas/%s/month/' % agenda.pk, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/month/2020/09/10/' % agenda.pk)
|
|
Event.objects.create(
|
|
agenda=agenda,
|
|
places=1,
|
|
start_datetime=now() + datetime.timedelta(days=30),
|
|
)
|
|
resp = app.get('/manage/agendas/%s/month/' % agenda.pk, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/month/2020/08/11/' % agenda.pk)
|
|
|
|
# don't check events for meetings
|
|
agenda.kind = 'virtual'
|
|
agenda.save()
|
|
resp = app.get('/manage/agendas/%s/month/' % agenda.pk, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/month/2020/07/12/' % agenda.pk)
|
|
agenda.kind = 'meetings'
|
|
agenda.save()
|
|
resp = app.get('/manage/agendas/%s/month/' % agenda.pk, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/month/2020/07/12/' % agenda.pk)
|
|
|
|
|
|
@freezegun.freeze_time('2020-07-12')
|
|
def test_events_agenda_week_redirect(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Foo Bar', kind='events')
|
|
|
|
app = login(app)
|
|
# no event, redirect to current week
|
|
resp = app.get('/manage/agendas/%s/week/' % agenda.pk, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/week/2020/07/12/' % agenda.pk)
|
|
|
|
# only past events, redirect to last event month
|
|
Event.objects.create(
|
|
agenda=agenda,
|
|
places=1,
|
|
start_datetime=now() - datetime.timedelta(days=60),
|
|
)
|
|
resp = app.get('/manage/agendas/%s/week/' % agenda.pk, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/week/2020/05/13/' % agenda.pk)
|
|
Event.objects.create(
|
|
agenda=agenda,
|
|
places=1,
|
|
start_datetime=now() - datetime.timedelta(days=30),
|
|
)
|
|
resp = app.get('/manage/agendas/%s/week/' % agenda.pk, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/week/2020/06/12/' % agenda.pk)
|
|
|
|
# future events
|
|
Event.objects.create(
|
|
agenda=agenda,
|
|
places=1,
|
|
start_datetime=now() + datetime.timedelta(days=60),
|
|
)
|
|
resp = app.get('/manage/agendas/%s/week/' % agenda.pk, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/week/2020/09/10/' % agenda.pk)
|
|
Event.objects.create(
|
|
agenda=agenda,
|
|
places=1,
|
|
start_datetime=now() + datetime.timedelta(days=30),
|
|
)
|
|
resp = app.get('/manage/agendas/%s/week/' % agenda.pk, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/week/2020/08/11/' % agenda.pk)
|
|
|
|
# don't check events for meetings
|
|
agenda.kind = 'virtual'
|
|
agenda.save()
|
|
resp = app.get('/manage/agendas/%s/week/' % agenda.pk, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/week/2020/07/12/' % agenda.pk)
|
|
agenda.kind = 'meetings'
|
|
agenda.save()
|
|
resp = app.get('/manage/agendas/%s/week/' % agenda.pk, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/week/2020/07/12/' % agenda.pk)
|
|
|
|
|
|
@freezegun.freeze_time('2020-07-12')
|
|
def test_events_agenda_day_redirect(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Foo Bar', kind='events')
|
|
|
|
app = login(app)
|
|
# no event, redirect to current day
|
|
resp = app.get('/manage/agendas/%s/day/' % agenda.pk, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/day/2020/07/12/' % agenda.pk)
|
|
|
|
# only past events, redirect to last event day
|
|
Event.objects.create(
|
|
agenda=agenda,
|
|
places=1,
|
|
start_datetime=now() - datetime.timedelta(days=60),
|
|
)
|
|
resp = app.get('/manage/agendas/%s/day/' % agenda.pk, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/day/2020/05/13/' % agenda.pk)
|
|
Event.objects.create(
|
|
agenda=agenda,
|
|
places=1,
|
|
start_datetime=now() - datetime.timedelta(days=30),
|
|
)
|
|
resp = app.get('/manage/agendas/%s/day/' % agenda.pk, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/day/2020/06/12/' % agenda.pk)
|
|
|
|
# future events
|
|
Event.objects.create(
|
|
agenda=agenda,
|
|
places=1,
|
|
start_datetime=now() + datetime.timedelta(days=60),
|
|
)
|
|
resp = app.get('/manage/agendas/%s/day/' % agenda.pk, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/day/2020/09/10/' % agenda.pk)
|
|
Event.objects.create(
|
|
agenda=agenda,
|
|
places=1,
|
|
start_datetime=now() + datetime.timedelta(days=30),
|
|
)
|
|
resp = app.get('/manage/agendas/%s/day/' % agenda.pk, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/day/2020/08/11/' % agenda.pk)
|
|
|
|
# don't check events for meetings
|
|
agenda.kind = 'virtual'
|
|
agenda.save()
|
|
resp = app.get('/manage/agendas/%s/day/' % agenda.pk, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/day/2020/07/12/' % agenda.pk)
|
|
agenda.kind = 'meetings'
|
|
agenda.save()
|
|
resp = app.get('/manage/agendas/%s/day/' % agenda.pk, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/day/2020/07/12/' % agenda.pk)
|
|
|
|
|
|
def test_meetings_agenda_redirect(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Foo Bar', kind='meetings')
|
|
|
|
app = login(app)
|
|
for agenda_id in [agenda.pk, agenda.slug]:
|
|
resp = app.get('/manage/agendas/%s/' % agenda_id, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/day/' % agenda.pk)
|
|
|
|
agenda.default_view = 'month'
|
|
agenda.save()
|
|
for agenda_id in [agenda.pk, agenda.slug]:
|
|
resp = app.get('/manage/agendas/%s/' % agenda_id, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/month/' % agenda.pk)
|
|
|
|
agenda.default_view = 'week'
|
|
agenda.save()
|
|
for agenda_id in [agenda.pk, agenda.slug]:
|
|
resp = app.get('/manage/agendas/%s/' % agenda_id, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/week/' % agenda.pk)
|
|
|
|
# old month/week/days views
|
|
resp = app.get('/manage/agendas/%s/2022/12/15/' % agenda.pk, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/' % agenda.pk)
|
|
resp = app.get('/manage/agendas/%s/2022/12/' % agenda.pk, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/' % agenda.pk)
|
|
resp = app.get('/manage/agendas/%s/2022/week/1/' % agenda.pk, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/' % agenda.pk)
|
|
|
|
|
|
def test_virtual_agenda_redirect(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Foo Bar', kind='virtual')
|
|
|
|
app = login(app)
|
|
for agenda_id in [agenda.pk, agenda.slug]:
|
|
resp = app.get('/manage/agendas/%s/' % agenda_id, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/day/' % agenda.pk)
|
|
|
|
agenda.default_view = 'month'
|
|
agenda.save()
|
|
for agenda_id in [agenda.pk, agenda.slug]:
|
|
resp = app.get('/manage/agendas/%s/' % agenda_id, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/month/' % agenda.pk)
|
|
|
|
agenda.default_view = 'week'
|
|
agenda.save()
|
|
for agenda_id in [agenda.pk, agenda.slug]:
|
|
resp = app.get('/manage/agendas/%s/' % agenda_id, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/week/' % agenda.pk)
|
|
|
|
# old month/week/days views
|
|
resp = app.get('/manage/agendas/%s/2022/12/15/' % agenda.pk, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/' % agenda.pk)
|
|
resp = app.get('/manage/agendas/%s/2022/12/' % agenda.pk, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/' % agenda.pk)
|
|
resp = app.get('/manage/agendas/%s/2022/week/1/' % agenda.pk, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/' % agenda.pk)
|
|
|
|
|
|
def test_view_agendas_as_admin(app, admin_user):
|
|
Agenda.objects.create(label='Bar Foo')
|
|
|
|
app = login(app)
|
|
resp = app.get('/manage/', status=200)
|
|
assert 'Bar Foo <span class="identifier">[identifier: bar-foo]</span>' in resp.text
|
|
|
|
|
|
def test_view_agendas_as_manager(app, manager_user):
|
|
agenda = Agenda(label='Foo Bar')
|
|
agenda.view_role = manager_user.groups.all()[0]
|
|
agenda.save()
|
|
|
|
agenda2 = Agenda(label='Bar Foo')
|
|
agenda2.save()
|
|
|
|
app = login(app, username='manager', password='manager')
|
|
resp = app.get('/manage/', status=200)
|
|
assert 'Foo Bar' in resp.text
|
|
assert 'Bar Foo <span class="identifier">[identifier: bar-foo]</span>' not in resp.text
|
|
assert 'Bar Foo' not in resp.text
|
|
assert 'New' not in resp.text
|
|
|
|
# check user doesn't have access
|
|
app.get('/manage/agendas/%s/' % agenda2.id, status=403)
|
|
|
|
# check there's no access to the settings page for "events" agenda
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=403)
|
|
app.get('/manage/agendas/%s/add-event' % agenda.id, status=403)
|
|
app.get('/manage/agendas/%s/edit' % agenda.id, status=403)
|
|
|
|
# check it doesn't give access for "meetings" agenda
|
|
agenda.kind = 'meetings'
|
|
agenda.save()
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=403)
|
|
# or virtual agenda
|
|
agenda.kind = 'virtual'
|
|
agenda.save()
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=403)
|
|
|
|
# check it gives a 404 on unknown agendas
|
|
resp = app.get('/manage/agendas/0/settings', status=404)
|
|
|
|
|
|
def test_add_agenda(app, admin_user):
|
|
app = login(app)
|
|
resp = app.get('/manage/', status=200)
|
|
resp = resp.click('New')
|
|
resp.form['label'] = 'Foo bar'
|
|
resp = resp.form.submit()
|
|
|
|
agenda = Agenda.objects.get(label='Foo bar')
|
|
assert resp.location.endswith('/manage/agendas/%s/settings' % agenda.id)
|
|
resp = resp.follow()
|
|
assert 'Foo bar' in resp.text
|
|
assert '<h2>Settings' in resp.text
|
|
assert agenda.minimal_booking_delay == 1
|
|
assert agenda.maximal_booking_delay == 56
|
|
assert agenda.kind == 'events'
|
|
assert agenda.desk_simple_management is False
|
|
|
|
resp = app.get('/manage/agendas/add/')
|
|
resp.form['label'] = 'Foo bar 2'
|
|
resp.form['kind'] = 'meetings'
|
|
resp = resp.form.submit()
|
|
agenda = Agenda.objects.latest('pk')
|
|
assert agenda.kind == 'meetings'
|
|
assert agenda.desk_simple_management is True
|
|
|
|
resp = app.get('/manage/agendas/add/')
|
|
resp.form['label'] = 'Foo bar 3'
|
|
resp.form['kind'] = 'virtual'
|
|
resp = resp.form.submit()
|
|
agenda = Agenda.objects.latest('pk')
|
|
assert agenda.kind == 'virtual'
|
|
assert agenda.desk_simple_management is False
|
|
|
|
|
|
def test_add_agenda_as_manager(app, manager_user):
|
|
# open /manage/ access to manager_user, and check agenda creation is not
|
|
# allowed.
|
|
agenda = Agenda(label='Foo bar')
|
|
agenda.view_role = manager_user.groups.all()[0]
|
|
agenda.save()
|
|
app = login(app, username='manager', password='manager')
|
|
app.get('/manage/agendas/add/', status=403)
|
|
|
|
|
|
def test_add_agenda_and_set_role(app, admin_user, manager_user):
|
|
app = login(app)
|
|
resp = app.get('/manage/', status=200)
|
|
resp = resp.click('New')
|
|
resp.form['label'] = 'Foo bar'
|
|
resp.form['kind'] = 'meetings'
|
|
resp = resp.form.submit().follow()
|
|
|
|
agenda = Agenda.objects.get(label='Foo bar')
|
|
assert agenda.desk_set.count() == 1
|
|
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id)
|
|
resp = resp.click('Configure', href='roles')
|
|
resp.form['edit_role'] = manager_user.groups.all()[0].pk
|
|
resp = resp.form.submit().follow()
|
|
assert 'Edit Role: Managers' in resp.text
|
|
|
|
# still only one desk
|
|
assert agenda.desk_set.count() == 1
|
|
|
|
|
|
def test_options_agenda_redirect(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Foo Bar')
|
|
|
|
app = login(app)
|
|
for kind in ['events', 'meetings', 'virtual']:
|
|
agenda.kind = kind
|
|
agenda.save()
|
|
resp = app.get('/manage/agendas/%s/settings/' % agenda.slug, status=302)
|
|
assert resp.location.endswith('/manage/agendas/%s/settings' % agenda.pk)
|
|
|
|
|
|
def test_options_agenda(app, admin_user):
|
|
agenda_events = Agenda.objects.create(label='Foo bar', kind='events')
|
|
Desk.objects.create(agenda=agenda_events, slug='_exceptions_holder')
|
|
agenda_meetings = Agenda.objects.create(label='Foo bar', kind='meetings')
|
|
agenda_virtual = Agenda.objects.create(label='Foo bar', kind='virtual')
|
|
|
|
app = login(app)
|
|
resp = app.get('/manage/agendas/%s/edit' % agenda_events.pk)
|
|
assert resp.form['label'].value == 'Foo bar'
|
|
resp.form['label'] = 'Foo baz'
|
|
resp.form['anonymize_delay'] = 365
|
|
assert 'default_view' in resp.context['form'].fields
|
|
assert resp.context['form'].initial['default_view'] == 'month'
|
|
assert 'open_events' in [k for k, v in resp.context['form'].fields['default_view'].choices]
|
|
assert 'booking_form_url' in resp.context['form'].fields
|
|
resp = resp.form.submit()
|
|
assert resp.location.endswith('/manage/agendas/%s/settings' % agenda_events.pk)
|
|
resp = resp.follow()
|
|
assert 'has_resources' not in resp.context
|
|
assert 'Foo baz' in resp.text
|
|
assert '<h2>Settings' in resp.text
|
|
agenda_events.refresh_from_db()
|
|
assert agenda_events.anonymize_delay == 365
|
|
|
|
resp = app.get('/manage/agendas/%s/edit' % agenda_meetings.pk)
|
|
assert 'default_view' in resp.context['form'].fields
|
|
assert 'open_events' not in [k for k, v in resp.context['form'].fields['default_view'].choices]
|
|
assert 'booking_form_url' not in resp.context['form'].fields
|
|
|
|
resp.form['default_view'] = 'month'
|
|
resp.form.submit()
|
|
agenda_meetings.refresh_from_db()
|
|
assert agenda_meetings.default_view == 'month'
|
|
|
|
resp = app.get('/manage/agendas/%s/edit' % agenda_meetings.pk)
|
|
assert resp.form['default_view'].value == 'month'
|
|
assert 'open_events' not in [k for k, v in resp.context['form'].fields['default_view'].choices]
|
|
|
|
resp = app.get('/manage/agendas/%s/edit' % agenda_virtual.pk)
|
|
assert 'default_view' in resp.context['form'].fields
|
|
assert 'open_events' not in [k for k, v in resp.context['form'].fields['default_view'].choices]
|
|
assert 'booking_form_url' not in resp.context['form'].fields
|
|
|
|
|
|
def test_options_events_agenda_events_type(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Foo bar', kind='events')
|
|
|
|
app = login(app)
|
|
resp = app.get('/manage/agendas/%s/edit' % agenda.pk)
|
|
assert 'events_type' not in resp.context['form'].fields
|
|
|
|
events_type = EventsType.objects.create(label='Foo', slug='foo')
|
|
resp = app.get('/manage/agendas/%s/edit' % agenda.pk)
|
|
assert 'events_type' in resp.context['form'].fields
|
|
resp.form['events_type'] = events_type.pk
|
|
resp.form.submit()
|
|
agenda.refresh_from_db()
|
|
assert agenda.events_type == events_type
|
|
|
|
# check kind
|
|
agenda.kind = 'meetings'
|
|
agenda.save()
|
|
resp = app.get('/manage/agendas/%s/edit' % agenda.pk)
|
|
assert 'events_type' not in resp.context['form'].fields
|
|
agenda.kind = 'virtual'
|
|
agenda.save()
|
|
resp = app.get('/manage/agendas/%s/edit' % agenda.pk)
|
|
assert 'events_type' not in resp.context['form'].fields
|
|
|
|
|
|
def test_options_events_agenda_delays(settings, app, admin_user):
|
|
settings.WORKING_DAY_CALENDAR = None
|
|
agenda = Agenda.objects.create(label='Foo bar')
|
|
assert agenda.minimal_booking_delay == 1
|
|
app = login(app)
|
|
url = '/manage/agendas/%s/booking-delays' % agenda.pk
|
|
resp = app.get(url)
|
|
assert 'minimal_booking_delay_in_working_days' not in resp.context['form'].fields
|
|
resp.form['minimal_booking_delay'] = None
|
|
resp = resp.form.submit()
|
|
agenda.refresh_from_db()
|
|
assert agenda.minimal_booking_delay == 1
|
|
|
|
settings.WORKING_DAY_CALENDAR = 'workalendar.europe.France'
|
|
resp = app.get(url)
|
|
resp.form['minimal_booking_delay_in_working_days'] = True
|
|
resp = resp.form.submit()
|
|
agenda.refresh_from_db()
|
|
assert agenda.minimal_booking_delay_in_working_days is True
|
|
|
|
|
|
def test_options_events_agenda_lingo_link(settings, app, admin_user):
|
|
settings.KNOWN_SERVICES = {}
|
|
agenda = Agenda.objects.create(label='Foo bar')
|
|
|
|
app = login(app)
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
|
|
assert 'Pricing' not in resp
|
|
assert '/manage/pricing/agenda/%s/' % agenda.slug not in resp
|
|
|
|
settings.KNOWN_SERVICES['lingo'] = {'default': {'url': 'https://lingo.dev/'}}
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
|
|
assert 'https://lingo.dev/manage/pricing/agenda/%s/' % agenda.slug in resp
|
|
|
|
|
|
def test_options_virtual_agenda_delays(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Foo bar', kind='virtual', maximal_booking_delay=2)
|
|
assert agenda.maximal_booking_delay == 2
|
|
app = login(app)
|
|
url = '/manage/agendas/%s/booking-delays' % agenda.pk
|
|
resp = app.get(url)
|
|
assert 'minimal_booking_delay_in_working_days' not in resp.context['form'].fields
|
|
resp.form['maximal_booking_delay'] = None
|
|
resp = resp.form.submit()
|
|
agenda.refresh_from_db()
|
|
assert agenda.maximal_booking_delay is None
|
|
|
|
|
|
def test_options_agenda_booking_display_options(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Foo bar', kind='events')
|
|
|
|
app = login(app)
|
|
|
|
# check user template
|
|
assert agenda.booking_user_block_template == ''
|
|
assert (
|
|
agenda.get_booking_user_block_template()
|
|
== '{{ booking.user_name|default:booking.label|default:"Anonymous" }}'
|
|
)
|
|
|
|
url = '/manage/agendas/%s/display-options' % agenda.pk
|
|
resp = app.get(url)
|
|
resp.form['booking_user_block_template'] = '{{ booking.user_name }} Foo Bar'
|
|
resp = resp.form.submit()
|
|
agenda.refresh_from_db()
|
|
assert agenda.booking_user_block_template == '{{ booking.user_name }} Foo Bar'
|
|
assert agenda.get_booking_user_block_template() == '{{ booking.user_name }} Foo Bar'
|
|
|
|
resp = app.get(url)
|
|
resp.form['booking_user_block_template'] = ''
|
|
resp = resp.form.submit()
|
|
agenda.refresh_from_db()
|
|
assert agenda.booking_user_block_template == ''
|
|
assert (
|
|
agenda.get_booking_user_block_template()
|
|
== '{{ booking.user_name|default:booking.label|default:"Anonymous" }}'
|
|
)
|
|
|
|
resp = app.get(url)
|
|
valid_template = '{{ event.label|default:event.slug }} - {{ event.remaining_places|add:"5" }} / {{ event.start_datetime|date }} - {{ event.agenda.name }}'
|
|
resp.form['event_display_template'] = valid_template
|
|
resp = resp.form.submit().follow()
|
|
|
|
agenda.refresh_from_db()
|
|
assert agenda.event_display_template == valid_template
|
|
|
|
invalid_templates = [
|
|
'{{ syntax error }}',
|
|
'{{ event.label|invalidfilter }}',
|
|
'{{ event.label|default:notexist }}',
|
|
]
|
|
for template in invalid_templates:
|
|
resp = app.get(url)
|
|
resp.form['event_display_template'] = template
|
|
resp = resp.form.submit()
|
|
assert 'syntax error' in resp.text
|
|
|
|
# and for meetings agenda
|
|
agenda.kind = 'meetings'
|
|
agenda.save()
|
|
resp = app.get(url)
|
|
assert 'event_display_template' not in resp.form.fields
|
|
assert 'booking_user_block_template' in resp.form.fields
|
|
|
|
# check kind
|
|
agenda.kind = 'virtual'
|
|
agenda.save()
|
|
app.get(url, status=404)
|
|
|
|
|
|
def test_options_agenda_booking_check_options(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Foo bar', kind='events')
|
|
|
|
app = login(app)
|
|
|
|
# check filters
|
|
assert agenda.booking_check_filters == ''
|
|
assert agenda.get_booking_check_filters() == []
|
|
|
|
url = '/manage/agendas/%s/check-options' % agenda.pk
|
|
resp = app.get(url)
|
|
resp.form['booking_check_filters'] = 'foo,bar,baz'
|
|
resp = resp.form.submit()
|
|
agenda.refresh_from_db()
|
|
assert agenda.booking_check_filters == 'foo,bar,baz'
|
|
assert agenda.get_booking_check_filters() == ['foo', 'bar', 'baz']
|
|
|
|
# check auto checked
|
|
assert agenda.mark_event_checked_auto is False
|
|
resp = app.get(url)
|
|
resp.form['mark_event_checked_auto'] = True
|
|
resp = resp.form.submit()
|
|
agenda.refresh_from_db()
|
|
assert agenda.mark_event_checked_auto is True
|
|
|
|
# check disable check
|
|
assert agenda.disable_check_update is False
|
|
resp = app.get(url)
|
|
resp.form['disable_check_update'] = True
|
|
resp = resp.form.submit()
|
|
agenda.refresh_from_db()
|
|
assert agenda.disable_check_update is True
|
|
|
|
# check kind
|
|
agenda.kind = 'meetings'
|
|
agenda.save()
|
|
app.get(url, status=404)
|
|
agenda.kind = 'virtual'
|
|
agenda.save()
|
|
app.get(url, status=404)
|
|
|
|
|
|
def test_options_agenda_as_manager(app, manager_user):
|
|
agenda = Agenda(label='Foo bar')
|
|
agenda.view_role = manager_user.groups.all()[0]
|
|
agenda.save()
|
|
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
|
app = login(app, username='manager', password='manager')
|
|
resp = app.get('/manage/', status=200)
|
|
resp = resp.click('Foo bar').follow().follow()
|
|
assert 'Settings' not in resp.text
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=403)
|
|
resp = app.get('/manage/agendas/%s/edit' % agenda.id, status=403)
|
|
agenda.kind = 'meetings'
|
|
agenda.save()
|
|
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=403)
|
|
resp = app.get('/manage/agendas/%s/edit' % agenda.id, status=403)
|
|
|
|
agenda.kind = 'events'
|
|
agenda.save()
|
|
|
|
agenda.edit_role = manager_user.groups.all()[0]
|
|
agenda.save()
|
|
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
|
|
resp = resp.click('Options')
|
|
assert resp.form['label'].value == 'Foo bar'
|
|
resp.form['label'] = 'Foo baz'
|
|
resp = resp.form.submit()
|
|
assert resp.location.endswith('/manage/agendas/%s/settings' % agenda.id)
|
|
resp = resp.follow()
|
|
assert 'Foo baz' in resp.text
|
|
assert '<h2>Settings' in resp.text
|
|
|
|
|
|
@mock.patch('chrono.agendas.models.Agenda.is_available_for_simple_management')
|
|
def test_agenda_options_desk_simple_management(available_mock, app, admin_user):
|
|
agenda = Agenda.objects.create(label='Foo bar', kind='meetings')
|
|
app = login(app)
|
|
|
|
available_mock.return_value = True
|
|
assert agenda.desk_simple_management is False
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
|
|
assert '/manage/agendas/%s/desk-management-toggle' % agenda.pk in resp.text
|
|
agenda.desk_simple_management = True
|
|
agenda.save()
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
|
|
assert '/manage/agendas/%s/desk-management-toggle' % agenda.pk in resp.text
|
|
|
|
available_mock.return_value = False
|
|
agenda.desk_simple_management = False
|
|
agenda.save()
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
|
|
assert '/manage/agendas/%s/desk-management-toggle' % agenda.pk not in resp.text
|
|
agenda.desk_simple_management = True
|
|
agenda.save()
|
|
# always possible to disable this flag
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
|
|
assert '/manage/agendas/%s/desk-management-toggle' % agenda.pk in resp.text
|
|
|
|
available_mock.return_value = True
|
|
for old_value in [True, False]:
|
|
agenda.desk_simple_management = old_value
|
|
agenda.save()
|
|
resp = app.get('/manage/agendas/%s/desk-management-toggle' % agenda.pk)
|
|
assert resp.location.endswith('/manage/agendas/%s/settings' % agenda.pk)
|
|
agenda.refresh_from_db()
|
|
# was changed
|
|
assert agenda.desk_simple_management is not old_value
|
|
|
|
available_mock.return_value = False
|
|
for old_value in [True, False]:
|
|
agenda.desk_simple_management = old_value
|
|
agenda.save()
|
|
resp = app.get('/manage/agendas/%s/desk-management-toggle' % agenda.pk)
|
|
assert resp.location.endswith('/manage/agendas/%s/settings' % agenda.pk)
|
|
agenda.refresh_from_db()
|
|
# not possible to enable flag
|
|
assert agenda.desk_simple_management is False
|
|
|
|
# unknown pk
|
|
app.get('/manage/agendas/0/desk-management-toggle', status=404)
|
|
|
|
# check kind
|
|
agenda.kind = 'events'
|
|
agenda.save()
|
|
app.get('/manage/agendas/%s/desk-management-toggle' % agenda.pk, status=404)
|
|
agenda.kind = 'virtual'
|
|
agenda.save()
|
|
app.get('/manage/agendas/%s/desk-management-toggle' % agenda.pk, status=404)
|
|
|
|
|
|
def test_delete_agenda(app, admin_user):
|
|
agenda = Agenda(label='Foo bar')
|
|
agenda.save()
|
|
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
|
app = login(app)
|
|
resp = app.get('/manage/', status=200)
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
|
|
resp = resp.click('Delete')
|
|
resp = resp.form.submit()
|
|
assert resp.location.endswith('/manage/')
|
|
resp = resp.follow()
|
|
assert 'Foo bar' not in resp.text
|
|
|
|
|
|
def test_delete_busy_agenda(app, admin_user):
|
|
agenda = Agenda(label='Foo bar')
|
|
agenda.save()
|
|
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
|
event = Event(start_datetime=now() + datetime.timedelta(days=10), places=10, agenda=agenda)
|
|
event.save()
|
|
|
|
app = login(app)
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id)
|
|
resp = resp.click('Delete')
|
|
assert 'Are you sure you want to delete this?' in resp.text
|
|
|
|
booking = Booking(event=event)
|
|
booking.save()
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id)
|
|
resp = resp.click('Delete')
|
|
assert 'This cannot be removed' in resp.text
|
|
|
|
booking.cancellation_datetime = now()
|
|
booking.save()
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id)
|
|
resp = resp.click('Delete')
|
|
assert 'Are you sure you want to delete this?' in resp.text
|
|
|
|
# suddenly the booking is no longer cancelled, but the admin clicks on the
|
|
# delete button.
|
|
booking.cancellation_datetime = None
|
|
booking.save()
|
|
resp = resp.form.submit(status=403)
|
|
|
|
|
|
def test_delete_agenda_as_manager(app, manager_user):
|
|
agenda = Agenda(label='Foo bar')
|
|
agenda.edit_role = manager_user.groups.all()[0]
|
|
agenda.save()
|
|
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
|
app = login(app, username='manager', password='manager')
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
|
|
assert 'Options' in resp.text
|
|
assert 'Delete' not in resp.text
|
|
resp = app.get('/manage/agendas/%s/delete' % agenda.id, status=403)
|
|
|
|
|
|
def test_delete_busy_desk(app, admin_user):
|
|
agenda = Agenda(label='Foo bar', kind='meetings')
|
|
agenda.save()
|
|
desk_a = Desk.objects.create(agenda=agenda, label='Desk A')
|
|
Desk.objects.create(agenda=agenda, label='Desk B')
|
|
|
|
event = Event(start_datetime=now() + datetime.timedelta(days=10), places=10, agenda=agenda, desk=desk_a)
|
|
event.save()
|
|
|
|
app = login(app)
|
|
resp = app.get('/manage/', status=200)
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
|
|
desk_page = resp.click('Desk A')
|
|
desk_delete_page = desk_page.click('Delete')
|
|
assert 'Are you sure you want to delete this?' in desk_delete_page.text
|
|
# make sure the deleting is not disabled
|
|
assert 'disabled' not in desk_delete_page.text
|
|
|
|
booking = Booking(event=event)
|
|
booking.save()
|
|
|
|
resp = desk_page.click('Delete')
|
|
assert 'This cannot be removed' in resp.text
|
|
# the button is disabled
|
|
assert 'disabled' in resp.text
|
|
app.post('/manage/desks/%s/delete' % desk_a.pk, status=403)
|
|
|
|
|
|
def test_add_meetings_agenda(app, admin_user):
|
|
app = login(app)
|
|
resp = app.get('/manage/', status=200)
|
|
resp = resp.click('New')
|
|
resp.form['label'] = 'Foo bar'
|
|
resp.form['kind'] = 'meetings'
|
|
resp = resp.form.submit()
|
|
agenda = Agenda.objects.get(label='Foo bar')
|
|
assert resp.location.endswith('/manage/agendas/%s/settings' % agenda.id)
|
|
resp = resp.follow()
|
|
assert 'Foo bar' in resp.text
|
|
assert '<h2>Settings' in resp.text
|
|
assert 'Meeting Types' in resp.text
|
|
agenda = Agenda.objects.get(label='Foo bar')
|
|
assert agenda.kind == 'meetings'
|
|
|
|
|
|
def test_agenda_day_view(app, admin_user, manager_user, api_user, get_proper_html_str):
|
|
agenda = Agenda.objects.create(label='New Example', kind='meetings')
|
|
desk = Desk.objects.create(agenda=agenda, label='New Desk')
|
|
desk.save()
|
|
today = datetime.date.today()
|
|
|
|
meetingtype = MeetingType(agenda=agenda, label='Bar', duration=30)
|
|
meetingtype.save()
|
|
|
|
login(app)
|
|
app.get('/manage/agendas/%s/day/%d/%d/%d/' % (agenda.pk, today.year, 42, today.day), status=404)
|
|
resp = app.get('/manage/agendas/%s/day/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert 'No opening hours this day.' in resp.text # no time pediod
|
|
|
|
timeperiod = TimePeriod(
|
|
desk=desk, weekday=today.weekday(), start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
|
|
)
|
|
timeperiod.save()
|
|
resp = app.get('/manage/agendas/%s/day/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert 'No opening hours this day.' not in resp.text
|
|
assert 'div class="booking' not in resp.text
|
|
assert resp.text.count('<tr') == 9 # 10->18 (not included)
|
|
|
|
timeperiod.end_time = datetime.time(18, 30) # end during an hour
|
|
timeperiod.save()
|
|
resp = app.get('/manage/agendas/%s/day/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert resp.text.count('<tr') == 10 # 10->18 (included)
|
|
|
|
# check opening hours cells
|
|
assert '<div class="opening-hours"' in resp.text
|
|
assert 'style="height: 850%; top: 0%;"' in resp.text
|
|
|
|
# book some slots
|
|
app.reset()
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
resp = app.get('/api/agenda/%s/meetings/%s/datetimes/' % (agenda.slug, meetingtype.slug))
|
|
booking_url = resp.json['data'][0]['api']['fillslot_url']
|
|
booking_url2 = resp.json['data'][2]['api']['fillslot_url']
|
|
resp = app.post(booking_url)
|
|
resp = app.post_json(
|
|
booking_url2, params={'label': 'foo', 'user_last_name': "bar's", 'url': 'http://baz/'}
|
|
)
|
|
|
|
app.reset()
|
|
login(app)
|
|
date = Booking.objects.all()[0].event.start_datetime
|
|
resp = app.get('/manage/agendas/%s/day/%d/%d/%d/' % (agenda.id, date.year, date.month, date.day))
|
|
assert resp.text.count('div class="booking') == 2
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[0].text.strip() == 'booked'
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[1].text.strip() == "foo - bar's"
|
|
assert get_proper_html_str('foo - bar's') in resp
|
|
assert 'hourspan-2' in resp.text # table CSS class
|
|
assert 'height: 50%; top: 0%;' in resp.text # booking cells
|
|
|
|
agenda.booking_user_block_template = '<b>{{ booking.user_name }}</b> Foo Bar'
|
|
agenda.save()
|
|
resp = app.get('/manage/agendas/%s/day/%d/%d/%d/' % (agenda.id, date.year, date.month, date.day))
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[0].text.strip() == '<b></b> Foo Bar'
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[1].text.strip() == "<b>bar's</b> Foo Bar"
|
|
assert get_proper_html_str('<b>bar's</b> Foo Bar') in resp
|
|
|
|
# create a shorter meeting type, this will change the table CSS class
|
|
# (and visually this will give more room for events)
|
|
meetingtype = MeetingType(agenda=agenda, label='Baz', duration=15)
|
|
meetingtype.save()
|
|
resp = app.get('/manage/agendas/%s/day/%d/%d/%d/' % (agenda.id, date.year, date.month, date.day))
|
|
assert resp.text.count('div class="booking') == 2
|
|
assert 'hourspan-4' in resp.text # table CSS class
|
|
|
|
# cancel a booking
|
|
app.reset()
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
booking = Booking.objects.all()[0]
|
|
resp = app.post('/api/booking/%s/cancel/' % booking.id)
|
|
assert Booking.objects.filter(cancellation_datetime__isnull=False).count() == 1
|
|
|
|
app.reset()
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/day/%d/%d/%d/' % (agenda.id, date.year, date.month, date.day))
|
|
assert resp.text.count('div class="booking') == 1
|
|
|
|
# not enough permissions
|
|
app.reset()
|
|
app = login(app, username='manager', password='manager')
|
|
resp = app.get(
|
|
'/manage/agendas/%s/day/%d/%d/%d/' % (agenda.id, date.year, date.month, date.day), status=403
|
|
)
|
|
|
|
# just enough permissions
|
|
agenda.view_role = manager_user.groups.all()[0]
|
|
agenda.save()
|
|
resp = app.get(
|
|
'/manage/agendas/%s/day/%d/%d/%d/' % (agenda.id, date.year, date.month, date.day), status=200
|
|
)
|
|
|
|
# display exception
|
|
unavailability_calendar = UnavailabilityCalendar.objects.create(label='calendar')
|
|
TimePeriodException.objects.create(
|
|
label='Calendar exception',
|
|
unavailability_calendar=unavailability_calendar,
|
|
start_datetime=make_aware(datetime.datetime(date.year, date.month, date.day, 13, 0)),
|
|
end_datetime=make_aware(datetime.datetime(date.year, date.month, date.day, 15, 0)),
|
|
)
|
|
unavailability_calendar.desks.add(desk)
|
|
TimePeriodException.objects.create(
|
|
label='Exception for the afternoon',
|
|
desk=desk,
|
|
start_datetime=make_aware(datetime.datetime(date.year, date.month, date.day, 16, 0)),
|
|
end_datetime=make_aware(datetime.datetime(date.year, date.month, date.day, 23, 0)),
|
|
)
|
|
with CaptureQueriesContext(connection) as ctx:
|
|
resp = app.get(
|
|
'/manage/agendas/%s/day/%d/%d/%d/' % (agenda.id, date.year, date.month, date.day), status=200
|
|
)
|
|
assert len(ctx.captured_queries) == 14
|
|
# day is displaying rows from 10am to 6pm,
|
|
# opening hours, 10am to 1pm gives top: 300%
|
|
# calendar exception, 1pm to 3pm gives heigh: 200%
|
|
assert resp.pyquery.find('.exception-hours')[0].attrib == {
|
|
'class': 'exception-hours',
|
|
'style': 'height: 200%; top: 300%;',
|
|
}
|
|
assert resp.pyquery.find('.exception-hours span')[0].text == 'Calendar exception'
|
|
# rest of the day, opened from 3pm to 4pm, since we left off at 500% it gives top: 600%
|
|
# then exception from 4pm to 6pm included, gives height: 300%
|
|
assert resp.pyquery.find('.exception-hours')[1].attrib == {
|
|
'class': 'exception-hours',
|
|
'style': 'height: 300%; top: 600%;',
|
|
}
|
|
assert resp.pyquery.find('.exception-hours span')[1].text == 'Exception for the afternoon'
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
'view',
|
|
(
|
|
'/manage/agendas/%(agenda)s/day/%(year)d/%(month)d/%(day)d/',
|
|
'/manage/agendas/%(agenda)s/week/%(year)d/%(month)d/%(day)d/',
|
|
'/manage/agendas/%(agenda)s/month/%(year)d/%(month)d/%(day)d/',
|
|
),
|
|
)
|
|
def test_agenda_day_week_month_view_backoffice_url_translation(
|
|
app, admin_user, manager_user, api_user, settings, view
|
|
):
|
|
agenda = Agenda.objects.create(label='New Example', kind='meetings')
|
|
desk = Desk.objects.create(agenda=agenda, label='New Desk')
|
|
desk.save()
|
|
today = datetime.date.today()
|
|
meetingtype = MeetingType(agenda=agenda, label='Bar', duration=30)
|
|
meetingtype.save()
|
|
timeperiod = TimePeriod.objects.create(
|
|
desk=desk, weekday=today.weekday(), start_time=datetime.time(10, 0), end_time=datetime.time(18, 30)
|
|
)
|
|
timeperiod.save()
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
login(app)
|
|
|
|
resp = app.get('/api/agenda/%s/meetings/%s/datetimes/' % (agenda.slug, meetingtype.slug))
|
|
booking_url = resp.json['data'][0]['api']['fillslot_url']
|
|
|
|
# unkown service, backoffice url stored and displayed as is
|
|
backoffice_url = 'http://example.net/foo/bar/'
|
|
resp = app.post(booking_url, params={'backoffice_url': backoffice_url})
|
|
cancel_url = resp.json['api']['cancel_url']
|
|
booking_id = resp.json['booking_id']
|
|
booking = Booking.objects.get(pk=booking_id)
|
|
assert booking.backoffice_url == backoffice_url
|
|
date = booking.event.start_datetime
|
|
url = view % {
|
|
'agenda': agenda.id,
|
|
'year': date.year,
|
|
'month': date.month,
|
|
'day': date.day,
|
|
}
|
|
resp = app.get(url)
|
|
assert resp.text.count('div class="booking') == 1
|
|
assert backoffice_url in resp.text
|
|
|
|
# reset booking
|
|
resp = app.post(cancel_url)
|
|
assert resp.json['err'] == 0
|
|
|
|
# known service, backoffice url stored translated and displayed as it was passed
|
|
backoffice_url = 'http://example.org/backoffice/bar/'
|
|
resp = app.post(booking_url, params={'backoffice_url': backoffice_url})
|
|
cancel_url = resp.json['api']['cancel_url']
|
|
booking_id = resp.json['booking_id']
|
|
booking = Booking.objects.get(pk=booking_id)
|
|
assert booking.backoffice_url == 'publik://default/backoffice/bar/'
|
|
date = booking.event.start_datetime
|
|
resp = app.get(url)
|
|
assert resp.text.count('div class="booking') == 1
|
|
assert backoffice_url in resp.text
|
|
|
|
|
|
@pytest.mark.parametrize('kind', ['meetings', 'virtual'])
|
|
def test_agenda_day_view_late_meeting(app, admin_user, kind):
|
|
today = datetime.date.today()
|
|
if kind == 'meetings':
|
|
agenda = Agenda.objects.create(label='New Example', kind='meetings')
|
|
desk = Desk.objects.create(agenda=agenda, label='New Desk')
|
|
MeetingType.objects.create(agenda=agenda, label='Bar', duration=30)
|
|
else:
|
|
agenda = Agenda.objects.create(label='Virtual', kind='virtual')
|
|
real_agenda = Agenda.objects.create(label='Real', kind='meetings')
|
|
VirtualMember.objects.create(virtual_agenda=agenda, real_agenda=real_agenda)
|
|
desk = Desk.objects.create(agenda=real_agenda, label='New Desk')
|
|
MeetingType.objects.create(agenda=real_agenda, label='Bar', duration=30)
|
|
TimePeriod.objects.create(
|
|
desk=desk, weekday=today.weekday(), start_time=datetime.time(10, 0), end_time=datetime.time(23, 30)
|
|
)
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/day/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert resp.text.count('<tr') == 15
|
|
assert '<th class="hour">11 p.m.</th>' in resp.text
|
|
|
|
|
|
@pytest.mark.parametrize('kind', ['meetings', 'virtual'])
|
|
def test_agenda_invalid_day_view(app, admin_user, kind):
|
|
if kind == 'meetings':
|
|
agenda = Agenda.objects.create(label='New Example', kind='meetings')
|
|
Desk.objects.create(agenda=agenda, label='New Desk')
|
|
MeetingType.objects.create(agenda=agenda, label='Bar', duration=30)
|
|
else:
|
|
agenda = Agenda.objects.create(label='Virtual', kind='virtual')
|
|
real_agenda = Agenda.objects.create(label='Real', kind='meetings')
|
|
VirtualMember.objects.create(virtual_agenda=agenda, real_agenda=real_agenda)
|
|
Desk.objects.create(agenda=real_agenda, label='New Desk')
|
|
MeetingType.objects.create(agenda=real_agenda, label='Bar', duration=30)
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/day/%d/%d/%d/' % (agenda.id, 2018, 11, 31), status=302)
|
|
assert resp.location.endswith('2018/11/30/')
|
|
|
|
|
|
@pytest.mark.parametrize('kind', ['meetings', 'virtual'])
|
|
def test_agenda_day_view_event_outside_timeperiod(app, admin_user, kind):
|
|
if kind == 'meetings':
|
|
today = datetime.date.today()
|
|
agenda = Agenda.objects.create(label='New Example', kind='meetings')
|
|
desk = Desk.objects.create(agenda=agenda, label='New Desk')
|
|
meetingtype = MeetingType.objects.create(agenda=agenda, label='Bar', duration=30)
|
|
else:
|
|
today = datetime.date.today()
|
|
agenda = Agenda.objects.create(label='Virtual', kind='virtual')
|
|
real_agenda = Agenda.objects.create(label='Real', kind='meetings')
|
|
VirtualMember.objects.create(virtual_agenda=agenda, real_agenda=real_agenda)
|
|
desk = Desk.objects.create(agenda=real_agenda, label='New Desk')
|
|
meetingtype = MeetingType.objects.create(agenda=real_agenda, label='Bar', duration=30)
|
|
|
|
login(app)
|
|
|
|
# no time period - no events
|
|
resp = app.get('/manage/agendas/%s/day/%d/%d/%d/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert 'No opening hours this day.' in resp.text
|
|
assert 'div class="booking' not in resp.text
|
|
|
|
# book some slots
|
|
for hour, minute in [(9, 0), (17, 0)]:
|
|
event = Event.objects.create(
|
|
agenda=desk.agenda,
|
|
places=1,
|
|
desk=desk,
|
|
meeting_type=meetingtype,
|
|
start_datetime=localtime(now()).replace(hour=hour, minute=minute),
|
|
)
|
|
Booking.objects.create(event=event)
|
|
|
|
# no time period - events are displayed
|
|
resp = app.get('/manage/agendas/%s/day/%d/%d/%d/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert resp.text.count('div class="booking') == 2
|
|
|
|
# bookings are cancelled
|
|
Booking.objects.update(cancellation_datetime=now())
|
|
resp = app.get('/manage/agendas/%s/day/%d/%d/%d/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert 'No opening hours this day.' in resp.text
|
|
assert resp.text.count('div class="booking') == 0
|
|
|
|
# events outside time period
|
|
Booking.objects.update(cancellation_datetime=None) # reset
|
|
TimePeriod.objects.create(
|
|
desk=desk, weekday=today.weekday(), start_time=datetime.time(10, 0), end_time=datetime.time(16, 0)
|
|
)
|
|
resp = app.get('/manage/agendas/%s/day/%d/%d/%d/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert resp.text.count('div class="booking') == 2
|
|
assert '<div class="opening-hours"' in resp.text
|
|
assert 'style="height: 600%; top: 100%;"' in resp.text
|
|
|
|
|
|
@freezegun.freeze_time('2020-10-01')
|
|
def test_agenda_events_day_view(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Events', kind='events')
|
|
today = datetime.date.today()
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/day/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert '>Month<' in resp.text
|
|
assert '>Week<' in resp.text
|
|
assert '>Day<' in resp.text
|
|
assert "This day doesn't have any event configured." in resp.text
|
|
|
|
# event
|
|
Event.objects.create(
|
|
label='xyz', start_datetime=localtime().replace(day=11, month=11, year=2020), places=10, agenda=agenda
|
|
)
|
|
recurring_start_datetime = localtime().replace(day=4, month=11, year=2020)
|
|
event = Event.objects.create(
|
|
label='abc',
|
|
start_datetime=recurring_start_datetime,
|
|
places=10,
|
|
agenda=agenda,
|
|
recurrence_days=[recurring_start_datetime.weekday()],
|
|
recurrence_end_date=recurring_start_datetime + datetime.timedelta(days=15),
|
|
)
|
|
event.create_all_recurrences()
|
|
|
|
with CaptureQueriesContext(connection) as ctx:
|
|
resp = app.get('/manage/agendas/%s/day/2020/11/11/' % agenda.pk)
|
|
assert len(ctx.captured_queries) == 5
|
|
|
|
assert len(resp.pyquery.find('.event-info')) == 2
|
|
assert 'abc' in resp.pyquery.find('.event-info')[0].text
|
|
assert 'xyz' in resp.pyquery.find('.event-info')[1].text
|
|
|
|
resp = app.get('/manage/agendas/%s/day/2020/11/11/' % agenda.pk)
|
|
assert len(resp.pyquery.find('.event-info')) == 2
|
|
|
|
# create another event with recurrence, the same day/time
|
|
start_datetime = localtime().replace(day=4, month=11, year=2020)
|
|
event = Event.objects.create(
|
|
label='def',
|
|
start_datetime=start_datetime,
|
|
places=10,
|
|
agenda=agenda,
|
|
recurrence_days=[start_datetime.weekday()],
|
|
recurrence_end_date=start_datetime + datetime.timedelta(days=15),
|
|
)
|
|
event.create_all_recurrences()
|
|
resp = app.get('/manage/agendas/%s/day/2020/11/11/' % agenda.pk)
|
|
assert len(resp.pyquery.find('.event-info')) == 3
|
|
|
|
|
|
def test_agenda_events_day_view_midnight(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Events', kind='events', default_view='day')
|
|
midnight = localtime(now().replace(day=11, month=11, year=2020)).replace(hour=0, minute=0)
|
|
Event.objects.create(label='xyz', start_datetime=midnight, places=10, agenda=agenda)
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/day/' % agenda.pk)
|
|
assert resp.location.endswith('day/2020/11/11/')
|
|
resp = resp.follow()
|
|
assert len(resp.pyquery.find('.event-info')) == 1
|
|
|
|
|
|
@freezegun.freeze_time('2020-10-01')
|
|
def test_agenda_events_week_view(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Events', kind='events')
|
|
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
|
today = datetime.date.today()
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert '>Month<' in resp.text
|
|
assert '>Week<' in resp.text
|
|
assert '>Day<' in resp.text
|
|
assert "This week doesn't have any event configured." in resp.text
|
|
|
|
# add event in a future month, a wednesday
|
|
Event.objects.create(
|
|
label='xyz', start_datetime=localtime().replace(day=11, month=11, year=2020), places=10, agenda=agenda
|
|
)
|
|
# current month still doesn't have events
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert "This week doesn't have any event configured." in resp.text
|
|
|
|
# add recurring event on every Wednesday
|
|
start_datetime = localtime().replace(day=4, month=11, year=2020)
|
|
event = Event.objects.create(
|
|
label='abc',
|
|
start_datetime=start_datetime,
|
|
places=10,
|
|
agenda=agenda,
|
|
recurrence_days=[start_datetime.weekday()],
|
|
recurrence_end_date=start_datetime + datetime.timedelta(days=60),
|
|
)
|
|
event.create_all_recurrences()
|
|
|
|
with CaptureQueriesContext(connection) as ctx:
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.pk, 2020, 11, 11))
|
|
assert len(ctx.captured_queries) == 7
|
|
assert len(resp.pyquery.find('.event-info')) == 2
|
|
assert 'abc' in resp.pyquery.find('.event-info')[0].text
|
|
assert 'xyz' in resp.pyquery.find('.event-info')[1].text
|
|
|
|
TimePeriodException.objects.create(
|
|
desk=agenda.desk_set.get(),
|
|
start_datetime=start_datetime + datetime.timedelta(days=6),
|
|
end_datetime=start_datetime + datetime.timedelta(days=8),
|
|
)
|
|
agenda.update_event_recurrences()
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.pk, 2020, 11, 11))
|
|
assert len(resp.pyquery.find('.event-info')) == 1
|
|
assert 'Exception: 11/10/2020' in resp.pyquery.find('li')[4].text_content()
|
|
assert 'xyz' in resp.pyquery.find('li')[5].text_content()
|
|
|
|
# create another event with recurrence, the same day/time
|
|
start_datetime = localtime().replace(day=4, month=11, year=2020)
|
|
event = Event.objects.create(
|
|
label='def',
|
|
start_datetime=start_datetime,
|
|
places=10,
|
|
agenda=agenda,
|
|
recurrence_days=[start_datetime.weekday()],
|
|
recurrence_end_date=start_datetime + datetime.timedelta(days=60),
|
|
)
|
|
event.create_all_recurrences()
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.pk, 2020, 12, 7))
|
|
assert len(resp.pyquery.find('.event-info')) == 2
|
|
|
|
time = localtime(event.start_datetime).strftime('%H%M')
|
|
resp = resp.click('Dec. 9, 2020, 1 a.m.', index=1)
|
|
resp = resp.click('Options')
|
|
resp.form['start_datetime_1'] = '13:12'
|
|
resp = resp.form.submit(status=302).follow()
|
|
agenda.update_event_recurrences()
|
|
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.pk, 2020, 12, 7))
|
|
assert len(resp.pyquery.find('.event-info')) == 2
|
|
assert '1:12 p.m.' in resp.text
|
|
|
|
Event.objects.get(slug='abc--2020-12-02-%s' % time).cancel()
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.pk, 2020, 11, 30))
|
|
assert 'Cancelled' in resp.text
|
|
|
|
|
|
def test_agenda_events_week_view_midnight(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Events', kind='events', default_view='day')
|
|
midnight = localtime(now().replace(day=1, month=11, year=2020)).replace(hour=0, minute=0)
|
|
Event.objects.create(label='xyz', start_datetime=midnight, places=10, agenda=agenda)
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/week/' % agenda.pk)
|
|
assert resp.location.endswith('week/2020/11/01/')
|
|
resp = resp.follow()
|
|
assert len(resp.pyquery.find('.event-info')) == 1
|
|
|
|
|
|
@freezegun.freeze_time('2020-10-01')
|
|
def test_agenda_events_month_view(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Events', kind='events')
|
|
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
|
today = datetime.date.today()
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert '>Month<' in resp.text
|
|
assert '>Week<' in resp.text
|
|
assert '>Day<' in resp.text
|
|
assert "This month doesn't have any event configured." in resp.text
|
|
|
|
# add event in a future month, a wednesday
|
|
Event.objects.create(
|
|
label='xyz', start_datetime=localtime().replace(day=11, month=11, year=2020), places=10, agenda=agenda
|
|
)
|
|
# current month still doesn't have events
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert "This month doesn't have any event configured." in resp.text
|
|
|
|
# add recurring event on every Wednesday
|
|
start_datetime = localtime().replace(day=4, month=11, year=2020)
|
|
event = Event.objects.create(
|
|
label='abc',
|
|
start_datetime=start_datetime,
|
|
places=10,
|
|
agenda=agenda,
|
|
recurrence_days=[start_datetime.weekday()],
|
|
recurrence_end_date=start_datetime + datetime.timedelta(days=60),
|
|
)
|
|
event.create_all_recurrences()
|
|
|
|
with CaptureQueriesContext(connection) as ctx:
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.pk, 2020, 11, 1))
|
|
assert len(ctx.captured_queries) == 7
|
|
assert len(resp.pyquery.find('.event-info')) == 5
|
|
assert 'abc' in resp.pyquery.find('.event-info')[0].text
|
|
assert 'abc' in resp.pyquery.find('.event-info')[1].text
|
|
assert 'xyz' in resp.pyquery.find('.event-info')[2].text
|
|
assert 'abc' in resp.pyquery.find('.event-info')[3].text
|
|
assert 'abc' in resp.pyquery.find('.event-info')[4].text
|
|
|
|
TimePeriodException.objects.create(
|
|
desk=agenda.desk_set.get(),
|
|
start_datetime=start_datetime + datetime.timedelta(days=6),
|
|
end_datetime=start_datetime + datetime.timedelta(days=8),
|
|
)
|
|
agenda.update_event_recurrences()
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.pk, 2020, 11, 1))
|
|
assert len(resp.pyquery.find('.event-info')) == 4
|
|
assert 'abc' in resp.pyquery.find('li')[4].text_content()
|
|
assert 'Exception: 11/10/2020' in resp.pyquery.find('li')[5].text_content()
|
|
assert 'xyz' in resp.pyquery.find('li')[6].text_content()
|
|
|
|
# 12/2020 has 5 Wednesday
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.pk, 2020, 12, 1))
|
|
assert len(resp.pyquery.find('.event-info')) == 5
|
|
|
|
# create another event with recurrence, the same day/time
|
|
start_datetime = localtime().replace(day=4, month=11, year=2020)
|
|
event = Event.objects.create(
|
|
label='def',
|
|
start_datetime=start_datetime,
|
|
places=10,
|
|
agenda=agenda,
|
|
recurrence_days=[start_datetime.weekday()],
|
|
recurrence_end_date=start_datetime + datetime.timedelta(days=60),
|
|
)
|
|
event.create_all_recurrences()
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.pk, 2020, 12, 1))
|
|
assert len(resp.pyquery.find('.event-info')) == 10
|
|
|
|
time = localtime(event.start_datetime).strftime('%H%M')
|
|
resp = resp.click('Dec. 9, 2020, 1 a.m.', index=1)
|
|
resp = resp.click('Options')
|
|
resp.form['start_datetime_1'] = '13:12'
|
|
resp = resp.form.submit(status=302).follow()
|
|
agenda.update_event_recurrences()
|
|
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.pk, 2020, 12, 1))
|
|
assert len(resp.pyquery.find('.event-info')) == 10
|
|
assert '1:12 p.m.' in resp.text
|
|
|
|
Event.objects.get(slug='abc--2020-12-02-%s' % time).cancel()
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.pk, 2020, 12, 1))
|
|
assert 'Cancelled' in resp.text
|
|
|
|
bad_event_url = '/manage/agendas/%s/create_event_recurrence/abc:2020-10-8-1130/' % agenda.id
|
|
resp = app.get(bad_event_url, status=404)
|
|
|
|
|
|
def test_agenda_events_month_view_midnight(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Events', kind='events', default_view='day')
|
|
midnight = localtime(now().replace(day=1, month=11, year=2020)).replace(hour=0, minute=0)
|
|
Event.objects.create(label='xyz', start_datetime=midnight, places=10, agenda=agenda)
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/month/' % agenda.pk)
|
|
assert resp.location.endswith('month/2020/11/01/')
|
|
resp = resp.follow()
|
|
assert len(resp.pyquery.find('.event-info')) == 1
|
|
|
|
|
|
def test_agenda_open_events_view(app, admin_user, manager_user):
|
|
agenda = Agenda.objects.create(
|
|
label='Events', kind='events', minimal_booking_delay=2, maximal_booking_delay=5
|
|
)
|
|
today = datetime.date.today()
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert 'Open events' in resp.text
|
|
|
|
resp = app.get('/manage/agendas/%s/events/open/' % agenda.pk)
|
|
assert 'Month view' in resp.text
|
|
assert "This agenda doesn't have any open event configured." in resp.text
|
|
|
|
# create some events
|
|
# past event
|
|
Event.objects.create(
|
|
agenda=agenda, label='event A', start_datetime=now() - datetime.timedelta(days=1), places=42
|
|
)
|
|
# too late
|
|
Event.objects.create(
|
|
agenda=agenda, label='event B', start_datetime=now() + datetime.timedelta(days=1), places=42
|
|
)
|
|
# too soon
|
|
Event.objects.create(
|
|
agenda=agenda, label='event C', start_datetime=now() + datetime.timedelta(days=6), places=42
|
|
)
|
|
# in range
|
|
Event.objects.create(
|
|
agenda=agenda, label='event D', start_datetime=now() + datetime.timedelta(days=3), places=42
|
|
)
|
|
# publication date in future
|
|
Event.objects.create(
|
|
agenda=agenda,
|
|
label='event E',
|
|
start_datetime=now() + datetime.timedelta(days=3),
|
|
publication_datetime=now() + datetime.timedelta(days=1),
|
|
places=42,
|
|
)
|
|
# publication date in past
|
|
Event.objects.create(
|
|
agenda=agenda,
|
|
label='event F',
|
|
start_datetime=now() + datetime.timedelta(days=3),
|
|
publication_datetime=now() - datetime.timedelta(days=1),
|
|
places=42,
|
|
)
|
|
# weekly recurring event, first recurrence is in the past but second is in range
|
|
start_datetime = now() - datetime.timedelta(days=3)
|
|
event = Event.objects.create(
|
|
label='event G',
|
|
start_datetime=start_datetime,
|
|
places=10,
|
|
agenda=agenda,
|
|
recurrence_end_date=start_datetime + datetime.timedelta(days=30),
|
|
)
|
|
event.create_all_recurrences()
|
|
resp = app.get('/manage/agendas/%s/events/open/' % agenda.pk)
|
|
assert 'event A' not in resp.text
|
|
assert 'event B' not in resp.text
|
|
assert 'event C' not in resp.text
|
|
assert 'event D' in resp.text
|
|
assert 'event E' not in resp.text
|
|
assert 'event F' in resp.text
|
|
assert resp.text.count('event G') == 1
|
|
|
|
# event the first of February in 2 years at 00:00, already publicated
|
|
# and another event in January in 2 years
|
|
agenda.minimal_booking_delay = 0
|
|
agenda.maximal_booking_delay = 0
|
|
agenda.save()
|
|
Event.objects.create(
|
|
agenda=agenda,
|
|
label='event H',
|
|
start_datetime=now().replace(year=today.year + 2, month=1, day=15),
|
|
publication_datetime=now() - datetime.timedelta(days=1),
|
|
places=42,
|
|
)
|
|
start_datetime = localtime(now().replace(year=today.year + 2, month=2, day=1)).replace(hour=0, minute=0)
|
|
Event.objects.create(
|
|
agenda=agenda,
|
|
label='event H',
|
|
start_datetime=start_datetime,
|
|
publication_datetime=now() - datetime.timedelta(days=1),
|
|
places=42,
|
|
)
|
|
resp = app.get('/manage/agendas/%s/events/open/' % agenda.pk)
|
|
assert 'event H' in resp.text
|
|
assert '<h4>February %s</h4>' % (today.year + 2) in resp.text
|
|
|
|
# not enough permissions
|
|
app.reset()
|
|
app = login(app, username='manager', password='manager')
|
|
app.get('/manage/agendas/%s/events/open/' % agenda.pk, status=403)
|
|
|
|
# just enough permissions
|
|
agenda.view_role = manager_user.groups.all()[0]
|
|
agenda.save()
|
|
resp = app.get('/manage/agendas/%s/events/open/' % agenda.pk)
|
|
|
|
# wrong kind
|
|
agenda.kind = 'meetings'
|
|
agenda.save()
|
|
app.get('/manage/agendas/%s/events/open/' % agenda.pk, status=404)
|
|
agenda.kind = 'virtual'
|
|
agenda.save()
|
|
app.get('/manage/agendas/%s/events/open/' % agenda.pk, status=404)
|
|
|
|
|
|
def test_agenda_month_view(app, admin_user, manager_user, api_user, get_proper_html_str):
|
|
agenda = Agenda.objects.create(label='Passeports', kind='meetings')
|
|
desk = Desk.objects.create(agenda=agenda, label='Desk A')
|
|
today = datetime.date.today()
|
|
|
|
meetingtype = MeetingType(agenda=agenda, label='passeport', duration=20)
|
|
meetingtype.save()
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/day/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
resp = resp.click('Month')
|
|
assert resp.request.url.endswith('month/%s/%s/%s/' % (today.year, today.month, today.day))
|
|
|
|
assert '>Month<' in resp.text
|
|
assert '>Week<' in resp.text
|
|
assert '>Day<' in resp.text
|
|
assert 'No opening hours this month.' in resp.text
|
|
|
|
today = datetime.date(2018, 11, 10) # fixed day
|
|
timeperiod_weekday = today.weekday()
|
|
timeperiod = TimePeriod(
|
|
desk=desk, weekday=timeperiod_weekday, start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
|
|
)
|
|
timeperiod.save()
|
|
app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.pk, today.year, 42, today.day), status=404)
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert 'No opening hours this month.' not in resp.text
|
|
assert '<div class="booking' not in resp.text
|
|
first_month_day = today.replace(day=1)
|
|
last_month_day = today.replace(day=1, month=today.month + 1) - datetime.timedelta(days=1)
|
|
start_week_number = first_month_day.isocalendar()[1]
|
|
end_week_number = last_month_day.isocalendar()[1]
|
|
weeks_number = end_week_number - start_week_number + 1
|
|
assert resp.text.count('<tr') == 9 * weeks_number
|
|
|
|
# check opening hours cells
|
|
assert '<div class="opening-hours" style="height:800.0%;top:0.0%;width:97.0%;left:1.0%' in resp.text
|
|
|
|
# book some slots
|
|
app.reset()
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
resp = app.get('/api/agenda/%s/meetings/%s/datetimes/' % (agenda.slug, meetingtype.slug))
|
|
booking_url = resp.json['data'][0]['api']['fillslot_url']
|
|
booking_url2 = resp.json['data'][2]['api']['fillslot_url']
|
|
booking = app.post(booking_url)
|
|
booking_2 = app.post_json(
|
|
booking_url2, params={'label': 'foo book', 'user_last_name': "bar's", 'url': 'http://baz/'}
|
|
)
|
|
|
|
app.reset()
|
|
login(app)
|
|
date = Booking.objects.all()[0].event.start_datetime
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.pk, date.year, date.month, date.day))
|
|
assert resp.text.count('<div class="booking" style="left:1.0%;height:33.0%;') == 2 # booking cells
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[0].text.strip() == 'booked'
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[1].text.strip() == "foo book - bar's"
|
|
assert get_proper_html_str('foo book - bar's') in resp
|
|
assert len(resp.pyquery.find('span.desk')) == 0
|
|
|
|
agenda.booking_user_block_template = '<b>{{ booking.user_name }}</b> Foo Bar'
|
|
agenda.save()
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.pk, date.year, date.month, date.day))
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[0].text.strip() == '<b></b> Foo Bar'
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[1].text.strip() == "<b>bar's</b> Foo Bar"
|
|
assert get_proper_html_str('<b>bar's</b> Foo Bar') in resp
|
|
|
|
desk = Desk.objects.create(agenda=agenda, label='Desk B')
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.pk, date.year, date.month, date.day))
|
|
assert len(resp.pyquery.find('span.desk')) == 2
|
|
|
|
timeperiod = TimePeriod(
|
|
desk=desk, weekday=timeperiod_weekday, start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
|
|
)
|
|
timeperiod.save()
|
|
|
|
app.reset()
|
|
booking_3 = app.post(booking_url)
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
|
|
# count occurences of timeperiod weekday in current month
|
|
d = first_month_day
|
|
weekdays = 0
|
|
while d <= last_month_day:
|
|
if d.weekday() == timeperiod_weekday:
|
|
weekdays += 1
|
|
d += datetime.timedelta(days=1)
|
|
|
|
assert resp.text.count('<div class="opening-hours"') == 2 * weekdays
|
|
current_month = today.strftime('%Y-%m')
|
|
if current_month in booking_url or current_month in booking_url2:
|
|
assert resp.text.count('<div class="booking"') == 3
|
|
|
|
# cancel bookings
|
|
app.reset()
|
|
app.post(booking.json['api']['cancel_url'])
|
|
app.post(booking_2.json['api']['cancel_url'])
|
|
app.post(booking_3.json['api']['cancel_url'])
|
|
|
|
# make sure the are not
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert resp.text.count('<div class="booking"') == 0
|
|
|
|
# check December is correctly displayed
|
|
today = datetime.date(2018, 12, 10)
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert 'No opening hours this month.' not in resp.text
|
|
|
|
# display exception
|
|
unavailability_calendar = UnavailabilityCalendar.objects.create(label='calendar')
|
|
TimePeriodException.objects.create(
|
|
label='Calendar exception',
|
|
unavailability_calendar=unavailability_calendar,
|
|
start_datetime=make_aware(datetime.datetime(2018, 12, 15, 5, 0)),
|
|
end_datetime=make_aware(datetime.datetime(2018, 12, 15, 14, 0)),
|
|
)
|
|
unavailability_calendar.desks.add(desk)
|
|
TimePeriodException.objects.create(
|
|
label='Exception for a December day',
|
|
desk=desk,
|
|
start_datetime=make_aware(datetime.datetime(2018, 12, 15, 14, 0)),
|
|
end_datetime=make_aware(datetime.datetime(2018, 12, 15, 23, 0)),
|
|
)
|
|
TimePeriodException.objects.create(
|
|
label='Exception spanning multiple days',
|
|
desk=desk,
|
|
start_datetime=make_aware(datetime.datetime(2018, 12, 20, 14, 0)),
|
|
end_datetime=make_aware(datetime.datetime(2018, 12, 22, 16, 0)),
|
|
)
|
|
with CaptureQueriesContext(connection) as ctx:
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert len(ctx.captured_queries) == 10
|
|
assert resp.pyquery.find('.exception-hours')[0].attrib == {
|
|
'class': 'exception-hours',
|
|
'style': 'height:400.0%;top:0.0%;width:48.0%;left:50.0%;',
|
|
'title': 'Calendar exception',
|
|
}
|
|
assert resp.pyquery.find('.exception-hours')[1].attrib == {
|
|
'class': 'exception-hours',
|
|
'style': 'height:400.0%;top:400.0%;width:48.0%;left:50.0%;',
|
|
'title': 'Exception for a December day',
|
|
}
|
|
assert resp.pyquery.find('.exception-hours')[2].attrib == {
|
|
'class': 'exception-hours',
|
|
'style': 'height:400.0%;top:400.0%;width:48.0%;left:50.0%;',
|
|
'title': 'Exception spanning multiple days',
|
|
}
|
|
assert resp.pyquery.find('.exception-hours')[3].attrib == {
|
|
'class': 'exception-hours',
|
|
'style': 'height:800.0%;top:0.0%;width:48.0%;left:50.0%;',
|
|
'title': 'Exception spanning multiple days',
|
|
}
|
|
assert resp.pyquery.find('.exception-hours')[4].attrib == {
|
|
'class': 'exception-hours',
|
|
'style': 'height:600.0%;top:0.0%;width:48.0%;left:50.0%;',
|
|
'title': 'Exception spanning multiple days',
|
|
}
|
|
|
|
|
|
@pytest.mark.parametrize('kind', ['meetings', 'virtual'])
|
|
def test_agenda_month_view_weekend(app, admin_user, kind):
|
|
monday = 0
|
|
if kind == 'meetings':
|
|
agenda = Agenda.objects.create(label='Passeports', kind='meetings')
|
|
desk = Desk.objects.create(agenda=agenda, label='Desk A')
|
|
else:
|
|
agenda = Agenda.objects.create(label='Virtual', kind='virtual')
|
|
real_agenda = Agenda.objects.create(label='Real 1', kind='meetings')
|
|
VirtualMember.objects.create(virtual_agenda=agenda, real_agenda=real_agenda)
|
|
desk = Desk.objects.create(agenda=real_agenda, label='New Desk')
|
|
TimePeriod.objects.create(
|
|
desk=desk, weekday=monday, start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
|
|
)
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.pk, 2019, 1, 1))
|
|
assert 'Sunday' not in resp.text
|
|
assert 'Saturday' not in resp.text
|
|
# No Monday on first row since month starts a Tuesday
|
|
assert len(resp.pyquery.find('tbody tr:first th.weekday:empty')) == 1
|
|
|
|
# When weekend is hidden, do not display an empty first week
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.pk, 2019, 12, 1)) # month starts a Sunday
|
|
assert len(resp.pyquery.find('tbody tr:first th.weekday:empty')) == 0
|
|
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.pk, 2019, 6, 1)) # month starts a Saturday
|
|
assert len(resp.pyquery.find('tbody tr:first th.weekday:empty')) == 0
|
|
|
|
saturday = 5
|
|
timeperiod_sat = TimePeriod.objects.create(
|
|
desk=desk, weekday=saturday, start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
|
|
)
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.pk, 2019, 6, 1))
|
|
assert 'Sunday' not in resp.text
|
|
assert 'Saturday' in resp.text
|
|
assert len(resp.pyquery.find('tbody tr:first th.weekday:empty')) == 5
|
|
|
|
sunday = 6
|
|
TimePeriod.objects.create(
|
|
desk=desk, weekday=sunday, start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
|
|
)
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.pk, 2019, 6, 1))
|
|
assert 'Sunday' in resp.text
|
|
assert 'Saturday' in resp.text
|
|
|
|
timeperiod_sat.delete()
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.pk, 2019, 6, 1))
|
|
assert 'Sunday' in resp.text
|
|
assert 'Saturday' in resp.text
|
|
|
|
|
|
def test_agenda_meetings_view_opening_not_even_an_hour(app, admin_user):
|
|
month, year = 1, 2019
|
|
monday = 0
|
|
agenda = Agenda.objects.create(label='Passeports', kind='meetings')
|
|
desk = Desk.objects.create(agenda=agenda, label='Desk A')
|
|
TimePeriod.objects.create(
|
|
desk=desk, weekday=monday, start_time=datetime.time(10, 0), end_time=datetime.time(10, 30)
|
|
)
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.id, year, month, 1))
|
|
assert resp.pyquery('.opening-hours').length == 4 # four weeks
|
|
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.id, year, month, 15))
|
|
assert resp.pyquery('.opening-hours').length == 1
|
|
|
|
|
|
@pytest.mark.parametrize('kind', ['meetings', 'virtual'])
|
|
def test_agenda_month_view_dst_change(app, admin_user, kind):
|
|
if kind == 'meetings':
|
|
agenda = Agenda.objects.create(label='Passeports', kind='meetings')
|
|
desk = Desk.objects.create(agenda=agenda, label='Desk A')
|
|
meetingtype = MeetingType.objects.create(agenda=agenda, label='passeport', duration=20)
|
|
else:
|
|
agenda = Agenda.objects.create(label='Virtual', kind='virtual')
|
|
real_agenda = Agenda.objects.create(label='Real 1', kind='meetings')
|
|
VirtualMember.objects.create(virtual_agenda=agenda, real_agenda=real_agenda)
|
|
desk = Desk.objects.create(agenda=real_agenda, label='New Desk')
|
|
meetingtype = MeetingType.objects.create(agenda=real_agenda, label='passeport', duration=20)
|
|
|
|
for weekday in range(0, 7): # open all mornings
|
|
TimePeriod.objects.create(
|
|
desk=desk, weekday=weekday, start_time=datetime.time(9, 0), end_time=datetime.time(12, 0)
|
|
)
|
|
|
|
login(app)
|
|
for date in ('2019-10-01', '2019-10-31'):
|
|
with freezegun.freeze_time(date):
|
|
resp = app.get('/manage/agendas/%s/month/2019/10/01/' % agenda.id)
|
|
# check all days are correctly aligned
|
|
assert resp.text.count('height:300.0%;top:0.0%') == 31
|
|
|
|
# book some slots
|
|
for date_tuple in [(2019, 10, 2, 10, 0), (2019, 10, 29, 10, 0)]:
|
|
event = Event.objects.create(
|
|
agenda=desk.agenda,
|
|
places=1,
|
|
desk=desk,
|
|
meeting_type=meetingtype,
|
|
start_datetime=localtime(make_aware(datetime.datetime(*date_tuple))),
|
|
)
|
|
Booking.objects.create(event=event)
|
|
|
|
# check booked slots are similarly aligned
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/month/2019/10/01/' % agenda.id)
|
|
assert resp.text.count('height:33.0%;top:100.0%;') == 2
|
|
|
|
|
|
@pytest.mark.parametrize('kind', ['meetings', 'virtual'])
|
|
def test_agenda_month_view_januaries(app, admin_user, kind):
|
|
if kind == 'meetings':
|
|
agenda = Agenda.objects.create(label='Passports', kind='meetings')
|
|
desk = Desk.objects.create(agenda=agenda, label='Desk A')
|
|
MeetingType.objects.create(agenda=agenda, label='passport', duration=20)
|
|
else:
|
|
agenda = Agenda.objects.create(label='Virtual', kind='virtual')
|
|
real_agenda = Agenda.objects.create(label='Real 1', kind='meetings')
|
|
VirtualMember.objects.create(virtual_agenda=agenda, real_agenda=real_agenda)
|
|
desk = Desk.objects.create(agenda=real_agenda, label='New Desk')
|
|
MeetingType.objects.create(agenda=real_agenda, label='passport', duration=20)
|
|
TimePeriod(desk=desk, weekday=2, start_time=datetime.time(9, 0), end_time=datetime.time(12, 0)).save()
|
|
|
|
for year in range(2020, 2030):
|
|
date = datetime.date(year, 1, 1)
|
|
with freezegun.freeze_time(date):
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/month/%s/1/1/' % (agenda.id, date.year))
|
|
assert resp.text.count('<th class="weeknum">') in (4, 5)
|
|
|
|
|
|
@pytest.mark.parametrize('kind', ['meetings', 'virtual'])
|
|
def test_agenda_month_view_event_outside_timeperiod(app, admin_user, kind):
|
|
today = datetime.date.today()
|
|
if kind == 'meetings':
|
|
agenda = Agenda.objects.create(label='New Example', kind='meetings')
|
|
desk = Desk.objects.create(agenda=agenda, label='New Desk')
|
|
meetingtype = MeetingType.objects.create(agenda=agenda, label='Bar', duration=30)
|
|
else:
|
|
agenda = Agenda.objects.create(label='Virtual', kind='virtual')
|
|
real_agenda = Agenda.objects.create(label='Real 1', kind='meetings')
|
|
VirtualMember.objects.create(virtual_agenda=agenda, real_agenda=real_agenda)
|
|
desk = Desk.objects.create(agenda=real_agenda, label='New Desk')
|
|
meetingtype = MeetingType.objects.create(agenda=real_agenda, label='passport', duration=20)
|
|
login(app)
|
|
|
|
# no time period - no events
|
|
resp = app.get('/manage/agendas/%s/month/%d/%d/%d/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert 'No opening hours this month.' in resp.text
|
|
assert 'div class="booking' not in resp.text
|
|
|
|
# book some slots
|
|
middle_day = now().replace(day=15)
|
|
for hour, minute in [(9, 0), (17, 0)]:
|
|
event = Event.objects.create(
|
|
agenda=desk.agenda,
|
|
places=1,
|
|
desk=desk,
|
|
meeting_type=meetingtype,
|
|
start_datetime=localtime(now().replace(day=middle_day.day - middle_day.weekday() + 2)).replace(
|
|
hour=hour, minute=minute
|
|
),
|
|
)
|
|
Booking.objects.create(event=event)
|
|
|
|
# no time period - events are displayed
|
|
resp = app.get('/manage/agendas/%s/month/%d/%d/%d/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert resp.text.count('div class="booking') == 2
|
|
|
|
# bookings are cancelled
|
|
Booking.objects.update(cancellation_datetime=now())
|
|
resp = app.get('/manage/agendas/%s/month/%d/%d/%d/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert 'No opening hours this month.' in resp.text
|
|
assert resp.text.count('div class="booking') == 0
|
|
|
|
# events outside time period
|
|
Booking.objects.update(cancellation_datetime=None) # reset
|
|
TimePeriod.objects.create(
|
|
desk=desk, weekday=2, start_time=datetime.time(10, 0), end_time=datetime.time(16, 0)
|
|
)
|
|
resp = app.get('/manage/agendas/%s/month/%d/%d/%d/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert resp.text.count('div class="booking') == 2
|
|
assert '<div class="opening-hours" style="height:600.0%;top:100.0%;width:97.0%;left:1.0%' in resp.text
|
|
assert 'Sunday' not in resp.text
|
|
assert 'Saturday' not in resp.text
|
|
|
|
# create an event on saturday
|
|
event = Event.objects.create(
|
|
agenda=desk.agenda,
|
|
places=1,
|
|
desk=desk,
|
|
meeting_type=meetingtype,
|
|
start_datetime=localtime(now()).replace(
|
|
day=middle_day.day - middle_day.weekday() + 5, hour=10, minute=0
|
|
),
|
|
)
|
|
Booking.objects.create(event=event)
|
|
resp = app.get('/manage/agendas/%s/month/%d/%d/%d/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert resp.text.count('div class="booking') == 3
|
|
assert 'Sunday' not in resp.text
|
|
assert 'Saturday' in resp.text
|
|
# bookings are cancelled
|
|
Booking.objects.update(cancellation_datetime=now())
|
|
resp = app.get('/manage/agendas/%s/month/%d/%d/%d/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert resp.text.count('div class="booking') == 0
|
|
# and a timeperiod
|
|
Booking.objects.update(cancellation_datetime=None) # reset
|
|
TimePeriod.objects.create(
|
|
desk=desk, weekday=5, start_time=datetime.time(11, 0), end_time=datetime.time(12, 0)
|
|
)
|
|
resp = app.get('/manage/agendas/%s/month/%d/%d/%d/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert resp.text.count('div class="booking') == 3
|
|
assert 'Sunday' not in resp.text
|
|
assert 'Saturday' in resp.text
|
|
|
|
# create an event on sunday
|
|
middle_day = now().replace(day=15)
|
|
event = Event.objects.create(
|
|
agenda=desk.agenda,
|
|
places=1,
|
|
desk=desk,
|
|
meeting_type=meetingtype,
|
|
start_datetime=localtime(now()).replace(
|
|
day=middle_day.day - middle_day.weekday() + 6, hour=10, minute=0
|
|
),
|
|
)
|
|
Booking.objects.create(event=event)
|
|
resp = app.get('/manage/agendas/%s/month/%d/%d/%d/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert resp.text.count('div class="booking') == 4
|
|
assert 'Sunday' in resp.text
|
|
assert 'Saturday' in resp.text
|
|
# bookings are cancelled
|
|
Booking.objects.update(cancellation_datetime=now())
|
|
resp = app.get('/manage/agendas/%s/month/%d/%d/%d/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert resp.text.count('div class="booking') == 0
|
|
# and a timeperiod
|
|
Booking.objects.update(cancellation_datetime=None) # reset
|
|
TimePeriod.objects.create(
|
|
desk=desk, weekday=6, start_time=datetime.time(11, 0), end_time=datetime.time(12, 0)
|
|
)
|
|
resp = app.get('/manage/agendas/%s/month/%d/%d/%d/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert resp.text.count('div class="booking') == 4
|
|
assert 'Sunday' in resp.text
|
|
assert 'Saturday' in resp.text
|
|
|
|
|
|
def test_agenda_week_view(app, admin_user, manager_user, api_user, get_proper_html_str):
|
|
agenda = Agenda.objects.create(label='Passeports', kind='meetings')
|
|
desk = Desk.objects.create(agenda=agenda, label='Desk A')
|
|
today = datetime.date.today()
|
|
|
|
meetingtype = MeetingType(agenda=agenda, label='passeport', duration=20)
|
|
meetingtype.save()
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/day/%d/%d/%d/' % (agenda.pk, today.year, today.month, today.day))
|
|
resp = resp.click('Week')
|
|
assert resp.request.url.endswith('week/%s/%s/%s/' % (today.year, today.month, today.day))
|
|
|
|
assert '>Month<' in resp.text
|
|
assert '>Week<' in resp.text
|
|
assert '>Day<' in resp.text
|
|
assert 'No opening hours this week.' in resp.text
|
|
|
|
today = datetime.date(2018, 11, 10) # fixed day
|
|
timeperiod_weekday = today.weekday()
|
|
timeperiod = TimePeriod(
|
|
desk=desk, weekday=timeperiod_weekday, start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
|
|
)
|
|
timeperiod.save()
|
|
app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.id, today.year, 72, today.day), status=404)
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.id, today.year, today.month, today.day))
|
|
assert 'No opening hours this week.' not in resp.text
|
|
assert '<div class="booking' not in resp.text
|
|
assert resp.text.count('<tr') == 9
|
|
|
|
# check opening hours cells
|
|
assert '<div class="opening-hours" style="height:800.0%;top:0.0%;width:97.0%;left:1.0%' in resp.text
|
|
|
|
# book some slots
|
|
app.reset()
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
resp = app.get('/api/agenda/%s/meetings/%s/datetimes/' % (agenda.slug, meetingtype.slug))
|
|
booking_url = resp.json['data'][0]['api']['fillslot_url']
|
|
booking_url2 = resp.json['data'][2]['api']['fillslot_url']
|
|
booking = app.post(booking_url)
|
|
booking_2 = app.post_json(
|
|
booking_url2, params={'label': 'foo book', 'user_last_name': "bar's", 'url': 'http://baz/'}
|
|
)
|
|
|
|
app.reset()
|
|
login(app)
|
|
date = Booking.objects.all()[0].event.start_datetime
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.id, date.year, date.month, date.day))
|
|
assert resp.text.count('<div class="booking" style="left:1.0%;height:33.0%;') == 2 # booking cells
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[0].text.strip() == 'booked'
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[1].text.strip() == "foo book - bar's"
|
|
assert get_proper_html_str('foo book - bar's') in resp
|
|
assert len(resp.pyquery.find('span.desk')) == 0
|
|
|
|
agenda.booking_user_block_template = '<b>{{ booking.user_name }}</b> Foo Bar'
|
|
agenda.save()
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.id, date.year, date.month, date.day))
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[0].text.strip() == '<b></b> Foo Bar'
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[1].text.strip() == "<b>bar's</b> Foo Bar"
|
|
assert get_proper_html_str('<b>bar's</b> Foo Bar') in resp
|
|
|
|
desk = Desk.objects.create(agenda=agenda, label='Desk B')
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.id, date.year, date.month, date.day))
|
|
assert len(resp.pyquery.find('span.desk')) == 2
|
|
|
|
timeperiod = TimePeriod(
|
|
desk=desk, weekday=timeperiod_weekday, start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
|
|
)
|
|
timeperiod.save()
|
|
|
|
app.reset()
|
|
booking_3 = app.post(booking_url)
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.id, today.year, today.month, today.day))
|
|
|
|
# count occurences of timeperiod weekday in current month
|
|
assert resp.text.count('<div class="opening-hours"') == 2
|
|
current_month = today.strftime('%Y-%m')
|
|
if current_month in booking_url or current_month in booking_url2:
|
|
assert resp.text.count('<div class="booking"') == 3
|
|
|
|
# cancel bookings
|
|
app.reset()
|
|
app.post(booking.json['api']['cancel_url'])
|
|
app.post(booking_2.json['api']['cancel_url'])
|
|
app.post(booking_3.json['api']['cancel_url'])
|
|
|
|
# make sure the are not
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.id, today.year, today.month, today.day))
|
|
assert resp.text.count('<div class="booking"') == 0
|
|
|
|
# check December is correctly displayed
|
|
today = datetime.date(2018, 12, 10)
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.id, today.year, today.month, today.day))
|
|
assert 'No opening hours this week.' not in resp.text
|
|
|
|
# display exception
|
|
unavailability_calendar = UnavailabilityCalendar.objects.create(label='calendar')
|
|
TimePeriodException.objects.create(
|
|
label='Calendar exception',
|
|
unavailability_calendar=unavailability_calendar,
|
|
start_datetime=make_aware(datetime.datetime(2018, 12, 15, 5, 0)),
|
|
end_datetime=make_aware(datetime.datetime(2018, 12, 15, 14, 0)),
|
|
)
|
|
unavailability_calendar.desks.add(desk)
|
|
TimePeriodException.objects.create(
|
|
label='Exception for a December day',
|
|
desk=desk,
|
|
start_datetime=make_aware(datetime.datetime(2018, 12, 15, 14, 0)),
|
|
end_datetime=make_aware(datetime.datetime(2018, 12, 15, 23, 0)),
|
|
)
|
|
TimePeriodException.objects.create(
|
|
label='Exception spanning multiple days',
|
|
desk=desk,
|
|
start_datetime=make_aware(datetime.datetime(2018, 12, 11, 14, 0)),
|
|
end_datetime=make_aware(datetime.datetime(2018, 12, 13, 16, 0)),
|
|
)
|
|
with CaptureQueriesContext(connection) as ctx:
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.id, today.year, today.month, today.day))
|
|
assert len(ctx.captured_queries) == 10
|
|
assert resp.pyquery.find('.exception-hours')[0].attrib == {
|
|
'class': 'exception-hours',
|
|
'style': 'height:400.0%;top:400.0%;width:48.0%;left:50.0%;',
|
|
'title': 'Exception spanning multiple days',
|
|
}
|
|
assert resp.pyquery.find('.exception-hours')[1].attrib == {
|
|
'class': 'exception-hours',
|
|
'style': 'height:800.0%;top:0.0%;width:48.0%;left:50.0%;',
|
|
'title': 'Exception spanning multiple days',
|
|
}
|
|
assert resp.pyquery.find('.exception-hours')[2].attrib == {
|
|
'class': 'exception-hours',
|
|
'style': 'height:600.0%;top:0.0%;width:48.0%;left:50.0%;',
|
|
'title': 'Exception spanning multiple days',
|
|
}
|
|
assert resp.pyquery.find('.exception-hours')[3].attrib == {
|
|
'class': 'exception-hours',
|
|
'style': 'height:400.0%;top:0.0%;width:48.0%;left:50.0%;',
|
|
'title': 'Calendar exception',
|
|
}
|
|
assert resp.pyquery.find('.exception-hours')[4].attrib == {
|
|
'class': 'exception-hours',
|
|
'style': 'height:400.0%;top:400.0%;width:48.0%;left:50.0%;',
|
|
'title': 'Exception for a December day',
|
|
}
|
|
|
|
|
|
@pytest.mark.parametrize('kind', ['meetings', 'virtual'])
|
|
def test_agenda_week_view_weekend(app, admin_user, kind):
|
|
monday = 0
|
|
if kind == 'meetings':
|
|
agenda = Agenda.objects.create(label='Passeports', kind='meetings')
|
|
desk = Desk.objects.create(agenda=agenda, label='Desk A')
|
|
else:
|
|
agenda = Agenda.objects.create(label='Virtual', kind='virtual')
|
|
real_agenda = Agenda.objects.create(label='Real 1', kind='meetings')
|
|
VirtualMember.objects.create(virtual_agenda=agenda, real_agenda=real_agenda)
|
|
desk = Desk.objects.create(agenda=real_agenda, label='New Desk')
|
|
TimePeriod.objects.create(
|
|
desk=desk, weekday=monday, start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
|
|
)
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.id, 2019, 1, 1))
|
|
assert 'Sunday' not in resp.text
|
|
assert 'Saturday' not in resp.text
|
|
# Month starts a Tuesday, but monday is displayed
|
|
assert len(resp.pyquery.find('tbody tr:first th.weekday:empty')) == 0
|
|
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.id, 2019, 6, 1)) # month starts a Saturday
|
|
assert len(resp.pyquery.find('tbody tr:first th.weekday:empty')) == 0
|
|
|
|
saturday = 5
|
|
timeperiod_sat = TimePeriod.objects.create(
|
|
desk=desk, weekday=saturday, start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
|
|
)
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.id, 2019, 6, 1))
|
|
assert 'Sunday' not in resp.text
|
|
assert 'Saturday' in resp.text
|
|
assert len(resp.pyquery.find('tbody tr:first th.weekday:empty')) == 0
|
|
|
|
sunday = 6
|
|
TimePeriod.objects.create(
|
|
desk=desk, weekday=sunday, start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
|
|
)
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.id, 2019, 6, 1))
|
|
assert 'Sunday' in resp.text
|
|
assert 'Saturday' in resp.text
|
|
|
|
timeperiod_sat.delete()
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.id, 2019, 6, 1))
|
|
assert 'Sunday' in resp.text
|
|
assert 'Saturday' in resp.text
|
|
|
|
|
|
@pytest.mark.parametrize('kind', ['meetings', 'virtual'])
|
|
def test_agenda_week_view_dst_change(app, admin_user, kind):
|
|
if kind == 'meetings':
|
|
agenda = Agenda.objects.create(label='Passeports', kind='meetings')
|
|
desk = Desk.objects.create(agenda=agenda, label='Desk A')
|
|
meetingtype = MeetingType.objects.create(agenda=agenda, label='passeport', duration=20)
|
|
else:
|
|
agenda = Agenda.objects.create(label='Virtual', kind='virtual')
|
|
real_agenda = Agenda.objects.create(label='Real 1', kind='meetings')
|
|
VirtualMember.objects.create(virtual_agenda=agenda, real_agenda=real_agenda)
|
|
desk = Desk.objects.create(agenda=real_agenda, label='New Desk')
|
|
meetingtype = MeetingType.objects.create(agenda=real_agenda, label='passeport', duration=20)
|
|
|
|
for weekday in range(0, 7): # open all mornings
|
|
TimePeriod.objects.create(
|
|
desk=desk, weekday=weekday, start_time=datetime.time(9, 0), end_time=datetime.time(12, 0)
|
|
)
|
|
|
|
login(app)
|
|
for date in ('2019-10-28', '2019-11-03'):
|
|
# dst change was on 2019-11-03
|
|
with freezegun.freeze_time(date):
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.id, 2019, 10, 28))
|
|
# check all days are correctly aligned
|
|
assert resp.text.count('height:300.0%;top:0.0%') == 7
|
|
|
|
# book some slots
|
|
for date_tuple in [(2019, 10, 29, 10, 0), (2019, 10, 30, 10, 0)]:
|
|
event = Event.objects.create(
|
|
agenda=desk.agenda,
|
|
places=1,
|
|
desk=desk,
|
|
meeting_type=meetingtype,
|
|
start_datetime=localtime(make_aware(datetime.datetime(*date_tuple))),
|
|
)
|
|
Booking.objects.create(event=event)
|
|
|
|
# check booked slots are similarly aligned
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.id, 2019, 10, 28))
|
|
assert resp.text.count('height:33.0%;top:100.0%;') == 2
|
|
|
|
|
|
@pytest.mark.parametrize('kind', ['meetings', 'virtual'])
|
|
def test_agenda_week_view_januaries(app, admin_user, kind):
|
|
if kind == 'meetings':
|
|
agenda = Agenda.objects.create(label='Passports', kind='meetings')
|
|
desk = Desk.objects.create(agenda=agenda, label='Desk A')
|
|
MeetingType.objects.create(agenda=agenda, label='passport', duration=20)
|
|
else:
|
|
agenda = Agenda.objects.create(label='Virtual', kind='virtual')
|
|
real_agenda = Agenda.objects.create(label='Real 1', kind='meetings')
|
|
VirtualMember.objects.create(virtual_agenda=agenda, real_agenda=real_agenda)
|
|
desk = Desk.objects.create(agenda=real_agenda, label='New Desk')
|
|
MeetingType.objects.create(agenda=real_agenda, label='passport', duration=20)
|
|
TimePeriod(desk=desk, weekday=2, start_time=datetime.time(9, 0), end_time=datetime.time(12, 0)).save()
|
|
|
|
for year in range(2020, 2030):
|
|
date = datetime.date(year, 1, 1)
|
|
with freezegun.freeze_time(date):
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.id, year, 1, 1))
|
|
assert resp.text.count('<th class="weeknum">') == 1
|
|
|
|
|
|
@pytest.mark.parametrize('kind', ['meetings', 'virtual'])
|
|
def test_agenda_week_view_event_outside_timeperiod(app, admin_user, kind):
|
|
middle_day = now().replace(day=15)
|
|
middle_day = middle_day + datetime.timedelta(days=4 - middle_day.weekday())
|
|
if kind == 'meetings':
|
|
agenda = Agenda.objects.create(label='New Example', kind='meetings')
|
|
desk = Desk.objects.create(agenda=agenda, label='New Desk')
|
|
meetingtype = MeetingType.objects.create(agenda=agenda, label='Bar', duration=30)
|
|
else:
|
|
agenda = Agenda.objects.create(label='Virtual', kind='virtual')
|
|
real_agenda = Agenda.objects.create(label='Real 1', kind='meetings')
|
|
VirtualMember.objects.create(virtual_agenda=agenda, real_agenda=real_agenda)
|
|
desk = Desk.objects.create(agenda=real_agenda, label='New Desk')
|
|
meetingtype = MeetingType.objects.create(agenda=real_agenda, label='passport', duration=20)
|
|
login(app)
|
|
|
|
# no time period - no events
|
|
resp = app.get(
|
|
'/manage/agendas/%s/week/%s/%s/%s/' % (agenda.pk, middle_day.year, middle_day.month, middle_day.day)
|
|
)
|
|
assert 'No opening hours this week.' in resp.text
|
|
assert 'div class="booking' not in resp.text
|
|
|
|
# book some slots
|
|
middle_day = now().replace(day=15)
|
|
for hour, minute in [(9, 0), (17, 0)]:
|
|
event = Event.objects.create(
|
|
agenda=desk.agenda,
|
|
places=1,
|
|
desk=desk,
|
|
meeting_type=meetingtype,
|
|
start_datetime=localtime(now().replace(day=middle_day.day - middle_day.weekday() + 2)).replace(
|
|
hour=hour, minute=minute
|
|
),
|
|
)
|
|
Booking.objects.create(event=event)
|
|
|
|
# no time period - events are displayed
|
|
resp = app.get(
|
|
'/manage/agendas/%s/week/%s/%s/%s/' % (agenda.pk, middle_day.year, middle_day.month, middle_day.day)
|
|
)
|
|
assert resp.text.count('div class="booking') == 2
|
|
|
|
# bookings are cancelled
|
|
Booking.objects.update(cancellation_datetime=now())
|
|
resp = app.get(
|
|
'/manage/agendas/%s/week/%s/%s/%s/' % (agenda.pk, middle_day.year, middle_day.month, middle_day.day)
|
|
)
|
|
assert 'No opening hours this week.' in resp.text
|
|
assert resp.text.count('div class="booking') == 0
|
|
|
|
# events outside time period
|
|
Booking.objects.update(cancellation_datetime=None) # reset
|
|
TimePeriod.objects.create(
|
|
desk=desk, weekday=2, start_time=datetime.time(10, 0), end_time=datetime.time(16, 0)
|
|
)
|
|
resp = app.get(
|
|
'/manage/agendas/%s/week/%s/%s/%s/' % (agenda.pk, middle_day.year, middle_day.month, middle_day.day)
|
|
)
|
|
assert resp.text.count('div class="booking') == 2
|
|
assert '<div class="opening-hours" style="height:600.0%;top:100.0%;width:97.0%;left:1.0%' in resp.text
|
|
assert 'Sunday' not in resp.text
|
|
assert 'Saturday' not in resp.text
|
|
|
|
# create an event on saturday
|
|
middle_day = now().replace(day=15)
|
|
middle_day = middle_day + datetime.timedelta(days=5 - middle_day.weekday())
|
|
event = Event.objects.create(
|
|
agenda=desk.agenda,
|
|
places=1,
|
|
desk=desk,
|
|
meeting_type=meetingtype,
|
|
start_datetime=localtime(now()).replace(day=middle_day.day, hour=10, minute=0),
|
|
)
|
|
Booking.objects.create(event=event)
|
|
resp = app.get(
|
|
'/manage/agendas/%s/week/%s/%s/%s/' % (agenda.pk, middle_day.year, middle_day.month, middle_day.day)
|
|
)
|
|
assert resp.text.count('div class="booking') == 3
|
|
assert 'Sunday' not in resp.text
|
|
assert 'Saturday' in resp.text
|
|
# bookings are cancelled
|
|
Booking.objects.update(cancellation_datetime=now())
|
|
resp = app.get(
|
|
'/manage/agendas/%s/week/%s/%s/%s/' % (agenda.pk, middle_day.year, middle_day.month, middle_day.day)
|
|
)
|
|
assert resp.text.count('div class="booking') == 0
|
|
# and a timeperiod
|
|
Booking.objects.update(cancellation_datetime=None) # reset
|
|
TimePeriod.objects.create(
|
|
desk=desk, weekday=5, start_time=datetime.time(11, 0), end_time=datetime.time(12, 0)
|
|
)
|
|
resp = app.get(
|
|
'/manage/agendas/%s/week/%s/%s/%s/' % (agenda.pk, middle_day.year, middle_day.month, middle_day.day)
|
|
)
|
|
assert resp.text.count('div class="booking') == 3
|
|
assert 'Sunday' not in resp.text
|
|
assert 'Saturday' in resp.text
|
|
|
|
# create an event on sunday
|
|
middle_day = now().replace(day=15)
|
|
middle_day = middle_day + datetime.timedelta(days=6 - middle_day.weekday())
|
|
event = Event.objects.create(
|
|
agenda=desk.agenda,
|
|
places=1,
|
|
desk=desk,
|
|
meeting_type=meetingtype,
|
|
start_datetime=localtime(now()).replace(day=middle_day.day, hour=10, minute=0),
|
|
)
|
|
Booking.objects.create(event=event)
|
|
resp = app.get(
|
|
'/manage/agendas/%s/week/%s/%s/%s/' % (agenda.pk, middle_day.year, middle_day.month, middle_day.day)
|
|
)
|
|
assert resp.text.count('div class="booking') == 4
|
|
assert 'Sunday' in resp.text
|
|
assert 'Saturday' in resp.text
|
|
# bookings are cancelled
|
|
Booking.objects.update(cancellation_datetime=now())
|
|
resp = app.get(
|
|
'/manage/agendas/%s/week/%s/%s/%s/' % (agenda.pk, middle_day.year, middle_day.month, middle_day.day)
|
|
)
|
|
assert resp.text.count('div class="booking') == 0
|
|
# and a timeperiod
|
|
Booking.objects.update(cancellation_datetime=None) # reset
|
|
TimePeriod.objects.create(
|
|
desk=desk, weekday=6, start_time=datetime.time(11, 0), end_time=datetime.time(12, 0)
|
|
)
|
|
resp = app.get(
|
|
'/manage/agendas/%s/week/%s/%s/%s/' % (agenda.pk, middle_day.year, middle_day.month, middle_day.day)
|
|
)
|
|
assert resp.text.count('div class="booking') == 4
|
|
assert 'Sunday' in resp.text
|
|
assert 'Saturday' in resp.text
|
|
|
|
|
|
def test_agenda_view_event(app, manager_user):
|
|
agenda = Agenda(label='Foo bar')
|
|
agenda.view_role = manager_user.groups.all()[0]
|
|
agenda.save()
|
|
event = Event.objects.create(
|
|
label='xyz',
|
|
start_datetime=make_aware(datetime.datetime(2019, 12, 22, 17, 0)),
|
|
places=10,
|
|
agenda=agenda,
|
|
)
|
|
for i in range(8):
|
|
booking = Booking.objects.create(event=event)
|
|
if i < 5:
|
|
booking.creation_datetime = make_aware(datetime.datetime(2019, 12, 21, 14, 0 + i))
|
|
if i == 5:
|
|
booking.creation_datetime = make_aware(datetime.datetime(2019, 12, 21, 15, 0))
|
|
booking.user_first_name = 'Foo Bar'
|
|
booking.user_last_name = 'User'
|
|
if i == 6:
|
|
booking.creation_datetime = make_aware(datetime.datetime(2019, 12, 21, 16, 0))
|
|
booking.user_first_name = 'Foo Bar'
|
|
booking.user_last_name = 'User 2'
|
|
booking.label = 'Foo Bar Label 2'
|
|
if i == 7:
|
|
booking.creation_datetime = make_aware(datetime.datetime(2019, 12, 21, 17, 0))
|
|
booking.label = 'Foo Bar Label 3'
|
|
booking.save()
|
|
Booking.objects.create(event=event, cancellation_datetime=now())
|
|
app = login(app, username='manager', password='manager')
|
|
resp = app.get('/manage/agendas/%s/month/2019/12/01/' % agenda.id, status=200)
|
|
resp = resp.click('xyz')
|
|
assert 'Bookings (8/10): 2 remaining places' in resp.text
|
|
assert 'Waiting' not in resp.text
|
|
assert 'This event is overbooked.' not in resp.text
|
|
assert 'This event is full.' not in resp.text
|
|
event.waiting_list_places = 5
|
|
event.save()
|
|
resp = app.get(resp.request.url)
|
|
assert 'Waiting List (0/5): 5 remaining places' in resp.text
|
|
assert 'Anonymous, Dec. 21, 2019, 2 p.m.' in resp.text
|
|
assert 'Anonymous, Dec. 21, 2019, 2:01 p.m.' in resp.text
|
|
assert 'Anonymous, Dec. 21, 2019, 2:02 p.m.' in resp.text
|
|
assert 'Anonymous, Dec. 21, 2019, 2:03 p.m.' in resp.text
|
|
assert 'Anonymous, Dec. 21, 2019, 2:04 p.m.' in resp.text
|
|
assert 'Foo Bar User, Dec. 21, 2019, 3 p.m.' in resp.text
|
|
assert 'Foo Bar User 2, Dec. 21, 2019, 4 p.m.' in resp.text
|
|
assert 'Foo Bar Label 3, Dec. 21, 2019, 5 p.m.' in resp.text
|
|
|
|
booking = Booking.objects.order_by('pk')[0]
|
|
booking.in_waiting_list = True
|
|
booking.save()
|
|
booking = Booking.objects.order_by('pk')[1]
|
|
booking.in_waiting_list = True
|
|
booking.save()
|
|
resp = app.get(resp.request.url)
|
|
assert 'Waiting List (2/5): 3 remaining places' in resp.text
|
|
assert 'Bookings (6/10): 4 remaining places' in resp.text
|
|
assert list(resp.context['booked']) == list(Booking.objects.order_by('creation_datetime')[2:8])
|
|
assert list(resp.context['waiting']) == list(Booking.objects.order_by('creation_datetime')[0:2])
|
|
|
|
event.places = 5
|
|
event.save()
|
|
resp = app.get(resp.request.url)
|
|
assert 'This event is overbooked.' in resp.text
|
|
assert 'This event is full.' not in resp.text
|
|
|
|
event.places = 6
|
|
event.save()
|
|
resp = app.get(resp.request.url)
|
|
assert 'This event is overbooked.' not in resp.text
|
|
assert 'This event is full.' in resp.text
|
|
|
|
|
|
def test_agenda_view_edit_event(app, manager_user):
|
|
test_agenda_view_event(app, manager_user)
|
|
agenda = Agenda.objects.first()
|
|
resp = app.get('/manage/agendas/%s/month/2019/12/01/' % agenda.id, status=200)
|
|
resp = resp.click('xyz')
|
|
assert 'Options' not in resp.text
|
|
assert 'Delete' not in resp.text
|
|
|
|
agenda.edit_role = manager_user.groups.all()[0]
|
|
agenda.save()
|
|
event_url = resp.request.url
|
|
resp = app.get(event_url)
|
|
assert 'Options' in resp.text
|
|
resp = resp.click('Options')
|
|
resp.form['start_datetime_0'] = agenda.event_set.first().start_datetime.strftime('%Y-%m-%d')
|
|
resp.form['start_datetime_1'] = agenda.event_set.first().start_datetime.strftime('%H:%M')
|
|
resp = resp.form.submit(status=302).follow()
|
|
assert event_url == resp.request.url
|
|
|
|
resp = resp.click('Delete')
|
|
resp = resp.form.submit()
|
|
assert Event.objects.count() == 0
|
|
|
|
|
|
def test_virtual_agenda_add(app, admin_user):
|
|
app = login(app)
|
|
resp = app.get('/manage/', status=200)
|
|
resp = resp.click('New')
|
|
resp.form['label'] = 'Virtual agenda'
|
|
resp.form['kind'] = 'virtual'
|
|
resp = resp.form.submit()
|
|
agenda = Agenda.objects.get(label='Virtual agenda')
|
|
assert resp.location.endswith('/manage/agendas/%s/settings' % agenda.id)
|
|
assert agenda.minimal_booking_delay is None
|
|
assert agenda.maximal_booking_delay is None
|
|
|
|
|
|
def test_virtual_agenda_day_view(app, admin_user, manager_user, get_proper_html_str):
|
|
agenda = Agenda.objects.create(label='Virtual', kind='virtual')
|
|
real_agenda_1 = Agenda.objects.create(label='Real 1', kind='meetings')
|
|
real_agenda_2 = Agenda.objects.create(label='Real 2', kind='meetings')
|
|
VirtualMember.objects.create(virtual_agenda=agenda, real_agenda=real_agenda_1)
|
|
VirtualMember.objects.create(virtual_agenda=agenda, real_agenda=real_agenda_2)
|
|
|
|
desk1 = Desk.objects.create(agenda=real_agenda_1, label='New Desk')
|
|
desk2 = Desk.objects.create(agenda=real_agenda_2, label='New Desk')
|
|
today = datetime.date.today()
|
|
|
|
meetingtype1 = MeetingType.objects.create(agenda=real_agenda_1, label='Bar', duration=30)
|
|
meetingtype2 = MeetingType.objects.create(agenda=real_agenda_2, label='Bar', duration=30)
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/day/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert 'No opening hours this day.' in resp.text # no time pediod
|
|
|
|
timeperiod = TimePeriod.objects.create(
|
|
desk=desk1, weekday=today.weekday(), start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
|
|
)
|
|
resp = app.get('/manage/agendas/%s/day/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert 'No opening hours this day.' not in resp.text
|
|
assert 'div class="booking' not in resp.text
|
|
assert resp.text.count('<tr') == 9 # 10->18 (not included)
|
|
|
|
timeperiod.end_time = datetime.time(18, 30) # end during an hour
|
|
timeperiod.save()
|
|
resp = app.get('/manage/agendas/%s/day/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert resp.text.count('<tr') == 10 # 10->18 (included)
|
|
|
|
# check opening hours cells
|
|
assert '<div class="opening-hours"' in resp.text
|
|
assert 'style="height: 850%; top: 0%;"' in resp.text
|
|
|
|
# book some slots
|
|
for hour, minute in [(10, 30), (14, 0)]:
|
|
event = Event.objects.create(
|
|
agenda=real_agenda_1,
|
|
places=1,
|
|
desk=desk1,
|
|
meeting_type=meetingtype1,
|
|
start_datetime=now().replace(hour=hour, minute=minute),
|
|
)
|
|
Booking.objects.create(event=event)
|
|
event = Event.objects.create(
|
|
agenda=real_agenda_2,
|
|
places=1,
|
|
desk=desk2,
|
|
meeting_type=meetingtype2,
|
|
start_datetime=now().replace(hour=hour, minute=minute),
|
|
)
|
|
Booking.objects.create(event=event, label='foo', user_last_name="bar's")
|
|
|
|
date = Booking.objects.all()[0].event.start_datetime
|
|
resp = app.get('/manage/agendas/%s/day/%d/%d/%d/' % (agenda.id, date.year, date.month, date.day))
|
|
assert resp.text.count('div class="booking') == 4
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[0].text.strip() == 'booked'
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[1].text.strip() == "foo - bar's"
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[2].text.strip() == 'booked'
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[3].text.strip() == "foo - bar's"
|
|
assert get_proper_html_str('foo - bar's') in resp
|
|
assert 'hourspan-2' in resp.text # table CSS class
|
|
assert 'height: 50%; top: 0%;' in resp.text # booking cells
|
|
|
|
real_agenda_1.booking_user_block_template = '<b>{{ booking.user_name }}</b> Foo Bar'
|
|
real_agenda_1.save()
|
|
real_agenda_2.booking_user_block_template = '<b>{{ booking.user_name }}</b> Bar Foo'
|
|
real_agenda_2.save()
|
|
resp = app.get('/manage/agendas/%s/day/%d/%d/%d/' % (agenda.id, date.year, date.month, date.day))
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[0].text.strip() == '<b></b> Foo Bar'
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[1].text.strip() == "<b>bar's</b> Bar Foo"
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[2].text.strip() == '<b></b> Foo Bar'
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[3].text.strip() == "<b>bar's</b> Bar Foo"
|
|
assert get_proper_html_str('<b>bar's</b> Bar Foo') in resp
|
|
|
|
# create a shorter meeting type, this will change the table CSS class
|
|
# (and visually this will give more room for events)
|
|
MeetingType.objects.create(agenda=real_agenda_1, label='Baz', duration=15)
|
|
MeetingType.objects.create(agenda=real_agenda_2, label='Baz', duration=15)
|
|
resp = app.get('/manage/agendas/%s/day/%d/%d/%d/' % (agenda.id, date.year, date.month, date.day))
|
|
assert resp.text.count('div class="booking') == 4
|
|
assert 'hourspan-4' in resp.text # table CSS class
|
|
|
|
# cancel a booking
|
|
booking = Booking.objects.first()
|
|
booking.cancel()
|
|
|
|
resp = app.get('/manage/agendas/%s/day/%d/%d/%d/' % (agenda.id, date.year, date.month, date.day))
|
|
assert resp.text.count('div class="booking') == 3
|
|
|
|
# not enough permissions
|
|
app.reset()
|
|
app = login(app, username='manager', password='manager')
|
|
resp = app.get(
|
|
'/manage/agendas/%s/day/%d/%d/%d/' % (agenda.id, date.year, date.month, date.day), status=403
|
|
)
|
|
|
|
# just enough permissions
|
|
agenda.view_role = manager_user.groups.all()[0]
|
|
agenda.save()
|
|
resp = app.get(
|
|
'/manage/agendas/%s/day/%d/%d/%d/' % (agenda.id, date.year, date.month, date.day), status=200
|
|
)
|
|
|
|
# display exception
|
|
TimePeriodException.objects.create(
|
|
label='Exception for the afternoon',
|
|
desk=desk1,
|
|
start_datetime=make_aware(datetime.datetime(date.year, date.month, date.day, 13, 0)),
|
|
end_datetime=make_aware(datetime.datetime(date.year, date.month, date.day, 23, 0)),
|
|
)
|
|
with CaptureQueriesContext(connection) as ctx:
|
|
resp = app.get(
|
|
'/manage/agendas/%s/day/%d/%d/%d/' % (agenda.id, date.year, date.month, date.day), status=200
|
|
)
|
|
assert len(ctx.captured_queries) == 16
|
|
# day is displaying rows from 10am to 6pm,
|
|
# opening hours, 10am to 1pm gives top: 300%
|
|
# rest of the day, 1pm to 6(+1)pm gives 600%
|
|
assert resp.pyquery.find('.exception-hours')[0].attrib == {
|
|
'class': 'exception-hours',
|
|
'style': 'height: 600%; top: 300%;',
|
|
}
|
|
assert resp.pyquery.find('.exception-hours span')[0].text == 'Exception for the afternoon'
|
|
|
|
# display excluded period
|
|
date += datetime.timedelta(days=7)
|
|
TimePeriod.objects.create(
|
|
agenda=agenda, weekday=today.weekday(), start_time=datetime.time(14, 0), end_time=datetime.time(23, 0)
|
|
)
|
|
resp = app.get(
|
|
'/manage/agendas/%s/day/%d/%d/%d/' % (agenda.id, date.year, date.month, date.day), status=200
|
|
)
|
|
assert resp.pyquery.find('.exception-hours')[0].attrib == {
|
|
'class': 'exception-hours',
|
|
'style': 'height: 500%; top: 400%;',
|
|
}
|
|
|
|
# check excluded period is only displayed on relevant weekday
|
|
date += datetime.timedelta(days=1)
|
|
TimePeriod.objects.create(
|
|
desk=desk1, weekday=date.weekday(), start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
|
|
)
|
|
resp = app.get(
|
|
'/manage/agendas/%s/day/%d/%d/%d/' % (agenda.id, date.year, date.month, date.day), status=200
|
|
)
|
|
assert resp.text.count('<tr') == 9
|
|
assert 'exceptions-hours' not in resp.text
|
|
|
|
|
|
def test_virtual_agenda_week_view(app, admin_user, get_proper_html_str):
|
|
agenda = Agenda.objects.create(label='Virtual', kind='virtual')
|
|
real_agenda_1 = Agenda.objects.create(label='Real 1', kind='meetings')
|
|
real_agenda_2 = Agenda.objects.create(label='Real 2', kind='meetings')
|
|
VirtualMember.objects.create(virtual_agenda=agenda, real_agenda=real_agenda_1)
|
|
VirtualMember.objects.create(virtual_agenda=agenda, real_agenda=real_agenda_2)
|
|
|
|
desk1 = Desk.objects.create(agenda=real_agenda_1, label='New Desk')
|
|
desk2 = Desk.objects.create(agenda=real_agenda_2, label='New Desk')
|
|
today = datetime.date.today()
|
|
|
|
meetingtype1 = MeetingType.objects.create(agenda=real_agenda_1, label='Bar', duration=30)
|
|
meetingtype2 = MeetingType.objects.create(agenda=real_agenda_2, label='Bar', duration=30)
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/day/%d/%d/%d/' % (agenda.pk, today.year, today.month, today.day))
|
|
resp = resp.click('Week')
|
|
assert resp.request.url.endswith('week/%s/%s/%s/' % (today.year, today.month, today.day))
|
|
|
|
assert '>Month<' in resp.text
|
|
assert '>Week<' in resp.text
|
|
assert '>Day<' in resp.text
|
|
assert 'No opening hours this week.' in resp.text
|
|
|
|
today = datetime.date(2018, 11, 10) # fixed day
|
|
timeperiod_weekday = today.weekday()
|
|
TimePeriod.objects.create(
|
|
desk=desk1, weekday=timeperiod_weekday, start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
|
|
)
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.id, today.year, today.month, today.day))
|
|
assert 'No opening hours this week.' not in resp.text
|
|
assert '<div class="booking' not in resp.text
|
|
assert resp.text.count('<tr') == 9
|
|
|
|
# check opening hours cells
|
|
assert '<div class="opening-hours" style="height:800.0%;top:0.0%;width:48.0%;left:1.0%' in resp.text
|
|
|
|
# book some slots
|
|
for hour, minute in [(10, 30), (14, 0)]:
|
|
event = Event.objects.create(
|
|
agenda=real_agenda_1,
|
|
places=1,
|
|
desk=desk1,
|
|
meeting_type=meetingtype1,
|
|
start_datetime=now().replace(hour=hour, minute=minute),
|
|
)
|
|
Booking.objects.create(event=event)
|
|
event = Event.objects.create(
|
|
agenda=real_agenda_2,
|
|
places=1,
|
|
desk=desk2,
|
|
meeting_type=meetingtype2,
|
|
start_datetime=now().replace(hour=hour, minute=minute),
|
|
)
|
|
Booking.objects.create(event=event, label='foo', user_last_name="bar's")
|
|
|
|
date = Booking.objects.all()[0].event.start_datetime
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.id, date.year, date.month, date.day))
|
|
assert resp.text.count('<div class="booking" style="left:1.0%;height:50.0%;') == 2 # booking cells
|
|
assert (
|
|
resp.text.count('<div class="booking" style="left:50.0%;height:50.0%;min-height:50.0%;') == 2
|
|
) # booking cells
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[0].text.strip() == 'booked'
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[1].text.strip() == "foo - bar's"
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[2].text.strip() == 'booked'
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[3].text.strip() == "foo - bar's"
|
|
assert get_proper_html_str('foo - bar's') in resp
|
|
|
|
real_agenda_1.booking_user_block_template = '<b>{{ booking.user_name }}</b> Foo Bar'
|
|
real_agenda_1.save()
|
|
real_agenda_2.booking_user_block_template = '<b>{{ booking.user_name }}</b> Bar Foo'
|
|
real_agenda_2.save()
|
|
resp = app.get('/manage/agendas/%s/day/%s/%s/%s/' % (agenda.id, date.year, date.month, date.day))
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[0].text.strip() == '<b></b> Foo Bar'
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[1].text.strip() == "<b>bar's</b> Bar Foo"
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[2].text.strip() == '<b></b> Foo Bar'
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[3].text.strip() == "<b>bar's</b> Bar Foo"
|
|
assert get_proper_html_str('<b>bar's</b> Bar Foo') in resp
|
|
|
|
# cancel a booking
|
|
booking = Booking.objects.first()
|
|
booking.cancel()
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.id, date.year, date.month, date.day))
|
|
assert resp.text.count('<div class="booking"') == 3
|
|
|
|
# check December is correctly displayed
|
|
today = datetime.date(2018, 12, 10)
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.id, today.year, today.month, today.day))
|
|
assert 'No opening hours this month.' not in resp.text
|
|
|
|
# display exception
|
|
TimePeriodException.objects.create(
|
|
label='Exception for a December day',
|
|
desk=desk1,
|
|
start_datetime=make_aware(datetime.datetime(2018, 12, 15, 5, 0)),
|
|
end_datetime=make_aware(datetime.datetime(2018, 12, 15, 23, 0)),
|
|
)
|
|
with CaptureQueriesContext(connection) as ctx:
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.id, today.year, today.month, today.day))
|
|
assert len(ctx.captured_queries) == 12
|
|
assert len(resp.pyquery.find('.exception-hours')) == 1
|
|
assert resp.pyquery.find('.exception-hours')[0].attrib == {
|
|
'class': 'exception-hours',
|
|
'style': 'height:800.0%;top:0.0%;width:48.0%;left:1.0%;',
|
|
'title': 'Exception for a December day',
|
|
}
|
|
|
|
# display excluded period
|
|
TimePeriod.objects.create(
|
|
agenda=agenda, weekday=today.weekday(), start_time=datetime.time(13, 0), end_time=datetime.time(23, 0)
|
|
)
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.id, today.year, today.month, today.day))
|
|
assert len(resp.pyquery.find('.exception-hours')) == 3
|
|
assert resp.pyquery.find('.exception-hours')[0].attrib == {
|
|
'class': 'exception-hours',
|
|
'style': 'height:500.0%;top:300.0%;width:48.0%;left:1.0%;',
|
|
}
|
|
assert resp.pyquery.find('.exception-hours')[1].attrib == {
|
|
'class': 'exception-hours',
|
|
'style': 'height:500.0%;top:300.0%;width:48.0%;left:50.0%;',
|
|
}
|
|
|
|
|
|
def test_virtual_agenda_month_view(app, admin_user, get_proper_html_str):
|
|
agenda = Agenda.objects.create(label='Virtual', kind='virtual')
|
|
real_agenda_1 = Agenda.objects.create(label='Real 1', kind='meetings')
|
|
real_agenda_2 = Agenda.objects.create(label='Real 2', kind='meetings')
|
|
VirtualMember.objects.create(virtual_agenda=agenda, real_agenda=real_agenda_1)
|
|
VirtualMember.objects.create(virtual_agenda=agenda, real_agenda=real_agenda_2)
|
|
|
|
desk1 = Desk.objects.create(agenda=real_agenda_1, label='New Desk')
|
|
desk2 = Desk.objects.create(agenda=real_agenda_2, label='New Desk')
|
|
today = datetime.date.today()
|
|
|
|
meetingtype1 = MeetingType.objects.create(agenda=real_agenda_1, label='Bar', duration=30)
|
|
meetingtype2 = MeetingType.objects.create(agenda=real_agenda_2, label='Bar', duration=30)
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/day/%d/%d/%d/' % (agenda.pk, today.year, today.month, today.day))
|
|
resp = resp.click('Month')
|
|
assert resp.request.url.endswith('month/%s/%s/%s/' % (today.year, today.month, today.day))
|
|
|
|
assert '>Month<' in resp.text
|
|
assert '>Week<' in resp.text
|
|
assert '>Day<' in resp.text
|
|
assert 'No opening hours this month.' in resp.text
|
|
|
|
today = datetime.date(2018, 11, 10) # fixed day
|
|
timeperiod_weekday = today.weekday()
|
|
TimePeriod.objects.create(
|
|
desk=desk1, weekday=timeperiod_weekday, start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
|
|
)
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.id, today.year, today.month, today.day))
|
|
assert 'No opening hours this month.' not in resp.text
|
|
assert '<div class="booking' not in resp.text
|
|
first_month_day = today.replace(day=1)
|
|
last_month_day = today.replace(day=1, month=today.month + 1) - datetime.timedelta(days=1)
|
|
start_week_number = first_month_day.isocalendar()[1]
|
|
end_week_number = last_month_day.isocalendar()[1]
|
|
weeks_number = end_week_number - start_week_number + 1
|
|
assert resp.text.count('<tr') == 9 * weeks_number
|
|
|
|
# check opening hours cells
|
|
assert '<div class="opening-hours" style="height:800.0%;top:0.0%;width:48.0%;left:1.0%' in resp.text
|
|
|
|
# book some slots
|
|
for hour, minute in [(10, 30), (14, 0)]:
|
|
event = Event.objects.create(
|
|
agenda=real_agenda_1,
|
|
places=1,
|
|
desk=desk1,
|
|
meeting_type=meetingtype1,
|
|
start_datetime=now().replace(hour=hour, minute=minute),
|
|
)
|
|
Booking.objects.create(event=event)
|
|
event = Event.objects.create(
|
|
agenda=real_agenda_2,
|
|
places=1,
|
|
desk=desk2,
|
|
meeting_type=meetingtype2,
|
|
start_datetime=now().replace(hour=hour, minute=minute),
|
|
)
|
|
Booking.objects.create(event=event, label='foo', user_last_name="bar's")
|
|
|
|
date = Booking.objects.all()[0].event.start_datetime
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.id, date.year, date.month, date.day))
|
|
assert resp.text.count('<div class="booking" style="left:1.0%;height:50.0%;') == 2 # booking cells
|
|
assert (
|
|
resp.text.count('<div class="booking" style="left:50.0%;height:50.0%;min-height:50.0%;') == 2
|
|
) # booking cells
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[0].text.strip() == 'booked'
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[1].text.strip() == "foo - bar's"
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[2].text.strip() == 'booked'
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[3].text.strip() == "foo - bar's"
|
|
assert get_proper_html_str('foo - bar's') in resp
|
|
|
|
real_agenda_1.booking_user_block_template = '<b>{{ booking.user_name }}</b> Foo Bar'
|
|
real_agenda_1.save()
|
|
real_agenda_2.booking_user_block_template = '<b>{{ booking.user_name }}</b> Bar Foo'
|
|
real_agenda_2.save()
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.id, date.year, date.month, date.day))
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[0].text.strip() == '<b></b> Foo Bar'
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[1].text.strip() == "<b>bar's</b> Bar Foo"
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[2].text.strip() == '<b></b> Foo Bar'
|
|
assert resp.pyquery.find('div.booking a').not_('.cancel')[3].text.strip() == "<b>bar's</b> Bar Foo"
|
|
assert get_proper_html_str('<b>bar's</b> Bar Foo') in resp
|
|
|
|
# cancel a booking
|
|
booking = Booking.objects.first()
|
|
booking.cancel()
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.id, date.year, date.month, date.day))
|
|
assert resp.text.count('<div class="booking"') == 3
|
|
|
|
# check December is correctly displayed
|
|
today = datetime.date(2018, 12, 10)
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.id, today.year, today.month, today.day))
|
|
assert 'No opening hours this month.' not in resp.text
|
|
|
|
# display exception
|
|
TimePeriodException.objects.create(
|
|
label='Exception for a December day',
|
|
desk=desk1,
|
|
start_datetime=make_aware(datetime.datetime(2018, 12, 15, 5, 0)),
|
|
end_datetime=make_aware(datetime.datetime(2018, 12, 15, 23, 0)),
|
|
)
|
|
with CaptureQueriesContext(connection) as ctx:
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.id, today.year, today.month, today.day))
|
|
assert len(ctx.captured_queries) == 12
|
|
assert len(resp.pyquery.find('.exception-hours')) == 1
|
|
assert resp.pyquery.find('.exception-hours')[0].attrib == {
|
|
'class': 'exception-hours',
|
|
'style': 'height:800.0%;top:0.0%;width:48.0%;left:1.0%;',
|
|
'title': 'Exception for a December day',
|
|
}
|
|
|
|
# display excluded period
|
|
TimePeriod.objects.create(
|
|
agenda=agenda, weekday=today.weekday(), start_time=datetime.time(13, 0), end_time=datetime.time(23, 0)
|
|
)
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.id, today.year, today.month, today.day))
|
|
assert len(resp.pyquery.find('.exception-hours')) == 11 # five occurences on two desks
|
|
assert resp.pyquery.find('.exception-hours')[0].attrib == {
|
|
'class': 'exception-hours',
|
|
'style': 'height:500.0%;top:300.0%;width:48.0%;left:1.0%;',
|
|
}
|
|
assert resp.pyquery.find('.exception-hours')[1].attrib == {
|
|
'class': 'exception-hours',
|
|
'style': 'height:500.0%;top:300.0%;width:48.0%;left:50.0%;',
|
|
}
|
|
|
|
|
|
def test_virtual_agenda_settings_empty(app, admin_user):
|
|
agenda = Agenda.objects.create(label='My Virtual agenda', kind='virtual')
|
|
app = login(app)
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
|
|
assert 'Include Agenda' in resp.text
|
|
assert 'Options' in resp.text
|
|
assert 'Export' in resp.text
|
|
assert 'Delete' in resp.text
|
|
assert 'Included Agendas' in resp.text
|
|
assert 'Add Excluded Period' in resp.text
|
|
assert 'Excluded Periods' in resp.text
|
|
assert "This virtual agenda doesn't have any excluded period yet" in resp.text
|
|
assert "This virtual agenda doesn't include any agenda yet" in resp.text
|
|
# No meeting types yet
|
|
assert 'Meeting Types' not in resp.text
|
|
|
|
|
|
def test_virtual_agenda_settings(app, admin_user):
|
|
agenda = Agenda.objects.create(label='My Virtual agenda', kind='virtual')
|
|
meeting_agenda_1 = Agenda.objects.create(label='Meeting agenda 1', kind='meetings')
|
|
meeting_agenda_2 = Agenda.objects.create(label='Meeting agenda 2', kind='meetings')
|
|
VirtualMember.objects.create(virtual_agenda=agenda, real_agenda=meeting_agenda_1)
|
|
VirtualMember.objects.create(virtual_agenda=agenda, real_agenda=meeting_agenda_2)
|
|
MeetingType.objects.create(agenda=meeting_agenda_1, label='MT', slug='mt', duration=10)
|
|
mt2 = MeetingType.objects.create(agenda=meeting_agenda_2, label='MT', slug='mt', duration=10)
|
|
TimePeriod.objects.create(
|
|
agenda=agenda, weekday=0, start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
|
|
)
|
|
app = login(app)
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
|
|
assert "This virtual agenda doesn't include any agenda yet" not in resp.text
|
|
for real_agenda in [meeting_agenda_1, meeting_agenda_2]:
|
|
assert real_agenda.label in resp.text
|
|
assert '/manage/agendas/%s/settings' % real_agenda.pk in resp.text
|
|
|
|
assert 'Meeting Types' in resp.text
|
|
assert 'MT' in resp.text
|
|
assert 'mt' in resp.text
|
|
assert '10' in resp.text
|
|
|
|
assert 'Excluded Periods' in resp.text
|
|
assert 'Monday' in resp.text
|
|
|
|
# Error message when incompatible meeting types
|
|
mt2.delete()
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
|
|
assert "This virtual agenda doesn't have any meeting type." in resp.text
|
|
|
|
|
|
def test_virtual_agenda_settings_include(app, admin_user):
|
|
agenda = Agenda.objects.create(label='My Virtual agenda', kind='virtual')
|
|
Agenda.objects.create(label='Event agenda', kind='events')
|
|
meeting_agenda_1 = Agenda.objects.create(label='Meeting agenda 1', kind='meetings')
|
|
MeetingType.objects.create(label='MT', duration=30, agenda=meeting_agenda_1)
|
|
Agenda.objects.create(label='Meeting agenda 2', kind='meetings')
|
|
|
|
app = login(app)
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
|
|
resp = resp.click('Include Agenda')
|
|
# Only meetings agenda are proposed (2) + 1 empty choice = 3
|
|
assert len(resp.form['real_agenda'].options) == 3
|
|
# Include a real agenda
|
|
resp.form['real_agenda'].value = meeting_agenda_1.pk
|
|
resp = resp.form.submit()
|
|
assert resp.location.endswith('/manage/agendas/%s/settings' % agenda.id)
|
|
assert VirtualMember.objects.get(virtual_agenda=agenda, real_agenda=meeting_agenda_1)
|
|
|
|
resp = resp.follow()
|
|
resp = resp.click('Include Agenda')
|
|
# The previously include agenda is not proposed any more
|
|
assert len(resp.form['real_agenda'].options) == 2
|
|
|
|
|
|
def test_virtual_agenda_settings_add_excluded_period(app, admin_user):
|
|
agenda = Agenda.objects.create(label='My Virtual agenda', kind='virtual')
|
|
|
|
app = login(app)
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
|
|
resp = resp.click('Add Excluded Period')
|
|
|
|
assert 'repeat' not in resp.form.fields
|
|
assert 'weekday_indexes' not in resp.form.fields
|
|
|
|
resp.form.get('weekdays', index=0).checked = True
|
|
resp.form['start_time'] = '10:00'
|
|
resp.form['end_time'] = '17:00'
|
|
resp = resp.form.submit()
|
|
tp = TimePeriod.objects.get(agenda=agenda)
|
|
assert tp.weekday == 0
|
|
assert tp.start_time.hour == 10
|
|
assert tp.start_time.minute == 0
|
|
assert tp.end_time.hour == 17
|
|
assert tp.end_time.minute == 0
|
|
|
|
resp = resp.follow()
|
|
assert 'Monday / 10 a.m. → 5 p.m.' in resp.text
|
|
|
|
|
|
def test_virtual_agenda_settings_edit_excluded_period(app, admin_user):
|
|
agenda = Agenda.objects.create(label='My Virtual agenda', kind='virtual')
|
|
tp = TimePeriod.objects.create(
|
|
agenda=agenda, weekday=0, start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
|
|
)
|
|
app = login(app)
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
|
|
url = '/manage/timeperiods/%s/edit' % tp.pk
|
|
resp = resp.click(href=url)
|
|
|
|
assert 'repeat' not in resp.form.fields
|
|
assert 'weekday_indexes' not in resp.form.fields
|
|
|
|
resp.form['start_time'] = '11:00'
|
|
resp = resp.form.submit()
|
|
tp = TimePeriod.objects.get(agenda=agenda)
|
|
assert tp.weekday == 0
|
|
assert tp.start_time.hour == 11
|
|
assert tp.start_time.minute == 0
|
|
assert tp.end_time.hour == 18
|
|
assert tp.end_time.minute == 0
|
|
|
|
|
|
def test_virtual_agenda_settings_delete_excluded_period(app, admin_user):
|
|
agenda = Agenda.objects.create(label='My Virtual agenda', kind='virtual')
|
|
tp = TimePeriod.objects.create(
|
|
agenda=agenda, weekday=0, start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
|
|
)
|
|
app = login(app)
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
|
|
url = '/manage/timeperiods/%s/delete' % tp.pk
|
|
resp = resp.click(href=url)
|
|
resp = resp.form.submit()
|
|
assert resp.location.endswith('/manage/agendas/%s/settings#open:time-periods' % agenda.id)
|
|
assert TimePeriod.objects.count() == 0
|
|
|
|
|
|
def test_virtual_agenda_settings_include_incompatible_agenda(app, admin_user):
|
|
agenda = Agenda.objects.create(label='My Virtual agenda', kind='virtual')
|
|
meeting_agenda_1 = Agenda.objects.create(label='Meeting agenda 1', kind='meetings')
|
|
MeetingType.objects.create(agenda=meeting_agenda_1, label='MT', slug='mt', duration=10)
|
|
VirtualMember.objects.create(virtual_agenda=agenda, real_agenda=meeting_agenda_1)
|
|
meeting_agenda_2 = Agenda.objects.create(label='Meeting agenda 2', kind='meetings')
|
|
app = login(app)
|
|
|
|
# refused because different slug
|
|
mt = MeetingType.objects.create(agenda=meeting_agenda_2, label='MT', slug='mtt', duration=10)
|
|
resp = app.get('/manage/agendas/%s/add-virtual-member' % agenda.pk)
|
|
resp.form['real_agenda'].value = meeting_agenda_2.pk
|
|
resp = resp.form.submit()
|
|
assert 'This agenda does not have the same meeting types provided by the virtual agenda.' in resp.text
|
|
assert 'Meeting type "MT" (10 minutes) (identifier: mt) does no exist.' in resp.text
|
|
assert meeting_agenda_2.virtual_agendas.count() == 0
|
|
mt.delete()
|
|
|
|
# refused because different duration
|
|
mt = MeetingType.objects.create(agenda=meeting_agenda_2, label='MT', slug='mt', duration=15)
|
|
resp = app.get('/manage/agendas/%s/add-virtual-member' % agenda.pk)
|
|
resp.form['real_agenda'].value = meeting_agenda_2.pk
|
|
resp = resp.form.submit()
|
|
assert 'This agenda does not have the same meeting types provided by the virtual agenda.' in resp.text
|
|
assert 'Meeting type "MT" (10 minutes) (identifier: mt) does no exist.' in resp.text
|
|
assert meeting_agenda_2.virtual_agendas.count() == 0
|
|
mt.delete()
|
|
|
|
# refused because different label
|
|
mt = MeetingType.objects.create(agenda=meeting_agenda_2, label='MTT', slug='mt', duration=10)
|
|
resp = app.get('/manage/agendas/%s/add-virtual-member' % agenda.pk)
|
|
resp.form['real_agenda'].value = meeting_agenda_2.pk
|
|
resp = resp.form.submit()
|
|
assert 'This agenda does not have the same meeting types provided by the virtual agenda.' in resp.text
|
|
assert 'Meeting type "MT" (10 minutes) (identifier: mt) does no exist.' in resp.text
|
|
assert meeting_agenda_2.virtual_agendas.count() == 0
|
|
mt.delete()
|
|
|
|
# refused because has one more meeting type
|
|
mt = MeetingType.objects.create(agenda=meeting_agenda_2, label='MT', slug='mt', duration=10)
|
|
mt2 = MeetingType.objects.create(agenda=meeting_agenda_2, label='AA', slug='aa', duration=30)
|
|
resp = app.get('/manage/agendas/%s/add-virtual-member' % agenda.pk)
|
|
resp.form['real_agenda'].value = meeting_agenda_2.pk
|
|
resp = resp.form.submit()
|
|
assert 'This agenda does not have the same meeting types provided by the virtual agenda.' in resp.text
|
|
assert 'Extra meeting type, "AA".' in resp.text
|
|
assert meeting_agenda_2.virtual_agendas.count() == 0
|
|
|
|
# ok because mt2 is marked as deleted
|
|
mt2.deleted = True
|
|
mt2.save()
|
|
resp = app.get('/manage/agendas/%s/add-virtual-member' % agenda.pk)
|
|
resp.form['real_agenda'].value = meeting_agenda_2.pk
|
|
resp = resp.form.submit()
|
|
assert meeting_agenda_2.virtual_agendas.count() == 1
|
|
VirtualMember.objects.filter(real_agenda=meeting_agenda_2).delete()
|
|
mt.delete()
|
|
mt2.delete()
|
|
|
|
# refused because has one less meeting type
|
|
mt = MeetingType.objects.create(agenda=meeting_agenda_2, label='MT', slug='mt', duration=10)
|
|
mt2 = MeetingType.objects.create(agenda=meeting_agenda_1, label='AA', slug='aa', duration=30)
|
|
resp = app.get('/manage/agendas/%s/add-virtual-member' % agenda.pk)
|
|
resp.form['real_agenda'].value = meeting_agenda_2.pk
|
|
resp = resp.form.submit()
|
|
assert 'This agenda does not have the same meeting types provided by the virtual agenda.' in resp.text
|
|
assert 'Meeting type "AA" (30 minutes) (identifier: aa) does no exist.' in resp.text
|
|
assert meeting_agenda_2.virtual_agendas.count() == 0
|
|
mt.delete()
|
|
mt2.delete()
|
|
|
|
# deleted meeting type is not checked
|
|
mt = MeetingType.objects.create(agenda=meeting_agenda_2, label='MT', slug='mt', duration=10, deleted=True)
|
|
resp = app.get('/manage/agendas/%s/add-virtual-member' % agenda.pk)
|
|
resp.form['real_agenda'].value = meeting_agenda_2.pk
|
|
resp = resp.form.submit()
|
|
assert 'This agenda does not have the same meeting types provided by the virtual agenda.' in resp.text
|
|
assert 'Meeting type "MT" (10 minutes) (identifier: mt) does no exist.' in resp.text
|
|
assert meeting_agenda_2.virtual_agendas.count() == 0
|
|
mt.delete()
|
|
|
|
|
|
def test_cant_delete_meetingtype_used_by_virtual_agenda(app, admin_user):
|
|
agenda = Agenda.objects.create(label='My Virtual agenda', kind='virtual')
|
|
meeting_agenda_1 = Agenda.objects.create(label='Meeting agenda 1', kind='meetings')
|
|
mt1 = MeetingType.objects.create(agenda=meeting_agenda_1, label='MT', slug='mt', duration=10)
|
|
VirtualMember.objects.create(virtual_agenda=agenda, real_agenda=meeting_agenda_1)
|
|
|
|
# ok because there is only one agenda in the virtual agenda
|
|
app = login(app)
|
|
resp = app.get('/manage/agendas/%s/settings' % meeting_agenda_1.pk)
|
|
resp = resp.click('MT')
|
|
resp = resp.click('Delete')
|
|
resp = resp.form.submit()
|
|
assert not meeting_agenda_1.iter_meetingtypes()
|
|
mt1.deleted = False
|
|
mt1.save()
|
|
|
|
meeting_agenda_2 = Agenda.objects.create(label='Meeting agenda 2', kind='meetings')
|
|
mt2 = MeetingType.objects.create(agenda=meeting_agenda_2, label='MT', slug='mt', duration=10)
|
|
VirtualMember.objects.create(virtual_agenda=agenda, real_agenda=meeting_agenda_2)
|
|
|
|
resp = app.get('/manage/agendas/%s/settings' % meeting_agenda_2.pk)
|
|
resp = resp.click('MT')
|
|
resp = resp.click('Delete')
|
|
assert 'This cannot be removed as it used by a virtual agenda' in resp.text
|
|
assert 'disabled' in resp.text
|
|
resp = app.post('/manage/meetingtypes/%s/delete' % mt2.pk, status=403)
|
|
|
|
|
|
def test_cant_modify_meetingtype_used_by_virtual_agenda(app, admin_user):
|
|
agenda = Agenda.objects.create(label='My Virtual agenda', kind='virtual')
|
|
meeting_agenda_1 = Agenda.objects.create(label='Meeting agenda 1', kind='meetings')
|
|
mt1 = MeetingType.objects.create(agenda=meeting_agenda_1, label='MT', slug='mt', duration=10)
|
|
VirtualMember.objects.create(virtual_agenda=agenda, real_agenda=meeting_agenda_1)
|
|
app = login(app)
|
|
|
|
# ok because there is only one agenda in the virtual agenda
|
|
resp = app.get('/manage/meetingtypes/%s/edit' % mt1.pk)
|
|
resp.form['label'].value = 'MTT'
|
|
resp = resp.form.submit()
|
|
assert MeetingType.objects.get(agenda=meeting_agenda_1, label='MTT', slug='mt', duration=10)
|
|
|
|
meeting_agenda_2 = Agenda.objects.create(label='Meeting agenda 2', kind='meetings')
|
|
mt2 = MeetingType.objects.create(agenda=meeting_agenda_2, label='MTT', slug='mt', duration=10)
|
|
VirtualMember.objects.create(virtual_agenda=agenda, real_agenda=meeting_agenda_2)
|
|
|
|
app = login(app)
|
|
resp = app.get('/manage/meetingtypes/%s/edit' % mt2.pk)
|
|
resp.form['label'].value = 'Oho'
|
|
resp = resp.form.submit()
|
|
assert 'This meetingtype is used by a virtual agenda' in resp.text
|
|
mt = MeetingType.objects.get(pk=mt2.pk)
|
|
assert mt.label == 'MTT'
|
|
|
|
|
|
def test_cant_add_meetingtype_if_virtual_agenda(app, admin_user, get_proper_html_str):
|
|
agenda = Agenda.objects.create(label='My Virtual agenda', kind='virtual')
|
|
meeting_agenda_1 = Agenda.objects.create(label='Meeting agenda 1', kind='meetings')
|
|
MeetingType.objects.create(agenda=meeting_agenda_1, label='MT', slug='mt', duration=10)
|
|
VirtualMember.objects.create(virtual_agenda=agenda, real_agenda=meeting_agenda_1)
|
|
app = login(app)
|
|
|
|
# ok because there is only one agenda in the virtual agenda
|
|
resp = app.get('/manage/agendas/%s/add-meeting-type' % meeting_agenda_1.pk)
|
|
resp.form['duration'].value = '12'
|
|
resp.form['label'].value = 'Oho'
|
|
resp = resp.form.submit()
|
|
assert MeetingType.objects.filter(agenda=meeting_agenda_1).count() == 2
|
|
MeetingType.objects.get(agenda=meeting_agenda_1, label='Oho').delete()
|
|
|
|
meeting_agenda_2 = Agenda.objects.create(label='Meeting agenda 2', kind='meetings')
|
|
VirtualMember.objects.create(virtual_agenda=agenda, real_agenda=meeting_agenda_2)
|
|
MeetingType.objects.create(agenda=meeting_agenda_2, label='MT', slug='mt', duration=10)
|
|
|
|
app = login(app)
|
|
resp = app.get('/manage/agendas/%s/add-meeting-type' % meeting_agenda_1.pk)
|
|
resp.form['duration'].value = '12'
|
|
resp.form['label'].value = 'Oho'
|
|
resp = resp.form.submit()
|
|
assert (
|
|
get_proper_html_str('Can't add a meetingtype to an agenda that is included in a virtual agenda.')
|
|
in resp.text
|
|
)
|
|
assert MeetingType.objects.filter(agenda=meeting_agenda_1).count() == 1
|
|
|
|
|
|
def test_duplicate_agenda(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Foo Bar', slug='foo-bar', kind='meetings')
|
|
assert Agenda.objects.count() == 1
|
|
|
|
app = login(app)
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
|
|
resp = resp.click('Duplicate')
|
|
resp = resp.form.submit()
|
|
assert Agenda.objects.count() == 2
|
|
|
|
new_agenda = Agenda.objects.exclude(pk=agenda.pk).first()
|
|
assert resp.location == '/manage/agendas/%s/settings' % new_agenda.pk
|
|
assert new_agenda.pk != agenda.pk
|
|
|
|
resp = resp.follow()
|
|
assert 'copy-of-foo-bar' in resp.text
|
|
|
|
resp = resp.click('Duplicate')
|
|
resp.form['label'] = 'hop'
|
|
resp = resp.form.submit().follow()
|
|
assert 'hop' in resp.text
|
|
|
|
|
|
def test_booking_cancellation_meetings_agenda(app, admin_user, manager_user, managers_group, api_user):
|
|
agenda = Agenda.objects.create(label='Passeports', kind='meetings', view_role=managers_group)
|
|
desk = Desk.objects.create(agenda=agenda, label='Desk A')
|
|
meetingtype = MeetingType(agenda=agenda, label='passeport', duration=20)
|
|
meetingtype.save()
|
|
today = datetime.date(2018, 11, 10) # fixed day
|
|
timeperiod_weekday = today.weekday()
|
|
timeperiod = TimePeriod(
|
|
desk=desk, weekday=timeperiod_weekday, start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
|
|
)
|
|
timeperiod.save()
|
|
|
|
# book a slot
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
bookings_resp = app.get('/api/agenda/%s/meetings/%s/datetimes/' % (agenda.slug, meetingtype.slug))
|
|
booking_url = bookings_resp.json['data'][0]['api']['fillslot_url']
|
|
booking_json = app.post_json(booking_url, params={'backoffice_url': 'http://example.org/'}).json
|
|
|
|
booking = Booking.objects.get(pk=booking_json['booking_id'])
|
|
date = booking.event.start_datetime
|
|
month_view_url = '/manage/agendas/%s/month/%d/%d/%d/' % (agenda.id, date.year, date.month, date.day)
|
|
|
|
app.reset()
|
|
login(app, username='admin', password='admin')
|
|
resp = app.get(month_view_url)
|
|
assert len(resp.pyquery.find('div.booking a.cancel')) == 1 # cancel button is shown
|
|
|
|
resp = resp.click('Cancel')
|
|
# no callback url was provided at booking, warn user but allow cancellation as they are admin
|
|
assert 'no callback url' in resp.text
|
|
assert 'Proceed with cancellation' in resp.text
|
|
|
|
resp = resp.form.submit()
|
|
booking.refresh_from_db()
|
|
assert booking.cancellation_datetime
|
|
|
|
app.reset()
|
|
booking.cancellation_datetime = None
|
|
booking.save()
|
|
login(app, username='manager', password='manager')
|
|
resp = app.get(month_view_url)
|
|
assert len(resp.pyquery.find('div.booking a.cancel')) == 1 # cancel button is shown
|
|
|
|
resp = resp.click('Cancel')
|
|
# no callback url was provided at booking, warn user cancellation is forbidden
|
|
assert 'no callback url' in resp.text
|
|
assert 'Proceed with cancellation' not in resp.text
|
|
booking.delete()
|
|
|
|
# provide callback url this time
|
|
booking_url2 = bookings_resp.json['data'][1]['api']['fillslot_url']
|
|
booking_json2 = app.post_json(
|
|
booking_url2, params={'cancel_callback_url': 'http://example.org/jump/trigger/'}
|
|
).json
|
|
resp = app.get(month_view_url)
|
|
resp = resp.click('Cancel')
|
|
assert 'no callback url' not in resp.text
|
|
|
|
# a signed request is sent to callback_url
|
|
with mock.patch('chrono.utils.requests_wrapper.RequestsSession.send') as mock_send:
|
|
mock_response = mock.Mock(status_code=200)
|
|
mock_send.return_value = mock_response
|
|
resp = resp.form.submit()
|
|
url = mock_send.call_args[0][0].url
|
|
assert check_query(url.split('?', 1)[-1], 'chrono')
|
|
|
|
booking2 = Booking.objects.get(pk=booking_json2['booking_id'])
|
|
resp = resp.follow()
|
|
assert not resp.pyquery.find('div.booking')
|
|
assert booking2.cancellation_datetime
|
|
|
|
# request fails
|
|
booking_url3 = bookings_resp.json['data'][2]['api']['fillslot_url']
|
|
booking_json3 = app.post_json(
|
|
booking_url3, params={'cancel_callback_url': 'http://example.org/jump/trigger/'}
|
|
).json
|
|
booking3 = Booking.objects.get(pk=booking_json3['booking_id'])
|
|
|
|
def mocked_requests_connection_error(*args, **kwargs):
|
|
raise requests.exceptions.ConnectionError('unreachable')
|
|
|
|
resp = app.get(month_view_url)
|
|
resp = resp.click('Cancel')
|
|
assert resp.form['disable_trigger'].attrs['type'] == 'hidden'
|
|
|
|
with mock.patch('chrono.utils.requests_wrapper.RequestsSession.send') as mock_send:
|
|
mock_response = mock.Mock(status_code=200)
|
|
mock_send.return_value = mock_response
|
|
mock_send.side_effect = mocked_requests_connection_error
|
|
resp = resp.form.submit()
|
|
|
|
assert 'error' in resp.text
|
|
booking3.refresh_from_db()
|
|
assert not booking3.cancellation_datetime
|
|
|
|
# there is an option to force cancellation
|
|
resp.form['disable_trigger'] = True
|
|
resp = resp.form.submit()
|
|
booking3.refresh_from_db()
|
|
assert booking3.cancellation_datetime
|
|
|
|
# test day view
|
|
day_view_url = '/manage/agendas/%s/day/%d/%d/%d/' % (agenda.id, date.year, date.month, date.day)
|
|
booking_url4 = bookings_resp.json['data'][3]['api']['fillslot_url']
|
|
booking_json4 = app.post(booking_url4).json
|
|
resp = app.get(day_view_url)
|
|
resp = resp.click('Cancel')
|
|
resp = resp.form.submit()
|
|
assert resp.location.endswith(day_view_url)
|
|
|
|
booking4 = Booking.objects.get(pk=booking_json4['booking_id'])
|
|
assert booking4.cancellation_datetime
|
|
|
|
# again
|
|
app.get('/manage/agendas/%s/bookings/%s/cancel' % (agenda.pk, booking4.pk), status=404)
|
|
|
|
|
|
def test_booking_cancellation_meetings_agenda_backoffice_url_translation(
|
|
app, admin_user, manager_user, managers_group, api_user
|
|
):
|
|
agenda = Agenda.objects.create(label='Passeports', kind='meetings', view_role=managers_group)
|
|
desk = Desk.objects.create(agenda=agenda, label='Desk A')
|
|
meetingtype = MeetingType(agenda=agenda, label='passeport', duration=20)
|
|
meetingtype.save()
|
|
today = datetime.date(2018, 11, 10) # fixed day
|
|
timeperiod_weekday = today.weekday()
|
|
timeperiod = TimePeriod(
|
|
desk=desk, weekday=timeperiod_weekday, start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
|
|
)
|
|
timeperiod.save()
|
|
|
|
# book a slot
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
bookings_resp = app.get('/api/agenda/%s/meetings/%s/datetimes/' % (agenda.slug, meetingtype.slug))
|
|
booking_url = bookings_resp.json['data'][0]['api']['fillslot_url']
|
|
booking_json = app.post_json(booking_url, params={'backoffice_url': 'http://example.org/'}).json
|
|
|
|
booking = Booking.objects.get(pk=booking_json['booking_id'])
|
|
assert booking.backoffice_url == 'publik://default/'
|
|
date = booking.event.start_datetime
|
|
month_view_url = '/manage/agendas/%s/month/%d/%d/%d/' % (agenda.id, date.year, date.month, date.day)
|
|
|
|
app.reset()
|
|
login(app, username='admin', password='admin')
|
|
resp = app.get(month_view_url)
|
|
resp = resp.click('Cancel')
|
|
assert 'http://example.org/' in resp.text
|
|
|
|
|
|
def test_agenda_notifications(app, admin_user, managers_group):
|
|
agenda = Agenda.objects.create(label='Events', kind='events')
|
|
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id)
|
|
|
|
assert 'Notifications' in resp.text
|
|
assert 'Notifications are disabled' in resp.text
|
|
|
|
resp = resp.click('Configure', href='notifications')
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id)
|
|
assert 'Notifications are disabled' in resp.text
|
|
|
|
resp = resp.click('Configure', href='notifications')
|
|
resp.form['cancelled_event'] = 'use-email-field'
|
|
resp = resp.form.submit().follow()
|
|
assert 'Notifications are disabled' in resp.text
|
|
|
|
agenda.view_role = managers_group
|
|
agenda.save()
|
|
|
|
resp = resp.click('Configure', href='notifications')
|
|
resp.form['cancelled_event_emails'] = 'hop@entrouvert.com, top@entrouvert.com'
|
|
resp.form['almost_full_event'] = 'edit-role'
|
|
option = resp.form['almost_full_event'].selectedIndex
|
|
assert resp.form['almost_full_event'].options[option][2] == 'Edit Role (undefined)'
|
|
resp.form['full_event'] = 'view-role'
|
|
option = resp.form['full_event'].selectedIndex
|
|
assert resp.form['full_event'].options[option][2] == 'View Role (Managers)'
|
|
resp = resp.form.submit().follow()
|
|
|
|
settings = agenda.notifications_settings
|
|
assert settings.almost_full_event == 'edit-role'
|
|
assert settings.full_event == 'view-role'
|
|
assert settings.cancelled_event == 'use-email-field'
|
|
assert settings.cancelled_event_emails == ['hop@entrouvert.com', 'top@entrouvert.com']
|
|
|
|
assert 'Cancelled event: hop@entrouvert.com, top@entrouvert.com will be notified' in resp.text
|
|
assert 'Almost full event (90%): Edit Role (undefined) will be notified' in resp.text
|
|
assert 'Full event: View Role (Managers) will be notified' in resp.text
|
|
|
|
agenda.edit_role = Group.objects.create(name='hop')
|
|
agenda.save()
|
|
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id)
|
|
assert 'Almost full event (90%): Edit Role (hop) will be notified' in resp.text
|
|
|
|
|
|
def test_agenda_notifications_no_old_events(app, admin_user, mailoutbox):
|
|
agenda = Agenda.objects.create(label='Events', kind='events')
|
|
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
|
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10, label='Old event')
|
|
event.cancelled = True
|
|
event.save()
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id)
|
|
|
|
resp = resp.click('Configure', href='notifications')
|
|
resp.form['cancelled_event'] = 'use-email-field'
|
|
resp.form['cancelled_event_emails'] = 'hop@entrouvert.com'
|
|
resp.form.submit()
|
|
|
|
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10, label='New event')
|
|
event.cancelled = True
|
|
event.save()
|
|
|
|
call_command('send_email_notifications')
|
|
# no notification is sent for old event
|
|
assert len(mailoutbox) == 1
|
|
assert 'New event' in mailoutbox[0].subject
|
|
|
|
|
|
def test_manager_reminders(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Events', kind='events')
|
|
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id)
|
|
|
|
assert 'Booking reminders' in resp.text
|
|
assert 'Reminders are disabled' in resp.text
|
|
|
|
resp = resp.click('Configure', href='reminder')
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id)
|
|
assert 'Reminders are disabled' in resp.text
|
|
|
|
resp = resp.click('Configure', href='reminder')
|
|
assert 'SMS' not in resp.text
|
|
|
|
resp.form['days_before_email'] = 3
|
|
resp.form['email_extra_info'] = 'test'
|
|
resp = resp.form.submit().follow()
|
|
|
|
assert 'Users will be reminded of their booking by email, 3 days in advance.' in resp.text
|
|
assert 'reminded of their booking by SMS' not in resp.text
|
|
|
|
with override_settings(SMS_URL='https://passerelle.test.org/sms/send/', SMS_SENDER='EO'):
|
|
resp = resp.click('Configure', href='reminder')
|
|
resp.form['days_before_sms'] = 3
|
|
resp = resp.form.submit().follow()
|
|
assert 'Users will be reminded of their booking both by email and by SMS, 3 days in advance.' in resp.text
|
|
|
|
with override_settings(SMS_URL='https://passerelle.test.org/sms/send/', SMS_SENDER='EO'):
|
|
resp = resp.click('Configure', href='reminder')
|
|
resp.form['days_before_sms'] = 2
|
|
resp = resp.form.submit().follow()
|
|
assert 'Users will be reminded of their booking by email, 3 days in advance.' in resp.text
|
|
assert 'Users will be reminded of their booking by SMS, 2 days in advance.' in resp.text
|
|
|
|
with override_settings(SMS_URL='https://passerelle.test.org/sms/send/', SMS_SENDER='EO'):
|
|
resp = resp.click('Configure', href='reminder')
|
|
resp.form['days_before_email'] = ''
|
|
resp = resp.form.submit().follow()
|
|
assert 'reminded of their booking by email' not in resp.text
|
|
assert 'Users will be reminded of their booking by SMS, 2 days in advance.' in resp.text
|
|
|
|
agenda = Agenda.objects.create(label='Meetings', kind='meetings')
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id)
|
|
assert 'Booking reminders' in resp.text
|
|
|
|
agenda = Agenda.objects.create(label='Virtual', kind='virtual')
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id)
|
|
assert 'Booking reminders' not in resp.text
|
|
|
|
|
|
@override_settings(SMS_URL='https://passerelle.test.org/sms/send/', SMS_SENDER='EO', TIME_ZONE='UTC')
|
|
@pytest.mark.parametrize('extra_info_field', ('sms_extra_info', 'email_extra_info'))
|
|
def test_manager_reminders_templated_extra_info(app, admin_user, extra_info_field):
|
|
agenda = Agenda.objects.create(label='Events', kind='events')
|
|
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id)
|
|
resp = resp.click('Configure', href='reminder')
|
|
|
|
extra_info = 'test {{ booking.extra_data.xxx }} {{ booking.event.label|default:booking.extra_data.yyy }}'
|
|
resp.form[extra_info_field] = extra_info
|
|
resp = resp.form.submit().follow()
|
|
assert getattr(agenda.reminder_settings, extra_info_field) == extra_info
|
|
|
|
invalid_templates = [
|
|
'{{ syntax error }}',
|
|
'{{ booking.label|invalidfilter }}',
|
|
]
|
|
for template in invalid_templates:
|
|
resp = app.get('/manage/agendas/%s/reminder' % agenda.id)
|
|
resp.form[extra_info_field] = template
|
|
resp = resp.form.submit()
|
|
assert 'syntax error' in resp.text
|
|
|
|
|
|
def test_manager_reminders_preview(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Events', kind='events')
|
|
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
|
AgendaReminderSettings.objects.create(
|
|
agenda=agenda,
|
|
days_before_email=1,
|
|
email_extra_info='An ID will be required in order to process your form.',
|
|
days_before_sms=1,
|
|
sms_extra_info='Take ID card.',
|
|
)
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id)
|
|
assert (
|
|
'Users will be reminded of their booking both by email and by SMS, one day in advance.' in resp.text
|
|
)
|
|
|
|
resp = resp.click('Preview email')
|
|
assert 'Users will receive the following email:' in resp.text
|
|
assert len(resp.pyquery.find('p.email-subject')) == 1
|
|
assert '<strong>Subject:</strong> Reminder for your booking tomorrow at 2:30 p.m.' in resp.text
|
|
assert (
|
|
'You have booked event "Lorem Ipsum <small>(event label)</small>", on Tuesday 2 June at 2:30 p.m..'
|
|
in resp.text
|
|
)
|
|
assert 'An ID will be required' in resp.text
|
|
assert ' ea commodo consequat. <small>(event description, if present)</small>' in resp.text
|
|
assert 'Pricing: ... <small>(event pricing, if present)</small>' in resp.text
|
|
assert '<a href="#">More information<br>(link to event url, if present)</a>' in resp.text
|
|
|
|
resp = resp.click('Return to settings')
|
|
resp = resp.click('Preview SMS')
|
|
assert 'Users will receive the following SMS:' in resp.text
|
|
assert (
|
|
'Reminder: you have booked event "Lorem Ipsum <small>(event label)</small>", on 02/06 at 2:30 p.m.. Take ID card.'
|
|
in resp.text
|
|
)
|
|
|
|
# templates in extra info should not be interpreted
|
|
agenda.reminder_settings.sms_extra_info = '{{ booking.extra_data.xxx }}'
|
|
agenda.reminder_settings.email_extra_info = '{{ booking.extra_data.xxx }}'
|
|
agenda.reminder_settings.save()
|
|
|
|
resp = resp.click('Return to settings')
|
|
resp = resp.click('Preview SMS')
|
|
assert '{{ booking.extra_data.xxx }}' in resp.text
|
|
|
|
resp = resp.click('Return to settings')
|
|
resp = resp.click('Preview email')
|
|
assert '{{ booking.extra_data.xxx }}' in resp.text
|
|
|
|
|
|
def test_manager_reminders_test_sending(app, admin_user, freezer, mailoutbox, settings):
|
|
agenda = Agenda.objects.create(label='Events', kind='events')
|
|
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
|
AgendaReminderSettings.objects.create(
|
|
agenda=agenda,
|
|
days_before_email=1,
|
|
email_extra_info='Take your {{ booking.extra_data.document_type }}.',
|
|
days_before_sms=1,
|
|
sms_extra_info='Take {{ booking.extra_data.document_type }}.',
|
|
)
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id)
|
|
resp = resp.click('Test reminder sending')
|
|
|
|
assert 'phone_number' not in resp.form.fields
|
|
assert resp.form['msg_type'].attrs['type'] == 'hidden'
|
|
assert resp.form['booking'].options == [('', True, '---------')]
|
|
|
|
# add bookings
|
|
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
|
|
freezer.move_to('2020-01-01 14:00')
|
|
Booking.objects.create(user_first_name='oldest', user_email='t@test.org', event=event)
|
|
freezer.move_to('2020-01-02 14:00')
|
|
for _ in range(10):
|
|
Booking.objects.create(
|
|
event=event,
|
|
user_first_name='Jon',
|
|
user_last_name='Doe',
|
|
user_email='t@test.org',
|
|
user_phone_number='+336123456780',
|
|
)
|
|
freezer.move_to('2020-01-03 14:00')
|
|
last_booking = Booking.objects.create(
|
|
event=event,
|
|
user_first_name='Jane',
|
|
user_last_name='Doe',
|
|
user_email='t@test.org',
|
|
extra_emails=['u@test.org'],
|
|
user_phone_number='+33122334455',
|
|
extra_phone_numbers=['+33122334456'],
|
|
extra_data={'document_type': 'receipt'},
|
|
)
|
|
|
|
resp = app.get('/manage/agendas/%s/reminder/test/' % agenda.id)
|
|
assert [x[2] for x in resp.form['booking'].options[:2]] == [
|
|
'---------',
|
|
'Jane Doe, t@test.org, u@test.org (01/03/2020 3 p.m.)',
|
|
]
|
|
assert [x[2] for x in resp.form['booking'].options[2:]] == ['Jon Doe, t@test.org (01/02/2020 3 p.m.)'] * 9
|
|
|
|
resp.form['booking'] = last_booking.pk
|
|
resp = resp.form.submit().follow()
|
|
|
|
assert len(mailoutbox) == 2
|
|
assert {x.to[0] for x in mailoutbox} == {'t@test.org', 'u@test.org'}
|
|
assert all('Take your receipt' in mail.body for mail in mailoutbox)
|
|
mailoutbox.clear()
|
|
|
|
settings.SMS_URL = 'https://passerelle.test.org/sms/send/'
|
|
settings.SMS_SENDER = 'EO'
|
|
|
|
resp = app.get('/manage/agendas/%s/reminder/test/' % agenda.id)
|
|
assert [x[2] for x in resp.form['booking'].options[:2]] == [
|
|
'---------',
|
|
'Jane Doe, t@test.org, u@test.org, +33122334455, +33122334456 (01/03/2020 3 p.m.)',
|
|
]
|
|
assert [x[2] for x in resp.form['booking'].options[2:]] == [
|
|
'Jon Doe, t@test.org, +336123456780 (01/02/2020 3 p.m.)'
|
|
] * 9
|
|
|
|
resp.form['booking'] = last_booking.pk
|
|
resp.form['msg_type'] = ['email', 'sms']
|
|
with mock.patch('chrono.utils.requests_wrapper.RequestsSession.send') as mock_send:
|
|
mock_send.return_value = mock.Mock(status_code=200)
|
|
resp = resp.form.submit().follow()
|
|
|
|
body = json.loads(mock_send.call_args[0][0].body.decode())
|
|
assert 'Take receipt' in body['message']
|
|
assert set(body['to']) == {'+33122334455', '+33122334456'}
|
|
|
|
assert len(mailoutbox) == 2
|
|
mailoutbox.clear()
|
|
|
|
resp = app.get('/manage/agendas/%s/reminder/test/' % agenda.id)
|
|
resp.form['booking'] = last_booking.pk
|
|
resp.form['msg_type'] = ['sms', 'email']
|
|
resp.form['email'] = 'v@test.org'
|
|
resp.form['phone_number'] = '+33333333333'
|
|
with mock.patch('chrono.utils.requests_wrapper.RequestsSession.send') as mock_send:
|
|
mock_send.return_value = mock.Mock(status_code=200)
|
|
resp = resp.form.submit().follow()
|
|
|
|
body = json.loads(mock_send.call_args[0][0].body.decode())
|
|
assert body['to'] == ['+33333333333']
|
|
assert len(mailoutbox) == 1
|
|
assert mailoutbox[0].to == ['v@test.org']
|
|
|
|
|
|
def test_manager_agenda_roles(app, admin_user, manager_user):
|
|
agenda = Agenda.objects.create(label='Events', kind='events')
|
|
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id)
|
|
resp = resp.click('Configure', href='roles')
|
|
|
|
resp.form['edit_role'] = manager_user.groups.all()[0].pk
|
|
resp = resp.form.submit().follow()
|
|
|
|
assert 'Edit Role: Managers' in resp.text
|
|
|
|
|
|
def test_manager_agenda_booking_delays(app, admin_user):
|
|
agenda = Agenda.objects.create(label='Events', kind='events')
|
|
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
|
|
|
login(app)
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.id)
|
|
resp = resp.click('Configure', href='delays')
|
|
|
|
resp.form['maximal_booking_delay'] = 42
|
|
resp = resp.form.submit().follow()
|
|
|
|
assert '42 days' in resp.text
|
|
agenda.refresh_from_db()
|
|
assert agenda.maximal_booking_delay == 42
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
'view',
|
|
(
|
|
'/manage/agendas/%(agenda)s/day/%(year)d/%(month)d/%(day)d/',
|
|
'/manage/agendas/%(agenda)s/month/%(year)d/%(month)d/%(day)d/',
|
|
),
|
|
)
|
|
def test_agenda_booking_colors(app, admin_user, api_user, view):
|
|
agenda = Agenda.objects.create(label='New Example', kind='meetings')
|
|
desk = Desk.objects.create(agenda=agenda, label='New Desk')
|
|
meetingtype = MeetingType.objects.create(agenda=agenda, label='Bar', duration=30)
|
|
today = datetime.date.today()
|
|
TimePeriod.objects.create(
|
|
desk=desk, weekday=today.weekday(), start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
|
|
)
|
|
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
datetimes_resp = app.get('/api/agenda/%s/meetings/%s/datetimes/' % (agenda.slug, meetingtype.slug))
|
|
booking_url = datetimes_resp.json['data'][0]['api']['fillslot_url']
|
|
|
|
# book first slot without colors
|
|
resp = app.post(booking_url)
|
|
date = Booking.objects.all()[0].event.start_datetime
|
|
|
|
app.reset()
|
|
login(app)
|
|
|
|
url = view % {'agenda': agenda.id, 'year': date.year, 'month': date.month, 'day': date.day}
|
|
resp = app.get(url)
|
|
assert len(resp.pyquery.find('div.booking')) == 1
|
|
assert 'booking-color-' not in resp.text
|
|
assert 'Booking colors:' not in resp.text
|
|
|
|
app.reset()
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
booking_url2 = datetimes_resp.json['data'][1]['api']['fillslot_url']
|
|
booking_url3 = datetimes_resp.json['data'][2]['api']['fillslot_url']
|
|
resp = app.post_json(booking_url2, params={'use_color_for': 'Cooking'})
|
|
resp = app.post_json(booking_url3, params={'use_color_for': 'Cooking'})
|
|
booking = Booking.objects.get(pk=resp.json['booking_id'])
|
|
|
|
app.reset()
|
|
login(app)
|
|
|
|
resp = app.get(url)
|
|
assert len(resp.pyquery.find('div.booking')) == 3
|
|
assert len(resp.pyquery.find('div.booking.booking-color-%s' % booking.color.index)) == 2
|
|
assert 'Booking colors:' in resp.text
|
|
assert len(resp.pyquery.find('div.booking-colors span.booking-color-label')) == 1
|
|
assert resp.text.count('Cooking') == 3 # 2 bookings + legend
|
|
|
|
app.reset()
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
booking_url4 = datetimes_resp.json['data'][3]['api']['fillslot_url']
|
|
resp = app.post_json(booking_url4, params={'use_color_for': 'Swimming'})
|
|
new_booking = Booking.objects.get(pk=resp.json['booking_id'])
|
|
|
|
app.reset()
|
|
login(app)
|
|
|
|
resp = app.get(url)
|
|
assert len(resp.pyquery.find('div.booking')) == 4
|
|
assert len(resp.pyquery.find('div.booking.booking-color-%s' % booking.color.index)) == 2
|
|
assert len(resp.pyquery.find('div.booking.booking-color-%s' % new_booking.color.index)) == 1
|
|
assert resp.text.count('Swimming') == 2 # 1 booking + legend
|
|
assert 'Booking colors:' in resp.text
|
|
assert len(resp.pyquery.find('div.booking-colors span.booking-color-label')) == 2
|
|
|
|
|
|
@freezegun.freeze_time('2022-03-01 14:00')
|
|
def test_agenda_day_and_month_views_weekday_indexes(app, admin_user):
|
|
agenda = Agenda.objects.create(label='New Example', kind='meetings')
|
|
desk = Desk.objects.create(agenda=agenda, label='New Desk')
|
|
MeetingType.objects.create(agenda=agenda, label='Bar', duration=30)
|
|
today = datetime.date.today()
|
|
TimePeriod.objects.create(
|
|
desk=desk,
|
|
weekday=today.weekday(),
|
|
start_time=datetime.time(10, 0),
|
|
end_time=datetime.time(14, 0),
|
|
weekday_indexes=[1, 3],
|
|
)
|
|
TimePeriod.objects.create(
|
|
desk=desk,
|
|
weekday=today.weekday(),
|
|
start_time=datetime.time(14, 0),
|
|
end_time=datetime.time(17, 0),
|
|
weekday_indexes=[3, 5],
|
|
)
|
|
login(app)
|
|
|
|
# check day view
|
|
resp = app.get('/manage/agendas/%s/day/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert resp.text.count('<tr') == 5 # 10->14
|
|
assert 'style="height: 400%; top: 0%;"' in resp.text
|
|
|
|
resp = app.get('/manage/agendas/%s/day/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day + 7))
|
|
assert 'No opening hours this day.' in resp.text
|
|
|
|
resp = app.get('/manage/agendas/%s/day/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day + 14))
|
|
assert resp.text.count('<tr') == 8 # 10->14, 14->17
|
|
assert 'style="height: 700%; top: 0%;"' in resp.text
|
|
|
|
resp = app.get('/manage/agendas/%s/day/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day + 21))
|
|
assert 'No opening hours this day.' in resp.text
|
|
|
|
resp = app.get('/manage/agendas/%s/day/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day + 28))
|
|
assert resp.text.count('<tr') == 4 # 14->17
|
|
assert 'style="height: 300%; top: 0%;"' in resp.text
|
|
|
|
# check month view
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert resp.text.count('height:') == 3
|
|
assert resp.text.count('height:400.0%') == 1
|
|
assert resp.text.count('height:700.0%') == 1
|
|
assert resp.text.count('height:300.0%') == 1
|
|
|
|
|
|
@freezegun.freeze_time('2022-11-15 14:00')
|
|
def test_agenda_calendar_views_date_time_period(app, admin_user):
|
|
agenda = Agenda.objects.create(label='New Example', kind='meetings')
|
|
desk = Desk.objects.create(agenda=agenda, label='New Desk')
|
|
MeetingType.objects.create(agenda=agenda, label='Bar', duration=30)
|
|
today = datetime.date.today()
|
|
TimePeriod.objects.create(
|
|
desk=desk,
|
|
date=today,
|
|
start_time=datetime.time(10, 0),
|
|
end_time=datetime.time(14, 0),
|
|
)
|
|
login(app)
|
|
|
|
# check day view
|
|
resp = app.get('/manage/agendas/%s/day/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert resp.text.count('<tr') == 5 # 10->14
|
|
assert 'style="height: 400%; top: 0%;"' in resp.text
|
|
|
|
resp = app.get('/manage/agendas/%s/day/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day + 7))
|
|
assert 'No opening hours this day.' in resp.text
|
|
|
|
# check week view
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert resp.text.count('height:400.0%') == 1
|
|
|
|
# check month view
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert resp.text.count('height:400.0%') == 1
|
|
|
|
# check month boundaries
|
|
TimePeriod.objects.create(
|
|
desk=desk,
|
|
date=today.replace(day=1),
|
|
start_time=datetime.time(10, 0),
|
|
end_time=datetime.time(14, 0),
|
|
)
|
|
TimePeriod.objects.create(
|
|
desk=desk,
|
|
date=today.replace(day=30),
|
|
start_time=datetime.time(10, 0),
|
|
end_time=datetime.time(14, 0),
|
|
)
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert resp.text.count('height:400.0%') == 3
|
|
|
|
TimePeriod.objects.create(
|
|
desk=desk,
|
|
date=today.replace(day=31, month=10),
|
|
start_time=datetime.time(10, 0),
|
|
end_time=datetime.time(14, 0),
|
|
)
|
|
TimePeriod.objects.create(
|
|
desk=desk,
|
|
date=today.replace(day=1, month=12),
|
|
start_time=datetime.time(10, 0),
|
|
end_time=datetime.time(14, 0),
|
|
)
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert resp.text.count('height:400.0%') == 3
|
|
|
|
# check week boundaries
|
|
TimePeriod.objects.create(
|
|
desk=desk,
|
|
date=today.replace(day=14),
|
|
start_time=datetime.time(10, 0),
|
|
end_time=datetime.time(14, 0),
|
|
)
|
|
TimePeriod.objects.create(
|
|
desk=desk,
|
|
date=today.replace(day=20),
|
|
start_time=datetime.time(10, 0),
|
|
end_time=datetime.time(14, 0),
|
|
)
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert resp.text.count('height:400.0%') == 3
|
|
|
|
TimePeriod.objects.create(
|
|
desk=desk,
|
|
date=today.replace(day=13),
|
|
start_time=datetime.time(10, 0),
|
|
end_time=datetime.time(14, 0),
|
|
)
|
|
TimePeriod.objects.create(
|
|
desk=desk,
|
|
date=today.replace(day=21),
|
|
start_time=datetime.time(10, 0),
|
|
end_time=datetime.time(14, 0),
|
|
)
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert resp.text.count('height:400.0%') == 3
|
|
|
|
|
|
@freezegun.freeze_time('2022-11-15 14:00')
|
|
@pytest.mark.parametrize('kind', ['meetings', 'virtual'])
|
|
def test_agenda_date_time_period_hide_weekend(app, admin_user, kind):
|
|
today = datetime.date.today() # Tuesday
|
|
if kind == 'meetings':
|
|
agenda = Agenda.objects.create(label='Passeports', kind='meetings')
|
|
desk = Desk.objects.create(agenda=agenda, label='Desk A')
|
|
else:
|
|
agenda = Agenda.objects.create(label='Virtual', kind='virtual')
|
|
real_agenda = Agenda.objects.create(label='Real 1', kind='meetings')
|
|
VirtualMember.objects.create(virtual_agenda=agenda, real_agenda=real_agenda)
|
|
desk = Desk.objects.create(agenda=real_agenda, label='New Desk')
|
|
TimePeriod.objects.create(
|
|
desk=desk, date=today, start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
|
|
)
|
|
|
|
login(app)
|
|
# check month view
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert 'Sunday' not in resp.text
|
|
assert 'Saturday' not in resp.text
|
|
|
|
# check week view
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert 'Sunday' not in resp.text
|
|
assert 'Saturday' not in resp.text
|
|
|
|
TimePeriod.objects.create(
|
|
desk=desk, date=today.replace(day=19), start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
|
|
) # Saturday
|
|
|
|
# check month view
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert 'Sunday' not in resp.text
|
|
assert 'Saturday' in resp.text
|
|
|
|
# check week view
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert 'Sunday' not in resp.text
|
|
assert 'Saturday' in resp.text
|
|
|
|
TimePeriod.objects.create(
|
|
desk=desk, date=today.replace(day=20), start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
|
|
) # Sunday
|
|
|
|
# check month view
|
|
resp = app.get('/manage/agendas/%s/month/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert 'Sunday' in resp.text
|
|
assert 'Saturday' in resp.text
|
|
|
|
# check week view
|
|
resp = app.get('/manage/agendas/%s/week/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
|
|
assert 'Sunday' in resp.text
|
|
assert 'Saturday' in resp.text
|