def setUp(self): self.conn = self.lookup_connections(identities='111')[0] self.good_nid = get_random_number_string(length=constants.NID_LENGTH) self.fields = {'to_addr': settings.REGISTRATION_SHORT_CODE} self.msg = u"%s" % (self.good_nid) self.election = ElectionFactory(polling_start_time=PAST_DAY, polling_end_time=FUTURE_DAY)
def setUp(self): # lookup_connections takes any identity and creates connections. # It's better than create_connection because it uses 'mockbackend' # which keeps track of sent messages. self.conn = self.lookup_connections(identities=['111'])[0] self.good_nid = get_random_number_string(length=constants.NID_LENGTH) self.good_center_id = get_random_number_string( length=constants.CENTER_ID_LENGTH) self.fields = {'to_addr': settings.REGISTRATION_SHORT_CODE} self.reg_period = RegistrationPeriodFactory(start_time=PAST_DAY, end_time=FUTURE_DAY) self.election = ElectionFactory(polling_start_time=PAST_DAY, polling_end_time=FUTURE_DAY)
def setUp(self): self.original = RegistrationCenterFactory() self.copy = RegistrationCenterFactory(copy_of=self.original) self.polling_locations = get_all_polling_locations() self.election = ElectionFactory( polling_start_time=now() - datetime.timedelta(hours=1), polling_end_time=now() + datetime.timedelta(hours=1), ) # add decoy elections before/after the real one self.decoy_before_election = ElectionFactory( polling_start_time=self.election.polling_start_time - datetime.timedelta(days=5), polling_end_time=self.election.polling_end_time - datetime.timedelta(days=5), ) self.decoy_after_election = ElectionFactory( polling_start_time=self.election.polling_start_time + datetime.timedelta(days=5), polling_end_time=self.election.polling_end_time + datetime.timedelta(days=5), ) self.test_office_1 = 1 self.test_office_2 = 2 self.test_region = 3 self.polling_centers = { '11001': { 'polling_center_code': 11001, 'office_id': self.test_office_1, 'subconstituency_id': 2, 'region': Office.REGION_NAMES[self.test_region], 'country': 'Libya' }, '11002': { 'polling_center_code': 11002, 'office_id': self.test_office_2, 'subconstituency_id': 2, 'region': Office.REGION_NAMES[self.test_region], 'country': 'Libya' }, '11003': { 'polling_center_code': 11003, 'office_id': self.test_office_1, 'subconstituency_id': 2, 'region': Office.REGION_NAMES[self.test_region], 'country': 'Libya' } } self.center_opens = [] self.center_reports = [] self.inactive_for_election = ['11003']
def test(self): center = RegistrationCenterFactory() elections = [ { 'polling_start_time': now() - datetime.timedelta(days=60) }, { 'polling_start_time': now() - datetime.timedelta(days=40) }, { 'polling_start_time': now() - datetime.timedelta(days=20) }, ] for election in elections: election['polling_end_time'] = \ election['polling_start_time'] + datetime.timedelta(hours=6) election['object'] = ElectionFactory( polling_start_time=election['polling_start_time'], polling_end_time=election['polling_end_time'], ) election['staff_phone_1'] = StaffPhoneFactory( registration_center=center, creation_date=election['object'].work_start_time) election['staff_phone_2'] = StaffPhoneFactory( registration_center=center, creation_date=election['object'].work_end_time) for i, election in enumerate(elections, start=1): messages_for_center = message_log( election['object'])[center.center_id] self.assertEqual(len(messages_for_center), i * 2) # check for other junk leaking into the testcase for message in messages_for_center: self.assertEqual(message['type'], 'phonelink')
def setUp(self): subconstituency_name = os.environ.get('ROLLGEN_TEST_SUBCONSTITUENCY_NAME', '') subconstituency_name = subconstituency_name.decode('utf-8') if not subconstituency_name: subconstituency_name = generate_arabic_place_name() center_name = os.environ.get('ROLLGEN_TEST_CENTER_NAME', '') center_name = center_name.decode('utf-8') if not center_name: center_name = generate_arabic_place_name() subconstituency = SubConstituencyFactory(name_arabic=subconstituency_name) self.center = RegistrationCenterFactory(subconstituency=subconstituency, name=center_name) # For the center that has copies, I give it the max number of copies possible in order # to force the 'copied by' string to be as long as possible to reveal any line wrapping # problems that result. self.original_center = RegistrationCenterFactory() self.copy_centers = RegistrationCenterFactory.create_batch(settings.N_MAX_COPY_CENTERS, copy_of=self.original_center) self.election = ElectionFactory()
def setUp(self): self.election = ElectionFactory() self.center = RegistrationCenterFactory(name=generate_arabic_place_name()) self.office_id = self.center.office.id # Create a bunch of voters registered at each of these centers. The number of voters # matters somewhat. # station_distributor() will create a unisex station under certain conditions if # there are < N male or female voters, where N = UNISEX_TRIGGER (currently 25). The # names of the generated PDFs (which this code tests) have the gender embedded, so if I # change the # of voters and that causes a unisex station to be created, the filenames of # the generated PDFs will be different than these tests expect so the tests will fail. # I use a number of voters that guarantees I won't create a unisex station. n_voters = (settings.ROLLGEN_UNISEX_TRIGGER * 2) + 2 self.voters = create_voters(n_voters, center=self.center) self.password = '******' self.user = UserFactory(password=self.password) # Each test gets a fresh work dir. self.output_path = tempfile.mkdtemp() self.input_arguments = INPUT_ARGUMENTS_TEMPLATE.copy() self.input_arguments['center_ids'] = [self.center.center_id]
def setUp(self): self.NUMBER = get_random_phone_number() # Most tests need the number whitelisted, so whitelist by default WhitelistFactory(phone_number=self.NUMBER) self.election = ElectionFactory( polling_start_time=now() - timedelta(hours=1), polling_end_time=now() + timedelta(hours=1), )
def setUp(self): # lookup_connections takes any identity and creates connections. # It's better than create_connection because it uses 'mockbackend' # which keeps track of sent messages. self.conn = self.lookup_connections(identities=['111'])[0] self.good_nid = get_random_number_string(length=constants.NID_LENGTH) self.good_center_id = get_random_number_string(length=constants.CENTER_ID_LENGTH) self.fields = {'to_addr': settings.REGISTRATION_SHORT_CODE} self.reg_period = RegistrationPeriodFactory(start_time=PAST_DAY, end_time=FUTURE_DAY) self.election = ElectionFactory(polling_start_time=PAST_DAY, polling_end_time=FUTURE_DAY)
def setUp(self): self.url = reverse('check_registration') self.user = UserFactory(username='******', password='******') self.client.login(username='******', password='******') # captcha has 2 form fields, _0 is a key, _1 is the text entered by the user self.captcha = {'captcha_0': 'dummy', 'captcha_1': 'PASSED'} self.registration = RegistrationPeriodFactory(start_time=PAST_DAY, end_time=PAST_DAY) self.election = ElectionFactory(polling_start_time=FUTURE_DAY, polling_end_time=FUTURE_DAY)
def setUp(self): super(PrelimVoteReportTestPhoneActivated, self).setUp() self.center = RegistrationCenterFactory() # Activate the phone to the center: StaffPhone.objects.create(phone_number=self.NUMBER, registration_center=self.center) self.election = ElectionFactory( polling_start_time=now() - timedelta(hours=2), polling_end_time=now() + timedelta(hours=2), )
class QueryDuringRegistration(LibyaRapidTest): """ Voter query should work any time. """ def setUp(self): self.conn = self.lookup_connections(identities='111')[0] self.good_nid = get_random_number_string(length=constants.NID_LENGTH) self.fields = {'to_addr': settings.REGISTRATION_SHORT_CODE} self.msg = u"%s" % (self.good_nid) self.election = ElectionFactory(polling_start_time=PAST_DAY, polling_end_time=FUTURE_DAY) def test_query_before_reg_opens(self, mock_lookup): RegistrationPeriodFactory(start_time=FUTURE_DAY, end_time=FUTURE_DAY) self.receive(self.msg, self.conn, fields=self.fields) self.assertTrue(mock_lookup.called) def test_query_during_reg(self, mock_lookup): RegistrationPeriodFactory(start_time=PAST_DAY, end_time=FUTURE_DAY) mock_lookup.return_value = Result('1', constants.VOTER_QUERY_NOT_FOUND) self.receive(self.msg, self.conn, fields=self.fields) self.assertTrue(mock_lookup.called) def test_query_after_reg_closes(self, mock_lookup): # after reg closes but before polling is over self.election.polling_start_time = FUTURE_DAY self.election.save() RegistrationPeriodFactory(start_time=PAST_DAY, end_time=PAST_DAY) mock_lookup.return_value = Result('1', constants.VOTER_QUERY_NOT_FOUND) self.receive(self.msg, self.conn, fields=self.fields) self.assertTrue(mock_lookup.called) def test_query_after_polling(self, mock_lookup): # after polling is over, voters can still check their registrations RegistrationPeriodFactory(start_time=PAST_DAY, end_time=PAST_DAY) self.election.polling_end_time = PAST_DAY self.election.save() self.receive(self.msg, self.conn, fields=self.fields) self.assertTrue(mock_lookup.called)
def test_after_election(self, processor): # can still query registration after election RegistrationPeriodFactory(start_time=PAST_DAY, end_time=PAST_DAY) ElectionFactory(polling_start_time=PAST_DAY, polling_end_time=PAST_DAY) io_table = [ (self.garbage, constants.REGISTRATION_NOT_OPEN), (unicode(self.bad_nid), constants.VOTER_QUERY_NID_WRONG_LENGTH), (unicode(self.good_nid), constants.VOTER_QUERY_REGISTERED_AT), ] result = Mock(message="success", message_code=constants.VOTER_QUERY_REGISTERED_AT) processor.return_value = result for incoming_message, expected_code in io_table: self.receive(incoming_message, self.conn, fields=self.fields) self.assertEqual(self.get_last_response_code(), expected_code)
def setUp(self): super(TestPollingCSVs, self).setUp() # Jam a comma in one of the fields that appears in the CSV to exercise the code's # ability to escape the delimiter correctly. self.center.name = ',' + self.center.name self.center.save() job = Job('polling', [self.center], self.input_arguments, self.user.username, self.output_path) job.generate_rolls() # Create a station related to an older election in a (hopefully unsuccessful) attempt to # confuse the code that creates the polling metadata CSV. start = django_now() start = start.replace(year=start.year - 1) end = start.replace(year=start.year - 1) + datetime.timedelta(days=1) old_election = ElectionFactory(polling_start_time=start, polling_end_time=end) old_center = RegistrationCenterFactory() Station(election=old_election, center=old_center, number=1, gender=FEMALE, n_registrants=42, first_voter_name='first', first_voter_number=1, last_voter_name='last', last_voter_number=42)
def test_dont_get_deleted_election_by_default(self): election = ElectionFactory(deleted=True) self.assertNotIn(election, Election.objects.all())
class HandlerTest(LibyaRapidTest): def setUp(self): # lookup_connections takes any identity and creates connections. # It's better than create_connection because it uses 'mockbackend' # which keeps track of sent messages. self.conn = self.lookup_connections(identities=['111'])[0] self.good_nid = get_random_number_string(length=constants.NID_LENGTH) self.good_center_id = get_random_number_string(length=constants.CENTER_ID_LENGTH) self.fields = {'to_addr': settings.REGISTRATION_SHORT_CODE} self.reg_period = RegistrationPeriodFactory(start_time=PAST_DAY, end_time=FUTURE_DAY) self.election = ElectionFactory(polling_start_time=PAST_DAY, polling_end_time=FUTURE_DAY) def test_new_logic_rename_me(self): phone1 = get_random_number_string(length=10) phone2 = get_random_number_string(length=10) nid1 = self.good_nid ppc1 = self.good_center_id ppc2 = get_random_number_string(length=constants.CENTER_ID_LENGTH) ppc3 = get_random_number_string(length=constants.CENTER_ID_LENGTH) ppc4 = get_random_number_string(length=constants.CENTER_ID_LENGTH) ppc5 = get_random_number_string(length=constants.CENTER_ID_LENGTH) CitizenFactory(national_id=nid1) RegistrationCenterFactory(center_id=ppc1) RegistrationCenterFactory(center_id=ppc2) RegistrationCenterFactory(center_id=ppc3) RegistrationCenterFactory(center_id=ppc4) RegistrationCenterFactory(center_id=ppc5) # Each item in the test_data array is one test. # Each test contains one or more steps. # Each step contains the phone we receive a message from, the # registration center code in that message, the expected response, # and the expected registration state after that message. # All messages are for the same NID. # After each test item, the registrations are reset (deleted). # MSG1: you are registered, use same phone to change # MSG4: only one more time # MSG5: that was your last time test_data = [ # Repeat the same registration from the same phone [ (phone1, ppc1, constants.MESSAGE_1, ppc1), (phone1, ppc1, constants.MESSAGE_1, ppc1), (phone1, ppc1, constants.MESSAGE_1, ppc1), (phone1, ppc1, constants.MESSAGE_1, ppc1), ], # Keep trying to change your registration from the same phone [ (phone1, ppc1, constants.MESSAGE_1, ppc1), (phone1, ppc2, constants.MESSAGE_1, ppc2), # one change is okay (phone1, ppc3, constants.MESSAGE_4, ppc3), # twice is okay but only one left (phone1, ppc4, constants.MESSAGE_5, ppc4), # three is okay but last time (phone1, ppc3, constants.MESSAGE_6, ppc4), # too many, sorry (phone1, ppc5, constants.MESSAGE_6, ppc4), # still too many ], # Repeat the same registration from a different phone [ (phone1, ppc1, constants.MESSAGE_1, ppc1), (phone2, ppc1, constants.MESSAGE_7, ppc1), (phone1, ppc1, constants.MESSAGE_1, ppc1), (phone2, ppc1, constants.MESSAGE_7, ppc1), (phone1, ppc1, constants.MESSAGE_1, ppc1), (phone2, ppc1, constants.MESSAGE_7, ppc1), ], # Try to change registration from a different phone [ (phone1, ppc1, constants.MESSAGE_1, ppc1), (phone2, ppc2, constants.MESSAGE_2, ppc1), # sorry charlie # then from the original phone (phone1, ppc2, constants.MESSAGE_1, ppc2), # that's ok - change 1 # again from another phone (phone2, ppc3, constants.MESSAGE_2, ppc2), # back to original phone (phone1, ppc3, constants.MESSAGE_4, ppc3), # change 2 - 1 left # try other phone again (phone2, ppc4, constants.MESSAGE_2, ppc3), # original phone again (phone1, ppc2, constants.MESSAGE_5, ppc2), # 3rd change is the last (phone1, ppc4, constants.MESSAGE_6, ppc2), # too many, sorry (phone1, ppc5, constants.MESSAGE_6, ppc2), # still too many # Once you've used up your changes, even sending your current # registration results in message 6 (phone1, ppc2, constants.MESSAGE_6, ppc2), ], # After changing the registration, the repeat count is reset [ (phone1, ppc1, constants.MESSAGE_1, ppc1), (phone1, ppc1, constants.MESSAGE_1, ppc1), # 2nd time - msg 1 (phone1, ppc1, constants.MESSAGE_1, ppc1), # 3rd time - msg 1 (enhanced) (phone1, ppc2, constants.MESSAGE_1, ppc2), # change #1 reg - reset counter (phone1, ppc2, constants.MESSAGE_1, ppc2), # 2nd time, same data as #1 change (phone1, ppc2, constants.MESSAGE_1, ppc2), # 3rd time, same data as #1 change (phone1, ppc3, constants.MESSAGE_4, ppc3), # change reg - reset counter (phone1, ppc2, constants.MESSAGE_5, ppc2), # final change (phone1, ppc2, constants.MESSAGE_6, ppc2), # no more changes, always 6 ], ] for one_test in test_data: # Reset state Registration.objects.unfiltered().delete() for from_phone, center_id, expected_response, expected_center_id in one_test: text = "%s*%s" % (nid1, center_id) conn = self.lookup_connections(identities=[from_phone])[0] self.receive(text, conn, fields=self.fields) # Check the response self.assertEqual(expected_response, self.get_last_response_code()) # Check the state reg = Registration.objects.get(citizen__national_id=nid1) self.assertEqual(int(expected_center_id), reg.registration_center.center_id) def test_input_triggers_proper_response(self): short_center_id = u'%s*%s' % ( self.good_nid, get_random_number_string(length=constants.CENTER_ID_LENGTH - 1)) long_center_id = u'%s*%s' % ( self.good_nid, get_random_number_string(length=constants.CENTER_ID_LENGTH + 1)) short_nid = u"%s*%s" % ( get_random_number_string(length=constants.NID_LENGTH - 1), self.good_center_id) long_nid = u"%s*%s" % ( get_random_number_string(length=constants.NID_LENGTH + 1), self.good_center_id) three_ids = u"%s*%s*123" % (self.good_nid, self.good_center_id) io_table = [ (u"garbage", constants.MESSAGE_INCORRECT), (get_random_number_string(), constants.VOTER_QUERY_NID_WRONG_LENGTH), (short_center_id, constants.RESPONSE_CENTER_ID_WRONG_LENGTH), (long_center_id, constants.RESPONSE_CENTER_ID_WRONG_LENGTH), (short_nid, constants.RESPONSE_NID_WRONG_LENGTH), (long_nid, constants.RESPONSE_NID_WRONG_LENGTH), (three_ids, constants.MESSAGE_INCORRECT), ] # send the messages for (input, _) in io_table: self.receive(input, self.conn, fields=self.fields) # strip out our split messages outputs = [o.fields['message_code'] for o in self.outbound if not o.fields.get('split')] for (i, (_, expected_output)) in enumerate(io_table): self.assertEqual(outputs[i], expected_output) def test_unexpected_error(self): with patch.object(PatternHandler, 'dispatch') as dispatch: dispatch.side_effect = ValueError self.receive("Anything", self.conn, fields=self.fields) self.assertEqual(self.outbound[0].fields['message_code'], constants.RESPONSE_SERVER_ERROR) @patch('register.handlers.process_registration_request', autospec=True) def test_valid_nid(self, mock_prr): center_name = u"A Random Center" person_name = u"A Random Name" msg = u"%s*%s" % (self.good_nid, self.good_center_id) mock_prr.return_value = Result('', constants.RESPONSE_VALID_REGISTRATION, dict(person=person_name, centre=center_name, code=int(self.good_center_id))) self.receive(msg, self.conn, fields=self.fields) self.assertEqual(self.outbound[0].fields['message_code'], constants.RESPONSE_VALID_REGISTRATION) # message was saved sms = SMS.objects.get(message=msg) self.assertEqual(SMS.REGISTRATION, sms.msg_type) # response was saved sms = SMS.objects.filter(to_number=self.conn.identity) self.assertNotEqual(sms.count(), 0) @patch('register.processors.process_registration_request', autospec=True) def test_invalid_center_id(self, mock_prr): msg = u"%s*%s" % (self.good_nid, self.good_center_id) mock_prr.return_value = Result('', constants.RESPONSE_CENTER_ID_INVALID) self.receive(msg, self.conn, fields=self.fields) self.assertEqual(self.get_last_response_code(), constants.RESPONSE_CENTER_ID_INVALID) @patch('register.handlers.registration_allowed') def test_outside_registration_period(self, mock_is_open): mock_is_open.return_value = False RegistrationCenterFactory(center_id=self.good_center_id) msg = u"%s*%s" % (self.good_nid, self.good_center_id) self.receive(msg, self.conn, fields=self.fields) self.assertEqual(self.get_last_response_code(), constants.REGISTRATION_NOT_OPEN) def test_not_started(self): self.reg_period.start_time = FUTURE_DAY self.reg_period.save() RegistrationCenterFactory(center_id=self.good_center_id) msg = u"%s*%s" % (self.good_nid, self.good_center_id) self.receive(msg, self.conn, fields=self.fields) self.assertEqual(self.get_last_response_code(), constants.REGISTRATION_NOT_OPEN) def test_has_ended(self): self.reg_period.end_time = PAST_DAY self.reg_period.save() self.election.polling_end_time = PAST_DAY self.election.save() RegistrationCenterFactory(center_id=self.good_center_id) msg = u"%s*%s" % (self.good_nid, self.good_center_id) self.receive(msg, self.conn, fields=self.fields) self.assertEqual(self.get_last_response_code(), constants.REGISTRATION_NOT_OPEN) def test_we_only_handle_our_shortcode(self): msg = u"garbage" not_our_shortcode = '11111' self.receive(msg, self.conn, fields={'to_addr': not_our_shortcode}) # We do send a default response, but we test that more below. self.assertEqual(1, len(self.full_outbound())) def test_that_we_save_incoming_sms_when_closed(self): self.reg_period.start_time = FUTURE_DAY self.reg_period.save() self.election.polling_start_time = FUTURE_DAY self.election.save() msg = u"garbage" for shortcode in set((settings.REGISTRATION_SHORT_CODE, settings.VOTER_QUERY_SHORT_CODE, settings.REPORTS_SHORT_CODE)): self.receive(msg, self.conn, fields={'to_addr': shortcode}) # test that we save the incoming SMS incoming = SMS.objects.filter(to_number=shortcode) self.assertEqual(len(incoming), 1)
def setUp(self): # Need a superuser get_user_model().objects.create_superuser(username="******", email="*****@*****.**", password="******") self.election = ElectionFactory()
def get_or_create_election(stub): """Return a current election if one exists, or create a new one using ElectionFactory""" election = Election.objects.get_most_current_election() return election if election else ElectionFactory()
def setUp(self): self.staff_user = UserFactory() self.staff_user.is_staff = True self.staff_user.save() assert self.client.login(username=self.staff_user.username, password=DEFAULT_USER_PASSWORD) self.reporting_user = test_reports.TEST_USERNAME self.reporting_password = test_reports.TEST_PASSWORD REPORT_USER_DB[self.reporting_user] = self.reporting_password # Pick a start time that represents different days in Libya vs UTC tz = timezone(settings.TIME_ZONE) polling_start_time = astz(FUTURE_DAY.replace(hour=22), tz) polling_end_time = tz.normalize(polling_start_time + timedelta(hours=16)) self.election = ElectionFactory( polling_start_time=polling_start_time, polling_end_time=polling_end_time, ) self.election_day_dt = self.election.polling_start_time # Create "decoy" election just to confirm that it doesn't break reports. decoy_start_time = tz.normalize(polling_start_time - timedelta(days=10)) decoy_end_time = tz.normalize(decoy_start_time + timedelta(hours=16)) ElectionFactory( polling_start_time=decoy_start_time, polling_end_time=decoy_end_time, ) self.all_centers = [] self.rc_1 = RegistrationCenterFactory() self.all_centers.append(self.rc_1) self.rc_2 = RegistrationCenterFactory() self.all_centers.append(self.rc_2) self.rc_3 = RegistrationCenterFactory() self.all_centers.append(self.rc_3) self.rc_4 = RegistrationCenterFactory() self.all_centers.append(self.rc_4) self.copy_of_rc_1 = RegistrationCenterFactory(copy_of=self.rc_1, office=self.rc_1.office) self.all_centers.append(self.copy_of_rc_1) # rc_5 is inactive for this election self.rc_5 = RegistrationCenterFactory(office=self.rc_1.office) self.all_centers.append(self.rc_5) inactive_on_election = CenterClosedForElection( registration_center=self.rc_5, election=self.election) inactive_on_election.full_clean() inactive_on_election.save() self.all_office_ids = [center.office_id for center in self.all_centers] self.carrier_1 = BackendFactory() self.citizen_1 = CitizenFactory() # Create registrations on the 4 days leading up to election day # Put the registrations at different hours of the day to stress TZ handling. self.registration_dates = [] self.registration_date_strs = [] hour_of_day = 0 for delta_days in range(10, 4, -1): assert hour_of_day < 24 reg_date = astz(self.election_day_dt - timedelta(days=delta_days), tz)\ .replace(hour=hour_of_day) hour_of_day += 4 self.registration_dates.append(reg_date) self.registration_date_strs.append(reg_date.strftime('%Y-%m-%d')) self.yesterday_date, _ = calc_yesterday(self.registration_date_strs) self.yesterday_date_dm = self.yesterday_date.strftime('%d/%m') # yesterday_date is a date; get a datetime form self.yesterday_date_dt = tz.localize( datetime(self.yesterday_date.year, self.yesterday_date.month, self.yesterday_date.day, 0, 0, 0)) self.staff_phone_number = STAFF_PHONE_NUMBER_PATTERN % 12345
class HandlerTest(LibyaRapidTest): def setUp(self): # lookup_connections takes any identity and creates connections. # It's better than create_connection because it uses 'mockbackend' # which keeps track of sent messages. self.conn = self.lookup_connections(identities=['111'])[0] self.good_nid = get_random_number_string(length=constants.NID_LENGTH) self.good_center_id = get_random_number_string( length=constants.CENTER_ID_LENGTH) self.fields = {'to_addr': settings.REGISTRATION_SHORT_CODE} self.reg_period = RegistrationPeriodFactory(start_time=PAST_DAY, end_time=FUTURE_DAY) self.election = ElectionFactory(polling_start_time=PAST_DAY, polling_end_time=FUTURE_DAY) def test_new_logic_rename_me(self): phone1 = get_random_number_string(length=10) phone2 = get_random_number_string(length=10) nid1 = self.good_nid ppc1 = self.good_center_id ppc2 = get_random_number_string(length=constants.CENTER_ID_LENGTH) ppc3 = get_random_number_string(length=constants.CENTER_ID_LENGTH) ppc4 = get_random_number_string(length=constants.CENTER_ID_LENGTH) ppc5 = get_random_number_string(length=constants.CENTER_ID_LENGTH) CitizenFactory(national_id=nid1) RegistrationCenterFactory(center_id=ppc1) RegistrationCenterFactory(center_id=ppc2) RegistrationCenterFactory(center_id=ppc3) RegistrationCenterFactory(center_id=ppc4) RegistrationCenterFactory(center_id=ppc5) # Each item in the test_data array is one test. # Each test contains one or more steps. # Each step contains the phone we receive a message from, the # registration center code in that message, the expected response, # and the expected registration state after that message. # All messages are for the same NID. # After each test item, the registrations are reset (deleted). # MSG1: you are registered, use same phone to change # MSG4: only one more time # MSG5: that was your last time test_data = [ # Repeat the same registration from the same phone [ (phone1, ppc1, constants.MESSAGE_1, ppc1), (phone1, ppc1, constants.MESSAGE_1, ppc1), (phone1, ppc1, constants.MESSAGE_1, ppc1), (phone1, ppc1, constants.MESSAGE_1, ppc1), ], # Keep trying to change your registration from the same phone [ (phone1, ppc1, constants.MESSAGE_1, ppc1), (phone1, ppc2, constants.MESSAGE_1, ppc2), # one change is okay (phone1, ppc3, constants.MESSAGE_4, ppc3), # twice is okay but only one left (phone1, ppc4, constants.MESSAGE_5, ppc4), # three is okay but last time (phone1, ppc3, constants.MESSAGE_6, ppc4), # too many, sorry (phone1, ppc5, constants.MESSAGE_6, ppc4), # still too many ], # Repeat the same registration from a different phone [ (phone1, ppc1, constants.MESSAGE_1, ppc1), (phone2, ppc1, constants.MESSAGE_7, ppc1), (phone1, ppc1, constants.MESSAGE_1, ppc1), (phone2, ppc1, constants.MESSAGE_7, ppc1), (phone1, ppc1, constants.MESSAGE_1, ppc1), (phone2, ppc1, constants.MESSAGE_7, ppc1), ], # Try to change registration from a different phone [ (phone1, ppc1, constants.MESSAGE_1, ppc1), (phone2, ppc2, constants.MESSAGE_2, ppc1), # sorry charlie # then from the original phone (phone1, ppc2, constants.MESSAGE_1, ppc2 ), # that's ok - change 1 # again from another phone (phone2, ppc3, constants.MESSAGE_2, ppc2), # back to original phone (phone1, ppc3, constants.MESSAGE_4, ppc3), # change 2 - 1 left # try other phone again (phone2, ppc4, constants.MESSAGE_2, ppc3), # original phone again (phone1, ppc2, constants.MESSAGE_5, ppc2 ), # 3rd change is the last (phone1, ppc4, constants.MESSAGE_6, ppc2), # too many, sorry (phone1, ppc5, constants.MESSAGE_6, ppc2), # still too many # Once you've used up your changes, even sending your current # registration results in message 6 (phone1, ppc2, constants.MESSAGE_6, ppc2), ], # After changing the registration, the repeat count is reset [ (phone1, ppc1, constants.MESSAGE_1, ppc1), (phone1, ppc1, constants.MESSAGE_1, ppc1), # 2nd time - msg 1 (phone1, ppc1, constants.MESSAGE_1, ppc1), # 3rd time - msg 1 (enhanced) (phone1, ppc2, constants.MESSAGE_1, ppc2), # change #1 reg - reset counter (phone1, ppc2, constants.MESSAGE_1, ppc2), # 2nd time, same data as #1 change (phone1, ppc2, constants.MESSAGE_1, ppc2), # 3rd time, same data as #1 change (phone1, ppc3, constants.MESSAGE_4, ppc3), # change reg - reset counter (phone1, ppc2, constants.MESSAGE_5, ppc2), # final change (phone1, ppc2, constants.MESSAGE_6, ppc2), # no more changes, always 6 ], ] for one_test in test_data: # Reset state Registration.objects.unfiltered().delete() for from_phone, center_id, expected_response, expected_center_id in one_test: text = "%s*%s" % (nid1, center_id) conn = self.lookup_connections(identities=[from_phone])[0] self.receive(text, conn, fields=self.fields) # Check the response self.assertEqual(expected_response, self.get_last_response_code()) # Check the state reg = Registration.objects.get(citizen__national_id=nid1) self.assertEqual(int(expected_center_id), reg.registration_center.center_id) def test_input_triggers_proper_response(self): short_center_id = u'%s*%s' % ( self.good_nid, get_random_number_string(length=constants.CENTER_ID_LENGTH - 1)) long_center_id = u'%s*%s' % ( self.good_nid, get_random_number_string(length=constants.CENTER_ID_LENGTH + 1)) short_nid = u"%s*%s" % (get_random_number_string( length=constants.NID_LENGTH - 1), self.good_center_id) long_nid = u"%s*%s" % (get_random_number_string( length=constants.NID_LENGTH + 1), self.good_center_id) three_ids = u"%s*%s*123" % (self.good_nid, self.good_center_id) io_table = [ (u"garbage", constants.MESSAGE_INCORRECT), (get_random_number_string(), constants.VOTER_QUERY_NID_WRONG_LENGTH), (short_center_id, constants.RESPONSE_CENTER_ID_WRONG_LENGTH), (long_center_id, constants.RESPONSE_CENTER_ID_WRONG_LENGTH), (short_nid, constants.RESPONSE_NID_WRONG_LENGTH), (long_nid, constants.RESPONSE_NID_WRONG_LENGTH), (three_ids, constants.MESSAGE_INCORRECT), ] # send the messages for (input, _) in io_table: self.receive(input, self.conn, fields=self.fields) # strip out our split messages outputs = [ o.fields['message_code'] for o in self.outbound if not o.fields.get('split') ] for (i, (_, expected_output)) in enumerate(io_table): self.assertEqual(outputs[i], expected_output) def test_unexpected_error(self): with patch.object(PatternHandler, 'dispatch') as dispatch: dispatch.side_effect = ValueError self.receive("Anything", self.conn, fields=self.fields) self.assertEqual(self.outbound[0].fields['message_code'], constants.RESPONSE_SERVER_ERROR) @patch('register.handlers.process_registration_request', autospec=True) def test_valid_nid(self, mock_prr): center_name = u"A Random Center" person_name = u"A Random Name" msg = u"%s*%s" % (self.good_nid, self.good_center_id) mock_prr.return_value = Result( '', constants.RESPONSE_VALID_REGISTRATION, dict(person=person_name, centre=center_name, code=int(self.good_center_id))) self.receive(msg, self.conn, fields=self.fields) self.assertEqual(self.outbound[0].fields['message_code'], constants.RESPONSE_VALID_REGISTRATION) # message was saved sms = SMS.objects.get(message=msg) self.assertEqual(SMS.REGISTRATION, sms.msg_type) # response was saved sms = SMS.objects.filter(to_number=self.conn.identity) self.assertNotEqual(sms.count(), 0) @patch('register.processors.process_registration_request', autospec=True) def test_invalid_center_id(self, mock_prr): msg = u"%s*%s" % (self.good_nid, self.good_center_id) mock_prr.return_value = Result('', constants.RESPONSE_CENTER_ID_INVALID) self.receive(msg, self.conn, fields=self.fields) self.assertEqual(self.get_last_response_code(), constants.RESPONSE_CENTER_ID_INVALID) @patch('register.handlers.registration_allowed') def test_outside_registration_period(self, mock_is_open): mock_is_open.return_value = False RegistrationCenterFactory(center_id=self.good_center_id) msg = u"%s*%s" % (self.good_nid, self.good_center_id) self.receive(msg, self.conn, fields=self.fields) self.assertEqual(self.get_last_response_code(), constants.REGISTRATION_NOT_OPEN) def test_not_started(self): self.reg_period.start_time = FUTURE_DAY self.reg_period.save() RegistrationCenterFactory(center_id=self.good_center_id) msg = u"%s*%s" % (self.good_nid, self.good_center_id) self.receive(msg, self.conn, fields=self.fields) self.assertEqual(self.get_last_response_code(), constants.REGISTRATION_NOT_OPEN) def test_has_ended(self): self.reg_period.end_time = PAST_DAY self.reg_period.save() self.election.polling_end_time = PAST_DAY self.election.save() RegistrationCenterFactory(center_id=self.good_center_id) msg = u"%s*%s" % (self.good_nid, self.good_center_id) self.receive(msg, self.conn, fields=self.fields) self.assertEqual(self.get_last_response_code(), constants.REGISTRATION_NOT_OPEN) def test_we_only_handle_our_shortcode(self): msg = u"garbage" not_our_shortcode = '11111' self.receive(msg, self.conn, fields={'to_addr': not_our_shortcode}) # We do send a default response, but we test that more below. self.assertEqual(1, len(self.full_outbound())) def test_that_we_save_incoming_sms_when_closed(self): self.reg_period.start_time = FUTURE_DAY self.reg_period.save() self.election.polling_start_time = FUTURE_DAY self.election.save() msg = u"garbage" for shortcode in set( (settings.REGISTRATION_SHORT_CODE, settings.VOTER_QUERY_SHORT_CODE, settings.REPORTS_SHORT_CODE)): self.receive(msg, self.conn, fields={'to_addr': shortcode}) # test that we save the incoming SMS incoming = SMS.objects.filter(to_number=shortcode) self.assertEqual(len(incoming), 1)
def setUp(self): # Default to polling in progress self.election = ElectionFactory(polling_start_time=PAST_DAY, polling_end_time=FUTURE_DAY)
def create(center_without_office=False, num_copy_centers=DEFAULT_NUM_COPY_CENTERS, num_registrations=DEFAULT_NUM_REGISTRATIONS, num_registration_dates=DEFAULT_NUM_REGISTRATION_DATES, num_daily_reports=DEFAULT_NUM_DAILY_REPORTS, num_registration_centers=DEFAULT_NUM_REGISTRATION_CENTERS, num_subconstituencies=DEFAULT_NUM_SUBCONSTITUENCIES, use_existing_infra=False, num_inactive_centers_per_election=DEFAULT_NUM_INACTIVE_PER_ELECTION, num_no_reg_centers=DEFAULT_NUM_NO_REG_CENTERS, election_dates=()): assert settings.ENVIRONMENT not in ('production', 'testing') delete(delete_infra=not use_existing_infra) empty_report_store() # Remove any old data from Redis # Figure out ~10% of "normal" centers... fraction_of_normal_centers = \ max(1, int(0.1 * num_registration_centers)) if num_registration_centers else 0 # If numbers of some weird center types weren't specified, use a small # fraction of normal centers. if num_copy_centers == DEFAULT_NUM_COPY_CENTERS: num_copy_centers = fraction_of_normal_centers if num_no_reg_centers == DEFAULT_NUM_NO_REG_CENTERS: num_no_reg_centers = fraction_of_normal_centers carrier = BackendFactory() if election_dates: elections = [ ElectionFactory(polling_start_time=election_date.replace(hour=8), polling_end_time=election_date.replace(hour=20)) for election_date in election_dates ] else: election_date = PAST_DAY.replace(hour=8, microsecond=123456) election = ElectionFactory( polling_start_time=election_date, polling_end_time=election_date.replace(hour=20)) elections = (election, ) if not use_existing_infra: OfficeFactory() ConstituencyFactory(name_english='first') SubConstituencyFactory(name_english='Benghazi') offices = Office.objects.all() copy_centers = [] no_reg_centers = [] staff_phones = [] if use_existing_infra: # Pick centers that support registrations at random. centers = RegistrationCenter.objects.filter(reg_open=True)\ .exclude(center_type=RegistrationCenter.Types.COPY)\ .order_by('?')[:num_registration_centers] if num_copy_centers: # user wants some, but there might not be any copy_centers = RegistrationCenter.objects.\ filter(reg_open=True, center_type=RegistrationCenter.Types.COPY)\ .order_by('?')[:num_copy_centers] if num_no_reg_centers: # user wants some, but there might not be any no_reg_centers = RegistrationCenter.objects.\ filter(reg_open=False).order_by('?')[:num_no_reg_centers] # why like this? sliced queries and/or list all_kinds_of_centers = \ list(centers) + list(copy_centers) + list(no_reg_centers) else: subconstituencies = SubConstituency.objects.exclude( pk=SPLIT_CENTER_SUBCONSTITUENCY_ID) subconstituencies = subconstituencies[:num_subconstituencies] centers = [] for i in range(num_registration_centers): constituency = Constituency.objects.filter(name_english='first')[0] subconstituency = random.choice(subconstituencies) rc = RegistrationCenter(name='polling-center-%d' % i, center_id=CENTER_ID_MIN_INT_VALUE + i, constituency=constituency, subconstituency=subconstituency, office=random.choice(offices)) rc.full_clean() rc.save() centers.append(rc) for i in range(num_copy_centers): original = random.choice(centers) # XXX This doesn't handle accidentally making too many copies of the same # center, so make sure --num-centers is "big enough" w.r.t. --num-copy-centers. new_center_id = CENTER_ID_MIN_INT_VALUE + num_registration_centers + i copy = RegistrationCenter( name='Copy of %s' % original.name, center_id=new_center_id, constituency=original.constituency, subconstituency=original.subconstituency, office=original.office, center_type=RegistrationCenter.Types.COPY, copy_of=original) copy.full_clean() copy.save() copy_centers.append(copy) for i in range(num_no_reg_centers): constituency = Constituency.objects.filter(name_english='first')[0] subconstituency = random.choice(subconstituencies) center_id = CENTER_ID_MIN_INT_VALUE + num_registration_centers + num_copy_centers + i rc = RegistrationCenter(name='no-reg-polling-center-%d' % i, center_id=center_id, constituency=constituency, subconstituency=subconstituency, office=random.choice(offices), reg_open=False) rc.full_clean() rc.save() all_kinds_of_centers = centers + copy_centers + no_reg_centers if center_without_office: try: # by not specifying office and other infra, it will be "standalone" rc = RegistrationCenter(name='dummy-registration-center', center_id=UNUSED_CENTER_ID) rc.full_clean() rc.save() except ValidationError: pass # assume that it already exists for election in elections: num_daily_reports_on_election_day = int(round(0.9 * num_daily_reports)) centers_reported = set() for i in range(num_daily_reports_on_election_day): staff_phone_number = STAFF_PHONE_NUMBER_PATTERN % i from_center = random.choice(all_kinds_of_centers) ensure_staff_phone_exists( staff_phone_number, from_center, staff_phones, election.work_start_time + datetime.timedelta(minutes=5)) # split votes between two options number_of_votes = (random.randint(1, 100), random.randint(1, 100)) random_period_number = random.randint(FIRST_PERIOD_NUMBER, LAST_PERIOD_NUMBER) pr = PollingReport(election=election, phone_number=staff_phone_number, registration_center=from_center, period_number=random_period_number, num_voters=sum(number_of_votes), creation_date=election.polling_start_time) pr.full_clean() pr.save() s = SMS(from_number=staff_phone_number, to_number=POLLING_REPORT_PHONE_NUMBER, direction=INCOMING, message='my message', msg_type=SMS.POLLING_REPORT, message_code=MESSAGE_1, carrier=carrier, creation_date=election.polling_start_time) s.full_clean() s.save() if from_center in centers_reported: continue # can't send but one PreliminaryVoteCount from a center # send a corresponding vote count for option, votes_for_option in enumerate(number_of_votes, start=1): pvc = PreliminaryVoteCount( election=election, phone_number=staff_phone_number, registration_center=from_center, option=option, num_votes=votes_for_option, creation_date=election.polling_start_time) pvc.full_clean() pvc.save() s = SMS( from_number=staff_phone_number, to_number=PRELIMINARY_VOTE_COUNT_PHONE_NUMBER, # XXX no specific message type for PreliminaryVoteCount direction=INCOMING, message='my message', msg_type=SMS.POLLING_REPORT, message_code=MESSAGE_1, carrier=carrier, creation_date=election.polling_start_time) s.full_clean() s.save() centers_reported.add(from_center) # some daily reports on the day after for i in range(num_daily_reports - num_daily_reports_on_election_day): staff_phone_number = STAFF_PHONE_NUMBER_PATTERN % i rc = random.choice(all_kinds_of_centers) ensure_staff_phone_exists( staff_phone_number, rc, staff_phones, election.work_start_time + datetime.timedelta(minutes=5)) report_creation_date = election.polling_start_time + datetime.timedelta( days=1) pr = PollingReport( election=election, phone_number=staff_phone_number, registration_center=rc, period_number= LAST_PERIOD_NUMBER, # day after counts as last period num_voters=random.randint(1, 50), creation_date=report_creation_date) pr.full_clean() pr.save() s = SMS(from_number=staff_phone_number, to_number=POLLING_REPORT_PHONE_NUMBER, direction=INCOMING, message='my message', msg_type=SMS.POLLING_REPORT, message_code=MESSAGE_1, carrier=carrier, creation_date=election.polling_start_time) s.full_clean() s.save() # Tag some centers as inactive for the election. We may or may not pick some that # sent messages as being inactive. num_inactive_centers_per_election = \ min(num_inactive_centers_per_election, len(all_kinds_of_centers)) if num_inactive_centers_per_election: reordered = all_kinds_of_centers random.shuffle(reordered) for i in range(num_inactive_centers_per_election): inactive_on_election = CenterClosedForElection( registration_center=reordered[i], election=election) inactive_on_election.full_clean() inactive_on_election.save() tz = timezone(settings.TIME_ZONE) # construct a datetime that will change based on timezone discrepancies # 0-2am in Libya has a different date than the same time in UDT or EDT today_fragile = now().astimezone(tz).replace(hour=0, minute=59) # tz.normalize fixes up the date arithmetic when crossing DST boundaries creation_dates = \ [tz.normalize((today_fragile - datetime.timedelta(days=DAYS_BETWEEN_REGISTRATIONS * i)).astimezone(tz)) for i in range(num_registration_dates)] citizens = [] for i in range(num_registrations): # about 60% of registrations are for males, just as with actual data gender = MALE if random.randint(1, 100) <= 60 else FEMALE nat_id = '%d%011d' % (gender, i) creation_date = random.choice(creation_dates) modification_date = creation_date # Select voter ages from 18 years on up. voter_age = random.randint(18, 99) # If they were a certain age at any time yesterday, they are certainly that age at any time # today. yesterday = datetime.datetime.now().replace( tzinfo=tz) - datetime.timedelta(days=1) birth_date = datetime.date(yesterday.year - voter_age, yesterday.month, yesterday.day) civil_registry_id = random.randint(1, 99999999) citizen = CitizenFactory(civil_registry_id=civil_registry_id, national_id=nat_id, gender=gender, birth_date=birth_date) citizens.append(citizen) s = SMS(from_number=VOTER_PHONE_NUMBER_PATTERN % i, to_number=REGISTRATION_PHONE_NUMBER, citizen=citizen, direction=INCOMING, message='my reg message', msg_type=SMS.REGISTRATION, message_code=MESSAGE_1, carrier=carrier, creation_date=creation_date) s.full_clean() s.save() rc = random.choice(centers) confirmed = random.randint(1, 100) <= 80 # most are confirmed if confirmed: archive_time = None else: archive_time = random.choice(creation_dates) r = Registration(citizen=citizen, registration_center=rc, sms=s, archive_time=archive_time, creation_date=creation_date, modification_date=modification_date) r.full_clean() r.save() if num_registrations: # if any data being generated # generate a variety of sms messages for i in range(NUM_RANDOM_SMS_MESSAGES): sms_type = random.choice(SMS.MESSAGE_TYPES)[0] staff_phone = random.choice(staff_phones) s = SMS(from_number=staff_phone.phone_number, to_number=RANDOM_MESSAGE_PHONE_NUMBER, citizen=random.choice(citizens), direction=INCOMING, message='my long random message', msg_type=sms_type, message_code=MESSAGE_1, carrier=carrier, creation_date=random.choice(creation_dates)) s.full_clean() s.save() for election in elections: for rc in centers: i = random.randint(8888, 9999) staff_phone_number = STAFF_PHONE_NUMBER_PATTERN % i ensure_staff_phone_exists( staff_phone_number, rc, staff_phones, election.work_start_time + datetime.timedelta(minutes=5)) center_open = CenterOpen( election=election, phone_number=staff_phone_number, registration_center=rc, creation_date=election.polling_start_time.replace( hour=random.randint(0, 10), minute=23)) center_open.full_clean() center_open.save() s = SMS(from_number=staff_phone_number, to_number=ACTIVATE_PHONE_NUMBER, direction=INCOMING, message='my message', msg_type=SMS.ACTIVATE, message_code=MESSAGE_1, carrier=carrier, creation_date=election.polling_start_time) s.full_clean() s.save()
class PeriodsTest(LibyaTest): """ Match requirements in Phases google spreadsheet: https://docs.google.com/a/caktusgroup.com/spreadsheet/ccc? key=0ApHYnffwYN6edDJSVmZaeXBqWDZnVk9ReTh6RWEyRWc&usp=drive_web#gid=0 """ def setUp(self): # Default to polling in progress self.election = ElectionFactory(polling_start_time=PAST_DAY, polling_end_time=FUTURE_DAY) def test_before_registration_opens_period(self): self.election.polling_start_time = FUTURE_DAY self.election.save() RegistrationPeriodFactory(start_time=FUTURE_DAY, end_time=FUTURE_DAY) self.assertFalse(tool_1_enabled()) self.assertFalse(polling_reports_enabled()) def test_during_registration(self): self.election.polling_start_time = FUTURE_DAY self.election.save() RegistrationPeriodFactory(start_time=PAST_DAY, end_time=FUTURE_DAY) self.assertTrue(tool_1_enabled()) self.assertFalse(polling_reports_enabled()) def test_after_registration_before_polling(self): self.election.polling_start_time = FUTURE_DAY self.election.save() RegistrationPeriodFactory(start_time=PAST_DAY, end_time=PAST_DAY) self.assertFalse(tool_1_enabled()) self.assertFalse(polling_reports_enabled()) def test_polling_period(self): RegistrationPeriodFactory(start_time=PAST_DAY, end_time=PAST_DAY) self.assertFalse(tool_1_enabled()) self.assertTrue(polling_reports_enabled()) def test_post_polling_reporting_period(self): self.election.polling_end_time = FIFTEEN_HOURS_AGO self.election.save() RegistrationPeriodFactory(start_time=PAST_DAY, end_time=PAST_DAY) self.assertFalse(tool_1_enabled()) self.assertTrue(polling_reports_enabled()) def test_counting_period(self): self.election.polling_end_time = PAST_DAY self.election.save() RegistrationPeriodFactory(start_time=PAST_DAY, end_time=PAST_DAY) self.assertFalse(tool_1_enabled()) self.assertFalse(polling_reports_enabled()) def test_reopened_reg_period(self): self.election.polling_end_time = PAST_DAY self.election.save() RegistrationPeriodFactory(start_time=PAST_DAY, end_time=PAST_DAY) self.assertFalse(tool_1_enabled()) self.assertFalse(polling_reports_enabled()) def test_after_reopened_reg_period(self): self.election.polling_end_time = PAST_DAY self.election.save() RegistrationPeriodFactory(start_time=PAST_DAY, end_time=PAST_DAY) self.assertFalse(tool_1_enabled()) self.assertFalse(polling_reports_enabled())
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)