743 lines
32 KiB
Python
743 lines
32 KiB
Python
import datetime
|
|
import os
|
|
from unittest import mock
|
|
|
|
import pytest
|
|
from django.db import connection
|
|
from django.test.utils import CaptureQueriesContext
|
|
from webtest import Upload
|
|
|
|
from chrono.agendas.models import (
|
|
Agenda,
|
|
Booking,
|
|
Desk,
|
|
Event,
|
|
MeetingType,
|
|
TimePeriodException,
|
|
TimePeriodExceptionSource,
|
|
UnavailabilityCalendar,
|
|
)
|
|
from chrono.apps.snapshot.models import AgendaSnapshot, UnavailabilityCalendarSnapshot
|
|
from chrono.utils.timezone import localtime, make_aware, now
|
|
from tests.utils import login
|
|
|
|
pytestmark = pytest.mark.django_db
|
|
|
|
|
|
def test_no_unavailability_calendar(app, admin_user):
|
|
app = login(app)
|
|
|
|
# empty unavailability calendars list
|
|
resp = app.get('/manage/')
|
|
resp = resp.click('Unavailability calendars')
|
|
assert "This site doesn't have any unavailability calendar yet" in resp.text
|
|
|
|
# on the agenda settings page, no unavailability calendar reference
|
|
agenda = Agenda.objects.create(label='Agenda', kind='meetings')
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
|
|
assert 'unavailability calendar' not in resp.text
|
|
|
|
|
|
def test_add_unavailability_calendar(app, admin_user):
|
|
app = login(app)
|
|
resp = app.get('/manage/')
|
|
resp = resp.click('Unavailability calendars')
|
|
resp = resp.click('New')
|
|
resp.form['label'] = 'Foo bar'
|
|
resp = resp.form.submit()
|
|
unavailability_calendar = UnavailabilityCalendar.objects.latest('pk')
|
|
assert resp.location.endswith('/manage/unavailability-calendar/%s/settings' % unavailability_calendar.pk)
|
|
resp = app.get('/manage/unavailability-calendar/%s/' % unavailability_calendar.pk)
|
|
assert unavailability_calendar.label == 'Foo bar'
|
|
assert unavailability_calendar.slug == 'foo-bar'
|
|
assert 'This unavailability calendar is not used yet.' in resp.text
|
|
resp = app.get('/manage/unavailability-calendars/')
|
|
assert 'Foo bar' in resp.text
|
|
assert 'foo-bar' in resp.text
|
|
assert UnavailabilityCalendarSnapshot.objects.count() == 1
|
|
|
|
|
|
def test_used_unavailability_calendar(app, admin_user):
|
|
unavailability_calendar = UnavailabilityCalendar.objects.create(label='Calendar')
|
|
agenda = Agenda.objects.create(label='Foo', kind='meetings')
|
|
desk = Desk.objects.create(agenda=agenda, label='desk')
|
|
|
|
app = login(app)
|
|
url = '/manage/unavailability-calendar/%s/' % unavailability_calendar.pk
|
|
resp = app.get(url)
|
|
assert 'This unavailability calendar is not used yet.' in resp.text
|
|
assert 'Foo' not in resp.text
|
|
|
|
desk.unavailability_calendars.add(unavailability_calendar)
|
|
resp = app.get(url)
|
|
assert 'This unavailability calendar is not used yet.' not in resp.text
|
|
assert 'Foo' in resp.text
|
|
|
|
|
|
def test_edit_unavailability_calendar(app, admin_user):
|
|
unavailability_calendar = UnavailabilityCalendar.objects.create(label='Foo')
|
|
app = login(app)
|
|
settings_url = '/manage/unavailability-calendar/%s/settings' % unavailability_calendar.pk
|
|
resp = app.get(settings_url)
|
|
resp = resp.click('Options')
|
|
resp.form['label'] = 'Bar'
|
|
resp = resp.form.submit()
|
|
assert resp.location.endswith(settings_url)
|
|
resp = resp.follow()
|
|
assert 'Bar' in resp.text
|
|
unavailability_calendar.refresh_from_db()
|
|
assert unavailability_calendar.label == 'Bar'
|
|
assert UnavailabilityCalendarSnapshot.objects.count() == 1
|
|
|
|
|
|
def test_delete_unavailability_calendar(app, admin_user):
|
|
unavailability_calendar = UnavailabilityCalendar.objects.create(label='Foo')
|
|
app = login(app)
|
|
resp = app.get('/manage/unavailability-calendar/%s/settings' % unavailability_calendar.pk)
|
|
resp = resp.click('Delete')
|
|
resp = resp.form.submit()
|
|
assert resp.location.endswith('/manage/unavailability-calendars/')
|
|
resp = resp.follow()
|
|
assert 'Foo' not in resp.text
|
|
assert UnavailabilityCalendar.objects.count() == 0
|
|
assert UnavailabilityCalendarSnapshot.objects.count() == 1
|
|
|
|
|
|
def test_unavailability_calendar_add_time_period_exceptions(app, admin_user):
|
|
unavailability_calendar = UnavailabilityCalendar.objects.create(label='Foo')
|
|
app = login(app)
|
|
resp = app.get('/manage/unavailability-calendar/%s/' % unavailability_calendar.pk)
|
|
resp = resp.click('Settings')
|
|
assert 'There is no unavailabilities yet' in resp.text
|
|
resp = resp.click('Add Unavailability')
|
|
assert 'all_desks' not in resp.form.fields
|
|
today = datetime.datetime.today().replace(hour=0, minute=0, second=0, microsecond=0)
|
|
tomorrow = make_aware(today + datetime.timedelta(days=1))
|
|
resp.form['label'] = 'Exception 1'
|
|
resp.form['start_datetime_0'] = tomorrow.strftime('%Y-%m-%d')
|
|
resp.form['start_datetime_1'] = '08:00'
|
|
resp.form['end_datetime_0'] = tomorrow.strftime('%Y-%m-%d')
|
|
resp.form['end_datetime_1'] = '16:00'
|
|
resp = resp.form.submit().follow()
|
|
assert 'Exception 1' in resp.text
|
|
assert 'Unavailability added.' in resp.text
|
|
assert 'One or several bookings exists within this time slot.' not in resp.text
|
|
assert TimePeriodException.objects.count() == 1
|
|
assert UnavailabilityCalendarSnapshot.objects.count() == 1
|
|
|
|
time_period_exception = TimePeriodException.objects.first()
|
|
assert time_period_exception.unavailability_calendar == unavailability_calendar
|
|
assert time_period_exception.desk is None
|
|
assert time_period_exception.label == 'Exception 1'
|
|
|
|
# info message if new exception overlaps with a booking
|
|
agenda = Agenda.objects.create(label='Agenda')
|
|
desk = Desk.objects.create(label='Desk', agenda=agenda)
|
|
unavailability_calendar.desks.add(desk)
|
|
meeting_type = MeetingType.objects.create(label='Meeting Type', agenda=agenda)
|
|
event = Event.objects.create(
|
|
agenda=agenda,
|
|
places=1,
|
|
desk=desk,
|
|
meeting_type=meeting_type,
|
|
start_datetime=tomorrow.replace(hour=10, minute=30, second=0),
|
|
)
|
|
Booking.objects.create(event=event)
|
|
resp = app.get('/manage/unavailability-calendar/%s/settings' % unavailability_calendar.pk)
|
|
resp = resp.click('Add Unavailability')
|
|
resp.form['label'] = 'Exception 2'
|
|
resp.form['start_datetime_0'] = tomorrow.strftime('%Y-%m-%d')
|
|
resp.form['start_datetime_1'] = '08:00'
|
|
resp.form['end_datetime_0'] = tomorrow.strftime('%Y-%m-%d')
|
|
resp.form['end_datetime_1'] = '16:00'
|
|
resp = resp.form.submit().follow()
|
|
assert TimePeriodException.objects.count() == 2
|
|
assert 'Exception 2' in resp.text
|
|
assert 'Unavailability added.' in resp.text
|
|
assert 'One or several bookings exists within this time slot.' in resp.text
|
|
|
|
|
|
@pytest.mark.freeze_time('2021-03-20 12:12')
|
|
def test_unavailability_calendar_edit_time_period_exceptions(app, admin_user):
|
|
unavailability_calendar = UnavailabilityCalendar.objects.create(label='Foo')
|
|
time_period_exception = TimePeriodException.objects.create(
|
|
unavailability_calendar=unavailability_calendar,
|
|
label='Exception 1',
|
|
start_datetime=now() - datetime.timedelta(days=2),
|
|
end_datetime=now() - datetime.timedelta(days=1),
|
|
)
|
|
|
|
app = login(app)
|
|
resp = app.get('/manage/unavailability-calendar/%s/settings' % unavailability_calendar.pk)
|
|
assert 'Exception 1' in resp.text
|
|
resp = resp.click(href='/manage/time-period-exceptions/%s/edit' % time_period_exception.pk)
|
|
assert 'all_desks' not in resp.form.fields
|
|
resp.form['label'] = 'Exception foo'
|
|
resp = resp.form.submit().follow()
|
|
assert 'Exception foo' in resp.text
|
|
time_period_exception.refresh_from_db()
|
|
assert time_period_exception.label == 'Exception foo'
|
|
assert UnavailabilityCalendarSnapshot.objects.count() == 1
|
|
|
|
# with an error
|
|
resp = app.get('/manage/time-period-exceptions/%s/edit' % time_period_exception.pk)
|
|
resp.form['start_datetime_0'] = now().strftime('%Y-%m-%d')
|
|
resp.form['end_datetime_0'] = now().strftime('%Y-%m-%d')
|
|
resp = resp.form.submit()
|
|
assert '<ul class="errorlist">' in resp.text
|
|
|
|
|
|
def test_unavailability_calendar_delete_time_period_exceptions(app, admin_user):
|
|
unavailability_calendar = UnavailabilityCalendar.objects.create(label='Foo')
|
|
time_period_exception = TimePeriodException.objects.create(
|
|
unavailability_calendar=unavailability_calendar,
|
|
label='Exception 1',
|
|
start_datetime=now() - datetime.timedelta(days=2),
|
|
end_datetime=now() - datetime.timedelta(days=1),
|
|
)
|
|
|
|
app = login(app)
|
|
resp = app.get('/manage/unavailability-calendar/%s/settings' % unavailability_calendar.pk)
|
|
assert 'Exception 1' in resp.text
|
|
resp = resp.click(href='/manage/time-period-exceptions/%s/delete' % time_period_exception.pk)
|
|
resp = resp.form.submit().follow()
|
|
assert 'Exception foo' not in resp.text
|
|
assert unavailability_calendar.timeperiodexception_set.count() == 0
|
|
assert UnavailabilityCalendarSnapshot.objects.count() == 1
|
|
|
|
|
|
def test_unavailability_calendar_import_time_period_exception_from_ics(app, admin_user):
|
|
calendar = UnavailabilityCalendar.objects.create(label='Example')
|
|
login(app)
|
|
resp = app.get('/manage/unavailability-calendar/%d/settings' % calendar.pk)
|
|
assert 'Manage unavailabilities from ICS' in resp.text
|
|
resp = resp.click('Manage unavailabilities')
|
|
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
|
|
assert TimePeriodExceptionSource.objects.filter(unavailability_calendar=calendar).count() == 0
|
|
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
|
|
assert TimePeriodExceptionSource.objects.filter(unavailability_calendar=calendar).count() == 0
|
|
|
|
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/unavailability-calendar/%s/import-unavailabilities/' % calendar.pk)
|
|
resp.form['ics_file'] = Upload('exceptions.ics', ics_with_exceptions, 'text/calendar')
|
|
resp = resp.form.submit(status=302)
|
|
assert TimePeriodException.objects.filter(unavailability_calendar=calendar).count() == 1
|
|
assert TimePeriodExceptionSource.objects.filter(unavailability_calendar=calendar).count() == 1
|
|
source = calendar.timeperiodexceptionsource_set.get()
|
|
exception = calendar.timeperiodexception_set.get()
|
|
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 'Exceptions will be imported in a few minutes.' in resp.text
|
|
assert UnavailabilityCalendarSnapshot.objects.count() == 1
|
|
|
|
|
|
@mock.patch('chrono.agendas.models.requests.get')
|
|
def test_unavailability_calendar_import_time_period_exception_with_remote_ics(mocked_get, app, admin_user):
|
|
calendar = UnavailabilityCalendar.objects.create(label='Example')
|
|
login(app)
|
|
resp = app.get('/manage/unavailability-calendar/%s/import-unavailabilities/' % calendar.pk)
|
|
|
|
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(unavailability_calendar=calendar).count() == 1
|
|
assert TimePeriodExceptionSource.objects.filter(unavailability_calendar=calendar).count() == 1
|
|
source = calendar.timeperiodexceptionsource_set.get()
|
|
exception = calendar.timeperiodexception_set.get()
|
|
assert exception.source == source
|
|
assert source.ics_filename is None
|
|
assert source.ics_file.name == ''
|
|
assert source.ics_url == 'http://example.com/foo.ics'
|
|
|
|
|
|
def test_unavailability_calendar_delete_time_period_exception_source(app, admin_user):
|
|
calendar = UnavailabilityCalendar.objects.create(label='Example')
|
|
source1 = TimePeriodExceptionSource.objects.create(
|
|
unavailability_calendar=calendar, ics_url='https://example.com/test.ics'
|
|
)
|
|
TimePeriodException.objects.create(
|
|
unavailability_calendar=calendar,
|
|
source=source1,
|
|
start_datetime=now() - datetime.timedelta(days=1),
|
|
end_datetime=now() + datetime.timedelta(days=1),
|
|
)
|
|
source2 = TimePeriodExceptionSource.objects.create(
|
|
unavailability_calendar=calendar, ics_url='https://example.com/test.ics'
|
|
)
|
|
TimePeriodException.objects.create(
|
|
unavailability_calendar=calendar,
|
|
source=source2,
|
|
start_datetime=now() - datetime.timedelta(days=1),
|
|
end_datetime=now() + datetime.timedelta(days=1),
|
|
)
|
|
|
|
login(app)
|
|
resp = app.get('/manage/time-period-exceptions-source/%d/delete' % source2.pk)
|
|
resp = resp.form.submit()
|
|
assert TimePeriodException.objects.count() == 1
|
|
assert TimePeriodExceptionSource.objects.count() == 1
|
|
assert source1.timeperiodexception_set.count() == 1
|
|
assert TimePeriodExceptionSource.objects.filter(pk=source2.pk).exists() is False
|
|
assert UnavailabilityCalendarSnapshot.objects.count() == 1
|
|
|
|
|
|
def test_unavailability_calendar_replace_time_period_exception_source(app, admin_user, freezer):
|
|
freezer.move_to('2019-12-01')
|
|
calendar = UnavailabilityCalendar.objects.create(label='Example')
|
|
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/unavailability-calendar/%s/import-unavailabilities/' % calendar.pk)
|
|
resp.form['ics_file'] = Upload('exceptions.ics', ics_file_content, 'text/calendar')
|
|
resp = resp.form.submit(status=302).follow()
|
|
assert TimePeriodException.objects.filter(unavailability_calendar=calendar).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
|
|
assert UnavailabilityCalendarSnapshot.objects.count() == 1
|
|
|
|
# replace the source
|
|
resp = app.get('/manage/time-period-exceptions-source/%d/replace' % source.pk)
|
|
resp.form['ics_newfile'] = Upload('exceptions-bis.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 source.ics_filename == 'exceptions-bis.ics'
|
|
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
|
|
assert UnavailabilityCalendarSnapshot.objects.count() == 2
|
|
|
|
|
|
@mock.patch('chrono.agendas.models.requests.get')
|
|
def test_unavailability_calendar_refresh_time_period_exception_source(mocked_get, app, admin_user):
|
|
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
|
|
|
|
calendar = UnavailabilityCalendar.objects.create(label='Example')
|
|
|
|
login(app)
|
|
# import a source from an url
|
|
resp = app.get('/manage/unavailability-calendar/%d/settings' % calendar.pk)
|
|
resp = resp.click('Manage unavailabilities')
|
|
resp.form['ics_url'] = 'http://example.com/foo.ics'
|
|
resp = resp.form.submit(status=302).follow()
|
|
assert TimePeriodException.objects.filter(unavailability_calendar=calendar).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/unavailability-calendar/%d/settings' % calendar.pk)
|
|
resp = resp.click('Manage unavailabilities')
|
|
resp = resp.click(href='/manage/time-period-exceptions-source/%d/refresh' % source.pk)
|
|
assert TimePeriodException.objects.count() == 1
|
|
new_exceptions = list(source.timeperiodexception_set.order_by('pk'))
|
|
assert exceptions[0].pk != new_exceptions[0].pk
|
|
|
|
|
|
def test_unavailability_calendar_in_desk(app, admin_user):
|
|
app = login(app)
|
|
unavailability_calendar = UnavailabilityCalendar.objects.create(label='Calendar')
|
|
today = localtime(now().replace(hour=0, minute=0, second=0, microsecond=0))
|
|
tomorrow = today + datetime.timedelta(days=1)
|
|
TimePeriodException.objects.create(
|
|
unavailability_calendar=unavailability_calendar,
|
|
start_datetime=tomorrow,
|
|
end_datetime=tomorrow + datetime.timedelta(days=2),
|
|
label='what',
|
|
)
|
|
agenda = Agenda.objects.create(label='Agenda', kind='meetings')
|
|
desk = Desk.objects.create(agenda=agenda, label='desk')
|
|
desk2 = desk.duplicate()
|
|
assert not desk.unavailability_calendars.exists()
|
|
assert not desk2.unavailability_calendars.exists()
|
|
exceptions_url = '/manage/agendas/desk/%s/import-exceptions-from-ics/' % desk.pk
|
|
resp = app.get(exceptions_url)
|
|
assert 'calendar' in resp.text
|
|
assert 'enable' in resp.text
|
|
resp = resp.click(
|
|
href='/manage/desk/%s/unavailability-calendar/%s/toggle/' % (desk.pk, unavailability_calendar.pk)
|
|
)
|
|
settings_url = '/manage/agendas/%s/settings#open:time-periods' % agenda.pk
|
|
assert resp.location.endswith(settings_url)
|
|
# exception from calendar displayed on the settings page
|
|
resp = app.get(settings_url)
|
|
assert 'what' in resp.text
|
|
assert 'One or several bookings overlap with exceptions.' not in resp.text
|
|
assert AgendaSnapshot.objects.count() == 1
|
|
|
|
resp = app.get(exceptions_url)
|
|
assert 'calendar' in resp.text
|
|
assert 'disable' in resp.text
|
|
assert desk.unavailability_calendars.get(pk=unavailability_calendar.pk)
|
|
assert not desk2.unavailability_calendars.exists()
|
|
|
|
# reset
|
|
resp = resp.click(
|
|
href='/manage/desk/%s/unavailability-calendar/%s/toggle/' % (desk.pk, unavailability_calendar.pk)
|
|
)
|
|
assert resp.location.endswith('/manage/agendas/%s/settings#open:time-periods' % agenda.pk)
|
|
resp = app.get(exceptions_url)
|
|
assert 'calendar' in resp.text
|
|
assert 'enable' in resp.text
|
|
assert not desk.unavailability_calendars.exists()
|
|
assert AgendaSnapshot.objects.count() == 2
|
|
|
|
# info message if some exceptions overlaps with a booking
|
|
meeting_type = MeetingType.objects.create(label='Meeting Type', agenda=agenda)
|
|
event = Event.objects.create(
|
|
agenda=agenda,
|
|
places=1,
|
|
desk=desk,
|
|
meeting_type=meeting_type,
|
|
start_datetime=tomorrow.replace(hour=10, minute=30, second=0),
|
|
)
|
|
Booking.objects.create(event=event)
|
|
resp = app.get(exceptions_url)
|
|
assert 'calendar' in resp.text
|
|
assert 'enable' in resp.text
|
|
resp = resp.click(
|
|
href='/manage/desk/%s/unavailability-calendar/%s/toggle/' % (desk.pk, unavailability_calendar.pk)
|
|
)
|
|
assert resp.location.endswith('/manage/agendas/%s/settings#open:time-periods' % agenda.pk)
|
|
resp = resp.follow()
|
|
assert 'One or several bookings overlap with exceptions.' in resp.text
|
|
|
|
|
|
def test_unavailability_calendar_in_desk_desk_simple_management(app, admin_user):
|
|
unavailability_calendar = UnavailabilityCalendar.objects.create(label='Calendar')
|
|
today = localtime(now().replace(hour=0, minute=0, second=0, microsecond=0))
|
|
tomorrow = today + datetime.timedelta(days=1)
|
|
TimePeriodException.objects.create(
|
|
unavailability_calendar=unavailability_calendar,
|
|
start_datetime=tomorrow,
|
|
end_datetime=tomorrow + datetime.timedelta(days=2),
|
|
label='what',
|
|
)
|
|
agenda = Agenda.objects.create(label='Agenda', kind='meetings', desk_simple_management=True)
|
|
desk = Desk.objects.create(agenda=agenda, label='desk')
|
|
desk2 = desk.duplicate()
|
|
assert not desk.unavailability_calendars.exists()
|
|
assert not desk2.unavailability_calendars.exists()
|
|
assert agenda.is_available_for_simple_management() is True
|
|
|
|
meeting_type = MeetingType.objects.create(label='Meeting Type', agenda=agenda)
|
|
event = Event.objects.create(
|
|
agenda=agenda,
|
|
places=1,
|
|
desk=desk2,
|
|
meeting_type=meeting_type,
|
|
start_datetime=tomorrow.replace(hour=10, minute=30, second=0),
|
|
)
|
|
Booking.objects.create(event=event)
|
|
|
|
login(app)
|
|
|
|
resp = app.get(
|
|
'/manage/desk/%s/unavailability-calendar/%s/toggle/' % (desk.pk, unavailability_calendar.pk)
|
|
)
|
|
assert desk.unavailability_calendars.exists()
|
|
assert desk2.unavailability_calendars.exists()
|
|
assert agenda.is_available_for_simple_management() is True
|
|
resp = resp.follow()
|
|
assert 'One or several bookings overlap with exceptions.' in resp.text
|
|
assert AgendaSnapshot.objects.count() == 1
|
|
|
|
app.get('/manage/desk/%s/unavailability-calendar/%s/toggle/' % (desk.pk, unavailability_calendar.pk))
|
|
assert not desk.unavailability_calendars.exists()
|
|
assert not desk2.unavailability_calendars.exists()
|
|
assert agenda.is_available_for_simple_management() is True
|
|
assert AgendaSnapshot.objects.count() == 2
|
|
|
|
# should not happen: unavailability_calendar is not in the correct state
|
|
desk2.unavailability_calendars.add(unavailability_calendar)
|
|
assert not desk.unavailability_calendars.exists()
|
|
assert desk2.unavailability_calendars.exists()
|
|
assert agenda.is_available_for_simple_management() is False
|
|
app.get('/manage/desk/%s/unavailability-calendar/%s/toggle/' % (desk.pk, unavailability_calendar.pk))
|
|
assert desk.unavailability_calendars.exists()
|
|
assert desk2.unavailability_calendars.exists()
|
|
assert agenda.is_available_for_simple_management() is True
|
|
desk2.unavailability_calendars.remove(unavailability_calendar)
|
|
assert desk.unavailability_calendars.exists()
|
|
assert not desk2.unavailability_calendars.exists()
|
|
assert agenda.is_available_for_simple_management() is False
|
|
app.get('/manage/desk/%s/unavailability-calendar/%s/toggle/' % (desk.pk, unavailability_calendar.pk))
|
|
assert not desk.unavailability_calendars.exists()
|
|
assert not desk2.unavailability_calendars.exists()
|
|
assert agenda.is_available_for_simple_management() is True
|
|
|
|
|
|
def test_unavailability_calendar_exception_in_desk(app, admin_user):
|
|
unavailability_calendar = UnavailabilityCalendar.objects.create(label='Calendar')
|
|
start_datetime = localtime(now()) + datetime.timedelta(days=1)
|
|
TimePeriodException.objects.create(
|
|
unavailability_calendar=unavailability_calendar,
|
|
start_datetime=start_datetime,
|
|
end_datetime=localtime(now()) + datetime.timedelta(days=2),
|
|
label='exception foo bar',
|
|
)
|
|
agenda = Agenda.objects.create(label='Agenda', kind='meetings')
|
|
desk1 = Desk.objects.create(agenda=agenda, label='desk 1')
|
|
desk2 = Desk.objects.create(agenda=agenda, label='desk 2')
|
|
desk3 = Desk.objects.create(agenda=agenda, label='desk 3')
|
|
desk1.unavailability_calendars.add(unavailability_calendar)
|
|
desk2.unavailability_calendars.add(unavailability_calendar)
|
|
desk3.unavailability_calendars.add(unavailability_calendar)
|
|
|
|
app = login(app)
|
|
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
|
|
assert resp.text.count('exception foo bar') == 3 # displayed just once per desk
|
|
|
|
|
|
def test_unavailability_calendar_homepage_permission(app, manager_user):
|
|
unavailability_calendar = UnavailabilityCalendar.objects.create(label='Calendar 1')
|
|
app = login(app, username='manager', password='manager')
|
|
resp = app.get('/manage/', status=403)
|
|
group = manager_user.groups.all()[0]
|
|
unavailability_calendar.view_role = group
|
|
unavailability_calendar.edit_role = None
|
|
unavailability_calendar.save()
|
|
resp = app.get('/manage/', status=302)
|
|
resp = resp.follow()
|
|
assert 'Calendar 1' in resp.text
|
|
|
|
agenda = Agenda.objects.create(label='Agenda', kind='meetings')
|
|
agenda.view_role = group
|
|
agenda.save()
|
|
resp = app.get('/manage/')
|
|
assert 'Unavailability calendars' in resp.text
|
|
|
|
unavailability_calendar.view_role = None
|
|
unavailability_calendar.save()
|
|
resp = app.get('/manage/')
|
|
assert 'Unavailability calendars' not in resp.text
|
|
|
|
|
|
def test_unavailability_calendar_list_permissions(app, manager_user):
|
|
unavailability_calendar = UnavailabilityCalendar.objects.create(label='Calendar 1')
|
|
app = login(app, username='manager', password='manager')
|
|
app.get('/manage/unavailability-calendars/', status=403)
|
|
group = manager_user.groups.all()[0]
|
|
unavailability_calendar.view_role = group
|
|
unavailability_calendar.edit_role = None
|
|
unavailability_calendar.save()
|
|
resp = app.get('/manage/unavailability-calendars/')
|
|
assert 'Calendar 1' in resp.text
|
|
assert 'New' not in resp.text
|
|
unavailability_calendar.view_role = None
|
|
unavailability_calendar.edit_role = group
|
|
unavailability_calendar.save()
|
|
assert 'Calendar 1' in resp.text
|
|
assert 'New' not in resp.text
|
|
|
|
|
|
def test_unavailability_calendar_add_permissions(app, manager_user):
|
|
app = login(app, username='manager', password='manager')
|
|
url = '/manage/unavailability-calendar/add/'
|
|
app.get(url, status=403)
|
|
|
|
|
|
def test_unavailability_calendar_detail_permissions(app, manager_user):
|
|
unavailability_calendar = UnavailabilityCalendar.objects.create(label='Calendar 1')
|
|
app = login(app, username='manager', password='manager')
|
|
detail_url = '/manage/unavailability-calendar/%s/' % unavailability_calendar.pk
|
|
resp = app.get(detail_url, status=403)
|
|
group = manager_user.groups.all()[0]
|
|
unavailability_calendar.view_role = group
|
|
unavailability_calendar.edit_role = None
|
|
unavailability_calendar.save()
|
|
resp = app.get(detail_url)
|
|
assert 'Settings' not in resp.text
|
|
unavailability_calendar.view_role = None
|
|
unavailability_calendar.edit_role = group
|
|
unavailability_calendar.save()
|
|
resp = app.get(detail_url)
|
|
assert 'Settings' in resp.text
|
|
|
|
|
|
def test_unavailability_calendar_edit_permissions(app, manager_user):
|
|
unavailability_calendar = UnavailabilityCalendar.objects.create(label='Calendar 1')
|
|
app = login(app, username='manager', password='manager')
|
|
url = '/manage/unavailability-calendar/%s/edit/' % unavailability_calendar.pk
|
|
app.get(url, status=403)
|
|
group = manager_user.groups.all()[0]
|
|
unavailability_calendar.view_role = group
|
|
unavailability_calendar.edit_role = None
|
|
unavailability_calendar.save()
|
|
app.get(url, status=403)
|
|
unavailability_calendar.view_role = None
|
|
unavailability_calendar.edit_role = group
|
|
unavailability_calendar.save()
|
|
app.get(url)
|
|
|
|
|
|
def test_unavailability_calendar_delete_permissions(app, manager_user):
|
|
unavailability_calendar = UnavailabilityCalendar.objects.create(label='Calendar 1')
|
|
app = login(app, username='manager', password='manager')
|
|
url = '/manage/unavailability-calendar/%s/delete/' % unavailability_calendar.pk
|
|
app.get(url, status=403)
|
|
group = manager_user.groups.all()[0]
|
|
unavailability_calendar.view_role = group
|
|
unavailability_calendar.edit_role = None
|
|
unavailability_calendar.save()
|
|
app.get(url, status=403)
|
|
unavailability_calendar.view_role = None
|
|
unavailability_calendar.edit_role = group
|
|
unavailability_calendar.save()
|
|
app.get(url, status=403)
|
|
|
|
|
|
def test_unavailability_calendar_settings_permissions(app, manager_user):
|
|
unavailability_calendar = UnavailabilityCalendar.objects.create(label='Calendar 1')
|
|
app = login(app, username='manager', password='manager')
|
|
settings_url = '/manage/unavailability-calendar/%s/settings' % unavailability_calendar.pk
|
|
app.get(settings_url, status=403)
|
|
group = manager_user.groups.all()[0]
|
|
unavailability_calendar.view_role = group
|
|
unavailability_calendar.edit_role = None
|
|
unavailability_calendar.save()
|
|
app.get(settings_url, status=403)
|
|
unavailability_calendar.view_role = None
|
|
unavailability_calendar.edit_role = group
|
|
unavailability_calendar.save()
|
|
app.get(settings_url)
|
|
|
|
|
|
def test_unavailability_calendar_add_unavailability_permissions(app, manager_user):
|
|
unavailability_calendar = UnavailabilityCalendar.objects.create(label='Calendar 1')
|
|
app = login(app, username='manager', password='manager')
|
|
url = '/manage/unavailability-calendar/%s/add-unavailability' % unavailability_calendar.pk
|
|
app.get(url, status=403)
|
|
group = manager_user.groups.all()[0]
|
|
unavailability_calendar.view_role = group
|
|
unavailability_calendar.edit_role = None
|
|
unavailability_calendar.save()
|
|
app.get(url, status=403)
|
|
unavailability_calendar.view_role = None
|
|
unavailability_calendar.edit_role = group
|
|
unavailability_calendar.save()
|
|
app.get(url)
|
|
|
|
|
|
def test_unavailability_calendar_edit_unavailability_permissions(app, manager_user):
|
|
unavailability_calendar = UnavailabilityCalendar.objects.create(label='Calendar 1')
|
|
time_period_exception = TimePeriodException.objects.create(
|
|
unavailability_calendar=unavailability_calendar,
|
|
start_datetime=now() - datetime.timedelta(days=2),
|
|
end_datetime=now() - datetime.timedelta(days=1),
|
|
)
|
|
app = login(app, username='manager', password='manager')
|
|
url = '/manage/time-period-exceptions/%s/edit' % time_period_exception.pk
|
|
app.get(url, status=403)
|
|
group = manager_user.groups.all()[0]
|
|
unavailability_calendar.view_role = group
|
|
unavailability_calendar.edit_role = None
|
|
unavailability_calendar.save()
|
|
app.get(url, status=403)
|
|
unavailability_calendar.view_role = None
|
|
unavailability_calendar.edit_role = group
|
|
unavailability_calendar.save()
|
|
app.get(url)
|
|
|
|
|
|
def test_unavailability_calendar_delete_unavailability_permissions(app, manager_user):
|
|
unavailability_calendar = UnavailabilityCalendar.objects.create(label='Calendar 1')
|
|
time_period_exception = TimePeriodException.objects.create(
|
|
unavailability_calendar=unavailability_calendar,
|
|
start_datetime=now() - datetime.timedelta(days=2),
|
|
end_datetime=now() - datetime.timedelta(days=1),
|
|
)
|
|
app = login(app, username='manager', password='manager')
|
|
url = '/manage/time-period-exceptions/%s/delete' % time_period_exception.pk
|
|
app.get(url, status=403)
|
|
group = manager_user.groups.all()[0]
|
|
unavailability_calendar.view_role = group
|
|
unavailability_calendar.edit_role = None
|
|
unavailability_calendar.save()
|
|
app.get(url, status=403)
|
|
unavailability_calendar.view_role = None
|
|
unavailability_calendar.edit_role = group
|
|
unavailability_calendar.save()
|
|
app.get(url)
|
|
|
|
|
|
def test_inspect_unavailability_calendar(app, admin_user):
|
|
unavailability_calendar = UnavailabilityCalendar.objects.create(label='Calendar 1')
|
|
TimePeriodException.objects.create(
|
|
unavailability_calendar=unavailability_calendar,
|
|
start_datetime=now() - datetime.timedelta(days=2),
|
|
end_datetime=now() - datetime.timedelta(days=1),
|
|
)
|
|
|
|
app = login(app)
|
|
|
|
resp = app.get('/manage/unavailability-calendar/%s/settings' % unavailability_calendar.pk)
|
|
with CaptureQueriesContext(connection) as ctx:
|
|
resp = resp.click('Inspect')
|
|
assert len(ctx.captured_queries) == 4
|
|
|
|
|
|
def test_inspect_unavailability_calendar_as_manager(app, manager_user):
|
|
unavailability_calendar = UnavailabilityCalendar.objects.create(label='Calendar 1')
|
|
|
|
app = login(app, username='manager', password='manager')
|
|
unavailability_calendar.view_role = manager_user.groups.all()[0]
|
|
unavailability_calendar.save()
|
|
app.get('/manage/unavailability-calendar/%s/inspect/' % unavailability_calendar.pk, status=403)
|
|
|
|
unavailability_calendar.edit_role = manager_user.groups.all()[0]
|
|
unavailability_calendar.save()
|
|
app.get('/manage/unavailability-calendar/%s/inspect/' % unavailability_calendar.pk, status=200)
|