Skip to content

Commit df571c2

Browse files
committed
Improved test coverage (from 66 to 87%) - checkpointing before removing move_to_default
- Legacy-Id: 10602
1 parent bf54e2b commit df571c2

3 files changed

Lines changed: 229 additions & 11 deletions

File tree

ietf/nomcom/factories.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -92,18 +92,20 @@ def populate_positions(self, create, extracted, **kwargs):
9292
if extracted is None:
9393
extracted = True
9494
if create and extracted:
95-
nominees = [Nominee.objects.create(nomcom=self, email=PersonFactory().email_set.first()) for i in range(2)]
95+
nominees = [Nominee.objects.create(nomcom=self, email=PersonFactory().email_set.first()) for i in range(4)]
9696
positions = [PositionFactory(nomcom=self) for i in range(3)]
9797

98-
def npc(x,y):
99-
return NomineePosition.objects.create(position=x,
100-
nominee=y,
101-
state_id='accepted')
98+
def npc(position,nominee,state_id):
99+
return NomineePosition.objects.create(position=position,
100+
nominee=nominee,
101+
state_id=state_id)
102102
# This gives us positions with 0, 1 and 2 nominees, and
103-
# one person who's been nomminated for more than one position
104-
npc(positions[0],nominees[0])
105-
npc(positions[1],nominees[0])
106-
npc(positions[1],nominees[1])
103+
# one person who's been nominated for more than one position
104+
npc(positions[0],nominees[0],'accepted')
105+
npc(positions[1],nominees[0],'accepted')
106+
npc(positions[1],nominees[1],'accepted')
107+
npc(positions[0],nominees[2],'pending')
108+
npc(positions[0],nominees[3],'declined')
107109

108110
@factory.post_generation
109111
def populate_personnel(self, create, extracted, **kwargs):

ietf/nomcom/tests.py

Lines changed: 217 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@
3131
from ietf.nomcom.management.commands.send_reminders import Command, is_time_to_send
3232

3333
from ietf.nomcom.factories import NomComFactory, FeedbackFactory, \
34-
nomcom_kwargs_for_year, provide_private_key_to_test_client
34+
nomcom_kwargs_for_year, provide_private_key_to_test_client, \
35+
key
3536
from ietf.person.factories import PersonFactory
3637
from ietf.dbtemplate.factories import DBTemplateFactory
3738

@@ -1199,6 +1200,37 @@ def test_help(self):
11991200
response = self.client.get(url)
12001201
self.assertEqual(response.status_code,200)
12011202

1203+
def test_accept_reject_nomination_edges(self):
1204+
1205+
np = self.nc.nominee_set.first().nomineeposition_set.first()
1206+
1207+
kwargs={'year':self.nc.year(),
1208+
'nominee_position_id':np.id,
1209+
'state':'accepted',
1210+
'date':np.time.strftime("%Y%m%d"),
1211+
'hash':get_hash_nominee_position(np.time.strftime("%Y%m%d"),np.id),
1212+
}
1213+
url = reverse('nomcom_process_nomination_status', kwargs=kwargs)
1214+
response = self.client.get(url)
1215+
self.assertEqual(response.status_code,403)
1216+
self.assertTrue('already was' in unicontent(response))
1217+
1218+
settings.DAYS_TO_EXPIRE_NOMINATION_LINK = 2
1219+
np.time = np.time - datetime.timedelta(days=3)
1220+
np.save()
1221+
kwargs['date'] = np.time.strftime("%Y%m%d")
1222+
kwargs['hash'] = get_hash_nominee_position(np.time.strftime("%Y%m%d"),np.id)
1223+
url = reverse('nomcom_process_nomination_status', kwargs=kwargs)
1224+
response = self.client.get(url)
1225+
self.assertEqual(response.status_code,403)
1226+
self.assertTrue('Link expired' in unicontent(response))
1227+
1228+
kwargs['hash'] = 'bad'
1229+
url = reverse('nomcom_process_nomination_status', kwargs=kwargs)
1230+
response = self.client.get(url)
1231+
self.assertEqual(response.status_code,403)
1232+
self.assertTrue('Bad hash!' in unicontent(response))
1233+
12021234
def test_accept_reject_nomination_comment(self):
12031235
np = self.nc.nominee_set.first().nomineeposition_set.first()
12041236
hash = get_hash_nominee_position(np.time.strftime("%Y%m%d"),np.id)
@@ -1224,4 +1256,188 @@ def test_accept_reject_nomination_comment(self):
12241256
response = self.client.post(url,{'comments':'A nonempty comment'})
12251257
self.assertEqual(response.status_code,200)
12261258
self.assertEqual(Feedback.objects.count(),feedback_count_before+1)
1259+
1260+
def test_provide_private_key(self):
1261+
url = reverse('nomcom_private_key',kwargs={'year':self.nc.year()})
1262+
login_testing_unauthorized(self,self.chair.user.username,url)
1263+
response = self.client.get(url)
1264+
self.assertEqual(response.status_code,200)
1265+
response = self.client.post(url,{'key':key})
1266+
self.assertEqual(response.status_code,302)
1267+
1268+
def test_email_pasting(self):
1269+
url = reverse('nomcom_private_feedback_email',kwargs={'year':self.nc.year()})
1270+
login_testing_unauthorized(self,self.chair.user.username,url)
1271+
response = self.client.get(url)
1272+
self.assertTrue(response.status_code,200)
1273+
fb_count_before = Feedback.objects.count()
1274+
response = self.client.post(url,{'email_text':"""To: rjsparks@nostrum.com
1275+
From: Robert Sparks <rjsparks@nostrum.com>
1276+
Subject: Junk message for feedback testing
1277+
Message-ID: <566F2FE5.1050401@nostrum.com>
1278+
Date: Mon, 14 Dec 2015 15:08:53 -0600
1279+
Content-Type: text/plain; charset=utf-8; format=flowed
1280+
Content-Transfer-Encoding: 7bit
1281+
1282+
Junk body for testing
1283+
1284+
"""})
1285+
self.assertEqual(response.status_code,200)
1286+
self.assertEqual(Feedback.objects.count(),fb_count_before+1)
1287+
1288+
def test_simple_feedback_pending(self):
1289+
url = reverse('nomcom_view_feedback_pending',kwargs={'year':self.nc.year() })
1290+
login_testing_unauthorized(self, self.chair.user.username, url)
1291+
provide_private_key_to_test_client(self)
1292+
1293+
# test simple classification when there's only one thing to classify
1294+
1295+
# junk is the only category you can set directly from the first form the view presents
1296+
fb = FeedbackFactory(nomcom=self.nc,type_id=None)
1297+
response = self.client.get(url)
1298+
self.assertEqual(response.status_code,200)
1299+
1300+
response = self.client.post(url, {'form-TOTAL_FORMS': 1,
1301+
'form-INITIAL_FORMS': 1,
1302+
'form-0-id': fb.id,
1303+
'form-0-type': 'junk',
1304+
})
1305+
self.assertEqual(response.status_code,302)
1306+
fb = Feedback.objects.get(id=fb.id)
1307+
self.assertEqual(fb.type_id,'junk')
1308+
1309+
# comments, nominations, and questionnare responses are catagorized via a second
1310+
# formset presented by the view (signaled by having 'end' appear in the POST)
1311+
fb = FeedbackFactory(nomcom=self.nc,type_id=None)
1312+
np = NomineePosition.objects.filter(position__nomcom = self.nc,state='accepted').first()
1313+
fb_count_before = np.nominee.feedback_set.count()
1314+
response = self.client.post(url, {'form-TOTAL_FORMS':1,
1315+
'form-INITIAL_FORMS':1,
1316+
'end':'Save feedback',
1317+
'form-0-id': fb.id,
1318+
'form-0-type': 'comment',
1319+
'form-0-nominee': '%s_%s'%(np.position.id,np.nominee.id),
1320+
})
1321+
self.assertEqual(response.status_code,302)
1322+
fb = Feedback.objects.get(id=fb.id)
1323+
self.assertEqual(fb.type_id,'comment')
1324+
self.assertEqual(np.nominee.feedback_set.count(),fb_count_before+1)
1325+
1326+
fb = FeedbackFactory(nomcom=self.nc,type_id=None)
1327+
nominee = self.nc.nominee_set.first()
1328+
position = self.nc.position_set.exclude(nomineeposition__nominee=nominee).first()
1329+
self.assertIsNotNone(position)
1330+
fb_count_before = nominee.feedback_set.count()
1331+
response = self.client.post(url, {'form-TOTAL_FORMS':1,
1332+
'form-INITIAL_FORMS':1,
1333+
'end':'Save feedback',
1334+
'form-0-id': fb.id,
1335+
'form-0-type': 'nomina',
1336+
'form-0-position': position.id,
1337+
'form-0-candidate_name' : nominee.name(),
1338+
'form-0-candidate_email' : nominee.email.address,
1339+
})
1340+
self.assertEqual(response.status_code,302)
1341+
fb = Feedback.objects.get(id=fb.id)
1342+
self.assertEqual(fb.type_id,'nomina')
1343+
self.assertEqual(nominee.feedback_set.count(),fb_count_before+1)
1344+
1345+
fb = FeedbackFactory(nomcom=self.nc,type_id=None)
1346+
np = NomineePosition.objects.filter(position__nomcom = self.nc,state='accepted').first()
1347+
fb_count_before = np.nominee.feedback_set.count()
1348+
response = self.client.post(url, {'form-TOTAL_FORMS':1,
1349+
'form-INITIAL_FORMS':1,
1350+
'end':'Save feedback',
1351+
'form-0-id': fb.id,
1352+
'form-0-type': 'questio',
1353+
'form-0-nominee': '%s_%s'%(np.position.id,np.nominee.id),
1354+
})
1355+
self.assertEqual(response.status_code,302)
1356+
fb = Feedback.objects.get(id=fb.id)
1357+
self.assertEqual(fb.type_id,'questio')
1358+
self.assertEqual(np.nominee.feedback_set.count(),fb_count_before+1)
1359+
1360+
def test_complicated_feedback_pending(self):
1361+
url = reverse('nomcom_view_feedback_pending',kwargs={'year':self.nc.year() })
1362+
login_testing_unauthorized(self, self.chair.user.username, url)
1363+
provide_private_key_to_test_client(self)
1364+
1365+
# Test having multiple things to classify
1366+
# The view has some complicated to handle having some forms in the initial form formset
1367+
# being categorized as 'junk' and others being categorized as something that requires
1368+
# more information. The second formset presented will have forms for any others initially
1369+
# categorized as nominations, then a third formset will be presented with any that were
1370+
# initially categorized as comments or questionnaire responses. The following exercises
1371+
# all the gears that glue these three formset presentations together.
12271372

1373+
fb0 = FeedbackFactory(nomcom=self.nc,type_id=None)
1374+
fb1 = FeedbackFactory(nomcom=self.nc,type_id=None)
1375+
fb2 = FeedbackFactory(nomcom=self.nc,type_id=None)
1376+
nominee = self.nc.nominee_set.first()
1377+
new_position_for_nominee = self.nc.position_set.exclude(nomineeposition__nominee=nominee).first()
1378+
1379+
# Initial formset
1380+
response = self.client.post(url, {'form-TOTAL_FORMS': 3,
1381+
'form-INITIAL_FORMS': 3,
1382+
'form-0-id': fb0.id,
1383+
'form-0-type': 'junk',
1384+
'form-1-id': fb1.id,
1385+
'form-1-type': 'nomina',
1386+
'form-2-id': fb2.id,
1387+
'form-2-type': 'comment',
1388+
})
1389+
self.assertEqual(response.status_code,200) # Notice that this is not a 302
1390+
fb0 = Feedback.objects.get(id=fb0.id)
1391+
self.assertEqual(fb0.type_id,'junk')
1392+
q = PyQuery(response.content)
1393+
self.assertEqual(q('input[name=\"form-0-type\"]').attr['value'],'nomina')
1394+
self.assertEqual(q('input[name=\"extra_ids\"]').attr['value'],'%s:comment' % fb2.id)
1395+
1396+
# Second formset
1397+
response = self.client.post(url, {'form-TOTAL_FORMS':1,
1398+
'form-INITIAL_FORMS':1,
1399+
'end':'Save feedback',
1400+
'form-0-id': fb1.id,
1401+
'form-0-type': 'nomina',
1402+
'form-0-position': new_position_for_nominee.id,
1403+
'form-0-candidate_name' : nominee.name(),
1404+
'form-0-candidate_email' : nominee.email.address,
1405+
'extra_ids': '%s:comment' % fb2.id,
1406+
})
1407+
self.assertEqual(response.status_code,200) # Notice that this is also is not a 302
1408+
fb1 = Feedback.objects.get(id=fb1.id)
1409+
self.assertEqual(fb1.type_id,'nomina')
1410+
q = PyQuery(response.content)
1411+
self.assertEqual(q('input[name=\"form-0-type\"]').attr['value'],'comment')
1412+
self.assertFalse(q('input[name=\"extra_ids\"]'))
1413+
1414+
# Exercising the resulting third formset is identical to the simple test above
1415+
# that categorizes a single thing as a comment. Note that it returns a 302.
1416+
1417+
# There is yet another code-path for transitioning to the second form when
1418+
# nothing was classified as a nomination.
1419+
fb0 = FeedbackFactory(nomcom=self.nc,type_id=None)
1420+
fb1 = FeedbackFactory(nomcom=self.nc,type_id=None)
1421+
np = NomineePosition.objects.filter(position__nomcom = self.nc,state='accepted').first()
1422+
response = self.client.post(url, {'form-TOTAL_FORMS': 2,
1423+
'form-INITIAL_FORMS': 2,
1424+
'form-0-id': fb0.id,
1425+
'form-0-type': 'junk',
1426+
'form-1-id': fb1.id,
1427+
'form-1-type': 'comment',
1428+
})
1429+
self.assertEqual(response.status_code,200)
1430+
q = PyQuery(response.content)
1431+
self.assertEqual(q('input[name=\"form-0-type\"]').attr['value'],'comment')
1432+
self.assertFalse(q('input[name=\"extra_ids\"]'))
1433+
1434+
1435+
class NomComIndexTests(TestCase):
1436+
def setUp(self):
1437+
for year in range(2000,2014):
1438+
NomComFactory.create(**nomcom_kwargs_for_year(year=year,populate_positions=False,populate_personnel=False))
1439+
1440+
def testIndex(self):
1441+
url = reverse('ietf.nomcom.views.index')
1442+
response = self.client.get(url)
1443+
self.assertEqual(response.status_code,200)

ietf/nomcom/views.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,7 @@ def process_nomination_status(request, year, nominee_position_id, state, date, h
533533
expiration_days = getattr(settings, 'DAYS_TO_EXPIRE_NOMINATION_LINK', None)
534534
if expiration_days:
535535
request_date = datetime.date(int(date[:4]), int(date[4:6]), int(date[6:]))
536-
if datetime.date.today() > (request_date + datetime.timedelta(days=settings.DAYS_TO_EXPIRE_REGISTRATION_LINK)):
536+
if datetime.date.today() > (request_date + datetime.timedelta(days=settings.DAYS_TO_EXPIRE_NOMINATION_LINK)):
537537
return HttpResponseForbidden("Link expired")
538538

539539
need_confirmation = True

0 commit comments

Comments
 (0)