def test_clone_repeaters(self): from corehq.motech.repeaters.models import Repeater from corehq.motech.repeaters.models import CaseRepeater from corehq.motech.repeaters.models import FormRepeater self.assertEqual(0, len(Repeater.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) self.make_clone(include=['repeaters']) cloned_repeaters = Repeater.by_domain(self.new_domain) self.assertEqual(2, len(cloned_repeaters)) self.assertEqual({'CaseRepeater', 'FormRepeater'}, {repeater.doc_type for repeater in cloned_repeaters})
def test_get_list(self): # Add a form repeater and check that it comes back form_repeater = FormRepeater(domain=self.domain.name, url='http://example.com/forwarding/form') form_repeater.save() self.addCleanup(form_repeater.delete) backend_id = form_repeater._id response = self._assert_auth_get_resource(self.list_endpoint) self.assertEqual(response.status_code, 200) api_repeaters = json.loads(response.content)['objects'] self.assertEqual(len(api_repeaters), 1) self.assertEqual(api_repeaters[0]['id'], backend_id) self.assertEqual(api_repeaters[0]['url'], form_repeater.url) self.assertEqual(api_repeaters[0]['domain'], form_repeater.domain) self.assertEqual(api_repeaters[0]['type'], 'FormRepeater') # Add a case repeater and check that both come back case_repeater = CaseRepeater(domain=self.domain.name, url='http://example.com/forwarding/case') case_repeater.save() self.addCleanup(case_repeater.delete) backend_id = case_repeater._id response = self._assert_auth_get_resource(self.list_endpoint) self.assertEqual(response.status_code, 200) api_repeaters = json.loads(response.content)['objects'] self.assertEqual(len(api_repeaters), 2) api_case_repeater = [r for r in api_repeaters if r['type'] == 'CaseRepeater'][0] self.assertEqual(api_case_repeater['id'], case_repeater._id) self.assertEqual(api_case_repeater['url'], case_repeater.url) self.assertEqual(api_case_repeater['domain'], case_repeater.domain)
def setUpClass(cls): super(TestRepeatersDBAccessors, cls).setUpClass() repeater = CaseRepeater(domain=cls.domain, ) cls.repeaters = [repeater] for repeater in cls.repeaters: repeater.save()
class RepeaterFailureTest(BaseRepeaterTest): domain = 'repeat-fail' def setUp(self): super().setUp() self.connx = ConnectionSettings.objects.create( domain=self.domain, url='case-repeater-url', ) self.repeater = CaseRepeater( domain=self.domain, connection_settings_id=self.connx.id, ) self.repeater.save() self.post_xml(self.xform_xml, self.domain) def tearDown(self): self.repeater.delete() self.connx.delete() FormProcessorTestUtils.delete_all_cases_forms_ledgers(self.domain) delete_all_repeat_records() super().tearDown() @run_with_all_backends def test_get_payload_exception(self): repeat_record = self.repeater.register( CaseAccessors(self.domain).get_case(CASE_ID)) with self.assertRaises(Exception): with patch.object(CaseRepeater, 'get_payload', side_effect=Exception('Boom!')): repeat_record.fire() self.assertEqual(repeat_record.failure_reason, 'Boom!') self.assertFalse(repeat_record.succeeded) @run_with_all_backends def test_failure(self): repeat_record = self.repeater.register( CaseAccessors(self.domain).get_case(CASE_ID)) with patch('corehq.motech.repeaters.models.simple_post', side_effect=Exception('Boom!')): repeat_record.fire() self.assertEqual(repeat_record.failure_reason, 'Boom!') self.assertFalse(repeat_record.succeeded) @run_with_all_backends def test_success(self): repeat_record = self.repeater.register( CaseAccessors(self.domain).get_case(CASE_ID)) repeat_record = RepeatRecord.get(repeat_record.record_id) # Should be marked as successful after a successful run with patch('corehq.motech.repeaters.models.simple_post' ) as mock_simple_post: mock_simple_post.return_value.status_code = 200 repeat_record.fire() self.assertTrue(repeat_record.succeeded)
def setUpClass(cls): super(TestRepeatersDBAccessors, cls).setUpClass() repeater = CaseRepeater( domain=cls.domain, ) cls.repeaters = [ repeater ] for repeater in cls.repeaters: repeater.save()
class TestRepeaterPause(BaseRepeaterTest): domain = 'rep-pause' def setUp(self): super().setUp() self.connx = ConnectionSettings.objects.create( domain=self.domain, url='case-repeater-url', ) self.repeater = CaseRepeater( domain=self.domain, connection_settings_id=self.connx.id, ) self.repeater.save() self.post_xml(self.xform_xml, self.domain) self.repeater = reloaded(self.repeater) def tearDown(self): self.repeater.delete() self.connx.delete() FormProcessorTestUtils.delete_all_cases_forms_ledgers(self.domain) delete_all_repeat_records() super(TestRepeaterPause, self).tearDown() @run_with_all_backends 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_obj).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)
class RepeaterFailureTest(BaseRepeaterTest): domain = 'repeat-fail' def setUp(self): super().setUp() # Create the case before creating the repeater, so that the # repeater doesn't fire for the case creation. Each test # registers this case, and the repeater will fire then. 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='case_json', ) self.repeater.save() def tearDown(self): self.repeater.delete() self.connx.delete() FormProcessorTestUtils.delete_all_cases_forms_ledgers(self.domain) delete_all_repeat_records() super().tearDown() def test_get_payload_exception(self): repeat_record = self.repeater.register( CommCareCase.objects.get_case(CASE_ID, self.domain)) with self.assertRaises(Exception): with patch.object(CaseRepeater, 'get_payload', side_effect=Exception('Boom!')): repeat_record.fire() self.assertEqual(repeat_record.failure_reason, 'Boom!') self.assertFalse(repeat_record.succeeded) def test_failure(self): case = CommCareCase.objects.get_case(CASE_ID, self.domain) 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)
class RepeaterFailureTest(BaseRepeaterTest): def setUp(self): super(RepeaterFailureTest, self).setUp() self.domain_name = "test-domain" self.domain = create_domain(self.domain_name) self.repeater = CaseRepeater( domain=self.domain_name, url='case-repeater-url', ) self.repeater.save() self.post_xml(self.xform_xml, self.domain_name) def tearDown(self): self.domain.delete() self.repeater.delete() delete_all_repeat_records() super(RepeaterFailureTest, self).tearDown() @run_with_all_backends def test_get_payload_exception(self): repeat_record = self.repeater.register( CaseAccessors(self.domain_name).get_case(CASE_ID)) with self.assertRaises(Exception): with patch.object(CaseRepeater, 'get_payload', side_effect=Exception('Boom!')): repeat_record.fire() self.assertEquals(repeat_record.failure_reason, 'Boom!') self.assertFalse(repeat_record.succeeded) @run_with_all_backends def test_failure(self): repeat_record = self.repeater.register( CaseAccessors(self.domain_name).get_case(CASE_ID)) with patch('corehq.motech.repeaters.models.simple_post', side_effect=Exception('Boom!')): repeat_record.fire() self.assertEquals(repeat_record.failure_reason, 'Boom!') self.assertFalse(repeat_record.succeeded) # Should be marked as successful after a successful run with patch('corehq.motech.repeaters.models.simple_post' ) as mock_simple_post: mock_simple_post.return_value.status_code = 200 repeat_record.fire() self.assertTrue(repeat_record.succeeded)
class TestRepeaterPause(BaseRepeaterTest): def setUp(self): super(TestRepeaterPause, self).setUp() self.domain_name = "test-domain" self.domain = create_domain(self.domain_name) self.repeater = CaseRepeater( domain=self.domain_name, url='case-repeater-url', ) self.repeater.save() self.post_xml(self.xform_xml, self.domain_name) self.repeat_record = self.repeater.register( CaseAccessors(self.domain).get_case(CASE_ID)) @run_with_all_backends @flag_enabled('ENABLE_REPEATER_EDIT_AND_PAUSE') 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 tearDown(self): self.domain.delete() self.repeater.delete() delete_all_repeat_records() super(TestRepeaterPause, self).tearDown()
class TestRepeaterDeleted(BaseRepeaterTest): domain = 'rep-deleted' def setUp(self): super().setUp() 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='case_json', ) self.repeater.save() self.post_xml(self.xform_xml, self.domain) self.repeater = reloaded(self.repeater) def tearDown(self): self.repeater.delete() # Making sure that SQL repeater are deleted after retire is called. SQLRepeater.all_objects.all().delete() self.connx.delete() FormProcessorTestUtils.delete_all_cases_forms_ledgers(self.domain) delete_all_repeat_records() super().tearDown() def test_trigger_when_deleted(self): self.repeater.retire() with patch.object(RepeatRecord, 'fire') as mock_fire: self.repeat_record = self.repeater.register( CommCareCase.objects.get_case(CASE_ID, self.domain)) _process_repeat_record(self.repeat_record) self.assertEqual(mock_fire.call_count, 0) self.assertEqual(self.repeat_record.doc_type, "RepeatRecord-Deleted") def test_paused_then_deleted(self): self.repeater.pause() self.repeater.retire() with patch.object(RepeatRecord, 'fire') as mock_fire: self.repeat_record = self.repeater.register( CommCareCase.objects.get_case(CASE_ID, self.domain)) _process_repeat_record(self.repeat_record) self.assertEqual(mock_fire.call_count, 0) self.assertEqual(self.repeat_record.doc_type, "RepeatRecord-Deleted")
class TestRepeaterDeleted(BaseRepeaterTest): domain = 'rep-deleted' def setUp(self): super().setUp() self.connx = ConnectionSettings.objects.create( domain=self.domain, url='case-repeater-url', ) self.repeater = CaseRepeater( domain=self.domain, connection_settings_id=self.connx.id, ) self.repeater.save() self.post_xml(self.xform_xml, self.domain) self.repeater = reloaded(self.repeater) def tearDown(self): self.repeater.delete() self.connx.delete() FormProcessorTestUtils.delete_all_cases_forms_ledgers(self.domain) delete_all_repeat_records() super().tearDown() @run_with_all_backends def test_trigger_when_deleted(self): self.repeater.retire() with patch.object(RepeatRecord, 'fire') as mock_fire: self.repeat_record = self.repeater.register( CaseAccessors(self.domain_obj).get_case(CASE_ID)) process_repeat_record(self.repeat_record) self.assertEqual(mock_fire.call_count, 0) self.assertEqual(self.repeat_record.doc_type, "RepeatRecord-Deleted") @run_with_all_backends def test_paused_then_deleted(self): self.repeater.pause() self.repeater.retire() with patch.object(RepeatRecord, 'fire') as mock_fire: self.repeat_record = self.repeater.register( CaseAccessors(self.domain_obj).get_case(CASE_ID)) process_repeat_record(self.repeat_record) self.assertEqual(mock_fire.call_count, 0) self.assertEqual(self.repeat_record.doc_type, "RepeatRecord-Deleted")
def test_save_with_no_connection_settings(self): repeater = CaseRepeater( domain='test-domain', url='https://example.com/create-case/', format='case_json', white_listed_case_types=['test_case_type'], ) self.addCleanup(repeater.delete) repeater.save() num_case_repeaters = SQLCaseRepeater.objects.filter( repeater_id=repeater._id).count() self.assertEqual(num_case_repeaters, 1) num_repeaters = SQLRepeater.objects.filter( repeater_id=repeater._id).count() self.assertEqual(num_repeaters, 1)
class TestRepeaterPause(BaseRepeaterTest): def setUp(self): super(TestRepeaterPause, self).setUp() self.domain_name = "test-domain" self.domain = create_domain(self.domain_name) self.repeater = CaseRepeater( domain=self.domain_name, url='case-repeater-url', ) self.repeater.save() self.post_xml(self.xform_xml, self.domain_name) @run_with_all_backends 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 tearDown(self): self.domain.delete() self.repeater.delete() delete_all_repeat_records() super(TestRepeaterPause, self).tearDown()
class RepeaterFailureTest(BaseRepeaterTest): def setUp(self): super(RepeaterFailureTest, self).setUp() self.domain_name = "test-domain" self.domain = create_domain(self.domain_name) self.repeater = CaseRepeater( domain=self.domain_name, url='case-repeater-url', ) self.repeater.save() self.post_xml(self.xform_xml, self.domain_name) def tearDown(self): self.domain.delete() self.repeater.delete() delete_all_repeat_records() super(RepeaterFailureTest, self).tearDown() @run_with_all_backends def test_get_payload_exception(self): repeat_record = self.repeater.register(CaseAccessors(self.domain_name).get_case(CASE_ID)) with self.assertRaises(Exception): with patch.object(CaseRepeater, 'get_payload', side_effect=Exception('Boom!')): repeat_record.fire() self.assertEquals(repeat_record.failure_reason, 'Boom!') self.assertFalse(repeat_record.succeeded) @run_with_all_backends def test_failure(self): repeat_record = self.repeater.register(CaseAccessors(self.domain_name).get_case(CASE_ID)) with patch('corehq.motech.repeaters.models.simple_post', side_effect=Exception('Boom!')): repeat_record.fire() self.assertEquals(repeat_record.failure_reason, 'Boom!') self.assertFalse(repeat_record.succeeded) # Should be marked as successful after a successful run with patch('corehq.motech.repeaters.models.simple_post') as mock_simple_post: mock_simple_post.return_value.status_code = 200 repeat_record.fire() self.assertTrue(repeat_record.succeeded)
class TestRepeaterDeleted(BaseRepeaterTest): def setUp(self): super(TestRepeaterDeleted, self).setUp() self.domain_name = "test-domain" self.domain = create_domain(self.domain_name) self.repeater = CaseRepeater( domain=self.domain_name, url='case-repeater-url', ) self.repeater.save() self.post_xml(self.xform_xml, self.domain_name) def tearDown(self): self.domain.delete() self.repeater.delete() delete_all_repeat_records() super(TestRepeaterDeleted, self).tearDown() @run_with_all_backends def test_trigger_when_deleted(self): self.repeater.retire() with patch.object(RepeatRecord, 'fire') as mock_fire: self.repeat_record = self.repeater.register( CaseAccessors(self.domain).get_case(CASE_ID)) process_repeat_record(self.repeat_record) self.assertEqual(mock_fire.call_count, 0) self.assertEqual(self.repeat_record.doc_type, "RepeatRecord-Deleted") @run_with_all_backends def test_paused_then_deleted(self): self.repeater.pause() self.repeater.retire() with patch.object(RepeatRecord, 'fire') as mock_fire: self.repeat_record = self.repeater.register( CaseAccessors(self.domain).get_case(CASE_ID)) process_repeat_record(self.repeat_record) self.assertEqual(mock_fire.call_count, 0) self.assertEqual(self.repeat_record.doc_type, "RepeatRecord-Deleted")
def test_clone_repeaters(self): from corehq.motech.repeaters.models import Repeater from corehq.motech.repeaters.models import CaseRepeater from corehq.motech.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 TestRepeaterDeleted(BaseRepeaterTest): def setUp(self): super(TestRepeaterDeleted, self).setUp() self.domain_name = "test-domain" self.domain = create_domain(self.domain_name) self.repeater = CaseRepeater( domain=self.domain_name, url='case-repeater-url', ) self.repeater.save() self.post_xml(self.xform_xml, self.domain_name) def tearDown(self): self.domain.delete() self.repeater.delete() delete_all_repeat_records() super(TestRepeaterDeleted, self).tearDown() @run_with_all_backends def test_trigger_when_deleted(self): self.repeater.retire() with patch.object(RepeatRecord, 'fire') as mock_fire: self.repeat_record = self.repeater.register(CaseAccessors(self.domain).get_case(CASE_ID)) process_repeat_record(self.repeat_record) self.assertEqual(mock_fire.call_count, 0) self.assertEqual(self.repeat_record.doc_type, "RepeatRecord-Deleted") @run_with_all_backends def test_paused_then_deleted(self): self.repeater.pause() self.repeater.retire() with patch.object(RepeatRecord, 'fire') as mock_fire: self.repeat_record = self.repeater.register(CaseAccessors(self.domain).get_case(CASE_ID)) process_repeat_record(self.repeat_record) self.assertEqual(mock_fire.call_count, 0) self.assertEqual(self.repeat_record.doc_type, "RepeatRecord-Deleted")
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_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) @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.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) 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.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) @run_with_all_backends 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) @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.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) @run_with_all_backends 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) @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.motech.repeaters.models.simple_post', side_effect=Exception('Boom!')): repeat_record.fire() self.assertEqual(2, repeat_record.overall_tries) with patch('corehq.motech.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)
class TestRepeaterFormat(BaseRepeaterTest): @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(TestRepeaterFormat, self).setUp() self.domain = "test-domain" create_domain(self.domain) self.post_xml(self.xform_xml, self.domain) self.repeater = CaseRepeater( domain=self.domain, url='case-repeater-url', format='new_format', ) self.repeater.save() def tearDown(self): self.repeater.delete() FormProcessorTestUtils.delete_all_cases_forms_ledgers(self.domain) delete_all_repeat_records() super(TestRepeaterFormat, self).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) @run_with_all_backends def test_new_format_payload(self): repeat_record = self.repeater.register( CaseAccessors(self.domain).get_case(CASE_ID)) with patch('corehq.motech.repeaters.models.simple_post') as mock_post: mock_post.return_value.status_code = 200 repeat_record.fire() headers = self.repeater.get_headers(repeat_record) mock_post.assert_called_with( self.payload, self.repeater.url, headers=headers, timeout=POST_TIMEOUT, auth=self.repeater.get_auth(), verify=self.repeater.verify, ) def test_get_format_by_deprecated_name(self): self.assertIsInstance( CaseRepeater( domain=self.domain, url='case-repeater-url', format='new_format_alias', ).generator, self.new_generator)
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, ) 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, ) self.form_repeater.save() self.log = [] with patch('corehq.motech.repeaters.models.simple_post', 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) @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) for repeat_record in self.repeat_records(): self.assertNotEqual(repeat_record.payload_id, '1234') @run_with_all_backends 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) @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 = 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) @run_with_all_backends 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) @run_with_all_backends def test_repeater_successful_send(self): repeat_records = self.repeat_records() for repeat_record in repeat_records: with patch('corehq.motech.repeaters.models.simple_post') as mock_post, \ patch.object(ConnectionSettings, 'get_auth_manager') as mock_manager: mock_post.return_value.status_code = 200 mock_manager.return_value = 'MockAuthManager' repeat_record.fire() self.assertEqual(mock_post.call_count, 1) mock_post.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, ) # 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) @run_with_all_backends 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_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(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_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 self.repeat_records(): 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 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_post') 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) @run_with_all_backends 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) @run_with_all_backends def test_automatic_cancel_repeat_record(self): repeat_record = self.case_repeater.register( CaseAccessors(self.domain).get_case(CASE_ID)) self.assertEqual(1, repeat_record.overall_tries) with patch('corehq.motech.repeaters.models.simple_post', 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 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 = [] with patch('corehq.motech.repeaters.models.simple_post') 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.form_repeater.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) @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) for repeat_record in self.repeat_records(): self.assertNotEqual(repeat_record.payload_id, '1234') @run_with_all_backends 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) @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 = 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) @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 = self.repeat_records() 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 = 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) @run_with_all_backends 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_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(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_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 self.repeat_records(): 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 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_post') 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) @run_with_all_backends def test_process_repeat_record_locking(self): self.assertEqual(len(self.repeat_records()), 2) with patch('corehq.motech.repeaters.tasks.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.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)) self.assertEqual(1, repeat_record.overall_tries) with patch('corehq.motech.repeaters.models.simple_post', 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): @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(TestRepeaterFormat, self).setUp() self.domain = "test-domain" create_domain(self.domain) self.post_xml(self.xform_xml, self.domain) self.repeater = CaseRepeater( domain=self.domain, url='case-repeater-url', format='new_format', ) self.repeater.save() def tearDown(self): self.repeater.delete() FormProcessorTestUtils.delete_all_cases_forms_ledgers(self.domain) delete_all_repeat_records() super(TestRepeaterFormat, self).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) @run_with_all_backends def test_new_format_payload(self): repeat_record = self.repeater.register(CaseAccessors(self.domain).get_case(CASE_ID)) with patch('corehq.motech.repeaters.models.simple_post') as mock_post: mock_post.return_value.status_code = 200 repeat_record.fire() headers = self.repeater.get_headers(repeat_record) mock_post.assert_called_with( self.payload, self.repeater.url, headers=headers, timeout=POST_TIMEOUT, auth=self.repeater.get_auth(), verify=self.repeater.verify, ) def test_get_format_by_deprecated_name(self): self.assertIsInstance(CaseRepeater( domain=self.domain, url='case-repeater-url', format='new_format_alias', ).generator, self.new_generator)
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', ) self.repeater.save() def tearDown(self): self.repeater.delete() 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) @run_with_all_backends def test_new_format_payload(self): repeat_record = self.repeater.register( CaseAccessors(self.domain).get_case(CASE_ID)) with patch('corehq.motech.repeaters.models.simple_post') as mock_post, \ patch.object(ConnectionSettings, 'get_auth_manager') as mock_manager: mock_post.return_value.status_code = 200 mock_manager.return_value = 'MockAuthManager' repeat_record.fire() headers = self.repeater.get_headers(repeat_record) mock_post.assert_called_with( self.domain, self.connx.url, self.payload, auth_manager='MockAuthManager', headers=headers, notify_addresses=[], payload_id='ABC123CASEID', verify=self.repeater.verify, ) def test_get_format_by_deprecated_name(self): self.assertIsInstance( CaseRepeater( domain=self.domain, url='case-repeater-url', format='new_format_alias', ).generator, self.new_generator)
class CaseRepeaterTest(BaseRepeaterTest, TestXmlMixin): domain = "case-rep" def setUp(self): super().setUp() self.connx = ConnectionSettings.objects.create( domain=self.domain, url="case-repeater-url", ) self.repeater = CaseRepeater( domain=self.domain, connection_settings_id=self.connx.id, ) self.repeater.save() def tearDown(self): FormProcessorTestUtils.delete_all_cases(self.domain) delete_all_repeat_records() self.repeater.delete() self.connx.delete() super().tearDown() @run_with_all_backends def test_case_close_format(self): # create a case self.post_xml(self.xform_xml, self.domain) repeat_records = self.repeat_records(self.domain).all() payload = repeat_records[0].get_payload() self.assertXmlHasXpath(payload, '//*[local-name()="case"]') self.assertXmlHasXpath(payload, '//*[local-name()="create"]') # close the case CaseFactory(self.domain).close_case(CASE_ID) close_payload = self.repeat_records(self.domain).all()[1].get_payload() self.assertXmlHasXpath(close_payload, '//*[local-name()="case"]') self.assertXmlHasXpath(close_payload, '//*[local-name()="close"]') @run_with_all_backends def test_excluded_case_types_are_not_forwarded(self): self.repeater.white_listed_case_types = ['planet'] self.repeater.save() white_listed_case = CaseBlock.deprecated_init( case_id="a_case_id", create=True, case_type="planet", ).as_xml() CaseFactory(self.domain).post_case_blocks([white_listed_case]) self.assertEqual(1, len(self.repeat_records(self.domain).all())) non_white_listed_case = CaseBlock.deprecated_init( case_id="b_case_id", create=True, case_type="cat", ).as_xml() CaseFactory(self.domain).post_case_blocks([non_white_listed_case]) self.assertEqual(1, len(self.repeat_records(self.domain).all())) @run_with_all_backends def test_black_listed_user_cases_do_not_forward(self): self.repeater.black_listed_users = ['black_listed_user'] self.repeater.save() black_list_user_id = 'black_listed_user' # case-creations by black-listed users shouldn't be forwarded black_listed_user_case = CaseBlock.deprecated_init( case_id="b_case_id", create=True, case_type="planet", owner_id="owner", user_id=black_list_user_id).as_text() xform_xml = XFORM_XML_TEMPLATE.format( "https://www.commcarehq.org/test/repeater/", black_list_user_id, '1234', black_listed_user_case, ) self.post_xml(xform_xml, self.domain) self.assertEqual(0, len(self.repeat_records(self.domain).all())) # case-creations by normal users should be forwarded normal_user_case = CaseBlock.deprecated_init( case_id="a_case_id", create=True, case_type="planet", owner_id="owner", user_id="normal_user").as_text() xform_xml = XFORM_XML_TEMPLATE.format( "https://www.commcarehq.org/test/repeater/", USER_ID, '6789', normal_user_case, ) self.post_xml(xform_xml, self.domain) self.assertEqual(1, len(self.repeat_records(self.domain).all())) # case-updates by black-listed users shouldn't be forwarded black_listed_user_case = CaseBlock.deprecated_init( case_id="b_case_id", case_type="planet", owner_id="owner", user_id=black_list_user_id, ).as_text() xform_xml = XFORM_XML_TEMPLATE.format( "https://www.commcarehq.org/test/repeater/", black_list_user_id, '2345', black_listed_user_case, ) self.post_xml(xform_xml, self.domain) self.assertEqual(1, len(self.repeat_records(self.domain).all())) # case-updates by normal users should be forwarded normal_user_case = CaseBlock.deprecated_init( case_id="a_case_id", case_type="planet", owner_id="owner", user_id="normal_user", ).as_text() xform_xml = XFORM_XML_TEMPLATE.format( "https://www.commcarehq.org/test/repeater/", USER_ID, '3456', normal_user_case, ) self.post_xml(xform_xml, self.domain) self.assertEqual(2, len(self.repeat_records(self.domain).all()))