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
Esempio n. 2
0
    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)
Esempio n. 3
0
    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})
Esempio n. 4
0
    def setUpClass(cls):
        super(TestRepeatersDBAccessors, cls).setUpClass()
        repeater = CaseRepeater(domain=cls.domain, )
        cls.repeaters = [repeater]

        for repeater in cls.repeaters:
            repeater.save()
Esempio n. 5
0
    def setUpClass(cls):
        cls.domain_1 = 'caserepeater-migration'
        cls.domain_2 = 'migration-caserepeater'
        cls.date = datetime.utcnow().strftime('%Y-%m-%dT%H-%M-%S')
        cls.conn = ConnectionSettings(domain=cls.domain_1,
                                      url='http://url.com')
        cls.conn.save()
        cls.couch_repeater_1 = CaseRepeater(
            domain=cls.domain_1,
            connection_settings_id=cls.conn.id,
            format='case_json',
        )
        cls.couch_repeater_2 = CaseRepeater(
            domain=cls.domain_2,
            connection_settings_id=cls.conn.id,
            format='case_json',
        )
        cls.couch_repeater_3 = CaseRepeater(
            domain=cls.domain_1,
            connection_settings_id=cls.conn.id,
            format='case_json',
        )
        cls.repeaters = [
            cls.couch_repeater_1, cls.couch_repeater_2, cls.couch_repeater_3
        ]

        for repeater in cls.repeaters:
            repeater.save(sync_to_sql=False)
        return super(TestMigrationCommand, cls).setUpClass()
Esempio n. 6
0
 def setUp(self):
     super().setUp()
     self.repeater = CaseRepeater(
         domain=self.domain,
         url="case-repeater-url",
     )
     self.repeater.save()
Esempio n. 7
0
 def setUp(self):
     super().setUp()
     self.repeater = CaseRepeater(
         domain=self.domain,
         url='case-repeater-url',
     )
     self.repeater.save()
     self.post_xml(self.xform_xml, self.domain)
 def test_repeaters_are_synced_to_couch(self):
     for sql_repeater in self.get_sql_objects(SQLCaseRepeater):
         sql_repeater.save()
         couch_repeater_dict = CaseRepeater.get_db().get(
             sql_repeater.repeater_id)
         self.assertIsNotNone(couch_repeater_dict)
         couch_repeater = CaseRepeater.wrap(couch_repeater_dict)
         self.addCleanup(couch_repeater.delete)
         self._assert_same_repeater_objects(sql_repeater, couch_repeater)
Esempio n. 9
0
    def setUpClass(cls):
        super(TestRepeatersDBAccessors, cls).setUpClass()
        repeater = CaseRepeater(
            domain=cls.domain,
        )
        cls.repeaters = [
            repeater
        ]

        for repeater in cls.repeaters:
            repeater.save()
Esempio n. 10
0
    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)
Esempio n. 11
0
    def setUp(self):
        super(TestRepeaterFormat, self).setUp()

        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 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 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)
Esempio n. 14
0
    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)
        self.repeat_record = self.repeater.register(
            CaseAccessors(self.domain).get_case(CASE_ID))
Esempio n. 15
0
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)
Esempio n. 16
0
 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)
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)
Esempio n. 18
0
 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)
    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)
Esempio n. 20
0
 def setUpClass(cls):
     domain = 'caserepeater-migration'
     cls.conn = ConnectionSettings(domain=domain, url='http://url.com')
     cls.conn.save()
     cls.couch_repeater_obj = CaseRepeater(
         _id='id_1',
         domain=domain,
         connection_settings_id=cls.conn.id,
         white_listed_case_types=['white_case', 'black_case'],
         black_listed_users=['user1'],
         paused=False,
         format='case_json',
     )
     cls.sql_repeater_obj = SQLCaseRepeater(
         domain=domain,
         connection_settings=cls.conn,
         white_listed_case_types=['white_case', 'black_case'],
         black_listed_users=['user1'],
         is_paused=False,
         format='case_json',
         repeater_id='id_1',
     )
     cls.incorrect_sql_repeater_obj = SQLCaseRepeater(
         domain=domain,
         connection_settings=cls.conn,
         white_listed_case_types=['black_case'],
         black_listed_users=['user2'],
         is_paused=True,
         format='case_json',
         repeater_id='id_1',
     )
     super().setUpClass()
Esempio n. 21
0
 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)
Esempio n. 22
0
    def allowed_to_forward(self, payload):
        """
        Forward the payload if ...

        * it did not come from OpenMRS, and
        * CaseRepeater says it's OK for the case types and users of any
          of the payload's cases, and
        * this repeater forwards to the right OpenMRS server for any of
          the payload's cases.

        :param payload: An XFormInstance (not a case)

        """
        if payload.xmlns == XMLNS_OPENMRS:
            # payload came from OpenMRS. Don't send it back.
            return False

        case_blocks = extract_case_blocks(payload)
        case_ids = [case_block['@case_id'] for case_block in case_blocks]
        cases = CaseAccessors(payload.domain).get_cases(case_ids, ordered=True)
        if not any(CaseRepeater.allowed_to_forward(self, case) for case in cases):
            # If none of the case updates in the payload are allowed to
            # be forwarded, drop it.
            return False

        repeaters = [repeater for case in cases for repeater in get_case_location_ancestor_repeaters(case)]
        if repeaters and self not in repeaters:
            # This repeater points to the wrong OpenMRS server for this
            # payload. Let the right repeater handle it.
            return False

        return True
Esempio n. 23
0
    def setUpClass(cls):
        super().setUpClass()

        cls.repeater = CaseRepeater(
            domain=cls.domain,
            url="case-repeater-url",
        )
        cls.repeater.save()
Esempio n. 24
0
    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()
Esempio n. 25
0
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()
Esempio n. 26
0
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)
Esempio n. 27
0
    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
Esempio n. 28
0
    def setUpClass(cls):
        super(TestRepeatersDBAccessors, cls).setUpClass()
        cls.conn = ConnectionSettings(domain=cls.domain_1,
                                      url='http://url.com')
        cls.conn.save()
        repeater_1 = CaseRepeater(
            domain=cls.domain_1,
            format='case_json',
            connection_settings_id=cls.conn.id,
        )
        repeater_2 = CaseRepeater(
            domain=cls.domain_2,
            connection_settings_id=cls.conn.id,
            format='case_json',
        )
        cls.repeaters = [repeater_1, repeater_2]

        for repeater in cls.repeaters:
            repeater.save()
Esempio n. 29
0
    def setUpClass(cls):
        super(CaseRepeaterTest, cls).setUpClass()

        cls.domain_name = "test-domain"
        cls.domain = create_domain(cls.domain_name)
        cls.repeater = CaseRepeater(
            domain=cls.domain_name,
            url="case-repeater-url",
        )
        cls.repeater.save()
Esempio n. 30
0
    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)
Esempio n. 31
0
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()
Esempio n. 32
0
    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()
Esempio n. 33
0
    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)
        self.repeat_record = self.repeater.register(CaseAccessors(self.domain).get_case(CASE_ID))
Esempio n. 34
0
    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))
Esempio n. 35
0
 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)
Esempio n. 36
0
    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
Esempio n. 37
0
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)
Esempio n. 38
0
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)
Esempio n. 39
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 = []

        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)
Esempio n. 40
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_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)
Esempio n. 41
0
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)
Esempio n. 42
0
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")