def zapier_subscription_pre_save(sender, instance, *args, **kwargs): """ Creates a repeater object corresponding to the type of trigger (form or case) """ if instance.pk: return if instance.event_name == EventTypes.NEW_FORM: repeater = FormRepeater(domain=instance.domain, url=instance.url, format='form_json', include_app_id_param=False, white_listed_form_xmlns=[instance.form_xmlns]) elif instance.event_name == EventTypes.NEW_CASE: repeater = CaseRepeater( domain=instance.domain, url=instance.url, format='case_json', white_listed_case_types=[instance.case_type], ) else: raise ImmediateHttpResponse( HttpBadRequest('The passed event type is not valid.')) repeater.save() instance.repeater_id = repeater.get_id
def setUp(self): super(IgnoreDocumentTest, self).setUp() self.domain = "test-domain" create_domain(self.domain) self.repeater = FormRepeater(domain=self.domain, url='form-repeater-url', format='new_format') self.repeater.save()
def zapier_subscription_pre_save(sender, instance, *args, **kwargs): if instance.pk: return repeater = FormRepeater( domain=instance.domain, url=instance.url, format='form_json', include_app_id_param=False, white_listed_form_xmlns=[instance.form_xmlns] ) repeater.save() instance.repeater_id = repeater.get_id
def tearDownClass(cls): cls.web_user.delete() cls.application.delete() cls.domain_object.delete() for repeater in FormRepeater.by_domain(cls.domain): repeater.delete() super(TestZapierIntegration, cls).tearDownClass()
def setUp(self): super(RepeaterTest, self).setUp() self.domain = "test-domain" create_domain(self.domain) self.case_repeater = CaseRepeater( domain=self.domain, url='case-repeater-url', ) self.case_repeater.save() self.form_repeater = FormRepeater( domain=self.domain, url='form-repeater-url', ) self.form_repeater.save() self.log = [] self.post_xml(self.xform_xml, self.domain)
def tearDownClass(cls): ZAPIER_INTEGRATION.set('domain:{}'.format(cls.domain), False) cls.web_user.delete() cls.application.delete() cls.domain_object.delete() for repeater in FormRepeater.by_domain(cls.domain): repeater.delete() super(TestZapierIntegration, cls).tearDownClass()
class IgnoreDocumentTest(BaseRepeaterTest): @classmethod def setUpClass(cls): super(IgnoreDocumentTest, cls).setUpClass() class NewFormGenerator(BasePayloadGenerator): format_name = 'new_format' format_label = 'XML' def get_payload(self, repeat_record, payload_doc): raise IgnoreDocument RegisterGenerator.get_collection(FormRepeater).add_new_format(NewFormGenerator) def setUp(self): super(IgnoreDocumentTest, self).setUp() self.domain = "test-domain" create_domain(self.domain) self.repeater = FormRepeater( domain=self.domain, url='form-repeater-url', format='new_format' ) self.repeater.save() def tearDown(self): self.repeater.delete() delete_all_repeat_records() super(IgnoreDocumentTest, self).tearDown() @run_with_all_backends 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 setUpClass(cls): super(FormRepeaterTest, cls).setUpClass() cls.domain_name = "test-domain" cls.domain = create_domain(cls.domain_name) cls.repeater = FormRepeater( domain=cls.domain_name, url="form-repeater-url", ) cls.repeater.save()
class IgnoreDocumentTest(BaseRepeaterTest): @classmethod def setUpClass(cls): super(IgnoreDocumentTest, cls).setUpClass() @RegisterGenerator(FormRepeater, 'new_format', 'XML') class NewFormGenerator(BasePayloadGenerator): def get_payload(self, repeat_record, payload_doc): raise IgnoreDocument def setUp(self): super(IgnoreDocumentTest, self).setUp() self.domain = "test-domain" create_domain(self.domain) self.repeater = FormRepeater( domain=self.domain, url='form-repeater-url', format='new_format' ) self.repeater.save() def tearDown(self): self.repeater.delete() delete_all_repeat_records() super(IgnoreDocumentTest, self).tearDown() @run_with_all_backends 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 setUp(self): self.domain = "test-domain" create_domain(self.domain) self.repeater = FormRepeater( domain=self.domain, url='form-repeater-url', version=V1, format='new_format' ) self.repeater.save()
def setUp(self): super(IgnoreDocumentTest, self).setUp() self.domain = "test-domain" create_domain(self.domain) self.repeater = FormRepeater( domain=self.domain, url='form-repeater-url', format='new_format' ) self.repeater.save()
def setUpClass(cls): super(FormPayloadGeneratorTest, cls).setUpClass() cls.domain_name = "test-domain" cls.domain = create_domain(cls.domain_name) cls.repeater = FormRepeater( domain=cls.domain_name, url="form-repeater-url", ) cls.repeatergenerator = FormRepeaterXMLPayloadGenerator( repeater=cls.repeater) cls.repeater.save()
def zapier_subscription_post_delete(sender, instance, *args, **kwargs): """ Deletes the repeater object when the corresponding zap is turned off """ if instance.event_name == EventTypes.NEW_FORM: repeater = FormRepeater.get(instance.repeater_id) elif instance.event_name == EventTypes.NEW_CASE: repeater = CaseRepeater.get(instance.repeater_id) else: raise ImmediateHttpResponse( HttpBadRequest('The passed event type is not valid.')) repeater.delete()
def test_clone_repeaters(self): from corehq.apps.repeaters.models import Repeater from corehq.apps.repeaters.models import CaseRepeater from corehq.apps.repeaters.models import FormRepeater from custom.enikshay.integrations.nikshay.repeaters import NikshayRegisterPatientRepeater self.assertEqual(0, len(Repeater.by_domain(self.new_domain))) self.assertEqual( 0, len(NikshayRegisterPatientRepeater.by_domain(self.new_domain))) case_repeater = CaseRepeater( domain=self.old_domain, url='case-repeater-url', ) case_repeater.save() self.addCleanup(case_repeater.delete) form_repeater = FormRepeater( domain=self.old_domain, url='form-repeater-url', ) form_repeater.save() self.addCleanup(form_repeater.delete) custom_repeater = NikshayRegisterPatientRepeater( domain=self.old_domain, url='99dots') custom_repeater.save() self.addCleanup(custom_repeater.delete) self.make_clone(include=['repeaters']) cloned_repeaters = Repeater.by_domain(self.new_domain) self.assertEqual(3, len(cloned_repeaters)) self.assertEqual( {'CaseRepeater', 'FormRepeater', 'NikshayRegisterPatientRepeater'}, {repeater.doc_type for repeater in cloned_repeaters}) # test cache clearing cloned_niksay_repeaters = NikshayRegisterPatientRepeater.by_domain( self.new_domain) self.assertEqual(1, len(cloned_niksay_repeaters))
class IgnoreDocumentTest(BaseRepeaterTest): def setUp(self): self.domain = "test-domain" create_domain(self.domain) self.repeater = FormRepeater( domain=self.domain, url='form-repeater-url', version=V1, format='new_format' ) self.repeater.save() def tearDown(self): self.repeater.delete() repeat_records = RepeatRecord.all() for repeat_record in repeat_records: repeat_record.delete() def test_ignore_document(self): """ When get_payload raises IgnoreDocument, fire should call update_success """ @RegisterGenerator(FormRepeater, 'new_format', 'XML') class NewFormGenerator(BasePayloadGenerator): def get_payload(self, repeat_record, payload_doc): raise IgnoreDocument 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 setUp(self): self.domain = "test-domain" create_domain(self.domain) self.case_repeater = CaseRepeater( domain=self.domain, url='case-repeater-url', version=V1, ) self.case_repeater.save() self.form_repeater = FormRepeater( domain=self.domain, url='form-repeater-url', ) self.form_repeater.save() self.log = [] self.post_xml(xform_xml, self.domain)
def test_unsubscribe_form(self): ZapierSubscription.objects.create( url=ZAPIER_URL, user_id=self.web_user.get_id, domain=TEST_DOMAIN, event_name=EventTypes.NEW_FORM, application_id=self.application.get_id, form_xmlns=FORM_XMLNS) data = {"subscription_url": ZAPIER_URL, "target_url": ZAPIER_URL} response = self.client.post( reverse(UnsubscribeView.urlname, kwargs={'domain': self.domain}), data=json.dumps(data), content_type='application/json; charset=utf-8', HTTP_AUTHORIZATION='ApiKey test:{}'.format(self.api_key)) self.assertEqual(response.status_code, 200) self.assertEqual(ZapierSubscription.objects.all().count(), 0) self.assertEqual(len(FormRepeater.by_domain(TEST_DOMAIN)), 0)
def test_unsubscribe(self): ZapierSubscription.objects.create( url=ZAPIER_URL, user_id=self.web_user.get_id, domain=TEST_DOMAIN, event_name=consts.EventTypes.NEW_FORM, application_id=self.application.get_id, form_xmlns=FORM_XMLNS ) data = { "subscription_url": ZAPIER_URL, "target_url": ZAPIER_URL } response = self.client.post(reverse('zapier_unsubscribe', kwargs={'domain': self.domain}), data=json.dumps(data), content_type='application/json; charset=utf-8', HTTP_AUTHORIZATION='ApiKey test:{}'.format(self.api_key)) self.assertEqual(response.status_code, 200) self.assertEqual(ZapierSubscription.objects.all().count(), 0) self.assertEqual(len(FormRepeater.by_domain(TEST_DOMAIN)), 0)
class RepeaterTest(BaseRepeaterTest): def setUp(self): super(RepeaterTest, self).setUp() self.domain = "test-domain" create_domain(self.domain) self.case_repeater = CaseRepeater( domain=self.domain, url='case-repeater-url', ) self.case_repeater.save() self.form_repeater = FormRepeater( domain=self.domain, url='form-repeater-url', ) self.form_repeater.save() self.log = [] self.post_xml(self.xform_xml, self.domain) def tearDown(self): self.case_repeater.delete() self.form_repeater.delete() FormProcessorTestUtils.delete_all_cases_forms_ledgers(self.domain) delete_all_repeat_records() super(RepeaterTest, self).tearDown() @run_with_all_backends 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') @run_with_all_backends def test_repeater_failed_sends(self): """ This tests records that fail are requeued later """ def now(): return datetime.utcnow() repeat_records = RepeatRecord.all(domain=self.domain, due_before=now()) self.assertEqual(len(repeat_records), 2) for repeat_record in repeat_records: with patch( 'corehq.apps.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) next_check_time = now() + timedelta(minutes=60) 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) @run_with_all_backends 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) @run_with_all_backends 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.apps.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(), ) # The following is pretty fickle and depends on which of # - corehq.apps.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) @run_with_all_backends def test_check_repeat_records(self): self.assertEqual(len(RepeatRecord.all()), 2) with patch('corehq.apps.repeaters.models.simple_post') as mock_fire: check_repeaters() self.assertEqual(mock_fire.call_count, 2) with patch('corehq.apps.repeaters.models.simple_post') as mock_fire: check_repeaters() self.assertEqual(mock_fire.call_count, 0) @run_with_all_backends 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.apps.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.apps.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.apps.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) @run_with_all_backends def test_process_repeat_record_locking(self): self.assertEqual(len(RepeatRecord.all()), 2) with patch('corehq.apps.repeaters.tasks.process_repeat_record') as mock_process: check_repeaters() self.assertEqual(mock_process.delay.call_count, 2) with patch('corehq.apps.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.apps.repeaters.tasks.process_repeat_record') as mock_process: check_repeaters() self.assertEqual(mock_process.delay.call_count, 2) @run_with_all_backends def test_automatic_cancel_repeat_record(self): repeat_record = self.case_repeater.register(CaseAccessors(self.domain).get_case(CASE_ID)) repeat_record.overall_tries = 1 with patch('corehq.apps.repeaters.models.simple_post', side_effect=Exception('Boom!')): repeat_record.fire() self.assertEqual(2, repeat_record.overall_tries) with patch('corehq.apps.repeaters.models.simple_post', side_effect=Exception('Boom!')): 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)
def zapier_subscription_post_delete(sender, instance, *args, **kwargs): repeater = FormRepeater.get(instance.repeater_id) repeater.delete()
class RepeaterTest(BaseRepeaterTest): def setUp(self): self.domain = "test-domain" create_domain(self.domain) self.case_repeater = CaseRepeater( domain=self.domain, url='case-repeater-url', version=V1, ) self.case_repeater.save() self.form_repeater = FormRepeater( domain=self.domain, url='form-repeater-url', ) self.form_repeater.save() self.log = [] self.post_xml(xform_xml, self.domain) def tearDown(self): self.case_repeater.delete() self.form_repeater.delete() XFormInstance.get(instance_id).delete() repeat_records = RepeatRecord.all() for repeat_record in repeat_records: repeat_record.delete() def test_skip_device_logs(self): devicelog_xml = xform_xml_template.format(DEVICE_LOG_XMLNS, '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 test_repeater_failed_sends(self): """ This tests records that fail to send three times """ def now(): return datetime.utcnow() repeat_records = RepeatRecord.all(domain=self.domain, due_before=now()) self.assertEqual(len(repeat_records), 2) for repeat_record in repeat_records: with patch( 'corehq.apps.repeaters.models.simple_post_with_cached_timeout', return_value=MockResponse(status_code=404)) as mock_post: repeat_record.fire() self.assertEqual(mock_post.call_count, 3) repeat_record.save() next_check_time = now() + timedelta(minutes=60) 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, next_check=now) self.assertIsNone(record.last_checked) record.update_failure() 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 = RepeatRecord.all(domain=self.domain, due_before=datetime.utcnow()) mocked_responses = [MockResponse(status_code=404), MockResponse(status_code=200)] for repeat_record in repeat_records: with patch( 'corehq.apps.repeaters.models.simple_post_with_cached_timeout', side_effect=mocked_responses) as mock_post: repeat_record.fire() self.assertEqual(mock_post.call_count, 2) mock_post.assert_any_call( repeat_record.get_payload(), repeat_record.repeater.get_url(repeat_record), headers=repeat_record.repeater.get_headers(repeat_record), force_send=False, timeout=POST_TIMEOUT, ) repeat_record.save() # The following is pretty fickle and depends on which of # - corehq.apps.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(update_xform_xml, self.domain) self.assertEqual(len(self.repeat_records(self.domain)), 2) def test_check_repeat_records(self): self.assertEqual(len(RepeatRecord.all()), 2) with patch('corehq.apps.repeaters.models.simple_post_with_cached_timeout') as mock_fire: check_repeaters() self.assertEqual(mock_fire.call_count, 2) with patch('corehq.apps.repeaters.models.simple_post_with_cached_timeout') 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.apps.repeaters.tasks.process_repeat_record') as mock_process: check_repeaters() self.assertEqual(mock_process.delay.call_count, 2) with patch('corehq.apps.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.apps.repeaters.tasks.process_repeat_record') as mock_process: check_repeaters() self.assertEqual(mock_process.delay.call_count, 2)
class RepeaterTest(BaseRepeaterTest): def setUp(self): super(RepeaterTest, self).setUp() self.domain = "test-domain" create_domain(self.domain) self.case_repeater = CaseRepeater( domain=self.domain, url='case-repeater-url', ) self.case_repeater.save() self.form_repeater = FormRepeater( domain=self.domain, url='form-repeater-url', ) self.form_repeater.save() self.log = [] self.post_xml(self.xform_xml, self.domain) def tearDown(self): self.case_repeater.delete() self.form_repeater.delete() FormProcessorTestUtils.delete_all_xforms(self.domain) delete_all_repeat_records() super(RepeaterTest, self).tearDown() @run_with_all_backends 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') @run_with_all_backends def test_repeater_failed_sends(self): """ This tests records that fail to send three times """ def now(): return datetime.utcnow() repeat_records = RepeatRecord.all(domain=self.domain, due_before=now()) self.assertEqual(len(repeat_records), 2) for repeat_record in repeat_records: with patch( 'corehq.apps.repeaters.models.simple_post_with_cached_timeout', return_value=MockResponse( status_code=404, reason='Not Found')) as mock_post: repeat_record.fire() self.assertEqual(mock_post.call_count, 3) repeat_record.save() next_check_time = now() + timedelta(minutes=60) 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) @run_with_all_backends def test_update_failure_next_check(self): now = datetime.utcnow() record = RepeatRecord(domain=self.domain, next_check=now) self.assertIsNone(record.last_checked) record.set_next_try() self.assertTrue(record.last_checked > now) self.assertEqual(record.next_check, record.last_checked + MIN_RETRY_WAIT) @run_with_all_backends def test_repeater_successful_send(self): repeat_records = RepeatRecord.all(domain=self.domain, due_before=datetime.utcnow()) mocked_responses = [ MockResponse(status_code=404, reason='Not Found'), MockResponse(status_code=200, reason='No Reason') ] for repeat_record in repeat_records: with patch( 'corehq.apps.repeaters.models.simple_post_with_cached_timeout', side_effect=mocked_responses) as mock_post: repeat_record.fire() self.assertEqual(mock_post.call_count, 2) mock_post.assert_any_call( repeat_record.get_payload(), repeat_record.repeater.get_url(repeat_record), headers=repeat_record.repeater.get_headers(repeat_record), force_send=False, timeout=POST_TIMEOUT, ) repeat_record.save() # The following is pretty fickle and depends on which of # - corehq.apps.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) @run_with_all_backends def test_check_repeat_records(self): self.assertEqual(len(RepeatRecord.all()), 2) with patch( 'corehq.apps.repeaters.models.simple_post_with_cached_timeout' ) as mock_fire: check_repeaters() self.assertEqual(mock_fire.call_count, 2) with patch( 'corehq.apps.repeaters.models.simple_post_with_cached_timeout' ) as mock_fire: check_repeaters() self.assertEqual(mock_fire.call_count, 0) @run_with_all_backends def test_process_repeat_record_locking(self): self.assertEqual(len(RepeatRecord.all()), 2) with patch('corehq.apps.repeaters.tasks.process_repeat_record' ) as mock_process: check_repeaters() self.assertEqual(mock_process.delay.call_count, 2) with patch('corehq.apps.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.apps.repeaters.tasks.process_repeat_record' ) as mock_process: check_repeaters() self.assertEqual(mock_process.delay.call_count, 2)
class RepeaterTest(BaseRepeaterTest): def setUp(self): self.domain = "test-domain" create_domain(self.domain) self.case_repeater = CaseRepeater( domain=self.domain, url='case-repeater-url', version=V1, ) self.case_repeater.save() self.form_repeater = FormRepeater( domain=self.domain, url='form-repeater-url', ) self.form_repeater.save() self.log = [] self.post_xml(xform_xml, self.domain) def clear_log(self): for i in range(len(self.log)): self.log.pop() def make_post_fn(self, status_codes): status_codes = iter(status_codes) def post_fn(data, url, headers=None): status_code = status_codes.next() self.log.append((url, status_code, data, headers)) class resp: status = status_code return resp return post_fn def tearDown(self): self.case_repeater.delete() self.form_repeater.delete() XFormInstance.get(instance_id).delete() repeat_records = RepeatRecord.all() for repeat_record in repeat_records: repeat_record.delete() def test_repeater(self): # this test should probably be divided into more units CommCareCase.get(case_id) def now(): return datetime.utcnow() repeat_records = RepeatRecord.all(domain=self.domain, due_before=now()) self.assertEqual(len(repeat_records), 2) self.clear_log() records_by_repeater_id = {} for repeat_record in repeat_records: repeat_record.fire(post_fn=self.make_post_fn([404, 404, 404])) repeat_record.save() records_by_repeater_id[repeat_record.repeater_id] = repeat_record for (url, status, data, headers) in self.log: self.assertEqual(status, 404) self.clear_log() next_check_time = now() + timedelta(minutes=60) 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 + timedelta(seconds=2), ) self.assertEqual(len(repeat_records), 2) for repeat_record in repeat_records: self.assertLess(abs(next_check_time - repeat_record.next_check), timedelta(seconds=3)) repeat_record.fire(post_fn=self.make_post_fn([404, 200])) repeat_record.save() self.assertEqual(len(self.log), 4) # The following is pretty fickle and depends on which of # - corehq.apps.repeaters.signals # - casexml.apps.case.signals # gets loaded first. # This is deterministic but easily affected by minor code changes # check case stuff rec = records_by_repeater_id[self.case_repeater.get_id] self.assertEqual(self.log[1][:2], (self.case_repeater.get_url(rec), 200)) self.assertIn('server-modified-on', self.log[1][3]) check_xml_line_by_line(self, self.log[1][2], case_block) # check form stuff rec = records_by_repeater_id[self.form_repeater.get_id] self.assertEqual(self.log[3][:3], (self.form_repeater.get_url(rec), 200, xform_xml)) self.assertIn('received-on', self.log[3][3]) repeat_records = RepeatRecord.all( domain=self.domain, due_before=next_check_time, ) 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(update_xform_xml, self.domain) self.assertEqual(len(self.repeat_records(self.domain)), 2)