chrono/tests/manager/test_shared_custody_agenda.py

401 lines
17 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import datetime
import pytest
from django.core.files.base import ContentFile
from django.db import connection
from django.test.utils import CaptureQueriesContext
from django.utils.timezone import now
from chrono.agendas.models import (
Person,
SharedCustodyAgenda,
SharedCustodyHolidayRule,
SharedCustodyPeriod,
SharedCustodyRule,
SharedCustodySettings,
TimePeriodExceptionGroup,
UnavailabilityCalendar,
)
from tests.utils import login
pytestmark = pytest.mark.django_db
with open('tests/data/holidays.ics') as f:
ICS_HOLIDAYS = f.read()
@pytest.mark.freeze_time('2022-02-22 14:00') # Tuesday
def test_shared_custody_agenda_settings_rules(app, admin_user):
father = Person.objects.create(user_external_id='father_id', first_name='John', last_name='Doe')
mother = Person.objects.create(user_external_id='mother_id', first_name='Jane', last_name='Doe')
agenda = SharedCustodyAgenda.objects.create(
first_guardian=father, second_guardian=mother, date_start=now()
)
app = login(app)
resp = app.get('/manage/shared-custody/%s/' % agenda.pk).follow()
resp = resp.click('Settings')
assert 'Custody agenda of John Doe and Jane Doe' in resp.text
assert 'Custody rules are not complete.' in resp.text
assert 'This agenda doesn\'t have any custody rules yet.' in resp.text
resp = resp.click('Add custody rule')
resp.form['guardian'] = father.pk
resp.form['days'] = list(range(7))
resp.form['weeks'] = 'even'
resp = resp.form.submit()
assert resp.location.endswith('/manage/shared-custody/%s/settings/' % agenda.pk)
resp = resp.follow()
assert 'Custody rules are not complete.' in resp.text
assert 'John Doe, daily, on even weeks' in resp.text
resp = resp.click('Add custody rule')
resp.form['guardian'] = mother.pk
resp.form['days'] = list(range(7))
resp.form['weeks'] = 'odd'
resp = resp.form.submit().follow()
assert 'Custody rules are not complete.' not in resp.text
assert 'John Doe, daily, on even weeks' in resp.text
assert 'Jane Doe, daily, on odd weeks' in resp.text
resp = resp.click('John Doe, daily, on even weeks')
resp.form['days'] = list(range(6))
resp = resp.form.submit()
assert resp.location.endswith('/manage/shared-custody/%s/settings/' % agenda.pk)
resp = resp.follow()
assert 'Custody rules are not complete.' in resp.text
resp = resp.click('John Doe, from Monday to Saturday, on even weeks')
resp.form['days'] = [0]
resp.form['weeks'] = 'odd'
resp = resp.form.submit()
assert 'Rule overlaps existing rules.' in resp.text
resp.form['weeks'] = 'even'
resp = resp.form.submit().follow()
resp = resp.click('remove', index=1)
resp = resp.form.submit()
assert resp.location.endswith('/manage/shared-custody/%s/settings/' % agenda.pk)
resp = resp.follow()
assert SharedCustodyRule.objects.count() == 1
def test_shared_custody_agenda_settings_rules_require_days(app, admin_user):
father = Person.objects.create(user_external_id='father_id', first_name='John', last_name='Doe')
mother = Person.objects.create(user_external_id='mother_id', first_name='Jane', last_name='Doe')
agenda = SharedCustodyAgenda.objects.create(
first_guardian=father, second_guardian=mother, date_start=now()
)
app = login(app)
resp = app.get('/manage/shared-custody/%s/settings/' % agenda.pk)
resp = resp.click('Add custody rule')
resp.form['guardian'] = father.pk
resp.form['weeks'] = 'even'
resp = resp.form.submit()
assert 'This field is required.' in resp.text
resp.form['days'] = [0]
resp.form.submit().follow()
assert SharedCustodyRule.objects.count() == 1
@pytest.mark.freeze_time('2022-02-22 14:00') # Tuesday
def test_shared_custody_agenda_settings_periods(app, admin_user):
father = Person.objects.create(user_external_id='father_id', first_name='John', last_name='Doe')
mother = Person.objects.create(user_external_id='mother_id', first_name='Jane', last_name='Doe')
agenda = SharedCustodyAgenda.objects.create(
first_guardian=father, second_guardian=mother, date_start=now()
)
app = login(app)
resp = app.get('/manage/shared-custody/%s/settings/' % agenda.pk)
assert 'This agenda doesn\'t have any custody period.' in resp.text
resp = resp.click('Add custody period')
resp.form['guardian'] = father.pk
resp.form['date_start'] = '2022-03-01'
resp.form['date_end'] = '2022-03-03'
resp = resp.form.submit()
assert resp.location.endswith('/manage/shared-custody/%s/settings/#open:time-periods' % agenda.pk)
resp = resp.follow()
assert 'This agenda doesn\'t have any custody period.' not in resp.text
assert 'John Doe, 03/01/2022 → 03/03/2022' in resp.text
resp = resp.click('John Doe, 03/01/2022 → 03/03/2022')
resp.form['guardian'] = mother.pk
resp = resp.form.submit()
assert resp.location.endswith('/manage/shared-custody/%s/settings/#open:time-periods' % agenda.pk)
resp = resp.follow()
assert 'Jane Doe, 03/01/2022 → 03/03/2022' in resp.text
resp = resp.click('Add custody period')
resp.form['guardian'] = mother.pk
resp.form['date_start'] = '2022-03-05'
resp.form['date_end'] = '2022-03-03'
resp = resp.form.submit()
assert 'End date must be greater than start date.' in resp.text
resp.form['date_start'] = '2022-03-02'
resp.form['date_end'] = '2022-03-06'
resp = resp.form.submit()
assert 'Period overlaps existing periods.' in resp.text
resp = app.get('/manage/shared-custody/%s/settings/' % agenda.pk)
resp = resp.click('remove', href='delete')
resp = resp.form.submit()
assert resp.location.endswith('/manage/shared-custody/%s/settings/#open:time-periods' % agenda.pk)
resp = resp.follow()
assert not SharedCustodyPeriod.objects.exists()
@pytest.mark.freeze_time('2022-02-22 14:00') # Tuesday
def test_shared_custody_agenda_month_view(app, admin_user):
father = Person.objects.create(user_external_id='father_id', first_name='John', last_name='Doe')
mother = Person.objects.create(user_external_id='mother_id', first_name='Jane', last_name='Doe')
agenda = SharedCustodyAgenda.objects.create(
first_guardian=father, second_guardian=mother, date_start=now()
)
SharedCustodyRule.objects.create(agenda=agenda, guardian=father, days=list(range(7)), weeks='even')
app = login(app)
resp = app.get('/manage/shared-custody/%s/' % agenda.pk).follow()
assert 'Custody agenda of John Doe and Jane Doe' in resp.text
assert 'February 2022' in resp.text
assert 'Configuration is not completed yet.' in resp.text
SharedCustodyRule.objects.create(agenda=agenda, guardian=mother, days=list(range(7)), weeks='odd')
resp = app.get('/manage/shared-custody/%s/' % agenda.pk).follow()
assert 'Configuration is not completed yet.' not in resp.text
assert all('Week %s' % i in resp.text for i in range(5, 10))
assert resp.pyquery('tbody tr th.today span').text() == 'Tuesday 22'
days = [x.text for x in resp.pyquery('tbody tr th span')]
assert len(days) == 7 * 5
assert days[:3] == ['Monday 31', 'Tuesday 1', 'Wednesday 2']
assert days[-3:] == ['Friday 4', 'Saturday 5', 'Sunday 6']
tds = [x.text for x in resp.pyquery('tbody tr td')]
for week_number, i in zip(range(5, 10), range(0, 29, 7)):
guardian = 'Jane Doe' if week_number % 2 else 'John Doe'
assert tds[i : i + 7] == [guardian] * 7
SharedCustodyPeriod.objects.create(
agenda=agenda,
guardian=father,
date_start=datetime.date(2022, 2, 1),
date_end=datetime.date(2022, 2, 3),
)
resp = app.get('/manage/shared-custody/%s/' % agenda.pk).follow()
tds = [x.text for x in resp.pyquery('tbody tr td')]
assert tds[:7] == ['Jane Doe', 'John Doe', 'John Doe', 'Jane Doe', 'Jane Doe', 'Jane Doe', 'Jane Doe']
old_resp = resp
resp = resp.click('')
assert 'March 2022' in resp.text
assert 'today' not in resp.text
assert all('Week %s' % i in resp.text for i in range(9, 14))
days = [x.text for x in resp.pyquery('tbody tr th span')]
assert len(days) == 7 * 5
assert days[:3] == ['Monday 28', 'Tuesday 1', 'Wednesday 2']
assert days[-3:] == ['Friday 1', 'Saturday 2', 'Sunday 3']
resp = resp.click('')
assert resp.text == old_resp.text
app.get('/manage/shared-custody/%s/42/42/' % agenda.pk, status=404)
def test_shared_custody_agenda_month_view_queries(app, admin_user):
father = Person.objects.create(user_external_id='father_id', first_name='John', last_name='Doe')
mother = Person.objects.create(user_external_id='mother_id', first_name='Jane', last_name='Doe')
agenda = SharedCustodyAgenda.objects.create(
first_guardian=father, second_guardian=mother, date_start=now()
)
SharedCustodyRule.objects.create(agenda=agenda, guardian=father, days=[0, 1, 2], weeks='even')
SharedCustodyRule.objects.create(agenda=agenda, guardian=father, days=[3, 4, 5, 6], weeks='odd')
SharedCustodyRule.objects.create(agenda=agenda, guardian=mother, days=[0, 1, 2], weeks='odd')
SharedCustodyRule.objects.create(agenda=agenda, guardian=mother, days=[3, 4, 5, 6], weeks='even')
for i in range(1, 10):
SharedCustodyPeriod.objects.create(
agenda=agenda,
guardian=mother,
date_start=datetime.date(year=2022, month=12, day=i),
date_end=datetime.date(year=2022, month=12, day=i + 1),
)
# configure holidays
unavailability_calendar = UnavailabilityCalendar.objects.create(label='Calendar')
SharedCustodySettings.objects.create(holidays_calendar=unavailability_calendar)
source = unavailability_calendar.timeperiodexceptionsource_set.create(
ics_filename='holidays.ics', ics_file=ContentFile(ICS_HOLIDAYS, name='holidays.ics')
)
source.refresh_timeperiod_exceptions_from_ics()
app = login(app)
resp = app.get('/manage/shared-custody/%s/settings/' % agenda.pk)
resp = resp.click('Add custody rule during holidays')
resp.form['guardian'] = father.pk
resp.form['holiday'].select(text='Vacances de Noël')
resp = resp.form.submit().follow()
with CaptureQueriesContext(connection) as ctx:
app.get('/manage/shared-custody/%s/2022/12/' % agenda.pk)
assert len(ctx.captured_queries) == 9
def test_shared_custody_agenda_holiday_rules(app, admin_user):
father = Person.objects.create(user_external_id='father_id', first_name='John', last_name='Doe')
mother = Person.objects.create(user_external_id='mother_id', first_name='Jane', last_name='Doe')
agenda = SharedCustodyAgenda.objects.create(
first_guardian=father, second_guardian=mother, date_start=now()
)
app = login(app)
resp = app.get('/manage/shared-custody/%s/settings/' % agenda.pk)
assert 'Add custody rule during holidays' not in resp.text
assert 'Custody rules during holidays' not in resp.text
# configure holidays
unavailability_calendar = UnavailabilityCalendar.objects.create(label='Calendar')
SharedCustodySettings.objects.create(holidays_calendar=unavailability_calendar)
source = unavailability_calendar.timeperiodexceptionsource_set.create(
ics_filename='holidays.ics', ics_file=ContentFile(ICS_HOLIDAYS, name='holidays.ics')
)
source.refresh_timeperiod_exceptions_from_ics()
resp = app.get('/manage/shared-custody/%s/settings/' % agenda.pk)
resp = resp.click('Add custody rule during holidays')
resp.form['guardian'] = father.pk
resp.form['holiday'].select(text='Vacances de Noël')
resp.form['years'] = 'odd'
resp.form['periodicity'] = 'first-half'
resp = resp.form.submit()
assert resp.location.endswith('/manage/shared-custody/%s/settings/#open:holidays' % agenda.pk)
resp = resp.follow()
assert SharedCustodyHolidayRule.objects.count() == 1
assert SharedCustodyPeriod.objects.count() == 3
assert 'This agenda doesn\'t have any custody period.' in resp.text
resp = resp.click('John Doe, Vacances de Noël, the first half, on odd years')
resp.form['years'] = ''
resp = resp.form.submit()
assert resp.location.endswith('/manage/shared-custody/%s/settings/#open:holidays' % agenda.pk)
resp = resp.follow()
assert 'John Doe, Vacances de Noël, the first half' in resp.text
assert SharedCustodyHolidayRule.objects.count() == 1
assert SharedCustodyPeriod.objects.count() == 6
resp = resp.click('Add custody rule during holidays')
resp.form['guardian'] = mother.pk
resp.form['holiday'].select(text='Vacances de Noël')
resp.form['periodicity'] = 'first-half'
resp = resp.form.submit()
assert 'Rule overlaps existing rules.' in resp.text
resp.form['periodicity'] = 'second-half'
resp = resp.form.submit().follow()
assert 'Jane Doe, Vacances de Noël, the second half' in resp.text
assert SharedCustodyHolidayRule.objects.count() == 2
assert SharedCustodyPeriod.objects.count() == 12
resp = resp.click('remove', index=1)
resp = resp.form.submit()
assert resp.location.endswith('/manage/shared-custody/%s/settings/#open:holidays' % agenda.pk)
resp = resp.follow()
assert SharedCustodyHolidayRule.objects.count() == 1
assert SharedCustodyPeriod.objects.count() == 6
resp = resp.click('Add custody rule during holidays')
resp.form['guardian'] = father.pk
resp.form['holiday'].select(text='Vacances de Noël')
resp.form['periodicity'] = 'first-and-third-quarters'
resp = resp.form.submit()
assert 'Short holidays cannot be cut into quarters.' in resp.text
resp.form['holiday'].select(text='Vacances dÉté')
resp = resp.form.submit().follow()
assert 'John Doe, Vacances dÉté, the first and third quarters' in resp.text
# if dates get deleted, rules still exist but holiday is not shown anymore
summer_holidays = TimePeriodExceptionGroup.objects.get(slug='summer_holidays')
summer_holidays.exceptions.all().delete()
assert SharedCustodyHolidayRule.objects.filter(holiday=summer_holidays).exists()
resp = resp.click('Add custody rule during holidays')
assert [x[2] for x in resp.form['holiday'].options] == ['---------', 'Vacances de Noël']
# holiday name is shown on month view
SharedCustodyRule.objects.create(agenda=agenda, guardian=father, days=list(range(7)), weeks='even')
SharedCustodyRule.objects.create(agenda=agenda, guardian=mother, days=list(range(7)), weeks='odd')
resp = app.get('/manage/shared-custody/%s/2022/12/' % agenda.pk)
assert 'John Doe (Vacances de Noël)' in resp.text
# calendar cannot be deleted
resp = app.get('/manage/unavailability-calendar/%s/settings' % unavailability_calendar.pk)
resp = resp.click('Delete')
resp = resp.form.submit().follow()
assert 'This calendar cannot be deleted because it is used by shared custody agendas.' in resp.text
def test_shared_custody_settings_feature_flag(app, admin_user, settings):
settings.SHARED_CUSTODY_ENABLED = False
app = login(app)
resp = app.get('/manage/')
assert 'Shared custody' not in resp.text
settings.SHARED_CUSTODY_ENABLED = True
resp = app.get('/manage/')
assert 'Shared custody' in resp.text
def test_shared_custody_settings_management_role(app, admin_user, manager_user):
father = Person.objects.create(user_external_id='father_id', first_name='John', last_name='Doe')
mother = Person.objects.create(user_external_id='mother_id', first_name='Jane', last_name='Doe')
agenda = SharedCustodyAgenda.objects.create(
first_guardian=father, second_guardian=mother, date_start=now()
)
app = login(app, username='manager', password='manager')
app.get('/manage/shared-custody/%s/settings/' % agenda.pk, status=403)
app.reset()
app = login(app)
resp = app.get('/manage/')
resp = resp.click('Shared custody')
resp.form['management_role'] = manager_user.groups.all()[0].pk
resp.form.submit()
app.reset()
app = login(app, username='manager', password='manager')
resp = app.get('/manage/shared-custody/%s/settings/' % agenda.pk)
assert 'Custody agenda of John Doe and Jane Doe' in resp.text
def test_shared_custody_agenda_delete(app, admin_user, manager_user):
father = Person.objects.create(user_external_id='father_id', first_name='John', last_name='Doe')
mother = Person.objects.create(user_external_id='mother_id', first_name='Jane', last_name='Doe')
agenda = SharedCustodyAgenda.objects.create(
first_guardian=father, second_guardian=mother, date_start=now()
)
SharedCustodySettings.objects.create(management_role=manager_user.groups.all()[0])
app = login(app, username='manager', password='manager')
resp = app.get('/manage/shared-custody/%s/settings/' % agenda.pk)
assert 'Delete' not in resp.text
app = login(app)
resp = app.get('/manage/shared-custody/%s/settings/' % agenda.pk)
resp = resp.click('Delete')
resp = resp.form.submit().follow()
assert not SharedCustodyAgenda.objects.exists()