# -*- coding: utf-8 -*- from __future__ import unicode_literals import json from django.contrib.auth.models import User, Group from django.utils.timezone import make_aware, now, localtime import datetime import mock import pytest import requests from webtest import Upload from chrono.wsgi import application from chrono.agendas.models import (Agenda, Event, Booking, MeetingType, TimePeriod, Desk, TimePeriodException) from chrono.manager.utils import export_site pytestmark = pytest.mark.django_db @pytest.fixture def simple_user(): try: user = User.objects.get(username='user') except User.DoesNotExist: user = User.objects.create_user('user', password='user') return user @pytest.fixture def manager_user(): try: user = User.objects.get(username='manager') except User.DoesNotExist: user = User.objects.create_user('manager', password='manager') group, created = Group.objects.get_or_create(name='Managers') if created: group.save() user.groups = [group] return user @pytest.fixture def admin_user(): try: user = User.objects.get(username='admin') except User.DoesNotExist: user = User.objects.create_superuser('admin', email=None, password='admin') return user @pytest.fixture def api_user(): try: user = User.objects.get(username='api-user') except User.DoesNotExist: user = User.objects.create(username='john.doe', first_name=u'John', last_name=u'Doe', email='john.doe@example.net') user.set_password('password') user.save() return user def login(app, username='admin', password='admin'): login_page = app.get('/login/') login_form = login_page.forms[0] login_form['username'] = username login_form['password'] = password resp = login_form.submit() assert resp.status_int == 302 return app def 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') assert app.get('/manage/', status=403) 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=u'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 = manager_user.groups.all()[0] agenda.view_role = None 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 '

Agendas

' 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.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 def test_view_agendas_as_manager(app, manager_user): agenda = Agenda(label=u'Foo Bar') agenda.view_role = manager_user.groups.all()[0] agenda.save() agenda2 = Agenda(label=u'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' 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 view gives access to the settings page for "events" agenda resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200) # but there's no links to actions assert not '>New Event<' in resp.text assert not '>Options<' in resp.text 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) # check it gives a 404 on unknown agendas resp = app.get('/manage/agendas/%s/settings' % '9999', 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 '

Settings' in resp.text 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') resp = app.get('/manage/', status=200) resp = app.get('/manage/agendas/add/', status=403) def test_options_agenda(app, admin_user): agenda = Agenda(label=u'Foo bar') agenda.save() app = login(app) resp = app.get('/manage/', status=200) resp = resp.click('Foo bar').follow() 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 '

Settings' in resp.text def test_options_agenda_as_manager(app, manager_user): agenda = Agenda(label=u'Foo bar') agenda.view_role = manager_user.groups.all()[0] agenda.save() app = login(app, username='manager', password='manager') resp = app.get('/manage/', status=200) resp = resp.click('Foo bar') assert not 'Settings' in resp.text resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200) # ok for "events" agendas 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/', status=200) resp = resp.click('Foo bar').follow() 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 '

Settings' in resp.text def test_delete_agenda(app, admin_user): agenda = Agenda(label=u'Foo bar') agenda.save() app = login(app) resp = app.get('/manage/', status=200) resp = resp.click('Foo bar').follow() resp = resp.click('Delete') resp = resp.form.submit() assert resp.location.endswith('/manage/') resp = resp.follow() assert not 'Foo bar' in resp.text def test_delete_busy_agenda(app, admin_user): agenda = Agenda(label=u'Foo bar') agenda.save() event = Event(start_datetime=now() + datetime.timedelta(days=10), places=10, agenda=agenda) event.save() app = login(app) resp = app.get('/manage/', status=200) resp = resp.click('Foo bar').follow() 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/', status=200) resp = resp.click('Foo bar').follow() resp = resp.click('Delete') assert 'This cannot be removed' in resp.text booking.cancellation_datetime = now() booking.save() resp = app.get('/manage/', status=200) resp = resp.click('Foo bar').follow() 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=u'Foo bar') agenda.edit_role = manager_user.groups.all()[0] agenda.save() app = login(app, username='manager', password='manager') resp = app.get('/manage/', status=200) resp = resp.click('Foo bar').follow() 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=u'Foo bar', kind='meetings') agenda.save() desk_a = Desk.objects.create(agenda=agenda, label='Desk A') desk_b = 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 = resp.click('Foo bar').follow() resp = resp.click('Settings') 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_event(app, admin_user): agenda = Agenda(label=u'Foo bar') agenda.maximal_booking_delay = 0 agenda.save() app = login(app) resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200) assert "This agenda doesn't have any event yet." in resp.text year = now().year + 1 resp = resp.click('New Event') resp.form['start_datetime'] = '%s-02-15 17:00' % year resp.form['places'] = 10 resp = resp.form.submit() resp = resp.follow() event = Event.objects.get(places=10) assert not "This agenda doesn't have any event yet." in resp.text assert '/manage/events/%s/' % event.id in resp.text assert ('Feb. 15, %s, 5 p.m.' % year) in resp.text assert '10 places' in resp.text resp_datetimes = app.get('/api/agenda/%s/datetimes/' % agenda.id) assert resp_datetimes.json['data'][0]['text'] == 'Feb. 15, %s, 5 p.m.' % year assert resp_datetimes.json['data'][0]['datetime'] == '%s-02-15 17:00:00' % year def test_add_event_on_missing_agenda(app, admin_user): app = login(app) app.get('/manage/agendas/%s/add-event' % '999', status=404) def test_add_event_as_manager(app, manager_user): agenda = Agenda(label=u'Foo bar') agenda.view_role = manager_user.groups.all()[0] agenda.save() app = login(app, username='manager', password='manager') resp = app.get('/manage/agendas/%s/' % agenda.id, status=302) app.get('/manage/agendas/%s/add-event' % agenda.id, status=403) agenda.edit_role = manager_user.groups.all()[0] agenda.save() resp = app.get('/manage/agendas/%s/' % agenda.id).follow() assert '

Settings' in resp.text resp = resp.click('New Event') resp.form['start_datetime'] = '2016-02-15 17:00' resp.form['places'] = 10 resp = resp.form.submit() resp = resp.follow() event = Event.objects.get(places=10) assert not "This agenda doesn't have any event yet." in resp.text assert '/manage/events/%s/' % event.id in resp.text assert 'Feb. 15, 2016, 5 p.m.' in resp.text assert '10 places' in resp.text def test_edit_event(app, admin_user): agenda = Agenda(label=u'Foo bar') agenda.save() event = Event( start_datetime=make_aware(datetime.datetime(2016, 2, 15, 17, 0)), places=20, agenda=agenda) event.save() app = login(app) resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200) resp = resp.click('Feb. 15, 2016, 5 p.m.') assert resp.form['start_datetime'].value == '15/02/2016 17:00' resp.form['start_datetime'] = '2016-02-16 17:00' resp.form['places'] = 20 resp = resp.form.submit() resp = resp.follow() assert '/manage/events/%s/' % event.id in resp.text assert 'Feb. 16, 2016, 5 p.m.' in resp.text assert '20 places' in resp.text def test_edit_missing_event(app, admin_user): app = login(app) app.get('/manage/agendas/999/', status=404) def test_edit_event_as_manager(app, manager_user): agenda = Agenda(label=u'Foo bar') agenda.view_role = manager_user.groups.all()[0] agenda.save() event = Event(start_datetime=make_aware(datetime.datetime(2016, 2, 15, 17, 0)), places=20, agenda=agenda) event.save() app = login(app, username='manager', password='manager') resp = app.get('/manage/events/%s/' % event.id, status=403) agenda.edit_role = manager_user.groups.all()[0] agenda.save() resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200) resp = resp.click('Feb. 15, 2016, 5 p.m.') assert resp.form['start_datetime'].value == '15/02/2016 17:00' resp.form['start_datetime'] = '2016-02-16 17:00' resp.form['places'] = 20 resp = resp.form.submit() resp = resp.follow() assert '/manage/events/%s/' % event.id in resp.text assert 'Feb. 16, 2016, 5 p.m.' in resp.text assert '20 places' in resp.text def test_booked_places(app, admin_user): agenda = Agenda(label=u'Foo bar') agenda.save() event = Event(start_datetime=make_aware(datetime.datetime(2016, 2, 15, 17, 0)), places=10, agenda=agenda) event.save() Booking(event=event).save() Booking(event=event).save() app = login(app) resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200) assert '10 places' in resp.text assert '2 booked places' in resp.text def test_event_classes(app, admin_user): agenda = Agenda(label=u'Foo bar') agenda.save() event = Event(start_datetime=make_aware(datetime.datetime(2016, 2, 15, 17, 0)), places=10, agenda=agenda) event.save() for i in range(2): Booking(event=event).save() app = login(app) resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200) assert not 'full' in resp.text assert not 'overbooking' in resp.text for i in range(8): Booking(event=event).save() resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200) assert 'full' in resp.text assert not 'overbooking' in resp.text Booking(event=event).save() resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200) assert 'full' in resp.text assert 'overbooking' in resp.text def test_delete_event(app, admin_user): agenda = Agenda(label=u'Foo bar') agenda.save() event = Event(start_datetime=make_aware(datetime.datetime(2016, 2, 15, 17, 0)), places=10, agenda=agenda) event.save() app = login(app) resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200) resp = resp.click(href=r'/manage/events/%s/$' % event.id) resp = resp.click('Delete') resp = resp.form.submit() assert resp.location.endswith('/manage/agendas/%s/settings' % agenda.id) assert Event.objects.count() == 0 def test_delete_busy_event(app, admin_user): agenda = Agenda(label=u'Foo bar') agenda.save() 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, status=200) resp = resp.click(href=r'/manage/events/%s/$' % event.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, status=200) resp = resp.click(href=r'/manage/events/%s/$' % event.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, status=200) resp = resp.click(href=r'/manage/events/%s/$' % event.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_event_as_manager(app, manager_user): agenda = Agenda(label=u'Foo bar') agenda.edit_role = manager_user.groups.all()[0] agenda.save() event = Event(start_datetime=make_aware(datetime.datetime(2016, 2, 15, 17, 0)), places=10, agenda=agenda) event.save() app = login(app, username='manager', password='manager') resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200) resp = resp.click(href=r'/manage/events/%s/$' % event.id) resp = resp.click('Delete') resp = resp.form.submit() assert resp.location.endswith('/manage/agendas/%s/settings' % agenda.id) assert Event.objects.count() == 0 def test_import_events(app, admin_user): agenda = Agenda(label=u'Foo bar') agenda.save() app = login(app) resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200) resp = resp.click('Import Events') sample_csv_resp = resp.click('Download sample file') assert sample_csv_resp.content_type == 'text/csv' assert sample_csv_resp.text.startswith('date,time,') resp.form['events_csv_file'] = Upload('t.csv', sample_csv_resp.content, 'text/csv') resp = resp.form.submit(status=302) assert Event.objects.count() == 0 resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200) resp.form['events_csv_file'] = Upload('t.csv', b'xx', 'text/csv') resp = resp.form.submit(status=200) assert 'Invalid file format.' in resp.text resp.form['events_csv_file'] = Upload('t.csv', b'xxxx\0\0xxxx', 'text/csv') resp = resp.form.submit(status=200) assert 'Invalid file format.' in resp.text resp.form['events_csv_file'] = Upload('t.csv', b'2016-14-16,18:00', 'text/csv') resp = resp.form.submit(status=200) assert 'Invalid file format.' in resp.text resp.form['events_csv_file'] = Upload('t.csv', b'2016-14-16,18:00,10', 'text/csv') resp = resp.form.submit(status=200) assert 'Invalid file format. (date/time format' in resp.text resp.form['events_csv_file'] = Upload('t.csv', b'2016-09-16,18:00,blah', 'text/csv') resp = resp.form.submit(status=200) assert 'Invalid file format. (number of places,' in resp.text resp.form['events_csv_file'] = Upload('t.csv', b'2016-09-16,18:00,10,blah', 'text/csv') resp = resp.form.submit(status=200) assert 'Invalid file format. (number of places in waiting list,' in resp.text resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200) resp.form['events_csv_file'] = Upload('t.csv', b'2016-09-16,18:00,10', 'text/csv') resp = resp.form.submit(status=302) assert Event.objects.count() == 1 assert Event.objects.all()[0].start_datetime == make_aware(datetime.datetime(2016, 9, 16, 18, 0)) assert Event.objects.all()[0].places == 10 Event.objects.all().delete() resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200) resp.form['events_csv_file'] = Upload('t.csv', b'2016-09-16,18:00,10,5', 'text/csv') resp = resp.form.submit(status=302) assert Event.objects.count() == 1 assert Event.objects.all()[0].start_datetime == make_aware(datetime.datetime(2016, 9, 16, 18, 0)) assert Event.objects.all()[0].places == 10 assert Event.objects.all()[0].waiting_list_places == 5 Event.objects.all().delete() resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200) resp.form['events_csv_file'] = Upload('t.csv', u'2016-09-16,18:00,10,5,éléphant'.encode('utf-8'), 'text/csv') resp = resp.form.submit(status=302) assert Event.objects.count() == 1 assert Event.objects.all()[0].start_datetime == make_aware(datetime.datetime(2016, 9, 16, 18, 0)) assert Event.objects.all()[0].places == 10 assert Event.objects.all()[0].waiting_list_places == 5 assert Event.objects.all()[0].label == u'éléphant' Event.objects.all().delete() resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200) resp.form['events_csv_file'] = Upload('t.csv', b'date,time,etc.\n' b'2016-09-16,18:00,10,5,bla bla bla\n' b'\n' b'2016-09-19,18:00,10', 'text/csv') resp = resp.form.submit(status=302) assert Event.objects.count() == 2 Event.objects.all().delete() 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 '

Settings' in resp.text assert 'Meeting Types' in resp.text agenda = Agenda.objects.get(label='Foo bar') assert agenda.kind == 'meetings' def test_meetings_agenda_add_meeting_type(app, admin_user): agenda = Agenda(label=u'Foo bar', kind='meetings') agenda.save() app = login(app) resp = app.get('/manage/agendas/%s/' % agenda.id).follow() resp = resp.click('Settings') assert "This agenda doesn't have any meeting type yet." in resp.text resp = resp.click('New Meeting Type') resp.form['label'] = 'Blah' resp.form['duration'] = '60' resp = resp.form.submit() assert MeetingType.objects.get(agenda=agenda).label == 'Blah' assert MeetingType.objects.get(agenda=agenda).duration == 60 resp = resp.follow() assert 'Blah' in resp.text # and edit resp = resp.click('Blah') resp.form['duration'] = '30' resp = resp.form.submit() assert MeetingType.objects.get(agenda=agenda).duration == 30 def test_meetings_agenda_delete_meeting_type(app, admin_user): agenda = Agenda(label=u'Foo bar', kind='meetings') agenda.save() meeting_type = MeetingType(agenda=agenda, label='Blah') meeting_type.save() app = login(app) resp = app.get('/manage/agendas/%s/' % agenda.id).follow() resp = resp.click('Settings') resp = resp.click('Blah') resp = resp.click('Delete') resp = resp.form.submit() assert resp.location.endswith('/manage/agendas/%s/settings' % agenda.id) assert MeetingType.objects.count() == 0 def test_meetings_agenda_add_time_period(app, admin_user): agenda = Agenda(label=u'Foo bar', kind='meetings') agenda.save() desk = Desk.objects.create(agenda=agenda, label='Desk A') MeetingType(agenda=agenda, label='Blah').save() app = login(app) resp = app.get('/manage/agendas/%s/' % agenda.id, status=302).follow() resp = resp.click('Settings') resp = resp.click('Add a time period') resp.form['weekdays-2'].checked = True resp.form['start_time'] = '10:00' resp.form['end_time'] = '17:00' resp = resp.form.submit() assert TimePeriod.objects.get(desk=desk).weekday == 2 assert TimePeriod.objects.get(desk=desk).start_time.hour == 10 assert TimePeriod.objects.get(desk=desk).start_time.minute == 0 assert TimePeriod.objects.get(desk=desk).end_time.hour == 17 assert TimePeriod.objects.get(desk=desk).end_time.minute == 0 resp = resp.follow() # add a second time period resp = resp.click('Add a time period', index=0) resp.form['weekdays-0'].checked = True resp.form['start_time'] = '10:00' resp.form['end_time'] = '13:00' resp = resp.form.submit() resp = resp.follow() assert u'Monday / 10 a.m. → 1 p.m.' in resp.text assert u'Wednesday / 10 a.m. → 5 p.m.' in resp.text assert resp.text.index('Monday') < resp.text.index('Wednesday') # and edit resp = resp.click(u'Wednesday / 10 a.m. → 5 p.m.') assert 'Edit Time Period' in resp.text resp.form['start_time'] = '9:00' resp = resp.form.submit() resp = resp.follow() assert TimePeriod.objects.get(desk=desk, weekday=2).start_time.hour == 9 # and add same time periods on multiple days resp = resp.click('Add a time period', index=0) resp.form['weekdays-4'].checked = True resp.form['weekdays-5'].checked = True resp.form['start_time'] = '10:00' resp.form['end_time'] = '13:00' resp = resp.form.submit() assert TimePeriod.objects.filter(desk=desk).count() == 4 def test_meetings_agenda_delete_time_period(app, admin_user): agenda = Agenda(label=u'Foo bar', kind='meetings') agenda.save() MeetingType(agenda=agenda, label='Blah').save() desk = Desk.objects.create(agenda=agenda, label='Desk A') time_period = TimePeriod(desk=desk, weekday=2, start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)) time_period.save() app = login(app) resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200) resp = resp.click('Wednesday') resp = resp.click('Delete') resp = resp.form.submit() assert resp.location.endswith('/manage/agendas/%s/settings' % agenda.id) assert TimePeriod.objects.count() == 0 def test_meetings_agenda_add_time_period_on_missing_desk(app, admin_user): app = login(app) agenda = Agenda(label=u'Foo bar', kind='meetings') agenda.save() MeetingType(agenda=agenda, label='Blah').save() app.get('/manage/agendas/1/desk/777/add-time-period', status=404) def test_meetings_agenda_add_time_period_as_manager(app, manager_user): agenda = Agenda(label='Foo bar', kind='meetings') agenda.view_role = manager_user.groups.all()[0] agenda.save() desk = Desk.objects.create(agenda=agenda, label='Desk A') app = login(app, username='manager', password='manager') resp = app.get('/manage/agendas/%d/' % agenda.id) assert not 'Settings' in resp.text resp = app.get('/manage/agendas/%d/settings' % agenda.id, status=403) MeetingType(agenda=agenda, label='Blah').save() app.get('/manage/agendas/%d/desk/%d/add-time-period' % (agenda.id, desk.id), status=403) time_period = TimePeriod(desk=desk, weekday=0, start_time=datetime.time(9, 0), end_time=datetime.time(12, 0)) time_period.save() resp = app.get('/manage/agendas/%d/' % agenda.id) app.get('/manage/timeperiods/%d/edit' % time_period.id, status=403) app.get('/manage/timeperiods/%d/delete' % time_period.id, status=403) # grant edit right to manager agenda.edit_role = manager_user.groups.all()[0] agenda.save() resp = app.get('/manage/agendas/%d/' % agenda.id).follow() resp = resp.click('Settings') assert 'Add a time period' in resp.text assert '/manage/timeperiods/%s/edit' % time_period.id in resp.text assert '/manage/timeperiods/%s/delete' % time_period.id in resp.text app.get('/manage/agendas/%d/desk/%d/add-time-period' % (agenda.id, desk.id), status=200) app.get('/manage/timeperiods/%d/edit' % time_period.id, status=200) def test_meetings_agenda_add_desk(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() assert Desk.objects.count() == 1 assert str(Desk.objects.first()) == 'Desk 1' agenda = Agenda.objects.get(slug='foo-bar') MeetingType(agenda=agenda, label='Blah').save() resp = app.get('/manage/agendas/%s/' % agenda.id).follow() resp = resp.click('Settings') resp = resp.click('New Desk') resp.form['label'] = 'Desk A' resp = resp.form.submit().follow() assert Desk.objects.count() == 2 resp = resp.click('New Desk') resp.form['label'] = 'Desk A' resp = resp.form.submit().follow() assert Desk.objects.count() == 3 assert Desk.objects.filter(slug='desk-a-1').count() == 1 assert 'Desk A' in resp.text resp = resp.click('Desk A', index=1) resp.form['label'] = 'Desk B' resp = resp.form.submit().follow() assert 'Desk A' in resp.text assert 'Desk B' in resp.text def test_meetings_agenda_delete_desk(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() assert Desk.objects.count() == 1 agenda = Agenda.objects.get(slug='foo-bar') MeetingType(agenda=agenda, label='Blah').save() resp = app.get('/manage/agendas/%s/' % agenda.id).follow() resp = resp.click('Settings') resp = resp.click('New Desk') resp.form['label'] = 'Desk A' resp = resp.form.submit().follow() assert Desk.objects.count() == 2 resp = resp.click('Desk A', index=0) resp = resp.click('Delete') resp = resp.form.submit() assert resp.location.endswith('/manage/agendas/%s/settings' % agenda.id) assert Desk.objects.count() == 1 def test_meetings_agenda_add_time_period_exception(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().follow() agenda = Agenda.objects.first() resp = resp.click('New Meeting Type') resp.form['label'] = 'Blah' resp.form['duration'] = '60' resp = resp.form.submit().follow() # adding a new time period resp = resp.click('Add a time period') resp.form['weekdays-2'].checked = True resp.form['start_time'] = '10:00' resp.form['end_time'] = '17:00' resp = resp.form.submit().follow() resp = resp.click('Add a time period exception') today = datetime.datetime.today().replace(hour=0, minute=0, second=0, microsecond=0) tomorrow = make_aware(today + datetime.timedelta(days=1)) dt_format = '%Y-%m-%d %H:%M' resp.form['label'] = 'Exception 1' resp.form['start_datetime'] = tomorrow.replace(hour=8).strftime(dt_format) resp.form['end_datetime'] = tomorrow.replace(hour=16).strftime(dt_format) resp = resp.form.submit().follow() assert TimePeriodException.objects.count() == 1 time_period_exception = TimePeriodException.objects.first() assert localtime(time_period_exception.start_datetime).strftime(dt_format) == tomorrow.replace(hour=8).strftime(dt_format) assert localtime(time_period_exception.end_datetime).strftime(dt_format) == tomorrow.replace(hour=16).strftime(dt_format) # add an exception beyond 2 weeks and make sure it isn't listed resp = resp.click('Add a time period exception', index=1) future = tomorrow + datetime.timedelta(days=15) resp.form['label'] = 'Exception 2' resp.form['start_datetime'] = future.replace(hour=0, minute=0).strftime(dt_format) resp.form['end_datetime'] = future.replace(hour=16).strftime(dt_format) resp = resp.form.submit().follow() assert TimePeriodException.objects.count() == 2 assert 'Exception 1' in resp.text assert 'Exception 2' not in resp.text resp = resp.click(href="/manage/time-period-exceptions/%d/exception-list" % agenda.desk_set.first().pk) assert 'Exception 1' in resp.text assert 'Exception 2' in resp.text def test_meetings_agenda_add_time_period_exception_when_booking_exists(app, admin_user): agenda = Agenda.objects.create(label='Foo bar', kind='meetings') desk = Desk.objects.create(agenda=agenda, label='Desk A') MeetingType(agenda=agenda, label='Blah').save() TimePeriod.objects.create(weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)) event = Event.objects.create(agenda=agenda, places=1, desk=desk, start_datetime=make_aware(datetime.datetime(2017, 5, 22, 10, 30))) Booking.objects.create(event=event) login(app) resp = app.get('/manage/agendas/%d/' % agenda.pk).follow() resp = resp.click('Settings') resp = resp.click('Add a time period exception') resp = resp.form.submit() # submit empty form # fields should be marked with errors assert resp.text.count('This field is required.') == 2 # try again with data in fields resp.form['start_datetime'] = '2017-05-22 08:00' resp.form['end_datetime'] = '2017-05-26 17:30' resp = resp.form.submit() assert 'One or several bookings exists within this time slot.' in resp.text assert TimePeriodException.objects.count() == 0 # check it's possible to add an exception on another desk desk = Desk.objects.create(agenda=agenda, label='Desk B') TimePeriod.objects.create(weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)) resp = app.get('/manage/agendas/%d/' % agenda.pk).follow() resp = resp.click('Settings') resp = resp.click('Add a time period exception', href='desk/%s/' % desk.id) resp.form['start_datetime'] = '2017-05-22 08:00' resp.form['end_datetime'] = '2017-05-26 17:30' resp = resp.form.submit() assert TimePeriodException.objects.count() == 1 def test_meetings_agenda_add_time_period_exception_when_cancelled_booking_exists(app, admin_user): agenda = Agenda.objects.create(label='Foo bar', kind='meetings') desk = Desk.objects.create(agenda=agenda, label='Desk A') MeetingType(agenda=agenda, label='Blah').save() TimePeriod.objects.create(weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)) event = Event.objects.create(agenda=agenda, places=1, start_datetime=make_aware(datetime.datetime(2017, 5, 22, 10, 30))) Booking.objects.create(event=event, cancellation_datetime=make_aware(datetime.datetime(2017, 5, 20, 10, 30))) login(app) resp = app.get('/manage/agendas/%d/' % agenda.pk).follow() resp = resp.click('Settings') resp = resp.click('Add a time period exception') resp.form['start_datetime'] = '2017-05-22 08:00' resp.form['end_datetime'] = '2017-05-26 17:30' resp = resp.form.submit() assert 'One or several bookings exists within this time slot.' not in resp.text assert TimePeriodException.objects.count() == 1 def test_meetings_agenda_add_invalid_time_period_exception(app, admin_user): agenda = Agenda.objects.create(label='Foo bar', kind='meetings') desk = Desk.objects.create(agenda=agenda, label='Desk A') MeetingType(agenda=agenda, label='Blah').save() TimePeriod.objects.create(weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)) login(app) resp = app.get('/manage/agendas/%d/' % agenda.pk).follow() resp = resp.click('Settings') resp = resp.click('Add a time period exception') resp.form['start_datetime'] = '2017-05-26 17:30' resp.form['end_datetime'] = '2017-05-22 08:00' resp = resp.form.submit() assert 'End datetime must be greater than start datetime.' in resp.text def test_meetings_agenda_delete_time_period_exception(app, admin_user): agenda = Agenda.objects.create(label='Foo bar', kind='meetings') desk = Desk.objects.create(agenda=agenda, label='Desk A') MeetingType(agenda=agenda, label='Blah').save() TimePeriod.objects.create(weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)) login(app) resp = app.get('/manage/agendas/%d/' % agenda.pk).follow() resp = resp.click('Settings') resp = resp.click('Add a time period exception') today = datetime.datetime.today().replace(hour=0, minute=0, second=0, microsecond=0) tomorrow = make_aware(today + datetime.timedelta(days=15)) dt_format = '%Y-%m-%d %H:%M' resp.form['label'] = 'Exception 1' resp.form['start_datetime'] = tomorrow.replace(hour=8).strftime(dt_format) resp.form['end_datetime'] = tomorrow.replace(hour=16).strftime(dt_format) resp = resp.form.submit().follow() assert TimePeriodException.objects.count() == 1 time_period_exception = TimePeriodException.objects.first() assert localtime(time_period_exception.start_datetime).strftime(dt_format) == tomorrow.replace(hour=8).strftime(dt_format) assert localtime(time_period_exception.end_datetime).strftime(dt_format) == tomorrow.replace(hour=16).strftime(dt_format) resp = resp.click(href='/manage/time-period-exceptions/%d/edit' % time_period_exception.id) resp = resp.click('Delete') resp = resp.form.submit() assert TimePeriodException.objects.count() == 0 def test_agenda_import_time_period_exception_from_ics(app, admin_user): agenda = Agenda.objects.create(label='Example', kind='meetings') desk = Desk.objects.create(agenda=agenda, label='Test Desk') MeetingType(agenda=agenda, label='Foo').save() login(app) resp = app.get('/manage/agendas/%d/' % agenda.pk).follow() resp = resp.click('Settings') assert 'Import exceptions from .ics' not in resp.text TimePeriod.objects.create(weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)) resp = app.get('/manage/agendas/%d/' % agenda.pk).follow() resp = resp.click('Settings') assert 'Import exceptions from .ics' in resp.text resp = resp.click('upload') assert "You can upload a file or specify an address to a remote calendar." in resp resp = resp.form.submit(status=302) resp = app.get('/manage/agendas/%d/' % agenda.pk).follow() resp = resp.click('Settings') resp = resp.click('upload') resp.form['ics_file'] = Upload('exceptions.ics', b'invalid content', 'text/calendar') resp = resp.form.submit(status=200) assert 'File format is invalid' in resp.text ics_with_no_start_date = b"""BEGIN:VCALENDAR VERSION:2.0 PRODID:-//foo.bar//EN BEGIN:VEVENT DTEND:20180101 SUMMARY:New Year's Eve END:VEVENT END:VCALENDAR""" resp.form['ics_file'] = Upload('exceptions.ics', ics_with_no_start_date, 'text/calendar') resp = resp.form.submit(status=200) assert 'Event "New Year's Eve" has no start date.' in resp.text ics_with_no_events = b"""BEGIN:VCALENDAR VERSION:2.0 PRODID:-//foo.bar//EN END:VCALENDAR""" resp.form['ics_file'] = Upload('exceptions.ics', ics_with_no_events, 'text/calendar') resp = resp.form.submit(status=200) assert "The file doesn't contain any events." in resp.text ics_with_exceptions = b"""BEGIN:VCALENDAR VERSION:2.0 PRODID:-//foo.bar//EN BEGIN:VEVENT DTSTART:20180101 DTEND:20180101 SUMMARY:New Year's Eve END:VEVENT END:VCALENDAR""" resp = app.get('/manage/agendas/%d/' % agenda.pk).follow() resp = resp.click('Settings') resp = resp.click('upload') resp.form['ics_file'] = Upload('exceptions.ics', ics_with_exceptions, 'text/calendar') resp = resp.form.submit(status=302) assert TimePeriodException.objects.filter(desk=desk).count() == 1 resp = resp.follow() assert 'An exception has been imported.' in resp.text @pytest.mark.freeze_time('2017-12-01') def test_agenda_import_time_period_exception_from_ics_recurrent(app, admin_user): agenda = Agenda.objects.create(label='Example', kind='meetings') desk = Desk.objects.create(agenda=agenda, label='Test Desk') MeetingType(agenda=agenda, label='Foo').save() TimePeriod.objects.create(weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)) login(app) resp = app.get('/manage/agendas/%d/' % agenda.pk).follow() resp = resp.click('Settings') resp = resp.click('upload') ics_with_recurrent_exceptions = b"""BEGIN:VCALENDAR VERSION:2.0 PRODID:-//foo.bar//EN BEGIN:VEVENT DTSTART:20180101 DTEND:20180101 SUMMARY:New Year's Eve RRULE:FREQ=YEARLY END:VEVENT END:VCALENDAR""" resp.form['ics_file'] = Upload('exceptions.ics', ics_with_recurrent_exceptions, 'text/calendar') resp = resp.form.submit(status=302).follow() assert TimePeriodException.objects.filter(desk=desk).count() == 2 @mock.patch('chrono.agendas.models.requests.get') def test_agenda_import_time_period_exception_with_remote_ics(mocked_get, app, admin_user): agenda = Agenda.objects.create(label='New Example', kind='meetings') desk = Desk.objects.create(agenda=agenda, label='New Desk') MeetingType(agenda=agenda, label='Bar').save() login(app) resp = app.get('/manage/agendas/%d/' % agenda.pk).follow() resp = resp.click('Settings') assert 'Import exceptions from .ics' not in resp.text TimePeriod.objects.create(weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)) resp = app.get('/manage/agendas/%d/' % agenda.pk).follow() resp = resp.click('Settings') resp = resp.click('upload') assert 'ics_file' in resp.form.fields assert 'ics_url' in resp.form.fields resp.form['ics_url'] = 'http://example.com/foo.ics' mocked_response = mock.Mock() mocked_response.text = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//foo.bar//EN BEGIN:VEVENT UID:random-event-id DTSTART:20180101 DTEND:20180101 SUMMARY:New Year's Eve END:VEVENT END:VCALENDAR""" mocked_get.return_value = mocked_response resp = resp.form.submit(status=302) assert TimePeriodException.objects.filter(desk=desk).count() == 1 exception = TimePeriodException.objects.get(desk=desk) assert exception.external_id == 'random-event-id' resp = app.get('/manage/agendas/%d/' % agenda.pk).follow() resp = resp.click('Settings') resp = resp.click('upload') resp.form['ics_url'] = '' resp = resp.form.submit(status=302) assert not TimePeriodException.objects.filter(desk=desk, external_id='desk-%s:random-event-id' % desk.id).exists() @mock.patch('chrono.agendas.models.requests.get') def test_agenda_import_time_period_exception_with_remote_ics_no_events(mocked_get, app, admin_user): agenda = Agenda.objects.create(label='New Example', kind='meetings') desk = Desk.objects.create(agenda=agenda, label='New Desk') MeetingType(agenda=agenda, label='Bar').save() login(app) resp = app.get('/manage/agendas/%d/' % agenda.pk).follow() resp = resp.click('Settings') assert 'Import exceptions from .ics' not in resp.text TimePeriod.objects.create(weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)) resp = app.get('/manage/agendas/%d/' % agenda.pk).follow() resp = resp.click('Settings') resp = resp.click('upload') resp.form['ics_url'] = 'http://example.com/foo.ics' mocked_response = mock.Mock() mocked_response.text = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//foo.bar//EN BEGIN:VEVENT UID:random-event-id DTSTART:20180101 DTEND:20180101 SUMMARY:New Year's Eve END:VEVENT END:VCALENDAR""" mocked_get.return_value = mocked_response resp = resp.form.submit(status=302) assert TimePeriodException.objects.filter(desk=desk).count() == 1 exception = TimePeriodException.objects.get(desk=desk) assert exception.external_id == 'random-event-id' mocked_response.text = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//foo.bar//EN END:VCALENDAR""" resp = app.get('/manage/agendas/%d/' % agenda.pk).follow() resp = resp.click('Settings') resp = resp.click('upload') resp = resp.form.submit(status=302) assert not TimePeriodException.objects.filter(desk=desk, external_id='random-event-id').exists() @mock.patch('chrono.agendas.models.requests.get') def test_agenda_update_time_period_exception_from_remote_ics(mocked_get, app, admin_user): agenda = Agenda.objects.create(label='New Example', kind='meetings') desk = Desk.objects.create(agenda=agenda, label='New Desk') MeetingType(agenda=agenda, label='Bar').save() login(app) resp = app.get('/manage/agendas/%d/' % agenda.pk).follow() resp = resp.click('Settings') assert 'Import exceptions from .ics' not in resp.text TimePeriod.objects.create(weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)) resp = app.get('/manage/agendas/%d/' % agenda.pk).follow() resp = resp.click('Settings') resp = resp.click('upload') resp.form['ics_url'] = 'http://example.com/foo.ics' mocked_response = mock.Mock() mocked_response.text = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//foo.bar//EN BEGIN:VEVENT UID:first-eventrandom-event-id DTSTART:20180101 DTEND:20180101 SUMMARY:First test event END:VEVENT BEGIN:VEVENT UID:second-eventrandom-event-id DTSTART:20190101 DTEND:20190101 SUMMARY:Second test event END:VEVENT END:VCALENDAR""" mocked_get.return_value = mocked_response resp = resp.form.submit(status=302) assert TimePeriodException.objects.filter(desk=desk).count() == 2 resp = app.get('/manage/agendas/%d/' % agenda.pk).follow() resp = resp.click('Settings') resp = resp.click('upload') resp.form['ics_url'] = 'http://example.com/foo.ics' mocked_response.text = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//foo.bar//EN BEGIN:VEVENT UID:secord-eventrandom-event-id DTSTART:20190101 DTEND:20190101 SUMMARY:Second test event END:VEVENT END:VCALENDAR""" mocked_get.return_value = mocked_response resp = resp.form.submit(status=302) assert TimePeriodException.objects.filter(desk=desk).count() == 1 @mock.patch('chrono.agendas.models.requests.get') def test_agenda_import_time_period_exception_from_remote_ics_with_connection_error(mocked_get, app, admin_user): agenda = Agenda.objects.create(label='New Example', kind='meetings') desk = Desk.objects.create(agenda=agenda, label='New Desk') MeetingType(agenda=agenda, label='Bar').save() login(app) resp = app.get('/manage/agendas/%d/' % agenda.pk).follow() resp = resp.click('Settings') assert 'Import exceptions from .ics' not in resp.text TimePeriod.objects.create(weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)) resp = app.get('/manage/agendas/%d/' % agenda.pk).follow() resp = resp.click('Settings') resp = resp.click('upload') assert 'ics_file' in resp.form.fields assert 'ics_url' in resp.form.fields resp.form['ics_url'] = 'http://example.com/foo.ics' mocked_response = mock.Mock() mocked_get.return_value = mocked_response def mocked_requests_connection_error(*args, **kwargs): raise requests.exceptions.ConnectionError('unreachable') mocked_get.side_effect = mocked_requests_connection_error resp = resp.form.submit(status=200) assert 'Failed to retrieve remote calendar (unreachable).' in resp.text @mock.patch('chrono.agendas.models.requests.get') def test_agenda_import_time_period_exception_from_forbidden_remote_ics(mocked_get, app, admin_user): agenda = Agenda.objects.create(label='New Example', kind='meetings') desk = Desk.objects.create(agenda=agenda, label='New Desk') MeetingType(agenda=agenda, label='Bar').save() login(app) resp = app.get('/manage/agendas/%d/' % agenda.pk).follow() resp = resp.click('Settings') assert 'Import exceptions from .ics' not in resp.text TimePeriod.objects.create(weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)) resp = app.get('/manage/agendas/%d/' % agenda.pk).follow() resp = resp.click('Settings') resp = resp.click('upload') resp.form['ics_url'] = 'http://example.com/foo.ics' mocked_response = mock.Mock() mocked_response.status_code = 403 mocked_get.return_value = mocked_response def mocked_requests_http_forbidden_error(*args, **kwargs): raise requests.exceptions.HTTPError(response=mocked_response) mocked_get.side_effect = mocked_requests_http_forbidden_error resp = resp.form.submit(status=200) assert 'Failed to retrieve remote calendar (HTTP error 403).' in resp.text @mock.patch('chrono.agendas.models.requests.get') def test_agenda_import_time_period_exception_from_remote_ics_with_ssl_error(mocked_get, app, admin_user): agenda = Agenda.objects.create(label='New Example', kind='meetings') desk = Desk.objects.create(agenda=agenda, label='New Desk') MeetingType(agenda=agenda, label='Bar').save() login(app) resp = app.get('/manage/agendas/%d/' % agenda.pk).follow() resp = resp.click('Settings') assert 'Import exceptions from .ics' not in resp.text TimePeriod.objects.create(weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)) resp = app.get('/manage/agendas/%d/' % agenda.pk).follow() resp = resp.click('Settings') resp = resp.click('upload') resp.form['ics_url'] = 'https://example.com/foo.ics' mocked_response = mock.Mock() mocked_get.return_value = mocked_response def mocked_requests_http_ssl_error(*args, **kwargs): raise requests.exceptions.SSLError('SSL error') mocked_get.side_effect = mocked_requests_http_ssl_error resp = resp.form.submit(status=200) assert 'Failed to retrieve remote calendar (SSL error).' in resp.text def test_agenda_day_view(app, admin_user, manager_user, api_user): agenda = Agenda.objects.create(label='New Example', kind='meetings') desk = Desk.objects.create(agenda=agenda, label='New Desk') desk.save() meetingtype = MeetingType(agenda=agenda, label='Bar', duration=30) meetingtype.save() login(app) resp = app.get('/manage/agendas/%s/' % agenda.id, status=302) today = datetime.date.today() assert resp.location.endswith('%s/%s/%s/' % (today.year, today.month, today.day)) resp = resp.follow() 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/' % agenda.id, status=302).follow() assert not 'No opening hours this day.' in resp.text assert not 'div class="booking' in resp.text assert resp.text.count('18 (not included) timeperiod.end_time = datetime.time(18, 30) # end during an hour timeperiod.save() resp = app.get('/manage/agendas/%s/' % agenda.id, status=302).follow() assert resp.text.count('18 (included) # check opening hours cells assert '
11 p.m.' in resp.text def test_agenda_invalid_day_view(app, admin_user, manager_user, api_user): agenda = Agenda.objects.create(label='New Example', kind='meetings') desk = Desk.objects.create(agenda=agenda, label='New Desk') desk.save() meetingtype = MeetingType(agenda=agenda, label='Bar', duration=30) meetingtype.save() login(app) resp = app.get('/manage/agendas/%s/%d/%d/%d/' % (agenda.id, 2018, 11, 31), status=302) assert resp.location.endswith('2018/11/30/') def test_agenda_month_view(app, admin_user, manager_user, api_user): agenda = Agenda.objects.create(label='Passeports', kind='meetings') desk = Desk.objects.create(agenda=agenda, label='Desk A') meetingtype = MeetingType(agenda=agenda, label='passeport', duration=20) meetingtype.save() login(app) resp = app.get('/manage/agendas/%s/' % agenda.id, status=302) resp = resp.follow() assert 'Month view' in resp.text resp = resp.click('Month view') today = datetime.date.today() assert resp.request.url.endswith('%s/%s/' % (today.year, today.month)) assert 'Day view' in resp.text # date view link should be present 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() resp = app.get('/manage/agendas/%s/%s/%s/' % (agenda.id, today.year, today.month)) assert not 'No opening hours this month.' in resp.text assert not '