De-avatarify most of room booking (except room owner)
[cds-indico.git] / indico / modules / rb / models / rooms_test.py
blob019a2906b62ae49dd51a550ac17dd426e2907729
1 # This file is part of Indico.
2 # Copyright (C) 2002 - 2015 European Organization for Nuclear Research (CERN).
4 # Indico is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License as
6 # published by the Free Software Foundation; either version 3 of the
7 # License, or (at your option) any later version.
9 # Indico is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with Indico; if not, see <http://www.gnu.org/licenses/>.
17 import itertools
18 from datetime import timedelta, datetime, date, time
19 from operator import itemgetter
21 import pytest
23 from indico.core.errors import IndicoError
24 from indico.modules.rb import settings as rb_settings
25 from indico.modules.rb.models.blocked_rooms import BlockedRoom
26 from indico.modules.rb.models.photos import Photo
27 from indico.modules.rb.models.reservations import RepeatFrequency
28 from indico.modules.rb.models.room_bookable_hours import BookableHours
29 from indico.modules.rb.models.rooms import Room
30 from indico.testing.util import bool_matrix
31 from indico.util.date_time import get_day_start, get_day_end
32 from indico.util.struct.iterables import powerset
35 pytest_plugins = 'indico.modules.rb.testing.fixtures'
36 _notset = object()
39 def assert_is_in_digest_window(room, expected, expected_with_exclude):
40 assert room.is_in_digest_window() == expected
41 assert room.is_in_digest_window(exclude_first_day=True) == expected_with_exclude
42 assert Room.find_first(Room.is_in_digest_window()) == (room if expected else None)
43 assert Room.find_first(Room.is_in_digest_window(exclude_first_day=True)) == (room if expected_with_exclude
44 else None)
47 digest_window_cases = (
48 # W: window T: today B: both
49 # | OCT |
50 ('2014-10-01', 99, True, True), # |T------------------------------|
51 ('2014-10-01', 99, True, True), # |-T-----------------------------|
52 ('2014-10-16', 31, True, True), # |W--------------T---------------|
53 ('2014-10-16', 17, True, True), # |--------------WT---------------|
54 ('2014-10-16', 16, True, False), # |---------------B---------------|
55 ('2014-10-16', 15, False, False), # |---------------TW--------------|
56 ('2014-10-30', 1, False, False), # |-----------------------------TW|
57 ('2014-10-31', 1, True, False), # |------------------------------B|
58 ('2014-11-01', 1, True, True), # |------------------------------W|T
59 ('2014-11-02', 1, False, False), # |------------------------------W|-T
63 @pytest.mark.parametrize('need_confirmation', (True, False))
64 def test_is_auto_confirm(create_room, need_confirmation):
65 room = create_room(reservations_need_confirmation=need_confirmation)
66 assert room.is_auto_confirm != need_confirmation
67 assert Room.find_first(is_auto_confirm=need_confirmation) is None
68 assert Room.find_first(is_auto_confirm=not need_confirmation) == room
71 def test_urls_transient_object():
72 room = Room()
73 assert room.booking_url is None
74 assert room.details_url is None
75 assert room.large_photo_url is None
76 assert room.small_photo_url is None
79 def test_urls(dummy_room):
80 assert dummy_room.booking_url is not None
81 assert dummy_room.details_url is not None
82 assert dummy_room.large_photo_url is not None
83 assert dummy_room.small_photo_url is not None
86 def test_has_photo(db, dummy_room):
87 assert not dummy_room.has_photo
88 dummy_room.photo = Photo()
89 db.session.flush()
90 assert dummy_room.has_photo
93 @pytest.mark.parametrize(('building', 'floor', 'number', 'name', 'expected_name'), (
94 (u'1', u'2', u'3', u'', u'1-2-3'),
95 (u'1', u'2', u'X', u'', u'1-2-X'),
96 (u'1', u'X', u'3', u'', u'1-X-3'),
97 (u'X', u'2', u'3', u'', u'X-2-3'),
98 (u'1', u'2', u'3', u'Test', u'1-2-3 - Test'),
99 (u'1', u'2', u'3', u'm\xf6p', u'1-2-3 - m\xf6p')
101 def test_full_name(create_room, building, floor, number, name, expected_name):
102 room = create_room(building=building, floor=floor, number=number, name=name)
103 assert room.full_name == expected_name
106 @pytest.mark.parametrize(('name', 'expected'), (
107 (u'', False),
108 (u'1-2-3', False),
109 (u'Test', True),
111 def test_has_special_name(create_room, name, expected):
112 room = create_room(name=name)
113 assert room.has_special_name == expected
116 @pytest.mark.parametrize(('value', 'expected'), (
117 (u'foo', True),
118 (u'', False)
120 def test_has_booking_groups(create_room_attribute, dummy_room, value, expected):
121 create_room_attribute(u'allowed-booking-group')
122 assert not dummy_room.has_booking_groups
123 dummy_room.set_attribute_value(u'allowed-booking-group', value)
124 assert dummy_room.has_booking_groups == expected
127 def test_has_projector(create_equipment_type, dummy_room, db):
128 assert not dummy_room.has_projector
129 dummy_room.available_equipment.append(create_equipment_type(u'Computer Projector'))
130 db.session.flush()
131 assert dummy_room.has_projector
134 def test_has_webcast_recording(create_equipment_type, dummy_room, db):
135 assert not dummy_room.has_webcast_recording
136 dummy_room.available_equipment.append(create_equipment_type(u'Webcast/Recording'))
137 db.session.flush()
138 assert dummy_room.has_webcast_recording
141 def test_has_vc(create_equipment_type, dummy_room, db):
142 assert not dummy_room.has_vc
143 dummy_room.available_equipment.append(create_equipment_type(u'Video conference'))
144 db.session.flush()
145 assert dummy_room.has_vc
148 @pytest.mark.parametrize(('reservable', 'booking_group', 'expected'), (
149 (True, u'', True),
150 (True, u'foo', False),
151 (False, u'', False),
152 (False, u'foo', False)
154 def test_is_public(create_room_attribute, dummy_room, reservable, booking_group, expected):
155 create_room_attribute(u'allowed-booking-group')
156 dummy_room.set_attribute_value(u'allowed-booking-group', booking_group)
157 dummy_room.is_reservable = reservable
158 assert dummy_room.is_public == expected
161 @pytest.mark.parametrize(('is_reservable', 'reservations_need_confirmation', 'booking_group', 'expected_kind'), (
162 (False, False, u'foo', u'privateRoom'),
163 (False, True, u'foo', u'privateRoom'),
164 (True, False, u'foo', u'privateRoom'),
165 (True, True, u'foo', u'privateRoom'),
166 (False, False, u'', u'privateRoom'),
167 (False, True, u'', u'privateRoom'),
168 (True, False, u'', u'basicRoom'),
169 (True, True, u'', u'moderatedRoom')
171 def test_kind(create_room, create_room_attribute,
172 is_reservable, reservations_need_confirmation, booking_group, expected_kind):
173 room = create_room(is_reservable=is_reservable, reservations_need_confirmation=reservations_need_confirmation)
174 create_room_attribute(u'allowed-booking-group')
175 room.set_attribute_value(u'allowed-booking-group', booking_group)
176 assert room.kind == expected_kind
179 def test_location_name(dummy_room, dummy_location):
180 assert dummy_room.location_name == dummy_location.name
183 @pytest.mark.parametrize(('capacity', 'is_reservable', 'reservations_need_confirmation', 'has_vc', 'expected'), (
184 (1, False, True, False, u'1 person, private, needs confirmation'),
185 (2, False, True, False, u'2 people, private, needs confirmation'),
186 (2, True, True, False, u'2 people, public, needs confirmation'),
187 (2, False, False, False, u'2 people, private, auto-confirmation'),
188 (2, False, True, True, u'2 people, private, needs confirmation, videoconference')
190 def test_marker_description(db, create_room, create_equipment_type,
191 capacity, is_reservable, reservations_need_confirmation, has_vc, expected):
192 room = create_room(capacity=capacity, is_reservable=is_reservable,
193 reservations_need_confirmation=reservations_need_confirmation)
194 if has_vc:
195 room.available_equipment.append(create_equipment_type(u'Video conference'))
196 db.session.flush()
197 assert room.marker_description == expected
200 def test_owner(dummy_room, dummy_user):
201 assert dummy_room.owner == dummy_user
204 def test_owner_after_change(dummy_room, create_user):
205 other_user = create_user(123)
206 dummy_room.owner = other_user
207 assert dummy_room.owner == other_user
210 @pytest.mark.parametrize(('value', 'emails'), (
211 (u'', set()),
212 (u'example@example.com', {u'example@example.com'}),
213 (u' example@example.com ,m\xf6p@example.cm\xf6pm ', {u'example@example.com', u'm\xf6p@example.cm\xf6pm'}),
215 def test_notification_emails(create_room_attribute, dummy_room, value, emails):
216 create_room_attribute(u'notification-email')
217 dummy_room.set_attribute_value(u'notification-email', value)
218 assert dummy_room.notification_emails == emails
221 @pytest.mark.parametrize(('name', 'expected'), (
222 (u'foo', True),
223 (u'bar', True),
224 (u'xxx', False), # existent
225 (u'yyy', False), # not existent
227 def test_has_equipment(create_equipment_type, dummy_room, name, expected):
228 dummy_room.available_equipment.append(create_equipment_type(u'foo'))
229 dummy_room.available_equipment.append(create_equipment_type(u'bar'))
230 create_equipment_type(u'xxx')
231 assert dummy_room.has_equipment(name) == expected
234 def test_find_available_vc_equipment(db, dummy_room, create_equipment_type):
235 foo = create_equipment_type(u'foo')
236 vc = create_equipment_type(u'Video conference')
237 vc_items = [create_equipment_type(u'vc1'), create_equipment_type(u'vc2')]
238 vc.children += vc_items
239 dummy_room.available_equipment.extend(vc_items + [vc, foo])
240 db.session.flush()
241 assert set(dummy_room.find_available_vc_equipment()) == set(vc_items)
244 def test_get_attribute_by_name(create_room_attribute, dummy_room):
245 attr = create_room_attribute(u'foo')
246 assert dummy_room.get_attribute_by_name(u'foo') is None
247 dummy_room.set_attribute_value(u'foo', u'bar')
248 assert dummy_room.get_attribute_by_name(u'foo').attribute == attr
251 def test_has_attribute(create_room_attribute, dummy_room):
252 create_room_attribute(u'foo')
253 assert not dummy_room.has_attribute(u'foo')
254 dummy_room.set_attribute_value(u'foo', u'bar')
255 assert dummy_room.has_attribute(u'foo')
258 @pytest.mark.parametrize(('value', 'expected'), (
259 (u'', _notset),
260 (None, _notset),
261 (0, _notset),
262 ([], _notset),
263 (u'foo', u'foo'),
264 (123, 123),
265 (True, True),
266 (['a', 'b'], ['a', 'b']),
268 def test_get_attribute_value(create_room_attribute, dummy_room, value, expected):
269 assert dummy_room.get_attribute_value(u'foo', _notset) is _notset
270 create_room_attribute(u'foo')
271 assert dummy_room.get_attribute_value(u'foo', _notset) is _notset
272 dummy_room.set_attribute_value(u'foo', value)
273 assert dummy_room.get_attribute_value(u'foo', _notset) == expected
276 def test_set_attribute_value(create_room_attribute, dummy_room):
277 # setting an attribute that doesn't exist fails
278 with pytest.raises(ValueError):
279 dummy_room.set_attribute_value(u'foo', u'something')
280 create_room_attribute(u'foo')
281 # the value can be cleared even if it is not set
282 dummy_room.set_attribute_value(u'foo', None)
283 assert dummy_room.get_attribute_value(u'foo', _notset) is _notset
284 # set it to some value
285 dummy_room.set_attribute_value(u'foo', u'test')
286 assert dummy_room.get_attribute_value(u'foo') == u'test'
287 # set to some other value while we have an existing association entry
288 dummy_room.set_attribute_value(u'foo', u'something')
289 assert dummy_room.get_attribute_value(u'foo') == u'something'
290 # clear it
291 dummy_room.set_attribute_value(u'foo', None)
292 assert dummy_room.get_attribute_value(u'foo', _notset) is _notset
295 def test_getLocator(dummy_location, dummy_room):
296 assert dummy_room.getLocator() == {'roomLocation': dummy_location.name, 'roomID': dummy_room.id}
299 @pytest.mark.parametrize(('building', 'floor', 'number', 'name', 'expected_name'), (
300 (u'1', u'2', u'3', u'', u'1-2-3'),
301 (u'1', u'2', u'X', u'', u'1-2-X'),
302 (u'1', u'X', u'3', u'', u'1-X-3'),
303 (u'X', u'2', u'3', u'', u'X-2-3'),
304 (u'1', u'2', u'3', u'Test', u'Test')
306 def test_update_name(create_room, building, floor, number, name, expected_name):
307 room = create_room()
308 room.building = building
309 room.floor = floor
310 room.number = number
311 room.name = name
312 assert room.name == name
313 room.update_name()
314 assert room.name == expected_name
317 def test_find_all(create_location, create_room):
318 # Here we just test if we get the rooms in natural sort order
319 loc1 = create_location('Z')
320 loc2 = create_location('A')
321 data = [
322 (2, dict(location=loc1, building=u'1', floor=u'2', number=u'3', name=u'')),
323 (3, dict(location=loc1, building=u'2', floor=u'2', number=u'3', name=u'')),
324 (5, dict(location=loc1, building=u'100', floor=u'2', number=u'3', name=u'')),
325 (4, dict(location=loc1, building=u'10', floor=u'2', number=u'3', name=u'')),
326 (1, dict(location=loc2, building=u'999', floor=u'2', number=u'3', name=u''))
328 rooms = [(pos, create_room(**params)) for pos, params in data]
329 sorted_rooms = map(itemgetter(1), sorted(rooms, key=itemgetter(0)))
330 assert sorted_rooms == Room.find_all()
333 def test_find_with_attribute(dummy_room, create_room, create_room_attribute):
334 assert Room.find_all() == [dummy_room] # one room without the attribute
335 assert not Room.find_with_attribute(u'foo')
336 create_room_attribute(u'foo')
337 assert not Room.find_with_attribute(u'foo')
338 expected = set()
339 for room in [create_room(), create_room()]:
340 value = u'bar-{}'.format(room.id)
341 room.set_attribute_value(u'foo', value)
342 expected.add((room, value))
343 assert set(Room.find_with_attribute(u'foo')) == expected
346 def test_get_with_data_errors():
347 with pytest.raises(ValueError):
348 Room.get_with_data(foo='bar')
351 @pytest.mark.parametrize(('only_active', 'data'), list(itertools.product(
352 (True, False),
353 powerset(('equipment', 'vc_equipment', 'non_vc_equipment'))
355 def test_get_with_data(db, create_room, create_equipment_type, only_active, data):
356 eq = create_equipment_type(u'eq')
357 vc = create_equipment_type(u'Video conference')
358 vc1 = create_equipment_type(u'vc1')
359 vc2 = create_equipment_type(u'vc2')
360 vc.children.append(vc1)
361 vc.children.append(vc2)
363 rooms = {
364 'inactive': {'room': create_room(is_active=False),
365 'equipment': set(),
366 'vc_equipment': set(),
367 'non_vc_equipment': set()},
368 'no_eq': {'room': create_room(),
369 'equipment': set(),
370 'vc_equipment': set(),
371 'non_vc_equipment': set()},
372 'non_vc_eq': {'room': create_room(),
373 'equipment': {eq},
374 'vc_equipment': set(),
375 'non_vc_equipment': {eq}},
376 'vc_eq': {'room': create_room(),
377 'equipment': {vc, vc1, vc2},
378 'vc_equipment': {vc1, vc2},
379 'non_vc_equipment': {vc}},
380 'all_eq': {'room': create_room(),
381 'equipment': {eq, vc, vc1, vc2},
382 'vc_equipment': {vc1, vc2},
383 'non_vc_equipment': {vc, eq}}
385 room_types = {room_data['room']: type_ for type_, room_data in rooms.iteritems()}
386 for room in rooms.itervalues():
387 room['room'].available_equipment = room['equipment']
388 db.session.flush()
389 results = list(Room.get_with_data(*data, only_active=only_active))
390 assert len(results) == len(rooms) - only_active
391 for row in results:
392 room = row.pop('room')
393 assert row.viewkeys() == set(data)
394 room_type = room_types[room]
395 if room_type == 'inactive':
396 assert not only_active
397 for key in data:
398 assert set(row[key]) == {x.name for x in rooms[room_type][key]}
401 def test_max_capacity(create_room):
402 assert not Room.query.count()
403 assert Room.max_capacity == 0
404 create_room(capacity=0)
405 assert Room.max_capacity == 0
406 create_room(capacity=10)
407 create_room(capacity=5)
408 assert Room.max_capacity == 10
411 @pytest.mark.parametrize(
412 ('has_booking', 'has_blocking',
413 'has_pre_booking', 'include_pre_bookings',
414 'has_pending_blocking', 'include_pending_blockings',
415 'filtered'),
416 set(bool_matrix('00.0.0', expect=False) + # nothing confirmed/pending
417 bool_matrix('000.0.', expect=False) + # nothing pending included
418 bool_matrix('1.....', expect=True) + # confirmed booking
419 bool_matrix('.1....', expect=True) + # active blocking
420 bool_matrix('00....', expect=lambda x: all(x[2:4]) or all(x[4:6]))) # included pending booking/blocking
422 def test_filter_available(dummy_room, create_reservation, create_blocking,
423 has_booking, has_blocking,
424 has_pre_booking, include_pre_bookings,
425 has_pending_blocking, include_pending_blockings, filtered):
426 if has_booking:
427 create_reservation(start_dt=datetime.combine(date.today(), time(8)),
428 end_dt=datetime.combine(date.today(), time(10)))
429 if has_pre_booking:
430 create_reservation(start_dt=datetime.combine(date.today(), time(10)),
431 end_dt=datetime.combine(date.today(), time(12)),
432 is_accepted=False)
433 if has_blocking:
434 create_blocking(state=BlockedRoom.State.accepted)
435 if has_pending_blocking:
436 create_blocking(state=BlockedRoom.State.pending)
437 availabilty_filter = Room.filter_available(get_day_start(date.today()), get_day_end(date.today()),
438 (RepeatFrequency.NEVER, 0),
439 include_pre_bookings=include_pre_bookings,
440 include_pending_blockings=include_pending_blockings)
441 assert set(Room.find_all(availabilty_filter)) == (set() if filtered else {dummy_room})
444 def test_find_with_filters(db, dummy_room, create_room, dummy_user, create_equipment_type, create_room_attribute,
445 dummy_reservation):
446 # Simple testcase that ensures we find the room when many filters are used
447 other_room = create_room()
448 assert set(Room.find_with_filters({}, dummy_user)) == {dummy_room, other_room}
449 create_room_attribute(u'attr')
450 eq = create_equipment_type(u'eq')
451 dummy_room.capacity = 100
452 dummy_room.is_reservable = True
453 dummy_room.available_equipment.append(eq)
454 dummy_room.set_attribute_value(u'attr', u'meowmeow')
455 db.session.flush()
456 filters = {'available_equipment': {eq},
457 'capacity': 90,
458 'only_public': True,
459 'is_only_my_rooms': True,
460 'details': u'meow',
461 'available': 0,
462 'repeatability': 'None',
463 'start_dt': dummy_reservation.start_dt,
464 'end_dt': dummy_reservation.end_dt}
465 assert set(Room.find_with_filters(filters, dummy_user)) == {dummy_room}
468 def test_find_with_filters_equipment(db, dummy_room, create_room, create_equipment_type):
469 other_room = create_room()
470 assert set(Room.find_with_filters({}, None)) == set(Room.find_all())
471 eq1 = create_equipment_type(u'eq1')
472 eq2 = create_equipment_type(u'eq2')
473 assert not Room.find_with_filters({'available_equipment': {eq1}}, None)
474 dummy_room.available_equipment.append(eq1)
475 db.session.flush()
476 assert set(Room.find_with_filters({'available_equipment': {eq1}}, None)) == {dummy_room}
477 assert not Room.find_with_filters({'available_equipment': {eq1, eq2}}, None)
478 dummy_room.available_equipment.append(eq2)
479 other_room.available_equipment.append(eq2)
480 db.session.flush()
481 assert set(Room.find_with_filters({'available_equipment': {eq1}}, None)) == {dummy_room}
482 assert set(Room.find_with_filters({'available_equipment': {eq2}}, None)) == {dummy_room, other_room}
483 assert set(Room.find_with_filters({'available_equipment': {eq1, eq2}}, None)) == {dummy_room}
486 @pytest.mark.parametrize(('capacity', 'other_capacity', 'search_capacity', 'match', 'match_other'), (
487 (100, 79, 100, True, False), # 79 outside 80..120
488 (110, 95, 100, True, True), # 110, 95 inside 80..120
489 (120, 80, 100, True, True), # 120, 80 exactly on the edges
490 (121, 80, 100, False, True), # 121 outside range
491 (121, 50, 100, True, False), # 121 exceeds upper bound = match anyway to avoid getting no results
492 (79, 50, 100, False, False), # 79 outside lower bound => hard limit
493 (None, 999, 999, True, True), # no capacity always matches
495 def test_find_with_filters_capacity(db, dummy_room, create_room,
496 capacity, other_capacity, search_capacity, match, match_other):
497 other_room = create_room()
498 assert set(Room.find_with_filters({}, None)) == set(Room.find_all())
499 dummy_room.capacity = capacity
500 other_room.capacity = other_capacity
501 db.session.flush()
502 expected = set()
503 if match:
504 expected.add(dummy_room)
505 if match_other:
506 expected.add(other_room)
507 assert set(Room.find_with_filters({'capacity': search_capacity}, None)) == expected
510 @pytest.mark.parametrize(('is_reservable', 'booking_group', 'match'), (
511 (True, None, True),
512 (True, u'foo', False),
513 (False, None, False),
514 (False, u'foo', False)
516 def test_find_with_filters_only_public(dummy_room, create_room_attribute,
517 is_reservable, booking_group, match):
518 create_room_attribute(u'allowed-booking-group')
519 dummy_room.is_reservable = is_reservable
520 dummy_room.set_attribute_value(u'allowed-booking-group', booking_group)
521 if match:
522 assert set(Room.find_with_filters({'is_only_public': True}, None)) == {dummy_room}
523 else:
524 assert not Room.find_with_filters({'is_only_public': True}, None)
527 @pytest.mark.parametrize(('owner_id', 'match'), (
528 (1337, True),
529 (123, False)
531 def test_find_with_filters_only_my_rooms(dummy_room, create_user, owner_id, match):
532 user = create_user(owner_id)
533 if match:
534 assert set(Room.find_with_filters({'is_only_my_rooms': True}, user)) == {dummy_room}
535 else:
536 assert not Room.find_with_filters({'is_only_my_rooms': True}, user)
539 @pytest.mark.parametrize('available', (True, False))
540 def test_find_with_filters_availability(dummy_room, dummy_reservation, available):
541 if available:
542 start_dt = dummy_reservation.end_dt + timedelta(days=1)
543 end_dt = start_dt + timedelta(days=1)
544 else:
545 start_dt = dummy_reservation.start_dt
546 end_dt = dummy_reservation.end_dt
547 filters = {'available': int(available),
548 'repeatability': 'None',
549 'start_dt': start_dt,
550 'end_dt': end_dt}
551 assert set(Room.find_with_filters(filters, None)) == {dummy_room}
554 def test_find_with_filters_availability_error():
555 with pytest.raises(ValueError):
556 filters = {'available': 123,
557 'repeatability': 'None',
558 'start_dt': datetime.now(),
559 'end_dt': datetime.now()}
560 Room.find_with_filters(filters, None)
563 @pytest.mark.parametrize('col', ('name', 'site', 'division', 'building', 'floor', 'number', 'telephone',
564 'key_location', 'comments'))
565 def test_find_with_filters_details_cols(db, dummy_room, create_room, col):
566 create_room() # some room we won't find!
567 assert set(Room.find_with_filters({}, None)) == set(Room.find_all())
568 assert not Room.find_with_filters({'details': u'meow'}, None)
569 setattr(dummy_room, col, u'meow')
570 db.session.flush()
571 assert set(Room.find_with_filters({'details': u'meow'}, None)) == {dummy_room}
574 find_with_filters_details = (
575 (u'meow', u'meow', None),
576 (u'meow', u'MEOW', None),
577 (u'foo"bar', u'foo"bar', None),
578 (ur'foo\bar', ur'foo\bar', None),
579 (u'test%bla', u'test%bla', u'testXbla'),
580 (u'test_bla', u'test_bla', u'testXbla')
584 @pytest.mark.parametrize(('value', 'search_value', 'other_value'), find_with_filters_details)
585 def test_find_with_filters_details_values(db, dummy_room, create_room, value, search_value, other_value):
586 other_room = create_room()
587 assert set(Room.find_with_filters({}, None)) == set(Room.find_all())
588 assert not Room.find_with_filters({'details': search_value}, None)
589 dummy_room.comments = value
590 other_room.comments = other_value
591 db.session.flush()
592 assert set(Room.find_with_filters({'details': search_value}, None)) == {dummy_room}
595 @pytest.mark.parametrize(('value', 'search_value', 'other_value'), find_with_filters_details)
596 def test_find_with_filters_details_attrs(dummy_room, create_room, create_room_attribute,
597 value, search_value, other_value):
598 other_room = create_room()
599 assert set(Room.find_with_filters({}, None)) == set(Room.find_all())
600 assert not Room.find_with_filters({'details': search_value}, None)
601 create_room_attribute(u'foo')
602 assert not Room.find_with_filters({'details': search_value}, None)
603 dummy_room.set_attribute_value(u'foo', value)
604 other_room.set_attribute_value(u'foo', other_value)
605 assert set(Room.find_with_filters({'details': search_value}, None)) == {dummy_room}
608 def test_has_live_reservations(dummy_room, create_reservation):
609 assert not dummy_room.has_live_reservations()
610 create_reservation(start_dt=datetime.combine(date.today() - timedelta(days=1), time(8)),
611 end_dt=datetime.combine(date.today() - timedelta(days=1), time(10)))
612 assert not dummy_room.has_live_reservations()
613 create_reservation(start_dt=datetime.combine(date.today() + timedelta(days=1), time(8)),
614 end_dt=datetime.combine(date.today() + timedelta(days=1), time(10)))
615 assert dummy_room.has_live_reservations()
618 @pytest.mark.parametrize(
619 ('is_admin', 'ignore_admin', 'is_active', 'is_owned_by', 'is_reservable', 'has_group', 'in_group', 'expected'),
620 set(bool_matrix('10.....', expect=True) + # admin
621 bool_matrix('..0....', mask='10.....', expect=False, ) + # inactive
622 bool_matrix('..11...', expect=True) + # owned
623 bool_matrix('..100..', mask='10.....', expect=False) + # not reservable
624 bool_matrix('..1010.', expect=True) + # no group
625 bool_matrix('..1011.', mask='10.....', expect=lambda x: x[6])) # user in group
627 def test_can_be_booked(dummy_room, create_user, create_room_attribute, create_group,
628 is_admin, ignore_admin, is_active, is_owned_by, is_reservable, has_group, in_group, expected):
629 create_room_attribute(u'allowed-booking-group')
630 user = create_user(123, rb_admin=is_admin, legacy=False)
631 dummy_room.is_active = is_active
632 dummy_room.is_reservable = is_reservable
633 if in_group:
634 user.local_groups.add(create_group(123).group)
635 if is_owned_by:
636 dummy_room.owner = user.as_avatar
637 if has_group:
638 dummy_room.set_attribute_value(u'allowed-booking-group', u'123')
639 assert dummy_room.can_be_booked(user, ignore_admin=ignore_admin) == expected
640 assert dummy_room.can_be_prebooked(user, ignore_admin=ignore_admin) == expected
643 @pytest.mark.parametrize(
644 ('is_admin', 'ignore_admin', 'is_active', 'is_owned_by', 'is_reservable', 'has_group', 'in_group', 'expected'),
645 set(bool_matrix('10.....', expect=True) + # admin
646 bool_matrix('..0....', mask='10.....', expect=False, ) + # inactive
647 bool_matrix('..11...', expect=True) + # owned
648 bool_matrix('..100..', mask='10.....', expect=False) + # not reservable
649 bool_matrix('..1010.', expect=True) + # no group
650 bool_matrix('..1011.', mask='10.....', expect=lambda x: x[6])) # user in group
652 def test_can_be_prebooked(dummy_room, create_user, create_room_attribute, create_group,
653 is_admin, ignore_admin, is_active, is_owned_by, is_reservable, has_group, in_group, expected):
654 create_room_attribute(u'allowed-booking-group')
655 user = create_user(123, rb_admin=is_admin)
656 dummy_room.is_active = is_active
657 dummy_room.is_reservable = is_reservable
658 dummy_room.reservations_need_confirmation = True
659 if in_group:
660 user.user.local_groups.add(create_group(123).group)
661 if is_owned_by:
662 dummy_room.owner = user
663 if has_group:
664 dummy_room.set_attribute_value(u'allowed-booking-group', u'123')
665 assert dummy_room.can_be_prebooked(user, ignore_admin=ignore_admin) == expected
668 @pytest.mark.parametrize(('has_acl', 'in_acl', 'expected'), (
669 (False, False, True),
670 (True, True, True),
671 (True, False, False),
673 def test_can_be_booked_prebooked_no_rb_access(db, dummy_room, dummy_user, create_user, has_acl, in_acl, expected):
674 user = create_user(123)
675 if has_acl:
676 acl = [(u'Avatar', dummy_user.id)]
677 if in_acl:
678 acl.append((u'Avatar', user.id))
679 rb_settings.set('authorized_principals', acl)
680 db.session.flush()
681 assert dummy_room.can_be_booked(user) == expected
682 assert dummy_room.can_be_prebooked(user) == expected
685 @pytest.mark.parametrize(('is_owner', 'is_admin', 'expected'), bool_matrix('..', expect=any))
686 def test_can_be_overridden(dummy_room, create_user, is_owner, is_admin, expected):
687 user = create_user(123, rb_admin=is_admin)
688 if is_owner:
689 dummy_room.owner = user
690 assert dummy_room.can_be_overridden(user) == expected
693 @pytest.mark.parametrize(('is_admin', 'expected'), (
694 (True, True),
695 (False, False)
697 def test_can_be_modified_deleted(dummy_room, create_user, is_admin, expected):
698 user = create_user(123, rb_admin=is_admin)
699 assert dummy_room.can_be_modified(user) == expected
700 assert dummy_room.can_be_deleted(user) == expected
703 def test_can_be_no_user(dummy_room):
704 assert not dummy_room.can_be_booked(None)
705 assert not dummy_room.can_be_prebooked(None)
706 assert not dummy_room.can_be_overridden(None)
707 assert not dummy_room.can_be_modified(None)
708 assert not dummy_room.can_be_deleted(None)
711 @pytest.mark.parametrize(('is_owner', 'has_group', 'in_group', 'expected'),
712 bool_matrix('...', expect=lambda x: x[0] or all(x[1:])))
713 def test_ownership_functions(dummy_room, create_user, create_room_attribute, create_group,
714 is_owner, has_group, in_group, expected):
715 user = create_user(123)
716 create_room_attribute(u'manager-group')
717 if is_owner:
718 dummy_room.owner = user
719 if has_group:
720 dummy_room.set_attribute_value(u'manager-group', u'123')
721 if in_group:
722 user.user.local_groups.add(create_group(123).group)
723 assert dummy_room.is_owned_by(user) == expected
724 assert Room.user_owns_rooms(user) == expected
725 assert set(Room.get_owned_by(user)) == ({dummy_room} if expected else set())
728 @pytest.mark.parametrize(('is_admin', 'is_owner', 'max_advance_days', 'days_delta', 'success'), (
729 (True, False, 10, 15, True),
730 (False, True, 10, 15, True),
731 (False, False, None, 15, True),
732 (False, False, 0, 15, True),
733 (False, False, 10, -5, True),
734 (False, False, 10, 10, False),
735 (False, False, 10, 15, False)
737 def test_check_advance_days(create_user, dummy_room, is_admin, is_owner, max_advance_days, days_delta, success):
738 user = create_user(123, rb_admin=is_admin)
739 dummy_room.max_advance_days = max_advance_days
740 end_date = date.today() + timedelta(days=days_delta)
741 if is_owner:
742 dummy_room.owner = user
743 if success:
744 assert dummy_room.check_advance_days(end_date, user, quiet=True)
745 assert dummy_room.check_advance_days(end_date, user)
746 else:
747 assert not dummy_room.check_advance_days(end_date, user, quiet=True)
748 with pytest.raises(IndicoError):
749 dummy_room.check_advance_days(end_date, user)
752 def test_check_advance_days_no_user(dummy_room):
753 dummy_room.max_advance_days = 10
754 end_date = date.today() + timedelta(days=15)
755 assert not dummy_room.check_advance_days(end_date, quiet=True)
758 @pytest.mark.parametrize(('is_admin', 'is_owner', 'fits', 'success'), bool_matrix('...', expect=any))
759 def test_check_bookable_hours(db, dummy_room, create_user, is_admin, is_owner, fits, success):
760 user = create_user(123, rb_admin=is_admin)
761 if is_owner:
762 dummy_room.owner = user
763 dummy_room.bookable_hours = [BookableHours(start_time=time(12), end_time=time(14))]
764 db.session.flush()
765 booking_hours = (time(12), time(13)) if fits else (time(8), time(9))
766 if success:
767 assert dummy_room.check_bookable_hours(booking_hours[0], booking_hours[1], user, quiet=True)
768 assert dummy_room.check_bookable_hours(booking_hours[0], booking_hours[1], user)
769 else:
770 assert not dummy_room.check_bookable_hours(booking_hours[0], booking_hours[1], user, quiet=True)
771 with pytest.raises(IndicoError):
772 dummy_room.check_bookable_hours(booking_hours[0], booking_hours[1], user)
775 def test_check_bookable_hours_hours(dummy_room):
776 assert dummy_room.check_bookable_hours(time(8), time(9), quiet=True)
779 def test_check_bookable_hours_no_user(db, dummy_room):
780 dummy_room.bookable_hours = [BookableHours(start_time=time(12), end_time=time(14))]
781 db.session.flush()
782 assert not dummy_room.check_bookable_hours(time(8), time(9), quiet=True)
785 @pytest.mark.parametrize(('current_date', 'notification_window', 'expected', 'expected_with_exclude'),
786 digest_window_cases)
787 def test_is_in_digest_window(db, freeze_time, dummy_room,
788 current_date, notification_window, expected, expected_with_exclude):
789 freeze_time(current_date)
790 dummy_room.notification_before_days = notification_window
791 db.session.flush()
792 assert_is_in_digest_window(dummy_room, expected, expected_with_exclude)
795 @pytest.mark.parametrize(('current_date', 'notification_window', 'expected', 'expected_with_exclude'),
796 digest_window_cases)
797 def test_is_in_digest_window_from_settings(db, freeze_time, dummy_room,
798 current_date, notification_window, expected, expected_with_exclude):
799 freeze_time(current_date)
800 dummy_room.notification_window = None
801 rb_settings.set('notification_before_days', notification_window)
802 db.session.flush()
803 assert_is_in_digest_window(dummy_room, expected, expected_with_exclude)
806 @pytest.mark.parametrize(('current_date', 'expected', 'expected_with_exclude'), (
807 # W: window T: today B: both
808 # | OCT |
809 ('2014-10-30', False, False), # |-----------------------------TW|
810 ('2014-10-31', True, False), # |------------------------------B|
811 ('2014-11-01', True, True), # |------------------------------W|T
812 ('2014-11-02', False, False), # |------------------------------W|-T
814 def test_is_in_digest_window_from_settings_empty(db, freeze_time, dummy_room,
815 current_date, expected, expected_with_exclude):
816 freeze_time(current_date)
817 dummy_room.notification_before_days = None
818 db.session.flush()
819 assert_is_in_digest_window(dummy_room, expected, expected_with_exclude)