def test_get_message_code_display_for_obsolete_message(self): """If MessageText object gets deleted, we should not fail.""" msg = MessageText.objects.create(number=23, label='TWENTY_THREE') sms = SMSFactory(message_code=msg.number) msg.delete() self.assertEqual('Obsolete message code: 23', sms.get_message_code_display())
def test_surrounding_pages_have_links(self): SMSFactory.create_batch(size=8) request = self.create_request(page=5) paginator_links = self.browse_view(request).context_data['paginator_links'] page_4_url = self.url + '?page=4' page_6_url = self.url + '?page=6' self.assertIn([page_4_url, 4], paginator_links) self.assertIn([page_6_url, 6], paginator_links) # page 3 is not in the list (it's elided) page_3_url = self.url + '?page=3' self.assertNotIn([page_3_url, 3], paginator_links)
def test_sent_messages_dont_get_resent(self): for i in range(20): BulkMessageFactory(batch=self.batch, sms=None) for i in range(10): sms = SMSFactory() BulkMessageFactory(batch=self.batch, sms=sms) BulkMessageFactory(batch=self.batch, sms=SMSFactory(), deleted=True) send_messages(self.batch) # only 21 messages get sent out (20 + 1 from setUp) self.assertEqual(len(self.outbound), 21)
def test_surrounding_pages_have_links(self): SMSFactory.create_batch(size=8) request = self.create_request(page=5) paginator_links = self.browse_view( request).context_data['paginator_links'] page_4_url = self.url + '?page=4' page_6_url = self.url + '?page=6' self.assertIn([page_4_url, 4], paginator_links) self.assertIn([page_6_url, 6], paginator_links) # page 3 is not in the list (it's elided) page_3_url = self.url + '?page=3' self.assertNotIn([page_3_url, 3], paginator_links)
def create_voters(n_voters, gender=None, center=None): """Create voters in bulk, with options not available via the factory""" toggle_gender = not bool(gender) if not gender: gender = MALE # I create a dummy SMS here for optimization. If the VoterFactory creates a registration for # each user and I don't pass an SMS instance, it will create an SMS for each registration which # triggers the creation of a Citizen and a Backend. Passing a dummy SMS reduces this overhead # from O(3 * n_voters) to O(1). It's logically incorrect to associate the same SMS with multiple # registrations, but rollgen doesn't pay attention to SMSes. sms = SMSFactory() voter_ids = [] for i in range(n_voters): if toggle_gender: gender = FEMALE if (gender == MALE) else MALE voter = VoterFactory(gender=gender, post__center=center, post__sms=sms) voter_ids.append(voter.pk) # It's a bit painful performance-wise, but in order to sort these the same way as # get_voter_roll(), I have to let the database do the sorting. return list( Citizen.objects.filter(pk__in=voter_ids).order_by( *CITIZEN_SORT_FIELDS))
def test_dont_send_msg_if_sms_field_set(self): # set the sms field self.bulk_msg.sms = SMSFactory() self.bulk_msg.save() send_message_by_id(self.bulk_msg.pk) # no message sent self.assertEqual(len(self.outbound), 0)
def setUp(self): self.citizen = CitizenFactory() self.good_nid = self.citizen.national_id self.bad_nid = long( get_random_number_string(length=constants.NID_LENGTH)) self.nid_without_citizen = long( get_random_number_string(length=constants.NID_LENGTH)) self.sms = SMSFactory()
def test_dont_find_message_tester_sms_objects(self): """SMS objects which don't go to Vumi should not be audited.""" # make sure the SMS objects are older than 24 hours, or else we don't audit them creation_date = now() - timedelta(hours=25) # create a message_tester SMS object which should not get audited test_backend = BackendFactory(name=settings.HTTPTESTER_BACKEND) SMSFactory(direction=OUTGOING, creation_date=creation_date, carrier=test_backend) # create an SMS object that SHOULD get audited audited_sms = SMSFactory(direction=OUTGOING, creation_date=creation_date, carrier=self.vumi_backend) audit_outgoing_sms() discrepancies = models.Discrepancy.objects.all() # only 1 discrepancy found self.assertEqual(discrepancies.count(), 1) self.assertEqual(discrepancies[0].trail.sms, audited_sms)
def setUp(self): self.sms = SMSFactory() self.citizen = CitizenFactory(national_id=219782058018) self.center = RegistrationCenterFactory() RegistrationCenterFactory(center_id=self.center.center_id, deleted=True) self.mock_response = Mock() self.reg_period = RegistrationPeriodFactory(start_time=PAST_DAY, end_time=FUTURE_DAY)
def create(delete_old_data=False): assert settings.ENVIRONMENT not in ('production', 'testing') if delete_old_data: SMSTrail.objects.unfiltered().delete() VumiLog.objects.unfiltered().delete() Case.objects.unfiltered().delete() Registration.objects.unfiltered().delete() SMS.objects.unfiltered().delete() Discrepancy.objects.unfiltered().delete() for i in range(NUM_INCOMING): # create incoming VumiLog instances v = VumiLogFactory() # create SMS instances for all but 1, so we'll have 1 discrepancy if i > 0: SMSFactory( from_number=v.from_addr, to_number=v.to_addr, direction=v.direction, message=v.content, uuid=v.uuid, ) for i in range(NUM_OUTGOING): # create outgoing SMS instances (a couple days old, so they'll be audited) s = SMSFactory(creation_date=PAST_DAY, modification_date=PAST_DAY, direction=OUTGOING) # create Vumi instances for all but 1, so we'll have 1 discrepancy if i > 0: VumiLogFactory( from_addr=s.from_number, to_addr=s.to_number, direction=s.direction, content=s.message, uuid=s.uuid, ) # run the audit audit_sms()
def test_phone_reaches_only_one_more(self): number = '12345678' RegistrationFactory(sms__from_number=number, archive_time=None) new_sms = SMSFactory(from_number=number) result = process_registration_request( sms=new_sms, national_id=self.citizen.national_id, center_id=self.center.center_id) self.assertEqual(result.message_code, constants.ONE_MORE_REGISTRATION_ON_PHONE) models.Registration.objects.get(citizen=self.citizen)
def test_phone_has_max_registrations(self): number = '12345678' RegistrationFactory(sms__from_number=number, archive_time=None) new_sms = SMSFactory(from_number=number) result = process_registration_request( sms=new_sms, national_id=self.citizen.national_id, center_id=self.center.center_id) self.assertEqual(result.message_code, constants.TOO_MANY_REGISTRATIONS_ON_PHONE) with self.assertRaises(models.Registration.DoesNotExist): models.Registration.objects.get(citizen=self.citizen)
def test_anonymize_outgoing(self): citizen = CitizenFactory() sms = SMSFactory( from_number='7', to_number='6', message='Hey man let\'s vote', citizen=citizen, uuid='278348723478234', direction=OUTGOING, need_to_anonymize=True, ) sms.save() SMS.objects.filter(pk=sms.pk).anonymize() sms = SMS.objects.get(pk=sms.pk) # only anonymize the 'to' number for outgoing self.assertEqual('7', sms.from_number) self.assertEqual('', sms.to_number) self.assertEqual('', sms.message) self.assertIsNone(sms.citizen) self.assertEqual('', sms.uuid) self.assertFalse(sms.need_to_anonymize)
def test_complex_example(self): # Request page 3 of an 8 page listing. Make sure that page 2 isn't included twice (for being # in head and being a surrounding page), and also test that the proper pages are elided # after the surrounding pages. SMSFactory.create_batch(size=8) request = self.create_request(page=3) paginator_links = self.browse_view(request).context_data['paginator_links'] page_1_url = self.url + '?page=1' page_2_url = self.url + '?page=2' page_4_url = self.url + '?page=4' page_7_url = self.url + '?page=7' page_8_url = self.url + '?page=8' expected_links = [ [page_1_url, 1], [page_2_url, 2], [None, 3], [page_4_url, 4], [None, None], # ellipsis # page 6 is covered by the ellipsis [page_7_url, 7], [page_8_url, 8], ] self.assertEqual(paginator_links, expected_links)
def add_message(self, phone_number, message_code): """ Add a fake outgoing SMS message as if we sent it, to the given phone number, with the given message code. Set the dates each time to at least 1 second later than any previous date. """ self.last_timestamp += ONE_SECOND SMSFactory( message_code=message_code, to_number=phone_number, direction=OUTGOING, creation_date=self.last_timestamp, modification_date=self.last_timestamp, )
def test_complex_example(self): # Request page 3 of an 8 page listing. Make sure that page 2 isn't included twice (for being # in head and being a surrounding page), and also test that the proper pages are elided # after the surrounding pages. SMSFactory.create_batch(size=8) request = self.create_request(page=3) paginator_links = self.browse_view( request).context_data['paginator_links'] page_1_url = self.url + '?page=1' page_2_url = self.url + '?page=2' page_4_url = self.url + '?page=4' page_7_url = self.url + '?page=7' page_8_url = self.url + '?page=8' expected_links = [ [page_1_url, 1], [page_2_url, 2], [None, 3], [page_4_url, 4], [None, None], # ellipsis # page 6 is covered by the ellipsis [page_7_url, 7], [page_8_url, 8], ] self.assertEqual(paginator_links, expected_links)
def test_register_after_unconfirmed_registrations(self): # We might have unconfirmed registrations due to previous changes. # Create 2 registrations for this Citizen RegistrationFactory(citizen=self.citizen, archive_time=now()) RegistrationFactory(citizen=self.citizen, archive_time=now(), deleted=True) RegistrationFactory(citizen=self.citizen, archive_time=None, deleted=True) RegistrationFactory(citizen=self.citizen, archive_time=None) # Process another registration update process_registration_request(sms=SMSFactory(), national_id=self.citizen.national_id, center_id=self.center.center_id) # There should be only one confirmed registration registrations = models.Registration.objects.filter( citizen=self.citizen) self.assertEqual(1, registrations.count())
def test_attempt_update_wrong_from_number_same_center( self, registration_open): # create a valid registration sms = SMSFactory(from_number=self.number, citizen=self.citizen) RegistrationFactory(citizen=self.citizen, registration_center=self.center, archive_time=None, sms=sms) # try to register at same center with a new number new_number = '919-888-8888' msg = "{nid}#{center}".format(nid=self.good_nid, center=self.center.center_id) new_conn = self.create_connection(data={'identity': new_number}) self.receive(msg, new_conn, fields=self.fields) # message should have the existing number in it (not new_number) context = {'centre': self.center.name, 'number': self.number[-4:]} expected = self.translate(constants.MESSAGE_2, context=context) # arabic self.assertEqual(self.get_last_response_message(), expected)
def test_update_registration(self): registration = models.Registration(citizen=self.citizen, archive_time=None, sms=self.sms, registration_center=self.center) registration.save() # same number sends new sms new_sms = SMSFactory(from_number=self.sms.from_number) new_center = RegistrationCenterFactory() result = process_registration_request( sms=new_sms, national_id=self.citizen.national_id, center_id=new_center.center_id) # There should be only one registration for this user and should have been updated registrations = models.Registration.objects.filter( citizen=self.citizen) self.assertEqual(1, registrations.count()) self.assertEqual(registrations[0].registration_center, new_center) # We tell the user that everything went well self.assertEqual(result.message_code, constants.MESSAGE_1)
def test_user_already_registered(self): """New registration for same user from different phone""" # Must be unlocked to update reg from different phone registration = models.Registration( citizen=self.citizen, registration_center=self.center, archive_time=None, sms=self.sms, unlocked_until=now() + datetime.timedelta(hours=1), ) registration.save() new_sms = SMSFactory() result = process_registration_request( sms=new_sms, national_id=self.citizen.national_id, center_id=self.center.center_id) # There should be only one registration for this new user new_registration = models.Registration.objects.get( citizen=self.citizen) # The registering phone number was updated self.assertEqual(new_sms.from_number, new_registration.sms.from_number) # We tell the user that everything went well self.assertEqual(result.message_code, constants.MESSAGE_1)
def test_get_message_code_display(self): """SMS.get_message_code_display returns label of corresponding MessageText object.""" msg = MessageText.objects.create(number=23, label='TWENTY_THREE') sms = SMSFactory(message_code=msg.number) self.assertEqual(msg.label, sms.get_message_code_display())
def test_tail_pages_have_links(self): SMSFactory.create_batch(size=8) paginator_links = self.browse_view(self.request).context_data['paginator_links'] page_8_url = self.url + '?page=8' self.assertIn([page_8_url, 8], paginator_links)
def setUp(self): self.registrations_per_center = 4 self.oil_center_period_1_voters = 1 self.oil_center_period_2_voters = 2 self.offices = [OfficeFactory(region=Office.REGION_EAST), OfficeFactory(region=Office.REGION_WEST)] # Note: An oil center doesn't normally allow registrations, but it does so for # this testcase. self.oil_center = RegistrationCenterFactory(office=self.offices[0], center_type=RegistrationCenter.Types.OIL) # !reg_open won't affect election day counts but it will affect whether # or not any registrations are found self.inactive_for_reg_center = RegistrationCenterFactory(office=self.offices[1], reg_open=False) self.centers = [self.oil_center, RegistrationCenterFactory(office=self.offices[0]), RegistrationCenterFactory(office=self.offices[0]), RegistrationCenterFactory(office=self.offices[1]), self.inactive_for_reg_center, ] copy_center = RegistrationCenterFactory(office=self.offices[1], copy_of=self.centers[3]) self.centers.append(copy_center) self.election_decoy_before = ElectionFactory( name_english='decoy before', name_arabic='decoy before (ar)', polling_start_time=now() - timedelta(days=10), polling_end_time=now() - timedelta(days=9), ) self.election = ElectionFactory( name_english='%s election' % type(self).__name__, name_arabic='not Arabic', polling_start_time=now() - timedelta(hours=2), polling_end_time=now() + timedelta(hours=2), ) self.election_decoy_after = ElectionFactory( name_english='decoy after', name_arabic='decoy after (ar)', polling_start_time=now() + timedelta(days=9), polling_end_time=now() + timedelta(days=10), ) self.center_opens = [] for center in self.centers: if center != self.centers[1]: self.center_opens.append(CenterOpenFactory(election=self.election, registration_center=center)) # CenterOpen may refer to a deleted center. Make sure that we don't find those self.deleted_center = RegistrationCenterFactory(office=self.offices[0], deleted=True) self.center_open_referring_to_deleted_center = CenterOpenFactory( election=self.election, registration_center=self.deleted_center) # Performance enhancement: this dummy person and SMS allow me to avoid creation of two # spurious objects for each registration I create. self.citizen = CitizenFactory() self.sms = SMSFactory(citizen=self.citizen) # Create registrations, but be careful not to create any at the copy center # or at the center which doesn't support registrations. self.registrations = [] for center in self.centers: if center.reg_open and not center.copy_of: self.registrations += \ RegistrationFactory.create_batch(self.registrations_per_center, citizen=self.citizen, sms=self.sms, registration_center=center) # These reports include quirks such as multiple reports for a center (very common in real # life), a missing final period report, and multiple reports for the same center & period. self.reports = [ PollingReportFactory(election=self.election, registration_center=self.oil_center, period_number=FIRST_PERIOD_NUMBER, num_voters=self.oil_center_period_1_voters), PollingReportFactory(election=self.election, registration_center=self.oil_center, period_number=FIRST_PERIOD_NUMBER + 1, num_voters=self.oil_center_period_2_voters), PollingReportFactory(election=self.election, registration_center=self.centers[2], period_number=FIRST_PERIOD_NUMBER, num_voters=1), # The next two reports are for the same center & period with different num_voters # to exercise the code that sorts by modification_date. PollingReportFactory(election=self.election, registration_center=self.centers[2], period_number=FIRST_PERIOD_NUMBER + 1, num_voters=4), PollingReportFactory(election=self.election, registration_center=self.centers[2], period_number=FIRST_PERIOD_NUMBER + 1, num_voters=6), PollingReportFactory(election=self.election, registration_center=self.centers[3], period_number=FIRST_PERIOD_NUMBER, num_voters=1), PollingReportFactory(election=self.election, registration_center=self.centers[3], period_number=FIRST_PERIOD_NUMBER + 1, num_voters=4), # This report for a deleted center should be ignored PollingReportFactory(election=self.election, registration_center=self.deleted_center, period_number=FIRST_PERIOD_NUMBER + 1, num_voters=50), PollingReportFactory(election=self.election, registration_center=self.inactive_for_reg_center, period_number=FIRST_PERIOD_NUMBER + 1, num_voters=50), # This report for a copy center should count towards the original/parent center PollingReportFactory(election=self.election, registration_center=copy_center, period_number=LAST_PERIOD_NUMBER, num_voters=1), ] self.result = generate_election_day_hq_reports(self.election) # Create an alternate result which reflects that the "oil center" is # marked inactive for this election. self.inactive_on_election = CenterClosedForElection( registration_center=self.oil_center, election=self.election ) self.inactive_on_election.full_clean() self.inactive_on_election.save() self.result_with_inactive = generate_election_day_hq_reports(self.election)
def test_tail_pages_have_links(self): SMSFactory.create_batch(size=8) paginator_links = self.browse_view( self.request).context_data['paginator_links'] page_8_url = self.url + '?page=8' self.assertIn([page_8_url, 8], paginator_links)
def test_dont_get_deleted_sms_by_default(self): sms = SMSFactory(deleted=True) self.assertNotIn(sms, SMS.objects.all())
def test_head_pages_have_links(self): SMSFactory.create_batch(size=2) paginator_links = self.browse_view(self.request).context_data['paginator_links'] page_2_url = self.url + '?page=2' self.assertEqual(paginator_links, [[None, 1], [page_2_url, 2]])
def test_head_pages_have_links(self): SMSFactory.create_batch(size=2) paginator_links = self.browse_view( self.request).context_data['paginator_links'] page_2_url = self.url + '?page=2' self.assertEqual(paginator_links, [[None, 1], [page_2_url, 2]])