Merge lp:~cjohnston/summit/seperate-tests into lp:summit

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
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

To post a comment you must log in.
lp:~cjohnston/summit/seperate-tests updated
490. By Chris Johnston

Fix conflicts

491. By Chris Johnston

oops

Revision history for this message
Michael Hall (mhall119) wrote :

Looks good

review: Approve

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.

Subscribers

People subscribed via source and target branches