chrono/tests/test_manager.py

892 lines
35 KiB
Python

# -*- coding: utf-8 -*-
from django.contrib.auth.models import User, Group
from django.utils.timezone import make_aware, now, localtime
import datetime
import pytest
from webtest import TestApp, Upload
from chrono.wsgi import application
from chrono.agendas.models import (Agenda, Event, Booking, MeetingType,
TimePeriod, Desk, TimePeriodException)
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
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 == 'http://testserver/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 == 'http://testserver/manage/'
def test_access(app, admin_user):
app = login(app)
resp = app.get('/manage/', status=200)
assert '<h2>Agendas</h2>' in resp.body
assert "This site doesn't have any agenda yet." in resp.body
def test_logout(app, admin_user):
app = login(app)
app.get('/logout/')
assert app.get('/manage/', status=302).location == 'http://testserver/login/?next=/manage/'
def test_logout_next(app, admin_user):
app = login(app)
app.get('/logout/')
assert app.get('/manage/', status=302).location == 'http://testserver/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.body == 'Q(%s);' % resp.body
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()
agenda = Agenda(label=u'Bar Foo')
agenda.save()
app = login(app, username='manager', password='manager')
resp = app.get('/manage/', status=200)
assert 'Foo Bar' in resp.body
assert 'Bar Foo' not in resp.body
assert 'New' not in resp.body
app.get('/manage/agendas/%s/' % agenda.id, status=403)
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 == 'http://testserver/manage/agendas/%s/' % agenda.id
resp = resp.follow()
assert '<h2>Foo bar' in resp.body
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')
resp = resp.click('Options')
assert resp.form['label'].value == 'Foo bar'
resp.form['label'] = 'Foo baz'
resp = resp.form.submit()
assert resp.location == 'http://testserver/manage/agendas/%s/' % agenda.id
resp = resp.follow()
assert '<h2>Foo baz' in resp.body
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 'Options' in resp.body
resp = app.get('/manage/agendas/%s/edit' % agenda.id, status=403)
agenda.edit_role = manager_user.groups.all()[0]
agenda.save()
resp = app.get('/manage/', status=200)
resp = resp.click('Foo bar')
resp = resp.click('Options')
assert resp.form['label'].value == 'Foo bar'
resp.form['label'] = 'Foo baz'
resp = resp.form.submit()
assert resp.location == 'http://testserver/manage/agendas/%s/' % agenda.id
resp = resp.follow()
assert '<h2>Foo baz' in resp.body
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')
resp = resp.click('Delete')
resp = resp.form.submit()
assert resp.location == 'http://testserver/manage/'
resp = resp.follow()
assert not 'Foo bar' in resp.body
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')
resp = resp.click('Delete')
assert 'Are you sure you want to delete this?' in resp.body
booking = Booking(event=event)
booking.save()
resp = app.get('/manage/', status=200)
resp = resp.click('Foo bar')
resp = resp.click('Delete')
assert 'This cannot be removed' in resp.body
booking.cancellation_datetime = now()
booking.save()
resp = app.get('/manage/', status=200)
resp = resp.click('Foo bar')
resp = resp.click('Delete')
assert 'Are you sure you want to delete this?' in resp.body
# 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')
assert 'Options' in resp.body
assert 'Delete' not in resp.body
resp = app.get('/manage/agendas/%s/delete' % agenda.id, 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/' % agenda.id, status=200)
assert "This agenda doesn't have any event yet." in resp.body
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.body
assert '/manage/events/%s/' % event.id in resp.body
assert ('Feb. 15, %s, 5 p.m.' % year) in resp.body
assert '10 places' in resp.body
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=200)
assert "This agenda doesn't have any event yet." in resp.body
assert '>New Event<' not in resp.body
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, status=200)
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.body
assert '/manage/events/%s/' % event.id in resp.body
assert 'Feb. 15, 2016, 5 p.m.' in resp.body
assert '10 places' in resp.body
def test_edit_event(app, admin_user):
agenda = Agenda(label=u'Foo bar')
agenda.save()
event = Event(start_datetime=datetime.datetime(2016, 2, 15, 17, 0),
places=20, agenda=agenda)
event.save()
app = login(app)
resp = app.get('/manage/agendas/%s/' % 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.body
assert 'Feb. 16, 2016, 5 p.m.' in resp.body
assert '20 places' in resp.body
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=datetime.datetime(2016, 2, 15, 17, 0),
places=20, agenda=agenda)
event.save()
app = login(app, username='manager', password='manager')
resp = app.get('/manage/agendas/%s/' % agenda.id, status=200)
assert '/events/%s/' % event.id not in resp.body
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/' % 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.body
assert 'Feb. 16, 2016, 5 p.m.' in resp.body
assert '20 places' in resp.body
def test_booked_places(app, admin_user):
agenda = Agenda(label=u'Foo bar')
agenda.save()
event = Event(start_datetime=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/' % agenda.id, status=200)
assert '10 places' in resp.body
assert '2 booked places' in resp.body
def test_event_classes(app, admin_user):
agenda = Agenda(label=u'Foo bar')
agenda.save()
event = Event(start_datetime=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/' % agenda.id, status=200)
assert not 'full' in resp.body
assert not 'overbooking' in resp.body
for i in range(8):
Booking(event=event).save()
resp = app.get('/manage/agendas/%s/' % agenda.id, status=200)
assert 'full' in resp.body
assert not 'overbooking' in resp.body
Booking(event=event).save()
resp = app.get('/manage/agendas/%s/' % agenda.id, status=200)
assert 'full' in resp.body
assert 'overbooking' in resp.body
def test_delete_event(app, admin_user):
agenda = Agenda(label=u'Foo bar')
agenda.save()
event = Event(start_datetime=datetime.datetime(2016, 2, 15, 17, 0),
places=10, agenda=agenda)
event.save()
app = login(app)
resp = app.get('/manage/agendas/%s/' % 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 == 'http://testserver/manage/agendas/%s/' % 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/' % 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.body
booking = Booking(event=event)
booking.save()
resp = app.get('/manage/agendas/%s/' % 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.body
booking.cancellation_datetime = now()
booking.save()
resp = app.get('/manage/agendas/%s/' % 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.body
# 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=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/' % 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 == 'http://testserver/manage/agendas/%s/' % 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/' % 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.body.startswith('date,time,')
resp.form['events_csv_file'] = Upload('t.csv', sample_csv_resp.body, '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', 'xx', 'text/csv')
resp = resp.form.submit(status=200)
assert 'Invalid file format.' in resp.body
resp.form['events_csv_file'] = Upload('t.csv', 'xxxx\0\0xxxx', 'text/csv')
resp = resp.form.submit(status=200)
assert 'Invalid file format.' in resp.body
resp.form['events_csv_file'] = Upload('t.csv', '2016-14-16,18:00', 'text/csv')
resp = resp.form.submit(status=200)
assert 'Invalid file format.' in resp.body
resp.form['events_csv_file'] = Upload('t.csv', '2016-14-16,18:00,10', 'text/csv')
resp = resp.form.submit(status=200)
assert 'Invalid file format. (date/time format' in resp.body
resp.form['events_csv_file'] = Upload('t.csv', '2016-09-16,18:00,blah', 'text/csv')
resp = resp.form.submit(status=200)
assert 'Invalid file format. (number of places,' in resp.body
resp.form['events_csv_file'] = Upload('t.csv', '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.body
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
resp.form['events_csv_file'] = Upload('t.csv', '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', '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', '2016-09-16,18:00,10,5,bla bla bla', '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 == 'bla bla bla'
Event.objects.all().delete()
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
resp.form['events_csv_file'] = Upload('t.csv', 'date,time,etc.\n'
'2016-09-16,18:00,10,5,bla bla bla\n'
'\n'
'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 == 'http://testserver/manage/agendas/%s/' % agenda.id
resp = resp.follow()
assert '<h2>Foo bar' in resp.body
assert 'Meeting Types' in resp.body
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, status=200)
assert "This agenda doesn't have any meeting type yet." in resp.body
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.body
# 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, status=200)
resp = resp.click('Blah')
resp = resp.click('Delete')
resp = resp.form.submit()
assert resp.location == 'http://testserver/manage/agendas/%s/' % 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')
app = login(app)
resp = app.get('/manage/agendas/%s/' % agenda.id, status=200)
assert not 'Add a time period' in resp.body
MeetingType(agenda=agenda, label='Blah').save()
resp = app.get('/manage/agendas/%s/' % agenda.id, status=200)
resp = resp.click('Add a time period')
resp.form['weekday'].select(text='Wednesday')
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['weekday'].select(text='Monday')
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.body.index('Monday') < resp.body.index('Wednesday')
# and edit
resp = resp.click(u'Wednesday / 10 a.m. → 5 p.m.')
assert 'Edit Time Period' in resp.body
resp.form['start_time'] = '9:00'
resp = resp.form.submit()
assert TimePeriod.objects.get(desk=desk, weekday=2).start_time.hour == 9
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/' % agenda.id, status=200)
resp = resp.click('Wednesday')
resp = resp.click('Delete')
resp = resp.form.submit()
assert resp.location == 'http://testserver/manage/agendas/%s/' % 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 'New Meeting Type' in resp.content
assert 'Add a time period' not in resp.content
MeetingType(agenda=agenda, label='Blah').save()
resp = app.get('/manage/agendas/%d/' % agenda.id)
assert 'Add a time period' not in resp.content
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)
assert '/manage/timeperiods/%s/edit' % time_period.id not in resp.body
assert '/manage/timeperiods/%s/delete' % time_period.id not in resp.body
app.get('/manage/timeperiods/%d/edit' % 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)
assert 'Add a time period' in resp.content
assert '/manage/timeperiods/%s/edit' % time_period.id in resp.body
assert '/manage/timeperiods/%s/delete' % time_period.id in resp.body
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, status=200)
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, status=200)
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 == 'http://testserver/manage/agendas/%s/' % 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['weekday'].select(text='Wednesday')
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.content
assert 'Exception 2' not in resp.content
resp = resp.click(href="/manage/time-period-exceptions/%d/exception-list" % agenda.desk_set.first().pk)
assert 'Exception 1' in resp.content
assert 'Exception 2' in resp.content
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,
start_datetime=datetime.datetime(2017, 5, 22, 10, 30))
Booking.objects.create(event=event)
login(app)
resp = app.get('/manage/agendas/%d/' % agenda.pk)
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.' in resp.content
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)
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.content
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)
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)
assert 'Import exceptions from .ics' not in resp.content
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)
assert 'Import exceptions from .ics' in resp.content
resp = resp.click('upload')
resp.form['ics_file'] = Upload('exceptions.ics', 'invalid content', 'text/calendar')
resp = resp.form.submit(status=200)
assert 'File format is invalid' in resp.content
ics_with_recurrent_exceptions = """BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//foo.bar//EN
BEGIN:VEVENT
DTSTART:20180101
DTEND:20180101
SUMMARY:New 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=200)
assert 'Recurrent events are not handled.' in resp.content
ics_with_no_start_date = """BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//foo.bar//EN
BEGIN:VEVENT
DTEND:20180101
SUMMARY:New 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 &quot;New eve&quot; has no start date.' in resp.content
ics_with_no_events = """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&#39;t contain any events." in resp.content
ics_with_exceptions = """BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//foo.bar//EN
BEGIN:VEVENT
DTSTART:20180101
DTEND:20180101
SUMMARY:New eve
END:VEVENT
END:VCALENDAR"""
resp.form['ics_file'] = Upload('exceptions.ics', ics_with_exceptions, 'text/calendar')
resp = resp.form.submit(status=302)
assert TimePeriodException.objects.count() == 1
resp = resp.follow()
assert 'An exception has been imported.' in resp.content