chrono/tests/manager/test_unavailability_calenda...

599 lines
26 KiB
Python

# -*- coding: utf-8 -*-
import copy
import datetime
import json
import freezegun
import pytest
from django.utils.encoding import force_text
from django.utils.timezone import localtime, make_aware, now
from webtest import Upload
from chrono.agendas.models import (
Agenda,
Booking,
Desk,
Event,
MeetingType,
TimePeriodException,
UnavailabilityCalendar,
)
from .test_all import login
pytestmark = pytest.mark.django_db
def test_import_unavailability_calendar(app, admin_user):
calendar = UnavailabilityCalendar.objects.create(label=u'Foo bar')
app = login(app)
with freezegun.freeze_time('2020-06-15'):
resp = app.get('/manage/unavailability-calendar/%s/export' % calendar.id)
assert resp.headers['content-type'] == 'application/json'
assert (
resp.headers['content-disposition']
== 'attachment; filename="export_unavailability-calendar_foo-bar_20200615.json"'
)
calendar_export = resp.text
# empty json
resp = app.get('/manage/', status=200)
resp = resp.click('Import')
resp.form['agendas_json'] = Upload('export.json', b'{}', 'application/json')
resp = resp.form.submit().follow()
assert 'No data found.' in resp.text
# existing unavailability calendar
resp = app.get('/manage/', status=200)
resp = resp.click('Import')
resp.form['agendas_json'] = Upload('export.json', calendar_export.encode('utf-8'), 'application/json')
resp = resp.form.submit().follow()
assert 'No unavailability calendar created. An unavailability calendar has been updated.' in resp.text
assert UnavailabilityCalendar.objects.count() == 1
# new unavailability calendar
UnavailabilityCalendar.objects.all().delete()
resp = app.get('/manage/', status=200)
resp = resp.click('Import')
resp.form['agendas_json'] = Upload('export.json', calendar_export.encode('utf-8'), 'application/json')
resp = resp.form.submit().follow()
assert 'An unavailability calendar has been created. No unavailability calendar updated.' in resp.text
assert UnavailabilityCalendar.objects.count() == 1
# multiple unavailability calendars
calendars = json.loads(calendar_export)
calendars['unavailability_calendars'].append(copy.copy(calendars['unavailability_calendars'][0]))
calendars['unavailability_calendars'].append(copy.copy(calendars['unavailability_calendars'][0]))
calendars['unavailability_calendars'][1]['label'] = 'Foo bar 2'
calendars['unavailability_calendars'][1]['slug'] = 'foo-bar-2'
calendars['unavailability_calendars'][2]['label'] = 'Foo bar 3'
calendars['unavailability_calendars'][2]['slug'] = 'foo-bar-3'
resp = app.get('/manage/', status=200)
resp = resp.click('Import')
resp.form['agendas_json'] = Upload(
'export.json', json.dumps(calendars).encode('utf-8'), 'application/json'
)
resp = resp.form.submit().follow()
assert (
'2 unavailability calendars have been created. An unavailability calendar has been updated.'
in resp.text
)
assert UnavailabilityCalendar.objects.count() == 3
UnavailabilityCalendar.objects.all().delete()
resp = app.get('/manage/', status=200)
resp = resp.click('Import')
resp.form['agendas_json'] = Upload(
'export.json', json.dumps(calendars).encode('utf-8'), 'application/json'
)
resp = resp.form.submit().follow()
assert '3 unavailability calendars have been created. No unavailability calendar updated.' in resp.text
assert UnavailabilityCalendar.objects.count() == 3
# reference to unknown group
calendar_export_dict = json.loads(force_text(calendar_export))
calendar_export_dict['unavailability_calendars'][0]['permissions']['view'] = u'gé1'
calendar_export = json.dumps(calendar_export_dict).encode('utf-8')
UnavailabilityCalendar.objects.all().delete()
resp = app.get('/manage/', status=200)
resp = resp.click('Import')
resp.form['agendas_json'] = Upload('export.json', calendar_export, 'application/json')
resp = resp.form.submit()
assert u'Missing roles: "gé1"' in resp.text
del calendar_export_dict['unavailability_calendars'][0]['permissions']['view']
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
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'
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
def test_unavailability_calendar_add_time_period_exeptions(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
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_exeptions(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'
# 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_exeptions(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
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' % 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
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' % agenda.pk)
resp = app.get(exceptions_url)
assert 'calendar' in resp.text
assert 'enable' in resp.text
assert not desk.unavailability_calendars.exists()
# 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' % 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
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
# 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=403)
resp = resp.click('Unavailability calendars')
unavailability_calendar.view_role = None
unavailability_calendar.edit_role = group
unavailability_calendar.save()
resp = app.get('/manage/', status=403)
resp = resp.click('Unavailability calendars')
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)