chrono/tests/test_utils.py

269 lines
8.8 KiB
Python

import datetime
import json
from unittest import mock
import pytest
from requests.exceptions import ConnectionError
from requests.models import Response
from chrono.agendas.models import Agenda, TimePeriod
from chrono.utils.date import get_weekday_index
from chrono.utils.lingo import CheckType, get_agenda_check_types
from .utils import build_agendas, build_meetings_agenda, build_virtual_agenda, paris, utc
def test_get_weekday_index():
for date in (
datetime.date(2021, 11, 1), # month starting a Monday
datetime.date(2021, 12, 1), # month starting a Wednesday
datetime.date(2021, 5, 1), # month starting a Sunday
):
assert get_weekday_index(date) == 1
assert get_weekday_index(date.replace(day=3)) == 1
assert get_weekday_index(date.replace(day=7)) == 1
assert get_weekday_index(date.replace(day=8)) == 2
assert get_weekday_index(date.replace(day=10)) == 2
assert get_weekday_index(date.replace(day=14)) == 2
assert get_weekday_index(date.replace(day=15)) == 3
assert get_weekday_index(date.replace(day=21)) == 3
assert get_weekday_index(date.replace(day=22)) == 4
assert get_weekday_index(date.replace(day=28)) == 4
assert get_weekday_index(date.replace(day=29)) == 5
assert get_weekday_index(date.replace(day=30)) == 5
CHECK_TYPES_DATA = [
{'id': 'bar-reason', 'kind': 'presence', 'text': 'Bar reason'},
{'id': 'foo-reason', 'kind': 'absence', 'text': 'Foo reason'},
]
class MockedRequestResponse(mock.Mock):
status_code = 200
def json(self):
return json.loads(self.content)
def test_get_agenda_check_types_no_service(settings):
agenda = Agenda(slug='foo')
settings.KNOWN_SERVICES = {}
assert get_agenda_check_types(agenda) == []
settings.KNOWN_SERVICES = {'other': []}
assert get_agenda_check_types(agenda) == []
def test_get_agenda_check_types():
agenda = Agenda(slug='foo')
with mock.patch('requests.Session.get') as requests_get:
requests_get.side_effect = ConnectionError()
assert get_agenda_check_types(agenda) == []
with mock.patch('requests.Session.get') as requests_get:
mock_resp = Response()
mock_resp.status_code = 500
requests_get.return_value = mock_resp
assert get_agenda_check_types(agenda) == []
with mock.patch('requests.Session.get') as requests_get:
mock_resp = Response()
mock_resp.status_code = 404
requests_get.return_value = mock_resp
assert get_agenda_check_types(agenda) == []
with mock.patch('requests.Session.get') as requests_get:
requests_get.return_value = MockedRequestResponse(content=json.dumps({'foo': 'bar'}))
assert get_agenda_check_types(agenda) == []
data = {'data': []}
with mock.patch('requests.Session.get') as requests_get:
requests_get.return_value = MockedRequestResponse(content=json.dumps(data))
assert get_agenda_check_types(agenda) == []
assert requests_get.call_args_list[0][0] == ('api/agenda/foo/check-types/',)
assert requests_get.call_args_list[0][1]['remote_service']['url'] == 'http://lingo.example.org'
data = {'data': CHECK_TYPES_DATA}
with mock.patch('requests.Session.get') as requests_get:
requests_get.return_value = MockedRequestResponse(content=json.dumps(data))
assert get_agenda_check_types(agenda) == [
CheckType(slug='bar-reason', label='Bar reason', kind='presence'),
CheckType(slug='foo-reason', label='Foo reason', kind='absence'),
]
def test_build_meetings_agenda(db):
agenda = build_meetings_agenda(
meeting_types=[30], resources=['Re1'], desks=('Desk 1', 'monday-friday 09:00-12:00 14:00-17:00')
)
assert agenda.slug == 'agenda'
assert agenda.label == 'Agenda'
assert agenda._mt_30
assert list(agenda.meetingtype_set.all()) == [agenda._mt_30]
assert agenda.desk_set.count() == 1
assert agenda.desk_set.all()[0].slug == 'desk-1'
timeperiods = agenda.desk_set.all()[0].timeperiod_set.all()
assert timeperiods.count() == 10
assert set(timeperiods.values_list('weekday', flat=True)) == set(range(0, 5))
assert set(timeperiods.values_list('start_time', 'end_time')) == {
(datetime.time(9), datetime.time(12)),
(datetime.time(14), datetime.time(17)),
}
assert agenda.resources.count() == 1
assert agenda.resources.get().label == 'Re1'
assert agenda.resources.get().slug == 're1'
def test_build_meetings_agenda_multiple_desks(db):
agenda = build_meetings_agenda(
meeting_types=[30],
desks={
'desk-1': ['monday-friday 09:00-12:00'],
'desk-2': ['monday-friday 14:00-17:00'],
},
)
desks = agenda.desk_set.all()
assert set(desks.values_list('slug', flat=True)) == {'desk-1', 'desk-2'}
assert agenda.desk_set.all()[0].slug == 'desk-1'
timeperiods = TimePeriod.objects.filter(desk__in=desks)
assert timeperiods.count() == 10
assert set(timeperiods.values_list('weekday', flat=True)) == set(range(0, 5))
assert set(timeperiods.values_list('start_time', 'end_time')) == {
(datetime.time(9), datetime.time(12)),
(datetime.time(14), datetime.time(17)),
}
def test_build_virtual_agenda(db):
agenda = build_virtual_agenda(
agendas={
'Agenda 1': {
'desks': ('Bureau 1', 'monday-friday 08:00-12:00 14:00-17:00'),
},
'Agenda 2': {
'desks': ('Bureau 1', 'monday,tuesday 09:00-12:00'),
},
'Agenda 3': {
'desks': ('Bureau 1', 'monday-friday 15:00-17:00'),
},
},
meeting_types=[30],
)
assert agenda._agenda_1
assert agenda._agenda_1._mt_30
assert agenda._agenda_2
assert agenda._agenda_3
assert agenda._mt_30
assert agenda.real_agendas.count() == 3
timeperiods = TimePeriod.objects.filter(desk__agenda__in=agenda.real_agendas.all())
assert timeperiods.count() == 17
assert set(timeperiods.values_list('weekday', flat=True)) == set(range(0, 5))
assert set(timeperiods.values_list('start_time', 'end_time')) == {
(datetime.time(8), datetime.time(12)),
(datetime.time(9), datetime.time(12)),
(datetime.time(14), datetime.time(17)),
(datetime.time(15), datetime.time(17)),
}
assert agenda._agenda_1
def test_build_agendas(db):
# pylint: disable=unused-variable
ICS_SAMPLE = """BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//foo.bar//EN
BEGIN:VEVENT
DTSTAMP:20170824T082855Z
DTSTART:20170831T170800Z
DTEND:20170831T203400Z
SEQUENCE:1
SUMMARY:Événement 1
END:VEVENT
BEGIN:VEVENT
DTSTAMP:20170824T092855Z
DTSTART:20170830T180800Z
DTEND:20170831T223400Z
SEQUENCE:2
END:VEVENT
END:VCALENDAR"""
unavailability_calendar, agenda_1, agenda_2, virtual = build_agendas(
'''
unavailability-calendar Congés
exception Noël
start_datetime paris('2023-12-25T00:00:00 24h')
exception-source sample.ics ICS_SAMPLE
meetings "Agenda 1" maximal_booking_delay=15 30 45 # comment 1
# comment 2
desk "Desk 1"
timeperiod monday-friday 08:00-12:00
exception Grève
start_datetime paris('2023-04-01T01:01:01')
end_datetime paris('2023-04-01T01:01:01')
exception-source sample.ics ICS_SAMPLE
unavailability-calendar Congés
desk "Bureau 2"
timeperiod monday-friday 14:00-17:00
meetings 'Agenda 2' 30
desk "Desk 1" monday-friday 08:00-12:00
desk "Desk 2" monday,friday 14:00-17:00
virtual "Agenda 3" 30
meetings CNI
desk bureau1 monday-friday 10:00-12:00
meetings Passeport
desk bureau2 monday-friday 14:00-17:00
'''
)
assert unavailability_calendar.label == 'Congés'
assert unavailability_calendar._noel
assert unavailability_calendar._sample_ics
assert agenda_1.label == 'Agenda 1'
assert agenda_1.maximal_booking_delay == 15
assert agenda_1._desk_1._greve
assert agenda_1._desk_1._sample_ics
assert agenda_1._desk_1
assert agenda_1._desk_1._conges == unavailability_calendar
assert agenda_1._bureau_2
assert agenda_1._mt_30
assert agenda_1._mt_45
assert agenda_2.label == 'Agenda 2'
assert agenda_2._desk_1
assert agenda_2._desk_2
assert agenda_2._mt_30
assert virtual._cni._bureau1
assert virtual._cni._mt_30
assert virtual._mt_30
assert virtual._passeport._bureau2
assert virtual._passeport._mt_30
def test_build_agendas_indentation_mismatch(db):
with pytest.raises(SyntaxError, match=r'on line 5'):
build_agendas(
'''
agenda xxx
zobi dd
kkk
iii # here, bad indentation
agenda "Agenda 1" 30
desk 1
desk 2
'''
)
def test_paris():
assert paris('2023-04-19T11:00:00').isoformat() == '2023-04-19T11:00:00+02:00'
def test_utc():
assert utc('2023-04-19T11:00:00').isoformat() == '2023-04-19T11:00:00+00:00'