chrono/tests/manager/test_resource.py

974 lines
40 KiB
Python

import datetime
import freezegun
import pytest
from django.db import connection
from django.test.utils import CaptureQueriesContext
from django.utils.timezone import localtime, make_aware, now
from chrono.agendas.models import Agenda, Booking, Desk, Event, MeetingType, Resource, TimePeriod
from tests.utils import login
pytestmark = pytest.mark.django_db
def test_list_resources_as_manager(app, manager_user):
agenda = Agenda(label='Foo Bar')
agenda.view_role = manager_user.groups.all()[0]
agenda.save()
app = login(app, username='manager', password='manager')
app.get('/manage/resources/', status=403)
resp = app.get('/manage/', status=200)
assert 'Resources' not in resp.text
def test_add_resource(app, admin_user):
app = login(app)
resp = app.get('/manage/', status=200)
resp = resp.click('Resources')
resp = resp.click('New')
resp.form['label'] = 'Foo bar'
resp = resp.form.submit()
resource = Resource.objects.latest('pk')
assert resp.location.endswith('/manage/resource/%s/' % resource.pk)
assert resource.label == 'Foo bar'
assert resource.slug == 'foo-bar'
def test_add_resource_as_manager(app, manager_user):
agenda = Agenda(label='Foo Bar')
agenda.view_role = manager_user.groups.all()[0]
agenda.save()
app = login(app, username='manager', password='manager')
app.get('/manage/resource/add/', status=403)
def test_view_resource(app, admin_user):
agenda = Agenda.objects.create(label='Foo Bar', kind='meetings')
resource = Resource.objects.create(label='Resource 1')
app = login(app)
resp = app.get('/manage/resource/%s/' % resource.pk, status=200)
assert '/manage/agendas/%s/settings' % agenda.pk not in resp.text
agenda.resources.add(resource)
resp = app.get('/manage/resource/%s/' % resource.pk, status=200)
assert '/manage/agendas/%s/settings' % agenda.pk in resp.text
def test_view_resource_as_manager(app, manager_user):
agenda = Agenda.objects.create(label='Foo Bar', kind='meetings')
agenda.view_role = manager_user.groups.all()[0]
agenda.save()
resource = Resource.objects.create(label='Resource 1')
app = login(app, username='manager', password='manager')
app.get('/manage/resource/%s/' % resource.pk, status=403)
def test_resource_day_view(app, admin_user, get_proper_html_str):
today = datetime.date.today()
resource = Resource.objects.create(label='Foo bar')
agenda = Agenda.objects.create(label='Agenda', kind='meetings')
desk = Desk.objects.create(agenda=agenda, label='Desk')
meetingtype = MeetingType.objects.create(agenda=agenda, label='Bar', duration=30)
timeperiod = TimePeriod.objects.create(
desk=desk, weekday=today.weekday(), start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
)
login(app)
app.get('/manage/agendas/%s/%d/%d/%d/' % (agenda.pk, today.year, 42, today.day), status=404)
resp = app.get('/manage/resource/%s/%d/%d/%d/' % (resource.pk, today.year, today.month, today.day))
assert 'div class="booking' not in resp.text
assert 'No bookings this day.' in resp.text
agenda.resources.add(resource)
resp = app.get('/manage/resource/%s/%d/%d/%d/' % (resource.pk, today.year, today.month, today.day))
assert 'div class="booking' not in resp.text
assert resp.text.count('<tr') == 8 # 10->18 (not included)
timeperiod.end_time = datetime.time(18, 30) # end during an hour
timeperiod.save()
resp = app.get('/manage/resource/%s/%d/%d/%d/' % (resource.pk, today.year, today.month, today.day))
assert resp.text.count('<tr') == 9 # 10->18 (included)
# book some slots
for hour, minute in [(10, 30), (14, 0)]:
event = Event.objects.create(
agenda=agenda,
places=1,
desk=desk,
meeting_type=meetingtype,
start_datetime=now().replace(hour=hour, minute=minute),
)
event.resources.add(resource)
if hour == 10:
Booking.objects.create(event=event)
else:
Booking.objects.create(event=event, label='foo', user_last_name="bar's")
with CaptureQueriesContext(connection) as ctx:
resp = app.get('/manage/resource/%s/%d/%d/%d/' % (resource.pk, today.year, today.month, today.day))
assert len(ctx.captured_queries) == 7
assert resp.text.count('div class="booking') == 2
assert resp.pyquery.find('div.booking a').not_('.cancel')[0].text.strip() == 'booked'
assert resp.pyquery.find('div.booking a').not_('.cancel')[1].text.strip() == "foo - bar's"
assert get_proper_html_str('foo - bar&#39;s') in resp
assert 'hourspan-2' in resp.text # table CSS class
assert 'height: 50%; top: 0%;' in resp.text # booking cells
assert 'height: 50%; top: 50%;' in resp.text # booking cells
agenda.booking_user_block_template = '<b>{{ booking.user_name }}</b> Foo Bar'
agenda.save()
resp = app.get('/manage/resource/%s/%d/%d/%d/' % (resource.pk, today.year, today.month, today.day))
assert resp.pyquery.find('div.booking a').not_('.cancel')[0].text.strip() == '<b></b> Foo Bar'
assert resp.pyquery.find('div.booking a').not_('.cancel')[1].text.strip() == "<b>bar's</b> Foo Bar"
assert get_proper_html_str('&lt;b&gt;bar&#39;s&lt;/b&gt; Foo Bar') in resp
# create a shorter meeting type, this will change the table CSS class
# (and visually this will give more room for events)
meetingtype = MeetingType.objects.create(agenda=agenda, label='Baz', duration=15)
resp = app.get('/manage/resource/%s/%d/%d/%d/' % (resource.pk, today.year, today.month, today.day))
assert resp.text.count('div class="booking') == 2
assert 'hourspan-4' in resp.text # table CSS class
# cancel a booking
booking = Booking.objects.first()
booking.cancel()
resp = app.get('/manage/resource/%s/%d/%d/%d/' % (resource.pk, today.year, today.month, today.day))
assert resp.text.count('div class="booking') == 1
def test_resource_day_view_late_meeting(app, admin_user):
today = datetime.date.today()
resource = Resource.objects.create(label='Foo bar')
agenda = Agenda.objects.create(label='Agenda', kind='meetings')
agenda.resources.add(resource)
desk = Desk.objects.create(agenda=agenda, label='Desk')
MeetingType.objects.create(agenda=agenda, label='Bar', duration=30)
TimePeriod.objects.create(
desk=desk, weekday=today.weekday(), start_time=datetime.time(10, 0), end_time=datetime.time(23, 30)
)
login(app)
resp = app.get('/manage/resource/%s/%d/%d/%d/' % (resource.pk, today.year, today.month, today.day))
assert resp.text.count('<tr') == 14
assert '<th class="hour">midnight</th>' not in resp.text
assert '<th class="hour">11 p.m.</th>' in resp.text
def test_resource_invalid_day_view(app, admin_user):
resource = Resource.objects.create(label='Foo bar')
login(app)
resp = app.get('/manage/resource/%s/%d/%d/%d/' % (resource.pk, 2018, 11, 31), status=302)
assert resp.location.endswith('2018/11/30/')
def test_resource_day_view_event_outside_timeperiod(app, admin_user):
today = datetime.date.today()
resource = Resource.objects.create(label='Foo bar')
agenda = Agenda.objects.create(label='Agenda', kind='meetings')
agenda.resources.add(resource)
desk = Desk.objects.create(agenda=agenda, label='New Desk')
meetingtype = MeetingType.objects.create(agenda=agenda, label='Bar', duration=30)
login(app)
# no time period - no events
resp = app.get('/manage/resource/%s/%d/%d/%d/' % (resource.pk, today.year, today.month, today.day))
assert 'No bookings this day.' in resp.text
assert 'div class="booking' not in resp.text
# book some slots
for hour, minute in [(9, 0), (17, 0)]:
event = Event.objects.create(
agenda=agenda,
places=1,
desk=desk,
meeting_type=meetingtype,
start_datetime=localtime(now()).replace(hour=hour, minute=minute),
)
event.resources.add(resource)
Booking.objects.create(event=event)
# no time period - events are displayed
resp = app.get('/manage/resource/%s/%d/%d/%d/' % (resource.pk, today.year, today.month, today.day))
assert resp.text.count('div class="booking') == 2
# bookings are cancelled
Booking.objects.update(cancellation_datetime=now())
resp = app.get('/manage/resource/%s/%d/%d/%d/' % (resource.pk, today.year, today.month, today.day))
assert 'No bookings this day.' in resp.text
assert resp.text.count('div class="booking') == 0
# events outside time period
Booking.objects.update(cancellation_datetime=None) # reset
TimePeriod.objects.create(
desk=desk, weekday=today.weekday(), start_time=datetime.time(10, 0), end_time=datetime.time(16, 0)
)
resp = app.get('/manage/resource/%s/%d/%d/%d/' % (resource.pk, today.year, today.month, today.day))
assert resp.text.count('div class="booking') == 2
def test_day_view_resource_as_manager(app, manager_user):
agenda = Agenda.objects.create(label='Foo Bar', kind='meetings')
agenda.view_role = manager_user.groups.all()[0]
agenda.save()
resource = Resource.objects.create(label='Resource 1')
app = login(app, username='manager', password='manager')
today = datetime.date.today()
app.get('/manage/resource/%s/%d/%d/%d/' % (resource.pk, today.year, today.month, today.day), status=403)
@freezegun.freeze_time('2020-06-15')
def test_resource_week_view(app, admin_user, get_proper_html_str):
resource = Resource.objects.create(label='Foo bar')
agenda = Agenda.objects.create(label='Agenda', kind='meetings')
agenda.resources.add(resource)
desk = Desk.objects.create(agenda=agenda, label='Desk')
meetingtype = MeetingType.objects.create(agenda=agenda, label='Bar', duration=20)
TimePeriod.objects.create(
desk=desk, weekday=0, start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
)
login(app)
today = datetime.date(2018, 11, 10) # fixed day
app.get('/manage/resource/%s/%s/%s/' % (resource.pk, today.year, 72), status=404)
resp = app.get('/manage/resource/%s/%s/week/%s/' % (resource.pk, today.year, today.strftime('%W')))
assert '<div class="booking' not in resp.text
assert resp.text.count('<tr') == 9
# book some slots
for hour, minute in [(10, 30), (14, 0)]:
event = Event.objects.create(
agenda=agenda,
places=1,
desk=desk,
meeting_type=meetingtype,
start_datetime=now().replace(hour=hour, minute=minute),
)
event.resources.add(resource)
if hour == 10:
Booking.objects.create(event=event)
else:
Booking.objects.create(event=event, label='foo', user_last_name="bar's")
today = datetime.date.today()
with CaptureQueriesContext(connection) as ctx:
resp = app.get('/manage/resource/%s/%s/week/%s/' % (resource.pk, today.year, today.strftime('%W')))
assert len(ctx.captured_queries) == 8
assert resp.text.count('<div class="booking" style="height:33.0%;') == 2 # booking cells
assert resp.pyquery.find('div.booking a').not_('.cancel')[0].text.strip() == 'booked'
assert resp.pyquery.find('div.booking a').not_('.cancel')[1].text.strip() == "foo - bar's"
assert get_proper_html_str('foo - bar&#39;s') in resp
agenda.booking_user_block_template = '<b>{{ booking.user_name }}</b> Foo Bar'
agenda.save()
resp = app.get('/manage/resource/%s/%s/week/%s/' % (resource.pk, today.year, today.strftime('%W')))
assert resp.pyquery.find('div.booking a').not_('.cancel')[0].text.strip() == '<b></b> Foo Bar'
assert resp.pyquery.find('div.booking a').not_('.cancel')[1].text.strip() == "<b>bar's</b> Foo Bar"
assert get_proper_html_str('&lt;b&gt;bar&#39;s&lt;/b&gt; Foo Bar') in resp
# cancel booking
booking = Booking.objects.first()
booking.cancel()
# make sure the are not
resp = app.get('/manage/resource/%s/%s/week/%s/' % (resource.pk, today.year, today.strftime('%W')))
assert resp.text.count('<div class="booking"') == 1
def test_resource_week_view_weekend(app, admin_user):
resource = Resource.objects.create(label='Foo bar')
agenda = Agenda.objects.create(label='Agenda', kind='meetings')
agenda.resources.add(resource)
desk = Desk.objects.create(agenda=agenda, label='Desk')
MeetingType.objects.create(agenda=agenda, label='Bar', duration=30)
monday = 0
TimePeriod.objects.create(
desk=desk, weekday=monday, start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
)
week, year = '01', 2019
login(app)
resp = app.get('/manage/resource/%s/%s/week/%s/' % (resource.pk, year, week))
assert 'Sunday' not in resp.text
assert 'Saturday' not in resp.text
# Month starts a Tuesday, but monday is displayed
assert len(resp.pyquery.find('tbody tr:first th.weekday:empty')) == 0
week, year = 21, 2019 # month starts a Saturday
resp = app.get('/manage/resource/%s/%s/week/%s/' % (resource.pk, year, week))
assert len(resp.pyquery.find('tbody tr:first th.weekday:empty')) == 0
saturday = 5
timeperiod_sat = TimePeriod.objects.create(
desk=desk, weekday=saturday, start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
)
resp = app.get('/manage/resource/%s/%s/week/%s/' % (resource.pk, year, week))
assert 'Sunday' not in resp.text
assert 'Saturday' in resp.text
assert len(resp.pyquery.find('tbody tr:first th.weekday:empty')) == 0
sunday = 6
TimePeriod.objects.create(
desk=desk, weekday=sunday, start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
)
resp = app.get('/manage/resource/%s/%s/week/%s/' % (resource.pk, year, week))
assert 'Sunday' in resp.text
assert 'Saturday' in resp.text
timeperiod_sat.delete()
resp = app.get('/manage/resource/%s/%s/week/%s/' % (resource.pk, year, week))
assert 'Sunday' in resp.text
assert 'Saturday' in resp.text
def test_resource_week_view_opening_not_even_an_hour(app, admin_user, get_proper_html_str):
resource = Resource.objects.create(label='Foo bar')
agenda = Agenda.objects.create(label='Agenda', kind='meetings')
agenda.resources.add(resource)
desk = Desk.objects.create(agenda=agenda, label='Desk')
meetingtype = MeetingType.objects.create(agenda=agenda, label='Bar', duration=15)
TimePeriod.objects.create(
desk=desk, weekday=0, start_time=datetime.time(10, 0), end_time=datetime.time(10, 30)
)
login(app)
today = datetime.date(2018, 11, 10) # fixed day
resp = app.get('/manage/resource/%s/%s/week/%s/' % (resource.pk, today.year, today.strftime('%W')))
assert '<div class="booking' not in resp.text
assert resp.text.count('<tr') == 2
# book a slot
event = Event.objects.create(
agenda=agenda,
places=1,
desk=desk,
meeting_type=meetingtype,
start_datetime=datetime.datetime(today.year, today.month, today.day, hour=10, minute=0),
)
event.resources.add(resource)
Booking.objects.create(event=event)
resp = app.get('/manage/resource/%s/%s/week/%s/' % (resource.pk, today.year, today.strftime('%W')))
assert resp.text.count('<div class="booking" style="height:25.0%;') == 1 # booking cell
def test_resource_week_view_dst_change(app, admin_user):
resource = Resource.objects.create(label='Foo bar')
agenda = Agenda.objects.create(label='Agenda', kind='meetings')
agenda.resources.add(resource)
desk = Desk.objects.create(agenda=agenda, label='Desk')
meetingtype = MeetingType.objects.create(agenda=agenda, label='Bar', duration=30)
TimePeriod.objects.create(
desk=desk, weekday=0, start_time=datetime.time(9, 0), end_time=datetime.time(12, 0)
)
login(app)
# book some slots
with freezegun.freeze_time('2019-10-01'):
for start_datetime in [
make_aware(datetime.datetime(2019, 10, 2, 10, 0)),
make_aware(datetime.datetime(2019, 10, 29, 10, 0)),
]:
event = Event.objects.create(
agenda=agenda,
places=1,
desk=desk,
meeting_type=meetingtype,
start_datetime=start_datetime,
)
event.resources.add(resource)
Booking.objects.create(event=event)
# check booked slots are similarly aligned
resp = app.get('/manage/resource/%s/2019/week/43/' % resource.pk)
assert resp.text.count('height:50.0%;top:100.0%') == 1
def test_resource_week_view_januaries(app, admin_user):
resource = Resource.objects.create(label='Foo bar')
agenda = Agenda.objects.create(label='Agenda', kind='meetings')
agenda.resources.add(resource)
desk = Desk.objects.create(agenda=agenda, label='Desk')
TimePeriod(desk=desk, weekday=2, start_time=datetime.time(9, 0), end_time=datetime.time(12, 0)).save()
for year in range(2020, 2030):
date = datetime.date(year, 1, 1)
with freezegun.freeze_time(date):
login(app)
resp = app.get('/manage/resource/%s/%s/week/01/' % (resource.pk, date.year))
assert resp.text.count('<th class="weeknum">') == 1
def test_resource_week_view_event_outside_timeperiod(app, admin_user):
middle_day = now().replace(day=15)
middle_day = middle_day + datetime.timedelta(days=4 - middle_day.weekday())
resource = Resource.objects.create(label='Foo bar')
agenda = Agenda.objects.create(label='Agenda', kind='meetings')
agenda.resources.add(resource)
desk = Desk.objects.create(agenda=agenda, label='Desk')
meetingtype = MeetingType.objects.create(agenda=agenda, label='Bar', duration=30)
login(app)
# no time period - no events
resp = app.get(
'/manage/resource/%s/%d/week/%s/' % (resource.pk, middle_day.year, middle_day.strftime('%W'))
)
assert 'No bookings this week.' in resp.text
assert 'div class="booking' not in resp.text
# book some slots
for hour, minute in [(9, 0), (17, 0)]:
event = Event.objects.create(
agenda=agenda,
places=1,
desk=desk,
meeting_type=meetingtype,
start_datetime=localtime(now()).replace(
day=middle_day.day - middle_day.weekday() + 2, hour=hour, minute=minute
),
)
event.resources.add(resource)
Booking.objects.create(event=event)
# no time period - events are displayed
resp = app.get(
'/manage/resource/%s/%d/week/%s/' % (resource.pk, middle_day.year, middle_day.strftime('%W'))
)
assert resp.text.count('div class="booking') == 2
# events outside time period
TimePeriod.objects.create(
desk=desk, weekday=2, start_time=datetime.time(10, 0), end_time=datetime.time(16, 0)
)
resp = app.get(
'/manage/resource/%s/%d/week/%s/' % (resource.pk, middle_day.year, middle_day.strftime('%W'))
)
assert resp.text.count('div class="booking') == 2
assert 'Sunday' not in resp.text
assert 'Saturday' not in resp.text
# bookings are cancelled
Booking.objects.update(cancellation_datetime=now())
resp = app.get(
'/manage/resource/%s/%d/week/%s/' % (resource.pk, middle_day.year, middle_day.strftime('%W'))
)
assert resp.text.count('div class="booking') == 0
# create an event on saturday
Booking.objects.update(cancellation_datetime=None) # reset
middle_day = now().replace(day=15)
middle_day = middle_day + datetime.timedelta(days=5 - middle_day.weekday())
event = Event.objects.create(
agenda=agenda,
places=1,
desk=desk,
meeting_type=meetingtype,
start_datetime=localtime(now()).replace(day=middle_day.day, hour=10, minute=0),
)
event.resources.add(resource)
Booking.objects.create(event=event)
resp = app.get(
'/manage/resource/%s/%d/week/%s/' % (resource.pk, middle_day.year, middle_day.strftime('%W'))
)
assert resp.text.count('div class="booking') == 3
assert 'Sunday' not in resp.text
assert 'Saturday' in resp.text
# bookings are cancelled
Booking.objects.update(cancellation_datetime=now())
resp = app.get(
'/manage/resource/%s/%d/week/%s/' % (resource.pk, middle_day.year, middle_day.strftime('%W'))
)
assert resp.text.count('div class="booking') == 0
# and a timeperiod
Booking.objects.update(cancellation_datetime=None) # reset
TimePeriod.objects.create(
desk=desk, weekday=5, start_time=datetime.time(11, 0), end_time=datetime.time(12, 0)
)
resp = app.get(
'/manage/resource/%s/%d/week/%s/' % (resource.pk, middle_day.year, middle_day.strftime('%W'))
)
assert resp.text.count('div class="booking') == 3
assert 'Sunday' not in resp.text
assert 'Saturday' in resp.text
# create an event on sunday
middle_day = now().replace(day=15)
middle_day = middle_day + datetime.timedelta(days=6 - middle_day.weekday())
event = Event.objects.create(
agenda=agenda,
places=1,
desk=desk,
meeting_type=meetingtype,
start_datetime=localtime(now()).replace(day=middle_day.day, hour=10, minute=0),
)
event.resources.add(resource)
Booking.objects.create(event=event)
resp = app.get(
'/manage/resource/%s/%d/week/%s/' % (resource.pk, middle_day.year, middle_day.strftime('%W'))
)
assert resp.text.count('div class="booking') == 4
assert 'Sunday' in resp.text
assert 'Saturday' in resp.text
# bookings are cancelled
Booking.objects.update(cancellation_datetime=now())
resp = app.get(
'/manage/resource/%s/%d/week/%s/' % (resource.pk, middle_day.year, middle_day.strftime('%W'))
)
assert resp.text.count('div class="booking') == 0
# and a timeperiod
Booking.objects.update(cancellation_datetime=None) # reset
TimePeriod.objects.create(
desk=desk, weekday=6, start_time=datetime.time(11, 0), end_time=datetime.time(12, 0)
)
resp = app.get(
'/manage/resource/%s/%d/week/%s/' % (resource.pk, middle_day.year, middle_day.strftime('%W'))
)
assert resp.text.count('div class="booking') == 4
assert 'Sunday' in resp.text
assert 'Saturday' in resp.text
def test_week_view_resource_as_manager(app, manager_user):
agenda = Agenda.objects.create(label='Foo Bar', kind='meetings')
agenda.view_role = manager_user.groups.all()[0]
agenda.save()
resource = Resource.objects.create(label='Resource 1')
app = login(app, username='manager', password='manager')
today = datetime.date.today()
app.get('/manage/resource/%s/%d/week/%s/' % (resource.pk, today.year, today.strftime('%W')), status=403)
@freezegun.freeze_time('2020-06-15')
def test_resource_month_view(app, admin_user, get_proper_html_str):
resource = Resource.objects.create(label='Foo bar')
agenda = Agenda.objects.create(label='Agenda', kind='meetings')
agenda.resources.add(resource)
desk = Desk.objects.create(agenda=agenda, label='Desk')
meetingtype = MeetingType.objects.create(agenda=agenda, label='Bar', duration=20)
TimePeriod.objects.create(
desk=desk, weekday=0, start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
)
login(app)
today = datetime.date(2018, 11, 10) # fixed day
app.get('/manage/resource/%s/%s/%s/' % (resource.pk, today.year, 42), status=404)
resp = app.get('/manage/resource/%s/%s/%s/' % (resource.pk, today.year, today.month))
assert '<div class="booking' not in resp.text
first_month_day = today.replace(day=1)
last_month_day = today.replace(day=1, month=today.month + 1) - datetime.timedelta(days=1)
start_week_number = first_month_day.isocalendar()[1]
end_week_number = last_month_day.isocalendar()[1]
weeks_number = end_week_number - start_week_number + 1
assert resp.text.count('<tr') == 9 * weeks_number
# book some slots
for hour, minute in [(10, 30), (14, 0)]:
event = Event.objects.create(
agenda=agenda,
places=1,
desk=desk,
meeting_type=meetingtype,
start_datetime=now().replace(hour=hour, minute=minute),
)
event.resources.add(resource)
if hour == 10:
Booking.objects.create(event=event)
else:
Booking.objects.create(event=event, label='foo', user_last_name="bar's")
today = datetime.date.today()
with CaptureQueriesContext(connection) as ctx:
resp = app.get('/manage/resource/%s/%s/%s/' % (resource.pk, today.year, today.month))
assert len(ctx.captured_queries) == 9
assert resp.text.count('<div class="booking" style="height:33.0%;') == 2 # booking cells
assert resp.pyquery.find('div.booking a').not_('.cancel')[0].text.strip() == 'booked'
assert resp.pyquery.find('div.booking a').not_('.cancel')[1].text.strip() == "foo - bar's"
assert get_proper_html_str('foo - bar&#39;s') in resp
agenda.booking_user_block_template = '<b>{{ booking.user_name }}</b> Foo Bar'
agenda.save()
resp = app.get('/manage/resource/%s/%s/%s/' % (resource.pk, today.year, today.month))
assert resp.pyquery.find('div.booking a').not_('.cancel')[0].text.strip() == '<b></b> Foo Bar'
assert resp.pyquery.find('div.booking a').not_('.cancel')[1].text.strip() == "<b>bar's</b> Foo Bar"
assert get_proper_html_str('&lt;b&gt;bar&#39;s&lt;/b&gt; Foo Bar') in resp
# cancel booking
booking = Booking.objects.first()
booking.cancel()
# make sure the are not
resp = app.get('/manage/resource/%s/%s/%s/' % (resource.pk, today.year, today.month))
assert resp.text.count('<div class="booking"') == 1
def test_resource_month_view_weekend(app, admin_user):
resource = Resource.objects.create(label='Foo bar')
agenda = Agenda.objects.create(label='Agenda', kind='meetings')
agenda.resources.add(resource)
desk = Desk.objects.create(agenda=agenda, label='Desk')
MeetingType.objects.create(agenda=agenda, label='Bar', duration=30)
monday = 0
TimePeriod.objects.create(
desk=desk, weekday=monday, start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
)
month, year = 1, 2019
login(app)
resp = app.get('/manage/resource/%s/%s/%s/' % (resource.pk, year, month))
assert 'Sunday' not in resp.text
assert 'Saturday' not in resp.text
# No Monday on first row since month starts a Tuesday
assert len(resp.pyquery.find('tbody tr:first th.weekday:empty')) == 1
# When weekend is hidden, do not display an empty first week
month, year = 12, 2019 # month starts a Sunday
resp = app.get('/manage/resource/%s/%s/%s/' % (resource.pk, year, month))
assert len(resp.pyquery.find('tbody tr:first th.weekday:empty')) == 0
month, year = 6, 2019 # month starts a Saturday
resp = app.get('/manage/resource/%s/%s/%s/' % (resource.pk, year, month))
assert len(resp.pyquery.find('tbody tr:first th.weekday:empty')) == 0
saturday = 5
timeperiod_sat = TimePeriod.objects.create(
desk=desk, weekday=saturday, start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
)
resp = app.get('/manage/resource/%s/%s/%s/' % (resource.pk, year, month))
assert 'Sunday' not in resp.text
assert 'Saturday' in resp.text
assert len(resp.pyquery.find('tbody tr:first th.weekday:empty')) == 5
sunday = 6
TimePeriod.objects.create(
desk=desk, weekday=sunday, start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
)
resp = app.get('/manage/resource/%s/%s/%s/' % (resource.pk, year, month))
assert 'Sunday' in resp.text
assert 'Saturday' in resp.text
timeperiod_sat.delete()
resp = app.get('/manage/resource/%s/%s/%s/' % (resource.pk, year, month))
assert 'Sunday' in resp.text
assert 'Saturday' in resp.text
def test_resource_month_view_dst_change(app, admin_user):
resource = Resource.objects.create(label='Foo bar')
agenda = Agenda.objects.create(label='Agenda', kind='meetings')
agenda.resources.add(resource)
desk = Desk.objects.create(agenda=agenda, label='Desk')
meetingtype = MeetingType.objects.create(agenda=agenda, label='Bar', duration=30)
TimePeriod.objects.create(
desk=desk, weekday=0, start_time=datetime.time(9, 0), end_time=datetime.time(12, 0)
)
login(app)
# book some slots
with freezegun.freeze_time('2019-10-01'):
for start_datetime in [
make_aware(datetime.datetime(2019, 10, 2, 10, 0)),
make_aware(datetime.datetime(2019, 10, 29, 10, 0)),
]:
event = Event.objects.create(
agenda=agenda,
places=1,
desk=desk,
meeting_type=meetingtype,
start_datetime=start_datetime,
)
event.resources.add(resource)
Booking.objects.create(event=event)
# check booked slots are similarly aligned
resp = app.get('/manage/resource/%s/2019/10/' % resource.pk)
assert resp.text.count('height:50.0%;top:100.0%') == 2
def test_resource_month_view_januaries(app, admin_user):
resource = Resource.objects.create(label='Foo bar')
agenda = Agenda.objects.create(label='Agenda', kind='meetings')
agenda.resources.add(resource)
desk = Desk.objects.create(agenda=agenda, label='Desk')
TimePeriod(desk=desk, weekday=2, start_time=datetime.time(9, 0), end_time=datetime.time(12, 0)).save()
for year in range(2020, 2030):
date = datetime.date(year, 1, 1)
with freezegun.freeze_time(date):
login(app)
resp = app.get('/manage/resource/%s/%s/1/' % (resource.pk, date.year))
assert resp.text.count('<th class="weeknum">') in (4, 5)
def test_resource_month_view_event_outside_timeperiod(app, admin_user):
today = datetime.date.today()
resource = Resource.objects.create(label='Foo bar')
agenda = Agenda.objects.create(label='Agenda', kind='meetings')
agenda.resources.add(resource)
desk = Desk.objects.create(agenda=agenda, label='Desk')
meetingtype = MeetingType.objects.create(agenda=agenda, label='Bar', duration=30)
login(app)
# no time period - no events
resp = app.get('/manage/resource/%s/%d/%d/' % (resource.pk, today.year, today.month))
assert 'No bookings this month.' in resp.text
assert 'div class="booking' not in resp.text
# book some slots
middle_day = now().replace(day=15)
for hour, minute in [(9, 0), (17, 0)]:
event = Event.objects.create(
agenda=agenda,
places=1,
desk=desk,
meeting_type=meetingtype,
start_datetime=localtime(now()).replace(
day=middle_day.day - middle_day.weekday() + 2, hour=hour, minute=minute
),
)
event.resources.add(resource)
Booking.objects.create(event=event)
# no time period - events are displayed
resp = app.get('/manage/resource/%s/%d/%d/' % (resource.pk, today.year, today.month))
assert resp.text.count('div class="booking') == 2
# events outside time period
TimePeriod.objects.create(
desk=desk, weekday=2, start_time=datetime.time(10, 0), end_time=datetime.time(16, 0)
)
resp = app.get('/manage/resource/%s/%d/%d/' % (resource.pk, today.year, today.month))
assert resp.text.count('div class="booking') == 2
assert 'Sunday' not in resp.text
assert 'Saturday' not in resp.text
# bookings are cancelled
Booking.objects.update(cancellation_datetime=now())
resp = app.get('/manage/resource/%s/%d/%d/' % (resource.pk, today.year, today.month))
assert resp.text.count('div class="booking') == 0
# create an event on saturday
Booking.objects.update(cancellation_datetime=None) # reset
event = Event.objects.create(
agenda=agenda,
places=1,
desk=desk,
meeting_type=meetingtype,
start_datetime=localtime(now()).replace(
day=middle_day.day - middle_day.weekday() + 5, hour=10, minute=0
),
)
event.resources.add(resource)
Booking.objects.create(event=event)
resp = app.get('/manage/resource/%s/%d/%d/' % (resource.pk, today.year, today.month))
assert resp.text.count('div class="booking') == 3
assert 'Sunday' not in resp.text
assert 'Saturday' in resp.text
# bookings are cancelled
Booking.objects.update(cancellation_datetime=now())
resp = app.get('/manage/resource/%s/%d/%d/' % (resource.pk, today.year, today.month))
assert resp.text.count('div class="booking') == 0
# and a timeperiod
Booking.objects.update(cancellation_datetime=None) # reset
TimePeriod.objects.create(
desk=desk, weekday=5, start_time=datetime.time(11, 0), end_time=datetime.time(12, 0)
)
resp = app.get('/manage/resource/%s/%d/%d/' % (resource.pk, today.year, today.month))
assert resp.text.count('div class="booking') == 3
assert 'Sunday' not in resp.text
assert 'Saturday' in resp.text
# create an event on sunday
middle_day = now().replace(day=15)
event = Event.objects.create(
agenda=agenda,
places=1,
desk=desk,
meeting_type=meetingtype,
start_datetime=localtime(now()).replace(
day=middle_day.day - middle_day.weekday() + 6, hour=10, minute=0
),
)
event.resources.add(resource)
Booking.objects.create(event=event)
resp = app.get('/manage/resource/%s/%d/%d/' % (resource.pk, today.year, today.month))
assert resp.text.count('div class="booking') == 4
assert 'Sunday' in resp.text
assert 'Saturday' in resp.text
# bookings are cancelled
Booking.objects.update(cancellation_datetime=now())
resp = app.get('/manage/resource/%s/%d/%d/' % (resource.pk, today.year, today.month))
assert resp.text.count('div class="booking') == 0
# and a timeperiod
Booking.objects.update(cancellation_datetime=None) # reset
TimePeriod.objects.create(
desk=desk, weekday=6, start_time=datetime.time(11, 0), end_time=datetime.time(12, 0)
)
resp = app.get('/manage/resource/%s/%d/%d/' % (resource.pk, today.year, today.month))
assert resp.text.count('div class="booking') == 4
assert 'Sunday' in resp.text
assert 'Saturday' in resp.text
def test_month_view_resource_as_manager(app, manager_user):
agenda = Agenda.objects.create(label='Foo Bar', kind='meetings')
agenda.view_role = manager_user.groups.all()[0]
agenda.save()
resource = Resource.objects.create(label='Resource 1')
app = login(app, username='manager', password='manager')
today = datetime.date.today()
app.get('/manage/resource/%s/%d/%d/' % (resource.pk, today.year, today.month), status=403)
def test_edit_resource(app, admin_user):
resource = Resource.objects.create(label='Foo bar')
app = login(app)
resp = app.get('/manage/resource/%s/' % resource.pk, status=200)
resp = resp.click('Edit')
resp.form['label'] = 'Foo bar baz'
resp.form['slug'] = 'baz'
resp = resp.form.submit()
assert resp.location.endswith('/manage/resource/%s/' % resource.pk)
resource.refresh_from_db()
assert resource.label == 'Foo bar baz'
assert resource.slug == 'baz'
def test_edit_resource_as_manager(app, manager_user):
agenda = Agenda.objects.create(label='Foo Bar', kind='meetings')
agenda.view_role = manager_user.groups.all()[0]
agenda.save()
resource = Resource.objects.create(label='Resource 1')
app = login(app, username='manager', password='manager')
app.get('/manage/resource/%s/edit/' % resource.pk, status=403)
def test_delete_resource(app, admin_user):
resource = Resource.objects.create(label='Foo bar')
app = login(app)
resp = app.get('/manage/resource/%s/' % resource.pk, status=200)
resp = resp.click('Delete')
resp = resp.form.submit()
assert resp.location.endswith('/manage/resources/')
assert Resource.objects.exists() is False
def test_delete_resource_as_manager(app, manager_user):
agenda = Agenda.objects.create(label='Foo Bar', kind='meetings')
agenda.view_role = manager_user.groups.all()[0]
agenda.save()
resource = Resource.objects.create(label='Resource 1')
app = login(app, username='manager', password='manager')
app.get('/manage/resource/%s/delete/' % resource.pk, status=403)
def test_agenda_resources(app, admin_user):
agenda = Agenda.objects.create(label='Foo bar', kind='events')
resource = Resource.objects.create(label='Resource 1')
app = login(app)
# not for events agenda
app.get('/manage/agendas/%s/add-resource/' % agenda.pk, status=404)
app.get('/manage/agendas/%s/resource/%s/delete/' % (agenda.pk, resource.pk), status=404)
def test_meetings_agenda_resources(app, admin_user):
agenda = Agenda.objects.create(label='Foo bar', kind='meetings')
app = login(app)
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
assert 'has_resources' in resp.context
assert resp.context['has_resources'] is False
assert 'Add resource' not in resp.text
resource = Resource.objects.create(label='Resource 1')
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
assert 'has_resources' in resp.context
assert resp.context['has_resources'] is True
assert '/manage/resource/%s/' % resource.pk not in resp.text
assert '/manage/agendas/%s/resource/%s/delete/' % (agenda.pk, resource.pk) not in resp.text
resp = resp.click('Add resource')
assert list(resp.context['form'].fields['resource'].queryset) == [resource]
resp.form['resource'] = resource.pk
resp = resp.form.submit()
assert resp.location.endswith('/manage/agendas/%s/settings#open:resources' % agenda.pk)
assert list(agenda.resources.all()) == [resource]
resp = resp.follow()
assert '/manage/resource/%s/' % resource.pk in resp.text
assert '/manage/agendas/%s/resource/%s/delete/' % (agenda.pk, resource.pk) in resp.text
resp = resp.click('Add resource')
assert list(resp.context['form'].fields['resource'].queryset) == []
resp = app.get('/manage/agendas/%s/resource/%s/delete/' % (agenda.pk, resource.pk))
resp = resp.form.submit()
assert resp.location.endswith('/manage/agendas/%s/settings#open:resources' % agenda.pk)
assert list(agenda.resources.all()) == []
resp = resp.follow()
assert '/manage/resource/%s/' % resource.pk not in resp.text
assert '/manage/agendas/%s/resource/%s/delete/' % (agenda.pk, resource.pk) not in resp.text
@pytest.mark.parametrize(
'view',
(
'/manage/resource/%(resource)s/%(year)d/%(month)d/%(day)d/',
'/manage/resource/%(resource)s/%(year)d/%(month)d/',
),
)
def test_agenda_day_month_view_backoffice_url_translation(
app, admin_user, manager_user, api_user, settings, view
):
today = datetime.date.today()
resource = Resource.objects.create(label='Foo bar')
agenda = Agenda.objects.create(label='Agenda', kind='meetings')
desk = Desk.objects.create(agenda=agenda, label='Desk')
meetingtype = MeetingType.objects.create(agenda=agenda, label='Bar', duration=30)
TimePeriod.objects.create(
desk=desk, weekday=today.weekday(), start_time=datetime.time(10, 0), end_time=datetime.time(18, 30)
)
login(app)
url = view % {'resource': resource.id, 'year': today.year, 'month': today.month, 'day': today.day}
# book some slots
for hour, minute in [(10, 30), (14, 0)]:
event = Event.objects.create(
agenda=agenda,
places=1,
desk=desk,
meeting_type=meetingtype,
start_datetime=now().replace(hour=hour, minute=minute),
)
event.resources.add(resource)
Booking.objects.create(event=event, backoffice_url='publik://default/foo/')
resp = app.get(url)
assert 'http://example.org/foo/' in resp.text
def test_resource_access_permission(app, manager_user):
agenda = Agenda.objects.create(label='Foo Bar', kind='meetings')
resource = Resource.objects.create(label='Resource 1', agenda=agenda)
resource2 = Resource.objects.create(label='Resource 2')
agenda.resources.add(resource)
app = login(app, username='manager', password='manager')
assert app.get('/manage/resource/%s/' % resource.pk, status=403)
assert app.get('/manage/resource/%s/' % resource2.pk, status=403)
agenda.edit_role = manager_user.groups.all()[0]
agenda.save()
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
resp = resp.click('Resource 1')
assert 'Edit' not in resp.text
assert 'Delete' not in resp.text
assert resp.click('Month')
assert resp.click('Week')
assert resp.click('Day')
assert app.get('/manage/resource/%s/' % resource2.pk, status=403)