chrono/tests/test_import_export.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

1013 lines
39 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import copy
import datetime
import json
import os
import shutil
import sys
import tempfile
2019-09-21 22:36:08 +02:00
from io import StringIO
import mock
import pytest
from django.contrib.auth.models import Group
from django.core.management import CommandError, call_command
from django.test import override_settings
from django.utils.encoding import force_bytes
2020-07-21 16:38:14 +02:00
from django.utils.timezone import make_aware, now
from chrono.agendas.models import (
AbsenceReason,
AbsenceReasonGroup,
Agenda,
AgendaImportError,
AgendaNotificationsSettings,
AgendaReminderSettings,
2020-07-24 15:59:49 +02:00
Category,
Desk,
Event,
MeetingType,
Resource,
TimePeriod,
TimePeriodException,
TimePeriodExceptionSource,
UnavailabilityCalendar,
VirtualMember,
)
from chrono.manager.utils import import_site
pytestmark = pytest.mark.django_db
def get_output_of_command(command, *args, **kwargs):
old_stdout = sys.stdout
output = sys.stdout = StringIO()
call_command(command, *args, **kwargs)
sys.stdout = old_stdout
return output.getvalue()
2020-07-21 16:38:14 +02:00
def test_import_export(app):
agenda_events = Agenda.objects.create(label='Events Agenda', kind='events')
first_event = Event.objects.create(
agenda=agenda_events, start_datetime=make_aware(datetime.datetime(2020, 7, 21, 16, 42, 35)), places=10
)
agenda_meetings = Agenda.objects.create(label='Meetings Agenda', kind='meetings')
MeetingType.objects.create(agenda=agenda_meetings, label='Meeting Type', duration=30)
desk = Desk.objects.create(agenda=agenda_meetings, label='Desk')
exceptions_desk = Desk.objects.create(agenda=agenda_events, slug='_exceptions_holder')
tpx_start = make_aware(datetime.datetime(2017, 5, 22, 8, 0))
tpx_end = make_aware(datetime.datetime(2017, 5, 22, 12, 30))
TimePeriodException.objects.create(desk=desk, start_datetime=tpx_start, end_datetime=tpx_end)
TimePeriodException.objects.create(desk=exceptions_desk, start_datetime=tpx_start, end_datetime=tpx_end)
output = get_output_of_command('export_site')
2020-07-21 16:38:14 +02:00
assert len(json.loads(output)['agendas']) == 2
import_site(data={}, clean=True)
empty_output = get_output_of_command('export_site')
assert len(json.loads(empty_output)['agendas']) == 0
Agenda(label=u'test').save()
old_stdin = sys.stdin
sys.stdin = StringIO(json.dumps({}))
assert Agenda.objects.count() == 1
try:
call_command('import_site', '-', clean=True)
finally:
sys.stdin = old_stdin
assert Agenda.objects.count() == 0
with tempfile.NamedTemporaryFile() as f:
f.write(force_bytes(output))
f.flush()
call_command('import_site', f.name)
2020-07-21 16:38:14 +02:00
assert Agenda.objects.count() == 2
first_imported_event = Agenda.objects.get(label='Events Agenda').event_set.first()
assert first_imported_event.start_datetime == first_event.start_datetime
assert TimePeriodException.objects.get(desk__agenda__kind='meetings').start_datetime == tpx_start
assert TimePeriodException.objects.get(desk__agenda__kind='meetings').end_datetime == tpx_end
assert TimePeriodException.objects.get(desk__agenda__kind='events').start_datetime == tpx_start
assert TimePeriodException.objects.get(desk__agenda__kind='events').end_datetime == tpx_end
2020-07-21 16:38:14 +02:00
agenda1 = Agenda.objects.get(label='Events Agenda')
agenda2 = Agenda.objects.get(label='Meetings Agenda')
event = Event(agenda=agenda1, start_datetime=now(), places=10)
event.save()
2017-09-01 15:01:07 +02:00
desk, _ = Desk.objects.get_or_create(agenda=agenda2, label='Desk A', slug='desk-a')
timeperiod = TimePeriod(
desk=desk, weekday=2, start_time=datetime.time(10, 0), end_time=datetime.time(11, 0)
)
timeperiod.save()
exception = TimePeriodException(
desk=desk,
start_datetime=make_aware(datetime.datetime(2017, 5, 22, 8, 0)),
end_datetime=make_aware(datetime.datetime(2017, 5, 22, 12, 30)),
)
exception.save()
import_site(json.loads(output), overwrite=True)
assert Event.objects.filter(id=event.id).count() == 0
2017-09-01 15:01:07 +02:00
assert Desk.objects.filter(slug='desk-a').count() == 0
assert TimePeriod.objects.filter(id=timeperiod.id).count() == 0
assert TimePeriodException.objects.filter(id=exception.id).count() == 0
2020-07-21 16:38:14 +02:00
event = Event(agenda=agenda1, start_datetime=now(), places=10)
event.save()
desk, _ = Desk.objects.get_or_create(agenda=agenda2, label='Desk A', slug='desk-a')
timeperiod = TimePeriod(
weekday=2, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(11, 0)
)
timeperiod.save()
exception = TimePeriodException(
desk=desk,
start_datetime=make_aware(datetime.datetime(2017, 5, 22, 8, 0)),
end_datetime=make_aware(datetime.datetime(2017, 5, 22, 12, 30)),
)
exception.save()
import_site(json.loads(output), overwrite=False)
assert Event.objects.filter(id=event.id).count() == 1
assert TimePeriod.objects.filter(id=timeperiod.id).count() == 1
assert TimePeriodException.objects.filter(id=exception.id).count() == 1
import_site(data={}, if_empty=True)
2020-07-21 16:38:14 +02:00
assert Agenda.objects.count() == 2
import_site(data={}, clean=True)
tempdir = tempfile.mkdtemp('chrono-test')
empty_output = get_output_of_command('export_site', output=os.path.join(tempdir, 't.json'))
assert os.path.exists(os.path.join(tempdir, 't.json'))
shutil.rmtree(tempdir)
def test_import_export_events_agenda_options(app):
agenda = Agenda.objects.create(
label='Foo Bar',
kind='events',
default_view='open_events',
booking_form_url='{{ eservices_url }}backoffice/submission/inscription-aux-activites/',
minimal_booking_delay_in_working_days=True,
booking_user_block_template='foo bar',
booking_check_filters='foo,bar',
event_display_template='foo bar',
mark_event_checked_auto=True,
)
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
output = get_output_of_command('export_site')
assert len(json.loads(output)['agendas']) == 1
import_site(data={}, clean=True)
with tempfile.NamedTemporaryFile() as f:
f.write(force_bytes(output))
f.flush()
call_command('import_site', f.name)
assert Agenda.objects.count() == 1
agenda = Agenda.objects.first()
assert agenda.default_view == 'open_events'
assert agenda.booking_form_url == '{{ eservices_url }}backoffice/submission/inscription-aux-activites/'
assert agenda.minimal_booking_delay_in_working_days is True
assert agenda.booking_user_block_template == 'foo bar'
assert agenda.booking_check_filters == 'foo,bar'
assert agenda.event_display_template == 'foo bar'
assert agenda.mark_event_checked_auto is True
2020-07-21 16:38:14 +02:00
def test_import_export_event_details(app):
agenda = Agenda.objects.create(label='Foo Bar', kind='events')
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
2020-07-21 16:38:14 +02:00
Event.objects.create(
2021-05-11 14:20:14 +02:00
slug='event',
2020-07-21 16:38:14 +02:00
agenda=agenda,
description='description',
pricing='100',
url='https://example.net/',
publication_date=datetime.date(2020, 5, 11),
places=42,
start_datetime=now(),
)
2021-05-11 14:20:14 +02:00
# check event (agenda, slug) unicity
agenda2 = Agenda.objects.create(label='Foo Bar 2', kind='events')
Desk.objects.create(agenda=agenda2, slug='_exceptions_holder')
2021-05-11 14:20:14 +02:00
Event.objects.create(
slug='event',
agenda=agenda2,
places=42,
start_datetime=now(),
)
output = get_output_of_command('export_site')
2021-05-11 14:20:14 +02:00
assert len(json.loads(output)['agendas']) == 2
import_site(data={}, clean=True)
with tempfile.NamedTemporaryFile() as f:
f.write(force_bytes(output))
f.flush()
call_command('import_site', f.name)
2021-05-11 14:20:14 +02:00
assert Agenda.objects.count() == 2
assert Event.objects.count() == 2
2020-07-21 16:38:14 +02:00
first_imported_event = Agenda.objects.get(label='Foo Bar').event_set.first()
2021-05-11 14:20:14 +02:00
assert first_imported_event.slug == 'event'
assert first_imported_event.description == 'description'
assert first_imported_event.pricing == '100'
assert first_imported_event.url == 'https://example.net/'
assert first_imported_event.publication_date == datetime.date(2020, 5, 11)
2021-05-11 14:20:14 +02:00
assert Agenda.objects.get(label='Foo Bar 2').event_set.first().slug == 'event'
def test_import_export_recurring_event(app, freezer):
freezer.move_to('2021-01-12 12:10')
agenda = Agenda.objects.create(label='Foo Bar', kind='events')
desk = Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
event = Event.objects.create(
agenda=agenda,
start_datetime=now(),
recurrence_days=list(range(7)),
recurrence_week_interval=2,
places=10,
slug='test',
)
event.refresh_from_db()
event.get_or_create_event_recurrence(event.start_datetime + datetime.timedelta(days=3))
assert Event.objects.count() == 2
output = get_output_of_command('export_site')
assert len(json.loads(output)['agendas']) == 1
import_site(data={}, clean=True)
with tempfile.NamedTemporaryFile() as f:
f.write(force_bytes(output))
f.flush()
call_command('import_site', f.name)
assert Agenda.objects.count() == 1
assert Event.objects.count() == 1
event = Agenda.objects.get(label='Foo Bar').event_set.first()
assert event.primary_event is None
assert event.recurrence_days == list(range(7))
assert event.recurrence_week_interval == 2
# importing event with end recurrence date creates recurrences
event.recurrence_end_date = now() + datetime.timedelta(days=7)
event.recurrence_week_interval = 1
event.save()
output = get_output_of_command('export_site')
import_site(data={}, clean=True)
with tempfile.NamedTemporaryFile() as f:
f.write(force_bytes(output))
f.flush()
call_command('import_site', f.name)
event = Event.objects.get(slug='test')
assert Event.objects.filter(primary_event=event).count() == 7
# import again
with tempfile.NamedTemporaryFile() as f:
f.write(force_bytes(output))
f.flush()
call_command('import_site', f.name)
event = Event.objects.get(slug='test')
assert Event.objects.filter(primary_event=event).count() == 7
# import again but change places
payload = json.loads(output)
payload['agendas'][0]['events'][0]['places'] = 42
with tempfile.NamedTemporaryFile() as f:
f.write(force_bytes(json.dumps(payload)))
f.flush()
call_command('import_site', f.name)
event = Event.objects.get(slug='test')
assert event.places == 42
assert Event.objects.filter(primary_event=event, places=42).count() == 7
def test_import_export_meetings_agenda_options(app):
agenda = Agenda.objects.create(
label='Foo Bar',
kind='meetings',
default_view='month',
)
output = get_output_of_command('export_site')
assert len(json.loads(output)['agendas']) == 1
import_site(data={}, clean=True)
with tempfile.NamedTemporaryFile() as f:
f.write(force_bytes(output))
f.flush()
call_command('import_site', f.name)
assert Agenda.objects.count() == 1
agenda = Agenda.objects.first()
assert agenda.default_view == 'month'
2020-07-21 16:38:14 +02:00
def test_import_export_permissions(app):
meetings_agenda = Agenda.objects.create(label='Foo Bar', kind='meetings')
group1 = Group.objects.create(name=u'gé1')
group2 = Group.objects.create(name=u'gé2')
meetings_agenda.view_role = group1
meetings_agenda.edit_role = group2
meetings_agenda.save()
output = get_output_of_command('export_site')
2020-07-21 16:38:14 +02:00
assert len(json.loads(output)['agendas']) == 1
import_site(data={}, clean=True)
assert Agenda.objects.count() == 0
Group.objects.all().delete()
with pytest.raises(AgendaImportError) as excinfo:
import_site(json.loads(output), overwrite=True)
assert 'gé1' in str(excinfo.value) and 'gé2' in str(excinfo.value)
group1 = Group(name=u'gé1')
group1.save()
with pytest.raises(AgendaImportError) as excinfo:
import_site(json.loads(output), overwrite=True)
assert u'%s' % excinfo.value == u'Missing roles: "gé2"'
with tempfile.NamedTemporaryFile() as f:
f.write(force_bytes(output))
f.flush()
with pytest.raises(CommandError) as excinfo:
call_command('import_site', f.name)
assert u'%s' % excinfo.value == u'Missing roles: "gé2"'
group2 = Group(name=u'gé2')
group2.save()
import_site(json.loads(output), overwrite=True)
agenda = Agenda.objects.get(slug=meetings_agenda.slug)
assert agenda.view_role == group1
assert agenda.edit_role == group2
2020-07-21 16:38:14 +02:00
def test_import_export_resources(app):
meetings_agenda = Agenda.objects.create(label='Foo Bar', kind='meetings')
resource = Resource.objects.create(label='foo')
meetings_agenda.resources.add(resource)
output = get_output_of_command('export_site')
import_site(data={}, clean=True)
assert Agenda.objects.count() == 0
resource.delete()
with pytest.raises(AgendaImportError) as excinfo:
import_site(json.loads(output), overwrite=True)
assert str(excinfo.value) == 'Missing "foo" resource'
resource = Resource.objects.create(label='foobar')
with pytest.raises(AgendaImportError) as excinfo:
import_site(json.loads(output), overwrite=True)
assert str(excinfo.value) == 'Missing "foo" resource'
resource = Resource.objects.create(label='foo')
import_site(json.loads(output), overwrite=True)
agenda = Agenda.objects.get(slug=meetings_agenda.slug)
assert list(agenda.resources.all()) == [resource]
2020-07-24 15:59:49 +02:00
def test_import_export_categorys(app):
category = Category.objects.create(label='foo')
agenda = Agenda.objects.create(label='Foo Bar', category=category)
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
2020-07-24 15:59:49 +02:00
output = get_output_of_command('export_site')
import_site(data={}, clean=True)
assert Agenda.objects.count() == 0
category.delete()
with pytest.raises(AgendaImportError) as excinfo:
import_site(json.loads(output), overwrite=True)
assert str(excinfo.value) == 'Missing "foo" category'
category = Category.objects.create(label='foobar')
with pytest.raises(AgendaImportError) as excinfo:
import_site(json.loads(output), overwrite=True)
assert str(excinfo.value) == 'Missing "foo" category'
category = Category.objects.create(label='foo')
import_site(json.loads(output), overwrite=True)
agenda = Agenda.objects.get(slug=agenda.slug)
assert agenda.category == category
def test_import_export_absence_reasons(app):
group = AbsenceReasonGroup.objects.create(label='foo')
agenda = Agenda.objects.create(label='Foo Bar', kind='events', absence_reasons_group=group)
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
output = get_output_of_command('export_site')
import_site(data={}, clean=True)
assert Agenda.objects.count() == 0
assert AbsenceReasonGroup.objects.count() == 0
data = json.loads(output)
del data['absence_reason_groups']
with pytest.raises(AgendaImportError) as excinfo:
import_site(data, overwrite=True)
assert str(excinfo.value) == 'Missing "foo" absence reasons group'
AbsenceReasonGroup.objects.create(label='foobar')
with pytest.raises(AgendaImportError) as excinfo:
import_site(data, overwrite=True)
assert str(excinfo.value) == 'Missing "foo" absence reasons group'
group = AbsenceReasonGroup.objects.create(label='foo')
import_site(data, overwrite=True)
agenda = Agenda.objects.get(slug=agenda.slug)
assert agenda.absence_reasons_group == group
def test_import_export_virtual_agenda(app):
virtual_agenda = Agenda.objects.create(label='Virtual Agenda', kind='virtual')
output = get_output_of_command('export_site')
payload = json.loads(output)
assert len(payload['agendas']) == 1
virtual_agenda.delete()
import_site(json.loads(output), overwrite=True)
virtual_agenda = Agenda.objects.get(label='Virtual Agenda', slug='virtual-agenda', kind='virtual')
assert virtual_agenda.minimal_booking_delay is None
assert virtual_agenda.maximal_booking_delay is None
assert virtual_agenda.real_agendas.count() == 0
assert virtual_agenda.excluded_timeperiods.count() == 0
# add booking delay
virtual_agenda.minimal_booking_delay = 2
virtual_agenda.maximal_booking_delay = 10
virtual_agenda.save()
output = get_output_of_command('export_site')
payload = json.loads(output)
virtual_agenda.delete()
import_site(json.loads(output), overwrite=True)
virtual_agenda = Agenda.objects.get(label='Virtual Agenda', slug='virtual-agenda', kind='virtual')
assert virtual_agenda.minimal_booking_delay == 2
assert virtual_agenda.maximal_booking_delay == 10
# add excluded timeperiods
tp1 = TimePeriod.objects.create(
agenda=virtual_agenda, weekday=1, start_time=datetime.time(10, 0), end_time=datetime.time(11, 0)
)
tp2 = TimePeriod.objects.create(
agenda=virtual_agenda, weekday=2, start_time=datetime.time(12, 0), end_time=datetime.time(13, 0)
)
output = get_output_of_command('export_site')
payload = json.loads(output)
virtual_agenda.delete()
tp1.delete()
tp2.delete()
import_site(json.loads(output), overwrite=True)
virtual_agenda = Agenda.objects.get(label='Virtual Agenda', slug='virtual-agenda', kind='virtual')
assert virtual_agenda.excluded_timeperiods.count() == 2
tp1 = TimePeriod.objects.get(
agenda=virtual_agenda, weekday=1, start_time=datetime.time(10, 0), end_time=datetime.time(11, 0)
)
tp2 = TimePeriod.objects.get(
agenda=virtual_agenda, weekday=2, start_time=datetime.time(12, 0), end_time=datetime.time(13, 0)
)
def test_import_export_virtual_agenda_with_included_agenda(app):
virtual_agenda = Agenda.objects.create(label='Virtual Agenda', kind='virtual')
foo_agenda = Agenda.objects.create(label='Foo', kind='meetings')
bar_agenda = Agenda.objects.create(label='Bar', kind='meetings')
mt1 = MeetingType.objects.create(agenda=foo_agenda, label='Meeting Type', duration=30)
mt2 = MeetingType.objects.create(agenda=bar_agenda, label='Meeting Type', duration=30)
VirtualMember.objects.create(virtual_agenda=virtual_agenda, real_agenda=foo_agenda)
VirtualMember.objects.create(virtual_agenda=virtual_agenda, real_agenda=bar_agenda)
output = get_output_of_command('export_site')
payload = json.loads(output)
assert len(payload['agendas']) == 3
virtual_agenda.delete()
foo_agenda.delete()
bar_agenda.delete()
mt1.delete()
mt2.delete()
import_site(payload, overwrite=True)
virtual_agenda = Agenda.objects.get(label='Virtual Agenda', slug='virtual-agenda', kind='virtual')
assert virtual_agenda.real_agendas.count() == 2
assert virtual_agenda.real_agendas.filter(label='Foo').count() == 1
assert virtual_agenda.real_agendas.filter(label='Bar').count() == 1
# add incompatible meetingtype
bar_agenda = Agenda.objects.get(label='Bar', kind='meetings')
mt2 = MeetingType.objects.get(agenda=bar_agenda, label='Meeting Type')
mt2.duration = 10
mt2.save()
output = get_output_of_command('export_site')
payload = json.loads(output)
virtual_agenda.delete()
with pytest.raises(AgendaImportError) as excinfo:
import_site(json.loads(output), overwrite=False)
assert (
'This agenda does not have the same meeting types provided by the virtual agenda.'
in '%s' % excinfo.value
)
def test_import_export_virtual_agenda_with_missing_agenda(app):
virtual_agenda = Agenda.objects.create(label='Virtual Agenda', kind='virtual')
foo_agenda = Agenda.objects.create(label='Foo', kind='meetings')
VirtualMember.objects.create(virtual_agenda=virtual_agenda, real_agenda=foo_agenda)
output = get_output_of_command('export_site')
payload = json.loads(output)
del payload['agendas'][0] # remove real agenda
virtual_agenda.delete()
foo_agenda.delete()
with pytest.raises(AgendaImportError) as excinfo:
import_site(payload, overwrite=False)
assert 'The real agenda "foo" does not exist.' in '%s' % excinfo.value
2020-07-21 16:38:14 +02:00
def test_import_export_desk_missing_fields(app):
meetings_agenda = Agenda.objects.create(label='Foo Bar', kind='meetings')
MeetingType.objects.create(agenda=meetings_agenda, label='Meeting Type', duration=30)
desk = Desk.objects.create(agenda=meetings_agenda, label='Desk')
TimePeriod.objects.create(
desk=desk, weekday=2, start_time=datetime.time(10, 0), end_time=datetime.time(11, 0)
)
TimePeriodException.objects.create(
desk=desk,
start_datetime=make_aware(datetime.datetime(2017, 5, 22, 8, 0)),
end_datetime=make_aware(datetime.datetime(2017, 5, 22, 12, 30)),
)
output = get_output_of_command('export_site')
payload = json.loads(output)
del payload['agendas'][0]['desks'][0]['timeperiods']
del payload['agendas'][0]['desks'][0]['exceptions']
Agenda.objects.all().delete()
import_site(payload)
assert TimePeriod.objects.exists() is False
assert TimePeriodException.objects.exists() is False
def test_import_export_unknown_fields(app):
2020-07-21 16:38:14 +02:00
events_agenda = Agenda.objects.create(label='Events Agenda', kind='events')
Desk.objects.create(agenda=events_agenda, slug='_exceptions_holder')
2020-07-21 16:38:14 +02:00
Event.objects.create(agenda=events_agenda, start_datetime=now(), places=10)
meetings_agenda = Agenda.objects.create(label='Meetings Agenda', kind='meetings')
MeetingType.objects.create(agenda=meetings_agenda, label='Meeting Type', duration=30)
Desk.objects.create(agenda=meetings_agenda, label='Desk')
desk = meetings_agenda.desk_set.first()
2020-07-21 16:38:14 +02:00
TimePeriod.objects.create(
desk=desk, weekday=2, start_time=datetime.time(10, 0), end_time=datetime.time(11, 0)
)
TimePeriodException.objects.create(
desk=desk,
start_datetime=make_aware(datetime.datetime(2017, 5, 22, 8, 0)),
end_datetime=make_aware(datetime.datetime(2017, 5, 22, 12, 30)),
)
output = get_output_of_command('export_site')
payload = json.loads(output)
Agenda.objects.all().delete()
assert Agenda.objects.exists() is False
assert MeetingType.objects.exists() is False
assert Desk.objects.exists() is False
assert TimePeriod.objects.exists() is False
assert TimePeriodException.objects.exists() is False
# add unknown fields everywhere
2020-07-21 16:38:14 +02:00
payload['agendas'][0]['unknown_field'] = 'foobar'
payload['agendas'][0]['events'][0]['unknown_field'] = 'foobar'
payload['agendas'][0]['real_agendas'] = ['foobar'] # not available for a non virtual agenda
2020-07-21 16:38:14 +02:00
payload['agendas'][1]['unknown_field'] = 'foobar'
payload['agendas'][1]['meetingtypes'][0]['unknown_field'] = 'foobar'
payload['agendas'][1]['desks'][0]['unknown_field'] = 'foobar'
payload['agendas'][1]['desks'][0]['timeperiods'][0]['unknown_field'] = 'foobar'
payload['agendas'][1]['desks'][0]['exceptions'][0]['unknown_field'] = 'foobar'
import_site(payload)
assert Agenda.objects.exists() is True
assert MeetingType.objects.exists() is True
assert Desk.objects.exists() is True
assert TimePeriod.objects.exists() is True
assert TimePeriodException.objects.exists() is True
def test_import_export_slug_fields(app):
agenda_events = Agenda.objects.create(label='Events Agenda', kind='events')
Desk.objects.create(agenda=agenda_events, slug='_exceptions_holder')
2020-07-21 16:38:14 +02:00
Event.objects.create(agenda=agenda_events, start_datetime=now(), places=10)
agenda_meetings = Agenda.objects.create(label='Meetings Agenda', kind='meetings')
MeetingType.objects.create(agenda=agenda_meetings, label='Meeting Type', duration=30)
Desk.objects.create(agenda=agenda_meetings, label='Desk')
output = get_output_of_command('export_site')
original_payload = json.loads(output)
Agenda.objects.all().delete()
assert Agenda.objects.exists() is False
assert MeetingType.objects.exists() is False
assert Desk.objects.exists() is False
assert Event.objects.exists() is False
payload = copy.deepcopy(original_payload)
payload['agendas'][0]['slug'] = 'events-agenda&'
with pytest.raises(AgendaImportError) as excinfo:
import_site(payload)
assert str(excinfo.value) == 'Bad slug format "events-agenda&"'
payload = copy.deepcopy(original_payload)
payload['agendas'][0]['events'][0]['slug'] = 'events-agenda-event&'
with pytest.raises(AgendaImportError) as excinfo:
import_site(payload)
assert str(excinfo.value) == 'Bad slug format "events-agenda-event&"'
payload = copy.deepcopy(original_payload)
payload['agendas'][1]['desks'][0]['slug'] = 'desk&'
with pytest.raises(AgendaImportError) as excinfo:
import_site(payload)
assert str(excinfo.value) == 'Bad slug format "desk&"'
payload = copy.deepcopy(original_payload)
payload['agendas'][1]['meetingtypes'][0]['slug'] = 'meeting-type&'
with pytest.raises(AgendaImportError) as excinfo:
import_site(payload)
assert str(excinfo.value) == 'Bad slug format "meeting-type&"'
def test_import_export_notification_settings():
agenda = Agenda.objects.create(label='Foo bar', kind='events')
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
AgendaNotificationsSettings.objects.create(
agenda=agenda,
almost_full_event=AgendaNotificationsSettings.EDIT_ROLE,
full_event=AgendaNotificationsSettings.VIEW_ROLE,
cancelled_event=AgendaNotificationsSettings.EMAIL_FIELD,
cancelled_event_emails=['hop@entrouvert.com', 'top@entrouvert.com'],
)
output = get_output_of_command('export_site')
payload = json.loads(output)
agenda.delete()
assert not AgendaNotificationsSettings.objects.exists()
import_site(payload)
agenda = Agenda.objects.first()
AgendaNotificationsSettings.objects.get(
agenda=agenda,
almost_full_event=AgendaNotificationsSettings.EDIT_ROLE,
full_event=AgendaNotificationsSettings.VIEW_ROLE,
cancelled_event=AgendaNotificationsSettings.EMAIL_FIELD,
cancelled_event_emails=['hop@entrouvert.com', 'top@entrouvert.com'],
)
# again - check OneToOneField
import_site(payload)
def test_import_export_reminder_settings():
agenda = Agenda.objects.create(label='Foo bar', kind='events')
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
AgendaReminderSettings.objects.create(
agenda=agenda,
days=2,
send_email=True,
send_sms=False,
email_extra_info='test',
)
output = get_output_of_command('export_site')
payload = json.loads(output)
agenda.delete()
assert not AgendaReminderSettings.objects.exists()
import_site(payload)
agenda = Agenda.objects.first()
AgendaReminderSettings.objects.get(
agenda=agenda,
days=2,
send_email=True,
send_sms=False,
email_extra_info='test',
)
# again - check OneToOneField
import_site(payload)
@override_settings(
EXCEPTIONS_SOURCES={
'holidays': {'class': 'workalendar.europe.France', 'label': 'Holidays'},
}
)
def test_import_export_time_period_exception_source():
agenda = Agenda.objects.create(label='Foo bar', kind='meetings')
desk = Desk.objects.create(slug='test', agenda=agenda)
desk.import_timeperiod_exceptions_from_settings(enable=True)
output = get_output_of_command('export_site')
payload = json.loads(output)
agenda.delete()
assert not TimePeriodExceptionSource.objects.exists()
import_site(payload)
desk = Desk.objects.get(slug='test')
source = desk.timeperiodexceptionsource_set.first()
assert source.enabled
assert desk.timeperiodexception_set.exists()
source.disable()
output = get_output_of_command('export_site')
payload = json.loads(output)
Agenda.objects.all().delete()
import_site(payload)
desk = Desk.objects.get(slug='test')
source = desk.timeperiodexceptionsource_set.first()
assert not source.enabled
assert not desk.timeperiodexception_set.exists()
@override_settings(
EXCEPTIONS_SOURCES={
'holidays': {'class': 'workalendar.europe.France', 'label': 'Holidays'},
}
)
def test_import_export_time_period_exception_source_enabled():
agenda = Agenda.objects.create(label='Foo bar', kind='events')
desk = Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
desk.import_timeperiod_exceptions_from_settings()
source = desk.timeperiodexceptionsource_set.first()
assert not source.enabled
assert source.settings_slug == 'holidays'
source.enabled = True
source.save()
output = get_output_of_command('export_site')
payload = json.loads(output)
agenda.delete()
assert not TimePeriodExceptionSource.objects.exists()
import_site(payload)
agenda = Agenda.objects.get(label='Foo bar')
assert agenda.desk_set.count() == 1
desk = agenda.desk_set.first()
assert desk.timeperiodexceptionsource_set.count() == 1
source = desk.timeperiodexceptionsource_set.first()
assert source.enabled
assert source.settings_slug == 'holidays'
def test_import_export_do_not_duplicate_timeperiod_and_exceptions():
agenda = Agenda.objects.create(label='Foo bar', kind='meetings')
desk = Desk.objects.create(slug='test', agenda=agenda)
TimePeriod.objects.create(
desk=desk, weekday=2, start_time=datetime.time(10, 0), end_time=datetime.time(11, 0)
)
TimePeriod.objects.create(
desk=desk, weekday=3, start_time=datetime.time(10, 0), end_time=datetime.time(11, 0)
)
tpe1 = TimePeriodException.objects.create(
desk=desk,
start_datetime=make_aware(datetime.datetime(2017, 5, 22, 8, 0)),
end_datetime=make_aware(datetime.datetime(2017, 5, 22, 12, 30)),
)
TimePeriodException.objects.create(
desk=desk,
start_datetime=make_aware(datetime.datetime(2017, 6, 22, 8, 0)),
end_datetime=make_aware(datetime.datetime(2017, 6, 22, 12, 30)),
)
assert TimePeriod.objects.count() == 2
assert TimePeriodException.objects.count() == 2
output = get_output_of_command('export_site')
payload = json.loads(output)
import_site(payload)
assert TimePeriod.objects.count() == 2
assert TimePeriodException.objects.count() == 2
# duplicated exception
output = get_output_of_command('export_site')
payload = json.loads(output)
assert len(payload['agendas'][0]['desks'][0]['exceptions']) == 2
tpe2 = TimePeriodException.objects.create(
desk=desk,
start_datetime=make_aware(datetime.datetime(2017, 5, 22, 8, 0)),
end_datetime=make_aware(datetime.datetime(2017, 5, 22, 12, 30)),
)
assert TimePeriod.objects.count() == 2
assert TimePeriodException.objects.count() == 3
assert tpe1.update_datetime < tpe2.update_datetime
import_site(payload)
assert TimePeriod.objects.count() == 2
assert TimePeriodException.objects.count() == 3
tpe1.refresh_from_db()
tpe2.refresh_from_db()
assert tpe1.update_datetime == tpe2.update_datetime
def test_import_export_unavailability_calendar(app):
output = get_output_of_command('export_site')
payload = json.loads(output)
assert len(payload['unavailability_calendars']) == 0
group1 = Group.objects.create(name=u'gé1')
group2 = Group.objects.create(name=u'gé2')
calendar = UnavailabilityCalendar.objects.create(label='Calendar', view_role=group1, edit_role=group2)
tp1_start = make_aware(datetime.datetime(2017, 5, 22, 8, 0))
tp1_end = make_aware(datetime.datetime(2017, 5, 22, 12, 30))
tp1 = TimePeriodException.objects.create(
unavailability_calendar=calendar, start_datetime=tp1_start, end_datetime=tp1_end
)
tp2_start = make_aware(datetime.datetime(2018, 5, 22, 8, 0))
tp2_end = make_aware(datetime.datetime(2018, 5, 22, 12, 30))
tp2 = TimePeriodException.objects.create(
unavailability_calendar=calendar, start_datetime=tp2_start, end_datetime=tp2_end
)
meetings_agenda = Agenda.objects.create(label='Foo Bar', kind='meetings')
MeetingType.objects.create(agenda=meetings_agenda, label='Meeting Type', duration=30)
desk = Desk.objects.create(agenda=meetings_agenda, label='Desk')
desk.unavailability_calendars.add(calendar)
output = get_output_of_command('export_site')
payload = json.loads(output)
assert len(payload['unavailability_calendars']) == 1
assert len(payload['agendas']) == 1
calendar.delete()
tp1.delete()
tp2.delete()
meetings_agenda.delete()
assert not UnavailabilityCalendar.objects.exists()
assert not TimePeriodException.objects.exists()
assert not Agenda.objects.exists()
assert not Desk.objects.exists()
import_site(copy.deepcopy(payload))
assert UnavailabilityCalendar.objects.count() == 1
calendar = UnavailabilityCalendar.objects.first()
assert calendar.label == 'Calendar'
assert calendar.view_role == group1
assert calendar.edit_role == group2
assert calendar.timeperiodexception_set.count() == 2
assert TimePeriodException.objects.get(
unavailability_calendar=calendar, start_datetime=tp1_start, end_datetime=tp1_end
)
assert TimePeriodException.objects.get(
unavailability_calendar=calendar, start_datetime=tp2_start, end_datetime=tp2_end
)
agenda = Agenda.objects.get(label='Foo Bar')
desk = agenda.desk_set.first()
assert desk.unavailability_calendars.count() == 1
assert desk.unavailability_calendars.first() == calendar
# update
update_payload = copy.deepcopy(payload)
update_payload['unavailability_calendars'][0]['label'] = 'Calendar Updated'
import_site(update_payload)
calendar.refresh_from_db()
assert calendar.label == 'Calendar Updated'
def test_import_export_absence_reason_group(app):
output = get_output_of_command('export_site')
payload = json.loads(output)
assert len(payload['absence_reason_groups']) == 0
group = AbsenceReasonGroup.objects.create(label='Foo bar')
AbsenceReason.objects.create(label='Foo reason', group=group)
AbsenceReason.objects.create(label='Baz', group=group)
output = get_output_of_command('export_site')
payload = json.loads(output)
assert len(payload['absence_reason_groups']) == 1
group.delete()
assert not AbsenceReasonGroup.objects.exists()
assert not AbsenceReason.objects.exists()
import_site(copy.deepcopy(payload))
assert AbsenceReasonGroup.objects.count() == 1
group = AbsenceReasonGroup.objects.first()
assert group.label == 'Foo bar'
assert group.slug == 'foo-bar'
assert group.absence_reasons.count() == 2
assert AbsenceReason.objects.get(group=group, label='Foo reason', slug='foo-reason')
assert AbsenceReason.objects.get(group=group, label='Baz', slug='baz')
# update
update_payload = copy.deepcopy(payload)
update_payload['absence_reason_groups'][0]['label'] = 'Foo bar Updated'
import_site(update_payload)
group.refresh_from_db()
assert group.label == 'Foo bar Updated'
# insert another group
group.slug = 'foo-bar-updated'
group.save()
import_site(copy.deepcopy(payload))
assert AbsenceReasonGroup.objects.count() == 2
group = AbsenceReasonGroup.objects.latest('pk')
assert group.label == 'Foo bar'
assert group.slug == 'foo-bar'
assert group.absence_reasons.count() == 2
assert AbsenceReason.objects.get(group=group, label='Foo reason', slug='foo-reason')
assert AbsenceReason.objects.get(group=group, label='Baz', slug='baz')
# with overwrite
AbsenceReason.objects.create(group=group, label='Baz2')
import_site(copy.deepcopy(payload), overwrite=True)
assert AbsenceReasonGroup.objects.count() == 2
group = AbsenceReasonGroup.objects.latest('pk')
assert group.label == 'Foo bar'
assert group.slug == 'foo-bar'
assert group.absence_reasons.count() == 2
assert AbsenceReason.objects.get(group=group, label='Foo reason', slug='foo-reason')
assert AbsenceReason.objects.get(group=group, label='Baz', slug='baz')
@mock.patch('chrono.agendas.models.Agenda.is_available_for_simple_management')
def test_import_export_desk_simple_management(available_mock):
agenda = Agenda.objects.create(label='Foo bar', kind='meetings', desk_simple_management=True)
output = get_output_of_command('export_site')
payload = json.loads(output)
assert len(payload['agendas']) == 1
assert payload['agendas'][0]['desk_simple_management'] is True
# check on creation
for available_value in [True, False]:
agenda.delete()
available_mock.return_value = available_value
import_site(payload)
agenda = Agenda.objects.latest('pk')
assert agenda.desk_simple_management == available_value
payload['agendas'][0]['desk_simple_management'] = False
for available_value in [True, False]:
# always ok to set flag to False
agenda.delete()
available_mock.return_value = available_value
import_site(payload)
agenda = Agenda.objects.latest('pk')
assert agenda.desk_simple_management is False
# check on update
payload['agendas'][0]['desk_simple_management'] = True
for available_value in [True, False]:
agenda.desk_simple_management = False
agenda.save()
available_mock.return_value = available_value
import_site(payload)
agenda.refresh_from_db()
assert agenda.desk_simple_management == available_value
# already True, no change
agenda.desk_simple_management = True
agenda.save()
available_mock.return_value = available_value
import_site(payload)
agenda.refresh_from_db()
assert agenda.desk_simple_management is True
payload['agendas'][0]['desk_simple_management'] = False
for available_value in [True, False]:
# always ok to set flag to False
for old_value in [True, False]:
agenda.desk_simple_management = old_value
agenda.save()
available_mock.return_value = available_value
import_site(payload)
agenda.refresh_from_db()
assert agenda.desk_simple_management is False
# not in payload, no changed
del payload['agendas'][0]['desk_simple_management']
for available_value in [True, False]:
for old_value in [True, False]:
agenda.desk_simple_management = old_value
agenda.save()
available_mock.return_value = available_value
import_site(payload)
agenda.refresh_from_db()
assert agenda.desk_simple_management == old_value
def test_export_deleted_meetingtype(app):
agenda = Agenda.objects.create(label='Agenda', kind='meetings')
meeting_type = MeetingType.objects.create(agenda=agenda, label='Meeting Type', duration=30)
output = get_output_of_command('export_site')
assert len(json.loads(output)['agendas'][0]['meetingtypes']) == 1
meeting_type.deleted = True
meeting_type.save()
output = get_output_of_command('export_site')
assert len(json.loads(output)['agendas'][0]['meetingtypes']) == 0