') in (4, 5)
def test_resource_month_view_event_outside_timeperiod(app, admin_user):
today = datetime.date.today()
resource = Resource.objects.create(label='Foo bar')
agenda = Agenda.objects.create(label='Agenda', kind='meetings')
agenda.resources.add(resource)
desk = Desk.objects.create(agenda=agenda, label='Desk')
meetingtype = MeetingType.objects.create(agenda=agenda, label='Bar', duration=30)
login(app)
# no time period - no events
resp = app.get('/manage/resource/%s/%d/%d/' % (resource.pk, today.year, today.month))
assert 'No bookings 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=agenda,
places=1,
desk=desk,
meeting_type=meetingtype,
start_datetime=localtime(now()).replace(
day=middle_day.day - middle_day.weekday() + 2, hour=9, minute=0
),
)
event.resources.add(resource)
Booking.objects.create(event=event)
# no time period - events are displayed
resp = app.get('/manage/resource/%s/%d/%d/' % (resource.pk, today.year, today.month))
assert resp.text.count('div class="booking') == 2
# events outside time period
TimePeriod.objects.create(
desk=desk, weekday=2, start_time=datetime.time(10, 0), end_time=datetime.time(16, 0)
)
resp = app.get('/manage/resource/%s/%d/%d/' % (resource.pk, today.year, today.month))
assert resp.text.count('div class="booking') == 2
assert 'Sunday' not in resp.text
assert 'Saturday' not in resp.text
# bookings are cancelled
Booking.objects.update(cancellation_datetime=now())
resp = app.get('/manage/resource/%s/%d/%d/' % (resource.pk, today.year, today.month))
assert resp.text.count('div class="booking') == 0
# create an event on saturday
Booking.objects.update(cancellation_datetime=None) # reset
event = Event.objects.create(
agenda=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
),
)
event.resources.add(resource)
Booking.objects.create(event=event)
resp = app.get('/manage/resource/%s/%d/%d/' % (resource.pk, today.year, today.month))
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/resource/%s/%d/%d/' % (resource.pk, today.year, today.month))
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/resource/%s/%d/%d/' % (resource.pk, today.year, today.month))
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=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
),
)
event.resources.add(resource)
Booking.objects.create(event=event)
resp = app.get('/manage/resource/%s/%d/%d/' % (resource.pk, today.year, today.month))
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/resource/%s/%d/%d/' % (resource.pk, today.year, today.month))
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/resource/%s/%d/%d/' % (resource.pk, today.year, today.month))
assert resp.text.count('div class="booking') == 4
assert 'Sunday' in resp.text
assert 'Saturday' in resp.text
def test_edit_resource(app, admin_user):
resource = Resource.objects.create(label='Foo bar')
app = login(app)
resp = app.get('/manage/resource/%s/' % resource.pk, status=200)
resp = resp.click('Edit')
resp.form['label'] = 'Foo bar baz'
resp.form['slug'] = 'baz'
resp = resp.form.submit()
assert resp.location.endswith('/manage/resource/%s/' % resource.pk)
resource.refresh_from_db()
assert resource.label == 'Foo bar baz'
assert resource.slug == 'baz'
def test_delete_resource(app, admin_user):
resource = Resource.objects.create(label='Foo bar')
app = login(app)
resp = app.get('/manage/resource/%s/' % resource.pk, status=200)
resp = resp.click('Delete')
resp = resp.form.submit()
assert resp.location.endswith('/manage/resources/')
assert Resource.objects.exists() is False
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
assert agenda.minimal_booking_delay == 1
assert agenda.maximal_booking_delay == 56
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('Settings')
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 'has_resources' not in resp.context
assert 'Foo baz' in resp.text
assert 'Settings' in resp.text
def test_options_agenda_cant_unset_delays(app, admin_user):
agenda = Agenda.objects.create(label=u'Foo bar')
assert agenda.minimal_booking_delay == 1
app = login(app)
url = '/manage/agendas/%s/edit' % agenda.pk
resp = app.get(url)
resp.form['minimal_booking_delay'] = None
resp = resp.form.submit()
agenda = Agenda.objects.get(label=u'Foo bar')
assert agenda.minimal_booking_delay == 1
def test_options_virtuale_agenda_can_unset_delays(app, admin_user):
agenda = Agenda.objects.create(label=u'Foo bar', kind='virtual', maximal_booking_delay=2)
assert agenda.maximal_booking_delay == 2
app = login(app)
url = '/manage/agendas/%s/edit' % agenda.pk
resp = app.get(url)
resp.form['maximal_booking_delay'] = None
resp = resp.form.submit()
agenda = Agenda.objects.get(label=u'Foo bar')
assert agenda.maximal_booking_delay is None
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=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/', status=200)
resp = resp.click('Foo bar').follow()
resp = resp.click('Settings')
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_meetings_agenda_num_queries(app, admin_user):
agenda = Agenda.objects.create(label='Agenda', kind='meetings')
for i in range(0, 10):
MeetingType.objects.create(agenda=agenda, label='MT %s' % i)
desk = Desk.objects.create(agenda=agenda, label='Desk %s' % i)
for weekday in (0, 6):
TimePeriod.objects.create(
weekday=weekday, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)
)
# exception starts and ends in the past
TimePeriodException.objects.create(
desk=desk,
start_datetime=now() - datetime.timedelta(days=2),
end_datetime=now() - datetime.timedelta(days=1),
)
if i % 2:
# exception starts in the past but ends in the futur
TimePeriodException.objects.create(
desk=desk,
start_datetime=now() - datetime.timedelta(days=1),
end_datetime=now() + datetime.timedelta(days=1),
)
else:
# exception in more than 2 weeks
TimePeriodException.objects.create(
desk=desk,
start_datetime=now() + datetime.timedelta(days=20),
end_datetime=now() + datetime.timedelta(days=21),
)
app = login(app)
with CaptureQueriesContext(connection) as ctx:
app.get('/manage/agendas/%s/settings' % agenda.pk)
assert len(ctx.captured_queries) == 8
def test_agenda_resources(app, admin_user):
agenda = Agenda.objects.create(label=u'Foo bar', kind='events')
resource = Resource.objects.create(label='Resource 1')
app = login(app)
# not for events agenda
app.get('/manage/agendas/%s/add-resource/' % agenda.pk, status=404)
app.get('/manage/agendas/%s/resource/%s/delete/' % (agenda.pk, resource.pk), status=404)
def test_meetings_agenda_resources(app, admin_user):
agenda = Agenda.objects.create(label=u'Foo bar', kind='meetings')
app = login(app)
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
assert 'has_resources' in resp.context
assert resp.context['has_resources'] is False
assert 'Add resource' not in resp.text
resource = Resource.objects.create(label='Resource 1')
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
assert 'has_resources' in resp.context
assert resp.context['has_resources'] is True
assert '/manage/resource/%s/' % resource.pk not in resp.text
assert '/manage/agendas/%s/resource/%s/delete/' % (agenda.pk, resource.pk) not in resp.text
resp = resp.click('Add resource')
assert list(resp.context['form'].fields['resource'].queryset) == [resource]
resp.form['resource'] = resource.pk
resp = resp.form.submit()
assert resp.location.endswith('/manage/agendas/%s/settings' % agenda.pk)
assert list(agenda.resources.all()) == [resource]
resp = resp.follow()
assert '/manage/resource/%s/' % resource.pk in resp.text
assert '/manage/agendas/%s/resource/%s/delete/' % (agenda.pk, resource.pk) in resp.text
resp = resp.click('Add resource')
assert list(resp.context['form'].fields['resource'].queryset) == []
resp = app.get('/manage/agendas/%s/resource/%s/delete/' % (agenda.pk, resource.pk))
resp = resp.form.submit()
assert resp.location.endswith('/manage/agendas/%s/settings' % agenda.pk)
assert list(agenda.resources.all()) == []
resp = resp.follow()
assert '/manage/resource/%s/' % resource.pk not in resp.text
assert '/manage/agendas/%s/resource/%s/delete/' % (agenda.pk, resource.pk) not 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('Settings')
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('Settings')
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('Settings')
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('Settings')
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()
resp = resp.click('Settings')
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$date'] = '%s-02-15' % year
resp.form['start_datetime$time'] = '17:00'
resp.form['places'] = 10
resp = resp.form.submit()
resp = resp.follow()
event = Event.objects.get(places=10)
assert event.publication_date is None
assert "This agenda doesn't have any event yet." not in resp.text
assert '/manage/agendas/%s/events/%s/' % (agenda.id, 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
# add with a description
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)
resp = resp.click('New Event')
resp.form['start_datetime$date'] = '%s-02-15' % year
resp.form['start_datetime$time'] = '18:00'
resp.form['publication_date'] = '2020-05-11'
resp.form['places'] = 11
resp.form['description'] = 'A description'
resp = resp.form.submit()
resp = resp.follow()
event = Event.objects.get(places=11)
assert event.description == 'A description'
assert event.publication_date == datetime.date(2020, 5, 11)
# add with errors in datetime parts
for parts in (
('', ''),
('invalid', ''),
('', 'invalid'),
('2019-02-24', 'invalid'),
('invalid', '17:00'),
):
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)
resp = resp.click('New Event')
resp.form['start_datetime$date'] = parts[0]
resp.form['start_datetime$time'] = parts[1]
resp.form['places'] = 10
resp = resp.form.submit()
assert resp.text.count('This field is required.') == 1
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()
resp = resp.click('Settings')
assert 'Settings' in resp.text
resp = resp.click('New Event')
resp.form['start_datetime$date'] = '2016-02-15'
resp.form['start_datetime$time'] = '17:00'
resp.form['places'] = 10
resp = resp.form.submit()
resp = resp.follow()
event = Event.objects.get(places=10)
assert "This agenda doesn't have any event yet." not in resp.text
assert '/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id) in resp.text
assert 'Feb. 15, 2016, 5 p.m.' in resp.text
assert '10 places' in resp.text
assert event.duration is None
assert event.end_datetime is None
resp = resp.click('New Event')
resp.form['start_datetime$date'] = '2016-02-15'
resp.form['start_datetime$time'] = '17:00'
resp.form['duration'] = 45
resp.form['places'] = 12
resp = resp.form.submit()
resp = resp.follow()
event = Event.objects.get(places=12)
assert event.duration == 45
assert event.end_datetime == event.start_datetime + datetime.timedelta(minutes=45)
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()
assert event.duration is None
assert event.end_datetime is None
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$date'].value == '2016-02-15'
assert resp.form['start_datetime$time'].value == '17:00'
assert resp.form['publication_date'].value == ''
assert resp.form['duration'].value == ''
resp.form['start_datetime$date'] = '2016-02-16'
resp.form['start_datetime$time'] = '17:00'
resp.form['publication_date'] = '2020-05-11'
resp.form['duration'].value = 45
resp.form['places'] = 20
resp = resp.form.submit()
resp = resp.follow()
assert '/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id) in resp.text
assert 'Feb. 16, 2016, 5 p.m.' in resp.text
assert '20 places' in resp.text
event.refresh_from_db()
assert event.publication_date == datetime.date(2020, 5, 11)
assert event.duration == 45
assert event.end_datetime == event.start_datetime + datetime.timedelta(minutes=45)
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.objects.create(
start_datetime=make_aware(datetime.datetime(2016, 2, 15, 17, 0)),
places=20,
agenda=agenda,
publication_date=datetime.date(2020, 5, 11),
)
app = login(app, username='manager', password='manager')
resp = app.get('/manage/agendas/%s/events/%s/edit' % (agenda.id, 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$date'].value == '2016-02-15'
assert resp.form['start_datetime$time'].value == '17:00'
assert resp.form['publication_date'].value == '2020-05-11'
resp.form['start_datetime$date'] = '2016-02-16'
resp.form['start_datetime$time'] = '17:00'
resp.form['publication_date'] = ''
resp.form['places'] = 20
resp = resp.form.submit()
resp = resp.follow()
assert '/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id) in resp.text
assert 'Feb. 16, 2016, 5 p.m.' in resp.text
assert '20 places' in resp.text
event.refresh_from_db()
assert event.publication_date is None
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='/manage/agendas/%s/events/%s/edit' % (agenda.id, 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='/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id))
resp = resp.click('Delete')
assert 'Are you sure you want to delete this event?' in resp.text
booking = Booking(event=event)
booking.save()
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)
resp = resp.click(href='/manage/agendas/%s/events/%s/edit' % (agenda.id, 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='/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id))
resp = resp.click('Delete')
assert 'Are you sure you want to delete this event?' 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='/manage/agendas/%s/events/%s/edit' % (agenda.id, 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() == 1
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'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.form['events_csv_file'] = Upload('t.csv', b'2016-09-16,18:00,10,5,' + b'x' * 151, 'text/csv')
resp = resp.form.submit(status=200)
assert 'Ensure this value has at most 150' 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()
# BOM
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
resp.form['events_csv_file'] = Upload(
't.csv', codecs.BOM_UTF8 + 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', u'2016-09-16,18:00,10,5,éléphant'.encode('iso-8859-15'), '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', u'2016-09-16,18:00,10,5,éléphant'.encode('eucjp'), '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'\x8f«±l\x8f«±phant' # eucjp interpreted as iso-8859-15
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()
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
resp.form['events_csv_file'] = Upload(
't.csv',
'"date"\t"time"\t"etc."\n'
'"2016-09-16"\t"18:00"\t"10"\t"5"\t"éléphant"\n'
'"2016-09-19"\t"18:00"\t"10"'.encode('iso-8859-15'),
'text/csv',
)
resp = resp.form.submit(status=302)
assert Event.objects.count() == 2
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,label,slug', 'text/csv')
resp = resp.form.submit(status=302)
assert Event.objects.count() == 1
event = Event.objects.latest('pk')
assert event.start_datetime == make_aware(datetime.datetime(2016, 9, 16, 18, 0))
assert event.places == 10
assert event.waiting_list_places == 5
assert event.label == 'label'
assert event.slug == 'slug'
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,label,slug', 'text/csv')
resp = resp.form.submit(status=200)
assert 'Event with this Agenda and Identifier already exists.' in resp.text
assert '__all__' not in resp.text
# additional optional attributes
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,label,slug,,,,', 'text/csv')
resp = resp.form.submit(status=302)
assert Event.objects.count() == 1
event = Event.objects.get()
assert event.description == ''
assert event.pricing == ''
assert event.url == ''
assert event.publication_date is None
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,label,slug,"description\nfoobar",pricing,url,2016-10-16', 'text/csv'
)
resp = resp.form.submit(status=302)
assert Event.objects.count() == 1
event = Event.objects.get()
assert event.description == 'description\nfoobar'
assert event.pricing == 'pricing'
assert event.url == 'url'
assert event.publication_date == datetime.date(2016, 10, 16)
# publication date bad format
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,label,slug,description,pricing,url,foobar', 'text/csv'
)
resp = resp.form.submit(status=200)
assert 'Invalid file format. (date format' in resp.text
# import events with empty slugs
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,label,,,pricing,\n'
b'2016-09-17,18:00,10,5,label,,,pricing,\n'
b'2016-09-18,18:00,10,5,label,,,pricing,\n',
'text/csv',
)
resp = resp.form.submit(status=302)
assert Event.objects.count() == 3
# forbidden numerical slug
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,label,1234', 'text/csv')
resp = resp.form.submit(status=200)
assert 'value cannot be a number' in resp.text
assert 'Identifier:' in resp.text # verbose_name is shown, not field name ('slug:')
# handle duplicated slug
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,label,slug\n' b'2016-09-16,18:00,10,5,label,slug\n', 'text/csv',
)
resp = resp.form.submit(status=200)
assert 'duplicated event identifiers' in resp.text
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'
assert 'deleted' not in resp.form.fields
resp = resp.form.submit()
meeeting_type = MeetingType.objects.get(agenda=agenda)
assert meeeting_type.label == 'Blah'
assert meeeting_type.duration == 60
assert meeeting_type.deleted is False
resp = resp.follow()
assert 'Blah' in resp.text
# and edit
resp = resp.click('Blah')
resp.form['duration'] = '30'
assert 'deleted' not in resp.form.fields
resp = resp.form.submit()
meeeting_type = MeetingType.objects.get(agenda=agenda)
assert meeeting_type.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')
assert 'Are you sure you want to delete this?' in resp.text
assert 'disabled' not in resp.text
resp = resp.form.submit()
assert resp.location.endswith('/manage/agendas/%s/settings' % agenda.id)
meeting_type.refresh_from_db()
assert meeting_type.deleted is True
assert '__deleted__' in meeting_type.slug
# meeting type not showing up anymore
resp = app.get('/manage/', status=200)
resp = resp.click('Foo').follow()
resp = resp.click('Settings')
assert 'Meeting Type Foo' not in resp.text
# it is possible to add a new meeting type with the same slug
new_meeting_type = MeetingType.objects.create(agenda=agenda, label='Blah')
assert new_meeting_type.slug == 'blah'
def test_meetings_agenda_add_time_period(app, admin_user):
agenda = Agenda.objects.create(label=u'Foo bar', kind='meetings')
desk = Desk.objects.create(agenda=agenda, label='Desk A')
MeetingType.objects.create(agenda=agenda, label='Blah')
app = login(app)
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
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')
# invert start and end
resp2 = resp.click('Add a time period', index=0)
resp2.form['weekdays-0'].checked = True
resp2.form['start_time'] = '13:00'
resp2.form['end_time'] = '10:00'
resp2 = resp2.form.submit()
assert 'End time must come after start time.' in resp2.text
# 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 edit with inverted start/end
resp2 = resp.click(u'Wednesday / 9 a.m. → 5 p.m.')
resp2.form['start_time'] = '18:00'
resp2 = resp2.form.submit()
assert 'End time must come after start time.' in resp2.text
# 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
desk = Desk.objects.latest('pk')
TimePeriod.objects.create(
weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)
)
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
new_desk = Desk.objects.latest('pk')
assert new_desk.timeperiod_set.count() == 0
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_add_desk_from_another(app, admin_user):
agenda = Agenda.objects.create(label=u'Foo bar', kind='meetings')
desk = Desk.objects.create(agenda=agenda, label='Desk A')
TimePeriod.objects.create(
weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)
)
assert Desk.objects.count() == 1
app = login(app)
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
resp = resp.click('New Desk')
resp.form['label'] = 'Desk B'
resp.form['copy_from'] = desk.pk
resp = resp.form.submit().follow()
assert Desk.objects.count() == 2
new_desk = Desk.objects.latest('pk')
assert new_desk.label == 'Desk B'
assert new_desk.timeperiod_set.count() == 1
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):
agenda = Agenda.objects.create(label=u'Foo bar', kind='meetings')
desk = Desk.objects.create(agenda=agenda, label='Desk A')
MeetingType.objects.create(agenda=agenda, label='Blah')
app = login(app)
resp = app.get('/manage/agendas/%s/settings' % 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=1))
dt_format = '%Y-%m-%d %H:%M'
resp.form['label'] = 'Exception 1'
resp.form['start_datetime$date'] = tomorrow.strftime('%Y-%m-%d')
resp.form['start_datetime$time'] = '08:00'
resp.form['end_datetime$date'] = tomorrow.strftime('%Y-%m-%d')
resp.form['end_datetime$time'] = '16:00'
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$date'] = future.strftime('%Y-%m-%d')
resp.form['start_datetime$time'] = '00:00'
resp.form['end_datetime$date'] = future.strftime('%Y-%m-%d')
resp.form['end_datetime$time'] = '16:00'
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-extract-list" % desk.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$date'] = '2017-05-22'
resp.form['start_datetime$time'] = '08:00'
resp.form['end_datetime$date'] = '2017-05-26'
resp.form['end_datetime$time'] = '17:30'
resp = resp.form.submit().follow()
assert 'Exception added. Note: one or several bookings exists within this time slot.' in resp.text
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$date'] = '2017-05-22'
resp.form['start_datetime$time'] = '08:00'
resp.form['end_datetime$date'] = '2017-05-26'
resp.form['end_datetime$time'] = '17:30'
resp = resp.form.submit().follow()
assert 'Exception added. Note: 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():
form = TimePeriodExceptionForm(
data={
'start_datetime$date': '2017-05-26',
'start_datetime$time': '17:30',
'end_datetime$date': '2017-05-22',
'end_datetime$time': '08:00',
}
)
assert form.is_valid() is False
assert form.errors['end_datetime'] == ['End datetime must be greater than start datetime.']
# start_datetime is invalid
form = TimePeriodExceptionForm(
data={
'start_datetime$date': '2017-05-26',
'start_datetime$time': 'foo',
'end_datetime$date': '2017-05-22',
'end_datetime$time': '08:00',
}
)
assert form.is_valid() is False
# end_datetime is invalid
form = TimePeriodExceptionForm(
data={
'start_datetime$date': '2017-05-26',
'start_datetime$time': '17:30',
'end_datetime$date': 'bar',
'end_datetime$time': '08:00',
}
)
assert form.is_valid() is False
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$date'] = tomorrow.strftime('%Y-%m-%d')
resp.form['start_datetime$time'] = '08:00'
resp.form['end_datetime$date'] = tomorrow.strftime('%Y-%m-%d')
resp.form['end_datetime$time'] = '16:00'
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().follow()
assert TimePeriodException.objects.count() == 0
assert resp.request.url.endswith('/manage/agendas/%d/settings' % agenda.pk)
# stay on exception list
time_period_exception = TimePeriodException.objects.create(
label='Future Exception',
desk=desk,
start_datetime=now() + datetime.timedelta(days=1),
end_datetime=now() + datetime.timedelta(days=2),
)
resp = app.get('/manage/time-period-exceptions/%d/exception-list' % desk.pk)
resp = resp.click(href='/manage/time-period-exceptions/%d/delete' % time_period_exception.pk)
resp = resp.form.submit(
extra_environ={'HTTP_REFERER': str('/manage/time-period-exceptions/%d/exception-list' % desk.pk)}
).follow()
assert resp.request.url.endswith('/manage/time-period-exceptions/%d/exception-list' % desk.pk)
def test_exception_list(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)
)
past_exception = TimePeriodException.objects.create(
label='Past Exception',
desk=desk,
start_datetime=now() - datetime.timedelta(days=2),
end_datetime=now() - datetime.timedelta(days=1),
)
current_exception = TimePeriodException.objects.create(
label='Current Exception',
desk=desk,
start_datetime=now() - datetime.timedelta(days=1),
end_datetime=now() + datetime.timedelta(days=1),
)
future_exception = TimePeriodException.objects.create(
label='Future Exception',
desk=desk,
start_datetime=now() + datetime.timedelta(days=1),
end_datetime=now() + datetime.timedelta(days=2),
)
login(app)
resp = app.get('/manage/agendas/%d/settings' % agenda.pk)
assert '/manage/time-period-exceptions/%d/edit' % past_exception.pk not in resp.text
assert '/manage/time-period-exceptions/%d/edit' % current_exception.pk in resp.text
assert '/manage/time-period-exceptions/%d/edit' % future_exception.pk in resp.text
resp = resp.click(href="/manage/time-period-exceptions/%d/exception-extract-list" % desk.pk)
assert '/manage/time-period-exceptions/%d/edit' % past_exception.pk not in resp.text
assert '/manage/time-period-exceptions/%d/edit' % current_exception.pk in resp.text
assert '/manage/time-period-exceptions/%d/edit' % future_exception.pk in resp.text
resp = resp.click(href="/manage/time-period-exceptions/%d/exception-list" % desk.pk)
assert '/manage/time-period-exceptions/%d/edit' % past_exception.pk not in resp.text
assert '/manage/time-period-exceptions/%d/edit' % current_exception.pk in resp.text
assert '/manage/time-period-exceptions/%d/edit' % future_exception.pk in resp.text
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.objects.create(agenda=agenda, label='Foo')
login(app)
resp = app.get('/manage/agendas/%d/settings' % agenda.pk)
assert 'Import exceptions from .ics' in resp.text
resp = resp.click('upload')
assert "To add new exceptions, you can upload a file or specify an address to a remote calendar." in resp
resp = resp.form.submit(status=200)
assert 'Please provide an ICS File or an URL.' in resp.text
resp = app.get('/manage/agendas/%d/settings' % agenda.pk)
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/settings' % agenda.pk)
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
assert TimePeriodExceptionSource.objects.filter(desk=desk).count() == 1
source = TimePeriodExceptionSource.objects.latest('pk')
exception = TimePeriodException.objects.latest('pk')
assert exception.source == source
assert source.ics_filename == 'exceptions.ics'
assert 'exceptions.ics' in source.ics_file.name
assert source.ics_url is None
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.objects.create(agenda=agenda, label='Bar')
login(app)
resp = app.get('/manage/agendas/%d/settings' % agenda.pk)
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
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 TimePeriodExceptionSource.objects.filter(desk=desk).count() == 1
source = TimePeriodExceptionSource.objects.latest('pk')
exception = TimePeriodException.objects.latest('pk')
assert exception.source == source
assert source.ics_filename is None
assert source.ics_file.name == ''
assert source.ics_url == 'http://example.com/foo.ics'
@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.objects.create(agenda=agenda, label='Bar')
login(app)
resp = app.get('/manage/agendas/%d/settings' % agenda.pk)
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
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
@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.objects.create(agenda=agenda, label='Bar')
login(app)
resp = app.get('/manage/agendas/%d/settings' % agenda.pk)
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 (http://example.com/foo.ics, 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.objects.create(agenda=agenda, label='Bar')
login(app)
resp = app.get('/manage/agendas/%d/settings' % agenda.pk)
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://example.com/foo.ics, 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.objects.create(agenda=agenda, label='Bar')
login(app)
resp = app.get('/manage/agendas/%d/settings' % agenda.pk)
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 (https://example.com/foo.ics, SSL error).' in resp.text
def test_meetings_agenda_delete_time_period_exception_source(app, admin_user, freezer):
freezer.move_to('2019-12-01')
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)
# import a source
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
source1 = TimePeriodExceptionSource.objects.latest('pk')
assert source1.timeperiodexception_set.count() == 2
# import another one
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_recurrent_exceptions, 'text/calendar')
resp = resp.form.submit(status=302).follow()
assert TimePeriodException.objects.filter(desk=desk).count() == 4
source2 = TimePeriodExceptionSource.objects.latest('pk')
assert source2.timeperiodexception_set.count() == 2
# delete the second one
resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
resp = resp.click('Settings')
resp = resp.click('upload')
resp = resp.click(href='/manage/time-period-exceptions-source/%d/delete' % source2.pk)
resp = resp.form.submit().follow()
assert TimePeriodException.objects.count() == 2
assert source1.timeperiodexception_set.count() == 2
assert TimePeriodExceptionSource.objects.filter(pk=source2.pk).exists() is False
# delete the first one
resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
resp = resp.click('Settings')
resp = resp.click('upload')
resp = resp.click(href='/manage/time-period-exceptions-source/%d/delete' % source1.pk)
resp = resp.form.submit().follow()
assert TimePeriodException.objects.count() == 0
assert TimePeriodExceptionSource.objects.filter(pk=source1.pk).exists() is False
def test_meetings_agenda_replace_time_period_exception_source(app, admin_user, freezer):
freezer.move_to('2019-12-01')
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)
)
ics_file_content = 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"""
login(app)
# import a source from a file
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_file_content, 'text/calendar')
resp = resp.form.submit(status=302).follow()
assert TimePeriodException.objects.filter(desk=desk).count() == 2
source = TimePeriodExceptionSource.objects.latest('pk')
assert source.timeperiodexception_set.count() == 2
exceptions = list(source.timeperiodexception_set.order_by('pk'))
old_ics_file_path = source.ics_file.path
# replace the source
resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
resp = resp.click('Settings')
resp = resp.click('upload')
resp = resp.click(href='/manage/time-period-exceptions-source/%d/replace' % source.pk)
resp.form['ics_newfile'] = Upload('exceptions.ics', ics_file_content, 'text/calendar')
resp = resp.form.submit().follow()
source.refresh_from_db()
assert source.ics_file.path != old_ics_file_path
assert os.path.exists(old_ics_file_path) is False
assert TimePeriodException.objects.count() == 2
assert source.timeperiodexception_set.count() == 2
new_exceptions = list(source.timeperiodexception_set.order_by('pk'))
assert exceptions[0].pk != new_exceptions[0].pk
assert exceptions[1].pk != new_exceptions[1].pk
@mock.patch('chrono.agendas.models.requests.get')
def test_meetings_agenda_refresh_time_period_exception_source(mocked_get, 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)
)
ics_url_content = """BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//foo.bar//EN
BEGIN:VEVENT
DTSTART:20180101
DTEND:20180101
SUMMARY:New Year's Eve
END:VEVENT
END:VCALENDAR"""
login(app)
# import a source from an url
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 = ics_url_content
mocked_get.return_value = mocked_response
resp = resp.form.submit(status=302).follow()
assert TimePeriodException.objects.filter(desk=desk).count() == 1
source = TimePeriodExceptionSource.objects.latest('pk')
assert source.timeperiodexception_set.count() == 1
exceptions = list(source.timeperiodexception_set.order_by('pk'))
# refresh the source
resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
resp = resp.click('Settings')
resp = resp.click('upload')
mocked_response = mock.Mock()
mocked_response.text = ics_url_content
mocked_get.return_value = mocked_response
resp = resp.click(href='/manage/time-period-exceptions-source/%d/refresh' % source.pk)
assert TimePeriodException.objects.count() == 1
assert source.timeperiodexception_set.count() == 1
new_exceptions = list(source.timeperiodexception_set.order_by('pk'))
assert exceptions[0].pk != new_exceptions[0].pk
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 'No opening hours this day.' not in resp.text
assert 'div class="booking' not 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_day_view_event_outside_timeperiod(app, admin_user):
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)
login(app)
# no time period - no events
resp = app.get('/manage/agendas/%s/%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=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/%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/%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/%d/%d/%d/' % (agenda.pk, today.year, today.month, today.day))
assert resp.text.count('div class="booking') == 2
assert '
') in (4, 5)
def test_agenda_month_view_event_outside_timeperiod(app, admin_user):
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)
login(app)
# no time period - no events
resp = app.get('/manage/agendas/%s/%d/%d/' % (agenda.pk, today.year, today.month))
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=agenda,
places=1,
desk=desk,
meeting_type=meetingtype,
start_datetime=localtime(now()).replace(
day=middle_day.day - middle_day.weekday() + 2, hour=9, minute=0
),
)
Booking.objects.create(event=event)
# no time period - events are displayed
resp = app.get('/manage/agendas/%s/%d/%d/' % (agenda.pk, today.year, today.month))
assert resp.text.count('div class="booking') == 2
# bookings are cancelled
Booking.objects.update(cancellation_datetime=now())
resp = app.get('/manage/agendas/%s/%d/%d/' % (agenda.pk, today.year, today.month))
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/%d/%d/' % (agenda.pk, today.year, today.month))
assert resp.text.count('div class="booking') == 2
assert '