Merge lp:~cjohnston/summit/propose-meeting-not-attendee into lp:summit

Proposed by Chris Johnston
Status: Merged
Approved by: Chris Johnston
Approved revision: 513
Merged at revision: 512
Proposed branch: lp:~cjohnston/summit/propose-meeting-not-attendee
Merge into: lp:summit
Prerequisite: lp:~cjohnston/summit/update-django-1-4
Diff against target: 389 lines (+240/-21)
7 files modified
requirements.txt (+1/-1)
summit/schedule/models/meetingmodel.py (+1/-2)
summit/schedule/tests/__init__.py (+1/-0)
summit/schedule/tests/meeting_model.py (+37/-15)
summit/schedule/tests/propose_meeting.py (+187/-0)
summit/schedule/views.py (+12/-2)
summit/ubuntu_settings.py (+1/-1)
To merge this branch: bzr merge lp:~cjohnston/summit/propose-meeting-not-attendee
Reviewer Review Type Date Requested Status
Michael Hall (community) Approve
Review via email: mp+153465@code.launchpad.net

This proposal supersedes a proposal from 2013-03-14.

Commit message

Allows a user to propose a meeting without being an attendee. Creates an attendee record for this user

To post a comment you must log in.
509. By Chris Johnston

flake8 support

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

Line 230 does nothing.

Line 243 shouldn't be there.

Line 228, this will set the Attendee's end time to be 00:00:00 the morning of the last day of the summit, which would cause a schedule conflict for any session on the last day. It should either use 23:59:59 for the time portion, or add one day to the summit.date_end

review: Needs Fixing
510. By Chris Johnston

fixes per mhall119

511. By Chris Johnston

Fixes null issue with tests

512. By Chris Johnston

cleanup

513. By Chris Johnston

Update to trunk

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 'requirements.txt'
2--- requirements.txt 2013-03-19 16:30:35 +0000
3+++ requirements.txt 2013-03-19 16:30:35 +0000
4@@ -17,7 +17,7 @@
5 python-dateutil==1.5
6 simplejson==2.0.9
7 wsgiref==0.1.2
8-model-mommy==0.7
9+model-mommy==0.8.1
10 Markdown==2.1.1
11 pylint
12
13
14=== modified file 'summit/schedule/models/meetingmodel.py'
15--- summit/schedule/models/meetingmodel.py 2013-03-09 04:42:44 +0000
16+++ summit/schedule/models/meetingmodel.py 2013-03-19 16:30:35 +0000
17@@ -401,8 +401,7 @@
18 if name:
19 self.name = name[:100]
20 else:
21- self.name = None
22-
23+ self.name = ""
24 status = elem.get("status")
25 if status:
26 self.status = status
27
28=== modified file 'summit/schedule/tests/__init__.py'
29--- summit/schedule/tests/__init__.py 2013-02-27 03:29:31 +0000
30+++ summit/schedule/tests/__init__.py 2013-03-19 16:30:35 +0000
31@@ -30,3 +30,4 @@
32 from private_scheduling import *
33 from schedule import *
34 from summit_model import *
35+from propose_meeting import *
36
37=== modified file 'summit/schedule/tests/meeting_model.py'
38--- summit/schedule/tests/meeting_model.py 2013-02-27 03:29:31 +0000
39+++ summit/schedule/tests/meeting_model.py 2013-03-19 16:30:35 +0000
40@@ -509,8 +509,11 @@
41 meeting.update_from_launchpad(elem)
42 self.assertEqual(wiki_url, meeting.wiki_url)
43
44- def get_person_node(self, username, required=False):
45- elem = LaunchpadExportNode()
46+ def get_person_node(self, username, name=None, required=False):
47+ if name:
48+ elem = LaunchpadExportNode(name=name)
49+ else:
50+ elem = LaunchpadExportNode()
51 required_map = {True: "True", False: "False"}
52 elem.add_child(
53 "person",
54@@ -526,20 +529,29 @@
55 summit = factory.make_one(Summit)
56 now = datetime.datetime.utcnow()
57 one_hour = datetime.timedelta(hours=1)
58- return factory.make_one(
59+ slot = factory.make_one(
60 Slot,
61 summit=summit,
62 start=now+one_hour,
63 end=now+one_hour+one_hour,
64 type='open'
65 )
66+ return slot
67
68 def make_summit_and_attendee(self):
69- username = "username"
70- user = factory.make_one(User, username=username)
71 summit = factory.make_one(Summit)
72 slot = self.make_one_future_slot(summit=summit)
73- attendee = summit.attendee_set.create(
74+ user = factory.make_one(
75+ User,
76+ username='testuser',
77+ first_name='Test',
78+ last_name='User',
79+ is_active=True,
80+ is_superuser=False,
81+ )
82+ attendee = factory.make_one(
83+ Attendee,
84+ summit=summit,
85 user=user,
86 start_utc=slot.start_utc,
87 end_utc=slot.end_utc
88@@ -555,9 +567,10 @@
89 summit=summit,
90 private=False
91 )
92- name = meeting.name
93+ meeting_name = meeting.name
94 elem = self.get_person_node(
95 attendee.user.username,
96+ meeting_name,
97 required=False,
98 )
99 meeting.update_from_launchpad(elem)
100@@ -574,10 +587,14 @@
101 summit=summit,
102 private=False
103 )
104- name = meeting.name
105+ meeting_name = meeting.name
106+ username = attendee.user.username
107+ required = True
108+
109 elem = self.get_person_node(
110- attendee.user.username,
111- required=True,
112+ username,
113+ meeting_name,
114+ required,
115 )
116 meeting.update_from_launchpad(elem)
117 participant = meeting.participant_set.get()
118@@ -586,7 +603,7 @@
119 def test_update_from_launchpad_sets_from_launchpad(self):
120 summit, attendee = self.make_summit_and_attendee()
121 meeting = summit.meeting_set.create()
122- elem = self.get_person_node(attendee.user.username)
123+ elem = self.get_person_node(attendee.user.username, meeting.name)
124 meeting.update_from_launchpad(elem)
125 participant = meeting.participant_set.get()
126 self.assertEqual(True, participant.from_launchpad)
127@@ -594,15 +611,20 @@
128 def test_update_from_launchpad_removes_from_launchpad_unsubscribed(self):
129 summit, attendee = self.make_summit_and_attendee()
130 meeting = summit.meeting_set.create()
131- elem = self.get_person_node(attendee.user.username)
132+ elem = self.get_person_node(attendee.user.username, meeting.name)
133+ slot = self.make_one_future_slot(summit=summit)
134 otheruser = factory.make_one(User, username="otheruser")
135- otherattendee = summit.attendee_set.create(user=otheruser)
136+ otherattendee = summit.attendee_set.create(
137+ user=otheruser,
138+ start_utc=slot.start_utc,
139+ end_utc=slot.end_utc
140+ )
141 meeting.participant_set.create(
142 attendee=otherattendee,
143- from_launchpad=True
144+ from_launchpad=True,
145 )
146 meeting.update_from_launchpad(elem)
147 usernames = [
148 p.attendee.user.username for p in meeting.participant_set.all()
149 ]
150- self.assertEqual(["username"], usernames)
151+ self.assertEqual(["testuser"], usernames)
152
153=== added file 'summit/schedule/tests/propose_meeting.py'
154--- summit/schedule/tests/propose_meeting.py 1970-01-01 00:00:00 +0000
155+++ summit/schedule/tests/propose_meeting.py 2013-03-19 16:30:35 +0000
156@@ -0,0 +1,187 @@
157+# The Summit Scheduler web application
158+# Copyright (C) 2008 - 2013 Ubuntu Community, Canonical Ltd
159+#
160+# This program is free software: you can redistribute it and/or modify
161+# it under the terms of the GNU Affero General Public License as
162+# published by the Free Software Foundation, either version 3 of the
163+# License, or (at your option) any later version.
164+#
165+# This program is distributed in the hope that it will be useful,
166+# but WITHOUT ANY WARRANTY; without even the implied warranty of
167+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
168+# GNU Affero General Public License for more details.
169+#
170+# You should have received a copy of the GNU Affero General Public License
171+# along with this program. If not, see <http://www.gnu.org/licenses/>.
172+
173+import datetime
174+
175+from django import test as djangotest
176+from django.core.urlresolvers import reverse
177+from django.contrib.auth.models import User
178+from django.test.client import Client
179+
180+from model_mommy import mommy as factory
181+
182+from summit.schedule.models import (
183+ Summit,
184+ Slot,
185+ Attendee,
186+ Meeting,
187+ Track,
188+ Room,
189+)
190+
191+
192+class ProposeMeetingSummitTestCase(djangotest.TestCase):
193+ """
194+ Tests for the propose meeting functions
195+ """
196+
197+ c = Client()
198+
199+ def setUp(self):
200+ now = datetime.datetime.utcnow()
201+ one_hour = datetime.timedelta(0, 3600)
202+ week = datetime.timedelta(days=5)
203+ self.summit = factory.make_one(
204+ Summit,
205+ name='uds-virt',
206+ virtual_summit=True,
207+ date_start=now,
208+ date_end=now + week,
209+ )
210+
211+ self.slot = factory.make_one(
212+ Slot,
213+ start_utc=now+one_hour,
214+ end_utc=now+(2*one_hour),
215+ type='open',
216+ summit=self.summit
217+ )
218+ self.track = factory.make_one(Track, summit=self.summit, title='test')
219+ self.room = factory.make_one(
220+ Room,
221+ summit=self.summit,
222+ type='open',
223+ irc_channel='test-channel',
224+ )
225+
226+ self.user1 = factory.make_one(
227+ User,
228+ username='testuser',
229+ first_name='Test',
230+ last_name='User',
231+ is_active=True,
232+ is_superuser=False,
233+ )
234+ self.user1.set_password('password')
235+ self.user1.save()
236+
237+ def tearDown(self):
238+ self.client.logout()
239+
240+ def login(self):
241+ logged_in = self.c.login(
242+ username='testuser',
243+ password='password')
244+ self.assertTrue(logged_in)
245+
246+ def view_and_save_propose_meeting_form(self):
247+ """
248+ Tests that a user, attendee or not, can propose a meeting
249+ """
250+ # View the edit meeting hangout form
251+ rev_args = [self.summit.name, ]
252+ response = self.c.get(
253+ reverse(
254+ 'summit.schedule.views.propose_meeting',
255+ args=rev_args
256+ )
257+ )
258+ self.assertEqual(response.status_code, 200)
259+ self.assertTemplateUsed(response, 'schedule/propose_meeting.html')
260+
261+ # Define data to fill our the form
262+ title = 'Test Meeting'
263+ description = "This is a test meeting."
264+ tracks = [self.track.pk]
265+ spec_url = "http://www.example.com/spec"
266+ wiki_url = "http://www.example.com/wiki"
267+ pad_url = "http://www.example.com/pad"
268+ csrf_token = '%s' % response.context['csrf_token']
269+
270+ # Post the form
271+ post = self.c.post(
272+ reverse(
273+ 'summit.schedule.views.propose_meeting',
274+ args=rev_args
275+ ),
276+ data={
277+ 'csrfmiddlewaretoken': csrf_token,
278+ 'title': title,
279+ 'description': description,
280+ 'tracks': tracks,
281+ 'spec_url': spec_url,
282+ 'wiki_url': wiki_url,
283+ 'pad_url': pad_url,
284+ }
285+ )
286+
287+ # A successful post should redirect to the meeting page
288+ response = self.view_meeting_page()
289+ meeting = Meeting.objects.get(title='Test Meeting')
290+ redirect_args = [self.summit.name, meeting.id, meeting.name]
291+ redirect_url = reverse(
292+ 'summit.schedule.views.meeting',
293+ args=redirect_args
294+ )
295+ self.assertEqual(post.status_code, 302)
296+ self.assertRedirects(
297+ post,
298+ redirect_url,
299+ )
300+ redirect_response = self.c.get(redirect_url)
301+
302+ # Verify that the new data appears on the meeting page
303+ self.assertEqual(redirect_response.status_code, 200)
304+ self.assertIn("Test Meeting", redirect_response.content)
305+
306+ def view_meeting_page(self):
307+ meeting = Meeting.objects.get(title='Test Meeting')
308+ rev_args = [self.summit.name, meeting.id, meeting.name]
309+ response = self.c.get(
310+ reverse(
311+ 'summit.schedule.views.meeting',
312+ args=rev_args
313+ )
314+ )
315+ self.assertEqual(response.status_code, 200)
316+
317+ return response
318+
319+ def test_propose_meeting_no_attendee(self):
320+ """
321+ Tests that a user who is not an attendee can propose a meeting
322+ and that an attendee record is created when the user does.
323+ """
324+
325+ self.login()
326+
327+ self.view_and_save_propose_meeting_form()
328+
329+ def test_propose_meeting_with_attendee(self):
330+ """
331+ Tests that a user who is not an attendee can propose a meeting
332+ and that an attendee record is created when the user does.
333+ """
334+
335+ self.attendee1 = factory.make_one(
336+ Attendee,
337+ summit=self.summit,
338+ user=self.user1,
339+ start_utc=self.summit.date_start,
340+ end_utc=self.summit.date_end
341+ )
342+
343+ self.login()
344
345=== modified file 'summit/schedule/views.py'
346--- summit/schedule/views.py 2013-03-07 22:33:12 +0000
347+++ summit/schedule/views.py 2013-03-19 16:30:35 +0000
348@@ -24,7 +24,7 @@
349 from django.core.urlresolvers import reverse
350 from django.utils.datastructures import SortedDict
351 from django.views.decorators.csrf import csrf_exempt
352-from django.views.decorators.csrf import csrf_protect
353+from django.contrib.auth.decorators import login_required
354
355 from summit.schedule.decorators import (
356 summit_required,
357@@ -716,8 +716,18 @@
358 )
359
360
361-@summit_attendee_required
362+@login_required
363+@summit_required
364 def propose_meeting(request, summit, attendee):
365+ eod=datetime.time(23, 59, 59)
366+ eos=summit.date_end
367+ if attendee is None:
368+ attendee = Attendee.objects.create(
369+ summit=summit,
370+ user=request.user,
371+ start_utc=summit.date_start,
372+ end_utc=datetime.datetime.combine(eos, eod)
373+ )
374
375 meeting = Meeting(
376 summit=summit,
377
378=== modified file 'summit/ubuntu_settings.py'
379--- summit/ubuntu_settings.py 2013-02-26 22:28:51 +0000
380+++ summit/ubuntu_settings.py 2013-03-19 16:30:35 +0000
381@@ -14,7 +14,7 @@
382 import ubuntu_website
383
384 INSTALLED_APPS.append('ubuntu_website')
385-
386+
387 TEMPLATE_CONTEXT_PROCESSORS += (
388 "ubuntu_website.media_processor",
389 "ubuntu_website.popup_check",

Subscribers

People subscribed via source and target branches