def test_trigger_when_paused(self): # not paused with patch.object(RepeatRecord, 'fire') as mock_fire: with patch.object(RepeatRecord, 'postpone_by') as mock_postpone_fire: process_repeat_record(self.repeat_record) self.assertEqual(mock_fire.call_count, 1) self.assertEqual(mock_postpone_fire.call_count, 0) # paused self.repeater.pause() # re fetch repeat record repeat_record_id = self.repeat_record.get_id self.repeat_record = RepeatRecord.get(repeat_record_id) process_repeat_record(self.repeat_record) self.assertEqual(mock_fire.call_count, 1) self.assertEqual(mock_postpone_fire.call_count, 1) # resumed self.repeater.resume() # re fetch repeat record repeat_record_id = self.repeat_record.get_id self.repeat_record = RepeatRecord.get(repeat_record_id) process_repeat_record(self.repeat_record) self.assertEqual(mock_fire.call_count, 2) self.assertEqual(mock_postpone_fire.call_count, 1)
def test_trigger_when_paused(self): # not paused with patch.object(RepeatRecord, 'fire') as mock_fire: with patch.object(RepeatRecord, 'postpone_by') as mock_postpone_fire: # calls process_repeat_record(): self.repeat_record = self.repeater.register(CaseAccessors(self.domain).get_case(CASE_ID)) self.assertEqual(mock_fire.call_count, 1) self.assertEqual(mock_postpone_fire.call_count, 0) # paused self.repeater.pause() # re fetch repeat record repeat_record_id = self.repeat_record.get_id self.repeat_record = RepeatRecord.get(repeat_record_id) process_repeat_record(self.repeat_record) self.assertEqual(mock_fire.call_count, 1) self.assertEqual(mock_postpone_fire.call_count, 1) # resumed self.repeater.resume() # re fetch repeat record repeat_record_id = self.repeat_record.get_id self.repeat_record = RepeatRecord.get(repeat_record_id) process_repeat_record(self.repeat_record) self.assertEqual(mock_fire.call_count, 2) self.assertEqual(mock_postpone_fire.call_count, 1)
def test_repeat_record_status_check(self): self.assertEqual(len(RepeatRecord.all()), 2) # Do not trigger cancelled records for repeat_record in RepeatRecord.all(): repeat_record.cancelled = True repeat_record.save() with patch('corehq.motech.repeaters.models.simple_post') as mock_fire: check_repeaters() self.assertEqual(mock_fire.call_count, 0) # trigger force send records if not cancelled and tries not exhausted for repeat_record in RepeatRecord.all(): with patch('corehq.motech.repeaters.models.simple_post', return_value=MockResponse(status_code=200, reason='') ) as mock_fire: repeat_record.fire(force_send=True) self.assertEqual(mock_fire.call_count, 1) # all records should be in SUCCESS state after force try for repeat_record in RepeatRecord.all(): self.assertEqual(repeat_record.state, RECORD_SUCCESS_STATE) self.assertEqual(repeat_record.overall_tries, 1) # not trigger records succeeded triggered after cancellation with patch('corehq.motech.repeaters.models.simple_post') as mock_fire: check_repeaters() self.assertEqual(mock_fire.call_count, 0) for repeat_record in RepeatRecord.all(): self.assertEqual(repeat_record.state, RECORD_SUCCESS_STATE)
def test_repeater_failed_sends(self): """ This tests records that fail are requeued later """ def now(): return datetime.utcnow() repeat_records = self.repeat_records() self.assertEqual(len(repeat_records), 2) for repeat_record in repeat_records: with patch( 'corehq.motech.repeaters.models.simple_post', return_value=MockResponse(status_code=404, reason='Not Found')) as mock_post: repeat_record.fire() self.assertEqual(mock_post.call_count, 1) # Enqueued repeat records have next_check incremented by 48 hours next_check_time = now() + timedelta(minutes=60) + timedelta(hours=48) repeat_records = RepeatRecord.all( domain=self.domain, due_before=now() + timedelta(minutes=15), ) self.assertEqual(len(repeat_records), 0) repeat_records = RepeatRecord.all( domain=self.domain, due_before=next_check_time, ) self.assertEqual(len(repeat_records), 2)
def test_get_all_repeat_records_by_domain_since(self): new_records = [ # FAIL RepeatRecord( domain=self.domain, repeater_id=self.repeater_id, last_checked=datetime(2017, 5, 24, 0, 0, 0), failure_reason='some error', ), # CANCELLED RepeatRecord( domain=self.domain, repeater_id=self.repeater_id, last_checked=datetime(2017, 5, 10, 0, 0, 0), cancelled=True, ), # CANCELLED RepeatRecord( domain=self.domain, repeater_id=self.repeater_id, last_checked=datetime(2017, 5, 24, 0, 0, 0), cancelled=True, ), ] RepeatRecord.bulk_save(new_records) self.addCleanup(RepeatRecord.bulk_delete, new_records) records = list(iter_repeat_records_by_domain(self.domain, state=RECORD_CANCELLED_STATE, since=datetime(2017, 5, 20))) self.assertEqual(len(records), 1) record, = records self.assertEqual(record.to_json(), new_records[-1].to_json())
def setUpClass(cls): super(TestOtherDBAccessors, cls).setUpClass() cls.records = [ RepeatRecord(domain='a'), RepeatRecord(domain='b'), RepeatRecord(domain='c'), ] RepeatRecord.bulk_save(cls.records)
def test_skip_duplicates(self): """ Ensure that submitting a duplicate form does not create extra RepeatRecords """ self.assertEqual(len(RepeatRecord.all()), 2) # this form is already submitted during setUp so a second submission should be a duplicate form = self.post_xml(self.xform_xml, self.domain).xform self.assertTrue(form.is_duplicate) self.assertEqual(len(RepeatRecord.all()), 2)
def test_update_failure_next_check(self): now = datetime.utcnow() record = RepeatRecord(domain=self.domain, next_check=now) self.assertIsNone(record.last_checked) attempt = record.make_set_next_try_attempt(None) record.add_attempt(attempt) self.assertTrue(record.last_checked > now) self.assertEqual(record.next_check, record.last_checked + MIN_RETRY_WAIT)
def handle(self, *args, **options): domain = options.get('domain') repeater_id = options.get('repeater_id') state = options.get('state') records_file_path = options.get('records_file_path') if records_file_path: self._load_record_ids_from_file(records_file_path) records = self.record_ids record_count = len(records) elif domain and repeater_id: records = iter_repeat_records_by_domain(domain, repeater_id=repeater_id, state=state) record_count = get_repeat_record_count(domain, repeater_id=repeater_id, state=state) else: raise CommandError("Insufficient Arguments") for record in with_progress_bar(records, length=record_count): if isinstance(record, str): record_id = record try: record = RepeatRecord.get(record_id) except ResourceNotFound: self.ws.append([record_id, '', 'Not Found']) continue self._add_row(record) file_name = self._save_file(repeater_id, state) print("Report saved in file:{filename}".format(filename=file_name))
def delete_already_successful_records(self, redundant_records): log = [] with IterDB(RepeatRecord.get_db()) as iter_db: for record in redundant_records: iter_db.delete(record) log.append((record._id, record.payload_id, record.failure_reason, 'Yes', 'Already Sent')) return log
def openmrs_test_fire(request, domain, repeater_id, record_id): repeater = OpenmrsRepeater.get(repeater_id) record = RepeatRecord.get(record_id) assert repeater.domain == domain assert record.domain == domain assert record.repeater_id == repeater.get_id attempt = repeater.fire_for_record(record) return JsonResponse(attempt.to_json())
def requeue_repeat_record(request, domain): try: record = RepeatRecord.get(request.POST.get('record_id')) except ResourceNotFound: return HttpResponse(status=404) record.requeue() record.save() if record.cancelled: return HttpResponse(status=400) return HttpResponse('OK')
def get_record_or_404(request, domain, record_id): try: record = RepeatRecord.get(record_id) except ResourceNotFound: raise Http404() if record.domain != domain: raise Http404() return record
def resolve_duplicates(self, records_by_payload_id): log = [] with IterDB(RepeatRecord.get_db()) as iter_db: for payload_id, records in records_by_payload_id.items(): log.append((records[0]._id, payload_id, records[0].failure_reason, 'No', '')) if len(records) > 1: for record in records[1:]: iter_db.delete(record) log.append((record._id, payload_id, record.failure_reason, 'Yes', 'Duplicate')) return log
def test_check_repeat_records(self): self.assertEqual(len(RepeatRecord.all()), 2) with patch('corehq.motech.repeaters.models.simple_post') as mock_fire: check_repeaters() self.assertEqual(mock_fire.call_count, 2) with patch('corehq.motech.repeaters.models.simple_post') as mock_fire: check_repeaters() self.assertEqual(mock_fire.call_count, 0)
def test_process_repeat_record_locking(self): self.assertEqual(len(RepeatRecord.all()), 2) with patch('corehq.motech.repeaters.tasks.process_repeat_record') as mock_process: check_repeaters() self.assertEqual(mock_process.delay.call_count, 2) with patch('corehq.motech.repeaters.tasks.process_repeat_record') as mock_process: check_repeaters() self.assertEqual(mock_process.delay.call_count, 0) records = RepeatRecord.all() # Saving should unlock them again by changing the rev for record in records: record.save() with patch('corehq.motech.repeaters.tasks.process_repeat_record') as mock_process: check_repeaters() self.assertEqual(mock_process.delay.call_count, 2)
def _run_test(self, event_type, expected_records_after_create, expected_records_after_update, case_type=ZAPIER_CASE_TYPE): ZapierSubscription.objects.create( domain=self.domain, user_id=str(self.web_user._id), event_name=event_type, url='http://example.com/lets-make-some-cases/', case_type=ZAPIER_CASE_TYPE, ) # create case and run checks case_id = uuid.uuid4().hex post_case_blocks( [ CaseBlock( create=True, case_id=case_id, case_type=case_type, ).as_xml() ], domain=self.domain ) # Enqueued repeat records have next_check set 48 hours in the future. later = datetime.utcnow() + timedelta(hours=48 + 1) repeat_records = list(RepeatRecord.all(domain=self.domain, due_before=later)) self.assertEqual(expected_records_after_create, len(repeat_records)) for record in repeat_records: self.assertEqual(case_id, record.payload_id) # update case and run checks post_case_blocks( [ CaseBlock( create=False, case_id=case_id, ).as_xml() ], domain=self.domain ) repeat_records = list(RepeatRecord.all(domain=self.domain, due_before=later)) self.assertEqual(expected_records_after_update, len(repeat_records)) for record in repeat_records: self.assertEqual(case_id, record.payload_id)
def page_context(self): return { 'repeaters': self.repeaters, 'pending_record_count': RepeatRecord.count(self.domain), 'gefingerpoken': ( # Set gefingerpoken_ to whether the user should be allowed to change MOTECH configuration. # .. _gefingerpoken: https://en.wikipedia.org/wiki/Blinkenlights self.request.couch_user.is_superuser or self.request.couch_user.can_edit_motech() or toggles.IS_CONTRACTOR.enabled(self.request.couch_user.username) ) }
def test_ignore_document(self): """ When get_payload raises IgnoreDocument, fire should call update_success """ repeat_records = RepeatRecord.all( domain=self.domain, ) for repeat_record_ in repeat_records: repeat_record_.fire() self.assertIsNone(repeat_record_.next_check) self.assertTrue(repeat_record_.succeeded)
def _run_test(self, event_type, expected_records_after_create, expected_records_after_update, case_type=ZAPIER_CASE_TYPE): ZapierSubscription.objects.create( domain=self.domain, user_id=str(self.web_user._id), event_name=event_type, url='http://example.com/lets-make-some-cases/', case_type=ZAPIER_CASE_TYPE, ) # create case and run checks case_id = uuid.uuid4().hex post_case_blocks( [ CaseBlock( create=True, case_id=case_id, case_type=case_type, ).as_xml() ], domain=self.domain ) repeat_records = list(RepeatRecord.all(domain=self.domain)) self.assertEqual(expected_records_after_create, len(repeat_records)) for record in repeat_records: self.assertEqual(case_id, record.payload_id) # update case and run checks post_case_blocks( [ CaseBlock( create=False, case_id=case_id, ).as_xml() ], domain=self.domain ) repeat_records = list(RepeatRecord.all(domain=self.domain)) self.assertEqual(expected_records_after_update, len(repeat_records)) for record in repeat_records: self.assertEqual(case_id, record.payload_id)
def test_repeater_successful_send(self): repeat_records = RepeatRecord.all(domain=self.domain, due_before=datetime.utcnow()) for repeat_record in repeat_records: with patch( 'corehq.motech.repeaters.models.simple_post', return_value=MockResponse(status_code=200, reason='No Reason')) as mock_post: repeat_record.fire() self.assertEqual(mock_post.call_count, 1) mock_post.assert_any_call( repeat_record.get_payload(), repeat_record.repeater.get_url(repeat_record), headers=repeat_record.repeater.get_headers(repeat_record), timeout=POST_TIMEOUT, auth=repeat_record.repeater.get_auth(), verify=repeat_record.repeater.verify, ) # The following is pretty fickle and depends on which of # - corehq.motech.repeaters.signals # - casexml.apps.case.signals # gets loaded first. # This is deterministic but easily affected by minor code changes repeat_records = RepeatRecord.all( domain=self.domain, due_before=datetime.utcnow(), ) for repeat_record in repeat_records: self.assertEqual(repeat_record.succeeded, True) self.assertEqual(repeat_record.next_check, None) self.assertEqual(len(self.repeat_records(self.domain)), 0) self.post_xml(self.update_xform_xml, self.domain) self.assertEqual(len(self.repeat_records(self.domain)), 2)
def test_repeat_record_created(self): ''' Tests that whenever an application with a repeater is saved that a repeat record is created. ''' application = Application(domain=self.domain) application.save() repeat_records = RepeatRecord.all(domain=self.domain, due_before=datetime.utcnow()) self.assertEqual(len(repeat_records), 0) app_structure_repeater = AppStructureRepeater(domain=self.domain, url=self.forwarding_url) app_structure_repeater.save() application.save() repeat_records = RepeatRecord.all(domain=self.domain, due_before=datetime.utcnow()) self.assertEqual(len(repeat_records), 1) for repeat_record in repeat_records: self.assertEqual(repeat_record.repeater.get_url(repeat_record), self.forwarding_url) self.assertEqual(repeat_record.get_payload(), application.get_id) repeat_record.delete() application.delete() app_structure_repeater.delete()
def repeat_records(self): return RepeatRecord.all(domain=self.domain, due_before=datetime.utcnow())
def repeat_records(self): # Enqueued repeat records have next_check set 48 hours in the future. later = datetime.utcnow() + timedelta(hours=48 + 1) return RepeatRecord.all(domain=self.domain, due_before=later)
def repeat_records(self): return RepeatRecord.all(domain=self.domain, due_before=datetime.utcnow())
def repeat_records(cls, domain_name): return RepeatRecord.all(domain=domain_name, due_before=datetime.utcnow())
with patch('corehq.motech.repeaters.models.simple_request', side_effect=RequestException('Boom!')): rr = self.repeater.register(case) # calls repeat_record.fire() # Fetch the repeat_record revision that was updated repeat_record = RepeatRecord.get(rr.record_id) self.assertEqual(repeat_record.failure_reason, 'Boom!') self.assertFalse(repeat_record.succeeded) def test_unexpected_failure(self): case = CommCareCase.objects.get_case(CASE_ID, self.domain) with patch('corehq.motech.repeaters.models.simple_request', side_effect=Exception('Boom!')): rr = self.repeater.register(case) repeat_record = RepeatRecord.get(rr.record_id) self.assertEqual(repeat_record.failure_reason, 'Internal Server Error') self.assertFalse(repeat_record.succeeded) def test_success(self): case = CommCareCase.objects.get_case(CASE_ID, self.domain) # Should be marked as successful after a successful run with patch('corehq.motech.repeaters.models.simple_request' ) as mock_simple_post: mock_simple_post.return_value.status_code = 200 rr = self.repeater.register(case) repeat_record = RepeatRecord.get(rr.record_id) self.assertTrue(repeat_record.succeeded)
def test_content_is_None(self): response = Response(500, 'The core is exposed') formatted = RepeatRecord._format_response(response) self.assertEqual(formatted, '500: The core is exposed.\n')
def cleanup_repeat_records_for_domain(domain): for repeat_record in RepeatRecord.all(domain=domain): repeat_record.delete()
class RepeaterTest(BaseRepeaterTest): domain = "repeater-test" def setUp(self): super(RepeaterTest, self).setUp() self.case_connx = ConnectionSettings.objects.create( domain=self.domain, url='case-repeater-url', ) self.case_repeater = CaseRepeater( domain=self.domain, connection_settings_id=self.case_connx.id, format='case_json', ) self.case_repeater.save() self.form_connx = ConnectionSettings.objects.create( domain=self.domain, url='form-repeater-url', ) self.form_repeater = FormRepeater( domain=self.domain, connection_settings_id=self.form_connx.id, format='form_json') self.form_repeater.save() self.log = [] with patch('corehq.motech.repeaters.models.simple_request', return_value=MockResponse(status_code=500, reason="Borked")) as mock_fire: self.post_xml(self.xform_xml, self.domain) self.initial_fire_call_count = mock_fire.call_count def tearDown(self): self.case_repeater.delete() self.case_connx.delete() self.form_repeater.delete() self.form_connx.delete() FormProcessorTestUtils.delete_all_cases_forms_ledgers(self.domain) delete_all_repeat_records() super(RepeaterTest, self).tearDown() def repeat_records(self): return super(RepeaterTest, self).repeat_records(self.domain) # whatever value specified will be doubled since both case and form repeater are active def _create_additional_repeat_records(self, count): for _ in range(count): instance_id = uuid.uuid4().hex xform_xml = XFORM_XML_TEMPLATE.format( "https://www.commcarehq.org/test/repeater/", USER_ID, instance_id, self.case_block) with patch('corehq.motech.repeaters.models.simple_request', return_value=MockResponse(status_code=500, reason="Borked")): self.post_xml(xform_xml, self.domain) def test_skip_device_logs(self): devicelog_xml = XFORM_XML_TEMPLATE.format(DEVICE_LOG_XMLNS, USER_ID, '1234', '') self.post_xml(devicelog_xml, self.domain) for repeat_record in self.repeat_records(): self.assertNotEqual(repeat_record.payload_id, '1234') def test_skip_duplicates(self): """ Ensure that submitting a duplicate form does not create extra RepeatRecords """ self.assertEqual(len(self.repeat_records()), 2) # this form is already submitted during setUp so a second submission should be a duplicate form = self.post_xml(self.xform_xml, self.domain).xform self.assertTrue(form.is_duplicate) self.assertEqual(len(self.repeat_records()), 2) def test_repeater_failed_sends(self): """ This tests records that fail are requeued later """ def now(): return datetime.utcnow() repeat_records = self.repeat_records() self.assertEqual(len(repeat_records), 2) for repeat_record in repeat_records: with patch('corehq.motech.repeaters.models.simple_request', return_value=MockResponse( status_code=404, reason='Not Found')) as mock_request: repeat_record.fire() self.assertEqual(mock_request.call_count, 1) # Enqueued repeat records have next_check incremented by 48 hours next_check_time = now() + timedelta(minutes=60) + timedelta(hours=48) repeat_records = RepeatRecord.all( domain=self.domain, due_before=now() + timedelta(minutes=15), ) self.assertEqual(len(repeat_records), 0) repeat_records = RepeatRecord.all( domain=self.domain, due_before=next_check_time, ) self.assertEqual(len(repeat_records), 2) def test_update_failure_next_check(self): now = datetime.utcnow() record = RepeatRecord( domain=self.domain, repeater_id=self.case_repeater.get_id, next_check=now, ) self.assertIsNone(record.last_checked) attempt = record.make_set_next_try_attempt(None) record.add_attempt(attempt) self.assertTrue(record.last_checked > now) self.assertEqual(record.next_check, record.last_checked + MIN_RETRY_WAIT) def test_repeater_successful_send(self): repeat_records = self.repeat_records() for repeat_record in repeat_records: with patch('corehq.motech.repeaters.models.simple_request') as mock_request, \ patch.object(ConnectionSettings, 'get_auth_manager') as mock_manager: mock_request.return_value.status_code = 200 mock_manager.return_value = 'MockAuthManager' repeat_record.fire() self.assertEqual(mock_request.call_count, 1) mock_request.assert_called_with( self.domain, repeat_record.repeater.get_url(repeat_record), repeat_record.get_payload(), headers=repeat_record.repeater.get_headers(repeat_record), auth_manager='MockAuthManager', verify=repeat_record.repeater.verify, notify_addresses=[], payload_id=repeat_record.payload_id, method="POST", ) # The following is pretty fickle and depends on which of # - corehq.motech.repeaters.signals # - casexml.apps.case.signals # gets loaded first. # This is deterministic but easily affected by minor code changes repeat_records = self.repeat_records() for repeat_record in repeat_records: self.assertEqual(repeat_record.succeeded, True) self.assertEqual(repeat_record.next_check, None) self.assertEqual(len(self.repeat_records()), 0) self.post_xml(self.update_xform_xml, self.domain) self.assertEqual(len(self.repeat_records()), 2) def test_check_repeat_records(self): self.assertEqual(len(self.repeat_records()), 2) self.assertEqual(self.initial_fire_call_count, 2) with patch( 'corehq.motech.repeaters.models.simple_request') as mock_fire: check_repeaters() self.assertEqual(mock_fire.call_count, 0) def test_repeat_record_status_check(self): self.assertEqual(len(self.repeat_records()), 2) # Do not trigger cancelled records for repeat_record in self.repeat_records(): repeat_record.cancelled = True repeat_record.save() with patch( 'corehq.motech.repeaters.models.simple_request') as mock_fire: check_repeaters() self.assertEqual(mock_fire.call_count, 0) # trigger force send records if not cancelled and tries not exhausted for repeat_record in self.repeat_records(): with patch('corehq.motech.repeaters.models.simple_request', return_value=MockResponse(status_code=200, reason='')) as mock_fire: repeat_record.fire(force_send=True) self.assertEqual(mock_fire.call_count, 1) # all records should be in SUCCESS state after force try for repeat_record in self.repeat_records(): self.assertEqual(repeat_record.state, RECORD_SUCCESS_STATE) self.assertEqual(repeat_record.overall_tries, 1) # not trigger records succeeded triggered after cancellation with patch( 'corehq.motech.repeaters.models.simple_request') as mock_fire: check_repeaters() self.assertEqual(mock_fire.call_count, 0) for repeat_record in self.repeat_records(): self.assertEqual(repeat_record.state, RECORD_SUCCESS_STATE) def test_retry_process_repeat_record_locking(self): self.assertEqual(len(self.repeat_records()), 2) with patch('corehq.motech.repeaters.tasks.retry_process_repeat_record' ) as mock_process: check_repeaters() self.assertEqual(mock_process.delay.call_count, 0) for record in self.repeat_records(): # Resetting next_check should allow them to be requeued record.next_check = datetime.utcnow() record.save() with patch('corehq.motech.repeaters.tasks.retry_process_repeat_record' ) as mock_process: check_repeaters() self.assertEqual(mock_process.delay.call_count, 2) def test_automatic_cancel_repeat_record(self): case = CommCareCase.objects.get_case(CASE_ID, self.domain) rr = self.case_repeater.register(case) # Fetch the revision that was updated: repeat_record = RepeatRecord.get(rr.record_id) self.assertEqual(1, repeat_record.overall_tries) with patch('corehq.motech.repeaters.models.simple_request', side_effect=Exception('Boom!')): for __ in range(repeat_record.max_possible_tries - repeat_record.overall_tries): repeat_record.fire() self.assertEqual(True, repeat_record.cancelled) repeat_record.requeue() self.assertEqual(0, repeat_record.overall_tries) self.assertNotEqual(None, repeat_record.next_check)
class TestRepeaterFormat(BaseRepeaterTest): domain = 'test-fmt' @classmethod def setUpClass(cls): super(TestRepeaterFormat, cls).setUpClass() cls.payload = 'some random case' class NewCaseGenerator(BasePayloadGenerator): format_name = 'new_format' format_label = 'XML' deprecated_format_names = ('new_format_alias', ) def get_payload(self, repeat_record, payload_doc): return cls.payload RegisterGenerator.get_collection(CaseRepeater).add_new_format( NewCaseGenerator) cls.new_generator = NewCaseGenerator def setUp(self): super().setUp() self.post_xml(self.xform_xml, self.domain) self.connx = ConnectionSettings.objects.create( domain=self.domain, url='case-repeater-url', ) self.repeater = CaseRepeater( domain=self.domain, connection_settings_id=self.connx.id, format='new_format', ) # SQL Repeater Model restricts format and would raise error on unexpected values self.repeater.save(sync_to_sql=False) def tearDown(self): self.repeater.delete(sync_to_sql=False) self.connx.delete() FormProcessorTestUtils.delete_all_cases_forms_ledgers(self.domain) delete_all_repeat_records() super().tearDown() def test_new_format_same_name(self): class NewCaseGenerator(BasePayloadGenerator): format_name = 'case_xml' format_label = 'XML' def get_payload(self, repeat_record, payload_doc): return self.payload with self.assertRaises(DuplicateFormatException): RegisterGenerator.get_collection(CaseRepeater).add_new_format( NewCaseGenerator) def test_new_format_second_default(self): class NewCaseGenerator(BasePayloadGenerator): format_name = 'rubbish' format_label = 'XML' def get_payload(self, repeat_record, payload_doc): return self.payload with self.assertRaises(DuplicateFormatException): RegisterGenerator.get_collection(CaseRepeater).add_new_format( NewCaseGenerator, is_default=True) def test_new_format_payload(self): case = CommCareCase.objects.get_case(CASE_ID, self.domain) with patch('corehq.motech.repeaters.models.simple_request') as mock_request, \ patch.object(ConnectionSettings, 'get_auth_manager') as mock_manager: mock_request.return_value.status_code = 200 mock_manager.return_value = 'MockAuthManager' rr = self.repeater.register(case) repeat_record = RepeatRecord.get(rr.record_id) headers = self.repeater.get_headers(repeat_record) mock_request.assert_called_with( self.domain, self.connx.url, self.payload, auth_manager='MockAuthManager', headers=headers, notify_addresses=[], payload_id='ABC123CASEID', verify=self.repeater.verify, method="POST", )
def repeat_records(cls, domain_name): return RepeatRecord.all(domain=domain_name, due_before=datetime.utcnow())
def handle(self, domain, **options): next_year = datetime.datetime.utcnow() + datetime.timedelta(days=365) records = RepeatRecord.all(domain=domain, due_before=next_year) # Excludes succeeded and cancelled for record in records: record.fire(force_send=True) print('{} {}'.format(record._id, 'successful' if record.succeeded else 'failed'))
def get_domains_that_have_repeat_records(): from .models import RepeatRecord return [ row['key'][0] for row in RepeatRecord.view('repeaters/repeat_records', group_level=1).all() ]
def cleanup_repeat_records_for_domain(domain): for repeat_record in RepeatRecord.all(domain=domain): repeat_record.delete()
def iterate_repeat_records_for_ids(doc_ids): from .models import RepeatRecord return (RepeatRecord.wrap(doc) for doc in iter_docs(RepeatRecord.get_db(), doc_ids))
def test_skip_device_logs(self): devicelog_xml = XFORM_XML_TEMPLATE.format(DEVICE_LOG_XMLNS, USER_ID, '1234', '') self.post_xml(devicelog_xml, self.domain) repeat_records = RepeatRecord.all(domain=self.domain) for repeat_record in repeat_records: self.assertNotEqual(repeat_record.payload_id, '1234')
def tearDownClass(cls): RepeatRecord.bulk_delete(cls.records) super(TestOtherDBAccessors, cls).tearDownClass()
def test_skip_device_logs(self): devicelog_xml = XFORM_XML_TEMPLATE.format(DEVICE_LOG_XMLNS, USER_ID, '1234', '') self.post_xml(devicelog_xml, self.domain) repeat_records = RepeatRecord.all(domain=self.domain) for repeat_record in repeat_records: self.assertNotEqual(repeat_record.payload_id, '1234')
def repeat_records(cls, domain_name): # Enqueued repeat records have next_check set 48 hours in the future. later = datetime.utcnow() + timedelta(hours=48 + 1) return RepeatRecord.all(domain=domain_name, due_before=later)
def test_vaccination_payload(self, payload_doc_mock, connection_settings_mock): connection_settings_mock.return_value = ConnectionSettings(password="******") case_id = uuid.uuid4().hex case = CommCareCase(domain=self.domain, type='cowin_api_data', case_id=case_id, server_modified_on=datetime.datetime.utcnow()) payload_doc_mock.return_value = case repeater = BeneficiaryVaccinationRepeater() generator = BeneficiaryVaccinationPayloadGenerator(repeater) repeat_record = RepeatRecord() self.assertEqual(repeater.get_headers(repeat_record)['X-Api-Key'], "my-secure-api-key") # 1st dose case.case_json = { 'beneficiary_reference_id': '1234567890123', 'center_id': "1234", 'vaccine': "COVISHIELD", 'vaccine_batch': '123456', 'dose': '1', 'dose1_date': "2020-11-29", 'vaccinator_name': 'Neelima', } payload = generator.get_payload(repeat_record=None, cowin_api_data_vaccination_case=case) self.assertDictEqual( json.loads(payload), { "beneficiary_reference_id": "1234567890123", "center_id": 1234, "vaccine": "COVISHIELD", "vaccine_batch": "123456", "dose": 1, "dose1_date": "29-11-2020", "vaccinator_name": "Neelima" } ) # 2nd dose case.case_json = { 'beneficiary_reference_id': '1234567890123', 'center_id': "1234", 'vaccine': "COVISHIELD", 'vaccine_batch': '123456', 'dose': '2', 'dose2_date': "2020-12-29", 'vaccinator_name': 'Sumanthra', } payload = generator.get_payload(repeat_record=None, cowin_api_data_vaccination_case=case) self.assertDictEqual( json.loads(payload), { "beneficiary_reference_id": "1234567890123", "center_id": 1234, "vaccine": "COVISHIELD", "vaccine_batch": "123456", "dose": 2, "dose2_date": "29-12-2020", "vaccinator_name": "Sumanthra" } )