Merge lp:~cjohnston/summit/seperate-tests into lp:summit
- seperate-tests
- Merge into trunk
Proposed by
Chris Johnston
Status: | Merged |
---|---|
Approved by: | Michael Hall |
Approved revision: | 491 |
Merged at revision: | 491 |
Proposed branch: | lp:~cjohnston/summit/seperate-tests |
Merge into: | lp:summit |
Diff against target: |
7649 lines (+4092/-3423) 21 files modified
summit/schedule/tests/__init__.py (+16/-2) summit/schedule/tests/autoscheduler.py (+209/-0) summit/schedule/tests/delete_meeting.py (+203/-0) summit/schedule/tests/etherpad.py (+76/-0) summit/schedule/tests/ical.py (+232/-0) summit/schedule/tests/launchpad_export_node.py (+32/-0) summit/schedule/tests/meeting_model.py (+608/-0) summit/schedule/tests/meeting_page.py (+101/-0) summit/schedule/tests/meeting_search.py (+335/-0) summit/schedule/tests/participation_registration.py (+202/-0) summit/schedule/tests/private_scheduling.py (+225/-0) summit/schedule/tests/render_schedule.py (+196/-0) summit/schedule/tests/request_factory.py (+80/-0) summit/schedule/tests/reverse_url.py (+220/-0) summit/schedule/tests/schedule.py (+537/-0) summit/schedule/tests/schedule_cache.py (+167/-0) summit/schedule/tests/scheduling_conflicts.py (+146/-0) summit/schedule/tests/summit_model.py (+501/-0) summit/schedule/tests/tests.py (+0/-3417) summit/schedule/tests/virtual.py (+2/-2) summit/schedule/views.py (+4/-2) |
To merge this branch: | bzr merge lp:~cjohnston/summit/seperate-tests |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Michael Hall (community) | Approve | ||
Review via email: mp+150816@code.launchpad.net |
Commit message
Separate tests into different files
Description of the change
To post a comment you must log in.
- 490. By Chris Johnston
-
Fix conflicts
- 491. By Chris Johnston
-
oops
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'summit/schedule/tests/__init__.py' |
2 | --- summit/schedule/tests/__init__.py 2013-02-26 20:00:45 +0000 |
3 | +++ summit/schedule/tests/__init__.py 2013-02-27 15:35:39 +0000 |
4 | @@ -14,5 +14,19 @@ |
5 | # You should have received a copy of the GNU Affero General Public License |
6 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
7 | |
8 | -from tests import * |
9 | -from test_virtual import * |
10 | +from virtual import * |
11 | +from etherpad import * |
12 | +from meeting_page import * |
13 | +from render_schedule import * |
14 | +from scheduling_conflicts import * |
15 | +from ical import * |
16 | +from meeting_search import * |
17 | +from reverse_url import * |
18 | +from autoscheduler import * |
19 | +from participation_registration import * |
20 | +from schedule_cache import * |
21 | +from delete_meeting import * |
22 | +from meeting_model import * |
23 | +from private_scheduling import * |
24 | +from schedule import * |
25 | +from summit_model import * |
26 | |
27 | === added file 'summit/schedule/tests/autoscheduler.py' |
28 | --- summit/schedule/tests/autoscheduler.py 1970-01-01 00:00:00 +0000 |
29 | +++ summit/schedule/tests/autoscheduler.py 2013-02-27 15:35:39 +0000 |
30 | @@ -0,0 +1,209 @@ |
31 | +# The Summit Scheduler web application |
32 | +# Copyright (C) 2008 - 2013 Ubuntu Community, Canonical Ltd |
33 | +# |
34 | +# This program is free software: you can redistribute it and/or modify |
35 | +# it under the terms of the GNU Affero General Public License as |
36 | +# published by the Free Software Foundation, either version 3 of the |
37 | +# License, or (at your option) any later version. |
38 | +# |
39 | +# This program is distributed in the hope that it will be useful, |
40 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
41 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
42 | +# GNU Affero General Public License for more details. |
43 | +# |
44 | +# You should have received a copy of the GNU Affero General Public License |
45 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
46 | + |
47 | + |
48 | +import datetime |
49 | +from django import test as djangotest |
50 | +from django.contrib.auth.models import User |
51 | + |
52 | +from model_mommy import mommy as factory |
53 | +from summit.schedule.fields import NameField |
54 | + |
55 | +from summit.schedule.models import ( |
56 | + Summit, |
57 | + Slot, |
58 | + Attendee, |
59 | + Meeting, |
60 | + Room, |
61 | + Agenda, |
62 | + Participant, |
63 | +) |
64 | + |
65 | + |
66 | +# Monkey-patch our NameField into the types of fields that the factory |
67 | +# understands. This is simpler than trying to subclass the Mommy |
68 | +# class directly. |
69 | +factory.default_mapping[NameField] = str |
70 | + |
71 | + |
72 | +class AutoSchedulerTestCase(djangotest.TestCase): |
73 | + def setUp(self): |
74 | + now = datetime.datetime.utcnow() |
75 | + one_hour = datetime.timedelta(0, 3600) |
76 | + week = datetime.timedelta(days=5) |
77 | + self.summit = factory.make_one(Summit, name='uds-test') |
78 | + self.slot = factory.make_one( |
79 | + Slot, |
80 | + start_utc=now+week, |
81 | + end_utc=now+week+one_hour, |
82 | + type='open', |
83 | + summit=self.summit |
84 | + ) |
85 | + |
86 | + self.room1 = factory.make_one(Room, summit=self.summit, type='open') |
87 | + self.meeting1 = factory.make_one( |
88 | + Meeting, |
89 | + summit=self.summit, |
90 | + name='meeting1', |
91 | + requires_dial_in=False, |
92 | + approved='APPROVED', |
93 | + private=False |
94 | + ) |
95 | + self.agenda1 = factory.make_one( |
96 | + Agenda, |
97 | + slot=self.slot, |
98 | + meeting=self.meeting1, |
99 | + room=self.room1 |
100 | + ) |
101 | + |
102 | + self.room2 = factory.make_one(Room, summit=self.summit, type='open') |
103 | + self.meeting2 = factory.make_one( |
104 | + Meeting, |
105 | + summit=self.summit, |
106 | + name='meeting2', |
107 | + requires_dial_in=False, |
108 | + approved='APPROVED', |
109 | + private=False |
110 | + ) |
111 | + |
112 | + self.user = factory.make_one( |
113 | + User, |
114 | + username='testuser', |
115 | + first_name='Test', |
116 | + last_name='User' |
117 | + ) |
118 | + self.attendee = factory.make_one( |
119 | + Attendee, |
120 | + summit=self.summit, |
121 | + user=self.user, |
122 | + start_utc=now, |
123 | + end_utc=now+week |
124 | + ) |
125 | + |
126 | + def tearDown(self): |
127 | + pass |
128 | + |
129 | + def run_autoschedule(self): |
130 | + from django.core.management import execute_from_command_line |
131 | + execute_from_command_line( |
132 | + argv=['manage.py', 'autoschedule', 'uds-test', '-v', '2'] |
133 | + ) |
134 | + |
135 | + def run_reschedule(self): |
136 | + from django.core.management import execute_from_command_line |
137 | + execute_from_command_line( |
138 | + argv=['manage.py', 'reschedule', 'uds-test', '-v', '2'] |
139 | + ) |
140 | + |
141 | + def test_required_conflict(self): |
142 | + participant1 = Participant.objects.create( |
143 | + meeting=self.meeting1, |
144 | + attendee=self.attendee, |
145 | + participation='REQUIRED' |
146 | + ) |
147 | + |
148 | + participant2 = Participant.objects.create( |
149 | + meeting=self.meeting2, |
150 | + attendee=self.attendee, |
151 | + participation='REQUIRED' |
152 | + ) |
153 | + |
154 | + self.run_autoschedule() |
155 | + |
156 | + self.assertEquals(1, self.meeting1.agenda_set.all().count()) |
157 | + self.assertEquals(0, self.meeting2.agenda_set.all().count()) |
158 | + |
159 | + def test_required_and_interested(self): |
160 | + participant1 = Participant.objects.create( |
161 | + meeting=self.meeting1, |
162 | + attendee=self.attendee, |
163 | + participation='REQUIRED' |
164 | + ) |
165 | + |
166 | + participant2 = Participant.objects.create( |
167 | + meeting=self.meeting2, |
168 | + attendee=self.attendee, |
169 | + participation='INTERESTED' |
170 | + ) |
171 | + |
172 | + self.run_autoschedule() |
173 | + |
174 | + self.assertEquals(1, self.meeting1.agenda_set.all().count()) |
175 | + self.assertEquals(1, self.meeting2.agenda_set.all().count()) |
176 | + |
177 | + def test_interested_and_required(self): |
178 | + participant1 = Participant.objects.create( |
179 | + meeting=self.meeting1, |
180 | + attendee=self.attendee, |
181 | + participation='REQUIRED' |
182 | + ) |
183 | + |
184 | + participant2 = Participant.objects.create( |
185 | + meeting=self.meeting2, |
186 | + attendee=self.attendee, |
187 | + participation='INTERESTED' |
188 | + ) |
189 | + |
190 | + self.run_autoschedule() |
191 | + |
192 | + self.assertEquals(1, self.meeting1.agenda_set.all().count()) |
193 | + self.assertEquals(1, self.meeting2.agenda_set.all().count()) |
194 | + |
195 | + participant2.participation = 'REQUIRED' |
196 | + participant2.save() |
197 | + |
198 | + self.run_reschedule() |
199 | + |
200 | + self.assertEquals(0, self.meeting1.agenda_set.all().count()) |
201 | + self.assertEquals(0, self.meeting2.agenda_set.all().count()) |
202 | + |
203 | + def test_get_participants_by_level(self): |
204 | + participant1 = Participant.objects.create( |
205 | + meeting=self.meeting1, |
206 | + attendee=self.attendee, |
207 | + participation='REQUIRED' |
208 | + ) |
209 | + |
210 | + participant2 = Participant.objects.create( |
211 | + meeting=self.meeting2, |
212 | + attendee=self.attendee, |
213 | + participation='INTERESTED' |
214 | + ) |
215 | + |
216 | + self.assertEquals( |
217 | + 1, |
218 | + len(self.meeting1.get_participants_by_level('REQUIRED')) |
219 | + ) |
220 | + self.assertEquals( |
221 | + 0, len(self.meeting1.get_participants_by_level('INTERESTED')) |
222 | + ) |
223 | + self.assertEquals( |
224 | + 0, |
225 | + len(self.meeting1.get_participants_by_level('ATTENDING')) |
226 | + ) |
227 | + |
228 | + self.assertEquals( |
229 | + 0, |
230 | + len(self.meeting2.get_participants_by_level('REQUIRED')) |
231 | + ) |
232 | + self.assertEquals( |
233 | + 1, |
234 | + len(self.meeting2.get_participants_by_level('INTERESTED')) |
235 | + ) |
236 | + self.assertEquals( |
237 | + 0, |
238 | + len(self.meeting2.get_participants_by_level('ATTENDING')) |
239 | + ) |
240 | |
241 | === added file 'summit/schedule/tests/delete_meeting.py' |
242 | --- summit/schedule/tests/delete_meeting.py 1970-01-01 00:00:00 +0000 |
243 | +++ summit/schedule/tests/delete_meeting.py 2013-02-27 15:35:39 +0000 |
244 | @@ -0,0 +1,203 @@ |
245 | +# The Summit Scheduler web application |
246 | +# Copyright (C) 2008 - 2013 Ubuntu Community, Canonical Ltd |
247 | +# |
248 | +# This program is free software: you can redistribute it and/or modify |
249 | +# it under the terms of the GNU Affero General Public License as |
250 | +# published by the Free Software Foundation, either version 3 of the |
251 | +# License, or (at your option) any later version. |
252 | +# |
253 | +# This program is distributed in the hope that it will be useful, |
254 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
255 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
256 | +# GNU Affero General Public License for more details. |
257 | +# |
258 | +# You should have received a copy of the GNU Affero General Public License |
259 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
260 | + |
261 | + |
262 | +import datetime |
263 | +from django import test as djangotest |
264 | +from django.core.urlresolvers import reverse |
265 | +from django.contrib.auth.models import User, Permission |
266 | + |
267 | +from model_mommy import mommy as factory |
268 | +from summit.schedule.fields import NameField |
269 | + |
270 | +from summit.schedule.models import ( |
271 | + Summit, |
272 | + Slot, |
273 | + Attendee, |
274 | + Meeting, |
275 | + Room, |
276 | + Agenda, |
277 | + Participant, |
278 | + Lead, |
279 | +) |
280 | + |
281 | +# Monkey-patch our NameField into the types of fields that the factory |
282 | +# understands. This is simpler than trying to subclass the Mommy |
283 | +# class directly. |
284 | +factory.default_mapping[NameField] = str |
285 | + |
286 | + |
287 | +class DeleteMeetingTestCase(djangotest.TestCase): |
288 | + """ |
289 | + This will test different options for deleting a meeting from |
290 | + the front end UI. |
291 | + """ |
292 | + |
293 | + def setUp(self): |
294 | + now = datetime.datetime.utcnow() |
295 | + one_hour = datetime.timedelta(0, 3600) |
296 | + self.summit = factory.make_one( |
297 | + Summit, |
298 | + name='uds-test', |
299 | + date_start=now, |
300 | + date_end=now+one_hour |
301 | + ) |
302 | + self.summit.save() |
303 | + slot = factory.make_one( |
304 | + Slot, |
305 | + summit=self.summit, |
306 | + start_utc=now, |
307 | + end_utc=now+one_hour |
308 | + ) |
309 | + room = factory.make_one(Room) |
310 | + |
311 | + self.meeting = factory.make_one( |
312 | + Meeting, |
313 | + summit=self.summit, |
314 | + requires_dial_in=False, |
315 | + private=False |
316 | + ) |
317 | + |
318 | + attendee1 = factory.make_one(Attendee) |
319 | + factory.make_one(Participant, meeting=self.meeting, attendee=attendee1) |
320 | + |
321 | + factory.make_one(Agenda, meeting=self.meeting, slot=slot, room=room) |
322 | + |
323 | + self.user = factory.make_one( |
324 | + User, |
325 | + username='testuser', |
326 | + is_active=True, |
327 | + is_superuser=False |
328 | + ) |
329 | + self.user.set_password('password') |
330 | + self.user.save() |
331 | + |
332 | + self.attendee = factory.make_one( |
333 | + Attendee, |
334 | + user=self.user, |
335 | + summit=self.summit |
336 | + ) |
337 | + |
338 | + def tearDown(self): |
339 | + self.client.logout() |
340 | + self.user.user_permissions.all().delete() |
341 | + |
342 | + def login(self): |
343 | + logged_in = self.client.login(username='testuser', password='password') |
344 | + self.assertTrue(logged_in) |
345 | + |
346 | + def test_track_lead_cant_delete_meeting(self): |
347 | + self.lead = factory.make_one( |
348 | + Lead, |
349 | + lead=self.attendee, |
350 | + summit=self.summit |
351 | + ) |
352 | + self.login() |
353 | + response = self.client.get( |
354 | + reverse( |
355 | + 'summit.schedule.views.delete_meeting', |
356 | + args=(self.summit, self.meeting.id, self.meeting.name) |
357 | + ) |
358 | + ) |
359 | + self.assertRedirects( |
360 | + response, |
361 | + reverse( |
362 | + 'summit.schedule.views.summit', |
363 | + args=(self.summit.name,) |
364 | + ), |
365 | + status_code=302, |
366 | + target_status_code=200 |
367 | + ) |
368 | + |
369 | + def test_user_cant_delete_meeting(self): |
370 | + self.login() |
371 | + response = self.client.get( |
372 | + reverse( |
373 | + 'summit.schedule.views.delete_meeting', |
374 | + args=(self.summit, self.meeting.id, self.meeting.name) |
375 | + ) |
376 | + ) |
377 | + self.assertRedirects( |
378 | + response, |
379 | + reverse( |
380 | + 'summit.schedule.views.summit', |
381 | + args=(self.summit.name,) |
382 | + ), |
383 | + status_code=302, |
384 | + target_status_code=200 |
385 | + ) |
386 | + |
387 | + def test_managers_cant_delete_meeting(self): |
388 | + self.summit.managers.add(self.user) |
389 | + self.login() |
390 | + response = self.client.get( |
391 | + reverse( |
392 | + 'summit.schedule.views.delete_meeting', |
393 | + args=(self.summit, self.meeting.id, self.meeting.name) |
394 | + ) |
395 | + ) |
396 | + self.assertRedirects( |
397 | + response, |
398 | + reverse( |
399 | + 'summit.schedule.views.summit', |
400 | + args=(self.summit.name,) |
401 | + ), |
402 | + status_code=302, |
403 | + target_status_code=200 |
404 | + ) |
405 | + |
406 | + def test_schedulers_can_delete_meeting(self): |
407 | + self.summit.schedulers.add(self.user) |
408 | + self.login() |
409 | + response = self.client.get( |
410 | + reverse( |
411 | + 'summit.schedule.views.delete_meeting', |
412 | + args=(self.summit, self.meeting.id, self.meeting.name) |
413 | + ) |
414 | + ) |
415 | + self.assertRedirects( |
416 | + response, |
417 | + reverse( |
418 | + 'summit.schedule.views.delete_confirmed', |
419 | + args=(self.summit.name,) |
420 | + ), |
421 | + status_code=302, |
422 | + target_status_code=200 |
423 | + ) |
424 | + |
425 | + def test_change_agenda_can_delete_meeting(self): |
426 | + """ |
427 | + Testing if a user who is assigned can_change_agenda |
428 | + in django admin can delete a meeting |
429 | + """ |
430 | + change_agenda = Permission.objects.get(codename='change_agenda') |
431 | + self.user.user_permissions.add(change_agenda) |
432 | + self.login() |
433 | + response = self.client.get( |
434 | + reverse( |
435 | + 'summit.schedule.views.delete_meeting', |
436 | + args=(self.summit, self.meeting.id, self.meeting.name) |
437 | + ) |
438 | + ) |
439 | + self.assertRedirects( |
440 | + response, |
441 | + reverse( |
442 | + 'summit.schedule.views.delete_confirmed', |
443 | + args=(self.summit.name,) |
444 | + ), |
445 | + status_code=302, |
446 | + target_status_code=200 |
447 | + ) |
448 | |
449 | === added file 'summit/schedule/tests/etherpad.py' |
450 | --- summit/schedule/tests/etherpad.py 1970-01-01 00:00:00 +0000 |
451 | +++ summit/schedule/tests/etherpad.py 2013-02-27 15:35:39 +0000 |
452 | @@ -0,0 +1,76 @@ |
453 | +# The Summit Scheduler web application |
454 | +# Copyright (C) 2008 - 2013 Ubuntu Community, Canonical Ltd |
455 | +# |
456 | +# This program is free software: you can redistribute it and/or modify |
457 | +# it under the terms of the GNU Affero General Public License as |
458 | +# published by the Free Software Foundation, either version 3 of the |
459 | +# License, or (at your option) any later version. |
460 | +# |
461 | +# This program is distributed in the hope that it will be useful, |
462 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
463 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
464 | +# GNU Affero General Public License for more details. |
465 | +# |
466 | +# You should have received a copy of the GNU Affero General Public License |
467 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
468 | + |
469 | + |
470 | +from django import test as djangotest |
471 | + |
472 | +from model_mommy import mommy as factory |
473 | +from summit.schedule.fields import NameField |
474 | + |
475 | +from summit.schedule.models import ( |
476 | + Summit, |
477 | + Slot, |
478 | + Meeting, |
479 | + Room, |
480 | + Agenda, |
481 | +) |
482 | + |
483 | +# Monkey-patch our NameField into the types of fields that the factory |
484 | +# understands. This is simpler than trying to subclass the Mommy |
485 | +# class directly. |
486 | +factory.default_mapping[NameField] = str |
487 | + |
488 | + |
489 | +class EtherpadEditUrl(djangotest.TestCase): |
490 | + |
491 | + def setUp(self): |
492 | + self.summit = factory.make_one(Summit, name='uds-test') |
493 | + self.summit.save() |
494 | + |
495 | + def tearDown(self): |
496 | + pass |
497 | + |
498 | + def test_etherpad_edit_url(self): |
499 | + |
500 | + slot = factory.make_one( |
501 | + Slot, |
502 | + type='open', |
503 | + summit=self.summit) |
504 | + slot.save() |
505 | + |
506 | + room = factory.make_one(Room, summit=self.summit) |
507 | + meeting = factory.make_one( |
508 | + Meeting, |
509 | + summit=self.summit, |
510 | + name='test-meeting', |
511 | + private=False |
512 | + ) |
513 | + agenda = factory.make_one( |
514 | + Agenda, |
515 | + slot=slot, |
516 | + meeting=meeting, |
517 | + room=room |
518 | + ) |
519 | + |
520 | + response = self.client.get( |
521 | + '/uds-test/meeting/%s/test-meeting/' % meeting.id |
522 | + ) |
523 | + self.assertEquals(response.status_code, 200) |
524 | + self.assertContains( |
525 | + response, |
526 | + 'http://pad.ubuntu.com/ep/pad/view/uds-test-test-meeting/latest', |
527 | + 1 |
528 | + ) |
529 | |
530 | === added file 'summit/schedule/tests/ical.py' |
531 | --- summit/schedule/tests/ical.py 1970-01-01 00:00:00 +0000 |
532 | +++ summit/schedule/tests/ical.py 2013-02-27 15:35:39 +0000 |
533 | @@ -0,0 +1,232 @@ |
534 | +# The Summit Scheduler web application |
535 | +# Copyright (C) 2008 - 2013 Ubuntu Community, Canonical Ltd |
536 | +# |
537 | +# This program is free software: you can redistribute it and/or modify |
538 | +# it under the terms of the GNU Affero General Public License as |
539 | +# published by the Free Software Foundation, either version 3 of the |
540 | +# License, or (at your option) any later version. |
541 | +# |
542 | +# This program is distributed in the hope that it will be useful, |
543 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
544 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
545 | +# GNU Affero General Public License for more details. |
546 | +# |
547 | +# You should have received a copy of the GNU Affero General Public License |
548 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
549 | + |
550 | + |
551 | +import datetime |
552 | +from django import test as djangotest |
553 | +from django.conf import settings |
554 | +from django.contrib.auth.models import User |
555 | +from django.db import models |
556 | + |
557 | +from model_mommy import mommy as factory |
558 | +from summit.schedule.fields import NameField |
559 | + |
560 | +from summit.schedule.models import ( |
561 | + Summit, |
562 | + Slot, |
563 | + Attendee, |
564 | + Meeting, |
565 | + Room, |
566 | + Agenda, |
567 | + Participant, |
568 | +) |
569 | + |
570 | +site_root = getattr(settings, 'SITE_ROOT', 'http://summit.ubuntu.com') |
571 | + |
572 | +# Monkey-patch our NameField into the types of fields that the factory |
573 | +# understands. This is simpler than trying to subclass the Mommy |
574 | +# class directly. |
575 | +factory.default_mapping[NameField] = str |
576 | + |
577 | + |
578 | +class ICalTestCase(djangotest.TestCase): |
579 | + |
580 | + def test_ical_meeting_without_name(self): |
581 | + """ Tests that ical doesn't break for nameless meetings""" |
582 | + now = datetime.datetime.utcnow() |
583 | + one_hour = datetime.timedelta(0, 3600) |
584 | + summit = factory.make_one(Summit, name='uds-test') |
585 | + summit.save() |
586 | + slot = factory.make_one( |
587 | + Slot, |
588 | + start_utc=now, |
589 | + end_utc=now+one_hour, |
590 | + type='open', |
591 | + summit=summit |
592 | + ) |
593 | + slot.save() |
594 | + |
595 | + room = factory.make_one(Room, summit=summit) |
596 | + meeting = factory.make_one( |
597 | + Meeting, |
598 | + summit=summit, |
599 | + name='', |
600 | + private=False |
601 | + ) |
602 | + meeting.name = '' |
603 | + models.Model.save(meeting) |
604 | + agenda = factory.make_one( |
605 | + Agenda, |
606 | + slot=slot, |
607 | + meeting=meeting, |
608 | + room=room |
609 | + ) |
610 | + |
611 | + self.assertEquals( |
612 | + meeting.meeting_page_url, |
613 | + '/uds-test/meeting/%s/-/' % meeting.id |
614 | + ) |
615 | + |
616 | + response = self.client.get('/uds-test.ical') |
617 | + self.assertEquals(response.status_code, 200) |
618 | + self.assertContains( |
619 | + response, |
620 | + 'URL:%s/uds-test/meeting/%s/-/\n' % (site_root, meeting.id), |
621 | + 1 |
622 | + ) |
623 | + |
624 | + def test_ical_meeting_name_with_period(self): |
625 | + """ Tests that ical doesn't break for nameless meetings""" |
626 | + now = datetime.datetime.utcnow() |
627 | + one_hour = datetime.timedelta(0, 3600) |
628 | + summit = factory.make_one(Summit, name='uds-test') |
629 | + summit.save() |
630 | + slot = factory.make_one( |
631 | + Slot, |
632 | + start_utc=now, |
633 | + end_utc=now+one_hour, |
634 | + type='open', |
635 | + summit=summit |
636 | + ) |
637 | + slot.save() |
638 | + |
639 | + room = factory.make_one(Room, summit=summit) |
640 | + meeting = factory.make_one( |
641 | + Meeting, |
642 | + summit=summit, |
643 | + name='test.name', |
644 | + private=False |
645 | + ) |
646 | + agenda = factory.make_one( |
647 | + Agenda, |
648 | + slot=slot, |
649 | + meeting=meeting, |
650 | + room=room |
651 | + ) |
652 | + |
653 | + self.assertEquals( |
654 | + meeting.meeting_page_url, |
655 | + '/uds-test/meeting/%s/test.name/' % meeting.id |
656 | + ) |
657 | + |
658 | + response = self.client.get('/uds-test.ical') |
659 | + self.assertEquals(response.status_code, 200) |
660 | + self.assertContains( |
661 | + response, |
662 | + 'URL:%s/uds-test/meeting/%s/test.name/' % (site_root, meeting.id), |
663 | + 1 |
664 | + ) |
665 | + |
666 | + def test_ical_meeting_multiline_description(self): |
667 | + """ Tests that ical put spaces before multi-line descriptions""" |
668 | + now = datetime.datetime.utcnow() |
669 | + one_hour = datetime.timedelta(0, 3600) |
670 | + summit = factory.make_one(Summit, name='uds-test') |
671 | + summit.save() |
672 | + slot = factory.make_one( |
673 | + Slot, |
674 | + start_utc=now, |
675 | + end_utc=now+one_hour, |
676 | + type='open', |
677 | + summit=summit |
678 | + ) |
679 | + slot.save() |
680 | + |
681 | + room = factory.make_one(Room, summit=summit) |
682 | + meeting = factory.make_one( |
683 | + Meeting, |
684 | + summit=summit, |
685 | + name='test.name', |
686 | + description="Test\r\nDescription", |
687 | + private=False |
688 | + ) |
689 | + agenda = factory.make_one( |
690 | + Agenda, |
691 | + slot=slot, |
692 | + meeting=meeting, |
693 | + room=room |
694 | + ) |
695 | + |
696 | + self.assertEquals( |
697 | + meeting.meeting_page_url, |
698 | + '/uds-test/meeting/%s/test.name/' % meeting.id |
699 | + ) |
700 | + |
701 | + response = self.client.get('/uds-test.ical') |
702 | + self.assertEquals(response.status_code, 200) |
703 | + self.assertContains(response, 'DESCRIPTION:Test\NDescription', 1) |
704 | + |
705 | + def test_private_ical(self): |
706 | + """ Tests that private icals contain private meetings """ |
707 | + now = datetime.datetime.utcnow() |
708 | + one_hour = datetime.timedelta(0, 3600) |
709 | + week = datetime.timedelta(days=7) |
710 | + summit = factory.make_one(Summit, name='uds-test') |
711 | + slot = factory.make_one( |
712 | + Slot, |
713 | + start_utc=now, |
714 | + end_utc=now+one_hour, |
715 | + type='open', |
716 | + summit=summit |
717 | + ) |
718 | + |
719 | + room = factory.make_one(Room, summit=summit) |
720 | + meeting = factory.make_one( |
721 | + Meeting, |
722 | + summit=summit, |
723 | + name='test.name', |
724 | + private=True |
725 | + ) |
726 | + agenda = factory.make_one( |
727 | + Agenda, |
728 | + slot=slot, |
729 | + meeting=meeting, |
730 | + room=room |
731 | + ) |
732 | + |
733 | + self.assertEquals( |
734 | + meeting.meeting_page_url, |
735 | + '/uds-test/meeting/%s/test.name/' % meeting.id |
736 | + ) |
737 | + |
738 | + user = factory.make_one( |
739 | + User, |
740 | + username='testuser', |
741 | + first_name='Test', |
742 | + last_name='User' |
743 | + ) |
744 | + attendee = factory.make_one( |
745 | + Attendee, |
746 | + summit=summit, |
747 | + user=user, |
748 | + start_utc=now, |
749 | + end_utc=now+week |
750 | + ) |
751 | + participant = factory.make_one( |
752 | + Participant, |
753 | + attendee=attendee, |
754 | + meeting=meeting |
755 | + ) |
756 | + |
757 | + response = self.client.get( |
758 | + '/uds-test/participant/my_schedule_%s.ical' % attendee.secret_key |
759 | + ) |
760 | + self.assertEquals(response.status_code, 200) |
761 | + self.assertContains( |
762 | + response, |
763 | + 'URL:%s/uds-test/meeting/%s/test.name/' % (site_root, meeting.id), |
764 | + 1 |
765 | + ) |
766 | |
767 | === added file 'summit/schedule/tests/launchpad_export_node.py' |
768 | --- summit/schedule/tests/launchpad_export_node.py 1970-01-01 00:00:00 +0000 |
769 | +++ summit/schedule/tests/launchpad_export_node.py 2013-02-27 15:35:39 +0000 |
770 | @@ -0,0 +1,32 @@ |
771 | +# The Summit Scheduler web application |
772 | +# Copyright (C) 2008 - 2013 Ubuntu Community, Canonical Ltd |
773 | +# |
774 | +# This program is free software: you can redistribute it and/or modify |
775 | +# it under the terms of the GNU Affero General Public License as |
776 | +# published by the Free Software Foundation, either version 3 of the |
777 | +# License, or (at your option) any later version. |
778 | +# |
779 | +# This program is distributed in the hope that it will be useful, |
780 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
781 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
782 | +# GNU Affero General Public License for more details. |
783 | +# |
784 | +# You should have received a copy of the GNU Affero General Public License |
785 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
786 | + |
787 | + |
788 | +class LaunchpadExportNode(dict): |
789 | + |
790 | + def __init__(self, *args, **kwargs): |
791 | + self.__children = {} |
792 | + super(LaunchpadExportNode, self).__init__(*args, **kwargs) |
793 | + |
794 | + def add_child(self, key, node): |
795 | + self.__children.setdefault(key, []) |
796 | + self.__children[key].append(node) |
797 | + |
798 | + def findall(self, key): |
799 | + return self.__children.get(key, []) |
800 | + |
801 | + def find(self, key): |
802 | + return self.findall(key)[0] |
803 | |
804 | === added file 'summit/schedule/tests/meeting_model.py' |
805 | --- summit/schedule/tests/meeting_model.py 1970-01-01 00:00:00 +0000 |
806 | +++ summit/schedule/tests/meeting_model.py 2013-02-27 15:35:39 +0000 |
807 | @@ -0,0 +1,608 @@ |
808 | +# The Summit Scheduler web application |
809 | +# Copyright (C) 2008 - 2013 Ubuntu Community, Canonical Ltd |
810 | +# |
811 | +# This program is free software: you can redistribute it and/or modify |
812 | +# it under the terms of the GNU Affero General Public License as |
813 | +# published by the Free Software Foundation, either version 3 of the |
814 | +# License, or (at your option) any later version. |
815 | +# |
816 | +# This program is distributed in the hope that it will be useful, |
817 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
818 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
819 | +# GNU Affero General Public License for more details. |
820 | +# |
821 | +# You should have received a copy of the GNU Affero General Public License |
822 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
823 | + |
824 | + |
825 | +import datetime |
826 | +from django import test as djangotest |
827 | +from django.contrib.auth.models import User |
828 | + |
829 | +from model_mommy import mommy as factory |
830 | +from summit.schedule.fields import NameField |
831 | + |
832 | +from summit.schedule.models import ( |
833 | + Summit, |
834 | + Slot, |
835 | + Attendee, |
836 | + Meeting, |
837 | + Track, |
838 | + Room, |
839 | + Agenda, |
840 | + Participant, |
841 | +) |
842 | + |
843 | +from summit.schedule.tests.launchpad_export_node import LaunchpadExportNode |
844 | + |
845 | +# Monkey-patch our NameField into the types of fields that the factory |
846 | +# understands. This is simpler than trying to subclass the Mommy |
847 | +# class directly. |
848 | +factory.default_mapping[NameField] = str |
849 | + |
850 | + |
851 | +class MeetingModelTestCase(djangotest.TestCase): |
852 | + """Tests for the Meeting model.""" |
853 | + |
854 | + def test_meetings_can_not_be_scheduled_in_closed_slots(self): |
855 | + now = datetime.datetime.utcnow() |
856 | + one_hour = datetime.timedelta(0, 3600) |
857 | + slot = factory.make_one( |
858 | + Slot, |
859 | + start_utc=now, |
860 | + end_utc=now+one_hour, |
861 | + type='closed') |
862 | + |
863 | + agenda = factory.make_one(Agenda, slot=slot) |
864 | + meeting = factory.make_one( |
865 | + Meeting, |
866 | + requires_dial_in=False, |
867 | + private=False |
868 | + ) |
869 | + |
870 | + # XXX check_schedule should only be checking the schedule, not |
871 | + # checking and modifying the schedule. |
872 | + # XXX check_schedule's parameters should be an just an agenda object, |
873 | + # not the agenda object's attributes. |
874 | + self.assertRaises( |
875 | + Meeting.SchedulingError, |
876 | + meeting.check_schedule, agenda.slot, agenda.room) |
877 | + |
878 | + def test_participants_are_in_another_meeting(self): |
879 | + now = datetime.datetime.utcnow() |
880 | + one_hour = datetime.timedelta(0, 3600) |
881 | + slot = factory.make_one( |
882 | + Slot, |
883 | + start_utc=now, |
884 | + end_utc=now+one_hour) |
885 | + room1 = factory.make_one(Room) |
886 | + room2 = factory.make_one(Room) |
887 | + |
888 | + meeting1 = factory.make_one( |
889 | + Meeting, |
890 | + summit=slot.summit, |
891 | + requires_dial_in=False, |
892 | + private=False |
893 | + ) |
894 | + meeting2 = factory.make_one( |
895 | + Meeting, |
896 | + summit=slot.summit, |
897 | + requires_dial_in=False, |
898 | + private=False |
899 | + ) |
900 | + |
901 | + attendee = factory.make_one(Attendee) |
902 | + factory.make_one( |
903 | + Participant, |
904 | + meeting=meeting1, |
905 | + attendee=attendee, |
906 | + participation='REQUIRED' |
907 | + ) |
908 | + factory.make_one( |
909 | + Participant, |
910 | + meeting=meeting2, |
911 | + attendee=attendee, |
912 | + participation='REQUIRED' |
913 | + ) |
914 | + |
915 | + factory.make_one(Agenda, meeting=meeting1, slot=slot, room=room1) |
916 | + agenda = factory.make_one( |
917 | + Agenda, |
918 | + meeting=meeting2, |
919 | + slot=slot, |
920 | + room=room2 |
921 | + ) |
922 | + |
923 | + missing = meeting2.check_schedule(agenda.slot, agenda.room) |
924 | + self.assertEqual([attendee.name], [a.name for a in missing]) |
925 | + |
926 | + def make_open_slot(self): |
927 | + now = datetime.datetime.utcnow() |
928 | + one_hour = datetime.timedelta(0, 3600) |
929 | + slot = factory.make_one( |
930 | + Slot, |
931 | + start_utc=now+one_hour, |
932 | + end_utc=now+one_hour+one_hour, |
933 | + type='open') |
934 | + return slot |
935 | + |
936 | + def test_check_schedule_errors_on_no_dial_in(self): |
937 | + slot = self.make_open_slot() |
938 | + room = factory.make_one( |
939 | + Room, |
940 | + has_dial_in=False, |
941 | + summit=slot.summit, |
942 | + name="testroom" |
943 | + ) |
944 | + meeting = factory.make_one( |
945 | + Meeting, |
946 | + requires_dial_in=True, |
947 | + summit=slot.summit, |
948 | + name="testmeeting", |
949 | + private=False |
950 | + ) |
951 | + try: |
952 | + meeting.check_schedule(slot, room) |
953 | + except meeting.SchedulingError, e: |
954 | + self.assertEqual("Room has no dial-in capability", e.message) |
955 | + return |
956 | + self.fail("SchedulingError not thrown") |
957 | + |
958 | + def make_two_adjacent_slots(self): |
959 | + summit = factory.make_one(Summit, timezone='utc') |
960 | + now = datetime.datetime(2011, 9, 8, 12, 00) |
961 | + one_hour = datetime.timedelta(0, 3600) |
962 | + slot1 = factory.make_one( |
963 | + Slot, |
964 | + start_utc=now+one_hour, |
965 | + end_utc=now+one_hour+one_hour, |
966 | + type='open', summit=summit |
967 | + ) |
968 | + slot2 = factory.make_one( |
969 | + Slot, |
970 | + start_utc=now+one_hour+one_hour, |
971 | + end_utc=now+one_hour+one_hour+one_hour, |
972 | + type='open', summit=summit |
973 | + ) |
974 | + return slot1, slot2 |
975 | + |
976 | + def test_check_schedule_errors_on_same_track_in_previous_slot(self): |
977 | + slot1, slot2 = self.make_two_adjacent_slots() |
978 | + room = factory.make_one( |
979 | + Room, |
980 | + summit=slot1.summit, |
981 | + name="testroom" |
982 | + ) |
983 | + track = factory.make_one( |
984 | + Track, |
985 | + summit=slot1.summit, |
986 | + title="testtrack", |
987 | + allow_adjacent_sessions=False |
988 | + ) |
989 | + track2 = factory.make_one( |
990 | + Track, |
991 | + summit=slot1.summit, |
992 | + title="adjacenttrack", |
993 | + allow_adjacent_sessions=True |
994 | + ) |
995 | + meeting1 = factory.make_one( |
996 | + Meeting, |
997 | + requires_dial_in=False, |
998 | + summit=slot1.summit, |
999 | + name="testmeeting1", |
1000 | + type='blueprint', |
1001 | + private=False |
1002 | + ) |
1003 | + meeting2 = factory.make_one( |
1004 | + Meeting, |
1005 | + requires_dial_in=False, |
1006 | + summit=slot1.summit, |
1007 | + name="testmeeting2", |
1008 | + type='blueprint', |
1009 | + private=False |
1010 | + ) |
1011 | + meeting1.tracks = [track, track2] |
1012 | + meeting2.tracks = [track] |
1013 | + meeting1.agenda_set.create(room=room, slot=slot1) |
1014 | + try: |
1015 | + meeting2.check_schedule(slot2, room) |
1016 | + except meeting2.SchedulingError, e: |
1017 | + self.assertEqual("Same track in the previous slot", e.message) |
1018 | + return |
1019 | + self.fail("SchedulingError not thrown") |
1020 | + |
1021 | + def test_check_schedule_errors_on_same_track_in_next_slot(self): |
1022 | + slot1, slot2 = self.make_two_adjacent_slots() |
1023 | + room = factory.make_one(Room, summit=slot1.summit, name="testroom") |
1024 | + track = factory.make_one( |
1025 | + Track, |
1026 | + summit=slot1.summit, |
1027 | + title="testtrack", |
1028 | + allow_adjacent_sessions=False |
1029 | + ) |
1030 | + meeting1 = factory.make_one( |
1031 | + Meeting, |
1032 | + requires_dial_in=False, |
1033 | + summit=slot1.summit, |
1034 | + name="testmeeting1", |
1035 | + type='blueprint', |
1036 | + private=False |
1037 | + ) |
1038 | + meeting2 = factory.make_one( |
1039 | + Meeting, |
1040 | + requires_dial_in=False, |
1041 | + summit=slot1.summit, |
1042 | + name="testmeeting2", |
1043 | + type='blueprint', |
1044 | + private=False |
1045 | + ) |
1046 | + meeting1.tracks = [track] |
1047 | + meeting2.tracks = [track] |
1048 | + meeting1.agenda_set.create(room=room, slot=slot2) |
1049 | + try: |
1050 | + meeting2.check_schedule(slot1, room) |
1051 | + except meeting2.SchedulingError, e: |
1052 | + self.assertEqual("Same track in the next slot", e.message) |
1053 | + return |
1054 | + self.fail("SchedulingError not thrown") |
1055 | + |
1056 | + def test_check_schedule_no_error_on_different_track(self): |
1057 | + slot1, slot2 = self.make_two_adjacent_slots() |
1058 | + room = factory.make_one(Room, summit=slot1.summit, name="testroom") |
1059 | + track = factory.make_one( |
1060 | + Track, |
1061 | + summit=slot1.summit, |
1062 | + title="testtrack", |
1063 | + allow_adjacent_sessions=False |
1064 | + ) |
1065 | + other_track = factory.make_one( |
1066 | + Track, |
1067 | + summit=slot1.summit, |
1068 | + title="othertesttrack", |
1069 | + allow_adjacent_sessions=False |
1070 | + ) |
1071 | + meeting1 = factory.make_one( |
1072 | + Meeting, |
1073 | + requires_dial_in=False, |
1074 | + summit=slot1.summit, |
1075 | + name="testmeeting1", |
1076 | + type='blueprint', |
1077 | + private=False |
1078 | + ) |
1079 | + meeting2 = factory.make_one( |
1080 | + Meeting, |
1081 | + requires_dial_in=False, |
1082 | + summit=slot1.summit, |
1083 | + name="testmeeting2", |
1084 | + type='blueprint', |
1085 | + private=False |
1086 | + ) |
1087 | + meeting1.tracks = [track] |
1088 | + meeting2.tracks = [other_track] |
1089 | + meeting1.agenda_set.create(room=room, slot=slot2) |
1090 | + meeting2.check_schedule(slot1, room) |
1091 | + |
1092 | + def test_check_schedule_no_error_on_same_track_for_plenaries(self): |
1093 | + slot1, slot2 = self.make_two_adjacent_slots() |
1094 | + room = factory.make_one(Room, summit=slot1.summit, name="testroom") |
1095 | + track = factory.make_one( |
1096 | + Track, |
1097 | + summit=slot1.summit, |
1098 | + title="testtrack", |
1099 | + allow_adjacent_sessions=False |
1100 | + ) |
1101 | + meeting1 = factory.make_one( |
1102 | + Meeting, |
1103 | + requires_dial_in=False, |
1104 | + summit=slot1.summit, |
1105 | + name="testmeeting1", |
1106 | + type='blueprint', |
1107 | + private=False |
1108 | + ) |
1109 | + meeting2 = factory.make_one( |
1110 | + Meeting, |
1111 | + requires_dial_in=False, |
1112 | + summit=slot1.summit, |
1113 | + name="testmeeting2", |
1114 | + type='plenary', |
1115 | + private=False |
1116 | + ) |
1117 | + meeting1.tracks = [track] |
1118 | + meeting2.tracks = [track] |
1119 | + meeting1.agenda_set.create(room=room, slot=slot2) |
1120 | + meeting2.check_schedule(slot1, room) |
1121 | + |
1122 | + def test_check_schedule_no_error_same_track_ajdacent_sessions_allowed( |
1123 | + self |
1124 | + ): |
1125 | + slot1, slot2 = self.make_two_adjacent_slots() |
1126 | + room = factory.make_one(Room, summit=slot1.summit, name="testroom") |
1127 | + track = factory.make_one( |
1128 | + Track, |
1129 | + summit=slot1.summit, |
1130 | + title="adjacenttrack", |
1131 | + allow_adjacent_sessions=True |
1132 | + ) |
1133 | + meeting1 = factory.make_one( |
1134 | + Meeting, |
1135 | + requires_dial_in=False, |
1136 | + summit=slot1.summit, |
1137 | + name="testmeeting1", |
1138 | + type='blueprint', |
1139 | + private=False |
1140 | + ) |
1141 | + meeting2 = factory.make_one( |
1142 | + Meeting, |
1143 | + requires_dial_in=False, |
1144 | + summit=slot1.summit, |
1145 | + name="testmeeting2", |
1146 | + type='blueprint', |
1147 | + private=False |
1148 | + ) |
1149 | + meeting1.tracks = [track] |
1150 | + meeting2.tracks = [track] |
1151 | + meeting1.agenda_set.create(room=room, slot=slot2) |
1152 | + meeting2.check_schedule(slot1, room) |
1153 | + |
1154 | + def test_try_schedule_into_refuses_room_without_dial_in(self): |
1155 | + slot = self.make_open_slot() |
1156 | + room = factory.make_one( |
1157 | + Room, |
1158 | + has_dial_in=False, |
1159 | + summit=slot.summit, |
1160 | + name="testroom" |
1161 | + ) |
1162 | + meeting = factory.make_one( |
1163 | + Meeting, |
1164 | + requires_dial_in=True, |
1165 | + summit=slot.summit, |
1166 | + name="testmeeting", |
1167 | + private=False |
1168 | + ) |
1169 | + |
1170 | + self.assertEqual(False, meeting.try_schedule_into([room])) |
1171 | + self.assertEqual(0, meeting.agenda_set.all().count()) |
1172 | + |
1173 | + def test_try_schedule_into_allows_room_with_dial_in(self): |
1174 | + slot = self.make_open_slot() |
1175 | + room = factory.make_one( |
1176 | + Room, |
1177 | + has_dial_in=True, |
1178 | + summit=slot.summit, |
1179 | + name="testroom" |
1180 | + ) |
1181 | + meeting = factory.make_one( |
1182 | + Meeting, |
1183 | + requires_dial_in=True, |
1184 | + summit=slot.summit, |
1185 | + name="testmeeting", |
1186 | + private=False |
1187 | + ) |
1188 | + |
1189 | + self.assertEqual(True, meeting.try_schedule_into([room])) |
1190 | + self.assertEqual(1, meeting.agenda_set.all().count()) |
1191 | + |
1192 | + def test_link_to_pad_with_pad_url_set(self): |
1193 | + url = 'http://pad.com/url' |
1194 | + meeting = factory.make_one(Meeting, pad_url=url, private=False) |
1195 | + self.assertEqual(url, meeting.link_to_pad) |
1196 | + |
1197 | + def get_pad_host(self): |
1198 | + summit_name = 'testsummit' |
1199 | + summit = factory.make_one(Summit, name=summit_name) |
1200 | + return getattr(summit, 'etherpad', 'http://pad.ubuntu.com/') |
1201 | + |
1202 | + def test_link_to_pad_with_pad_url_unset(self): |
1203 | + summit_name = 'testsummit' |
1204 | + summit = factory.make_one(Summit, name=summit_name) |
1205 | + name = 'testmeeting' |
1206 | + meeting = factory.make_one( |
1207 | + Meeting, |
1208 | + pad_url=None, |
1209 | + name=name, |
1210 | + summit=summit, |
1211 | + private=False |
1212 | + ) |
1213 | + pad_host = self.get_pad_host() |
1214 | + url = pad_host + summit_name + '-' + name |
1215 | + self.assertEqual(url, meeting.link_to_pad) |
1216 | + |
1217 | + def test_link_to_pad_with_plus_in_meeting_name(self): |
1218 | + summit_name = 'testsummit' |
1219 | + summit = factory.make_one(Summit, name=summit_name) |
1220 | + name = 'test+meeting' |
1221 | + meeting = factory.make_one( |
1222 | + Meeting, |
1223 | + pad_url=None, |
1224 | + name=name, |
1225 | + summit=summit, |
1226 | + private=False |
1227 | + ) |
1228 | + pad_host = self.get_pad_host() |
1229 | + url = pad_host + summit_name + '-' + name.replace("+", "-") |
1230 | + self.assertEqual(url, meeting.link_to_pad) |
1231 | + |
1232 | + def test_edit_link_to_pad_with_pad_url_set(self): |
1233 | + url = 'http://pad.com/url' |
1234 | + meeting = factory.make_one(Meeting, pad_url=url, private=False) |
1235 | + self.assertEqual(url, meeting.edit_link_to_pad) |
1236 | + |
1237 | + def test_edit_link_to_pad_with_pad_url_unset(self): |
1238 | + summit_name = 'testsummit' |
1239 | + summit = factory.make_one(Summit, name=summit_name) |
1240 | + name = 'testmeeting' |
1241 | + meeting = factory.make_one( |
1242 | + Meeting, |
1243 | + pad_url=None, |
1244 | + name=name, |
1245 | + summit=summit, |
1246 | + private=False |
1247 | + ) |
1248 | + pad_host = self.get_pad_host() |
1249 | + url = pad_host + "ep/pad/view/" + summit_name + '-' + name + "/latest" |
1250 | + self.assertEqual(url, meeting.edit_link_to_pad) |
1251 | + |
1252 | + def test_edit_link_to_pad_with_plus_in_meeting_name(self): |
1253 | + summit_name = 'testsummit' |
1254 | + summit = factory.make_one(Summit, name=summit_name) |
1255 | + name = 'test+meeting' |
1256 | + meeting = factory.make_one( |
1257 | + Meeting, |
1258 | + pad_url=None, |
1259 | + name=name, |
1260 | + summit=summit, |
1261 | + private=False |
1262 | + ) |
1263 | + pad_host = self.get_pad_host() |
1264 | + url = ( |
1265 | + pad_host |
1266 | + + "ep/pad/view/" |
1267 | + + summit_name |
1268 | + + '-' |
1269 | + + name.replace("+", "-") |
1270 | + + "/latest" |
1271 | + ) |
1272 | + self.assertEqual(url, meeting.edit_link_to_pad) |
1273 | + |
1274 | + def test_update_from_launchpad_sets_status(self): |
1275 | + summit = factory.make_one(Summit, timezone='utc', name='test-summit') |
1276 | + meeting = factory.make_one( |
1277 | + Meeting, |
1278 | + pad_url=None, |
1279 | + name='test-meeting', |
1280 | + summit=summit, |
1281 | + private=False |
1282 | + ) |
1283 | + status = "Discussion" |
1284 | + name = meeting.name |
1285 | + elem = LaunchpadExportNode(status=status, name=name) |
1286 | + meeting.update_from_launchpad(elem) |
1287 | + self.assertEqual(status, meeting.status) |
1288 | + |
1289 | + def test_update_from_launchpad_sets_priority(self): |
1290 | + summit = factory.make_one(Summit, timezone='utc', name='test-summit') |
1291 | + meeting = factory.make_one( |
1292 | + Meeting, |
1293 | + pad_url=None, |
1294 | + name='test-meeting', |
1295 | + summit=summit, |
1296 | + private=False |
1297 | + ) |
1298 | + priority = 70 |
1299 | + name = meeting.name |
1300 | + elem = LaunchpadExportNode(priority=priority, name=name) |
1301 | + meeting.update_from_launchpad(elem) |
1302 | + self.assertEqual(priority, meeting.priority) |
1303 | + |
1304 | + def test_update_from_launchpad_sets_wiki_url(self): |
1305 | + summit = factory.make_one(Summit, timezone='utc', name='test-summit') |
1306 | + meeting = factory.make_one( |
1307 | + Meeting, |
1308 | + pad_url=None, |
1309 | + name='test-meeting', |
1310 | + summit=summit, |
1311 | + private=False |
1312 | + ) |
1313 | + wiki_url = "http://example.com/somespec" |
1314 | + name = meeting.name |
1315 | + elem = LaunchpadExportNode(specurl=wiki_url, name=name) |
1316 | + meeting.update_from_launchpad(elem) |
1317 | + self.assertEqual(wiki_url, meeting.wiki_url) |
1318 | + |
1319 | + def get_person_node(self, username, required=False): |
1320 | + elem = LaunchpadExportNode() |
1321 | + required_map = {True: "True", False: "False"} |
1322 | + elem.add_child( |
1323 | + "person", |
1324 | + LaunchpadExportNode( |
1325 | + name=username, |
1326 | + required=required_map[required] |
1327 | + ) |
1328 | + ) |
1329 | + return elem |
1330 | + |
1331 | + def make_one_future_slot(self, summit=None): |
1332 | + if summit is None: |
1333 | + summit = factory.make_one(Summit) |
1334 | + now = datetime.datetime.utcnow() |
1335 | + one_hour = datetime.timedelta(hours=1) |
1336 | + return factory.make_one( |
1337 | + Slot, |
1338 | + summit=summit, |
1339 | + start=now+one_hour, |
1340 | + end=now+one_hour+one_hour, |
1341 | + type='open' |
1342 | + ) |
1343 | + |
1344 | + def make_summit_and_attendee(self): |
1345 | + username = "username" |
1346 | + user = factory.make_one(User, username=username) |
1347 | + summit = factory.make_one(Summit) |
1348 | + slot = self.make_one_future_slot(summit=summit) |
1349 | + attendee = summit.attendee_set.create( |
1350 | + user=user, |
1351 | + start_utc=slot.start_utc, |
1352 | + end_utc=slot.end_utc |
1353 | + ) |
1354 | + return summit, attendee |
1355 | + |
1356 | + def test_update_from_launchpad_adds_participant(self): |
1357 | + summit, attendee = self.make_summit_and_attendee() |
1358 | + meeting = factory.make_one( |
1359 | + Meeting, |
1360 | + pad_url=None, |
1361 | + name='test-meeting', |
1362 | + summit=summit, |
1363 | + private=False |
1364 | + ) |
1365 | + name = meeting.name |
1366 | + elem = self.get_person_node( |
1367 | + attendee.user.username, |
1368 | + required=False, |
1369 | + ) |
1370 | + meeting.update_from_launchpad(elem) |
1371 | + participant = meeting.participant_set.get() |
1372 | + self.assertEqual(attendee, participant.attendee) |
1373 | + self.assertEqual('ATTENDING', participant.participation) |
1374 | + |
1375 | + def test_update_from_launchpad_sets_participant_essential(self): |
1376 | + summit, attendee = self.make_summit_and_attendee() |
1377 | + meeting = factory.make_one( |
1378 | + Meeting, |
1379 | + pad_url=None, |
1380 | + name='test-meeting', |
1381 | + summit=summit, |
1382 | + private=False |
1383 | + ) |
1384 | + name = meeting.name |
1385 | + elem = self.get_person_node( |
1386 | + attendee.user.username, |
1387 | + required=True, |
1388 | + ) |
1389 | + meeting.update_from_launchpad(elem) |
1390 | + participant = meeting.participant_set.get() |
1391 | + self.assertEqual('INTERESTED', participant.participation) |
1392 | + |
1393 | + def test_update_from_launchpad_sets_from_launchpad(self): |
1394 | + summit, attendee = self.make_summit_and_attendee() |
1395 | + meeting = summit.meeting_set.create() |
1396 | + elem = self.get_person_node(attendee.user.username) |
1397 | + meeting.update_from_launchpad(elem) |
1398 | + participant = meeting.participant_set.get() |
1399 | + self.assertEqual(True, participant.from_launchpad) |
1400 | + |
1401 | + def test_update_from_launchpad_removes_from_launchpad_unsubscribed(self): |
1402 | + summit, attendee = self.make_summit_and_attendee() |
1403 | + meeting = summit.meeting_set.create() |
1404 | + elem = self.get_person_node(attendee.user.username) |
1405 | + otheruser = factory.make_one(User, username="otheruser") |
1406 | + otherattendee = summit.attendee_set.create(user=otheruser) |
1407 | + meeting.participant_set.create( |
1408 | + attendee=otherattendee, |
1409 | + from_launchpad=True |
1410 | + ) |
1411 | + meeting.update_from_launchpad(elem) |
1412 | + usernames = [ |
1413 | + p.attendee.user.username for p in meeting.participant_set.all() |
1414 | + ] |
1415 | + self.assertEqual(["username"], usernames) |
1416 | |
1417 | === added file 'summit/schedule/tests/meeting_page.py' |
1418 | --- summit/schedule/tests/meeting_page.py 1970-01-01 00:00:00 +0000 |
1419 | +++ summit/schedule/tests/meeting_page.py 2013-02-27 15:35:39 +0000 |
1420 | @@ -0,0 +1,101 @@ |
1421 | +# The Summit Scheduler web application |
1422 | +# Copyright (C) 2008 - 2013 Ubuntu Community, Canonical Ltd |
1423 | +# |
1424 | +# This program is free software: you can redistribute it and/or modify |
1425 | +# it under the terms of the GNU Affero General Public License as |
1426 | +# published by the Free Software Foundation, either version 3 of the |
1427 | +# License, or (at your option) any later version. |
1428 | +# |
1429 | +# This program is distributed in the hope that it will be useful, |
1430 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1431 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1432 | +# GNU Affero General Public License for more details. |
1433 | +# |
1434 | +# You should have received a copy of the GNU Affero General Public License |
1435 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1436 | + |
1437 | + |
1438 | +import datetime |
1439 | +from django import test as djangotest |
1440 | +from django.core.urlresolvers import reverse |
1441 | +from django.conf import settings |
1442 | + |
1443 | +from model_mommy import mommy as factory |
1444 | +from summit.schedule.fields import NameField |
1445 | + |
1446 | +from summit.schedule.models import ( |
1447 | + Summit, |
1448 | + Slot, |
1449 | + Meeting, |
1450 | + Room, |
1451 | + Agenda, |
1452 | +) |
1453 | + |
1454 | +site_root = getattr(settings, 'SITE_ROOT', 'http://summit.ubuntu.com') |
1455 | + |
1456 | +# Monkey-patch our NameField into the types of fields that the factory |
1457 | +# understands. This is simpler than trying to subclass the Mommy |
1458 | +# class directly. |
1459 | +factory.default_mapping[NameField] = str |
1460 | + |
1461 | + |
1462 | +class MeetingPageTestCase(djangotest.TestCase): |
1463 | + |
1464 | + def test_meeting_page_url(self): |
1465 | + """ Tests the creation and reverse lookup of meeting page urls""" |
1466 | + now = datetime.datetime.utcnow() |
1467 | + one_hour = datetime.timedelta(0, 3600) |
1468 | + summit = factory.make_one(Summit, name='uds-test') |
1469 | + summit.save() |
1470 | + slot = factory.make_one( |
1471 | + Slot, |
1472 | + start_utc=now, |
1473 | + end_utc=now+one_hour, |
1474 | + type='open', |
1475 | + summit=summit |
1476 | + ) |
1477 | + slot.save() |
1478 | + |
1479 | + room = factory.make_one(Room, summit=summit) |
1480 | + meeting = factory.make_one( |
1481 | + Meeting, |
1482 | + summit=summit, |
1483 | + name='test-meeting', |
1484 | + private=False |
1485 | + ) |
1486 | + agenda = factory.make_one( |
1487 | + Agenda, |
1488 | + slot=slot, |
1489 | + meeting=meeting, |
1490 | + room=room |
1491 | + ) |
1492 | + |
1493 | + # check meeting page url generation |
1494 | + self.assertEquals( |
1495 | + meeting.meeting_page_url, |
1496 | + '/uds-test/meeting/%s/test-meeting/' % meeting.id |
1497 | + ) |
1498 | + |
1499 | + # check meeting page url reverse lookup |
1500 | + rev_args = ['uds-test', meeting.id, 'test-meeting'] |
1501 | + reverse_url = reverse('summit.schedule.views.meeting', args=rev_args) |
1502 | + self.assertEquals( |
1503 | + reverse_url, |
1504 | + '/uds-test/meeting/%s/test-meeting/' % meeting.id |
1505 | + ) |
1506 | + |
1507 | + # check meeting details page |
1508 | + response = self.client.get(reverse_url) |
1509 | + self.assertEquals(response.status_code, 200) |
1510 | + |
1511 | + # check meeting in ical |
1512 | + response = self.client.get('/uds-test.ical') |
1513 | + self.assertEquals(response.status_code, 200) |
1514 | + self.assertContains( |
1515 | + response, |
1516 | + 'URL:%s/uds-test/meeting/%s/test-meeting/' % ( |
1517 | + site_root, |
1518 | + meeting.id |
1519 | + ), |
1520 | + 1 |
1521 | + ) |
1522 | |
1523 | === added file 'summit/schedule/tests/meeting_search.py' |
1524 | --- summit/schedule/tests/meeting_search.py 1970-01-01 00:00:00 +0000 |
1525 | +++ summit/schedule/tests/meeting_search.py 2013-02-27 15:35:39 +0000 |
1526 | @@ -0,0 +1,335 @@ |
1527 | +# The Summit Scheduler web application |
1528 | +# Copyright (C) 2008 - 2013 Ubuntu Community, Canonical Ltd |
1529 | +# |
1530 | +# This program is free software: you can redistribute it and/or modify |
1531 | +# it under the terms of the GNU Affero General Public License as |
1532 | +# published by the Free Software Foundation, either version 3 of the |
1533 | +# License, or (at your option) any later version. |
1534 | +# |
1535 | +# This program is distributed in the hope that it will be useful, |
1536 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1537 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1538 | +# GNU Affero General Public License for more details. |
1539 | +# |
1540 | +# You should have received a copy of the GNU Affero General Public License |
1541 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1542 | + |
1543 | + |
1544 | +import datetime |
1545 | +from django import test as djangotest |
1546 | +from django.core.urlresolvers import reverse |
1547 | +from django.contrib.auth.models import User |
1548 | + |
1549 | +from model_mommy import mommy as factory |
1550 | +from summit.schedule.fields import NameField |
1551 | + |
1552 | +from summit.schedule.models import ( |
1553 | + Summit, |
1554 | + Slot, |
1555 | + Meeting, |
1556 | + Room, |
1557 | + Attendee, |
1558 | + Participant, |
1559 | +) |
1560 | + |
1561 | +# Monkey-patch our NameField into the types of fields that the factory |
1562 | +# understands. This is simpler than trying to subclass the Mommy |
1563 | +# class directly. |
1564 | +factory.default_mapping[NameField] = str |
1565 | + |
1566 | + |
1567 | +class MeetingSearchTestCase(djangotest.TestCase): |
1568 | + """ |
1569 | + This will test different options for deleting a meeting from |
1570 | + the front end UI. |
1571 | + """ |
1572 | + |
1573 | + form_html = '<form id="site_search_form"' |
1574 | + |
1575 | + def setUp(self): |
1576 | + now = datetime.datetime.utcnow() |
1577 | + one_hour = datetime.timedelta(0, 3600) |
1578 | + self.summit = factory.make_one( |
1579 | + Summit, |
1580 | + name='uds-test', |
1581 | + date_start=now, |
1582 | + date_end=now+one_hour |
1583 | + ) |
1584 | + self.slot = factory.make_one( |
1585 | + Slot, |
1586 | + summit=self.summit, |
1587 | + start_utc=now, |
1588 | + end_utc=now+one_hour |
1589 | + ) |
1590 | + self.room = factory.make_one(Room) |
1591 | + |
1592 | + def tearDown(self): |
1593 | + self.client.logout() |
1594 | + |
1595 | + def test_searchform_exists_on_summit_view(self): |
1596 | + ''' Search form should appear on the summit view page ''' |
1597 | + response = self.client.get( |
1598 | + reverse( |
1599 | + 'summit.schedule.views.summit', |
1600 | + args=[self.summit.name] |
1601 | + ) |
1602 | + ) |
1603 | + self.assertContains(response, self.form_html, 1) |
1604 | + |
1605 | + def test_searchform_exists_on_daily_view(self): |
1606 | + ''' Search form should appear on the list view page ''' |
1607 | + response = self.client.get( |
1608 | + reverse( |
1609 | + 'summit.schedule.views.daily_schedule', |
1610 | + args=[self.summit.name, '2012-10-10'] |
1611 | + ) |
1612 | + ) |
1613 | + self.assertContains(response, self.form_html, 1) |
1614 | + |
1615 | + def test_searchform_exists_on_today_view(self): |
1616 | + ''' Search form should appear on the today view page ''' |
1617 | + response = self.client.get( |
1618 | + reverse( |
1619 | + 'summit.schedule.views.today_view', |
1620 | + args=[self.summit.name] |
1621 | + ) |
1622 | + ) |
1623 | + self.assertContains(response, self.form_html, 1) |
1624 | + |
1625 | + def test_searchform_exists_on_meeting_view(self): |
1626 | + ''' Search form should appear on the meeting view page ''' |
1627 | + meeting = factory.make_one( |
1628 | + Meeting, |
1629 | + summit=self.summit, |
1630 | + requires_dial_in=False, |
1631 | + private=False |
1632 | + ) |
1633 | + |
1634 | + response = self.client.get( |
1635 | + reverse( |
1636 | + 'summit.schedule.views.meeting', |
1637 | + args=[self.summit.name, meeting.id, meeting.name] |
1638 | + ) |
1639 | + ) |
1640 | + self.assertContains(response, self.form_html, 1) |
1641 | + |
1642 | + def test_searchform_not_exists_on_index(self): |
1643 | + ''' |
1644 | + Search form should NOT appear on the index page because |
1645 | + there isn't a summit selected |
1646 | + ''' |
1647 | + response = self.client.get(reverse('summit.common.views.index')) |
1648 | + self.assertContains(response, self.form_html, 0) |
1649 | + |
1650 | + def test_meeting_in_search_results(self): |
1651 | + ''' |
1652 | + Meeting should appear in search results page if the query |
1653 | + matches the name or title |
1654 | + ''' |
1655 | + meeting = factory.make_one( |
1656 | + Meeting, |
1657 | + summit=self.summit, |
1658 | + name='test-name', |
1659 | + title='Test Title', |
1660 | + requires_dial_in=False, |
1661 | + private=False |
1662 | + ) |
1663 | + |
1664 | + # Attempt to match 'name' against 'test-name' in Meeting.name |
1665 | + response = self.client.get( |
1666 | + reverse( |
1667 | + 'summit.schedule.views.search', |
1668 | + args=[self.summit.name] |
1669 | + ), |
1670 | + {'q': 'name'} |
1671 | + ) |
1672 | + self.assertContains(response, self.form_html, 1) |
1673 | + self.assertContains( |
1674 | + response, |
1675 | + '<a href="%s">Test Title</a>' % meeting.get_meeting_page_url(), |
1676 | + 1 |
1677 | + ) |
1678 | + |
1679 | + # Attempt to match 'title' against 'Test Title' in Meeting.title |
1680 | + response = self.client.get( |
1681 | + reverse( |
1682 | + 'summit.schedule.views.search', |
1683 | + args=[self.summit.name] |
1684 | + ), |
1685 | + {'q': 'title'} |
1686 | + ) |
1687 | + self.assertContains(response, self.form_html, 1) |
1688 | + self.assertContains( |
1689 | + response, |
1690 | + '<a href="%s">Test Title</a>' % meeting.get_meeting_page_url(), |
1691 | + 1 |
1692 | + ) |
1693 | + |
1694 | + def test_meeting_not_in_search_results(self): |
1695 | + ''' |
1696 | + Meetings for one summit should NOT appear when searching |
1697 | + a different summit |
1698 | + ''' |
1699 | + now = datetime.datetime.utcnow() |
1700 | + one_hour = datetime.timedelta(0, 3600) |
1701 | + |
1702 | + # Create a second summit |
1703 | + other_summit = factory.make_one( |
1704 | + Summit, |
1705 | + name='uds-other', |
1706 | + date_start=now, |
1707 | + date_end=now+one_hour |
1708 | + ) |
1709 | + |
1710 | + meeting = factory.make_one( |
1711 | + Meeting, |
1712 | + summit=other_summit, |
1713 | + name='test-name', |
1714 | + title='Test Title', |
1715 | + requires_dial_in=False, |
1716 | + private=False |
1717 | + ) |
1718 | + |
1719 | + # Attempt to match 'test' against 'test-name' or 'Test Title' |
1720 | + # should return 0 results because the the meeting is in |
1721 | + # other_summit, not self.summit |
1722 | + response = self.client.get( |
1723 | + reverse( |
1724 | + 'summit.schedule.views.search', |
1725 | + args=[self.summit.name] |
1726 | + ), |
1727 | + {'q': 'test'} |
1728 | + ) |
1729 | + self.assertContains(response, self.form_html, 1) |
1730 | + self.assertContains( |
1731 | + response, |
1732 | + '<a href="%s">Test Title</a>' % meeting.get_meeting_page_url(), |
1733 | + 0 |
1734 | + ) |
1735 | + |
1736 | + # Same test, but searching the correct other_summit should return |
1737 | + # 1 result |
1738 | + response = self.client.get( |
1739 | + reverse( |
1740 | + 'summit.schedule.views.search', |
1741 | + args=[other_summit.name] |
1742 | + ), |
1743 | + {'q': 'test'} |
1744 | + ) |
1745 | + self.assertContains(response, self.form_html, 1) |
1746 | + self.assertContains( |
1747 | + response, |
1748 | + '<a href="%s">Test Title</a>' % meeting.get_meeting_page_url(), |
1749 | + 1 |
1750 | + ) |
1751 | + |
1752 | + def test_private_meeting_not_shown(self): |
1753 | + ''' |
1754 | + Private meetings should not be in the results if the attendee |
1755 | + is not attending it |
1756 | + ''' |
1757 | + now = datetime.datetime.now() |
1758 | + week = datetime.timedelta(days=7) |
1759 | + meeting = factory.make_one( |
1760 | + Meeting, |
1761 | + summit=self.summit, |
1762 | + name='test-name', |
1763 | + title='Test Title', |
1764 | + requires_dial_in=False, |
1765 | + private=True |
1766 | + ) |
1767 | + user = factory.make_one( |
1768 | + User, |
1769 | + username='testuser', |
1770 | + first_name='Test', |
1771 | + last_name='User', |
1772 | + is_active=True |
1773 | + ) |
1774 | + user.set_password('password') |
1775 | + user.save() |
1776 | + attendee = factory.make_one( |
1777 | + Attendee, |
1778 | + summit=self.summit, |
1779 | + user=user, |
1780 | + start_utc=now, |
1781 | + end_utc=now+week |
1782 | + ) |
1783 | + participant = factory.make_one( |
1784 | + Participant, |
1785 | + meeting=meeting, |
1786 | + attendee=attendee, |
1787 | + participation='ATTENDING', |
1788 | + from_launchpad=False |
1789 | + ) |
1790 | + |
1791 | + # Attempt to match 'name' against 'test-name' in Meeting.name |
1792 | + response = self.client.get( |
1793 | + reverse( |
1794 | + 'summit.schedule.views.search', |
1795 | + args=[self.summit.name] |
1796 | + ), |
1797 | + {'q': 'test'} |
1798 | + ) |
1799 | + self.assertContains(response, self.form_html, 1) |
1800 | + self.assertContains( |
1801 | + response, |
1802 | + '<a href="%s">Test Title</a>' % meeting.get_meeting_page_url(), |
1803 | + 0 |
1804 | + ) |
1805 | + |
1806 | + def test_private_meeting_with_attendee_shown(self): |
1807 | + ''' |
1808 | + Private meetings should be in the results if the attendee |
1809 | + is attending it |
1810 | + ''' |
1811 | + now = datetime.datetime.now() |
1812 | + week = datetime.timedelta(days=7) |
1813 | + meeting = factory.make_one( |
1814 | + Meeting, |
1815 | + summit=self.summit, |
1816 | + name='test-name', |
1817 | + title='Test Title', |
1818 | + requires_dial_in=False, |
1819 | + private=True |
1820 | + ) |
1821 | + user = factory.make_one( |
1822 | + User, |
1823 | + username='testuser', |
1824 | + first_name='Test', |
1825 | + last_name='User', |
1826 | + is_active=True |
1827 | + ) |
1828 | + user.set_password('password') |
1829 | + user.save() |
1830 | + attendee = factory.make_one( |
1831 | + Attendee, |
1832 | + summit=self.summit, |
1833 | + user=user, |
1834 | + start_utc=now, |
1835 | + end_utc=now+week |
1836 | + ) |
1837 | + participant = factory.make_one( |
1838 | + Participant, |
1839 | + meeting=meeting, |
1840 | + attendee=attendee, |
1841 | + participation='ATTENDING', |
1842 | + from_launchpad=False |
1843 | + ) |
1844 | + |
1845 | + logged_in = self.client.login(username='testuser', password='password') |
1846 | + self.assertTrue(logged_in) |
1847 | + |
1848 | + # Attempt to match 'name' against 'test-name' in Meeting.name |
1849 | + response = self.client.get( |
1850 | + reverse( |
1851 | + 'summit.schedule.views.search', |
1852 | + args=[self.summit.name] |
1853 | + ), |
1854 | + {'q': 'test'} |
1855 | + ) |
1856 | + self.assertContains(response, self.form_html, 1) |
1857 | + self.assertContains( |
1858 | + response, |
1859 | + '<a href="%s">Test Title</a>' % meeting.get_meeting_page_url(), |
1860 | + 1 |
1861 | + ) |
1862 | |
1863 | === added file 'summit/schedule/tests/participation_registration.py' |
1864 | --- summit/schedule/tests/participation_registration.py 1970-01-01 00:00:00 +0000 |
1865 | +++ summit/schedule/tests/participation_registration.py 2013-02-27 15:35:39 +0000 |
1866 | @@ -0,0 +1,202 @@ |
1867 | +# The Summit Scheduler web application |
1868 | +# Copyright (C) 2008 - 2013 Ubuntu Community, Canonical Ltd |
1869 | +# |
1870 | +# This program is free software: you can redistribute it and/or modify |
1871 | +# it under the terms of the GNU Affero General Public License as |
1872 | +# published by the Free Software Foundation, either version 3 of the |
1873 | +# License, or (at your option) any later version. |
1874 | +# |
1875 | +# This program is distributed in the hope that it will be useful, |
1876 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1877 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1878 | +# GNU Affero General Public License for more details. |
1879 | +# |
1880 | +# You should have received a copy of the GNU Affero General Public License |
1881 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1882 | + |
1883 | + |
1884 | +import datetime |
1885 | +from django import test as djangotest |
1886 | +from django.contrib.auth.models import User |
1887 | +from django.core.urlresolvers import reverse |
1888 | + |
1889 | +from model_mommy import mommy as factory |
1890 | +from summit.schedule.fields import NameField |
1891 | + |
1892 | +from summit.schedule.models import ( |
1893 | + Summit, |
1894 | + Slot, |
1895 | + Attendee, |
1896 | + Meeting, |
1897 | + Room, |
1898 | + Participant, |
1899 | +) |
1900 | + |
1901 | +# Monkey-patch our NameField into the types of fields that the factory |
1902 | +# understands. This is simpler than trying to subclass the Mommy |
1903 | +# class directly. |
1904 | +factory.default_mapping[NameField] = str |
1905 | + |
1906 | + |
1907 | +class ParticipationRegistrationTestCase(djangotest.TestCase): |
1908 | + |
1909 | + def setUp(self): |
1910 | + now = datetime.datetime.utcnow() |
1911 | + one_hour = datetime.timedelta(0, 3600) |
1912 | + week = datetime.timedelta(days=5) |
1913 | + self.summit = factory.make_one(Summit, name='uds-test') |
1914 | + self.slot = factory.make_one( |
1915 | + Slot, |
1916 | + start_utc=now+one_hour, |
1917 | + end_utc=now+(2*one_hour), |
1918 | + type='open', |
1919 | + summit=self.summit |
1920 | + ) |
1921 | + |
1922 | + self.room = factory.make_one(Room, summit=self.summit, type='open') |
1923 | + self.meeting = factory.make_one( |
1924 | + Meeting, |
1925 | + summit=self.summit, |
1926 | + name='meeting1', |
1927 | + private=False, |
1928 | + requires_dial_in=False, |
1929 | + spec_url='' |
1930 | + ) |
1931 | + |
1932 | + self.user = factory.make_one( |
1933 | + User, |
1934 | + username='testuser', |
1935 | + first_name='Test', |
1936 | + last_name='User', |
1937 | + is_active=True |
1938 | + ) |
1939 | + self.user.set_password('password') |
1940 | + self.user.save() |
1941 | + |
1942 | + self.attendee = factory.make_one( |
1943 | + Attendee, |
1944 | + summit=self.summit, |
1945 | + user=self.user, |
1946 | + start_utc=now, |
1947 | + end_utc=now+week |
1948 | + ) |
1949 | + |
1950 | + def tearDown(self): |
1951 | + pass |
1952 | + |
1953 | + def login(self): |
1954 | + logged_in = self.client.login(username='testuser', password='password') |
1955 | + self.assertTrue(logged_in) |
1956 | + |
1957 | + def test_attend_link(self): |
1958 | + self.assertEquals( |
1959 | + 0, |
1960 | + Participant.objects.filter( |
1961 | + attendee=self.attendee |
1962 | + ).count() |
1963 | + ) |
1964 | + self.login() |
1965 | + response = self.client.get( |
1966 | + reverse( |
1967 | + 'summit.schedule.views.meeting', |
1968 | + args=('uds-test', self.meeting.id, 'meeting1') |
1969 | + ) |
1970 | + ) |
1971 | + self.assertContains(response, 'Attend this meeting', 1) |
1972 | + self.assertContains(response, 'Subscribe to this meeting', 0) |
1973 | + self.assertContains(response, 'Skip this meeting', 0) |
1974 | + |
1975 | + def test_subscribe_link(self): |
1976 | + self.assertEquals( |
1977 | + 0, |
1978 | + Participant.objects.filter( |
1979 | + attendee=self.attendee |
1980 | + ).count() |
1981 | + ) |
1982 | + self.login() |
1983 | + self.meeting.spec_url = 'http://examplespec.com/test' |
1984 | + self.meeting.save() |
1985 | + response = self.client.get( |
1986 | + reverse( |
1987 | + 'summit.schedule.views.meeting', |
1988 | + args=('uds-test', self.meeting.id, 'meeting1') |
1989 | + ) |
1990 | + ) |
1991 | + self.assertContains(response, 'Subscribe to blueprint', 1) |
1992 | + self.assertContains( |
1993 | + response, |
1994 | + 'http://examplespec.com/test/+subscribe', |
1995 | + 1 |
1996 | + ) |
1997 | + self.assertContains(response, 'Attend this meeting', 1) |
1998 | + self.assertContains(response, 'Skip this meeting', 0) |
1999 | + |
2000 | + def test_skip_link(self): |
2001 | + self.meeting.participant_set.create( |
2002 | + attendee=self.attendee, |
2003 | + participation='ATTENDING', |
2004 | + from_launchpad=False |
2005 | + ) |
2006 | + self.assertEquals( |
2007 | + 1, |
2008 | + Participant.objects.filter( |
2009 | + attendee=self.attendee |
2010 | + ).count() |
2011 | + ) |
2012 | + self.login() |
2013 | + response = self.client.get( |
2014 | + reverse( |
2015 | + 'summit.schedule.views.meeting', |
2016 | + args=('uds-test', self.meeting.id, 'meeting1') |
2017 | + ) |
2018 | + ) |
2019 | + self.assertContains(response, 'Skip this meeting', 1) |
2020 | + self.assertContains(response, 'Subscribe to this meeting', 0) |
2021 | + self.assertContains(response, 'Attend this meeting', 0) |
2022 | + |
2023 | + def test_add_participation(self): |
2024 | + self.assertEquals( |
2025 | + 0, |
2026 | + Participant.objects.filter( |
2027 | + attendee=self.attendee |
2028 | + ).count() |
2029 | + ) |
2030 | + self.login() |
2031 | + response = self.client.get( |
2032 | + reverse( |
2033 | + 'summit.schedule.views.register', |
2034 | + args=('uds-test', self.meeting.id, 'meeting1') |
2035 | + ) |
2036 | + ) |
2037 | + self.assertEquals( |
2038 | + 1, |
2039 | + Participant.objects.filter( |
2040 | + attendee=self.attendee |
2041 | + ).count() |
2042 | + ) |
2043 | + |
2044 | + def test_delete_participation(self): |
2045 | + self.meeting.participant_set.create( |
2046 | + attendee=self.attendee, |
2047 | + participation='ATTENDING', |
2048 | + from_launchpad=False |
2049 | + ) |
2050 | + self.assertEquals( |
2051 | + 1, |
2052 | + Participant.objects.filter( |
2053 | + attendee=self.attendee |
2054 | + ).count() |
2055 | + ) |
2056 | + self.login() |
2057 | + response = self.client.get( |
2058 | + reverse( |
2059 | + 'summit.schedule.views.unregister', |
2060 | + args=('uds-test', self.meeting.id, 'meeting1') |
2061 | + ) |
2062 | + ) |
2063 | + self.assertEquals( |
2064 | + 0, |
2065 | + Participant.objects.filter( |
2066 | + attendee=self.attendee |
2067 | + ).count() |
2068 | + ) |
2069 | |
2070 | === added file 'summit/schedule/tests/private_scheduling.py' |
2071 | --- summit/schedule/tests/private_scheduling.py 1970-01-01 00:00:00 +0000 |
2072 | +++ summit/schedule/tests/private_scheduling.py 2013-02-27 15:35:39 +0000 |
2073 | @@ -0,0 +1,225 @@ |
2074 | +# The Summit Scheduler web application |
2075 | +# Copyright (C) 2008 - 2013 Ubuntu Community, Canonical Ltd |
2076 | +# |
2077 | +# This program is free software: you can redistribute it and/or modify |
2078 | +# it under the terms of the GNU Affero General Public License as |
2079 | +# published by the Free Software Foundation, either version 3 of the |
2080 | +# License, or (at your option) any later version. |
2081 | +# |
2082 | +# This program is distributed in the hope that it will be useful, |
2083 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
2084 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2085 | +# GNU Affero General Public License for more details. |
2086 | +# |
2087 | +# You should have received a copy of the GNU Affero General Public License |
2088 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
2089 | + |
2090 | + |
2091 | +import datetime |
2092 | +from django import test as djangotest |
2093 | +from django.contrib.auth.models import User |
2094 | + |
2095 | +from model_mommy import mommy as factory |
2096 | +from summit.schedule.fields import NameField |
2097 | + |
2098 | +from summit.schedule.models import ( |
2099 | + Summit, |
2100 | + Slot, |
2101 | + Attendee, |
2102 | + Meeting, |
2103 | + Room, |
2104 | + Agenda, |
2105 | +) |
2106 | + |
2107 | +# Monkey-patch our NameField into the types of fields that the factory |
2108 | +# understands. This is simpler than trying to subclass the Mommy |
2109 | +# class directly. |
2110 | +factory.default_mapping[NameField] = str |
2111 | + |
2112 | + |
2113 | +class PrivateSchedulingTestCase(djangotest.TestCase): |
2114 | + |
2115 | + def setUp(self): |
2116 | + now = datetime.datetime.utcnow() |
2117 | + one_hour = datetime.timedelta(0, 3600) |
2118 | + week = datetime.timedelta(days=5) |
2119 | + self.summit = factory.make_one(Summit, name='uds-test') |
2120 | + self.slot = factory.make_one( |
2121 | + Slot, |
2122 | + start_utc=now+one_hour, |
2123 | + end_utc=now+(2*one_hour), |
2124 | + type='open', |
2125 | + summit=self.summit |
2126 | + ) |
2127 | + |
2128 | + self.open_room = factory.make_one( |
2129 | + Room, |
2130 | + summit=self.summit, |
2131 | + type='open' |
2132 | + ) |
2133 | + self.public_meeting = factory.make_one( |
2134 | + Meeting, |
2135 | + summit=self.summit, |
2136 | + name='meeting1', |
2137 | + private=False, |
2138 | + requires_dial_in=False, |
2139 | + approved='APPROVED' |
2140 | + ) |
2141 | + |
2142 | + self.private_room = factory.make_one( |
2143 | + Room, |
2144 | + summit=self.summit, |
2145 | + type='private' |
2146 | + ) |
2147 | + self.private_meeting = factory.make_one( |
2148 | + Meeting, |
2149 | + summit=self.summit, |
2150 | + name='meeting2', |
2151 | + private=True, |
2152 | + requires_dial_in=False, |
2153 | + approved='APPROVED' |
2154 | + ) |
2155 | + |
2156 | + self.user = factory.make_one( |
2157 | + User, |
2158 | + username='testuser', |
2159 | + first_name='Test', |
2160 | + last_name='User' |
2161 | + ) |
2162 | + self.attendee = factory.make_one( |
2163 | + Attendee, |
2164 | + summit=self.summit, |
2165 | + user=self.user, |
2166 | + start_utc=now, |
2167 | + end_utc=now+week |
2168 | + ) |
2169 | + |
2170 | + def tearDown(self): |
2171 | + pass |
2172 | + |
2173 | + def assertRaises(self, exception_type, function, args): |
2174 | + try: |
2175 | + function(*args) |
2176 | + raise AssertionError( |
2177 | + 'Callable failed to raise exception %s' % exception_type |
2178 | + ) |
2179 | + except exception_type, e: |
2180 | + return True |
2181 | + |
2182 | + def run_autoschedule(self): |
2183 | + from django.core.management import execute_from_command_line |
2184 | + execute_from_command_line( |
2185 | + argv=['manage.py', 'autoschedule', 'uds-test', '-v', '2'] |
2186 | + ) |
2187 | + |
2188 | + def test_private_meeting_schedule(self): |
2189 | + ''' |
2190 | + General run of the autoschedule, no gurantee of what ends up where |
2191 | + ''' |
2192 | + self.run_autoschedule() |
2193 | + |
2194 | + # Private meetings should not ever be autoscheduled |
2195 | + self.assertEquals( |
2196 | + 0, |
2197 | + Agenda.objects.filter( |
2198 | + slot__summit=self.summit, |
2199 | + meeting__private=True, |
2200 | + room__type='open' |
2201 | + ).count() |
2202 | + ) |
2203 | + self.assertEquals( |
2204 | + 0, |
2205 | + Agenda.objects.filter( |
2206 | + slot__summit=self.summit, |
2207 | + meeting__private=False, |
2208 | + room__type='private' |
2209 | + ).count() |
2210 | + ) |
2211 | + # Private rooms should not ever be autoscheduled |
2212 | + self.assertEquals( |
2213 | + 0, |
2214 | + Agenda.objects.filter( |
2215 | + slot__summit=self.summit, |
2216 | + meeting__private=True, |
2217 | + room__type='private' |
2218 | + ).count() |
2219 | + ) |
2220 | + |
2221 | + # Public meetings in open rooms should be autoscheduled |
2222 | + self.assertEquals( |
2223 | + 1, |
2224 | + Agenda.objects.filter( |
2225 | + slot__summit=self.summit, |
2226 | + meeting__private=False, |
2227 | + room__type='open' |
2228 | + ).count() |
2229 | + ) |
2230 | + |
2231 | + def test_no_available_public_room(self): |
2232 | + ''' |
2233 | + Make sure public meetings will not be autoscheduled into private rooms |
2234 | + ''' |
2235 | + self.open_room.type = 'private' |
2236 | + self.open_room.save() |
2237 | + |
2238 | + self.run_autoschedule() |
2239 | + |
2240 | + # Without an open room, public meetings should not be autoscheduled |
2241 | + self.assertEquals(0, self.public_meeting.agenda_set.count()) |
2242 | + |
2243 | + # Private meetings should not ever be autoscheduled |
2244 | + self.assertEquals(0, self.private_meeting.agenda_set.count()) |
2245 | + |
2246 | + # Private rooms should not ever be autoscheduled |
2247 | + self.assertEquals( |
2248 | + 0, |
2249 | + Agenda.objects.filter( |
2250 | + room__type='private' |
2251 | + ).count() |
2252 | + ) |
2253 | + |
2254 | + def test_no_available_private_room(self): |
2255 | + ''' |
2256 | + Make sure private meetings will not be autoscheduled into open rooms |
2257 | + ''' |
2258 | + self.private_room.type = 'open' |
2259 | + self.private_room.save() |
2260 | + |
2261 | + self.run_autoschedule() |
2262 | + |
2263 | + # Private meetings should not ever be autoscheduled |
2264 | + self.assertEquals(0, self.private_meeting.agenda_set.count()) |
2265 | + |
2266 | + # Public meeting should be autoscheduled into one of the two open rooms |
2267 | + self.assertEquals(1, self.public_meeting.agenda_set.count()) |
2268 | + self.assertEquals(1, Agenda.objects.filter(room__type='open').count()) |
2269 | + |
2270 | + def test_required_participant_in_private_meeting(self): |
2271 | + ''' |
2272 | + Make sure meetings aren't scheduled when |
2273 | + someone is in a private meeting. |
2274 | + ''' |
2275 | + # Make the same person required for both meetings |
2276 | + self.public_meeting.participant_set.create( |
2277 | + attendee=self.attendee, |
2278 | + participation='REQUIRED' |
2279 | + ) |
2280 | + self.private_meeting.participant_set.create( |
2281 | + attendee=self.attendee, |
2282 | + participation='REQUIRED' |
2283 | + ) |
2284 | + # Schedule the private meeting in the one available slot |
2285 | + self.private_room.agenda_set.create( |
2286 | + slot=self.slot, |
2287 | + meeting=self.private_meeting |
2288 | + ) |
2289 | + |
2290 | + self.run_autoschedule() |
2291 | + |
2292 | + # Check that the private meeting is still scheduled |
2293 | + self.assertEquals( |
2294 | + 1, |
2295 | + self.private_meeting.agenda_set.count() |
2296 | + ) |
2297 | + # Check that the public meeting is not scheduled |
2298 | + self.assertEquals(0, self.public_meeting.agenda_set.count()) |
2299 | |
2300 | === added file 'summit/schedule/tests/render_schedule.py' |
2301 | --- summit/schedule/tests/render_schedule.py 1970-01-01 00:00:00 +0000 |
2302 | +++ summit/schedule/tests/render_schedule.py 2013-02-27 15:35:39 +0000 |
2303 | @@ -0,0 +1,196 @@ |
2304 | +# The Summit Scheduler web application |
2305 | +# Copyright (C) 2008 - 2013 Ubuntu Community, Canonical Ltd |
2306 | +# |
2307 | +# This program is free software: you can redistribute it and/or modify |
2308 | +# it under the terms of the GNU Affero General Public License as |
2309 | +# published by the Free Software Foundation, either version 3 of the |
2310 | +# License, or (at your option) any later version. |
2311 | +# |
2312 | +# This program is distributed in the hope that it will be useful, |
2313 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
2314 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2315 | +# GNU Affero General Public License for more details. |
2316 | +# |
2317 | +# You should have received a copy of the GNU Affero General Public License |
2318 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
2319 | + |
2320 | + |
2321 | +import datetime |
2322 | +from django import test as djangotest |
2323 | +from django.core.urlresolvers import reverse |
2324 | +from django.contrib.auth.models import User |
2325 | +from django.core.cache import cache |
2326 | + |
2327 | +from model_mommy import mommy as factory |
2328 | +from summit.schedule.fields import NameField |
2329 | + |
2330 | +from summit.schedule.models import ( |
2331 | + Summit, |
2332 | + Slot, |
2333 | + Attendee, |
2334 | + Meeting, |
2335 | + Track, |
2336 | + Room, |
2337 | + Agenda, |
2338 | +) |
2339 | + |
2340 | +# Monkey-patch our NameField into the types of fields that the factory |
2341 | +# understands. This is simpler than trying to subclass the Mommy |
2342 | +# class directly. |
2343 | +factory.default_mapping[NameField] = str |
2344 | + |
2345 | + |
2346 | +class RenderScheduleTestCase(djangotest.TestCase): |
2347 | + |
2348 | + def setUp(self): |
2349 | + now = datetime.datetime.utcnow() |
2350 | + one_hour = datetime.timedelta(0, 3600) |
2351 | + week = datetime.timedelta(days=5) |
2352 | + self.summit = factory.make_one(Summit, name='uds-test', timezone='UTC') |
2353 | + self.slot = factory.make_one( |
2354 | + Slot, |
2355 | + start_utc=now+one_hour, |
2356 | + end_utc=now+(2*one_hour), |
2357 | + type='open', |
2358 | + summit=self.summit |
2359 | + ) |
2360 | + |
2361 | + self.track1 = factory.make_one( |
2362 | + Track, |
2363 | + slug='test_slug', |
2364 | + summit=self.summit |
2365 | + ) |
2366 | + self.room1 = factory.make_one( |
2367 | + Room, |
2368 | + summit=self.summit, |
2369 | + name='room1' |
2370 | + ) |
2371 | + self.meeting1 = factory.make_one( |
2372 | + Meeting, |
2373 | + summit=self.summit, |
2374 | + name='meeting1', |
2375 | + private=False, |
2376 | + requires_dial_in=False |
2377 | + ) |
2378 | + self.agenda1 = factory.make_one( |
2379 | + Agenda, |
2380 | + slot=self.slot, |
2381 | + meeting=self.meeting1, |
2382 | + room=self.room1 |
2383 | + ) |
2384 | + |
2385 | + self.user = factory.make_one( |
2386 | + User, |
2387 | + username='testuser', |
2388 | + first_name='Test', |
2389 | + last_name='User' |
2390 | + ) |
2391 | + self.attendee = factory.make_one( |
2392 | + Attendee, |
2393 | + summit=self.summit, |
2394 | + user=self.user, |
2395 | + start_utc=now, |
2396 | + end_utc=now+week |
2397 | + ) |
2398 | + |
2399 | + def tearDown(self): |
2400 | + # Cached requests cause render.py to return old data. |
2401 | + # We will clear the cache |
2402 | + if hasattr(cache, 'clear'): |
2403 | + cache.clear() |
2404 | + # Older django didn't have .clear, but locmem cache did have ._cull |
2405 | + elif hasattr(cache, '_cull'): |
2406 | + cache._cull() |
2407 | + |
2408 | + def request_schedule(self): |
2409 | + schedule_args = [self.summit.name, self.agenda1.slot.start_utc.date()] |
2410 | + schedule_url = reverse( |
2411 | + 'summit.schedule.views.by_date', |
2412 | + args=schedule_args |
2413 | + ) |
2414 | + response = self.client.get(schedule_url) |
2415 | + return response |
2416 | + |
2417 | + def test_percent_in_meeting_name(self): |
2418 | + self.meeting1.name = 'test%meeting' |
2419 | + self.meeting1.save() |
2420 | + |
2421 | + response = self.request_schedule() |
2422 | + |
2423 | + self.assertContains(response, 'test%meeting', 1) |
2424 | + |
2425 | + def test_percent_in_meeting_title(self): |
2426 | + self.meeting1.title = 'test % meeting' |
2427 | + self.meeting1.save() |
2428 | + |
2429 | + response = self.request_schedule() |
2430 | + |
2431 | + self.assertContains(response, 'test % meeting', 1) |
2432 | + |
2433 | + def test_percent_in_room_title(self): |
2434 | + self.meeting1.type = 'talk' |
2435 | + self.meeting1.save() |
2436 | + self.room1.title = 'test % room' |
2437 | + self.room1.save() |
2438 | + |
2439 | + response = self.request_schedule() |
2440 | + |
2441 | + # Room title is displayed at top and bottom of the schedule, |
2442 | + # and also on the meeting div for self.meeting1 which is scheduled |
2443 | + # for that room |
2444 | + self.assertContains(response, 'test % room', 4) |
2445 | + |
2446 | + def test_percent_in_meeting_track_title(self): |
2447 | + self.track1.title = 'test % track' |
2448 | + self.track1.save() |
2449 | + self.meeting1.tracks.add(self.track1) |
2450 | + |
2451 | + response = self.request_schedule() |
2452 | + |
2453 | + self.assertContains(response, 'test % track', 1) |
2454 | + |
2455 | + def test_percent_in_meeting_track_slug(self): |
2456 | + self.track1.slug = 'test%track' |
2457 | + self.track1.save() |
2458 | + self.meeting1.tracks.add(self.track1) |
2459 | + |
2460 | + response = self.request_schedule() |
2461 | + |
2462 | + self.assertContains(response, 'test%track', 1) |
2463 | + |
2464 | + def test_specify_rooms_in_schedule(self): |
2465 | + room2 = factory.make_one( |
2466 | + Room, |
2467 | + summit=self.summit, |
2468 | + name='room2', |
2469 | + title='Room 2' |
2470 | + ) |
2471 | + self.room1.title = 'Room 1' |
2472 | + self.room1.save() |
2473 | + self.agenda1.delete() |
2474 | + |
2475 | + schedule_args = [self.summit.name, self.agenda1.slot.start_utc.date()] |
2476 | + schedule_url = reverse( |
2477 | + 'summit.schedule.views.by_date', |
2478 | + args=schedule_args |
2479 | + ) |
2480 | + |
2481 | + response = self.client.get(schedule_url) |
2482 | + self.assertContains(response, self.room1.title, 2) |
2483 | + self.assertContains(response, room2.title, 2) |
2484 | + |
2485 | + response = self.client.get(schedule_url + '?rooms=room1') |
2486 | + self.assertContains(response, self.room1.title, 2) |
2487 | + self.assertContains(response, room2.title, 0) |
2488 | + |
2489 | + response = self.client.get(schedule_url + '?rooms=room2') |
2490 | + self.assertContains(response, self.room1.title, 0) |
2491 | + self.assertContains(response, room2.title, 2) |
2492 | + |
2493 | + response = self.client.get(schedule_url + '?rooms=room1,room2') |
2494 | + self.assertContains(response, self.room1.title, 2) |
2495 | + self.assertContains(response, room2.title, 2) |
2496 | + |
2497 | + response = self.client.get(schedule_url + '?rooms=unknown1,unknown2') |
2498 | + self.assertContains(response, self.room1.title, 0) |
2499 | + self.assertContains(response, room2.title, 0) |
2500 | |
2501 | === added file 'summit/schedule/tests/request_factory.py' |
2502 | --- summit/schedule/tests/request_factory.py 1970-01-01 00:00:00 +0000 |
2503 | +++ summit/schedule/tests/request_factory.py 2013-02-27 15:35:39 +0000 |
2504 | @@ -0,0 +1,80 @@ |
2505 | +# The Summit Scheduler web application |
2506 | +# Copyright (C) 2008 - 2013 Ubuntu Community, Canonical Ltd |
2507 | +# |
2508 | +# This program is free software: you can redistribute it and/or modify |
2509 | +# it under the terms of the GNU Affero General Public License as |
2510 | +# published by the Free Software Foundation, either version 3 of the |
2511 | +# License, or (at your option) any later version. |
2512 | +# |
2513 | +# This program is distributed in the hope that it will be useful, |
2514 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
2515 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2516 | +# GNU Affero General Public License for more details. |
2517 | +# |
2518 | +# You should have received a copy of the GNU Affero General Public License |
2519 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
2520 | + |
2521 | + |
2522 | +from django import test as djangotest |
2523 | +from django.core.handlers.base import BaseHandler |
2524 | +from django.core.handlers.wsgi import WSGIRequest |
2525 | +from django.conf import settings |
2526 | + |
2527 | +from model_mommy import mommy as factory |
2528 | +from summit.schedule.fields import NameField |
2529 | + |
2530 | +# Monkey-patch our NameField into the types of fields that the factory |
2531 | +# understands. This is simpler than trying to subclass the Mommy |
2532 | +# class directly. |
2533 | +factory.default_mapping[NameField] = str |
2534 | + |
2535 | +site_root = getattr(settings, 'SITE_ROOT', 'http://summit.ubuntu.com') |
2536 | +theme_media = getattr(settings, 'THEME_MEDIA', 'ubuntu_website.MEDIA_ROOT') |
2537 | + |
2538 | + |
2539 | +class RequestFactory(djangotest.Client): |
2540 | + """ |
2541 | + Class that lets you create mock Request objects for use in testing. |
2542 | + |
2543 | + Usage: |
2544 | + |
2545 | + rf = RequestFactory() |
2546 | + get_request = rf.get('/hello/') |
2547 | + post_request = rf.post('/submit/', {'foo': 'bar'}) |
2548 | + |
2549 | + This class re-uses the django.test.client.Client interface, docs here: |
2550 | + http://www.djangoproject.com/documentation/testing/#the-test-client |
2551 | + |
2552 | + Once you have a request object you can pass it to any view function, |
2553 | + just as if that view had been hooked up using a URLconf. |
2554 | + |
2555 | + """ |
2556 | + def request(self, **request): |
2557 | + """ |
2558 | + Similar to parent class, but returns the request object as soon as it |
2559 | + has created it. |
2560 | + """ |
2561 | + environ = { |
2562 | + 'HTTP_COOKIE': self.cookies, |
2563 | + 'PATH_INFO': '/', |
2564 | + 'QUERY_STRING': '', |
2565 | + 'REQUEST_METHOD': 'GET', |
2566 | + 'SCRIPT_NAME': '', |
2567 | + 'SERVER_NAME': 'testserver', |
2568 | + 'SERVER_PORT': 80, |
2569 | + 'SERVER_PROTOCOL': 'HTTP/1.1', |
2570 | + 'wsgi.input': '', |
2571 | + } |
2572 | + environ.update(self.defaults) |
2573 | + environ.update(request) |
2574 | + request = WSGIRequest(environ) |
2575 | + handler = BaseHandler() |
2576 | + handler.load_middleware() |
2577 | + for middleware_method in handler._request_middleware: |
2578 | + if middleware_method(request): |
2579 | + raise Exception( |
2580 | + "Couldn't create request mock object - " |
2581 | + "request middleware %s returned a response" |
2582 | + % middleware_method |
2583 | + ) |
2584 | + return request |
2585 | |
2586 | === added file 'summit/schedule/tests/reverse_url.py' |
2587 | --- summit/schedule/tests/reverse_url.py 1970-01-01 00:00:00 +0000 |
2588 | +++ summit/schedule/tests/reverse_url.py 2013-02-27 15:35:39 +0000 |
2589 | @@ -0,0 +1,220 @@ |
2590 | +# The Summit Scheduler web application |
2591 | +# Copyright (C) 2008 - 2013 Ubuntu Community, Canonical Ltd |
2592 | +# |
2593 | +# This program is free software: you can redistribute it and/or modify |
2594 | +# it under the terms of the GNU Affero General Public License as |
2595 | +# published by the Free Software Foundation, either version 3 of the |
2596 | +# License, or (at your option) any later version. |
2597 | +# |
2598 | +# This program is distributed in the hope that it will be useful, |
2599 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
2600 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2601 | +# GNU Affero General Public License for more details. |
2602 | +# |
2603 | +# You should have received a copy of the GNU Affero General Public License |
2604 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
2605 | + |
2606 | + |
2607 | +import datetime |
2608 | +from django import test as djangotest |
2609 | +from django.core.urlresolvers import reverse |
2610 | +from django.contrib.auth.models import User |
2611 | + |
2612 | +from model_mommy import mommy as factory |
2613 | +from summit.schedule.fields import NameField |
2614 | + |
2615 | +from summit.schedule.models import ( |
2616 | + Summit, |
2617 | + Slot, |
2618 | + Meeting, |
2619 | + Track, |
2620 | + Room, |
2621 | +) |
2622 | + |
2623 | +# Monkey-patch our NameField into the types of fields that the factory |
2624 | +# understands. This is simpler than trying to subclass the Mommy |
2625 | +# class directly. |
2626 | +factory.default_mapping[NameField] = str |
2627 | + |
2628 | + |
2629 | +class ReverseUrlLookupTestCase(djangotest.TestCase): |
2630 | + |
2631 | + def setUp(self): |
2632 | + now = datetime.datetime.utcnow() |
2633 | + one_hour = datetime.timedelta(0, 3600) |
2634 | + self.summit = factory.make_one(Summit, name='uds-test') |
2635 | + self.summit.save() |
2636 | + self.slot = factory.make_one( |
2637 | + Slot, |
2638 | + start_utc=now, |
2639 | + end_utc=now+one_hour, |
2640 | + type='open', |
2641 | + summit=self.summit |
2642 | + ) |
2643 | + self.slot.save() |
2644 | + |
2645 | + def tearDown(self): |
2646 | + pass |
2647 | + |
2648 | + def test_meeting_name_with_period(self): |
2649 | + ''' |
2650 | + Testing a meeting with a . in the name |
2651 | + ''' |
2652 | + meeting = factory.make_one( |
2653 | + Meeting, |
2654 | + summit=self.summit, |
2655 | + name='test.meeting', |
2656 | + private=False |
2657 | + ) |
2658 | + |
2659 | + rev_args = ['uds-test', meeting.id, 'test.meeting'] |
2660 | + reverse_url = reverse('summit.schedule.views.meeting', args=rev_args) |
2661 | + self.assertEquals( |
2662 | + reverse_url, |
2663 | + '/uds-test/meeting/%s/test.meeting/' % meeting.id |
2664 | + ) |
2665 | + |
2666 | + def test_room_name_with_period(self): |
2667 | + ''' |
2668 | + Test the URL for a room name with a . in the name for both the website |
2669 | + and the ical |
2670 | + ''' |
2671 | + room = factory.make_one(Room, summit=self.summit, name='test.room') |
2672 | + |
2673 | + rev_args = ['uds-test', 'test.room'] |
2674 | + reverse_url = reverse('summit.schedule.views.by_room', args=rev_args) |
2675 | + self.assertEquals(reverse_url, '/uds-test/test.room/') |
2676 | + |
2677 | + reverse_url = reverse('summit.schedule.views.room_ical', args=rev_args) |
2678 | + self.assertEquals(reverse_url, '/uds-test/room/test.room.ical') |
2679 | + |
2680 | + def test_track_name_with_period(self): |
2681 | + ''' |
2682 | + Test the URL for a track name with a . in the name for both the website |
2683 | + and the ical |
2684 | + ''' |
2685 | + track = factory.make_one(Track, summit=self.summit, slug='test.track') |
2686 | + |
2687 | + rev_args = ['uds-test', 'test.track'] |
2688 | + reverse_url = reverse('summit.schedule.views.by_track', args=rev_args) |
2689 | + self.assertEquals(reverse_url, '/uds-test/track/test.track/') |
2690 | + |
2691 | + reverse_url = reverse( |
2692 | + 'summit.schedule.views.track_ical', |
2693 | + args=rev_args |
2694 | + ) |
2695 | + self.assertEquals(reverse_url, '/uds-test/track/test.track.ical') |
2696 | + |
2697 | + def test_participant_name_with_period(self): |
2698 | + ''' |
2699 | + Test the URL for a user with a . in their name for the website and |
2700 | + the iCal |
2701 | + ''' |
2702 | + user = factory.make_one(User, username='test.user') |
2703 | + |
2704 | + rev_args = ['uds-test', 'test.user'] |
2705 | + reverse_url = reverse('summit.schedule.views.user_ical', args=rev_args) |
2706 | + self.assertEquals(reverse_url, '/uds-test/participant/test.user.ical') |
2707 | + |
2708 | + def test_meeting_name_with_percent(self): |
2709 | + ''' |
2710 | + Test the URL for a meeting with a % in the name |
2711 | + ''' |
2712 | + meeting = factory.make_one( |
2713 | + Meeting, |
2714 | + summit=self.summit, |
2715 | + name='test.meeting', |
2716 | + private=False |
2717 | + ) |
2718 | + |
2719 | + rev_args = ['uds-test', meeting.id, 'test%meeting'] |
2720 | + reverse_url = reverse('summit.schedule.views.meeting', args=rev_args) |
2721 | + self.assertEquals( |
2722 | + reverse_url, |
2723 | + '/uds-test/meeting/%s/test%%meeting/' % meeting.id |
2724 | + ) |
2725 | + |
2726 | + def test_meeting_name_with_plus_sign(self): |
2727 | + meeting = factory.make_one( |
2728 | + Meeting, |
2729 | + summit=self.summit, |
2730 | + name='test.meeting', |
2731 | + private=False |
2732 | + ) |
2733 | + rev_args = ['uds-test', meeting.id, 'test+meeting'] |
2734 | + reverse_url = reverse('summit.schedule.views.meeting', args=rev_args) |
2735 | + self.assertEquals( |
2736 | + reverse_url, |
2737 | + '/uds-test/meeting/%s/test+meeting/' % meeting.id |
2738 | + ) |
2739 | + |
2740 | + def test_room_name_with_percent(self): |
2741 | + ''' |
2742 | + Test the URL for a room with a % in the name for both the website |
2743 | + and the iCal |
2744 | + ''' |
2745 | + room = factory.make_one(Room, summit=self.summit, name='test.room') |
2746 | + |
2747 | + rev_args = ['uds-test', 'test%room'] |
2748 | + reverse_url = reverse('summit.schedule.views.by_room', args=rev_args) |
2749 | + self.assertEquals(reverse_url, '/uds-test/test%room/') |
2750 | + |
2751 | + reverse_url = reverse('summit.schedule.views.room_ical', args=rev_args) |
2752 | + self.assertEquals(reverse_url, '/uds-test/room/test%room.ical') |
2753 | + |
2754 | + def test_room_name_with_plus_sign(self): |
2755 | + room = factory.make_one(Room, summit=self.summit, name='test.room') |
2756 | + |
2757 | + rev_args = ['uds-test', 'test+room'] |
2758 | + reverse_url = reverse('summit.schedule.views.by_room', args=rev_args) |
2759 | + self.assertEquals(reverse_url, '/uds-test/test+room/') |
2760 | + |
2761 | + reverse_url = reverse('summit.schedule.views.room_ical', args=rev_args) |
2762 | + self.assertEquals(reverse_url, '/uds-test/room/test+room.ical') |
2763 | + |
2764 | + def test_track_name_with_percent(self): |
2765 | + ''' |
2766 | + Test the URL for a track with a % in the name for both the website |
2767 | + and the iCal |
2768 | + ''' |
2769 | + track = factory.make_one(Track, summit=self.summit, slug='test.track') |
2770 | + |
2771 | + rev_args = ['uds-test', 'test%track'] |
2772 | + reverse_url = reverse('summit.schedule.views.by_track', args=rev_args) |
2773 | + self.assertEquals(reverse_url, '/uds-test/track/test%track/') |
2774 | + |
2775 | + reverse_url = reverse( |
2776 | + 'summit.schedule.views.track_ical', |
2777 | + args=rev_args |
2778 | + ) |
2779 | + self.assertEquals(reverse_url, '/uds-test/track/test%track.ical') |
2780 | + |
2781 | + def test_track_name_with_plus_sign(self): |
2782 | + track = factory.make_one(Track, summit=self.summit, slug='test.track') |
2783 | + |
2784 | + rev_args = ['uds-test', 'test+track'] |
2785 | + reverse_url = reverse('summit.schedule.views.by_track', args=rev_args) |
2786 | + self.assertEquals(reverse_url, '/uds-test/track/test+track/') |
2787 | + |
2788 | + reverse_url = reverse( |
2789 | + 'summit.schedule.views.track_ical', |
2790 | + args=rev_args |
2791 | + ) |
2792 | + self.assertEquals(reverse_url, '/uds-test/track/test+track.ical') |
2793 | + |
2794 | + def test_participant_name_with_percent(self): |
2795 | + ''' |
2796 | + Test the iCal URL for a participant with a % in the name. |
2797 | + ''' |
2798 | + user = factory.make_one(User, username='test.user') |
2799 | + |
2800 | + rev_args = ['uds-test', 'test%user'] |
2801 | + reverse_url = reverse('summit.schedule.views.user_ical', args=rev_args) |
2802 | + self.assertEquals(reverse_url, '/uds-test/participant/test%user.ical') |
2803 | + |
2804 | + def test_participant_name_with_plus_sign(self): |
2805 | + user = factory.make_one(User, username='test.user') |
2806 | + |
2807 | + rev_args = ['uds-test', 'test+user'] |
2808 | + reverse_url = reverse('summit.schedule.views.user_ical', args=rev_args) |
2809 | + self.assertEquals(reverse_url, '/uds-test/participant/test+user.ical') |
2810 | |
2811 | === added file 'summit/schedule/tests/schedule.py' |
2812 | --- summit/schedule/tests/schedule.py 1970-01-01 00:00:00 +0000 |
2813 | +++ summit/schedule/tests/schedule.py 2013-02-27 15:35:39 +0000 |
2814 | @@ -0,0 +1,537 @@ |
2815 | +# The Summit Scheduler web application |
2816 | +# Copyright (C) 2008 - 2013 Ubuntu Community, Canonical Ltd |
2817 | +# |
2818 | +# This program is free software: you can redistribute it and/or modify |
2819 | +# it under the terms of the GNU Affero General Public License as |
2820 | +# published by the Free Software Foundation, either version 3 of the |
2821 | +# License, or (at your option) any later version. |
2822 | +# |
2823 | +# This program is distributed in the hope that it will be useful, |
2824 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
2825 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2826 | +# GNU Affero General Public License for more details. |
2827 | +# |
2828 | +# You should have received a copy of the GNU Affero General Public License |
2829 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
2830 | + |
2831 | + |
2832 | +import datetime |
2833 | +import pytz |
2834 | +from django import test as djangotest |
2835 | +from django.contrib.auth.models import User |
2836 | +from django.contrib.contenttypes.models import ContentType |
2837 | + |
2838 | +from model_mommy import mommy as factory |
2839 | +from summit.schedule.fields import NameField |
2840 | + |
2841 | +from summit.schedule.models import ( |
2842 | + Summit, |
2843 | + Slot, |
2844 | + Attendee, |
2845 | + Meeting, |
2846 | + Track, |
2847 | + Room, |
2848 | +) |
2849 | + |
2850 | +from summit.schedule.render import Schedule |
2851 | + |
2852 | +from summit.schedule.tests.request_factory import RequestFactory |
2853 | + |
2854 | +# Monkey-patch our NameField into the types of fields that the factory |
2855 | +# understands. This is simpler than trying to subclass the Mommy |
2856 | +# class directly. |
2857 | +factory.default_mapping[NameField] = str |
2858 | + |
2859 | + |
2860 | +class ScheduleTestCase(djangotest.TestCase): |
2861 | + |
2862 | + def get_request(self): |
2863 | + return RequestFactory().request() |
2864 | + |
2865 | + def get_schedule_from_request(self, date=None): |
2866 | + request = self.get_request() |
2867 | + summit = factory.make_one(Summit) |
2868 | + return Schedule.from_request(request, summit, date=date) |
2869 | + |
2870 | + def test_default_read_only(self): |
2871 | + schedule = self.get_schedule_from_request() |
2872 | + self.assertEqual(False, schedule.edit) |
2873 | + |
2874 | + def get_user_with_schedule_permission(self): |
2875 | + user = factory.make_one( |
2876 | + User, |
2877 | + is_active=True, |
2878 | + is_staff=False, |
2879 | + is_superuser=False |
2880 | + ) |
2881 | + user.user_permissions.create( |
2882 | + codename='change_agenda', |
2883 | + content_type=factory.make_one(ContentType, app_label='schedule') |
2884 | + ) |
2885 | + return user |
2886 | + |
2887 | + def get_get_request(self, **kwargs): |
2888 | + return RequestFactory().get('/someurl/', data=kwargs) |
2889 | + |
2890 | + def get_edit_request(self, **kwargs): |
2891 | + kwargs['edit'] = True |
2892 | + return self.get_get_request(**kwargs) |
2893 | + |
2894 | + def test_editable(self): |
2895 | + user = self.get_user_with_schedule_permission() |
2896 | + request = self.get_edit_request() |
2897 | + request.user = user |
2898 | + summit = factory.make_one(Summit, state='schedule') |
2899 | + attendee = factory.make_one(Attendee, summit=summit, user=user) |
2900 | + schedule = Schedule.from_request(request, summit, attendee) |
2901 | + self.assertEqual(True, schedule.edit) |
2902 | + |
2903 | + def test_read_only_for_public_summit(self): |
2904 | + user = self.get_user_with_schedule_permission() |
2905 | + request = self.get_edit_request() |
2906 | + request.user = user |
2907 | + summit = factory.make_one(Summit, state='public') |
2908 | + attendee = factory.make_one(Attendee, summit=summit, user=user) |
2909 | + schedule = Schedule.from_request(request, summit, attendee) |
2910 | + self.assertEqual(False, schedule.edit) |
2911 | + |
2912 | + def test_read_only_for_non_edit_request(self): |
2913 | + user = self.get_user_with_schedule_permission() |
2914 | + request = self.get_request() |
2915 | + request.user = user |
2916 | + summit = factory.make_one(Summit, state='schedule') |
2917 | + attendee = factory.make_one(Attendee, summit=summit, user=user) |
2918 | + schedule = Schedule.from_request(request, summit, attendee) |
2919 | + self.assertEqual(False, schedule.edit) |
2920 | + |
2921 | + def test_read_only_for_unauthenticated_user(self): |
2922 | + request = self.get_edit_request() |
2923 | + summit = factory.make_one(Summit, state='schedule') |
2924 | + schedule = Schedule.from_request(request, summit) |
2925 | + self.assertEqual(False, schedule.edit) |
2926 | + |
2927 | + def test_read_only_for_user_without_permission(self): |
2928 | + user = factory.make_one(User, is_active=True, is_superuser=False) |
2929 | + request = self.get_edit_request() |
2930 | + request.user = user |
2931 | + summit = factory.make_one(Summit, state='schedule') |
2932 | + schedule = Schedule.from_request(request, summit) |
2933 | + self.assertEqual(False, schedule.edit) |
2934 | + |
2935 | + def test_default_not_personal(self): |
2936 | + schedule = self.get_schedule_from_request() |
2937 | + self.assertEqual(False, schedule.personal) |
2938 | + |
2939 | + def test_personal_if_specified_in_get(self): |
2940 | + request = self.get_get_request(personal=True) |
2941 | + summit = factory.make_one(Summit) |
2942 | + schedule = Schedule.from_request(request, summit) |
2943 | + self.assertEqual(True, schedule.personal) |
2944 | + |
2945 | + def test_date_set_from_date(self): |
2946 | + date = datetime.date.today() |
2947 | + schedule = self.get_schedule_from_request(date=date) |
2948 | + self.assertEqual(date, schedule.date) |
2949 | + self.assertEqual([date], schedule.dates) |
2950 | + |
2951 | + def test_date_parsed_from_string(self): |
2952 | + date = datetime.date.today() |
2953 | + date_str = date.strftime("%Y-%m-%d") |
2954 | + schedule = self.get_schedule_from_request(date=date_str) |
2955 | + self.assertEqual(date, schedule.date) |
2956 | + self.assertEqual([date], schedule.dates) |
2957 | + |
2958 | + def test_dates_set_from_summit_if_not_passed(self): |
2959 | + schedule = self.get_schedule_from_request() |
2960 | + self.assertEqual(None, schedule.date) |
2961 | + self.assertEqual(schedule.summit.dates(), schedule.dates) |
2962 | + |
2963 | + def test_room_set_from_room(self): |
2964 | + request = self.get_request() |
2965 | + summit = factory.make_one(Summit) |
2966 | + room = factory.make_one(Room, summit=summit) |
2967 | + schedule = Schedule.from_request(request, summit, room=room) |
2968 | + self.assertEqual(room, schedule.room) |
2969 | + self.assertEqual([room], schedule.rooms) |
2970 | + |
2971 | + def test_room_set_from_rooms(self): |
2972 | + request = self.get_request() |
2973 | + summit = factory.make_one(Summit) |
2974 | + rooms = factory.make_many(Room, 2, summit=summit) |
2975 | + schedule = Schedule.from_request(request, summit, room=rooms) |
2976 | + self.assertEqual(None, schedule.room) |
2977 | + self.assertEqual(rooms, schedule.rooms) |
2978 | + |
2979 | + def test_room_set_from_summit_if_not_passed(self): |
2980 | + request = self.get_request() |
2981 | + summit = factory.make_one(Summit) |
2982 | + room1 = factory.make_one( |
2983 | + Room, |
2984 | + summit=summit, |
2985 | + type='open', |
2986 | + name="room1" |
2987 | + ) |
2988 | + room2 = factory.make_one( |
2989 | + Room, |
2990 | + summit=summit, |
2991 | + type='open', |
2992 | + name="room2" |
2993 | + ) |
2994 | + factory.make_one(Room, summit=summit, type='closed') |
2995 | + factory.make_one(Room, summit=summit, type='private') |
2996 | + schedule = Schedule.from_request(request, summit) |
2997 | + self.assertEqual(None, schedule.room) |
2998 | + self.assertEqual( |
2999 | + ["room1", "room2"], |
3000 | + sorted([r.name for r in schedule.rooms]) |
3001 | + ) |
3002 | + |
3003 | + def test_rooms_include_private_if_user_is_staff(self): |
3004 | + user = factory.make_one( |
3005 | + User, |
3006 | + is_active=True, |
3007 | + is_staff=True, |
3008 | + is_superuser=False |
3009 | + ) |
3010 | + request = self.get_request() |
3011 | + request.user = user |
3012 | + summit = factory.make_one(Summit) |
3013 | + room1 = factory.make_one( |
3014 | + Room, |
3015 | + summit=summit, |
3016 | + type='open', |
3017 | + name="room1" |
3018 | + ) |
3019 | + room2 = factory.make_one( |
3020 | + Room, |
3021 | + summit=summit, |
3022 | + type='open', |
3023 | + name="room2" |
3024 | + ) |
3025 | + factory.make_one(Room, summit=summit, type='closed') |
3026 | + factory.make_one( |
3027 | + Room, |
3028 | + summit=summit, |
3029 | + type='private', |
3030 | + name="privateroom" |
3031 | + ) |
3032 | + schedule = Schedule.from_request(request, summit) |
3033 | + self.assertEqual(None, schedule.room) |
3034 | + self.assertEqual( |
3035 | + ["privateroom", "room1", "room2"], |
3036 | + sorted([r.name for r in schedule.rooms]) |
3037 | + ) |
3038 | + |
3039 | + def test_rooms_include_private_if_show_private(self): |
3040 | + request = self.get_request() |
3041 | + summit = factory.make_one(Summit) |
3042 | + room1 = factory.make_one( |
3043 | + Room, |
3044 | + summit=summit, |
3045 | + type='open', |
3046 | + name="room1" |
3047 | + ) |
3048 | + room2 = factory.make_one( |
3049 | + Room, |
3050 | + summit=summit, |
3051 | + type='open', |
3052 | + name="room2" |
3053 | + ) |
3054 | + factory.make_one(Room, summit=summit, type='closed') |
3055 | + factory.make_one( |
3056 | + Room, |
3057 | + summit=summit, |
3058 | + type='private', |
3059 | + name="privateroom" |
3060 | + ) |
3061 | + schedule = Schedule.from_request(request, summit, show_private=True) |
3062 | + self.assertEqual(None, schedule.room) |
3063 | + self.assertEqual( |
3064 | + ["privateroom", "room1", "room2"], |
3065 | + sorted([r.name for r in schedule.rooms]) |
3066 | + ) |
3067 | + |
3068 | + def test_track_is_none_by_default(self): |
3069 | + schedule = self.get_schedule_from_request() |
3070 | + self.assertEqual(None, schedule.track) |
3071 | + |
3072 | + def test_track_set_from_track(self): |
3073 | + request = self.get_request() |
3074 | + summit = factory.make_one(Summit) |
3075 | + track = factory.make_one(Track, summit=summit) |
3076 | + schedule = Schedule.from_request(request, summit, track=track) |
3077 | + self.assertEqual(track, schedule.track) |
3078 | + |
3079 | + def test_nextonly_false_by_default(self): |
3080 | + schedule = self.get_schedule_from_request() |
3081 | + self.assertEqual(False, schedule.nextonly) |
3082 | + |
3083 | + def test_nextonly_set_from_get_parameters(self): |
3084 | + request = self.get_get_request(next=True) |
3085 | + summit = factory.make_one(Summit) |
3086 | + schedule = Schedule.from_request(request, summit) |
3087 | + self.assertEqual(True, schedule.nextonly) |
3088 | + |
3089 | + def test_fakenow_none_by_default(self): |
3090 | + schedule = self.get_schedule_from_request() |
3091 | + self.assertEqual(None, schedule.fakenow) |
3092 | + |
3093 | + def test_fakenow_set_from_get_parameters(self): |
3094 | + summit = factory.make_one(Summit) |
3095 | + date = datetime.datetime(2011, 7, 8, 19, 12) |
3096 | + date = pytz.timezone(summit.timezone).localize(date) |
3097 | + request = self.get_get_request(fakenow=date.strftime("%Y-%m-%d_%H:%M")) |
3098 | + schedule = Schedule.from_request(request, summit) |
3099 | + self.assertEqual(date, schedule.fakenow) |
3100 | + |
3101 | + def test_fakenow_set_to_none_if_invalid(self): |
3102 | + summit = factory.make_one(Summit) |
3103 | + request = self.get_get_request(fakenow="AAAAA") |
3104 | + schedule = Schedule.from_request(request, summit) |
3105 | + self.assertEqual(None, schedule.fakenow) |
3106 | + |
3107 | + def get_schedule( |
3108 | + self, |
3109 | + edit=False, |
3110 | + room=None, |
3111 | + summit=None, |
3112 | + dates=None, |
3113 | + rooms=None |
3114 | + ): |
3115 | + request = self.get_request() |
3116 | + if summit is None: |
3117 | + summit = factory.make_one(Summit) |
3118 | + schedule = Schedule( |
3119 | + request, |
3120 | + summit, |
3121 | + edit=edit, |
3122 | + room=room, |
3123 | + dates=dates, |
3124 | + rooms=rooms |
3125 | + ) |
3126 | + return schedule |
3127 | + |
3128 | + def test_calculate_unscheduled_does_nothing_when_read_only(self): |
3129 | + schedule = self.get_schedule(edit=False) |
3130 | + schedule.calculate_unscheduled() |
3131 | + self.assertEqual([], schedule.unscheduled) |
3132 | + |
3133 | + def test_calculate_unscheduled_includes_unscheduled(self): |
3134 | + schedule = self.get_schedule(edit=True) |
3135 | + meeting = factory.make_one( |
3136 | + Meeting, |
3137 | + summit=schedule.summit, |
3138 | + private=False, |
3139 | + approved='APPROVED' |
3140 | + ) |
3141 | + schedule.calculate_unscheduled() |
3142 | + self.assertEqual([meeting], schedule.unscheduled) |
3143 | + |
3144 | + def test_calculate_unscheduled_ignores_scheduled_meetings(self): |
3145 | + schedule = self.get_schedule(edit=True) |
3146 | + meeting = factory.make_one( |
3147 | + Meeting, |
3148 | + summit=schedule.summit, |
3149 | + private=False |
3150 | + ) |
3151 | + room = factory.make_one(Room, summit=schedule.summit) |
3152 | + slot = factory.make_one(Slot, summit=schedule.summit) |
3153 | + meeting.agenda_set.create(room=room, slot=slot) |
3154 | + schedule.calculate_unscheduled() |
3155 | + self.assertEqual([], schedule.unscheduled) |
3156 | + |
3157 | + def test_calculate_unscheduled_ignores_meetings_in_tracks_not_in_this_room( |
3158 | + self |
3159 | + ): |
3160 | + summit = factory.make_one(Summit) |
3161 | + room = factory.make_one(Room, summit=summit, type='open') |
3162 | + schedule = self.get_schedule(edit=True, room=room, summit=summit) |
3163 | + meeting = factory.make_one( |
3164 | + Meeting, |
3165 | + summit=schedule.summit, |
3166 | + type='blueprint', |
3167 | + private=False |
3168 | + ) |
3169 | + track = factory.make_one(Track, summit=summit) |
3170 | + other_track = factory.make_one(Track, summit=summit) |
3171 | + room.tracks = [track] |
3172 | + meeting.tracks = [other_track] |
3173 | + schedule.calculate_unscheduled() |
3174 | + self.assertEqual([], schedule.unscheduled) |
3175 | + |
3176 | + def test_calculate_unscheduled_includes_meetings_without_a_track(self): |
3177 | + summit = factory.make_one(Summit) |
3178 | + room = factory.make_one(Room, summit=summit, type='open') |
3179 | + schedule = self.get_schedule(edit=True, room=room, summit=summit) |
3180 | + meeting = factory.make_one( |
3181 | + Meeting, |
3182 | + summit=schedule.summit, |
3183 | + type='blueprint', |
3184 | + private=False, |
3185 | + approved='APPROVED' |
3186 | + ) |
3187 | + track = factory.make_one(Track, summit=summit) |
3188 | + room.tracks = [track] |
3189 | + schedule.calculate_unscheduled() |
3190 | + self.assertEqual([meeting], schedule.unscheduled) |
3191 | + |
3192 | + def test_calculate_unscheduled_includes_all_meetings_in_room_without_a_track(self): |
3193 | + summit = factory.make_one(Summit) |
3194 | + room = factory.make_one(Room, summit=summit, type='open') |
3195 | + schedule = self.get_schedule(edit=True, room=room, summit=summit) |
3196 | + meeting = factory.make_one( |
3197 | + Meeting, |
3198 | + summit=schedule.summit, |
3199 | + type='blueprint', |
3200 | + private=False, |
3201 | + approved='APPROVED' |
3202 | + ) |
3203 | + track = factory.make_one(Track, summit=summit) |
3204 | + meeting.tracks = [track] |
3205 | + schedule.calculate_unscheduled() |
3206 | + self.assertEqual([meeting], schedule.unscheduled) |
3207 | + |
3208 | + def test_calculate_unscheduled_includes_meetings_of_the_right_track(self): |
3209 | + summit = factory.make_one(Summit) |
3210 | + room = factory.make_one(Room, summit=summit, type='open') |
3211 | + schedule = self.get_schedule(edit=True, room=room, summit=summit) |
3212 | + meeting = factory.make_one( |
3213 | + Meeting, |
3214 | + summit=schedule.summit, |
3215 | + type='blueprint', |
3216 | + private=False, |
3217 | + approved='APPROVED' |
3218 | + ) |
3219 | + track = factory.make_one(Track, summit=summit) |
3220 | + meeting.tracks = [track] |
3221 | + room.tracks = [track] |
3222 | + schedule.calculate_unscheduled() |
3223 | + self.assertEqual([meeting], schedule.unscheduled) |
3224 | + |
3225 | + def test_calculate_unscheduled_includes_meetings_with_one_right_track(self): |
3226 | + summit = factory.make_one(Summit) |
3227 | + room = factory.make_one(Room, summit=summit, type='open') |
3228 | + schedule = self.get_schedule(edit=True, room=room, summit=summit) |
3229 | + meeting = factory.make_one( |
3230 | + Meeting, |
3231 | + summit=schedule.summit, |
3232 | + type='blueprint', |
3233 | + private=False, |
3234 | + approved='APPROVED' |
3235 | + ) |
3236 | + track = factory.make_one(Track, summit=summit) |
3237 | + other_track = factory.make_one(Track, summit=summit) |
3238 | + meeting.tracks = [track, other_track] |
3239 | + room.tracks = [track] |
3240 | + schedule.calculate_unscheduled() |
3241 | + self.assertEqual([meeting], schedule.unscheduled) |
3242 | + |
3243 | + def test_calculate_unscheduled_ignores_plenaries_in_the_room_view(self): |
3244 | + summit = factory.make_one(Summit) |
3245 | + room = factory.make_one(Room, summit=summit, type='open') |
3246 | + schedule = self.get_schedule(edit=True, room=room, summit=summit) |
3247 | + meeting = factory.make_one( |
3248 | + Meeting, |
3249 | + summit=schedule.summit, |
3250 | + type='plenary', |
3251 | + private=False |
3252 | + ) |
3253 | + schedule.calculate_unscheduled() |
3254 | + self.assertEqual([], schedule.unscheduled) |
3255 | + |
3256 | + def test_calculate_unscheduled_ignores_talks_in_the_room_view(self): |
3257 | + summit = factory.make_one(Summit) |
3258 | + room = factory.make_one(Room, summit=summit, type='open') |
3259 | + schedule = self.get_schedule(edit=True, room=room, summit=summit) |
3260 | + meeting = factory.make_one( |
3261 | + Meeting, |
3262 | + summit=schedule.summit, |
3263 | + type='talk', |
3264 | + private=False |
3265 | + ) |
3266 | + schedule.calculate_unscheduled() |
3267 | + self.assertEqual([], schedule.unscheduled) |
3268 | + |
3269 | + def test_calculate_unscheduled_ignores_specials_in_the_room_view(self): |
3270 | + summit = factory.make_one(Summit) |
3271 | + room = factory.make_one(Room, summit=summit, type='open') |
3272 | + schedule = self.get_schedule(edit=True, room=room, summit=summit) |
3273 | + meeting = factory.make_one( |
3274 | + Meeting, |
3275 | + summit=schedule.summit, |
3276 | + type='special', |
3277 | + private=False |
3278 | + ) |
3279 | + schedule.calculate_unscheduled() |
3280 | + self.assertEqual([], schedule.unscheduled) |
3281 | + |
3282 | + def test_calculate_unscheduled_shows_plenaries_in_the_plenary_room_view( |
3283 | + self |
3284 | + ): |
3285 | + summit = factory.make_one(Summit) |
3286 | + room = factory.make_one(Room, summit=summit, type='plenary') |
3287 | + schedule = self.get_schedule(edit=True, room=room, summit=summit) |
3288 | + meeting = factory.make_one( |
3289 | + Meeting, |
3290 | + summit=schedule.summit, |
3291 | + type='plenary', |
3292 | + private=False, |
3293 | + approved='APPROVED' |
3294 | + ) |
3295 | + schedule.calculate_unscheduled() |
3296 | + self.assertEqual([meeting], schedule.unscheduled) |
3297 | + |
3298 | + def test_calculate_unscheduled_ignores_non_plenaries_in_the_plenary_room_view(self): |
3299 | + summit = factory.make_one(Summit) |
3300 | + room = factory.make_one(Room, summit=summit, type='plenary') |
3301 | + schedule = self.get_schedule(edit=True, room=room, summit=summit) |
3302 | + meeting = factory.make_one( |
3303 | + Meeting, |
3304 | + summit=schedule.summit, |
3305 | + type='blueprint', |
3306 | + private=False |
3307 | + ) |
3308 | + schedule.calculate_unscheduled() |
3309 | + self.assertEqual([], schedule.unscheduled) |
3310 | + |
3311 | + def test_calculate_passes_with_multiple_plenary_rooms_if_editing(self): |
3312 | + now = datetime.datetime.utcnow() |
3313 | + one_hour = datetime.timedelta(hours=1) |
3314 | + summit = factory.make_one( |
3315 | + Summit, |
3316 | + date_start=now.date(), |
3317 | + date_end=now.date(), |
3318 | + timezone='UTC' |
3319 | + ) |
3320 | + slot = factory.make_one( |
3321 | + Slot, |
3322 | + summit=summit, |
3323 | + type='plenary', |
3324 | + start_utc=now-(2*one_hour), |
3325 | + end_utc=now-(1*one_hour) |
3326 | + ) |
3327 | + room1 = factory.make_one( |
3328 | + Room, |
3329 | + summit=summit, |
3330 | + type='plenary', |
3331 | + start_utc=now-(2*one_hour), |
3332 | + end_utc=now-(1*one_hour) |
3333 | + ) |
3334 | + room2 = factory.make_one( |
3335 | + Room, |
3336 | + summit=summit, |
3337 | + type='plenary', |
3338 | + start_utc=now-(2*one_hour), |
3339 | + end_utc=now-(1*one_hour) |
3340 | + ) |
3341 | + schedule = self.get_schedule( |
3342 | + edit=True, |
3343 | + rooms=[room1, room2], |
3344 | + summit=summit, |
3345 | + dates=[now.date()] |
3346 | + ) |
3347 | + schedule.calculate() |
3348 | + # To avoid test being fragile and arbitrarily dependent on the |
3349 | + # room order, we check the returned schedule.meetings bit-by-bit. |
3350 | + self.assertEqual([slot], schedule.meetings.keys()) |
3351 | + self.assertEqual(1, len(set(schedule.meetings[slot]))) |
3352 | |
3353 | === added file 'summit/schedule/tests/schedule_cache.py' |
3354 | --- summit/schedule/tests/schedule_cache.py 1970-01-01 00:00:00 +0000 |
3355 | +++ summit/schedule/tests/schedule_cache.py 2013-02-27 15:35:39 +0000 |
3356 | @@ -0,0 +1,167 @@ |
3357 | +# The Summit Scheduler web application |
3358 | +# Copyright (C) 2008 - 2013 Ubuntu Community, Canonical Ltd |
3359 | +# |
3360 | +# This program is free software: you can redistribute it and/or modify |
3361 | +# it under the terms of the GNU Affero General Public License as |
3362 | +# published by the Free Software Foundation, either version 3 of the |
3363 | +# License, or (at your option) any later version. |
3364 | +# |
3365 | +# This program is distributed in the hope that it will be useful, |
3366 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
3367 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3368 | +# GNU Affero General Public License for more details. |
3369 | +# |
3370 | +# You should have received a copy of the GNU Affero General Public License |
3371 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
3372 | + |
3373 | + |
3374 | +import datetime |
3375 | +from django import test as djangotest |
3376 | +from django.core.urlresolvers import reverse |
3377 | +from django.contrib.auth.models import User |
3378 | +from django.core.cache import cache |
3379 | + |
3380 | +from model_mommy import mommy as factory |
3381 | +from summit.schedule.fields import NameField |
3382 | + |
3383 | +from summit.schedule.models import ( |
3384 | + Summit, |
3385 | + Slot, |
3386 | + Attendee, |
3387 | + Meeting, |
3388 | + Track, |
3389 | + Room, |
3390 | + Agenda, |
3391 | +) |
3392 | + |
3393 | +# Monkey-patch our NameField into the types of fields that the factory |
3394 | +# understands. This is simpler than trying to subclass the Mommy |
3395 | +# class directly. |
3396 | +factory.default_mapping[NameField] = str |
3397 | + |
3398 | + |
3399 | +class ScheduleCacheTestCase(djangotest.TestCase): |
3400 | + |
3401 | + def setUp(self): |
3402 | + now = datetime.datetime.utcnow() |
3403 | + one_hour = datetime.timedelta(0, 3600) |
3404 | + week = datetime.timedelta(days=5) |
3405 | + self.summit = factory.make_one(Summit, name='uds-test', timezone='UTC') |
3406 | + self.slot = factory.make_one( |
3407 | + Slot, |
3408 | + start_utc=now+one_hour, |
3409 | + end_utc=now+(2*one_hour), |
3410 | + type='open', |
3411 | + summit=self.summit |
3412 | + ) |
3413 | + |
3414 | + self.track = factory.make_one( |
3415 | + Track, |
3416 | + slug='test.track', |
3417 | + summit=self.summit |
3418 | + ) |
3419 | + self.room = factory.make_one( |
3420 | + Room, |
3421 | + name='test.room', |
3422 | + title='Test Room', |
3423 | + summit=self.summit |
3424 | + ) |
3425 | + self.room.tracks = [self.track] |
3426 | + self.meeting = factory.make_one( |
3427 | + Meeting, |
3428 | + summit=self.summit, |
3429 | + title='Test Meeting', |
3430 | + name='meeting', |
3431 | + private=False, |
3432 | + requires_dial_in=False |
3433 | + ) |
3434 | + self.meeting.tracks = [self.track] |
3435 | + self.agenda = factory.make_one( |
3436 | + Agenda, |
3437 | + slot=self.slot, |
3438 | + meeting=self.meeting, |
3439 | + room=self.room |
3440 | + ) |
3441 | + |
3442 | + self.user = factory.make_one( |
3443 | + User, |
3444 | + username='testuser', |
3445 | + first_name='Test', |
3446 | + last_name='User' |
3447 | + ) |
3448 | + self.attendee = factory.make_one( |
3449 | + Attendee, |
3450 | + summit=self.summit, |
3451 | + user=self.user, |
3452 | + start_utc=now, |
3453 | + end_utc=now+week |
3454 | + ) |
3455 | + |
3456 | + def tearDown(self): |
3457 | + # Cached requests cause render.py to return old data. |
3458 | + # Let's clear the cache |
3459 | + if hasattr(cache, 'clear'): |
3460 | + cache.clear() |
3461 | + # Older django didn't have .clear, but locmem cache did have ._cull |
3462 | + elif hasattr(cache, '_cull'): |
3463 | + cache._cull() |
3464 | + |
3465 | + def request_schedule_by_date(self): |
3466 | + schedule_args = [self.summit.name, self.agenda.slot.start_utc.date()] |
3467 | + schedule_url = reverse( |
3468 | + 'summit.schedule.views.by_date', |
3469 | + args=schedule_args |
3470 | + ) |
3471 | + response = self.client.get(schedule_url) |
3472 | + return response |
3473 | + |
3474 | + def request_schedule_by_track(self): |
3475 | + schedule_args = [self.summit.name, self.track.slug] |
3476 | + schedule_url = reverse( |
3477 | + 'summit.schedule.views.by_track', |
3478 | + args=schedule_args |
3479 | + ) |
3480 | + response = self.client.get(schedule_url) |
3481 | + return response |
3482 | + |
3483 | + def test_cache_cleared_on_meeting_change(self): |
3484 | + self.assertEqual(None, cache.get('meeting-html-%s' % self.meeting.id)) |
3485 | + response = self.request_schedule_by_date() |
3486 | + self.assertTrue( |
3487 | + 'Test Meeting' in cache.get( |
3488 | + 'meeting-html-%s' % self.meeting.id, |
3489 | + '' |
3490 | + ) |
3491 | + ) |
3492 | + |
3493 | + self.meeting.save() |
3494 | + |
3495 | + self.assertEqual(None, cache.get('meeting-html-%s' % self.meeting.id)) |
3496 | + response = self.request_schedule_by_date() |
3497 | + self.assertTrue( |
3498 | + 'Test Meeting' in cache.get( |
3499 | + 'meeting-html-%s' % self.meeting.id, |
3500 | + '' |
3501 | + ) |
3502 | + ) |
3503 | + |
3504 | + def test_cache_cleared_on_agenda_change(self): |
3505 | + self.assertEqual(None, cache.get('meeting-html-%s' % self.meeting.id)) |
3506 | + response = self.request_schedule_by_date() |
3507 | + self.assertTrue( |
3508 | + 'Test Meeting' in cache.get( |
3509 | + 'meeting-html-%s' % self.meeting.id, |
3510 | + '' |
3511 | + ) |
3512 | + ) |
3513 | + |
3514 | + self.agenda.save() |
3515 | + |
3516 | + self.assertEqual(None, cache.get('meeting-html-%s' % self.meeting.id)) |
3517 | + response = self.request_schedule_by_date() |
3518 | + self.assertTrue( |
3519 | + 'Test Meeting' in cache.get( |
3520 | + 'meeting-html-%s' % self.meeting.id, |
3521 | + '' |
3522 | + ) |
3523 | + ) |
3524 | |
3525 | === added file 'summit/schedule/tests/scheduling_conflicts.py' |
3526 | --- summit/schedule/tests/scheduling_conflicts.py 1970-01-01 00:00:00 +0000 |
3527 | +++ summit/schedule/tests/scheduling_conflicts.py 2013-02-27 15:35:39 +0000 |
3528 | @@ -0,0 +1,146 @@ |
3529 | +# The Summit Scheduler web application |
3530 | +# Copyright (C) 2008 - 2013 Ubuntu Community, Canonical Ltd |
3531 | +# |
3532 | +# This program is free software: you can redistribute it and/or modify |
3533 | +# it under the terms of the GNU Affero General Public License as |
3534 | +# published by the Free Software Foundation, either version 3 of the |
3535 | +# License, or (at your option) any later version. |
3536 | +# |
3537 | +# This program is distributed in the hope that it will be useful, |
3538 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
3539 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3540 | +# GNU Affero General Public License for more details. |
3541 | +# |
3542 | +# You should have received a copy of the GNU Affero General Public License |
3543 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
3544 | + |
3545 | + |
3546 | +import datetime |
3547 | +from django import test as djangotest |
3548 | +from django.contrib.auth.models import User |
3549 | + |
3550 | +from model_mommy import mommy as factory |
3551 | +from summit.schedule.fields import NameField |
3552 | + |
3553 | +from summit.schedule.models import ( |
3554 | + Summit, |
3555 | + Slot, |
3556 | + Attendee, |
3557 | + Meeting, |
3558 | + Room, |
3559 | + Agenda, |
3560 | + Participant, |
3561 | +) |
3562 | + |
3563 | + |
3564 | +# Monkey-patch our NameField into the types of fields that the factory |
3565 | +# understands. This is simpler than trying to subclass the Mommy |
3566 | +# class directly. |
3567 | +factory.default_mapping[NameField] = str |
3568 | + |
3569 | + |
3570 | +class SchedulingConflictsTestCase(djangotest.TestCase): |
3571 | + |
3572 | + def setUp(self): |
3573 | + now = datetime.datetime.utcnow() |
3574 | + one_hour = datetime.timedelta(0, 3600) |
3575 | + week = datetime.timedelta(days=5) |
3576 | + self.summit = factory.make_one(Summit, name='uds-test') |
3577 | + self.slot = factory.make_one( |
3578 | + Slot, |
3579 | + start_utc=now, |
3580 | + end_utc=now+one_hour, |
3581 | + type='open', |
3582 | + summit=self.summit) |
3583 | + |
3584 | + self.room1 = factory.make_one(Room, summit=self.summit) |
3585 | + self.meeting1 = factory.make_one( |
3586 | + Meeting, |
3587 | + summit=self.summit, |
3588 | + name='meeting1', |
3589 | + requires_dial_in=False |
3590 | + ) |
3591 | + self.agenda1 = factory.make_one( |
3592 | + Agenda, |
3593 | + slot=self.slot, |
3594 | + meeting=self.meeting1, |
3595 | + room=self.room1 |
3596 | + ) |
3597 | + |
3598 | + self.room2 = factory.make_one(Room, summit=self.summit) |
3599 | + self.meeting2 = factory.make_one( |
3600 | + Meeting, |
3601 | + summit=self.summit, |
3602 | + name='meeting2', |
3603 | + requires_dial_in=False |
3604 | + ) |
3605 | + |
3606 | + self.user = factory.make_one( |
3607 | + User, |
3608 | + username='testuser', |
3609 | + first_name='Test', |
3610 | + last_name='User' |
3611 | + ) |
3612 | + self.attendee = factory.make_one( |
3613 | + Attendee, |
3614 | + summit=self.summit, |
3615 | + user=self.user, |
3616 | + start_utc=now, |
3617 | + end_utc=now+week |
3618 | + ) |
3619 | + |
3620 | + def tearDown(self): |
3621 | + pass |
3622 | + |
3623 | + def assertRaises(self, exception_type, function, args): |
3624 | + try: |
3625 | + function(*args) |
3626 | + raise AssertionError( |
3627 | + 'Callable failed to raise exception %s' % exception_type |
3628 | + ) |
3629 | + except exception_type, e: |
3630 | + return True |
3631 | + |
3632 | + def test_meeting_check_schedule_no_conflict(self): |
3633 | + '''Checks the Meeting model's check_schedule''' |
3634 | + missing = self.meeting1.check_schedule(self.slot, self.room1) |
3635 | + self.assertEquals(len(missing), 0) |
3636 | + |
3637 | + missing = self.meeting2.check_schedule(self.slot, self.room2) |
3638 | + self.assertEquals(len(missing), 0) |
3639 | + |
3640 | + def test_meeting_check_room_conflict(self): |
3641 | + '''Checks that two meetings will not be scheduled in the same room |
3642 | + at the same time |
3643 | + ''' |
3644 | + missing = self.meeting1.check_schedule(self.slot, self.room1) |
3645 | + self.assertEquals(len(missing), 0) |
3646 | + |
3647 | + self.assertRaises( |
3648 | + Meeting.SchedulingError, |
3649 | + Meeting.check_schedule, |
3650 | + (self.meeting2, |
3651 | + self.slot, |
3652 | + self.room1) |
3653 | + ) |
3654 | + |
3655 | + def test_meeting_check_schedule_participant_conflict(self): |
3656 | + ''' |
3657 | + Checks that a two meetings requiring the same attendee will mark that |
3658 | + user as missing. |
3659 | + ''' |
3660 | + participant1 = Participant.objects.create( |
3661 | + meeting=self.meeting1, |
3662 | + attendee=self.attendee, |
3663 | + participation='REQUIRED' |
3664 | + ) |
3665 | + missing = self.meeting1.check_schedule(self.slot, self.room1) |
3666 | + self.assertEquals(len(missing), 0) |
3667 | + |
3668 | + participant1 = Participant.objects.create( |
3669 | + meeting=self.meeting2, |
3670 | + attendee=self.attendee, |
3671 | + participation='REQUIRED' |
3672 | + ) |
3673 | + missing = self.meeting2.check_schedule(self.slot, self.room2) |
3674 | + self.assertEquals(len(missing), 1) |
3675 | |
3676 | === added file 'summit/schedule/tests/summit_model.py' |
3677 | --- summit/schedule/tests/summit_model.py 1970-01-01 00:00:00 +0000 |
3678 | +++ summit/schedule/tests/summit_model.py 2013-02-27 15:35:39 +0000 |
3679 | @@ -0,0 +1,501 @@ |
3680 | +# The Summit Scheduler web application |
3681 | +# Copyright (C) 2008 - 2013 Ubuntu Community, Canonical Ltd |
3682 | +# |
3683 | +# This program is free software: you can redistribute it and/or modify |
3684 | +# it under the terms of the GNU Affero General Public License as |
3685 | +# published by the Free Software Foundation, either version 3 of the |
3686 | +# License, or (at your option) any later version. |
3687 | +# |
3688 | +# This program is distributed in the hope that it will be useful, |
3689 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
3690 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3691 | +# GNU Affero General Public License for more details. |
3692 | +# |
3693 | +# You should have received a copy of the GNU Affero General Public License |
3694 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
3695 | + |
3696 | + |
3697 | +import datetime |
3698 | +from django import test as djangotest |
3699 | + |
3700 | +from model_mommy import mommy as factory |
3701 | +from summit.schedule.fields import NameField |
3702 | + |
3703 | +from summit.schedule.models import ( |
3704 | + Summit, |
3705 | + Slot, |
3706 | + Attendee, |
3707 | + Meeting, |
3708 | + Room, |
3709 | + Agenda, |
3710 | + SummitSprint, |
3711 | +) |
3712 | + |
3713 | +from summit.common import launchpad |
3714 | + |
3715 | +from summit.schedule.tests.launchpad_export_node import LaunchpadExportNode |
3716 | + |
3717 | +# Monkey-patch our NameField into the types of fields that the factory |
3718 | +# understands. This is simpler than trying to subclass the Mommy |
3719 | +# class directly. |
3720 | +factory.default_mapping[NameField] = str |
3721 | + |
3722 | + |
3723 | +class SummitModelTestCase(djangotest.TestCase): |
3724 | + |
3725 | + def get_basic_launchpad_response(self): |
3726 | + elem = LaunchpadExportNode() |
3727 | + elem.add_child("attendees", LaunchpadExportNode()) |
3728 | + elem.add_child("unscheduled", LaunchpadExportNode()) |
3729 | + return elem |
3730 | + |
3731 | + def make_one_future_slot(self, summit=None): |
3732 | + if summit is None: |
3733 | + summit = factory.make_one(Summit) |
3734 | + now = datetime.datetime.utcnow() |
3735 | + one_hour = datetime.timedelta(hours=1) |
3736 | + return factory.make_one( |
3737 | + Slot, |
3738 | + summit=summit, |
3739 | + start=now+one_hour, |
3740 | + end=now+one_hour+one_hour, |
3741 | + type='open' |
3742 | + ) |
3743 | + |
3744 | + def test_update_meeting_skips_no_name(self): |
3745 | + summit = factory.make_one(Summit) |
3746 | + elem = LaunchpadExportNode() |
3747 | + meeting = summit.update_meeting_from_launchpad(elem) |
3748 | + self.assertEqual(None, meeting) |
3749 | + self.assertEqual(0, Meeting.objects.all().count()) |
3750 | + |
3751 | + def test_update_meeting_trims_name(self): |
3752 | + summit = factory.make_one(Summit) |
3753 | + elem = LaunchpadExportNode(name="very " * 20 + "longname", id="42") |
3754 | + meeting = summit.update_meeting_from_launchpad(elem) |
3755 | + # Names are truncated at 100 chars. |
3756 | + expected_name = "very " * 20 |
3757 | + self.assertEqual(expected_name, meeting.name) |
3758 | + self.assertEqual( |
3759 | + 1, |
3760 | + summit.meeting_set.filter( |
3761 | + name__exact=expected_name |
3762 | + ).count() |
3763 | + ) |
3764 | + |
3765 | + def test_update_meeting_accepts_existing_meeting(self): |
3766 | + summit = factory.make_one(Summit) |
3767 | + name = "meeting-name" |
3768 | + title = "other-title" |
3769 | + elem = LaunchpadExportNode(name=name, id="42") |
3770 | + summit.meeting_set.create(name=name, title=title) |
3771 | + meeting = summit.update_meeting_from_launchpad(elem) |
3772 | + self.assertEqual(name, meeting.name) |
3773 | + self.assertEqual( |
3774 | + 1, |
3775 | + summit.meeting_set.filter( |
3776 | + name__exact=name, |
3777 | + title__exact=title |
3778 | + ).count() |
3779 | + ) |
3780 | + |
3781 | + def test_update_from_launchpad_response_empty(self): |
3782 | + summit = factory.make_one(Summit) |
3783 | + elem = self.get_basic_launchpad_response() |
3784 | + meetings = summit.update_from_launchpad_response(elem) |
3785 | + self.assertEqual(set(), meetings) |
3786 | + self.assertEqual(0, Meeting.objects.all().count()) |
3787 | + self.assertEqual(0, Attendee.objects.all().count()) |
3788 | + |
3789 | + def test_update_from_launchpad_response_handles_no_name(self): |
3790 | + summit = factory.make_one(Summit) |
3791 | + elem = self.get_basic_launchpad_response() |
3792 | + meeting_node = LaunchpadExportNode(name=None, id="42") |
3793 | + elem.find("unscheduled").add_child("meeting", meeting_node) |
3794 | + meetings = summit.update_from_launchpad_response(elem) |
3795 | + self.assertEqual(set(), meetings) |
3796 | + |
3797 | + def test_launchpad_sprint_import_urls_uses_default(self): |
3798 | + summit = factory.make_one(Summit, name='test-sprint') |
3799 | + self.assertEqual( |
3800 | + ['https://launchpad.net/sprints/test-sprint/+temp-meeting-export'], |
3801 | + summit.launchpad_sprint_import_urls() |
3802 | + ) |
3803 | + |
3804 | + def test_launchpad_sprint_import_url_uses_one_summit_sprint(self): |
3805 | + import_url = 'http://example.com/test' |
3806 | + summit = factory.make_one(Summit) |
3807 | + factory.make_one(SummitSprint, summit=summit, import_url=import_url) |
3808 | + self.assertEqual([import_url], summit.launchpad_sprint_import_urls()) |
3809 | + |
3810 | + def test_launchpad_sprint_import_url_uses_two_summit_sprint(self): |
3811 | + import_url1 = 'http://example.com/test1' |
3812 | + import_url2 = 'http://example.com/test2' |
3813 | + summit = factory.make_one(Summit) |
3814 | + factory.make_one(SummitSprint, summit=summit, import_url=import_url1) |
3815 | + factory.make_one(SummitSprint, summit=summit, import_url=import_url2) |
3816 | + self.assertEqual( |
3817 | + sorted( |
3818 | + [import_url1, import_url2] |
3819 | + ), |
3820 | + sorted( |
3821 | + summit.launchpad_sprint_import_urls() |
3822 | + ) |
3823 | + ) |
3824 | + |
3825 | + def test_update_from_launchpad_gets_info_for_all_import_urls(self): |
3826 | + import_url1 = 'http://example.com/test1' |
3827 | + import_url2 = 'http://example.com/test2' |
3828 | + summit = factory.make_one(Summit) |
3829 | + factory.make_one(SummitSprint, summit=summit, import_url=import_url1) |
3830 | + factory.make_one(SummitSprint, summit=summit, import_url=import_url2) |
3831 | + called_urls = [] |
3832 | + |
3833 | + def get_sprint_info(url): |
3834 | + called_urls.append(url) |
3835 | + return self.get_basic_launchpad_response() |
3836 | + |
3837 | + summit._get_sprint_info_from_launchpad = get_sprint_info |
3838 | + summit.update_from_launchpad() |
3839 | + self.assertEqual( |
3840 | + sorted( |
3841 | + [import_url1, import_url2] |
3842 | + ), |
3843 | + sorted(called_urls) |
3844 | + ) |
3845 | + |
3846 | + def test_update_from_launchpad_does_the_update(self): |
3847 | + summit = factory.make_one(Summit) |
3848 | + |
3849 | + def get_sprint_info(url): |
3850 | + elem = self.get_basic_launchpad_response() |
3851 | + meeting_node = LaunchpadExportNode(name="foo", id="42") |
3852 | + elem.find("unscheduled").add_child("meeting", meeting_node) |
3853 | + return elem |
3854 | + |
3855 | + summit._get_sprint_info_from_launchpad = get_sprint_info |
3856 | + summit.update_from_launchpad() |
3857 | + self.assertEqual(1, summit.meeting_set.all().count()) |
3858 | + |
3859 | + def test_update_from_launchpad_does_renames(self): |
3860 | + summit = factory.make_one(Summit) |
3861 | + meeting = summit.meeting_set.create( |
3862 | + name="name", |
3863 | + launchpad_blueprint_id="42" |
3864 | + ) |
3865 | + |
3866 | + def get_sprint_info(url): |
3867 | + elem = self.get_basic_launchpad_response() |
3868 | + meeting_node = LaunchpadExportNode(name="other", id="42") |
3869 | + elem.find("unscheduled").add_child("meeting", meeting_node) |
3870 | + return elem |
3871 | + |
3872 | + summit._get_sprint_info_from_launchpad = get_sprint_info |
3873 | + summit.update_from_launchpad() |
3874 | + # Since both had blueprint id 42, it should just update |
3875 | + # the existing meeting |
3876 | + self.assertEqual( |
3877 | + 0, |
3878 | + summit.meeting_set.filter( |
3879 | + name__exact="name" |
3880 | + ).count() |
3881 | + ) |
3882 | + self.assertEqual( |
3883 | + 1, |
3884 | + summit.meeting_set.filter( |
3885 | + name__exact="other" |
3886 | + ).count() |
3887 | + ) |
3888 | + |
3889 | + def test_update_from_launchpad_deletes_missing_unscheduled_meetings(self): |
3890 | + summit = factory.make_one(Summit) |
3891 | + meeting = summit.meeting_set.create( |
3892 | + spec_url='test_url', |
3893 | + name="name", |
3894 | + launchpad_blueprint_id="42" |
3895 | + ) |
3896 | + |
3897 | + def get_sprint_info(url): |
3898 | + elem = self.get_basic_launchpad_response() |
3899 | + meeting_node = LaunchpadExportNode(name="other") |
3900 | + elem.find("unscheduled").add_child("meeting", meeting_node) |
3901 | + return elem |
3902 | + |
3903 | + summit._get_sprint_info_from_launchpad = get_sprint_info |
3904 | + summit.update_from_launchpad() |
3905 | + self.assertEqual( |
3906 | + 1, |
3907 | + summit.meeting_set.filter( |
3908 | + name__exact="name" |
3909 | + ).count() |
3910 | + ) |
3911 | + self.assertEqual( |
3912 | + 0, |
3913 | + summit.meeting_set.filter( |
3914 | + name__exact="name" |
3915 | + ).exclude( |
3916 | + approved='REMOVED' |
3917 | + ).count() |
3918 | + ) |
3919 | + |
3920 | + def test_update_from_launchpad_deletes_missing_scheduled_meetings(self): |
3921 | + summit = factory.make_one(Summit) |
3922 | + meeting = summit.meeting_set.create( |
3923 | + spec_url='test_url', |
3924 | + name="name", |
3925 | + launchpad_blueprint_id="42" |
3926 | + ) |
3927 | + room = factory.make_one(Room, summit=summit) |
3928 | + slot = factory.make_one(Slot) |
3929 | + agenda = meeting.agenda_set.create(room=room, slot=slot, auto=True) |
3930 | + |
3931 | + def get_sprint_info(url): |
3932 | + elem = self.get_basic_launchpad_response() |
3933 | + meeting_node = LaunchpadExportNode(name="other") |
3934 | + elem.find("unscheduled").add_child("meeting", meeting_node) |
3935 | + return elem |
3936 | + summit._get_sprint_info_from_launchpad = get_sprint_info |
3937 | + summit.update_from_launchpad() |
3938 | + self.assertEqual( |
3939 | + 1, |
3940 | + summit.meeting_set.filter( |
3941 | + name__exact="name" |
3942 | + ).count() |
3943 | + ) |
3944 | + self.assertEqual( |
3945 | + 0, |
3946 | + summit.meeting_set.filter( |
3947 | + name__exact="name" |
3948 | + ).exclude( |
3949 | + approved='REMOVED' |
3950 | + ).count() |
3951 | + ) |
3952 | + |
3953 | + def test_update_from_launchpad_doesnt_delete_meetings_with_spec_url(self): |
3954 | + summit = factory.make_one(Summit) |
3955 | + meeting = summit.meeting_set.create( |
3956 | + spec_url='http://example.com/foo', |
3957 | + name="name", |
3958 | + launchpad_blueprint_id="42" |
3959 | + ) |
3960 | + |
3961 | + def get_sprint_info(url): |
3962 | + elem = self.get_basic_launchpad_response() |
3963 | + meeting_node = LaunchpadExportNode(name="other", id="43") |
3964 | + elem.find("unscheduled").add_child("meeting", meeting_node) |
3965 | + return elem |
3966 | + summit._get_sprint_info_from_launchpad = get_sprint_info |
3967 | + summit.update_from_launchpad() |
3968 | + self.assertEqual( |
3969 | + 1, |
3970 | + summit.meeting_set.filter( |
3971 | + name__exact="name" |
3972 | + ).count() |
3973 | + ) |
3974 | + |
3975 | + def test_update_from_launchpad_wont_delete_meetings_without_spec_url(self): |
3976 | + summit = factory.make_one(Summit) |
3977 | + meeting = summit.meeting_set.create( |
3978 | + spec_url='', |
3979 | + name="name", |
3980 | + launchpad_blueprint_id="42" |
3981 | + ) |
3982 | + |
3983 | + def get_sprint_info(url): |
3984 | + elem = self.get_basic_launchpad_response() |
3985 | + meeting_node = LaunchpadExportNode(name="other", id="43") |
3986 | + elem.find("unscheduled").add_child("meeting", meeting_node) |
3987 | + return elem |
3988 | + |
3989 | + summit._get_sprint_info_from_launchpad = get_sprint_info |
3990 | + summit.update_from_launchpad() |
3991 | + self.assertEqual( |
3992 | + 1, |
3993 | + summit.meeting_set.filter( |
3994 | + name__exact="name" |
3995 | + ).count() |
3996 | + ) |
3997 | + |
3998 | + def test_update_from_launchpad_updates_last_update(self): |
3999 | + old_now = datetime.datetime.utcnow() - datetime.timedelta(days=1) |
4000 | + summit = factory.make_one(Summit, last_update=old_now) |
4001 | + |
4002 | + def get_sprint_info(url): |
4003 | + return self.get_basic_launchpad_response() |
4004 | + |
4005 | + summit._get_sprint_info_from_launchpad = get_sprint_info |
4006 | + summit.update_from_launchpad() |
4007 | + self.assertTrue(old_now < summit.last_update) |
4008 | + |
4009 | + def test_reschedule_does_nothing_on_empty_schedule(self): |
4010 | + summit = factory.make_one(Summit) |
4011 | + summit.reschedule() |
4012 | + |
4013 | + def test_reschedule_removes_missing_participants(self): |
4014 | + summit = factory.make_one(Summit) |
4015 | + meeting1 = factory.make_one( |
4016 | + Meeting, |
4017 | + summit=summit, |
4018 | + requires_dial_in=False, |
4019 | + private=False |
4020 | + ) |
4021 | + meeting2 = factory.make_one( |
4022 | + Meeting, |
4023 | + summit=summit, |
4024 | + requires_dial_in=False, |
4025 | + private=False |
4026 | + ) |
4027 | + room1 = factory.make_one(Room, summit=summit) |
4028 | + room2 = factory.make_one(Room, summit=summit) |
4029 | + slot = self.make_one_future_slot(summit=summit) |
4030 | + attendee = factory.make_one( |
4031 | + Attendee, |
4032 | + summit=summit, |
4033 | + start_utc=slot.start_utc, |
4034 | + end_utc=slot.end_utc |
4035 | + ) |
4036 | + meeting1.participant_set.create( |
4037 | + attendee=attendee, |
4038 | + participation='REQUIRED' |
4039 | + ) |
4040 | + meeting2.participant_set.create( |
4041 | + attendee=attendee, |
4042 | + participation='REQUIRED' |
4043 | + ) |
4044 | + factory.make_one( |
4045 | + Agenda, |
4046 | + meeting=meeting1, |
4047 | + room=room1, |
4048 | + slot=slot, |
4049 | + auto=True |
4050 | + ) |
4051 | + factory.make_one( |
4052 | + Agenda, |
4053 | + meeting=meeting2, |
4054 | + room=room2, |
4055 | + slot=slot, |
4056 | + auto=True |
4057 | + ) |
4058 | + summit.reschedule() |
4059 | + self.assertEqual(1, slot.agenda_set.all().count()) |
4060 | + |
4061 | + def test_reschedule_removes_unavailable_participants(self): |
4062 | + summit = factory.make_one(Summit) |
4063 | + meeting = factory.make_one( |
4064 | + Meeting, |
4065 | + summit=summit, |
4066 | + requires_dial_in=False, |
4067 | + private=False |
4068 | + ) |
4069 | + room = factory.make_one(Room, summit=summit) |
4070 | + slot = self.make_one_future_slot(summit=summit) |
4071 | + attendee = factory.make_one( |
4072 | + Attendee, |
4073 | + summit=summit, |
4074 | + start_utc=slot.end_utc, |
4075 | + end_utc=slot.end_utc+datetime.timedelta(hours=1) |
4076 | + ) |
4077 | + meeting.participant_set.create( |
4078 | + attendee=attendee, |
4079 | + participation='REQUIRED' |
4080 | + ) |
4081 | + factory.make_one( |
4082 | + Agenda, |
4083 | + meeting=meeting, |
4084 | + room=room, |
4085 | + slot=slot, |
4086 | + auto=True |
4087 | + ) |
4088 | + summit.reschedule() |
4089 | + self.assertEqual(0, slot.agenda_set.all().count()) |
4090 | + |
4091 | + def test_reschedule_removes_insufficient_slots(self): |
4092 | + summit = factory.make_one(Summit) |
4093 | + meeting = factory.make_one( |
4094 | + Meeting, |
4095 | + summit=summit, |
4096 | + slots=2, |
4097 | + requires_dial_in=False, |
4098 | + private=False |
4099 | + ) |
4100 | + room = factory.make_one(Room, summit=summit) |
4101 | + slot = self.make_one_future_slot(summit=summit) |
4102 | + factory.make_one( |
4103 | + Agenda, |
4104 | + meeting=meeting, |
4105 | + room=room, |
4106 | + slot=slot, |
4107 | + auto=True |
4108 | + ) |
4109 | + summit.reschedule() |
4110 | + self.assertEqual(0, slot.agenda_set.all().count()) |
4111 | + |
4112 | + def test_reschedule_leaves_old_slots(self): |
4113 | + summit = factory.make_one(Summit) |
4114 | + meeting = factory.make_one( |
4115 | + Meeting, |
4116 | + summit=summit, |
4117 | + slots=2, |
4118 | + requires_dial_in=False, |
4119 | + private=False |
4120 | + ) |
4121 | + room = factory.make_one(Room, summit=summit) |
4122 | + now = datetime.datetime.utcnow() |
4123 | + one_hour = datetime.timedelta(hours=1) |
4124 | + slot = factory.make_one( |
4125 | + Slot, |
4126 | + summit=summit, |
4127 | + start=now-one_hour, |
4128 | + end=now, |
4129 | + type='open' |
4130 | + ) |
4131 | + factory.make_one( |
4132 | + Agenda, |
4133 | + meeting=meeting, |
4134 | + room=room, |
4135 | + slot=slot, |
4136 | + auto=True |
4137 | + ) |
4138 | + summit.reschedule() |
4139 | + self.assertEqual(1, slot.agenda_set.all().count()) |
4140 | + |
4141 | + def test_reschedule_leaves_manually_scheduled(self): |
4142 | + summit = factory.make_one(Summit) |
4143 | + meeting = factory.make_one( |
4144 | + Meeting, |
4145 | + summit=summit, |
4146 | + slots=2, |
4147 | + requires_dial_in=False, |
4148 | + private=False |
4149 | + ) |
4150 | + room = factory.make_one(Room, summit=summit) |
4151 | + slot = self.make_one_future_slot(summit=summit) |
4152 | + factory.make_one( |
4153 | + Agenda, |
4154 | + meeting=meeting, |
4155 | + room=room, |
4156 | + slot=slot, |
4157 | + auto=False |
4158 | + ) |
4159 | + summit.reschedule() |
4160 | + self.assertEqual(1, slot.agenda_set.all().count()) |
4161 | + |
4162 | + def test_update_from_launchpad_adds_attendees(self): |
4163 | + def mock_set_openid(user, force=False): |
4164 | + self.assertEquals(user.username, 'testuser') |
4165 | + mock_set_openid.called = True |
4166 | + return True |
4167 | + mock_set_openid.called = False |
4168 | + launchpad.set_user_openid = mock_set_openid |
4169 | + |
4170 | + summit = factory.make_one(Summit) |
4171 | + attendee_node = LaunchpadExportNode(name='testuser') |
4172 | + summit.update_attendee_from_launchpad(attendee_node) |
4173 | + |
4174 | + self.assertEqual( |
4175 | + 1, |
4176 | + summit.attendee_set.filter( |
4177 | + user__username__exact="testuser" |
4178 | + ).count() |
4179 | + ) |
4180 | + self.assertTrue(mock_set_openid.called) |
4181 | |
4182 | === removed file 'summit/schedule/tests/tests.py' |
4183 | --- summit/schedule/tests/tests.py 2013-02-27 03:18:38 +0000 |
4184 | +++ summit/schedule/tests/tests.py 1970-01-01 00:00:00 +0000 |
4185 | @@ -1,3417 +0,0 @@ |
4186 | -# The Summit Scheduler web application |
4187 | -# Copyright (C) 2008 - 2013 Ubuntu Community, Canonical Ltd |
4188 | -# |
4189 | -# This program is free software: you can redistribute it and/or modify |
4190 | -# it under the terms of the GNU Affero General Public License as |
4191 | -# published by the Free Software Foundation, either version 3 of the |
4192 | -# License, or (at your option) any later version. |
4193 | -# |
4194 | -# This program is distributed in the hope that it will be useful, |
4195 | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
4196 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4197 | -# GNU Affero General Public License for more details. |
4198 | -# |
4199 | -# You should have received a copy of the GNU Affero General Public License |
4200 | -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
4201 | - |
4202 | - |
4203 | -import datetime |
4204 | -import pytz |
4205 | -import unittest |
4206 | -from django.core.management.base import CommandError |
4207 | -from django import test as djangotest |
4208 | -from django.core.handlers.base import BaseHandler |
4209 | -from django.core.handlers.wsgi import WSGIRequest |
4210 | -from django.core.urlresolvers import reverse |
4211 | -from django.conf import settings |
4212 | -from django.contrib.auth.models import User, Permission |
4213 | -from django.contrib.contenttypes.models import ContentType |
4214 | -from django.db import models |
4215 | -from django.core.cache import cache |
4216 | - |
4217 | -from summit.schedule.management.commands import reschedule |
4218 | - |
4219 | -from model_mommy import mommy as factory |
4220 | -from summit.schedule.fields import NameField |
4221 | - |
4222 | -from summit.schedule.models import ( |
4223 | - Summit, |
4224 | - Slot, |
4225 | - Attendee, |
4226 | - Meeting, |
4227 | - Track, |
4228 | - Room, |
4229 | - Agenda, |
4230 | - Participant, |
4231 | - SummitSprint, |
4232 | - Lead, |
4233 | -) |
4234 | - |
4235 | -from summit.schedule.render import Schedule |
4236 | -from summit.common import launchpad |
4237 | - |
4238 | -# Monkey-patch our NameField into the types of fields that the factory |
4239 | -# understands. This is simpler than trying to subclass the Mommy |
4240 | -# class directly. |
4241 | -factory.default_mapping[NameField] = str |
4242 | - |
4243 | -site_root = getattr(settings, 'SITE_ROOT', 'http://summit.ubuntu.com') |
4244 | -theme_media = getattr(settings, 'THEME_MEDIA', 'ubuntu_website.MEDIA_ROOT') |
4245 | - |
4246 | - |
4247 | -class RequestFactory(djangotest.Client): |
4248 | - """ |
4249 | - Class that lets you create mock Request objects for use in testing. |
4250 | - |
4251 | - Usage: |
4252 | - |
4253 | - rf = RequestFactory() |
4254 | - get_request = rf.get('/hello/') |
4255 | - post_request = rf.post('/submit/', {'foo': 'bar'}) |
4256 | - |
4257 | - This class re-uses the django.test.client.Client interface, docs here: |
4258 | - http://www.djangoproject.com/documentation/testing/#the-test-client |
4259 | - |
4260 | - Once you have a request object you can pass it to any view function, |
4261 | - just as if that view had been hooked up using a URLconf. |
4262 | - |
4263 | - """ |
4264 | - def request(self, **request): |
4265 | - """ |
4266 | - Similar to parent class, but returns the request object as soon as it |
4267 | - has created it. |
4268 | - """ |
4269 | - environ = { |
4270 | - 'HTTP_COOKIE': self.cookies, |
4271 | - 'PATH_INFO': '/', |
4272 | - 'QUERY_STRING': '', |
4273 | - 'REQUEST_METHOD': 'GET', |
4274 | - 'SCRIPT_NAME': '', |
4275 | - 'SERVER_NAME': 'testserver', |
4276 | - 'SERVER_PORT': 80, |
4277 | - 'SERVER_PROTOCOL': 'HTTP/1.1', |
4278 | - 'wsgi.input': '', |
4279 | - } |
4280 | - environ.update(self.defaults) |
4281 | - environ.update(request) |
4282 | - request = WSGIRequest(environ) |
4283 | - handler = BaseHandler() |
4284 | - handler.load_middleware() |
4285 | - for middleware_method in handler._request_middleware: |
4286 | - if middleware_method(request): |
4287 | - raise Exception( |
4288 | - "Couldn't create request mock object - " |
4289 | - "request middleware %s returned a response" |
4290 | - % middleware_method |
4291 | - ) |
4292 | - return request |
4293 | - |
4294 | - |
4295 | -class RescheduleCommandTestCase(unittest.TestCase): |
4296 | - """Tests for the 'reschedule' management command.""" |
4297 | - |
4298 | - def test_passing_nonexistant_summit_raises_error(self): |
4299 | - cmd = reschedule.Command() |
4300 | - self.assertRaises(CommandError, cmd.handle, summit='uds-xxx') |
4301 | - |
4302 | - |
4303 | -class MeetingModelTestCase(djangotest.TestCase): |
4304 | - """Tests for the Meeting model.""" |
4305 | - |
4306 | - def test_meetings_can_not_be_scheduled_in_closed_slots(self): |
4307 | - now = datetime.datetime.utcnow() |
4308 | - one_hour = datetime.timedelta(0, 3600) |
4309 | - slot = factory.make_one( |
4310 | - Slot, |
4311 | - start_utc=now, |
4312 | - end_utc=now+one_hour, |
4313 | - type='closed') |
4314 | - |
4315 | - agenda = factory.make_one(Agenda, slot=slot) |
4316 | - meeting = factory.make_one( |
4317 | - Meeting, |
4318 | - requires_dial_in=False, |
4319 | - private=False |
4320 | - ) |
4321 | - |
4322 | - # XXX check_schedule should only be checking the schedule, not |
4323 | - # checking and modifying the schedule. |
4324 | - # XXX check_schedule's parameters should be an just an agenda object, |
4325 | - # not the agenda object's attributes. |
4326 | - self.assertRaises( |
4327 | - Meeting.SchedulingError, |
4328 | - meeting.check_schedule, agenda.slot, agenda.room) |
4329 | - |
4330 | - def test_participants_are_in_another_meeting(self): |
4331 | - now = datetime.datetime.utcnow() |
4332 | - one_hour = datetime.timedelta(0, 3600) |
4333 | - slot = factory.make_one( |
4334 | - Slot, |
4335 | - start_utc=now, |
4336 | - end_utc=now+one_hour) |
4337 | - room1 = factory.make_one(Room) |
4338 | - room2 = factory.make_one(Room) |
4339 | - |
4340 | - meeting1 = factory.make_one( |
4341 | - Meeting, |
4342 | - summit=slot.summit, |
4343 | - requires_dial_in=False, |
4344 | - private=False |
4345 | - ) |
4346 | - meeting2 = factory.make_one( |
4347 | - Meeting, |
4348 | - summit=slot.summit, |
4349 | - requires_dial_in=False, |
4350 | - private=False |
4351 | - ) |
4352 | - |
4353 | - attendee = factory.make_one(Attendee) |
4354 | - factory.make_one( |
4355 | - Participant, |
4356 | - meeting=meeting1, |
4357 | - attendee=attendee, |
4358 | - participation='REQUIRED' |
4359 | - ) |
4360 | - factory.make_one( |
4361 | - Participant, |
4362 | - meeting=meeting2, |
4363 | - attendee=attendee, |
4364 | - participation='REQUIRED' |
4365 | - ) |
4366 | - |
4367 | - factory.make_one(Agenda, meeting=meeting1, slot=slot, room=room1) |
4368 | - agenda = factory.make_one( |
4369 | - Agenda, |
4370 | - meeting=meeting2, |
4371 | - slot=slot, |
4372 | - room=room2 |
4373 | - ) |
4374 | - |
4375 | - missing = meeting2.check_schedule(agenda.slot, agenda.room) |
4376 | - self.assertEqual([attendee.name], [a.name for a in missing]) |
4377 | - |
4378 | - def make_open_slot(self): |
4379 | - now = datetime.datetime.utcnow() |
4380 | - one_hour = datetime.timedelta(0, 3600) |
4381 | - slot = factory.make_one( |
4382 | - Slot, |
4383 | - start_utc=now+one_hour, |
4384 | - end_utc=now+one_hour+one_hour, |
4385 | - type='open') |
4386 | - return slot |
4387 | - |
4388 | - def test_check_schedule_errors_on_no_dial_in(self): |
4389 | - slot = self.make_open_slot() |
4390 | - room = factory.make_one( |
4391 | - Room, |
4392 | - has_dial_in=False, |
4393 | - summit=slot.summit, |
4394 | - name="testroom" |
4395 | - ) |
4396 | - meeting = factory.make_one( |
4397 | - Meeting, |
4398 | - requires_dial_in=True, |
4399 | - summit=slot.summit, |
4400 | - name="testmeeting", |
4401 | - private=False |
4402 | - ) |
4403 | - try: |
4404 | - meeting.check_schedule(slot, room) |
4405 | - except meeting.SchedulingError, e: |
4406 | - self.assertEqual("Room has no dial-in capability", e.message) |
4407 | - return |
4408 | - self.fail("SchedulingError not thrown") |
4409 | - |
4410 | - def make_two_adjacent_slots(self): |
4411 | - summit = factory.make_one(Summit, timezone='utc') |
4412 | - now = datetime.datetime(2011, 9, 8, 12, 00) |
4413 | - one_hour = datetime.timedelta(0, 3600) |
4414 | - slot1 = factory.make_one( |
4415 | - Slot, |
4416 | - start_utc=now+one_hour, |
4417 | - end_utc=now+one_hour+one_hour, |
4418 | - type='open', summit=summit |
4419 | - ) |
4420 | - slot2 = factory.make_one( |
4421 | - Slot, |
4422 | - start_utc=now+one_hour+one_hour, |
4423 | - end_utc=now+one_hour+one_hour+one_hour, |
4424 | - type='open', summit=summit |
4425 | - ) |
4426 | - return slot1, slot2 |
4427 | - |
4428 | - def test_check_schedule_errors_on_same_track_in_previous_slot(self): |
4429 | - slot1, slot2 = self.make_two_adjacent_slots() |
4430 | - room = factory.make_one( |
4431 | - Room, |
4432 | - summit=slot1.summit, |
4433 | - name="testroom" |
4434 | - ) |
4435 | - track = factory.make_one( |
4436 | - Track, |
4437 | - summit=slot1.summit, |
4438 | - title="testtrack", |
4439 | - allow_adjacent_sessions=False |
4440 | - ) |
4441 | - track2 = factory.make_one( |
4442 | - Track, |
4443 | - summit=slot1.summit, |
4444 | - title="adjacenttrack", |
4445 | - allow_adjacent_sessions=True |
4446 | - ) |
4447 | - meeting1 = factory.make_one( |
4448 | - Meeting, |
4449 | - requires_dial_in=False, |
4450 | - summit=slot1.summit, |
4451 | - name="testmeeting1", |
4452 | - type='blueprint', |
4453 | - private=False |
4454 | - ) |
4455 | - meeting2 = factory.make_one( |
4456 | - Meeting, |
4457 | - requires_dial_in=False, |
4458 | - summit=slot1.summit, |
4459 | - name="testmeeting2", |
4460 | - type='blueprint', |
4461 | - private=False |
4462 | - ) |
4463 | - meeting1.tracks = [track, track2] |
4464 | - meeting2.tracks = [track] |
4465 | - meeting1.agenda_set.create(room=room, slot=slot1) |
4466 | - try: |
4467 | - meeting2.check_schedule(slot2, room) |
4468 | - except meeting2.SchedulingError, e: |
4469 | - self.assertEqual("Same track in the previous slot", e.message) |
4470 | - return |
4471 | - self.fail("SchedulingError not thrown") |
4472 | - |
4473 | - def test_check_schedule_errors_on_same_track_in_next_slot(self): |
4474 | - slot1, slot2 = self.make_two_adjacent_slots() |
4475 | - room = factory.make_one(Room, summit=slot1.summit, name="testroom") |
4476 | - track = factory.make_one( |
4477 | - Track, |
4478 | - summit=slot1.summit, |
4479 | - title="testtrack", |
4480 | - allow_adjacent_sessions=False |
4481 | - ) |
4482 | - meeting1 = factory.make_one( |
4483 | - Meeting, |
4484 | - requires_dial_in=False, |
4485 | - summit=slot1.summit, |
4486 | - name="testmeeting1", |
4487 | - type='blueprint', |
4488 | - private=False |
4489 | - ) |
4490 | - meeting2 = factory.make_one( |
4491 | - Meeting, |
4492 | - requires_dial_in=False, |
4493 | - summit=slot1.summit, |
4494 | - name="testmeeting2", |
4495 | - type='blueprint', |
4496 | - private=False |
4497 | - ) |
4498 | - meeting1.tracks = [track] |
4499 | - meeting2.tracks = [track] |
4500 | - meeting1.agenda_set.create(room=room, slot=slot2) |
4501 | - try: |
4502 | - meeting2.check_schedule(slot1, room) |
4503 | - except meeting2.SchedulingError, e: |
4504 | - self.assertEqual("Same track in the next slot", e.message) |
4505 | - return |
4506 | - self.fail("SchedulingError not thrown") |
4507 | - |
4508 | - def test_check_schedule_no_error_on_different_track(self): |
4509 | - slot1, slot2 = self.make_two_adjacent_slots() |
4510 | - room = factory.make_one(Room, summit=slot1.summit, name="testroom") |
4511 | - track = factory.make_one( |
4512 | - Track, |
4513 | - summit=slot1.summit, |
4514 | - title="testtrack", |
4515 | - allow_adjacent_sessions=False |
4516 | - ) |
4517 | - other_track = factory.make_one( |
4518 | - Track, |
4519 | - summit=slot1.summit, |
4520 | - title="othertesttrack", |
4521 | - allow_adjacent_sessions=False |
4522 | - ) |
4523 | - meeting1 = factory.make_one( |
4524 | - Meeting, |
4525 | - requires_dial_in=False, |
4526 | - summit=slot1.summit, |
4527 | - name="testmeeting1", |
4528 | - type='blueprint', |
4529 | - private=False |
4530 | - ) |
4531 | - meeting2 = factory.make_one( |
4532 | - Meeting, |
4533 | - requires_dial_in=False, |
4534 | - summit=slot1.summit, |
4535 | - name="testmeeting2", |
4536 | - type='blueprint', |
4537 | - private=False |
4538 | - ) |
4539 | - meeting1.tracks = [track] |
4540 | - meeting2.tracks = [other_track] |
4541 | - meeting1.agenda_set.create(room=room, slot=slot2) |
4542 | - meeting2.check_schedule(slot1, room) |
4543 | - |
4544 | - def test_check_schedule_no_error_on_same_track_for_plenaries(self): |
4545 | - slot1, slot2 = self.make_two_adjacent_slots() |
4546 | - room = factory.make_one(Room, summit=slot1.summit, name="testroom") |
4547 | - track = factory.make_one( |
4548 | - Track, |
4549 | - summit=slot1.summit, |
4550 | - title="testtrack", |
4551 | - allow_adjacent_sessions=False |
4552 | - ) |
4553 | - meeting1 = factory.make_one( |
4554 | - Meeting, |
4555 | - requires_dial_in=False, |
4556 | - summit=slot1.summit, |
4557 | - name="testmeeting1", |
4558 | - type='blueprint', |
4559 | - private=False |
4560 | - ) |
4561 | - meeting2 = factory.make_one( |
4562 | - Meeting, |
4563 | - requires_dial_in=False, |
4564 | - summit=slot1.summit, |
4565 | - name="testmeeting2", |
4566 | - type='plenary', |
4567 | - private=False |
4568 | - ) |
4569 | - meeting1.tracks = [track] |
4570 | - meeting2.tracks = [track] |
4571 | - meeting1.agenda_set.create(room=room, slot=slot2) |
4572 | - meeting2.check_schedule(slot1, room) |
4573 | - |
4574 | - def test_check_schedule_no_error_on_same_track_for_ajdacent_sessions_allowed(self): |
4575 | - slot1, slot2 = self.make_two_adjacent_slots() |
4576 | - room = factory.make_one(Room, summit=slot1.summit, name="testroom") |
4577 | - track = factory.make_one( |
4578 | - Track, |
4579 | - summit=slot1.summit, |
4580 | - title="adjacenttrack", |
4581 | - allow_adjacent_sessions=True |
4582 | - ) |
4583 | - meeting1 = factory.make_one( |
4584 | - Meeting, |
4585 | - requires_dial_in=False, |
4586 | - summit=slot1.summit, |
4587 | - name="testmeeting1", |
4588 | - type='blueprint', |
4589 | - private=False |
4590 | - ) |
4591 | - meeting2 = factory.make_one( |
4592 | - Meeting, |
4593 | - requires_dial_in=False, |
4594 | - summit=slot1.summit, |
4595 | - name="testmeeting2", |
4596 | - type='blueprint', |
4597 | - private=False |
4598 | - ) |
4599 | - meeting1.tracks = [track] |
4600 | - meeting2.tracks = [track] |
4601 | - meeting1.agenda_set.create(room=room, slot=slot2) |
4602 | - meeting2.check_schedule(slot1, room) |
4603 | - |
4604 | - def test_try_schedule_into_refuses_room_without_dial_in(self): |
4605 | - slot = self.make_open_slot() |
4606 | - room = factory.make_one( |
4607 | - Room, |
4608 | - has_dial_in=False, |
4609 | - summit=slot.summit, |
4610 | - name="testroom" |
4611 | - ) |
4612 | - meeting = factory.make_one( |
4613 | - Meeting, |
4614 | - requires_dial_in=True, |
4615 | - summit=slot.summit, |
4616 | - name="testmeeting", |
4617 | - private=False |
4618 | - ) |
4619 | - |
4620 | - self.assertEqual(False, meeting.try_schedule_into([room])) |
4621 | - self.assertEqual(0, meeting.agenda_set.all().count()) |
4622 | - |
4623 | - def test_try_schedule_into_allows_room_with_dial_in(self): |
4624 | - slot = self.make_open_slot() |
4625 | - room = factory.make_one( |
4626 | - Room, |
4627 | - has_dial_in=True, |
4628 | - summit=slot.summit, |
4629 | - name="testroom" |
4630 | - ) |
4631 | - meeting = factory.make_one( |
4632 | - Meeting, |
4633 | - requires_dial_in=True, |
4634 | - summit=slot.summit, |
4635 | - name="testmeeting", |
4636 | - private=False |
4637 | - ) |
4638 | - |
4639 | - self.assertEqual(True, meeting.try_schedule_into([room])) |
4640 | - self.assertEqual(1, meeting.agenda_set.all().count()) |
4641 | - |
4642 | - def test_link_to_pad_with_pad_url_set(self): |
4643 | - url = 'http://pad.com/url' |
4644 | - meeting = factory.make_one(Meeting, pad_url=url, private=False) |
4645 | - self.assertEqual(url, meeting.link_to_pad) |
4646 | - |
4647 | - def get_pad_host(self): |
4648 | - summit_name = 'testsummit' |
4649 | - summit = factory.make_one(Summit, name=summit_name) |
4650 | - return getattr(summit, 'etherpad', 'http://pad.ubuntu.com/') |
4651 | - |
4652 | - def test_link_to_pad_with_pad_url_unset(self): |
4653 | - summit_name = 'testsummit' |
4654 | - summit = factory.make_one(Summit, name=summit_name) |
4655 | - name = 'testmeeting' |
4656 | - meeting = factory.make_one( |
4657 | - Meeting, |
4658 | - pad_url=None, |
4659 | - name=name, |
4660 | - summit=summit, |
4661 | - private=False |
4662 | - ) |
4663 | - pad_host = self.get_pad_host() |
4664 | - url = pad_host + summit_name + '-' + name |
4665 | - self.assertEqual(url, meeting.link_to_pad) |
4666 | - |
4667 | - def test_link_to_pad_with_plus_in_meeting_name(self): |
4668 | - summit_name = 'testsummit' |
4669 | - summit = factory.make_one(Summit, name=summit_name) |
4670 | - name = 'test+meeting' |
4671 | - meeting = factory.make_one( |
4672 | - Meeting, |
4673 | - pad_url=None, |
4674 | - name=name, |
4675 | - summit=summit, |
4676 | - private=False |
4677 | - ) |
4678 | - pad_host = self.get_pad_host() |
4679 | - url = pad_host + summit_name + '-' + name.replace("+", "-") |
4680 | - self.assertEqual(url, meeting.link_to_pad) |
4681 | - |
4682 | - def test_edit_link_to_pad_with_pad_url_set(self): |
4683 | - url = 'http://pad.com/url' |
4684 | - meeting = factory.make_one(Meeting, pad_url=url, private=False) |
4685 | - self.assertEqual(url, meeting.edit_link_to_pad) |
4686 | - |
4687 | - def test_edit_link_to_pad_with_pad_url_unset(self): |
4688 | - summit_name = 'testsummit' |
4689 | - summit = factory.make_one(Summit, name=summit_name) |
4690 | - name = 'testmeeting' |
4691 | - meeting = factory.make_one( |
4692 | - Meeting, |
4693 | - pad_url=None, |
4694 | - name=name, |
4695 | - summit=summit, |
4696 | - private=False |
4697 | - ) |
4698 | - pad_host = self.get_pad_host() |
4699 | - url = pad_host + "ep/pad/view/" + summit_name + '-' + name + "/latest" |
4700 | - self.assertEqual(url, meeting.edit_link_to_pad) |
4701 | - |
4702 | - def test_edit_link_to_pad_with_plus_in_meeting_name(self): |
4703 | - summit_name = 'testsummit' |
4704 | - summit = factory.make_one(Summit, name=summit_name) |
4705 | - name = 'test+meeting' |
4706 | - meeting = factory.make_one( |
4707 | - Meeting, |
4708 | - pad_url=None, |
4709 | - name=name, |
4710 | - summit=summit, |
4711 | - private=False |
4712 | - ) |
4713 | - pad_host = self.get_pad_host() |
4714 | - url = ( |
4715 | - pad_host |
4716 | - + "ep/pad/view/" |
4717 | - + summit_name |
4718 | - + '-' |
4719 | - + name.replace("+", "-") |
4720 | - + "/latest" |
4721 | - ) |
4722 | - self.assertEqual(url, meeting.edit_link_to_pad) |
4723 | - |
4724 | - def test_update_from_launchpad_sets_status(self): |
4725 | - summit = factory.make_one(Summit, timezone='utc', name='test-summit') |
4726 | - meeting = factory.make_one( |
4727 | - Meeting, |
4728 | - pad_url=None, |
4729 | - name='test-meeting', |
4730 | - summit=summit, |
4731 | - private=False |
4732 | - ) |
4733 | - status = "Discussion" |
4734 | - name = meeting.name |
4735 | - elem = LaunchpadExportNode(status=status, name=name) |
4736 | - meeting.update_from_launchpad(elem) |
4737 | - self.assertEqual(status, meeting.status) |
4738 | - |
4739 | - def test_update_from_launchpad_sets_priority(self): |
4740 | - summit = factory.make_one(Summit, timezone='utc', name='test-summit') |
4741 | - meeting = factory.make_one( |
4742 | - Meeting, |
4743 | - pad_url=None, |
4744 | - name='test-meeting', |
4745 | - summit=summit, |
4746 | - private=False |
4747 | - ) |
4748 | - priority = 70 |
4749 | - name = meeting.name |
4750 | - elem = LaunchpadExportNode(priority=priority, name=name) |
4751 | - meeting.update_from_launchpad(elem) |
4752 | - self.assertEqual(priority, meeting.priority) |
4753 | - |
4754 | - def test_update_from_launchpad_sets_wiki_url(self): |
4755 | - summit = factory.make_one(Summit, timezone='utc', name='test-summit') |
4756 | - meeting = factory.make_one( |
4757 | - Meeting, |
4758 | - pad_url=None, |
4759 | - name='test-meeting', |
4760 | - summit=summit, |
4761 | - private=False |
4762 | - ) |
4763 | - wiki_url = "http://example.com/somespec" |
4764 | - name = meeting.name |
4765 | - elem = LaunchpadExportNode(specurl=wiki_url, name=name) |
4766 | - meeting.update_from_launchpad(elem) |
4767 | - self.assertEqual(wiki_url, meeting.wiki_url) |
4768 | - |
4769 | - def get_person_node(self, username, required=False): |
4770 | - elem = LaunchpadExportNode() |
4771 | - required_map = {True: "True", False: "False"} |
4772 | - elem.add_child( |
4773 | - "person", |
4774 | - LaunchpadExportNode( |
4775 | - name=username, |
4776 | - required=required_map[required] |
4777 | - ) |
4778 | - ) |
4779 | - return elem |
4780 | - |
4781 | - def make_one_future_slot(self, summit=None): |
4782 | - if summit is None: |
4783 | - summit = factory.make_one(Summit) |
4784 | - now = datetime.datetime.utcnow() |
4785 | - one_hour = datetime.timedelta(hours=1) |
4786 | - return factory.make_one( |
4787 | - Slot, |
4788 | - summit=summit, |
4789 | - start=now+one_hour, |
4790 | - end=now+one_hour+one_hour, |
4791 | - type='open' |
4792 | - ) |
4793 | - |
4794 | - def make_summit_and_attendee(self): |
4795 | - username = "username" |
4796 | - user = factory.make_one(User, username=username) |
4797 | - summit = factory.make_one(Summit) |
4798 | - slot = self.make_one_future_slot(summit=summit) |
4799 | - attendee = summit.attendee_set.create( |
4800 | - user=user, |
4801 | - start_utc=slot.start_utc, |
4802 | - end_utc=slot.end_utc |
4803 | - ) |
4804 | - return summit, attendee |
4805 | - |
4806 | - def test_update_from_launchpad_adds_participant(self): |
4807 | - summit, attendee = self.make_summit_and_attendee() |
4808 | - meeting = factory.make_one( |
4809 | - Meeting, |
4810 | - pad_url=None, |
4811 | - name='test-meeting', |
4812 | - summit=summit, |
4813 | - private=False |
4814 | - ) |
4815 | - name = meeting.name |
4816 | - elem = self.get_person_node( |
4817 | - attendee.user.username, |
4818 | - required=False, |
4819 | - ) |
4820 | - meeting.update_from_launchpad(elem) |
4821 | - participant = meeting.participant_set.get() |
4822 | - self.assertEqual(attendee, participant.attendee) |
4823 | - self.assertEqual('ATTENDING', participant.participation) |
4824 | - |
4825 | - def test_update_from_launchpad_sets_participant_essential(self): |
4826 | - summit, attendee = self.make_summit_and_attendee() |
4827 | - meeting = factory.make_one( |
4828 | - Meeting, |
4829 | - pad_url=None, |
4830 | - name='test-meeting', |
4831 | - summit=summit, |
4832 | - private=False |
4833 | - ) |
4834 | - name = meeting.name |
4835 | - elem = self.get_person_node( |
4836 | - attendee.user.username, |
4837 | - required=True, |
4838 | - ) |
4839 | - meeting.update_from_launchpad(elem) |
4840 | - participant = meeting.participant_set.get() |
4841 | - self.assertEqual('INTERESTED', participant.participation) |
4842 | - |
4843 | - def test_update_from_launchpad_sets_from_launchpad(self): |
4844 | - summit, attendee = self.make_summit_and_attendee() |
4845 | - meeting = summit.meeting_set.create() |
4846 | - elem = self.get_person_node(attendee.user.username) |
4847 | - meeting.update_from_launchpad(elem) |
4848 | - participant = meeting.participant_set.get() |
4849 | - self.assertEqual(True, participant.from_launchpad) |
4850 | - |
4851 | - def test_update_from_launchpad_removes_from_launchpad_unsubscribed(self): |
4852 | - summit, attendee = self.make_summit_and_attendee() |
4853 | - meeting = summit.meeting_set.create() |
4854 | - elem = self.get_person_node(attendee.user.username) |
4855 | - otheruser = factory.make_one(User, username="otheruser") |
4856 | - otherattendee = summit.attendee_set.create(user=otheruser) |
4857 | - meeting.participant_set.create( |
4858 | - attendee=otherattendee, |
4859 | - from_launchpad=True |
4860 | - ) |
4861 | - meeting.update_from_launchpad(elem) |
4862 | - usernames = [ |
4863 | - p.attendee.user.username for p in meeting.participant_set.all() |
4864 | - ] |
4865 | - self.assertEqual(["username"], usernames) |
4866 | - |
4867 | - |
4868 | -class ICalTestCase(djangotest.TestCase): |
4869 | - |
4870 | - def test_ical_meeting_without_name(self): |
4871 | - """ Tests that ical doesn't break for nameless meetings""" |
4872 | - now = datetime.datetime.utcnow() |
4873 | - one_hour = datetime.timedelta(0, 3600) |
4874 | - summit = factory.make_one(Summit, name='uds-test') |
4875 | - summit.save() |
4876 | - slot = factory.make_one( |
4877 | - Slot, |
4878 | - start_utc=now, |
4879 | - end_utc=now+one_hour, |
4880 | - type='open', |
4881 | - summit=summit |
4882 | - ) |
4883 | - slot.save() |
4884 | - |
4885 | - room = factory.make_one(Room, summit=summit) |
4886 | - meeting = factory.make_one( |
4887 | - Meeting, |
4888 | - summit=summit, |
4889 | - name='', |
4890 | - private=False |
4891 | - ) |
4892 | - meeting.name = '' |
4893 | - models.Model.save(meeting) |
4894 | - agenda = factory.make_one( |
4895 | - Agenda, |
4896 | - slot=slot, |
4897 | - meeting=meeting, |
4898 | - room=room |
4899 | - ) |
4900 | - |
4901 | - self.assertEquals( |
4902 | - meeting.meeting_page_url, |
4903 | - '/uds-test/meeting/%s/-/' % meeting.id |
4904 | - ) |
4905 | - |
4906 | - response = self.client.get('/uds-test.ical') |
4907 | - self.assertEquals(response.status_code, 200) |
4908 | - self.assertContains( |
4909 | - response, |
4910 | - 'URL:%s/uds-test/meeting/%s/-/\n' % (site_root, meeting.id), |
4911 | - 1 |
4912 | - ) |
4913 | - |
4914 | - def test_ical_meeting_name_with_period(self): |
4915 | - """ Tests that ical doesn't break for nameless meetings""" |
4916 | - now = datetime.datetime.utcnow() |
4917 | - one_hour = datetime.timedelta(0, 3600) |
4918 | - summit = factory.make_one(Summit, name='uds-test') |
4919 | - summit.save() |
4920 | - slot = factory.make_one( |
4921 | - Slot, |
4922 | - start_utc=now, |
4923 | - end_utc=now+one_hour, |
4924 | - type='open', |
4925 | - summit=summit |
4926 | - ) |
4927 | - slot.save() |
4928 | - |
4929 | - room = factory.make_one(Room, summit=summit) |
4930 | - meeting = factory.make_one( |
4931 | - Meeting, |
4932 | - summit=summit, |
4933 | - name='test.name', |
4934 | - private=False |
4935 | - ) |
4936 | - agenda = factory.make_one( |
4937 | - Agenda, |
4938 | - slot=slot, |
4939 | - meeting=meeting, |
4940 | - room=room |
4941 | - ) |
4942 | - |
4943 | - self.assertEquals( |
4944 | - meeting.meeting_page_url, |
4945 | - '/uds-test/meeting/%s/test.name/' % meeting.id |
4946 | - ) |
4947 | - |
4948 | - response = self.client.get('/uds-test.ical') |
4949 | - self.assertEquals(response.status_code, 200) |
4950 | - self.assertContains( |
4951 | - response, |
4952 | - 'URL:%s/uds-test/meeting/%s/test.name/' % (site_root, meeting.id), |
4953 | - 1 |
4954 | - ) |
4955 | - |
4956 | - def test_ical_meeting_multiline_description(self): |
4957 | - """ Tests that ical put spaces before multi-line descriptions""" |
4958 | - now = datetime.datetime.utcnow() |
4959 | - one_hour = datetime.timedelta(0, 3600) |
4960 | - summit = factory.make_one(Summit, name='uds-test') |
4961 | - summit.save() |
4962 | - slot = factory.make_one( |
4963 | - Slot, |
4964 | - start_utc=now, |
4965 | - end_utc=now+one_hour, |
4966 | - type='open', |
4967 | - summit=summit |
4968 | - ) |
4969 | - slot.save() |
4970 | - |
4971 | - room = factory.make_one(Room, summit=summit) |
4972 | - meeting = factory.make_one( |
4973 | - Meeting, |
4974 | - summit=summit, |
4975 | - name='test.name', |
4976 | - description="Test\r\nDescription", |
4977 | - private=False |
4978 | - ) |
4979 | - agenda = factory.make_one( |
4980 | - Agenda, |
4981 | - slot=slot, |
4982 | - meeting=meeting, |
4983 | - room=room |
4984 | - ) |
4985 | - |
4986 | - self.assertEquals( |
4987 | - meeting.meeting_page_url, |
4988 | - '/uds-test/meeting/%s/test.name/' % meeting.id |
4989 | - ) |
4990 | - |
4991 | - response = self.client.get('/uds-test.ical') |
4992 | - self.assertEquals(response.status_code, 200) |
4993 | - self.assertContains(response, 'DESCRIPTION:Test\NDescription', 1) |
4994 | - |
4995 | - def test_private_ical(self): |
4996 | - """ Tests that private icals contain private meetings """ |
4997 | - now = datetime.datetime.utcnow() |
4998 | - one_hour = datetime.timedelta(0, 3600) |
4999 | - week = datetime.timedelta(days=7) |
5000 | - summit = factory.make_one(Summit, name='uds-test') |
The diff has been truncated for viewing.
Looks good