14 |
14 |
import requests
|
15 |
15 |
from webtest import Upload
|
16 |
16 |
|
17 |
|
from chrono.wsgi import application
|
18 |
|
|
19 |
17 |
from chrono.agendas.models import (Agenda, Event, Booking, MeetingType,
|
20 |
18 |
TimePeriod, Desk, TimePeriodException)
|
21 |
|
from chrono.manager.utils import export_site
|
22 |
19 |
|
23 |
20 |
pytestmark = pytest.mark.django_db
|
24 |
21 |
|
|
22 |
|
25 |
23 |
@pytest.fixture
|
26 |
24 |
def simple_user():
|
27 |
25 |
try:
|
... | ... | |
30 |
28 |
user = User.objects.create_user('user', password='user')
|
31 |
29 |
return user
|
32 |
30 |
|
|
31 |
|
33 |
32 |
@pytest.fixture
|
34 |
33 |
def manager_user():
|
35 |
34 |
try:
|
... | ... | |
42 |
41 |
user.groups.set([group])
|
43 |
42 |
return user
|
44 |
43 |
|
|
44 |
|
45 |
45 |
@pytest.fixture
|
46 |
46 |
def admin_user():
|
47 |
47 |
try:
|
... | ... | |
50 |
50 |
user = User.objects.create_superuser('admin', email=None, password='admin')
|
51 |
51 |
return user
|
52 |
52 |
|
|
53 |
|
53 |
54 |
@pytest.fixture
|
54 |
55 |
def api_user():
|
55 |
56 |
try:
|
56 |
57 |
user = User.objects.get(username='api-user')
|
57 |
58 |
except User.DoesNotExist:
|
58 |
|
user = User.objects.create(username='john.doe',
|
59 |
|
first_name=u'John', last_name=u'Doe', email='john.doe@example.net')
|
|
59 |
user = User.objects.create(
|
|
60 |
username='john.doe',
|
|
61 |
first_name=u'John', last_name=u'Doe', email='john.doe@example.net')
|
60 |
62 |
user.set_password('password')
|
61 |
63 |
user.save()
|
62 |
64 |
return user
|
63 |
65 |
|
|
66 |
|
64 |
67 |
def login(app, username='admin', password='admin'):
|
65 |
68 |
login_page = app.get('/login/')
|
66 |
69 |
login_form = login_page.forms[0]
|
... | ... | |
70 |
73 |
assert resp.status_int == 302
|
71 |
74 |
return app
|
72 |
75 |
|
|
76 |
|
73 |
77 |
def test_unlogged_access(app):
|
74 |
78 |
# connect while not being logged in
|
75 |
79 |
assert app.get('/manage/', status=302).location.endswith('/login/?next=/manage/')
|
76 |
80 |
|
|
81 |
|
77 |
82 |
def test_simple_user_access(app, simple_user):
|
78 |
83 |
# connect while being logged as a simple user, access should be forbidden
|
79 |
84 |
app = login(app, username='user', password='user')
|
80 |
85 |
assert app.get('/manage/', status=403)
|
81 |
86 |
|
|
87 |
|
82 |
88 |
def test_manager_user_access(app, manager_user):
|
83 |
89 |
# connect while being logged as a manager user, access should be granted if
|
84 |
90 |
# there's at least an agenda that is viewable or editable.
|
... | ... | |
99 |
105 |
agenda.save()
|
100 |
106 |
assert app.get('/manage/', status=200)
|
101 |
107 |
|
|
108 |
|
102 |
109 |
def test_home_redirect(app):
|
103 |
110 |
assert app.get('/', status=302).location.endswith('/manage/')
|
104 |
111 |
|
|
112 |
|
105 |
113 |
def test_access(app, admin_user):
|
106 |
114 |
app = login(app)
|
107 |
115 |
resp = app.get('/manage/', status=200)
|
108 |
116 |
assert '<h2>Agendas</h2>' in resp.text
|
109 |
117 |
assert "This site doesn't have any agenda yet." in resp.text
|
110 |
118 |
|
|
119 |
|
111 |
120 |
def test_logout(app, admin_user):
|
112 |
121 |
app = login(app)
|
113 |
122 |
app.get('/logout/')
|
114 |
123 |
assert app.get('/manage/', status=302).location.endswith('/login/?next=/manage/')
|
115 |
124 |
|
|
125 |
|
116 |
126 |
def test_menu_json(app, admin_user):
|
117 |
127 |
app = login(app)
|
118 |
128 |
resp = app.get('/manage/menu.json', status=200)
|
... | ... | |
123 |
133 |
assert resp2.text == 'Q(%s);' % resp.text
|
124 |
134 |
assert resp2.content_type == 'application/javascript'
|
125 |
135 |
|
|
136 |
|
126 |
137 |
def test_view_agendas_as_manager(app, manager_user):
|
127 |
138 |
agenda = Agenda(label=u'Foo Bar')
|
128 |
139 |
agenda.view_role = manager_user.groups.all()[0]
|
... | ... | |
143 |
154 |
# check view gives access to the settings page for "events" agenda
|
144 |
155 |
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)
|
145 |
156 |
# but there's no links to actions
|
146 |
|
assert not '>New Event<' in resp.text
|
147 |
|
assert not '>Options<' in resp.text
|
|
157 |
assert '>New Event<' not in resp.text
|
|
158 |
assert '>Options<' not in resp.text
|
148 |
159 |
app.get('/manage/agendas/%s/add-event' % agenda.id, status=403)
|
149 |
160 |
app.get('/manage/agendas/%s/edit' % agenda.id, status=403)
|
150 |
161 |
|
... | ... | |
156 |
167 |
# check it gives a 404 on unknown agendas
|
157 |
168 |
resp = app.get('/manage/agendas/%s/settings' % '9999', status=404)
|
158 |
169 |
|
|
170 |
|
159 |
171 |
def test_add_agenda(app, admin_user):
|
160 |
172 |
app = login(app)
|
161 |
173 |
resp = app.get('/manage/', status=200)
|
... | ... | |
169 |
181 |
assert 'Foo bar' in resp.text
|
170 |
182 |
assert '<h2>Settings' in resp.text
|
171 |
183 |
|
|
184 |
|
172 |
185 |
def test_add_agenda_as_manager(app, manager_user):
|
173 |
186 |
# open /manage/ access to manager_user, and check agenda creation is not
|
174 |
187 |
# allowed.
|
... | ... | |
176 |
189 |
agenda.view_role = manager_user.groups.all()[0]
|
177 |
190 |
agenda.save()
|
178 |
191 |
app = login(app, username='manager', password='manager')
|
179 |
|
resp = app.get('/manage/', status=200)
|
180 |
|
resp = app.get('/manage/agendas/add/', status=403)
|
|
192 |
app.get('/manage/', status=200)
|
|
193 |
app.get('/manage/agendas/add/', status=403)
|
|
194 |
|
181 |
195 |
|
182 |
196 |
def test_options_agenda(app, admin_user):
|
183 |
197 |
agenda = Agenda(label=u'Foo bar')
|
... | ... | |
194 |
208 |
assert 'Foo baz' in resp.text
|
195 |
209 |
assert '<h2>Settings' in resp.text
|
196 |
210 |
|
|
211 |
|
197 |
212 |
def test_options_agenda_as_manager(app, manager_user):
|
198 |
213 |
agenda = Agenda(label=u'Foo bar')
|
199 |
214 |
agenda.view_role = manager_user.groups.all()[0]
|
... | ... | |
201 |
216 |
app = login(app, username='manager', password='manager')
|
202 |
217 |
resp = app.get('/manage/', status=200)
|
203 |
218 |
resp = resp.click('Foo bar')
|
204 |
|
assert not 'Settings' in resp.text
|
|
219 |
assert 'Settings' not in resp.text
|
205 |
220 |
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200) # ok for "events" agendas
|
206 |
221 |
resp = app.get('/manage/agendas/%s/edit' % agenda.id, status=403)
|
207 |
222 |
agenda.kind = 'meetings'
|
... | ... | |
227 |
242 |
assert 'Foo baz' in resp.text
|
228 |
243 |
assert '<h2>Settings' in resp.text
|
229 |
244 |
|
|
245 |
|
230 |
246 |
def test_delete_agenda(app, admin_user):
|
231 |
247 |
agenda = Agenda(label=u'Foo bar')
|
232 |
248 |
agenda.save()
|
... | ... | |
237 |
253 |
resp = resp.form.submit()
|
238 |
254 |
assert resp.location.endswith('/manage/')
|
239 |
255 |
resp = resp.follow()
|
240 |
|
assert not 'Foo bar' in resp.text
|
|
256 |
assert 'Foo bar' not in resp.text
|
|
257 |
|
241 |
258 |
|
242 |
259 |
def test_delete_busy_agenda(app, admin_user):
|
243 |
260 |
agenda = Agenda(label=u'Foo bar')
|
... | ... | |
272 |
289 |
booking.save()
|
273 |
290 |
resp = resp.form.submit(status=403)
|
274 |
291 |
|
|
292 |
|
275 |
293 |
def test_delete_agenda_as_manager(app, manager_user):
|
276 |
294 |
agenda = Agenda(label=u'Foo bar')
|
277 |
295 |
agenda.edit_role = manager_user.groups.all()[0]
|
... | ... | |
288 |
306 |
agenda = Agenda(label=u'Foo bar', kind='meetings')
|
289 |
307 |
agenda.save()
|
290 |
308 |
desk_a = Desk.objects.create(agenda=agenda, label='Desk A')
|
291 |
|
desk_b = Desk.objects.create(agenda=agenda, label='Desk B')
|
|
309 |
Desk.objects.create(agenda=agenda, label='Desk B')
|
292 |
310 |
|
293 |
311 |
event = Event(start_datetime=now() + datetime.timedelta(days=10),
|
294 |
312 |
places=10, agenda=agenda, desk=desk_a)
|
... | ... | |
329 |
347 |
resp = resp.follow()
|
330 |
348 |
event = Event.objects.get(places=10)
|
331 |
349 |
assert event.slug is None
|
332 |
|
assert not "This agenda doesn't have any event yet." in resp.text
|
|
350 |
assert "This agenda doesn't have any event yet." not in resp.text
|
333 |
351 |
assert '/manage/events/%s/' % event.id in resp.text
|
334 |
352 |
assert ('Feb. 15, %s, 5 p.m.' % year) in resp.text
|
335 |
353 |
assert '10 places' in resp.text
|
... | ... | |
354 |
372 |
app = login(app)
|
355 |
373 |
app.get('/manage/agendas/%s/add-event' % '999', status=404)
|
356 |
374 |
|
|
375 |
|
357 |
376 |
def test_add_event_as_manager(app, manager_user):
|
358 |
377 |
agenda = Agenda(label=u'Foo bar')
|
359 |
378 |
agenda.view_role = manager_user.groups.all()[0]
|
... | ... | |
373 |
392 |
resp = resp.form.submit()
|
374 |
393 |
resp = resp.follow()
|
375 |
394 |
event = Event.objects.get(places=10)
|
376 |
|
assert not "This agenda doesn't have any event yet." in resp.text
|
|
395 |
assert "This agenda doesn't have any event yet." not in resp.text
|
377 |
396 |
assert '/manage/events/%s/' % event.id in resp.text
|
378 |
397 |
assert 'Feb. 15, 2016, 5 p.m.' in resp.text
|
379 |
398 |
assert '10 places' in resp.text
|
380 |
399 |
|
|
400 |
|
381 |
401 |
def test_edit_event(app, admin_user):
|
382 |
402 |
agenda = Agenda(label=u'Foo bar')
|
383 |
403 |
agenda.save()
|
... | ... | |
397 |
417 |
assert 'Feb. 16, 2016, 5 p.m.' in resp.text
|
398 |
418 |
assert '20 places' in resp.text
|
399 |
419 |
|
|
420 |
|
400 |
421 |
def test_edit_missing_event(app, admin_user):
|
401 |
422 |
app = login(app)
|
402 |
423 |
app.get('/manage/agendas/999/', status=404)
|
403 |
424 |
|
|
425 |
|
404 |
426 |
def test_edit_event_as_manager(app, manager_user):
|
405 |
427 |
agenda = Agenda(label=u'Foo bar')
|
406 |
428 |
agenda.view_role = manager_user.groups.all()[0]
|
... | ... | |
424 |
446 |
assert 'Feb. 16, 2016, 5 p.m.' in resp.text
|
425 |
447 |
assert '20 places' in resp.text
|
426 |
448 |
|
|
449 |
|
427 |
450 |
def test_booked_places(app, admin_user):
|
428 |
451 |
agenda = Agenda(label=u'Foo bar')
|
429 |
452 |
agenda.save()
|
... | ... | |
437 |
460 |
assert '10 places' in resp.text
|
438 |
461 |
assert '2 booked places' in resp.text
|
439 |
462 |
|
|
463 |
|
440 |
464 |
def test_event_classes(app, admin_user):
|
441 |
465 |
agenda = Agenda(label=u'Foo bar')
|
442 |
466 |
agenda.save()
|
... | ... | |
448 |
472 |
app = login(app)
|
449 |
473 |
|
450 |
474 |
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)
|
451 |
|
assert not 'full' in resp.text
|
452 |
|
assert not 'overbooking' in resp.text
|
|
475 |
assert 'full' not in resp.text
|
|
476 |
assert 'overbooking' not in resp.text
|
453 |
477 |
|
454 |
478 |
for i in range(8):
|
455 |
479 |
Booking(event=event).save()
|
456 |
480 |
|
457 |
481 |
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)
|
458 |
482 |
assert 'full' in resp.text
|
459 |
|
assert not 'overbooking' in resp.text
|
|
483 |
assert 'overbooking' not in resp.text
|
460 |
484 |
|
461 |
485 |
Booking(event=event).save()
|
462 |
486 |
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)
|
463 |
487 |
assert 'full' in resp.text
|
464 |
488 |
assert 'overbooking' in resp.text
|
465 |
489 |
|
|
490 |
|
466 |
491 |
def test_delete_event(app, admin_user):
|
467 |
492 |
agenda = Agenda(label=u'Foo bar')
|
468 |
493 |
agenda.save()
|
... | ... | |
478 |
503 |
assert resp.location.endswith('/manage/agendas/%s/settings' % agenda.id)
|
479 |
504 |
assert Event.objects.count() == 0
|
480 |
505 |
|
|
506 |
|
481 |
507 |
def test_delete_busy_event(app, admin_user):
|
482 |
508 |
agenda = Agenda(label=u'Foo bar')
|
483 |
509 |
agenda.save()
|
... | ... | |
511 |
537 |
booking.save()
|
512 |
538 |
resp = resp.form.submit(status=403)
|
513 |
539 |
|
|
540 |
|
514 |
541 |
def test_delete_event_as_manager(app, manager_user):
|
515 |
542 |
agenda = Agenda(label=u'Foo bar')
|
516 |
543 |
agenda.edit_role = manager_user.groups.all()[0]
|
... | ... | |
527 |
554 |
assert resp.location.endswith('/manage/agendas/%s/settings' % agenda.id)
|
528 |
555 |
assert Event.objects.count() == 0
|
529 |
556 |
|
|
557 |
|
530 |
558 |
def test_import_events(app, admin_user):
|
531 |
559 |
agenda = Agenda(label=u'Foo bar')
|
532 |
560 |
agenda.save()
|
... | ... | |
590 |
618 |
Event.objects.all().delete()
|
591 |
619 |
|
592 |
620 |
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
|
593 |
|
resp.form['events_csv_file'] = Upload('t.csv',
|
594 |
|
u'2016-09-16,18:00,10,5,éléphant'.encode('utf-8'), 'text/csv')
|
|
621 |
resp.form['events_csv_file'] = Upload(
|
|
622 |
't.csv',
|
|
623 |
u'2016-09-16,18:00,10,5,éléphant'.encode('utf-8'), 'text/csv')
|
595 |
624 |
resp = resp.form.submit(status=302)
|
596 |
625 |
assert Event.objects.count() == 1
|
597 |
626 |
assert Event.objects.all()[0].start_datetime == make_aware(datetime.datetime(2016, 9, 16, 18, 0))
|
... | ... | |
601 |
630 |
Event.objects.all().delete()
|
602 |
631 |
|
603 |
632 |
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
|
604 |
|
resp.form['events_csv_file'] = Upload('t.csv',
|
605 |
|
u'2016-09-16,18:00,10,5,éléphant'.encode('iso-8859-15'), 'text/csv')
|
|
633 |
resp.form['events_csv_file'] = Upload(
|
|
634 |
't.csv',
|
|
635 |
u'2016-09-16,18:00,10,5,éléphant'.encode('iso-8859-15'), 'text/csv')
|
606 |
636 |
resp = resp.form.submit(status=302)
|
607 |
637 |
assert Event.objects.count() == 1
|
608 |
638 |
assert Event.objects.all()[0].start_datetime == make_aware(datetime.datetime(2016, 9, 16, 18, 0))
|
... | ... | |
612 |
642 |
Event.objects.all().delete()
|
613 |
643 |
|
614 |
644 |
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
|
615 |
|
resp.form['events_csv_file'] = Upload('t.csv',
|
616 |
|
u'2016-09-16,18:00,10,5,éléphant'.encode('eucjp'), 'text/csv')
|
|
645 |
resp.form['events_csv_file'] = Upload(
|
|
646 |
't.csv',
|
|
647 |
u'2016-09-16,18:00,10,5,éléphant'.encode('eucjp'), 'text/csv')
|
617 |
648 |
resp = resp.form.submit(status=302)
|
618 |
649 |
assert Event.objects.count() == 1
|
619 |
650 |
assert Event.objects.all()[0].start_datetime == make_aware(datetime.datetime(2016, 9, 16, 18, 0))
|
... | ... | |
623 |
654 |
Event.objects.all().delete()
|
624 |
655 |
|
625 |
656 |
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
|
626 |
|
resp.form['events_csv_file'] = Upload('t.csv', b'date,time,etc.\n'
|
627 |
|
b'2016-09-16,18:00,10,5,bla bla bla\n'
|
628 |
|
b'\n'
|
629 |
|
b'2016-09-19,18:00,10', 'text/csv')
|
|
657 |
resp.form['events_csv_file'] = Upload(
|
|
658 |
't.csv',
|
|
659 |
b'date,time,etc.\n'
|
|
660 |
b'2016-09-16,18:00,10,5,bla bla bla\n'
|
|
661 |
b'\n'
|
|
662 |
b'2016-09-19,18:00,10', 'text/csv')
|
630 |
663 |
resp = resp.form.submit(status=302)
|
631 |
664 |
assert Event.objects.count() == 2
|
632 |
665 |
Event.objects.all().delete()
|
633 |
666 |
|
634 |
667 |
resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
|
635 |
|
resp.form['events_csv_file'] = Upload('t.csv', '"date"\t"time"\t"etc."\n'
|
636 |
|
'"2016-09-16"\t"18:00"\t"10"\t"5"\t"éléphant"\n'
|
637 |
|
'"2016-09-19"\t"18:00"\t"10"'.encode('iso-8859-15'), 'text/csv')
|
|
668 |
resp.form['events_csv_file'] = Upload(
|
|
669 |
't.csv', '"date"\t"time"\t"etc."\n'
|
|
670 |
'"2016-09-16"\t"18:00"\t"10"\t"5"\t"éléphant"\n'
|
|
671 |
'"2016-09-19"\t"18:00"\t"10"'.encode('iso-8859-15'), 'text/csv')
|
638 |
672 |
resp = resp.form.submit(status=302)
|
639 |
673 |
assert Event.objects.count() == 2
|
640 |
674 |
Event.objects.all().delete()
|
... | ... | |
671 |
705 |
agenda = Agenda.objects.get(label='Foo bar')
|
672 |
706 |
assert agenda.kind == 'meetings'
|
673 |
707 |
|
|
708 |
|
674 |
709 |
def test_meetings_agenda_add_meeting_type(app, admin_user):
|
675 |
710 |
agenda = Agenda(label=u'Foo bar', kind='meetings')
|
676 |
711 |
agenda.save()
|
... | ... | |
693 |
728 |
resp = resp.form.submit()
|
694 |
729 |
assert MeetingType.objects.get(agenda=agenda).duration == 30
|
695 |
730 |
|
|
731 |
|
696 |
732 |
def test_meetings_agenda_delete_meeting_type(app, admin_user):
|
697 |
733 |
agenda = Agenda(label=u'Foo bar', kind='meetings')
|
698 |
734 |
agenda.save()
|
... | ... | |
709 |
745 |
assert resp.location.endswith('/manage/agendas/%s/settings' % agenda.id)
|
710 |
746 |
assert MeetingType.objects.count() == 0
|
711 |
747 |
|
|
748 |
|
712 |
749 |
def test_meetings_agenda_add_time_period(app, admin_user):
|
713 |
750 |
agenda = Agenda(label=u'Foo bar', kind='meetings')
|
714 |
751 |
agenda.save()
|
... | ... | |
771 |
808 |
resp = resp.form.submit()
|
772 |
809 |
assert TimePeriod.objects.filter(desk=desk).count() == 4
|
773 |
810 |
|
|
811 |
|
774 |
812 |
def test_meetings_agenda_delete_time_period(app, admin_user):
|
775 |
813 |
agenda = Agenda(label=u'Foo bar', kind='meetings')
|
776 |
814 |
agenda.save()
|
... | ... | |
778 |
816 |
MeetingType(agenda=agenda, label='Blah').save()
|
779 |
817 |
|
780 |
818 |
desk = Desk.objects.create(agenda=agenda, label='Desk A')
|
781 |
|
time_period = TimePeriod(desk=desk, weekday=2,
|
782 |
|
start_time=datetime.time(10, 0),
|
783 |
|
end_time=datetime.time(18, 0))
|
|
819 |
time_period = TimePeriod(
|
|
820 |
desk=desk, weekday=2,
|
|
821 |
start_time=datetime.time(10, 0),
|
|
822 |
end_time=datetime.time(18, 0))
|
784 |
823 |
time_period.save()
|
785 |
824 |
|
786 |
825 |
app = login(app)
|
... | ... | |
807 |
846 |
desk = Desk.objects.create(agenda=agenda, label='Desk A')
|
808 |
847 |
app = login(app, username='manager', password='manager')
|
809 |
848 |
resp = app.get('/manage/agendas/%d/' % agenda.id)
|
810 |
|
assert not 'Settings' in resp.text
|
|
849 |
assert 'Settings' not in resp.text
|
811 |
850 |
resp = app.get('/manage/agendas/%d/settings' % agenda.id, status=403)
|
812 |
851 |
MeetingType(agenda=agenda, label='Blah').save()
|
813 |
852 |
app.get('/manage/agendas/%d/desk/%d/add-time-period' % (agenda.id, desk.id), status=403)
|
... | ... | |
945 |
984 |
resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
|
946 |
985 |
resp = resp.click('Settings')
|
947 |
986 |
resp = resp.click('Add a time period exception')
|
948 |
|
resp = resp.form.submit() # submit empty form
|
|
987 |
resp = resp.form.submit() # submit empty form
|
949 |
988 |
# fields should be marked with errors
|
950 |
989 |
assert resp.text.count('This field is required.') == 2
|
951 |
990 |
# try again with data in fields
|
... | ... | |
967 |
1006 |
resp = resp.form.submit()
|
968 |
1007 |
assert TimePeriodException.objects.count() == 1
|
969 |
1008 |
|
|
1009 |
|
970 |
1010 |
def test_meetings_agenda_add_time_period_exception_when_cancelled_booking_exists(app, admin_user):
|
971 |
1011 |
agenda = Agenda.objects.create(label='Foo bar', kind='meetings')
|
972 |
1012 |
desk = Desk.objects.create(agenda=agenda, label='Desk A')
|
... | ... | |
975 |
1015 |
start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
|
976 |
1016 |
event = Event.objects.create(agenda=agenda, places=1,
|
977 |
1017 |
start_datetime=make_aware(datetime.datetime(2017, 5, 22, 10, 30)))
|
978 |
|
Booking.objects.create(event=event,
|
979 |
|
cancellation_datetime=make_aware(datetime.datetime(2017, 5, 20, 10, 30)))
|
|
1018 |
Booking.objects.create(
|
|
1019 |
event=event,
|
|
1020 |
cancellation_datetime=make_aware(datetime.datetime(2017, 5, 20, 10, 30)))
|
980 |
1021 |
login(app)
|
981 |
1022 |
resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
|
982 |
1023 |
resp = resp.click('Settings')
|
... | ... | |
987 |
1028 |
assert 'One or several bookings exists within this time slot.' not in resp.text
|
988 |
1029 |
assert TimePeriodException.objects.count() == 1
|
989 |
1030 |
|
|
1031 |
|
990 |
1032 |
def test_meetings_agenda_add_invalid_time_period_exception(app, admin_user):
|
991 |
1033 |
agenda = Agenda.objects.create(label='Foo bar', kind='meetings')
|
992 |
1034 |
desk = Desk.objects.create(agenda=agenda, label='Desk A')
|
... | ... | |
1092 |
1134 |
resp = resp.click('Settings')
|
1093 |
1135 |
assert 'Import exceptions from .ics' not in resp.text
|
1094 |
1136 |
|
1095 |
|
TimePeriod.objects.create(weekday=1, desk=desk,
|
1096 |
|
start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
|
|
1137 |
TimePeriod.objects.create(
|
|
1138 |
weekday=1, desk=desk,
|
|
1139 |
start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
|
1097 |
1140 |
|
1098 |
1141 |
resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
|
1099 |
1142 |
resp = resp.click('Settings')
|
... | ... | |
1182 |
1225 |
resp = resp.click('Settings')
|
1183 |
1226 |
assert 'Import exceptions from .ics' not in resp.text
|
1184 |
1227 |
|
1185 |
|
TimePeriod.objects.create(weekday=1, desk=desk,
|
1186 |
|
start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
|
|
1228 |
TimePeriod.objects.create(
|
|
1229 |
weekday=1, desk=desk,
|
|
1230 |
start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
|
1187 |
1231 |
|
1188 |
1232 |
resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
|
1189 |
1233 |
resp = resp.click('Settings')
|
... | ... | |
1193 |
1237 |
assert 'ics_url' in resp.form.fields
|
1194 |
1238 |
resp.form['ics_url'] = 'http://example.com/foo.ics'
|
1195 |
1239 |
mocked_response = mock.Mock()
|
1196 |
|
mocked_response.text = """BEGIN:VCALENDAR
|
|
1240 |
mocked_response.text = """BEGIN:VCALENDAR
|
1197 |
1241 |
VERSION:2.0
|
1198 |
1242 |
PRODID:-//foo.bar//EN
|
1199 |
1243 |
BEGIN:VEVENT
|
... | ... | |
1213 |
1257 |
resp = resp.click('upload')
|
1214 |
1258 |
resp.form['ics_url'] = ''
|
1215 |
1259 |
resp = resp.form.submit(status=302)
|
1216 |
|
assert not TimePeriodException.objects.filter(desk=desk,
|
1217 |
|
external_id='desk-%s:random-event-id' % desk.id).exists()
|
|
1260 |
assert not TimePeriodException.objects.filter(
|
|
1261 |
desk=desk,
|
|
1262 |
external_id='desk-%s:random-event-id' % desk.id).exists()
|
|
1263 |
|
1218 |
1264 |
|
1219 |
1265 |
@mock.patch('chrono.agendas.models.requests.get')
|
1220 |
1266 |
def test_agenda_import_time_period_exception_with_remote_ics_no_events(mocked_get, app, admin_user):
|
... | ... | |
1226 |
1272 |
resp = resp.click('Settings')
|
1227 |
1273 |
assert 'Import exceptions from .ics' not in resp.text
|
1228 |
1274 |
|
1229 |
|
TimePeriod.objects.create(weekday=1, desk=desk,
|
1230 |
|
start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
|
|
1275 |
TimePeriod.objects.create(
|
|
1276 |
weekday=1, desk=desk,
|
|
1277 |
start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
|
1231 |
1278 |
|
1232 |
1279 |
resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
|
1233 |
1280 |
resp = resp.click('Settings')
|
1234 |
1281 |
resp = resp.click('upload')
|
1235 |
1282 |
resp.form['ics_url'] = 'http://example.com/foo.ics'
|
1236 |
1283 |
mocked_response = mock.Mock()
|
1237 |
|
mocked_response.text = """BEGIN:VCALENDAR
|
|
1284 |
mocked_response.text = """BEGIN:VCALENDAR
|
1238 |
1285 |
VERSION:2.0
|
1239 |
1286 |
PRODID:-//foo.bar//EN
|
1240 |
1287 |
BEGIN:VEVENT
|
... | ... | |
1257 |
1304 |
resp = resp.click('Settings')
|
1258 |
1305 |
resp = resp.click('upload')
|
1259 |
1306 |
resp = resp.form.submit(status=302)
|
1260 |
|
assert not TimePeriodException.objects.filter(desk=desk,
|
1261 |
|
external_id='random-event-id').exists()
|
|
1307 |
assert not TimePeriodException.objects.filter(
|
|
1308 |
desk=desk,
|
|
1309 |
external_id='random-event-id').exists()
|
1262 |
1310 |
|
1263 |
1311 |
|
1264 |
1312 |
@mock.patch('chrono.agendas.models.requests.get')
|
... | ... | |
1271 |
1319 |
resp = resp.click('Settings')
|
1272 |
1320 |
assert 'Import exceptions from .ics' not in resp.text
|
1273 |
1321 |
|
1274 |
|
TimePeriod.objects.create(weekday=1, desk=desk,
|
1275 |
|
start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
|
|
1322 |
TimePeriod.objects.create(
|
|
1323 |
weekday=1, desk=desk,
|
|
1324 |
start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
|
1276 |
1325 |
|
1277 |
1326 |
resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
|
1278 |
1327 |
resp = resp.click('Settings')
|
1279 |
1328 |
resp = resp.click('upload')
|
1280 |
1329 |
resp.form['ics_url'] = 'http://example.com/foo.ics'
|
1281 |
1330 |
mocked_response = mock.Mock()
|
1282 |
|
mocked_response.text = """BEGIN:VCALENDAR
|
|
1331 |
mocked_response.text = """BEGIN:VCALENDAR
|
1283 |
1332 |
VERSION:2.0
|
1284 |
1333 |
PRODID:-//foo.bar//EN
|
1285 |
1334 |
BEGIN:VEVENT
|
... | ... | |
1316 |
1365 |
resp = resp.form.submit(status=302)
|
1317 |
1366 |
assert TimePeriodException.objects.filter(desk=desk).count() == 1
|
1318 |
1367 |
|
|
1368 |
|
1319 |
1369 |
@mock.patch('chrono.agendas.models.requests.get')
|
1320 |
1370 |
def test_agenda_import_time_period_exception_from_remote_ics_with_connection_error(mocked_get, app, admin_user):
|
1321 |
1371 |
agenda = Agenda.objects.create(label='New Example', kind='meetings')
|
... | ... | |
1326 |
1376 |
resp = resp.click('Settings')
|
1327 |
1377 |
assert 'Import exceptions from .ics' not in resp.text
|
1328 |
1378 |
|
1329 |
|
TimePeriod.objects.create(weekday=1, desk=desk,
|
1330 |
|
start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
|
|
1379 |
TimePeriod.objects.create(
|
|
1380 |
weekday=1, desk=desk,
|
|
1381 |
start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
|
1331 |
1382 |
|
1332 |
1383 |
resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
|
1333 |
1384 |
resp = resp.click('Settings')
|
... | ... | |
1338 |
1389 |
resp.form['ics_url'] = 'http://example.com/foo.ics'
|
1339 |
1390 |
mocked_response = mock.Mock()
|
1340 |
1391 |
mocked_get.return_value = mocked_response
|
|
1392 |
|
1341 |
1393 |
def mocked_requests_connection_error(*args, **kwargs):
|
1342 |
1394 |
raise requests.exceptions.ConnectionError('unreachable')
|
|
1395 |
|
1343 |
1396 |
mocked_get.side_effect = mocked_requests_connection_error
|
1344 |
1397 |
resp = resp.form.submit(status=200)
|
1345 |
1398 |
assert 'Failed to retrieve remote calendar (http://example.com/foo.ics, unreachable).' in resp.text
|
1346 |
1399 |
|
|
1400 |
|
1347 |
1401 |
@mock.patch('chrono.agendas.models.requests.get')
|
1348 |
1402 |
def test_agenda_import_time_period_exception_from_forbidden_remote_ics(mocked_get, app, admin_user):
|
1349 |
1403 |
agenda = Agenda.objects.create(label='New Example', kind='meetings')
|
... | ... | |
1354 |
1408 |
resp = resp.click('Settings')
|
1355 |
1409 |
assert 'Import exceptions from .ics' not in resp.text
|
1356 |
1410 |
|
1357 |
|
TimePeriod.objects.create(weekday=1, desk=desk,
|
1358 |
|
start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
|
|
1411 |
TimePeriod.objects.create(
|
|
1412 |
weekday=1, desk=desk,
|
|
1413 |
start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
|
1359 |
1414 |
|
1360 |
1415 |
resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
|
1361 |
1416 |
resp = resp.click('Settings')
|
... | ... | |
1364 |
1419 |
mocked_response = mock.Mock()
|
1365 |
1420 |
mocked_response.status_code = 403
|
1366 |
1421 |
mocked_get.return_value = mocked_response
|
|
1422 |
|
1367 |
1423 |
def mocked_requests_http_forbidden_error(*args, **kwargs):
|
1368 |
1424 |
raise requests.exceptions.HTTPError(response=mocked_response)
|
|
1425 |
|
1369 |
1426 |
mocked_get.side_effect = mocked_requests_http_forbidden_error
|
1370 |
1427 |
resp = resp.form.submit(status=200)
|
1371 |
1428 |
assert 'Failed to retrieve remote calendar (http://example.com/foo.ics, HTTP error 403).' in resp.text
|
1372 |
1429 |
|
|
1430 |
|
1373 |
1431 |
@mock.patch('chrono.agendas.models.requests.get')
|
1374 |
1432 |
def test_agenda_import_time_period_exception_from_remote_ics_with_ssl_error(mocked_get, app, admin_user):
|
1375 |
1433 |
agenda = Agenda.objects.create(label='New Example', kind='meetings')
|
... | ... | |
1379 |
1437 |
resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
|
1380 |
1438 |
resp = resp.click('Settings')
|
1381 |
1439 |
assert 'Import exceptions from .ics' not in resp.text
|
1382 |
|
TimePeriod.objects.create(weekday=1, desk=desk,
|
1383 |
|
start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
|
|
1440 |
TimePeriod.objects.create(
|
|
1441 |
weekday=1, desk=desk,
|
|
1442 |
start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
|
1384 |
1443 |
|
1385 |
1444 |
resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
|
1386 |
1445 |
resp = resp.click('Settings')
|
... | ... | |
1388 |
1447 |
resp.form['ics_url'] = 'https://example.com/foo.ics'
|
1389 |
1448 |
mocked_response = mock.Mock()
|
1390 |
1449 |
mocked_get.return_value = mocked_response
|
|
1450 |
|
1391 |
1451 |
def mocked_requests_http_ssl_error(*args, **kwargs):
|
1392 |
1452 |
raise requests.exceptions.SSLError('SSL error')
|
|
1453 |
|
1393 |
1454 |
mocked_get.side_effect = mocked_requests_http_ssl_error
|
1394 |
1455 |
resp = resp.form.submit(status=200)
|
1395 |
1456 |
assert 'Failed to retrieve remote calendar (https://example.com/foo.ics, SSL error).' in resp.text
|
1396 |
1457 |
|
|
1458 |
|
1397 |
1459 |
def test_agenda_day_view(app, admin_user, manager_user, api_user):
|
1398 |
1460 |
agenda = Agenda.objects.create(label='New Example', kind='meetings')
|
1399 |
1461 |
desk = Desk.objects.create(agenda=agenda, label='New Desk')
|
... | ... | |
1409 |
1471 |
resp = resp.follow()
|
1410 |
1472 |
assert 'No opening hours this day.' in resp.text # no time pediod
|
1411 |
1473 |
|
1412 |
|
timeperiod = TimePeriod(desk=desk, weekday=today.weekday(),
|
1413 |
|
start_time=datetime.time(10, 0),
|
1414 |
|
end_time=datetime.time(18, 0))
|
|
1474 |
timeperiod = TimePeriod(
|
|
1475 |
desk=desk, weekday=today.weekday(),
|
|
1476 |
start_time=datetime.time(10, 0),
|
|
1477 |
end_time=datetime.time(18, 0))
|
1415 |
1478 |
timeperiod.save()
|
1416 |
1479 |
resp = app.get('/manage/agendas/%s/' % agenda.id, status=302).follow()
|
1417 |
|
assert not 'No opening hours this day.' in resp.text
|
1418 |
|
assert not 'div class="booking' in resp.text
|
|
1480 |
assert 'No opening hours this day.' not in resp.text
|
|
1481 |
assert 'div class="booking' not in resp.text
|
1419 |
1482 |
assert resp.text.count('<tr') == 9 # 10->18 (not included)
|
1420 |
1483 |
|
1421 |
1484 |
timeperiod.end_time = datetime.time(18, 30) # end during an hour
|
... | ... | |
1434 |
1497 |
booking_url = resp.json['data'][0]['api']['fillslot_url']
|
1435 |
1498 |
booking_url2 = resp.json['data'][2]['api']['fillslot_url']
|
1436 |
1499 |
resp = app.post(booking_url)
|
1437 |
|
resp = app.post_json(booking_url2,
|
1438 |
|
params={'label': 'foo', 'user': 'bar', 'url': 'http://baz/'})
|
|
1500 |
resp = app.post_json(
|
|
1501 |
booking_url2,
|
|
1502 |
params={'label': 'foo', 'user': 'bar', 'url': 'http://baz/'})
|
1439 |
1503 |
|
1440 |
1504 |
app.reset()
|
1441 |
1505 |
login(app)
|
... | ... | |
1488 |
1552 |
resp = app.get('/manage/agendas/%s/%d/%d/%d/' % (
|
1489 |
1553 |
agenda.id, date.year, date.month, date.day), status=200)
|
1490 |
1554 |
|
|
1555 |
|
1491 |
1556 |
def test_agenda_day_view_late_meeting(app, admin_user, manager_user, api_user):
|
1492 |
1557 |
agenda = Agenda.objects.create(label='New Example', kind='meetings')
|
1493 |
1558 |
desk = Desk.objects.create(agenda=agenda, label='New Desk')
|
... | ... | |
1498 |
1563 |
|
1499 |
1564 |
today = datetime.date.today()
|
1500 |
1565 |
|
1501 |
|
timeperiod = TimePeriod(desk=desk, weekday=today.weekday(),
|
1502 |
|
start_time=datetime.time(10, 0),
|
1503 |
|
end_time=datetime.time(23, 30))
|
|
1566 |
timeperiod = TimePeriod(
|
|
1567 |
desk=desk, weekday=today.weekday(),
|
|
1568 |
start_time=datetime.time(10, 0),
|
|
1569 |
end_time=datetime.time(23, 30))
|
1504 |
1570 |
timeperiod.save()
|
1505 |
1571 |
|
1506 |
1572 |
login(app)
|
... | ... | |
1508 |
1574 |
assert resp.text.count('<tr') == 15
|
1509 |
1575 |
assert '<th class="hour">11 p.m.</th>' in resp.text
|
1510 |
1576 |
|
|
1577 |
|
1511 |
1578 |
def test_agenda_invalid_day_view(app, admin_user, manager_user, api_user):
|
1512 |
1579 |
agenda = Agenda.objects.create(label='New Example', kind='meetings')
|
1513 |
1580 |
desk = Desk.objects.create(agenda=agenda, label='New Desk')
|
... | ... | |
1520 |
1587 |
resp = app.get('/manage/agendas/%s/%d/%d/%d/' % (agenda.id, 2018, 11, 31), status=302)
|
1521 |
1588 |
assert resp.location.endswith('2018/11/30/')
|
1522 |
1589 |
|
|
1590 |
|
1523 |
1591 |
def test_agenda_month_view(app, admin_user, manager_user, api_user):
|
1524 |
1592 |
agenda = Agenda.objects.create(label='Passeports', kind='meetings')
|
1525 |
1593 |
desk = Desk.objects.create(agenda=agenda, label='Desk A')
|
... | ... | |
1535 |
1603 |
today = datetime.date.today()
|
1536 |
1604 |
assert resp.request.url.endswith('%s/%s/' % (today.year, today.month))
|
1537 |
1605 |
|
1538 |
|
assert 'Day view' in resp.text # date view link should be present
|
|
1606 |
assert 'Day view' in resp.text # date view link should be present
|
1539 |
1607 |
assert 'No opening hours this month.' in resp.text
|
1540 |
1608 |
|
1541 |
1609 |
today = datetime.date(2018, 11, 10) # fixed day
|
1542 |
1610 |
timeperiod_weekday = today.weekday()
|
1543 |
|
timeperiod = TimePeriod(desk=desk, weekday=timeperiod_weekday,
|
1544 |
|
start_time=datetime.time(10, 0),
|
1545 |
|
end_time=datetime.time(18, 0))
|
|
1611 |
timeperiod = TimePeriod(
|
|
1612 |
desk=desk, weekday=timeperiod_weekday,
|
|
1613 |
start_time=datetime.time(10, 0),
|
|
1614 |
end_time=datetime.time(18, 0))
|
1546 |
1615 |
timeperiod.save()
|
1547 |
1616 |
resp = app.get('/manage/agendas/%s/%s/%s/' % (agenda.id, today.year, today.month))
|
1548 |
|
assert not 'No opening hours this month.' in resp.text
|
1549 |
|
assert not '<div class="booking' in resp.text
|
|
1617 |
assert 'No opening hours this month.' not in resp.text
|
|
1618 |
assert '<div class="booking' not in resp.text
|
1550 |
1619 |
first_month_day = today.replace(day=1)
|
1551 |
1620 |
last_month_day = today.replace(day=1, month=today.month+1) - datetime.timedelta(days=1)
|
1552 |
1621 |
start_week_number = first_month_day.isocalendar()[1]
|
... | ... | |
1564 |
1633 |
booking_url = resp.json['data'][0]['api']['fillslot_url']
|
1565 |
1634 |
booking_url2 = resp.json['data'][2]['api']['fillslot_url']
|
1566 |
1635 |
booking = app.post(booking_url)
|
1567 |
|
booking_2 = app.post_json(booking_url2,
|
1568 |
|
params={'label': 'foo', 'user': 'bar', 'url': 'http://baz/'})
|
|
1636 |
booking_2 = app.post_json(
|
|
1637 |
booking_url2,
|
|
1638 |
params={'label': 'foo', 'user': 'bar', 'url': 'http://baz/'})
|
1569 |
1639 |
|
1570 |
1640 |
app.reset()
|
1571 |
1641 |
login(app)
|
1572 |
1642 |
date = Booking.objects.all()[0].event.start_datetime
|
1573 |
1643 |
resp = app.get('/manage/agendas/%s/%d/%d/' % (
|
1574 |
1644 |
agenda.id, date.year, date.month))
|
1575 |
|
assert resp.text.count('<div class="booking" style="left:1.0%;height:33.0%;') == 2 # booking cells
|
|
1645 |
assert resp.text.count('<div class="booking" style="left:1.0%;height:33.0%;') == 2 # booking cells
|
1576 |
1646 |
desk = Desk.objects.create(agenda=agenda, label='Desk B')
|
1577 |
|
timeperiod = TimePeriod(desk=desk, weekday=timeperiod_weekday,
|
1578 |
|
start_time=datetime.time(10, 0),
|
1579 |
|
end_time=datetime.time(18, 0))
|
|
1647 |
timeperiod = TimePeriod(
|
|
1648 |
desk=desk, weekday=timeperiod_weekday,
|
|
1649 |
start_time=datetime.time(10, 0),
|
|
1650 |
end_time=datetime.time(18, 0))
|
1580 |
1651 |
timeperiod.save()
|
1581 |
1652 |
|
1582 |
1653 |
app.reset()
|
... | ... | |
1611 |
1682 |
# check December is correctly displayed
|
1612 |
1683 |
today = datetime.date(2018, 12, 10)
|
1613 |
1684 |
resp = app.get('/manage/agendas/%s/%s/%s/' % (agenda.id, today.year, today.month))
|
1614 |
|
assert not 'No opening hours this month.' in resp.text
|
|
1685 |
assert 'No opening hours this month.' not in resp.text
|
|
1686 |
|
1615 |
1687 |
|
1616 |
1688 |
def test_agenda_month_view_dst_change(app, admin_user, manager_user, api_user):
|
1617 |
1689 |
agenda = Agenda.objects.create(label='Passeports', kind='meetings')
|
... | ... | |
1621 |
1693 |
meetingtype.save()
|
1622 |
1694 |
|
1623 |
1695 |
for weekday in range(0, 7): # open all mornings
|
1624 |
|
TimePeriod(desk=desk, weekday=weekday,
|
1625 |
|
start_time=datetime.time(9, 0),
|
1626 |
|
end_time=datetime.time(12, 0)).save()
|
|
1696 |
TimePeriod(
|
|
1697 |
desk=desk, weekday=weekday,
|
|
1698 |
start_time=datetime.time(9, 0),
|
|
1699 |
end_time=datetime.time(12, 0)).save()
|
1627 |
1700 |
|
1628 |
1701 |
login(app)
|
1629 |
1702 |
for date in ('2019-10-01', '2019-10-31'):
|
... | ... | |
1655 |
1728 |
agenda.view_role = manager_user.groups.all()[0]
|
1656 |
1729 |
agenda.save()
|
1657 |
1730 |
app = login(app, username='manager', password='manager')
|
1658 |
|
resp = app.get('/manage/', status=200)
|
1659 |
|
resp = app.get('/manage/agendas/import/', status=403)
|
|
1731 |
app.get('/manage/', status=200)
|
|
1732 |
app.get('/manage/agendas/import/', status=403)
|
|
1733 |
|
1660 |
1734 |
|
1661 |
1735 |
def test_import_agenda(app, admin_user):
|
1662 |
1736 |
agenda = Agenda(label=u'Foo bar')
|
1663 |
|
-
|