def test_date_case_properties_for_equality(self):
        """
        Date case properties are automatically converted from string to date
        when fetching from the db, so here we want to make sure this doesn't
        interfere with our ability to compare dates for equality.
        """
        case = CommCareCase(
            domain=self.domain,
            type='test-case-type-2',
        )

        self.rule2.automaticupdaterulecriteria_set = [
            AutomaticUpdateRuleCriteria(
                property_name='property1',
                property_value='2016-02-24',
                match_type=AutomaticUpdateRuleCriteria.MATCH_EQUAL,
            ),
        ]

        case.set_case_property('property1', '2016-02-24')
        case.save()
        case = CommCareCase.get(case.get_id)
        case.server_modified_on = datetime(2015, 1, 1)
        self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property('property1', '2016-02-25')
        case.save()
        case = CommCareCase.get(case.get_id)
        case.server_modified_on = datetime(2015, 1, 1)
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.delete()
    def test_phone_number_already_in_use(self):
        case1 = CommCareCase(
            domain='case-phone-number-test',
            name='TEST1'
        )
        case1.set_case_property('contact_phone_number', '99987658765')
        case1.set_case_property('contact_phone_number_is_verified', '1')
        case1.save()

        case2 = CommCareCase(
            domain='case-phone-number-test',
            name='TEST2'
        )
        case2.set_case_property('contact_phone_number', '99987698769')
        case2.set_case_property('contact_phone_number_is_verified', '1')
        case2.save()

        self.assertIsNotNone(self.get_case_verified_number(case1))
        self.assertIsNotNone(self.get_case_verified_number(case2))

        case2.set_case_property('contact_phone_number', '99987658765')
        case2.save()
        self.assertIsNotNone(self.get_case_verified_number(case1))
        self.assertIsNone(self.get_case_verified_number(case2))

        case2.delete()
        self.get_case_verified_number(case1).delete()
        case1.delete()
    def test_date_case_properties_for_inequality(self):
        case = CommCareCase(
            domain=self.domain,
            type='test-case-type-2',
        )

        self.rule2.automaticupdaterulecriteria_set = [
            AutomaticUpdateRuleCriteria(
                property_name='property1',
                property_value='2016-02-24',
                match_type=AutomaticUpdateRuleCriteria.MATCH_NOT_EQUAL,
            ),
        ]

        case.set_case_property('property1', '2016-02-24')
        case.save()
        case = CommCareCase.get(case.get_id)
        case.server_modified_on = datetime(2015, 1, 1)
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property('property1', '2016-02-25')
        case.save()
        case = CommCareCase.get(case.get_id)
        case.server_modified_on = datetime(2015, 1, 1)
        self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.delete()
    def test_case_soft_delete(self):
        case = CommCareCase(
            domain='case-phone-number-test',
            name='TEST1'
        )
        case.set_case_property('contact_phone_number', '99987658765')
        case.set_case_property('contact_phone_number_is_verified', '1')
        case.save()
        self.assertIsNotNone(self.get_case_verified_number(case))

        case.doc_type += '-Deleted'
        case.save()
        self.assertIsNone(self.get_case_verified_number(case))
        case.delete()
    def test_match_days_since(self):
        case = CommCareCase(
            domain=self.domain,
            type='test-case-type-2',
            server_modified_on=datetime(2015, 1, 1),
        )

        self.rule2.automaticupdaterulecriteria_set = [
            AutomaticUpdateRuleCriteria(
                property_name='last_visit_date',
                property_value='30',
                match_type=AutomaticUpdateRuleCriteria.MATCH_DAYS_SINCE,
            ),
        ]
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property('last_visit_date', '2015-12-30')
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property('last_visit_date', '2015-12-03')
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property('last_visit_date', '2015-12-02')
        self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property('last_visit_date', '2015-11-01')
        self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))
    def test_match_has_value(self):
        case = CommCareCase(domain=self.domain, type="test-case-type-2", server_modified_on=datetime(2015, 1, 1))

        self.rule2.automaticupdaterulecriteria_set = [
            AutomaticUpdateRuleCriteria(
                property_name="property3", match_type=AutomaticUpdateRuleCriteria.MATCH_HAS_VALUE
            )
        ]
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property("property3", "x")
        self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property("property3", "")
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))
Example #7
0
class MessageTestCase(BaseReminderTestCase):

    def setUp(self):
        self.domain = "test"

        self.parent_case = CommCareCase(
            domain=self.domain,
            type="parent",
            name="P001",
        )
        self.parent_case.set_case_property("parent_prop1", "abc")
        self.parent_case.save()

        self.child_case = CommCareCase(
            domain=self.domain,
            type="child",
            name="P002",
            indices=[CommCareCaseIndex(
                identifier="parent",
                referenced_type="parent",
                referenced_id=self.parent_case._id,
            )],
        )
        self.child_case.set_case_property("child_prop1", "def")
        self.child_case.save()

    def tearDown(self):
        self.child_case.delete()
        self.parent_case.delete()

    def test_message(self):
        message = 'The EDD for client with ID {case.external_id} is approaching in {case.edd.days_until} days.'
        case = {'external_id': 123, 'edd': datetime.utcnow() + timedelta(days=30)}
        outcome = 'The EDD for client with ID 123 is approaching in 30 days.'
        self.assertEqual(Message.render(message, case=case), outcome)

    def test_template_params(self):
        child_result = {"case": self.child_case.case_properties()}
        child_result["case"]["parent"] = self.parent_case.case_properties()
        self.assertEqual(
            get_message_template_params(self.child_case), child_result)

        parent_result = {"case": self.parent_case.case_properties()}
        parent_result["case"]["parent"] = {}
        self.assertEqual(
            get_message_template_params(self.parent_case), parent_result)
    def test_match_not_equal(self):
        case = CommCareCase(
            domain=self.domain,
            type='test-case-type-2',
            server_modified_on=datetime(2015, 1, 1),
        )

        self.rule2.automaticupdaterulecriteria_set = [
            AutomaticUpdateRuleCriteria(
                property_name='property2',
                property_value='value2',
                match_type=AutomaticUpdateRuleCriteria.MATCH_NOT_EQUAL,
            ),
        ]
        self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property('property2', 'value2')
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property('property2', 'x')
        self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))
    def test_invalid_phone_format(self):
        case = CommCareCase(
            domain='case-phone-number-test',
            name='TEST1'
        )
        case.set_case_property('contact_phone_number', '99987658765')
        case.set_case_property('contact_phone_number_is_verified', '1')
        case.save()
        self.assertIsNotNone(self.get_case_verified_number(case))

        case.set_case_property('contact_phone_number', 'xyz')
        case.save()
        self.assertIsNone(self.get_case_verified_number(case))
        case.delete()
    def test_match_days_since(self):
        case = CommCareCase(domain=self.domain, type="test-case-type-2", server_modified_on=datetime(2015, 1, 1))

        self.rule2.automaticupdaterulecriteria_set = [
            AutomaticUpdateRuleCriteria(
                property_name="last_visit_date",
                property_value="30",
                match_type=AutomaticUpdateRuleCriteria.MATCH_DAYS_SINCE,
            )
        ]
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property("last_visit_date", "2015-12-30")
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property("last_visit_date", "2015-12-03")
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property("last_visit_date", "2015-12-02")
        self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property("last_visit_date", "2015-11-01")
        self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))
    def test_and_criteria(self):
        case = CommCareCase(domain=self.domain, type="test-case-type-2", server_modified_on=datetime(2015, 1, 1))

        self.rule2.automaticupdaterulecriteria_set = [
            AutomaticUpdateRuleCriteria(
                property_name="last_visit_date",
                property_value="30",
                match_type=AutomaticUpdateRuleCriteria.MATCH_DAYS_SINCE,
            ),
            AutomaticUpdateRuleCriteria(
                property_name="property1", property_value="value1", match_type=AutomaticUpdateRuleCriteria.MATCH_EQUAL
            ),
            AutomaticUpdateRuleCriteria(
                property_name="property2",
                property_value="value2",
                match_type=AutomaticUpdateRuleCriteria.MATCH_NOT_EQUAL,
            ),
            AutomaticUpdateRuleCriteria(
                property_name="property3", match_type=AutomaticUpdateRuleCriteria.MATCH_HAS_VALUE
            ),
        ]

        case.set_case_property("last_visit_date", "2015-11-01")
        case.set_case_property("property1", "value1")
        case.set_case_property("property2", "x")
        case.set_case_property("property3", "x")
        self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property("last_visit_date", "2015-12-30")
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property("last_visit_date", "2015-11-01")
        case.set_case_property("property1", "x")
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property("property1", "value1")
        case.set_case_property("property2", "value2")
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property("property2", "x")
        case.set_case_property("property3", "")
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property("property3", "x")
        self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))
Example #12
0
class KooKooTestCase(TouchformsTestCase):
    """
    Must be run manually (see corehq.apps.sms.tests.util.TouchformsTestCase)
    """

    def setUp(self):
        super(KooKooTestCase, self).setUp()
        self.ivr_backend = MobileBackend(
            _id="MOBILE_BACKEND_KOOKOO",
            outbound_module="corehq.apps.kookoo.api",
            outbound_params={"is_test": True, "api_key": "xyz"},
        )
        self.ivr_backend.save()

        self.user1 = self.create_mobile_worker("user1", "123", "91001", save_vn=False)
        self.user2 = self.create_mobile_worker("user2", "123", "91002", save_vn=False)
        self.create_group("group1", [self.user1, self.user2])

        self.case = CommCareCase(
            domain=self.domain,
            type="participant",
            owner_id=self.groups[0]._id,
        )
        self.case.set_case_property("contact_phone_number", "91000")
        self.case.set_case_property("contact_phone_number_is_verified", "1")
        self.case.set_case_property("contact_ivr_backend_id", "MOBILE_BACKEND_KOOKOO")
        self.case.save()

        dirname = os.path.dirname(os.path.abspath(__file__))
        self.load_app("app1.json", dirname)
        self.load_app("app2.json", dirname)

        self.reminder1 = CaseReminderHandler(
            domain=self.domain,
            active=True,
            case_type="participant",
            method=METHOD_IVR_SURVEY,
            recipient=RECIPIENT_CASE,
            sample_id=None,
            user_group_id=None,
            user_id=None,
            case_id=None,
            reminder_type=REMINDER_TYPE_DEFAULT,
            submit_partial_forms=True,
            include_case_side_effects=False,
            max_question_retries=5,
            start_condition_type=CASE_CRITERIA,
            start_property="name",
            start_value="case1",
            start_date=None,
            start_offset=0,
            start_match_type=MATCH_EXACT,
            events=[
                CaseReminderEvent(
                    day_num=0,
                    fire_time=time(12,0),
                    fire_time_type=FIRE_TIME_DEFAULT,
                    callback_timeout_intervals=[30],
                    form_unique_id=self.apps[0].modules[0].forms[0].unique_id,
                ),
                CaseReminderEvent(
                    day_num=0,
                    fire_time=time(13,0),
                    fire_time_type=FIRE_TIME_DEFAULT,
                    callback_timeout_intervals=[30],
                    form_unique_id=self.apps[0].modules[0].forms[1].unique_id,
                ),
            ],
            schedule_length=1,
            event_interpretation=EVENT_AS_SCHEDULE,
            max_iteration_count=7,
            until=None,
            force_surveys_to_use_triggered_case=False,
        )
        self.reminder1.save()

        self.reminder2 = CaseReminderHandler(
            domain=self.domain,
            active=True,
            case_type="participant",
            method=METHOD_IVR_SURVEY,
            recipient=RECIPIENT_OWNER,
            sample_id=None,
            user_group_id=None,
            user_id=None,
            case_id=None,
            reminder_type=REMINDER_TYPE_DEFAULT,
            submit_partial_forms=True,
            include_case_side_effects=True,
            max_question_retries=5,
            start_condition_type=CASE_CRITERIA,
            start_property="name",
            start_value="case2",
            start_date=None,
            start_offset=0,
            start_match_type=MATCH_EXACT,
            events=[
                CaseReminderEvent(
                    day_num=0,
                    fire_time=time(12,0),
                    fire_time_type=FIRE_TIME_DEFAULT,
                    callback_timeout_intervals=[30, 30],
                    form_unique_id=self.apps[1].modules[0].forms[0].unique_id,
                ),
            ],
            schedule_length=1,
            event_interpretation=EVENT_AS_SCHEDULE,
            max_iteration_count=7,
            until=None,
            force_surveys_to_use_triggered_case=False,
        )
        self.reminder2.save()

    def kookoo_in(self, params):
        """
        params should be a dictionary containing:
        event, cid, sid, and (optionally) data
        """
        params = urllib.urlencode(params)
        url = "%s/kookoo/ivr/" % self.live_server_url
        return urllib2.urlopen("%s?%s" % (url, params)).read()

    def kookoo_finished(self, params):
        """
        params should be a dictionary containing:
        sid, status, and duration
        """
        params = urllib.urlencode(params)
        url = "%s/kookoo/ivr_finished/" % self.live_server_url
        return urllib2.urlopen(url, params).read()

    def testOutbound(self):
        # Send an outbound call using self.reminder1 to self.case
        # and answer it
        CaseReminderHandler.now = datetime(2014, 6, 23, 10, 0)
        self.case.name = "case1"
        self.case.save()
        CaseReminderHandler.now = datetime(2014, 6, 23, 12, 0)
        CaseReminderHandler.fire_reminders()
        reminder = self.reminder1.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 23, 12, 30))

        call = self.get_last_outbound_call(self.case)
        self.assertTrue(call.use_precached_first_response)

        kookoo_session_id = call.gateway_session_id[7:]
        resp = self.kookoo_in({
            "cid": "0000",
            "sid": kookoo_session_id,
            "event": "NewCall",
        })
        self.assertEqual(resp, '<response sid="%s"><collectdtmf l="1" o="3000">'
            '<playtext>How do you feel today? Press 1 for good, 2 for bad.'
            '</playtext></collectdtmf></response>' % kookoo_session_id)

        resp = self.kookoo_in({
            "cid": "0000",
            "sid": kookoo_session_id,
            "event": "GotDTMF",
            "data": "1",
        })
        self.assertEqual(resp, '<response sid="%s"><collectdtmf l="1" o="3000">'
            '<playtext>Did you remember to take your meds today? Press 1 for yes, 2 for no.'
            '</playtext></collectdtmf></response>' % kookoo_session_id)

        resp = self.kookoo_in({
            "cid": "0000",
            "sid": kookoo_session_id,
            "event": "GotDTMF",
            "data": "2",
        })
        self.assertEqual(resp, '<response sid="%s"><hangup/></response>' % kookoo_session_id)

        self.kookoo_finished({
            "sid": kookoo_session_id,
            "status": "answered",
            "duration": "20",
        })

        call = CallLog.get(call._id)
        self.assertTrue(call.answered)

        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "how_feel", "1")
        self.assertFormQuestionEquals(form, "take_meds", "2")
        case = CommCareCase.get(self.case._id)
        self.assertCasePropertyEquals(case, "how_feel", "1")
        self.assertCasePropertyEquals(case, "take_meds", "2")

        CaseReminderHandler.now = datetime(2014, 6, 23, 12, 30)
        CaseReminderHandler.fire_reminders()

        reminder = self.reminder1.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 23, 13, 0))

        last_call = self.get_last_outbound_call(self.case)
        self.assertEqual(call._id, last_call._id)

        # Move on to the second event which now uses an all-label form and
        # should not precache the first ivr response
        CaseReminderHandler.now = datetime(2014, 6, 23, 13, 0)
        CaseReminderHandler.fire_reminders()

        reminder = self.reminder1.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 23, 13, 30))

        call = self.get_last_outbound_call(self.case)
        self.assertFalse(call.use_precached_first_response)

        kookoo_session_id = call.gateway_session_id[7:]
        resp = self.kookoo_in({
            "cid": "0000",
            "sid": kookoo_session_id,
            "event": "NewCall",
        })
        self.assertEqual(resp, '<response sid="%s">'
            '<playtext>This is just a reminder to take your meds.'
            '</playtext><hangup/></response>' % kookoo_session_id)

        self.kookoo_finished({
            "sid": kookoo_session_id,
            "status": "answered",
            "duration": "5",
        })

        call = CallLog.get(call._id)
        self.assertTrue(call.answered)

        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "label", "ok")

        CaseReminderHandler.now = datetime(2014, 6, 23, 13, 30)
        CaseReminderHandler.fire_reminders()

        reminder = self.reminder1.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 24, 12, 0))

        last_call = self.get_last_outbound_call(self.case)
        self.assertEqual(call._id, last_call._id)

        # Now test sending outbound calls to a group of users (the owners
        # of the case)

        # Allow sending to unverified numbers
        self.domain_obj = Domain.get(self.domain_obj._id)
        self.domain_obj.send_to_duplicated_case_numbers = True
        self.domain_obj.save()

        CaseReminderHandler.now = datetime(2014, 6, 24, 10, 0)
        self.case = CommCareCase.get(self.case._id)
        self.case.name = "case2"
        self.case.save()
        reminder = self.reminder2.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 24, 12, 0))

        CaseReminderHandler.now = datetime(2014, 6, 24, 12, 0)
        CaseReminderHandler.fire_reminders()
        reminder = self.reminder2.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 24, 12, 30))

        call1 = self.get_last_outbound_call(self.user1)
        self.assertTrue(call1.use_precached_first_response)
        self.assertFalse(call1.answered)

        call2 = self.get_last_outbound_call(self.user2)
        self.assertTrue(call2.use_precached_first_response)
        self.assertFalse(call2.answered)

        old_call1 = call1
        old_call2 = call2

        CaseReminderHandler.now = datetime(2014, 6, 24, 12, 30)
        CaseReminderHandler.fire_reminders()
        reminder = self.reminder2.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 24, 13, 0))

        call1 = self.get_last_outbound_call(self.user1)
        self.assertTrue(call1.use_precached_first_response)
        self.assertNotEqual(call1._id, old_call1._id)

        call2 = self.get_last_outbound_call(self.user2)
        self.assertTrue(call2.use_precached_first_response)
        self.assertFalse(call2.answered)
        self.assertNotEqual(call2._id, old_call2._id)

        kookoo_session_id = call1.gateway_session_id[7:]
        resp = self.kookoo_in({
            "cid": "0001",
            "sid": kookoo_session_id,
            "event": "NewCall",
        })
        self.assertEqual(resp, '<response sid="%s"><collectdtmf l="1" o="3000">'
            '<playtext>How do you feel today? Press 1 for good, 2 for bad.'
            '</playtext></collectdtmf></response>' % kookoo_session_id)

        resp = self.kookoo_in({
            "cid": "0001",
            "sid": kookoo_session_id,
            "event": "GotDTMF",
            "data": "2",
        })
        self.assertEqual(resp, '<response sid="%s"><collectdtmf l="1" o="3000">'
            '<playtext>Did you remember to take your meds today? Press 1 for yes, 2 for no.'
            '</playtext></collectdtmf></response>' % kookoo_session_id)

        resp = self.kookoo_in({
            "cid": "0001",
            "sid": kookoo_session_id,
            "event": "GotDTMF",
            "data": "1",
        })
        self.assertEqual(resp, '<response sid="%s"><hangup/></response>' % kookoo_session_id)

        self.kookoo_finished({
            "sid": kookoo_session_id,
            "status": "answered",
            "duration": "20",
        })
        call1 = CallLog.get(call1._id)
        self.assertTrue(call.answered)

        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "how_feel", "2")
        self.assertFormQuestionEquals(form, "take_meds", "1")
        self.assertEqual(form.form["meta"]["userID"], self.user1._id)
        case = CommCareCase.get(self.case._id)
        self.assertCasePropertyEquals(case, "how_feel", "2")
        self.assertCasePropertyEquals(case, "take_meds", "1")
        self.assertEqual(case.user_id, self.user1._id)

        old_call1 = call1
        old_call2 = call2

        CaseReminderHandler.now = datetime(2014, 6, 24, 13, 0)
        CaseReminderHandler.fire_reminders()
        reminder = self.reminder2.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 25, 12, 0))

        call1 = self.get_last_outbound_call(self.user1)
        # No new call for user1 since it was already answered
        self.assertEqual(call1._id, old_call1._id)

        call2 = self.get_last_outbound_call(self.user2)
        self.assertTrue(call2.use_precached_first_response)
        self.assertNotEqual(call2._id, old_call2._id)

        kookoo_session_id = call2.gateway_session_id[7:]
        resp = self.kookoo_in({
            "cid": "0002",
            "sid": kookoo_session_id,
            "event": "NewCall",
        })
        self.assertEqual(resp, '<response sid="%s"><collectdtmf l="1" o="3000">'
            '<playtext>How do you feel today? Press 1 for good, 2 for bad.'
            '</playtext></collectdtmf></response>' % kookoo_session_id)

        resp = self.kookoo_in({
            "cid": "0002",
            "sid": kookoo_session_id,
            "event": "GotDTMF",
            "data": "1",
        })
        self.assertEqual(resp, '<response sid="%s"><collectdtmf l="1" o="3000">'
            '<playtext>Did you remember to take your meds today? Press 1 for yes, 2 for no.'
            '</playtext></collectdtmf></response>' % kookoo_session_id)

        resp = self.kookoo_in({
            "cid": "0002",
            "sid": kookoo_session_id,
            "event": "GotDTMF",
            "data": "2",
        })
        self.assertEqual(resp, '<response sid="%s"><hangup/></response>' % kookoo_session_id)

        self.kookoo_finished({
            "sid": kookoo_session_id,
            "status": "answered",
            "duration": "20",
        })
        call2 = CallLog.get(call2._id)
        self.assertTrue(call.answered)

        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "how_feel", "1")
        self.assertFormQuestionEquals(form, "take_meds", "2")
        self.assertEqual(form.form["meta"]["userID"], self.user2._id)
        case = CommCareCase.get(self.case._id)
        self.assertCasePropertyEquals(case, "how_feel", "1")
        self.assertCasePropertyEquals(case, "take_meds", "2")
        self.assertEqual(case.user_id, self.user2._id)

    def tearDown(self):
        self.ivr_backend.delete()
        super(KooKooTestCase, self).tearDown()
Example #13
0
class BackendTestCase(TestCase):
    def setUp(self):
        self.domain = "test-domain"
        self.domain2 = "test-domain2"

        self.domain_obj = Domain(name=self.domain)
        self.domain_obj.save()
        self.domain_obj = Domain.get(
            self.domain_obj._id)  # Prevent resource conflict

        self.backend1 = TestCaseBackend(name="BACKEND1", is_global=True)
        self.backend1.save()

        self.backend2 = TestCaseBackend(name="BACKEND2", is_global=True)
        self.backend2.save()

        self.backend3 = TestCaseBackend(name="BACKEND3", is_global=True)
        self.backend3.save()

        self.backend4 = TestCaseBackend(name="BACKEND4", is_global=True)
        self.backend4.save()

        self.backend5 = TestCaseBackend(name="BACKEND5",
                                        domain=self.domain,
                                        is_global=False,
                                        authorized_domains=[])
        self.backend5.save()

        self.backend6 = TestCaseBackend(name="BACKEND6",
                                        domain=self.domain2,
                                        is_global=False,
                                        authorized_domains=[self.domain])
        self.backend6.save()

        self.backend7 = TestCaseBackend(name="BACKEND7",
                                        domain=self.domain2,
                                        is_global=False,
                                        authorized_domains=[])
        self.backend7.save()

        self.backend8 = TestCaseBackend(name="BACKEND",
                                        domain=self.domain,
                                        is_global=False,
                                        authorized_domains=[])
        self.backend8.save()

        self.backend9 = TestCaseBackend(name="BACKEND",
                                        domain=self.domain2,
                                        is_global=False,
                                        authorized_domains=[self.domain])
        self.backend9.save()

        self.backend10 = TestCaseBackend(name="BACKEND", is_global=True)
        self.backend10.save()

        self.backend_mapping1 = BackendMapping(is_global=True,
                                               prefix="*",
                                               backend_id=self.backend1._id)
        self.backend_mapping1.save()

        self.backend_mapping2 = BackendMapping(is_global=True,
                                               prefix="1",
                                               backend_id=self.backend2._id)
        self.backend_mapping2.save()

        self.backend_mapping3 = BackendMapping(is_global=True,
                                               prefix="91",
                                               backend_id=self.backend3._id)
        self.backend_mapping3.save()

        self.backend_mapping4 = BackendMapping(is_global=True,
                                               prefix="265",
                                               backend_id=self.backend4._id)
        self.backend_mapping4.save()

        self.case = CommCareCase(domain=self.domain)
        self.case.set_case_property("contact_phone_number", "15551234567")
        self.case.set_case_property("contact_phone_number_is_verified", "1")
        self.case.save()

        self.contact = CommConnectCase.wrap(self.case.to_json())

        settings.SMS_LOADED_BACKENDS.append(
            "corehq.apps.sms.tests.TestCaseBackend")

    def tearDown(self):
        self.backend1.delete_invoke_doc()
        self.backend1.delete()
        self.backend_mapping1.delete()

        self.backend2.delete_invoke_doc()
        self.backend2.delete()
        self.backend_mapping2.delete()

        self.backend3.delete_invoke_doc()
        self.backend3.delete()
        self.backend_mapping3.delete()

        self.backend4.delete_invoke_doc()
        self.backend4.delete()
        self.backend_mapping4.delete()

        self.backend5.delete_invoke_doc()
        self.backend5.delete()

        self.backend6.delete_invoke_doc()
        self.backend6.delete()

        self.backend7.delete_invoke_doc()
        self.backend7.delete()

        self.contact.delete_verified_number()
        self.case.delete()

        self.domain_obj.delete()

        settings.SMS_LOADED_BACKENDS.pop()

    def test_backend(self):
        # Test the backend map

        self.assertTrue(
            send_sms(self.domain, None, "15551234567", "Test for BACKEND2"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertTrue(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend2.delete_invoke_doc()
        self.assertFalse(self.backend2.invoke_doc_exists())

        self.assertTrue(
            send_sms(self.domain, None, "9100000000", "Test for BACKEND3"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertTrue(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend3.delete_invoke_doc()
        self.assertFalse(self.backend3.invoke_doc_exists())

        self.assertTrue(
            send_sms(self.domain, None, "26500000000", "Test for BACKEND4"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertTrue(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend4.delete_invoke_doc()
        self.assertFalse(self.backend4.invoke_doc_exists())

        self.assertTrue(
            send_sms(self.domain, None, "25800000000", "Test for BACKEND1"))
        self.assertTrue(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend1.delete_invoke_doc()
        self.assertFalse(self.backend1.invoke_doc_exists())

        # Test overriding with a domain-level backend

        self.domain_obj.default_sms_backend_id = self.backend5._id
        self.domain_obj.save()

        self.assertTrue(
            send_sms(self.domain, None, "15551234567", "Test for BACKEND5"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertTrue(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend5.delete_invoke_doc()
        self.assertFalse(self.backend5.invoke_doc_exists())

        # Test use of backend that another domain owns but has granted access

        self.domain_obj.default_sms_backend_id = self.backend6._id
        self.domain_obj.save()

        self.assertTrue(
            send_sms(self.domain, None, "25800000000", "Test for BACKEND6"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertTrue(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend6.delete_invoke_doc()
        self.assertFalse(self.backend6.invoke_doc_exists())

        # Test backend access control

        self.domain_obj.default_sms_backend_id = self.backend7._id
        self.domain_obj.save()

        self.assertFalse(
            send_sms(self.domain, None, "25800000000", "Test for BACKEND7"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())

        # Test sending to verified number with backend map

        self.domain_obj.default_sms_backend_id = None
        self.domain_obj.save()

        verified_number = self.contact.get_verified_number()
        self.assertTrue(verified_number is not None)
        self.assertTrue(verified_number.backend_id is None)
        self.assertEqual(verified_number.phone_number, "15551234567")

        self.assertTrue(
            send_sms_to_verified_number(verified_number, "Test for BACKEND2"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertTrue(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend2.delete_invoke_doc()
        self.assertFalse(self.backend2.invoke_doc_exists())

        # Test sending to verified number with default domain backend

        self.domain_obj.default_sms_backend_id = self.backend5._id
        self.domain_obj.save()

        self.assertTrue(
            send_sms_to_verified_number(verified_number, "Test for BACKEND5"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertTrue(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend5.delete_invoke_doc()
        self.assertFalse(self.backend5.invoke_doc_exists())

        # Test sending to verified number with a contact-level backend owned by the domain

        self.case.set_case_property("contact_backend_id", "BACKEND")
        self.case.save()
        self.contact = CommConnectCase.wrap(self.case.to_json())
        verified_number = self.contact.get_verified_number()
        self.assertTrue(verified_number is not None)
        self.assertEqual(verified_number.backend_id, "BACKEND")
        self.assertEqual(verified_number.phone_number, "15551234567")

        self.assertTrue(
            send_sms_to_verified_number(verified_number, "Test for BACKEND"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertTrue(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend8.delete_invoke_doc()
        self.assertFalse(self.backend8.invoke_doc_exists())

        # Test sending to verified number with a contact-level backend granted to the domain by another domain

        self.backend8.delete()

        self.assertTrue(
            send_sms_to_verified_number(verified_number, "Test for BACKEND"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertTrue(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend9.delete_invoke_doc()
        self.assertFalse(self.backend9.invoke_doc_exists())

        # Test sending to verified number with a contact-level global backend

        self.backend9.delete()

        self.assertTrue(
            send_sms_to_verified_number(verified_number, "Test for BACKEND"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertTrue(self.backend10.invoke_doc_exists())
        self.backend10.delete_invoke_doc()
        self.assertFalse(self.backend10.invoke_doc_exists())

        # Test raising exception if contact-level backend is not found

        self.backend10.delete()

        try:
            self.assertTrue(
                send_sms_to_verified_number(verified_number,
                                            "Test for BACKEND"))
        except BadSMSConfigException:
            pass
        else:
            self.assertTrue(False)

        # Test send_sms_with_backend

        self.assertTrue(
            send_sms_with_backend(self.domain, "+15551234567",
                                  "Test for BACKEND3", self.backend3._id))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertTrue(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.backend3.delete_invoke_doc()
        self.assertFalse(self.backend3.invoke_doc_exists())

        # Test send_sms_with_backend_name

        self.assertTrue(
            send_sms_with_backend_name(self.domain, "+15551234567",
                                       "Test for BACKEND3", "BACKEND3"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertTrue(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.backend3.delete_invoke_doc()
        self.assertFalse(self.backend3.invoke_doc_exists())
Example #14
0
class StartConditionReminderTestCase(BaseReminderTestCase):
    def setUp(self):
        super(StartConditionReminderTestCase, self).setUp()
        self.domain = "test"
        self.user_id = "USER-ID-109351"
        self.user = CommCareUser.create(self.domain, 'chw.bob5', '****', uuid=self.user_id, phone_number="99912345")
        
        self.handler1 = CaseReminderHandler(
            domain=self.domain,
            case_type="case_type_a",
            method=METHOD_SMS,
            start_property='start_sending1',
            start_value="^(ok|OK|\d\d\d\d-\d\d-\d\d)",
            start_date='start_sending1',
            start_offset=1,
            start_match_type=MATCH_REGEX,
            until='stop_sending1',
            default_lang='en',
            max_iteration_count=REPEAT_SCHEDULE_INDEFINITELY,
            schedule_length=3,
            event_interpretation=EVENT_AS_OFFSET,
            events = [
                CaseReminderEvent(
                    day_num = 0
                   ,fire_time = time(0,0,0)
                   ,message={"en":"Message1"}
                   ,callback_timeout_intervals=[]
                )
            ]
        )
        self.handler1.save()
        
        self.case1 = CommCareCase(
            domain=self.domain,
            type="case_type_a",
            user_id=self.user_id
        )
        self.case1.save()

    def tearDown(self):
        self.user.delete()
        super(StartConditionReminderTestCase, self).tearDown()


    def test_ok(self):
        #
        # Test changing a start condition of "ok"
        #
        # Spawn the reminder with an "ok" start condition value
        CaseReminderHandler.now = datetime(year=2012, month=2, day=17, hour=12, minute=0)
        self.assertEqual(self.handler1.get_reminder(self.case1), None)
        
        self.case1.set_case_property("start_sending1", "ok")
        self.case1.save()
        
        reminder = self.handler1.get_reminder(self.case1)
        self.assertNotEqual(reminder, None)
        
        self.assertEqual(
            reminder.next_fire
           ,CaseReminderHandler.now + timedelta(days=self.handler1.start_offset)
        )
        
        # Test that saving the case without changing the start condition has no effect
        old_reminder_id = reminder._id
        self.case1.set_case_property("case_property1", "abc")
        self.case1.save()
        reminder = self.handler1.get_reminder(self.case1)
        self.assertNotEqual(reminder, None)
        self.assertEqual(reminder._id, old_reminder_id)
        
        # Test retiring the reminder
        old_reminder_id = reminder._id
        self.case1.set_case_property("start_sending1", None)
        self.case1.save()
        
        self.assertEqual(self.handler1.get_reminder(self.case1), None)
        self.assertEqual(CaseReminder.get(old_reminder_id).doc_type, "CaseReminder-Deleted")
        
        #
        # Test changing a start condition which is a datetime value
        #
        # Spawn the reminder with datetime start condition value
        start = datetime(2012,2,20,9,0,0)
        self.case1.set_case_property("start_sending1", start)
        self.case1.save()
        
        reminder = self.handler1.get_reminder(self.case1)
        self.assertNotEqual(reminder, None)
        
        self.assertEqual(
            reminder.next_fire
           ,start + timedelta(days=self.handler1.start_offset)
        )
        
        # Reset the datetime start condition
        old_reminder_id = reminder._id
        start = datetime(2012,2,22,10,15,0)
        self.case1.set_case_property("start_sending1", start)
        self.case1.save()
        
        reminder = self.handler1.get_reminder(self.case1)
        self.assertNotEqual(reminder, None)
        
        self.assertEqual(
            reminder.next_fire
           ,start + timedelta(days=self.handler1.start_offset)
        )
        self.assertEqual(CaseReminder.get(old_reminder_id).doc_type, "CaseReminder-Deleted")
        
        # Test that saving the case without changing the start condition has no effect
        old_reminder_id = reminder._id
        self.case1.set_case_property("case_property1", "xyz")
        self.case1.save()
        reminder = self.handler1.get_reminder(self.case1)
        self.assertNotEqual(reminder, None)
        self.assertEqual(reminder._id, old_reminder_id)
        
        # Retire the reminder
        old_reminder_id = reminder._id
        self.case1.set_case_property("start_sending1", None)
        self.case1.save()
        
        reminder = self.handler1.get_reminder(self.case1)
        self.assertEqual(reminder, None)
        self.assertEqual(CaseReminder.get(old_reminder_id).doc_type, "CaseReminder-Deleted")
        
        #
        # Test changing a start condition which is a date value
        #
        # Spawn the reminder with date start condition value
        start = date(2012,2,20)
        self.case1.set_case_property("start_sending1", start)
        self.case1.save()
        
        reminder = self.handler1.get_reminder(self.case1)
        self.assertNotEqual(reminder, None)
        
        self.assertEqual(
            reminder.next_fire
           ,datetime(start.year, start.month, start.day) + timedelta(days=self.handler1.start_offset)
        )
        
        # Reset the date start condition
        old_reminder_id = reminder._id
        start = date(2012,2,22)
        self.case1.set_case_property("start_sending1", start)
        self.case1.save()
        
        reminder = self.handler1.get_reminder(self.case1)
        self.assertNotEqual(reminder, None)
        
        self.assertEqual(
            reminder.next_fire
           ,datetime(start.year, start.month, start.day) + timedelta(days=self.handler1.start_offset)
        )
        self.assertEqual(CaseReminder.get(old_reminder_id).doc_type, "CaseReminder-Deleted")
        
        # Test that saving the case without changing the start condition has no effect
        old_reminder_id = reminder._id
        self.case1.set_case_property("case_property1", "abc")
        self.case1.save()
        reminder = self.handler1.get_reminder(self.case1)
        self.assertNotEqual(reminder, None)
        self.assertEqual(reminder._id, old_reminder_id)
        
        # Retire the reminder
        old_reminder_id = reminder._id
        self.case1.set_case_property("start_sending1", None)
        self.case1.save()
        
        reminder = self.handler1.get_reminder(self.case1)
        self.assertEqual(reminder, None)
        self.assertEqual(CaseReminder.get(old_reminder_id).doc_type, "CaseReminder-Deleted")
        
        #
        # Test changing a start condition which is a string representation of a datetime value
        #
        # Spawn the reminder with datetime start condition value
        self.case1.set_case_property("start_sending1", "2012-02-25 11:15")
        self.case1.save()
        
        reminder = self.handler1.get_reminder(self.case1)
        self.assertNotEqual(reminder, None)
        
        self.assertEqual(
            reminder.next_fire
           ,datetime(2012,2,25,11,15) + timedelta(days=self.handler1.start_offset)
        )
        
        # Reset the datetime start condition
        old_reminder_id = reminder._id
        self.case1.set_case_property("start_sending1", "2012-02-26 11:20")
        self.case1.save()
        
        reminder = self.handler1.get_reminder(self.case1)
        self.assertNotEqual(reminder, None)
        
        self.assertEqual(
            reminder.next_fire
           ,datetime(2012,2,26,11,20) + timedelta(days=self.handler1.start_offset)
        )
        self.assertEqual(CaseReminder.get(old_reminder_id).doc_type, "CaseReminder-Deleted")
        
        # Test that saving the case without changing the start condition has no effect
        old_reminder_id = reminder._id
        self.case1.set_case_property("case_property1", "xyz")
        self.case1.save()
        reminder = self.handler1.get_reminder(self.case1)
        self.assertNotEqual(reminder, None)
        self.assertEqual(reminder._id, old_reminder_id)
        
        # Retire the reminder
        old_reminder_id = reminder._id
        self.case1.set_case_property("start_sending1", None)
        self.case1.save()
        
        reminder = self.handler1.get_reminder(self.case1)
        self.assertEqual(reminder, None)
        self.assertEqual(CaseReminder.get(old_reminder_id).doc_type, "CaseReminder-Deleted")
Example #15
0
class CaseTypeReminderTestCase(BaseReminderTestCase):
    def setUp(self):
        super(CaseTypeReminderTestCase, self).setUp()
        self.domain = "test"
        self.user_id = "USER-ID-109350"
        self.user = CommCareUser.create(self.domain, 'chw.bob4', '****', uuid=self.user_id, phone_number="99912345")
        
        self.handler1 = CaseReminderHandler(
            domain=self.domain,
            case_type="case_type_a",
            method=METHOD_SMS,
            start_property='start_sending1',
            start_value=None,
            start_date=None,
            start_offset=1,
            start_match_type=MATCH_ANY_VALUE,
            until='stop_sending1',
            default_lang='en',
            max_iteration_count=REPEAT_SCHEDULE_INDEFINITELY,
            schedule_length=3,
            event_interpretation=EVENT_AS_OFFSET,
            events = [
                CaseReminderEvent(
                    day_num = 0
                   ,fire_time = time(0,0,0)
                   ,message={"en":"Message1"}
                   ,callback_timeout_intervals=[]
                )
            ]
        )
        self.handler1.save()
        
        self.handler2 = CaseReminderHandler(
            domain=self.domain,
            case_type="case_type_a",
            method=METHOD_SMS,
            start_property='start_sending2',
            start_value=None,
            start_date=None,
            start_offset=2,
            start_match_type=MATCH_ANY_VALUE,
            until='stop_sending2',
            default_lang='en',
            max_iteration_count=REPEAT_SCHEDULE_INDEFINITELY,
            schedule_length=3,
            event_interpretation=EVENT_AS_OFFSET,
            events = [
                CaseReminderEvent(
                    day_num = 0
                   ,fire_time = time(0,0,0)
                   ,message={"en":"Message2"}
                   ,callback_timeout_intervals=[]
                )
            ]
        )
        self.handler2.save()
        
        self.handler3 = CaseReminderHandler(
            domain=self.domain,
            case_type="case_type_a",
            method=METHOD_SMS,
            start_property='start_sending3',
            start_value=None,
            start_date=None,
            start_offset=3,
            start_match_type=MATCH_ANY_VALUE,
            until='stop_sending3',
            default_lang='en',
            max_iteration_count=REPEAT_SCHEDULE_INDEFINITELY,
            schedule_length=3,
            event_interpretation=EVENT_AS_OFFSET,
            events = [
                CaseReminderEvent(
                    day_num = 0
                   ,fire_time = time(0,0,0)
                   ,message={"en":"Message3"}
                   ,callback_timeout_intervals=[]
                )
            ]
        )
        self.handler3.save()
        
        self.case1 = CommCareCase(
            domain=self.domain,
            type="case_type_a",
            user_id=self.user_id
        )
        self.case1.save()
        
        self.case2 = CommCareCase(
            domain=self.domain,
            type="case_type_b",
            user_id=self.user_id
        )
        self.case2.save()

    def tearDown(self):
        self.user.delete()
        super(CaseTypeReminderTestCase, self).tearDown()

    def test_ok(self):
        # Initial condition
        CaseReminderHandler.now = datetime(year=2012, month=2, day=16, hour=11, minute=0)
        
        self.case1.set_case_property("start_sending1", "ok")
        self.case1.set_case_property("start_sending2", "ok")
        self.case2.set_case_property("start_sending1", "ok")
        self.case2.set_case_property("start_sending3", "ok")
        self.case1.save()
        self.case2.save()
        
        self.assertNotEqual(self.handler1.get_reminder(self.case1), None)
        self.assertEqual(self.handler1.get_reminder(self.case2), None)
        self.assertNotEqual(self.handler2.get_reminder(self.case1), None)
        self.assertEqual(self.handler2.get_reminder(self.case2), None)
        self.assertEqual(self.handler3.get_reminder(self.case1), None)
        self.assertEqual(self.handler3.get_reminder(self.case2), None)
        
        self.assertEqual(
            self.handler1.get_reminder(self.case1).next_fire
           ,CaseReminderHandler.now + timedelta(days=self.handler1.start_offset)
        )
        self.assertEqual(
            self.handler2.get_reminder(self.case1).next_fire
           ,CaseReminderHandler.now + timedelta(days=self.handler2.start_offset)
        )
        
        # Test deactivation and spawn on change of CaseReminderHandler.case_type
        CaseReminderHandler.now = datetime(year=2012, month=2, day=16, hour=11, minute=15)
        
        self.handler1.case_type = "case_type_b"
        self.handler1.save()
        self.handler2.case_type = "case_type_b"
        self.handler2.save()
        self.handler3.case_type = "case_type_b"
        self.handler3.save()
        
        self.assertEqual(self.handler1.get_reminder(self.case1), None)
        self.assertNotEqual(self.handler1.get_reminder(self.case2), None)
        self.assertEqual(self.handler2.get_reminder(self.case1), None)
        self.assertEqual(self.handler2.get_reminder(self.case2), None)
        self.assertEqual(self.handler3.get_reminder(self.case1), None)
        self.assertNotEqual(self.handler3.get_reminder(self.case2), None)
        
        self.assertEqual(
            self.handler1.get_reminder(self.case2).next_fire
           ,CaseReminderHandler.now + timedelta(days=self.handler1.start_offset)
        )
        self.assertEqual(
            self.handler3.get_reminder(self.case2).next_fire
           ,CaseReminderHandler.now + timedelta(days=self.handler3.start_offset)
        )
        
        # Test spawn on change of Case.type
        prev_now = CaseReminderHandler.now
        CaseReminderHandler.now = datetime(year=2012, month=2, day=16, hour=11, minute=30)
        
        self.case1.type = "case_type_b"
        self.case1.save()
        
        self.assertNotEqual(self.handler1.get_reminder(self.case1), None)
        self.assertNotEqual(self.handler1.get_reminder(self.case2), None)
        self.assertNotEqual(self.handler2.get_reminder(self.case1), None)
        self.assertEqual(self.handler2.get_reminder(self.case2), None)
        self.assertEqual(self.handler3.get_reminder(self.case1), None)
        self.assertNotEqual(self.handler3.get_reminder(self.case2), None)
        
        self.assertEqual(
            self.handler1.get_reminder(self.case1).next_fire
           ,CaseReminderHandler.now + timedelta(days=self.handler1.start_offset)
        )
        self.assertEqual(
            self.handler2.get_reminder(self.case1).next_fire
           ,CaseReminderHandler.now + timedelta(days=self.handler2.start_offset)
        )
        
        self.assertEqual(
            self.handler1.get_reminder(self.case2).next_fire
           ,prev_now + timedelta(days=self.handler1.start_offset)
        )
        self.assertEqual(
            self.handler3.get_reminder(self.case2).next_fire
           ,prev_now + timedelta(days=self.handler3.start_offset)
        )
        
        # Test deactivation on change of Case.type
        prev_now = CaseReminderHandler.now
        CaseReminderHandler.now = datetime(year=2012, month=2, day=16, hour=11, minute=45)
        
        self.case2.type = "case_type_a"
        self.case2.save()
        
        self.assertNotEqual(self.handler1.get_reminder(self.case1), None)
        self.assertEqual(self.handler1.get_reminder(self.case2), None)
        self.assertNotEqual(self.handler2.get_reminder(self.case1), None)
        self.assertEqual(self.handler2.get_reminder(self.case2), None)
        self.assertEqual(self.handler3.get_reminder(self.case1), None)
        self.assertEqual(self.handler3.get_reminder(self.case2), None)
        
        self.assertEqual(
            self.handler1.get_reminder(self.case1).next_fire
           ,prev_now + timedelta(days=self.handler1.start_offset)
        )
        self.assertEqual(
            self.handler2.get_reminder(self.case1).next_fire
           ,prev_now + timedelta(days=self.handler2.start_offset)
        )
Example #16
0
class ReminderTestCase(BaseReminderTestCase):
    """
    This is the original use case and tests a fixed reminder schedule.
    """
    def setUp(self):
        super(ReminderTestCase, self).setUp()
        self.domain = "test"
        self.case_type = "my_case_type"
        self.message = "Hey you're getting this message."
        self.handler = CaseReminderHandler(
            domain=self.domain,
            case_type=self.case_type,
            method=METHOD_SMS,
            start_property='start_sending',
            start_value="ok",
            start_date=None,
            start_offset=1,
            start_match_type=MATCH_EXACT,
            until='stop_sending',
            default_lang='en',
            max_iteration_count=REPEAT_SCHEDULE_INDEFINITELY,
            schedule_length=3,
            event_interpretation=EVENT_AS_OFFSET,
            events = [
                CaseReminderEvent(
                    day_num = 0
                   ,fire_time = time(0,0,0)
                   ,message={"en":self.message}
                   ,callback_timeout_intervals=[]
                )
            ]
        )
        self.handler.save()
        self.user_id = "USER-ID-109347"
        self.user = CommCareUser.create(self.domain, 'chw.bob', '****', uuid=self.user_id, phone_number="99912345")
        self.case = CommCareCase(
            domain=self.domain,
            type=self.case_type,
            user_id=self.user_id,
        )
        self.case.save()

    def tearDown(self):
        self.user.delete()
        super(ReminderTestCase, self).tearDown()

    def test_ok(self):
        self.assertEqual(self.handler.events[0].message['en'], self.message)
        self.assertEqual(self.handler.get_reminder(self.case), None)

        # create reminder
        CaseReminderHandler.now = datetime(year=2011, month=7, day=7, hour=19, minute=8)
        self.case.set_case_property('start_sending', 'ok')
        self.case.save()
        CaseReminderHandler.fire_reminders()
        reminder = self.handler.get_reminder(self.case)
        self.assertNotEqual(reminder, None)
        self.assertEqual(
            reminder.next_fire,
            CaseReminderHandler.now + timedelta(days=self.handler.start_offset)
        )
        self.assertEqual(reminder.last_fired, None)

        # fire a day after created
        CaseReminderHandler.now = datetime(year=2011, month=7, day=8, hour=19, minute=8)
        self.case.set_case_property('irrelevant_1', 'ok')
        self.case.save()
        CaseReminderHandler.fire_reminders()
        reminder = self.handler.get_reminder(self.case)
        self.assertNotEqual(reminder, None)
        self.assertEqual(
            reminder.next_fire,
            CaseReminderHandler.now + timedelta(days=self.handler.schedule_length)
        )
        self.assertEqual(reminder.last_fired, CaseReminderHandler.now)

        # Shouldn't fire until three days after created
        last_fired = CaseReminderHandler.now
        CaseReminderHandler.now = datetime(year=2011, month=7, day=9, hour=19, minute=8)
        CaseReminderHandler.fire_reminders()
        reminder = self.handler.get_reminder(self.case)
        self.assertNotEqual(reminder, None)
        self.assertEqual(reminder.last_fired, last_fired)
        self.assertEqual(
            reminder.next_fire,
            last_fired + timedelta(days=self.handler.schedule_length)
        )

        # fire three days after last fired
        CaseReminderHandler.now = datetime(year=2011, month=7, day=11, hour=19, minute=8)
        self.case.set_case_property('irrelevant_2', 'ok')
        self.case.save()
        CaseReminderHandler.fire_reminders()
        reminder = self.handler.get_reminder(self.case)
        self.assertNotEqual(reminder, None)
        self.assertEqual(
            reminder.next_fire,
            CaseReminderHandler.now + timedelta(days=self.handler.schedule_length)
        )
        self.assertEqual(reminder.last_fired, CaseReminderHandler.now)

        # set stop_sending to 'ok' should make it stop sending and make the reminder inactive
        last_fired = CaseReminderHandler.now
        CaseReminderHandler.now = datetime(year=2011, month=7, day=14, hour=19, minute=8)
        self.case.set_case_property('stop_sending', 'ok')
        self.case.save()
        CaseReminderHandler.fire_reminders()
        reminder = self.handler.get_reminder(self.case)
        self.assertNotEqual(reminder, None)
        self.assertEqual(reminder.last_fired, last_fired)
        self.assertEqual(reminder.active, False)
Example #17
0
class ReminderCallbackTestCase(BaseReminderTestCase):
    """
    This use case represents a reminder schedule with an expected callback:

    Day1: 10:00 Callback Message 1 [simple reminder]
    Day1: 11:00 Callback Message 2 [expects callback]
    Day1: 11:15 Callback Message 2 [15-minute timeout if callback is not received]
    Day1: 11:45 Callback Message 2 [30-minute timeout if callback is not received]

    Day2: (same as Day1)

    Day3: (same as Day1)

    This case also tests handling of time zones using the timezone of Africa/Nairobi (UTC+3).
    """
    def setUp(self):
        super(ReminderCallbackTestCase, self).setUp()
        self.domain = "test"
        self.case_type = "my_case_type"
        self.message_1 = "Callback Message 1"
        self.message_2 = "Callback Message 2"
        self.handler = CaseReminderHandler(
            domain=self.domain,
            case_type=self.case_type,
            method=METHOD_SMS_CALLBACK,
            start_property='start_sending',
            start_value=None,
            start_date=None,
            start_offset=0,
            start_match_type=MATCH_ANY_VALUE,
            until='stop_sending',
            default_lang='en',
            max_iteration_count=3,
            schedule_length=1,
            event_interpretation=EVENT_AS_SCHEDULE,
            events = [
                CaseReminderEvent(
                    day_num = 0
                   ,fire_time = time(10,00,00)
                   ,message={"en":self.message_1}
                   ,callback_timeout_intervals=[]
                )
               ,CaseReminderEvent(
                    day_num = 0
                   ,fire_time = time(11,00,00)
                   ,message={"en":self.message_2}
                   ,callback_timeout_intervals=[15,30]
                )
            ]
        )
        self.handler.save()
        self.user_id = "USER-ID-109349"
        self.user = CommCareUser.create(self.domain, 'chw.bob3', '****', uuid=self.user_id, phone_number="99912345")
        self.user.user_data["time_zone"]="Africa/Nairobi"
        self.user.save()
        self.case = CommCareCase(
            domain=self.domain,
            type=self.case_type,
            user_id=self.user_id
        )
        self.case.save()
        self.user.save_verified_number("test", "14445551234", True, None)

    def tearDown(self):
        self.user.delete()
        super(ReminderCallbackTestCase, self).tearDown()

    def test_ok(self):
        self.assertEqual(self.handler.get_reminder(self.case), None)

        # Spawn CaseReminder
        CaseReminderHandler.now = datetime(year=2011, month=12, day=31, hour=23, minute=0)
        self.case.set_case_property('start_sending', 'ok')
        self.case.save()
        reminder = self.handler.get_reminder(self.case)
        self.assertNotEqual(reminder, None)
        self.assertEqual(reminder.next_fire, datetime(year=2012, month=1, day=1, hour=7, minute=0))
        self.assertEqual(reminder.start_date, date(year=2012, month=1, day=1))
        self.assertEqual(reminder.schedule_iteration_num, 1)
        self.assertEqual(reminder.current_event_sequence_num, 0)
        self.assertEqual(reminder.last_fired, None)
        
        ######################
        # Day1, 10:00 reminder
        CaseReminderHandler.now = datetime(year=2012, month=1, day=1, hour=7, minute=0)
        CaseReminderHandler.fire_reminders()
        reminder = self.handler.get_reminder(self.case)
        self.assertNotEqual(reminder, None)
        self.assertEqual(reminder.next_fire, datetime(year=2012, month=1, day=1, hour=8, minute=0))
        self.assertEqual(reminder.schedule_iteration_num, 1)
        self.assertEqual(reminder.current_event_sequence_num, 1)
        self.assertEqual(reminder.last_fired, CaseReminderHandler.now)
        
        # Day1, 11:00 reminder
        CaseReminderHandler.now = datetime(year=2012, month=1, day=1, hour=8, minute=1)
        CaseReminderHandler.fire_reminders()
        reminder = self.handler.get_reminder(self.case)
        self.assertNotEqual(reminder, None)
        self.assertEqual(reminder.next_fire, datetime(year=2012, month=1, day=1, hour=8, minute=15))
        self.assertEqual(reminder.schedule_iteration_num, 1)
        self.assertEqual(reminder.current_event_sequence_num, 1)
        self.assertEqual(reminder.last_fired, CaseReminderHandler.now)
        
        event = ExpectedCallbackEventLog.view("sms/expected_callback_event",
                                              key=["test", json_format_datetime(datetime(year=2012, month=1, day=1, hour=8, minute=1)), self.user_id],
                                              include_docs=True).one()
        self.assertNotEqual(event, None)
        self.assertEqual(event.status, CALLBACK_PENDING)
        
        # Create a callback
        c = CallLog(
            couch_recipient_doc_type    = "CommCareUser",
            couch_recipient             = self.user_id,
            phone_number                = "14445551234",
            direction                   = "I",
            date                        = datetime(year=2012, month=1, day=1, hour=8, minute=5)
        )
        c.save()

        # Day1, 11:15 timeout (should move on to next event)
        CaseReminderHandler.now = datetime(year=2012, month=1, day=1, hour=8, minute=15)
        CaseReminderHandler.fire_reminders()
        reminder = self.handler.get_reminder(self.case)
        self.assertNotEqual(reminder, None)
        self.assertEqual(reminder.next_fire, datetime(year=2012, month=1, day=1, hour=8, minute=45))
        self.assertEqual(reminder.schedule_iteration_num, 1)
        self.assertEqual(reminder.current_event_sequence_num, 1)
        self.assertEqual(reminder.last_fired, CaseReminderHandler.now)

        # Day1, 11:45 timeout (should move on to next event)
        CaseReminderHandler.now = datetime(year=2012, month=1, day=1, hour=8, minute=45)
        CaseReminderHandler.fire_reminders()
        reminder = self.handler.get_reminder(self.case)
        self.assertNotEqual(reminder, None)
        self.assertEqual(reminder.next_fire, datetime(year=2012, month=1, day=2, hour=7, minute=0))
        self.assertEqual(reminder.schedule_iteration_num, 2)
        self.assertEqual(reminder.current_event_sequence_num, 0)
        self.assertEqual(reminder.last_fired, CaseReminderHandler.now)

        event = ExpectedCallbackEventLog.view("sms/expected_callback_event",
                                              key=["test", json_format_datetime(datetime(year=2012, month=1, day=1, hour=8, minute=1)), self.user_id],
                                              include_docs=True).one()
        self.assertNotEqual(event, None)
        self.assertEqual(event.status, CALLBACK_RECEIVED)

        ######################
        # Day2, 10:00 reminder
        CaseReminderHandler.now = datetime(year=2012, month=1, day=2, hour=7, minute=0)
        CaseReminderHandler.fire_reminders()
        reminder = self.handler.get_reminder(self.case)
        self.assertNotEqual(reminder, None)
        self.assertEqual(reminder.next_fire, datetime(year=2012, month=1, day=2, hour=8, minute=0))
        self.assertEqual(reminder.schedule_iteration_num, 2)
        self.assertEqual(reminder.current_event_sequence_num, 1)
        self.assertEqual(reminder.last_fired, CaseReminderHandler.now)
        
        # Day2, 11:00 reminder
        CaseReminderHandler.now = datetime(year=2012, month=1, day=2, hour=8, minute=1)
        CaseReminderHandler.fire_reminders()
        reminder = self.handler.get_reminder(self.case)
        self.assertNotEqual(reminder, None)
        self.assertEqual(reminder.next_fire, datetime(year=2012, month=1, day=2, hour=8, minute=15))
        self.assertEqual(reminder.schedule_iteration_num, 2)
        self.assertEqual(reminder.current_event_sequence_num, 1)
        self.assertEqual(reminder.last_fired, CaseReminderHandler.now)
        
        event = ExpectedCallbackEventLog.view("sms/expected_callback_event",
                                              key=["test", json_format_datetime(datetime(year=2012, month=1, day=2, hour=8, minute=1)), self.user_id],
                                              include_docs=True).one()
        self.assertNotEqual(event, None)
        self.assertEqual(event.status, CALLBACK_PENDING)
        
        # Day2, 11:15 timeout (should move on to next timeout)
        CaseReminderHandler.now = datetime(year=2012, month=1, day=2, hour=8, minute=15)
        CaseReminderHandler.fire_reminders()
        reminder = self.handler.get_reminder(self.case)
        self.assertNotEqual(reminder, None)
        self.assertEqual(reminder.next_fire, datetime(year=2012, month=1, day=2, hour=8, minute=45))
        self.assertEqual(reminder.schedule_iteration_num, 2)
        self.assertEqual(reminder.current_event_sequence_num, 1)
        self.assertEqual(reminder.last_fired, CaseReminderHandler.now)
        
        event = ExpectedCallbackEventLog.view("sms/expected_callback_event",
                                              key=["test", json_format_datetime(datetime(year=2012, month=1, day=2, hour=8, minute=1)), self.user_id],
                                              include_docs=True).one()
        self.assertNotEqual(event, None)
        self.assertEqual(event.status, CALLBACK_PENDING)
        
        # Day2, 11:45 timeout (should move on to next day)
        CaseReminderHandler.now = datetime(year=2012, month=1, day=2, hour=8, minute=45)
        CaseReminderHandler.fire_reminders()
        reminder = self.handler.get_reminder(self.case)
        self.assertNotEqual(reminder, None)
        self.assertEqual(reminder.next_fire, datetime(year=2012, month=1, day=3, hour=7, minute=0))
        self.assertEqual(reminder.schedule_iteration_num, 3)
        self.assertEqual(reminder.current_event_sequence_num, 0)
        self.assertEqual(reminder.last_fired, CaseReminderHandler.now)
        
        event = ExpectedCallbackEventLog.view("sms/expected_callback_event",
                                              key=["test", json_format_datetime(datetime(year=2012, month=1, day=2, hour=8, minute=1)), self.user_id],
                                              include_docs=True).one()
        self.assertNotEqual(event, None)
        self.assertEqual(event.status, CALLBACK_MISSED)
        
        ######################
        # Day3, 10:00 reminder
        CaseReminderHandler.now = datetime(year=2012, month=1, day=3, hour=7, minute=0)
        CaseReminderHandler.fire_reminders()
        reminder = self.handler.get_reminder(self.case)
        self.assertNotEqual(reminder, None)
        self.assertEqual(reminder.next_fire, datetime(year=2012, month=1, day=3, hour=8, minute=0))
        self.assertEqual(reminder.schedule_iteration_num, 3)
        self.assertEqual(reminder.current_event_sequence_num, 1)
        self.assertEqual(reminder.last_fired, CaseReminderHandler.now)
        
        # Day3, 11:00 reminder
        CaseReminderHandler.now = datetime(year=2012, month=1, day=3, hour=8, minute=1)
        CaseReminderHandler.fire_reminders()
        reminder = self.handler.get_reminder(self.case)
        self.assertNotEqual(reminder, None)
        self.assertEqual(reminder.next_fire, datetime(year=2012, month=1, day=3, hour=8, minute=15))
        self.assertEqual(reminder.schedule_iteration_num, 3)
        self.assertEqual(reminder.current_event_sequence_num, 1)
        self.assertEqual(reminder.last_fired, CaseReminderHandler.now)
        
        event = ExpectedCallbackEventLog.view("sms/expected_callback_event",
                                              key=["test", json_format_datetime(datetime(year=2012, month=1, day=3, hour=8, minute=1)), self.user_id],
                                              include_docs=True).one()
        self.assertNotEqual(event, None)
        self.assertEqual(event.status, CALLBACK_PENDING)
        
        # Day3, 11:15 timeout (should move on to next timeout)
        CaseReminderHandler.now = datetime(year=2012, month=1, day=3, hour=8, minute=15)
        CaseReminderHandler.fire_reminders()
        reminder = self.handler.get_reminder(self.case)
        self.assertNotEqual(reminder, None)
        self.assertEqual(reminder.next_fire, datetime(year=2012, month=1, day=3, hour=8, minute=45))
        self.assertEqual(reminder.schedule_iteration_num, 3)
        self.assertEqual(reminder.current_event_sequence_num, 1)
        self.assertEqual(reminder.last_fired, CaseReminderHandler.now)
        
        event = ExpectedCallbackEventLog.view("sms/expected_callback_event",
                                              key=["test", json_format_datetime(datetime(year=2012, month=1, day=3, hour=8, minute=1)), self.user_id],
                                              include_docs=True).one()
        self.assertNotEqual(event, None)
        self.assertEqual(event.status, CALLBACK_PENDING)
        
        # Create a callback (with phone_number missing country code)
        c = CallLog(
            couch_recipient_doc_type    = "CommCareUser",
            couch_recipient             = self.user_id,
            phone_number                = "4445551234",
            direction                   = "I",
            date                        = datetime(year=2012, month=1, day=3, hour=8, minute=22)
        )
        c.save()
        
        # Day3, 11:45 timeout (should deactivate the reminder)
        CaseReminderHandler.now = datetime(year=2012, month=1, day=3, hour=8, minute=45)
        CaseReminderHandler.fire_reminders()
        reminder = self.handler.get_reminder(self.case)
        self.assertNotEqual(reminder, None)
        self.assertEqual(reminder.schedule_iteration_num, 4)
        self.assertEqual(reminder.current_event_sequence_num, 0)
        self.assertEqual(reminder.last_fired, CaseReminderHandler.now)
        self.assertEqual(reminder.active, False)
        
        event = ExpectedCallbackEventLog.view("sms/expected_callback_event",
                                              key=["test", json_format_datetime(datetime(year=2012, month=1, day=3, hour=8, minute=1)), self.user_id],
                                              include_docs=True).one()
        self.assertNotEqual(event, None)
        self.assertEqual(event.status, CALLBACK_RECEIVED)
Example #18
0
class ReminderIrregularScheduleTestCase(BaseReminderTestCase):
    """
    This use case represents an irregular reminder schedule which is repeated twice:

    Week1: Day1: 10:00 Message 1
    Week1: Day4: 11:00 Message 2
    Week1: Day4: 11:30 Message 3

    Week2: Day1: 10:00 Message 1
    Week2: Day4: 11:00 Message 2
    Week2: Day4: 11:30 Message 3
    """
    def setUp(self):
        super(ReminderIrregularScheduleTestCase, self).setUp()
        self.domain = "test"
        self.case_type = "my_case_type"
        self.message_1 = "Message 1"
        self.message_2 = "Message 2"
        self.message_3 = "Message 3"
        self.handler = CaseReminderHandler(
            domain=self.domain,
            case_type=self.case_type,
            method=METHOD_SMS,
            start_property='start_sending',
            start_value=None,
            start_date=None,
            start_offset=1,
            start_match_type=MATCH_ANY_VALUE,
            until='stop_sending',
            default_lang='en',
            max_iteration_count=2,
            schedule_length=7,
            event_interpretation=EVENT_AS_SCHEDULE,
            events = [
                CaseReminderEvent(
                    day_num = 0
                   ,fire_time = time(10,00,00)
                   ,message={"en":self.message_1}
                   ,callback_timeout_intervals=[]
                )
               ,CaseReminderEvent(
                    day_num = 3
                   ,fire_time = time(11,00,00)
                   ,message={"en":self.message_2}
                   ,callback_timeout_intervals=[]
                )
               ,CaseReminderEvent(
                    day_num = 3
                   ,fire_time = time(11,30,00)
                   ,message={"en":self.message_3}
                   ,callback_timeout_intervals=[]
                )
            ]
        )
        self.handler.save()
        self.user_id = "USER-ID-109348"
        self.user = CommCareUser.create(self.domain, 'chw.bob2', '****', uuid=self.user_id, phone_number="99912345")
        self.case = CommCareCase(
            domain=self.domain,
            type=self.case_type,
            user_id=self.user_id,
        )
        self.case.save()

    def tearDown(self):
        self.user.delete()
        super(ReminderIrregularScheduleTestCase, self).tearDown()


    def test_ok(self):
        self.assertEqual(self.handler.get_reminder(self.case), None)

        # Spawn CaseReminder
        CaseReminderHandler.now = datetime(year=2012, month=1, day=1, hour=4, minute=0)
        self.case.set_case_property('start_sending', 'ok')
        self.case.save()
        reminder = self.handler.get_reminder(self.case)
        self.assertNotEqual(reminder, None)
        self.assertEqual(reminder.next_fire, datetime(year=2012, month=1, day=2, hour=10, minute=0))
        self.assertEqual(reminder.start_date, date(year=2012, month=1, day=1))
        self.assertEqual(reminder.schedule_iteration_num, 1)
        self.assertEqual(reminder.current_event_sequence_num, 0)
        self.assertEqual(reminder.last_fired, None)
        
        # Not yet the first fire time, nothing should happen
        CaseReminderHandler.now = datetime(year=2012, month=1, day=2, hour=9, minute=45)
        CaseReminderHandler.fire_reminders()
        reminder = self.handler.get_reminder(self.case)
        self.assertNotEqual(reminder, None)
        self.assertEqual(reminder.next_fire, datetime(year=2012, month=1, day=2, hour=10, minute=0))
        self.assertEqual(reminder.schedule_iteration_num, 1)
        self.assertEqual(reminder.current_event_sequence_num, 0)
        self.assertEqual(reminder.last_fired, None)
        
        # Week1, Day1, 10:00 reminder
        CaseReminderHandler.now = datetime(year=2012, month=1, day=2, hour=10, minute=7)
        CaseReminderHandler.fire_reminders()
        reminder = self.handler.get_reminder(self.case)
        self.assertNotEqual(reminder, None)
        self.assertEqual(reminder.next_fire, datetime(year=2012, month=1, day=5, hour=11, minute=0))
        self.assertEqual(reminder.schedule_iteration_num, 1)
        self.assertEqual(reminder.current_event_sequence_num, 1)
        self.assertEqual(reminder.last_fired, CaseReminderHandler.now)
        
        # Week1, Day4, 11:00 reminder
        CaseReminderHandler.now = datetime(year=2012, month=1, day=5, hour=11, minute=3)
        CaseReminderHandler.fire_reminders()
        reminder = self.handler.get_reminder(self.case)
        self.assertNotEqual(reminder, None)
        self.assertEqual(reminder.next_fire, datetime(year=2012, month=1, day=5, hour=11, minute=30))
        self.assertEqual(reminder.schedule_iteration_num, 1)
        self.assertEqual(reminder.current_event_sequence_num, 2)
        self.assertEqual(reminder.last_fired, CaseReminderHandler.now)
        
        # Week1, Day4, 11:30 reminder
        CaseReminderHandler.now = datetime(year=2012, month=1, day=5, hour=11, minute=30)
        CaseReminderHandler.fire_reminders()
        reminder = self.handler.get_reminder(self.case)
        self.assertNotEqual(reminder, None)
        self.assertEqual(reminder.next_fire, datetime(year=2012, month=1, day=9, hour=10, minute=0))
        self.assertEqual(reminder.schedule_iteration_num, 2)
        self.assertEqual(reminder.current_event_sequence_num, 0)
        self.assertEqual(reminder.last_fired, CaseReminderHandler.now)
        
        # Week2, Day1, 10:00 reminder
        CaseReminderHandler.now = datetime(year=2012, month=1, day=9, hour=10, minute=0)
        CaseReminderHandler.fire_reminders()
        reminder = self.handler.get_reminder(self.case)
        self.assertNotEqual(reminder, None)
        self.assertEqual(reminder.next_fire, datetime(year=2012, month=1, day=12, hour=11, minute=0))
        self.assertEqual(reminder.schedule_iteration_num, 2)
        self.assertEqual(reminder.current_event_sequence_num, 1)
        self.assertEqual(reminder.last_fired, CaseReminderHandler.now)
        
        # Week2, Day4, 11:00 reminder
        CaseReminderHandler.now = datetime(year=2012, month=1, day=12, hour=11, minute=0)
        CaseReminderHandler.fire_reminders()
        reminder = self.handler.get_reminder(self.case)
        self.assertNotEqual(reminder, None)
        self.assertEqual(reminder.next_fire, datetime(year=2012, month=1, day=12, hour=11, minute=30))
        self.assertEqual(reminder.schedule_iteration_num, 2)
        self.assertEqual(reminder.current_event_sequence_num, 2)
        self.assertEqual(reminder.last_fired, CaseReminderHandler.now)
        
        # Week2, Day4, 11:30 reminder
        CaseReminderHandler.now = datetime(year=2012, month=1, day=12, hour=11, minute=31)
        CaseReminderHandler.fire_reminders()
        reminder = self.handler.get_reminder(self.case)
        self.assertNotEqual(reminder, None)
        self.assertEqual(reminder.schedule_iteration_num, 3)
        self.assertEqual(reminder.current_event_sequence_num, 0)
        self.assertEqual(reminder.last_fired, CaseReminderHandler.now)
        self.assertEqual(reminder.active, False)
Example #19
0
class ReminderLockTestCase(BaseReminderTestCase):
    def setUp(self):
        super(ReminderLockTestCase, self).setUp()
        self.domain = "test"
        self.user_id = "USER-ID-109352"
        self.user = CommCareUser.create(self.domain, 'chw.bob6', '****', uuid=self.user_id, phone_number="99912345")
        
        self.handler1 = CaseReminderHandler(
            domain=self.domain,
            case_type="case_type_a",
            method=METHOD_SMS,
            start_property='start_sending1',
            start_value="^(ok|OK|\d\d\d\d-\d\d-\d\d)",
            start_date='start_sending1',
            start_offset=1,
            start_match_type=MATCH_REGEX,
            until='stop_sending1',
            default_lang='en',
            max_iteration_count=REPEAT_SCHEDULE_INDEFINITELY,
            schedule_length=3,
            event_interpretation=EVENT_AS_OFFSET,
            events = [
                CaseReminderEvent(
                    day_num = 0
                   ,fire_time = time(0,0,0)
                   ,message={"en":"Testing the lock"}
                   ,callback_timeout_intervals=[]
                )
            ]
        )
        self.handler1.save()
        
        self.case1 = CommCareCase(
            domain=self.domain,
            type="case_type_a",
            user_id=self.user_id
        )
        self.case1.save()

    def tearDown(self):
        self.user.delete()
        super(ReminderLockTestCase, self).tearDown()


    def test_ok(self):
        # Spawn the reminder with an "ok" start condition value
        CaseReminderHandler.now = datetime(year=2012, month=2, day=17, hour=12, minute=0)
        self.assertEqual(self.handler1.get_reminder(self.case1), None)
        
        self.case1.set_case_property("start_sending1", "ok")
        self.case1.save()
        
        reminder = self.handler1.get_reminder(self.case1)
        old_reminder = self.handler1.get_reminder(self.case1)
        self.assertNotEqual(reminder, None)
        
        self.assertEqual(
            reminder.next_fire
           ,CaseReminderHandler.now + timedelta(days=self.handler1.start_offset)
        )
        
        # Fire the reminder, testing that the locking process works
        CaseReminderHandler.now = datetime(year=2012, month=2, day=18, hour=12, minute=1)
        self.assertEqual(reminder.lock_date, None)
        self.assertEqual(reminder.acquire_lock(CaseReminderHandler.now), True)
        self.assertEqual(reminder.lock_date, CaseReminderHandler.now)
        self.assertEqual(reminder.acquire_lock(CaseReminderHandler.now), False)
        self.handler1.fire(reminder)
        self.handler1.set_next_fire(reminder, CaseReminderHandler.now)
        reminder.release_lock()
        self.assertEqual(reminder.lock_date, None)
        
        # Ensure old versions of the document cannot acquire the lock
        self.assertNotEqual(reminder._rev, old_reminder._rev)
        self.assertEqual(old_reminder.acquire_lock(CaseReminderHandler.now), False)
        
        # Test the lock timeout
        self.assertEqual(reminder.acquire_lock(CaseReminderHandler.now), True)
        self.assertEqual(reminder.acquire_lock(CaseReminderHandler.now), False)
        self.assertEqual(reminder.acquire_lock(CaseReminderHandler.now + LOCK_EXPIRATION + timedelta(minutes = 1)), True)
Example #20
0
class BackendTestCase(BaseAccountingTest):
    def get_or_create_site(self):
        site, created = Site.objects.get_or_create(id=settings.SITE_ID)
        if created:
            site.domain = 'localhost'
            site.name = 'localhost'
            site.save()
        return (site, created)

    def setUp(self):
        super(BackendTestCase, self).setUp()

        self.domain = "test-domain"
        self.domain2 = "test-domain2"

        self.site, self.site_created = self.get_or_create_site()

        self.domain_obj = Domain(name=self.domain)
        self.domain_obj.save()

        generator.instantiate_accounting_for_tests()
        self.account = BillingAccount.get_or_create_account_by_domain(
            self.domain_obj.name,
            created_by="automated-test",
        )[0]
        plan = DefaultProductPlan.get_default_plan_by_domain(
            self.domain_obj, edition=SoftwarePlanEdition.ADVANCED)
        self.subscription = Subscription.new_domain_subscription(
            self.account, self.domain_obj.name, plan)
        self.subscription.is_active = True
        self.subscription.save()
        self.domain_obj = Domain.get(
            self.domain_obj._id)  # Prevent resource conflict

        self.backend1 = TestCaseBackend(name="BACKEND1", is_global=True)
        self.backend1.save()

        self.backend2 = TestCaseBackend(name="BACKEND2", is_global=True)
        self.backend2.save()

        self.backend3 = TestCaseBackend(name="BACKEND3", is_global=True)
        self.backend3.save()

        self.backend4 = TestCaseBackend(name="BACKEND4", is_global=True)
        self.backend4.save()

        self.backend5 = TestCaseBackend(name="BACKEND5",
                                        domain=self.domain,
                                        is_global=False,
                                        authorized_domains=[])
        self.backend5.save()

        self.backend6 = TestCaseBackend(name="BACKEND6",
                                        domain=self.domain2,
                                        is_global=False,
                                        authorized_domains=[self.domain])
        self.backend6.save()

        self.backend7 = TestCaseBackend(name="BACKEND7",
                                        domain=self.domain2,
                                        is_global=False,
                                        authorized_domains=[])
        self.backend7.save()

        self.backend8 = TestCaseBackend(name="BACKEND",
                                        domain=self.domain,
                                        is_global=False,
                                        authorized_domains=[])
        self.backend8.save()

        self.backend9 = TestCaseBackend(name="BACKEND",
                                        domain=self.domain2,
                                        is_global=False,
                                        authorized_domains=[self.domain])
        self.backend9.save()

        self.backend10 = TestCaseBackend(name="BACKEND", is_global=True)
        self.backend10.save()

        self.backend_mapping1 = BackendMapping(is_global=True,
                                               prefix="*",
                                               backend_id=self.backend1._id)
        self.backend_mapping1.save()

        self.backend_mapping2 = BackendMapping(is_global=True,
                                               prefix="1",
                                               backend_id=self.backend2._id)
        self.backend_mapping2.save()

        self.backend_mapping3 = BackendMapping(is_global=True,
                                               prefix="91",
                                               backend_id=self.backend3._id)
        self.backend_mapping3.save()

        self.backend_mapping4 = BackendMapping(is_global=True,
                                               prefix="265",
                                               backend_id=self.backend4._id)
        self.backend_mapping4.save()

        self.backend_mapping5 = BackendMapping(is_global=True,
                                               prefix="256",
                                               backend_id=self.backend5._id)
        self.backend_mapping5.save()

        self.backend_mapping6 = BackendMapping(is_global=True,
                                               prefix="25670",
                                               backend_id=self.backend6._id)
        self.backend_mapping6.save()

        self.backend_mapping7 = BackendMapping(is_global=True,
                                               prefix="25675",
                                               backend_id=self.backend7._id)
        self.backend_mapping7.save()

        self.case = CommCareCase(domain=self.domain)
        self.case.set_case_property("contact_phone_number", "15551234567")
        self.case.set_case_property("contact_phone_number_is_verified", "1")
        self.case.save()

        self.contact = CommConnectCase.wrap(self.case.to_json())

        settings.SMS_LOADED_BACKENDS.append(
            "corehq.apps.sms.tests.TestCaseBackend")

    def tearDown(self):
        self.backend1.delete_invoke_doc()
        self.backend1.delete()
        self.backend_mapping1.delete()

        self.backend2.delete_invoke_doc()
        self.backend2.delete()
        self.backend_mapping2.delete()

        self.backend3.delete_invoke_doc()
        self.backend3.delete()
        self.backend_mapping3.delete()

        self.backend4.delete_invoke_doc()
        self.backend4.delete()
        self.backend_mapping4.delete()

        self.backend5.delete_invoke_doc()
        self.backend5.delete()
        self.backend_mapping5.delete()

        self.backend6.delete_invoke_doc()
        self.backend6.delete()
        self.backend_mapping6.delete()

        self.backend7.delete_invoke_doc()
        self.backend7.delete()
        self.backend_mapping7.delete()

        self.contact.delete_verified_number()
        self.case.delete()

        SubscriptionAdjustment.objects.all().delete()
        self.subscription.delete()
        self.account.delete()

        self.domain_obj.delete()

        if self.site_created:
            self.site.delete()

        settings.SMS_LOADED_BACKENDS.pop()

    def test_multiple_country_prefixes(self):
        self.assertEqual(
            MobileBackend.auto_load('256800000000')._id, self.backend5._id)
        self.assertEqual(
            MobileBackend.auto_load('256700000000')._id, self.backend6._id)
        self.assertEqual(
            MobileBackend.auto_load('256750000000')._id, self.backend7._id)

    def test_backend(self):
        # Test the backend map

        self.assertTrue(
            send_sms(self.domain, None, "15551234567", "Test for BACKEND2"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertTrue(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend2.delete_invoke_doc()
        self.assertFalse(self.backend2.invoke_doc_exists())

        self.assertTrue(
            send_sms(self.domain, None, "9100000000", "Test for BACKEND3"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertTrue(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend3.delete_invoke_doc()
        self.assertFalse(self.backend3.invoke_doc_exists())

        self.assertTrue(
            send_sms(self.domain, None, "26500000000", "Test for BACKEND4"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertTrue(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend4.delete_invoke_doc()
        self.assertFalse(self.backend4.invoke_doc_exists())

        self.assertTrue(
            send_sms(self.domain, None, "25800000000", "Test for BACKEND1"))
        self.assertTrue(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend1.delete_invoke_doc()
        self.assertFalse(self.backend1.invoke_doc_exists())

        # Test overriding with a domain-level backend

        self.domain_obj = Domain.get(
            self.domain_obj._id)  # Prevent resource conflict
        self.domain_obj.default_sms_backend_id = self.backend5._id
        self.domain_obj.save()

        self.assertTrue(
            send_sms(self.domain, None, "15551234567", "Test for BACKEND5"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertTrue(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend5.delete_invoke_doc()
        self.assertFalse(self.backend5.invoke_doc_exists())

        # Test use of backend that another domain owns but has granted access

        self.domain_obj.default_sms_backend_id = self.backend6._id
        self.domain_obj.save()

        self.assertTrue(
            send_sms(self.domain, None, "25800000000", "Test for BACKEND6"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertTrue(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend6.delete_invoke_doc()
        self.assertFalse(self.backend6.invoke_doc_exists())

        # Test backend access control

        self.domain_obj.default_sms_backend_id = self.backend7._id
        self.domain_obj.save()

        self.assertFalse(
            send_sms(self.domain, None, "25800000000", "Test for BACKEND7"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())

        # Test sending to verified number with backend map

        self.domain_obj.default_sms_backend_id = None
        self.domain_obj.save()

        verified_number = self.contact.get_verified_number()
        self.assertTrue(verified_number is not None)
        self.assertTrue(verified_number.backend_id is None)
        self.assertEqual(verified_number.phone_number, "15551234567")

        self.assertTrue(
            send_sms_to_verified_number(verified_number, "Test for BACKEND2"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertTrue(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend2.delete_invoke_doc()
        self.assertFalse(self.backend2.invoke_doc_exists())

        # Test sending to verified number with default domain backend

        self.domain_obj.default_sms_backend_id = self.backend5._id
        self.domain_obj.save()

        self.assertTrue(
            send_sms_to_verified_number(verified_number, "Test for BACKEND5"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertTrue(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend5.delete_invoke_doc()
        self.assertFalse(self.backend5.invoke_doc_exists())

        # Test sending to verified number with a contact-level backend owned by the domain

        self.case.set_case_property("contact_backend_id", "BACKEND")
        self.case.save()
        self.contact = CommConnectCase.wrap(self.case.to_json())
        verified_number = self.contact.get_verified_number()
        self.assertTrue(verified_number is not None)
        self.assertEqual(verified_number.backend_id, "BACKEND")
        self.assertEqual(verified_number.phone_number, "15551234567")

        self.assertTrue(
            send_sms_to_verified_number(verified_number, "Test for BACKEND"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertTrue(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend8.delete_invoke_doc()
        self.assertFalse(self.backend8.invoke_doc_exists())

        # Test sending to verified number with a contact-level backend granted to the domain by another domain

        self.backend8.delete()

        self.assertTrue(
            send_sms_to_verified_number(verified_number, "Test for BACKEND"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertTrue(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend9.delete_invoke_doc()
        self.assertFalse(self.backend9.invoke_doc_exists())

        # Test sending to verified number with a contact-level global backend

        self.backend9.delete()

        self.assertTrue(
            send_sms_to_verified_number(verified_number, "Test for BACKEND"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertTrue(self.backend10.invoke_doc_exists())
        self.backend10.delete_invoke_doc()
        self.assertFalse(self.backend10.invoke_doc_exists())

        # Test raising exception if contact-level backend is not found

        self.backend10.delete()

        try:
            self.assertTrue(
                send_sms_to_verified_number(verified_number,
                                            "Test for BACKEND"))
        except BadSMSConfigException:
            pass
        else:
            self.assertTrue(False)

        # Test send_sms_with_backend

        self.assertTrue(
            send_sms_with_backend(self.domain, "+15551234567",
                                  "Test for BACKEND3", self.backend3._id))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertTrue(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.backend3.delete_invoke_doc()
        self.assertFalse(self.backend3.invoke_doc_exists())

        # Test send_sms_with_backend_name

        self.assertTrue(
            send_sms_with_backend_name(self.domain, "+15551234567",
                                       "Test for BACKEND3", "BACKEND3"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertTrue(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.backend3.delete_invoke_doc()
        self.assertFalse(self.backend3.invoke_doc_exists())

    def test_sms_registration(self):
        formatted_username = format_username("tester", self.domain)

        incoming("+9991234567", "JOIN {} WORKER tester".format(self.domain),
                 "TEST_CASE_BACKEND")
        # Test without mobile worker registration enabled
        self.assertIsNone(CommCareUser.get_by_username(formatted_username))

        # Enable mobile worker registration
        setattr(self.domain_obj, "sms_mobile_worker_registration_enabled",
                True)
        self.domain_obj.save()

        incoming("+9991234567", "JOIN {} WORKER tester".format(self.domain),
                 "TEST_CASE_BACKEND")
        self.assertIsNotNone(CommCareUser.get_by_username(formatted_username))

        # Test a duplicate registration
        prev_num_users = num_mobile_users(self.domain)
        incoming("+9991234568", "JOIN {} WORKER tester".format(self.domain),
                 "TEST_CASE_BACKEND")
        current_num_users = num_mobile_users(self.domain)
        self.assertEqual(prev_num_users, current_num_users)
    def test_and_criteria(self):
        case = CommCareCase(
            domain=self.domain,
            type='test-case-type-2',
            server_modified_on=datetime(2015, 1, 1),
        )

        self.rule2.automaticupdaterulecriteria_set = [
            AutomaticUpdateRuleCriteria(
                property_name='last_visit_date',
                property_value='30',
                match_type=AutomaticUpdateRuleCriteria.MATCH_DAYS_SINCE,
            ),
            AutomaticUpdateRuleCriteria(
                property_name='property1',
                property_value='value1',
                match_type=AutomaticUpdateRuleCriteria.MATCH_EQUAL,
            ),
            AutomaticUpdateRuleCriteria(
                property_name='property2',
                property_value='value2',
                match_type=AutomaticUpdateRuleCriteria.MATCH_NOT_EQUAL,
            ),
            AutomaticUpdateRuleCriteria(
                property_name='property3',
                match_type=AutomaticUpdateRuleCriteria.MATCH_HAS_VALUE,
            ),
        ]

        case.set_case_property('last_visit_date', '2015-11-01')
        case.set_case_property('property1', 'value1')
        case.set_case_property('property2', 'x')
        case.set_case_property('property3', 'x')
        self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property('last_visit_date', '2015-12-30')
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property('last_visit_date', '2015-11-01')
        case.set_case_property('property1', 'x')
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property('property1', 'value1')
        case.set_case_property('property2', 'value2')
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property('property2', 'x')
        case.set_case_property('property3', '')
        self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

        case.set_case_property('property3', 'x')
        self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))
Example #22
0
class OutgoingFrameworkTestCase(BaseSMSTest):

    def setUp(self):
        super(OutgoingFrameworkTestCase, self).setUp()

        self.domain = "test-domain"
        self.domain2 = "test-domain2"

        self.domain_obj = Domain(name=self.domain)
        self.domain_obj.save()

        self.create_account_and_subscription(self.domain_obj.name)
        self.domain_obj = Domain.get(self.domain_obj._id)

        self.backend1 = SQLTestSMSBackend.objects.create(
            name='BACKEND1',
            is_global=True,
            hq_api_id=SQLTestSMSBackend.get_api_id()
        )

        self.backend2 = SQLTestSMSBackend.objects.create(
            name='BACKEND2',
            is_global=True,
            hq_api_id=SQLTestSMSBackend.get_api_id()
        )

        self.backend3 = SQLTestSMSBackend.objects.create(
            name='BACKEND3',
            is_global=True,
            hq_api_id=SQLTestSMSBackend.get_api_id()
        )

        self.backend4 = SQLTestSMSBackend.objects.create(
            name='BACKEND4',
            is_global=True,
            hq_api_id=SQLTestSMSBackend.get_api_id()
        )

        self.backend5 = SQLTestSMSBackend.objects.create(
            name='BACKEND5',
            domain=self.domain,
            is_global=False,
            hq_api_id=SQLTestSMSBackend.get_api_id()
        )

        self.backend6 = SQLTestSMSBackend.objects.create(
            name='BACKEND6',
            domain=self.domain2,
            is_global=False,
            hq_api_id=SQLTestSMSBackend.get_api_id()
        )
        self.backend6.set_shared_domains([self.domain])

        self.backend7 = SQLTestSMSBackend.objects.create(
            name='BACKEND7',
            domain=self.domain2,
            is_global=False,
            hq_api_id=SQLTestSMSBackend.get_api_id()
        )

        self.backend8 = SQLTestSMSBackend.objects.create(
            name='BACKEND',
            domain=self.domain,
            is_global=False,
            hq_api_id=SQLTestSMSBackend.get_api_id()
        )

        self.backend9 = SQLTestSMSBackend.objects.create(
            name='BACKEND',
            domain=self.domain2,
            is_global=False,
            hq_api_id=SQLTestSMSBackend.get_api_id()
        )
        self.backend9.set_shared_domains([self.domain])

        self.backend10 = SQLTestSMSBackend.objects.create(
            name='BACKEND',
            is_global=True,
            hq_api_id=SQLTestSMSBackend.get_api_id()
        )

        self.backend_mapping1 = SQLMobileBackendMapping.objects.create(
            is_global=True,
            backend_type=SQLMobileBackend.SMS,
            prefix='*',
            backend=self.backend1
        )

        self.backend_mapping2 = SQLMobileBackendMapping.objects.create(
            is_global=True,
            backend_type=SQLMobileBackend.SMS,
            prefix='1',
            backend=self.backend2
        )

        self.backend_mapping3 = SQLMobileBackendMapping.objects.create(
            is_global=True,
            backend_type=SQLMobileBackend.SMS,
            prefix='91',
            backend=self.backend3
        )

        self.backend_mapping4 = SQLMobileBackendMapping.objects.create(
            is_global=True,
            backend_type=SQLMobileBackend.SMS,
            prefix='265',
            backend=self.backend4
        )

        self.backend_mapping5 = SQLMobileBackendMapping.objects.create(
            is_global=True,
            backend_type=SQLMobileBackend.SMS,
            prefix='256',
            backend=self.backend5
        )

        self.backend_mapping6 = SQLMobileBackendMapping.objects.create(
            is_global=True,
            backend_type=SQLMobileBackend.SMS,
            prefix='25670',
            backend=self.backend6
        )

        self.backend_mapping7 = SQLMobileBackendMapping.objects.create(
            is_global=True,
            backend_type=SQLMobileBackend.SMS,
            prefix='25675',
            backend=self.backend7
        )

        self.case = CommCareCase(domain=self.domain)
        self.case.set_case_property('contact_phone_number', '15551234567')
        self.case.set_case_property('contact_phone_number_is_verified', '1')
        self.case.save()

        self.contact = CommConnectCase.wrap(self.case.to_json())

    def tearDown(self):
        delete_domain_phone_numbers(self.domain)
        delete_domain_phone_numbers(self.domain2)
        for obj in (
            list(MobileBackendInvitation.objects.all()) +
            list(SQLMobileBackendMapping.objects.all())
        ):
            # For now we can't do bulk delete because we need to have the
            # delete sync with couch
            obj.delete()

        self.backend1.delete()
        self.backend2.delete()
        self.backend3.delete()
        self.backend4.delete()
        self.backend5.delete()
        self.backend6.delete()
        self.backend7.delete()
        self.backend8.delete()
        self.backend9.delete()
        self.backend10.delete()

        self.contact.delete_verified_number()
        self.case.delete()
        self.domain_obj.delete()

        super(OutgoingFrameworkTestCase, self).tearDown()

    def test_multiple_country_prefixes(self):
        self.assertEqual(
            SQLMobileBackend.load_default_by_phone_and_domain(
                SQLMobileBackend.SMS,
                '256800000000'
            ).pk,
            self.backend5.pk
        )
        self.assertEqual(
            SQLMobileBackend.load_default_by_phone_and_domain(
                SQLMobileBackend.SMS,
                '256700000000'
            ).pk,
            self.backend6.pk
        )
        self.assertEqual(
            SQLMobileBackend.load_default_by_phone_and_domain(
                SQLMobileBackend.SMS,
                '256750000000'
            ).pk,
            self.backend7.pk
        )

    def __test_global_backend_map(self):
        with patch(
            'corehq.messaging.smsbackends.test.models.SQLTestSMSBackend.send',
            autospec=True
        ) as mock_send:
            self.assertTrue(send_sms(self.domain, None, '15551234567', 'Test for BACKEND2'))
        self.assertEqual(mock_send.call_count, 1)
        self.assertEqual(mock_send.call_args[0][0].pk, self.backend2.pk)

        with patch(
            'corehq.messaging.smsbackends.test.models.SQLTestSMSBackend.send',
            autospec=True
        ) as mock_send:
            self.assertTrue(send_sms(self.domain, None, '9100000000', 'Test for BACKEND3'))
        self.assertEqual(mock_send.call_count, 1)
        self.assertEqual(mock_send.call_args[0][0].pk, self.backend3.pk)

        with patch(
            'corehq.messaging.smsbackends.test.models.SQLTestSMSBackend.send',
            autospec=True
        ) as mock_send:
            self.assertTrue(send_sms(self.domain, None, '26500000000', 'Test for BACKEND4'))
        self.assertEqual(mock_send.call_count, 1)
        self.assertEqual(mock_send.call_args[0][0].pk, self.backend4.pk)

        with patch(
            'corehq.messaging.smsbackends.test.models.SQLTestSMSBackend.send',
            autospec=True
        ) as mock_send:
            self.assertTrue(send_sms(self.domain, None, '25800000000', 'Test for BACKEND1'))
        self.assertEqual(mock_send.call_count, 1)
        self.assertEqual(mock_send.call_args[0][0].pk, self.backend1.pk)

    def __test_domain_default(self):
        # Test overriding with domain-level backend
        SQLMobileBackendMapping.set_default_domain_backend(self.domain, self.backend5)

        with patch(
            'corehq.messaging.smsbackends.test.models.SQLTestSMSBackend.send',
            autospec=True
        ) as mock_send:
            self.assertTrue(send_sms(self.domain, None, '15551234567', 'Test for BACKEND5'))
        self.assertEqual(mock_send.call_count, 1)
        self.assertEqual(mock_send.call_args[0][0].pk, self.backend5.pk)

    def __test_shared_backend(self):
        # Test use of backend that another domain owns but has granted access
        SQLMobileBackendMapping.set_default_domain_backend(self.domain, self.backend6)

        with patch(
            'corehq.messaging.smsbackends.test.models.SQLTestSMSBackend.send',
            autospec=True
        ) as mock_send:
            self.assertTrue(send_sms(self.domain, None, '25800000000', 'Test for BACKEND6'))
        self.assertEqual(mock_send.call_count, 1)
        self.assertEqual(mock_send.call_args[0][0].pk, self.backend6.pk)

        # Test trying to use a backend that another domain owns but has not granted access
        SQLMobileBackendMapping.set_default_domain_backend(self.domain, self.backend7)

        with patch(
            'corehq.messaging.smsbackends.test.models.SQLTestSMSBackend.send',
            autospec=True
        ) as mock_send:
            self.assertFalse(send_sms(self.domain, None, '25800000000', 'Test Unauthorized'))
        self.assertEqual(mock_send.call_count, 0)

    def __test_verified_number_with_map(self):
        # Test sending to verified number with backend map
        SQLMobileBackendMapping.unset_default_domain_backend(self.domain)

        verified_number = self.contact.get_verified_number()
        self.assertTrue(verified_number is not None)
        self.assertTrue(verified_number.backend_id is None)
        self.assertEqual(verified_number.phone_number, '15551234567')

        with patch(
            'corehq.messaging.smsbackends.test.models.SQLTestSMSBackend.send',
            autospec=True
        ) as mock_send:
            self.assertTrue(send_sms_to_verified_number(verified_number, 'Test for BACKEND2'))
        self.assertEqual(mock_send.call_count, 1)
        self.assertEqual(mock_send.call_args[0][0].pk, self.backend2.pk)

        # Test sending to verified number with default domain backend
        SQLMobileBackendMapping.set_default_domain_backend(self.domain, self.backend5)

        with patch(
            'corehq.messaging.smsbackends.test.models.SQLTestSMSBackend.send',
            autospec=True
        ) as mock_send:
            self.assertTrue(send_sms_to_verified_number(verified_number, 'Test for BACKEND5'))
        self.assertEqual(mock_send.call_count, 1)
        self.assertEqual(mock_send.call_args[0][0].pk, self.backend5.pk)

    def __test_contact_level_backend(self):
        # Test sending to verified number with a contact-level backend owned by the domain
        self.case.set_case_property('contact_backend_id', 'BACKEND')
        self.case.save()
        self.contact = CommConnectCase.wrap(self.case.to_json())
        verified_number = self.contact.get_verified_number()
        self.assertTrue(verified_number is not None)
        self.assertEqual(verified_number.backend_id, 'BACKEND')
        self.assertEqual(verified_number.phone_number, '15551234567')

        with patch(
            'corehq.messaging.smsbackends.test.models.SQLTestSMSBackend.send',
            autospec=True
        ) as mock_send:
            self.assertTrue(send_sms_to_verified_number(verified_number, 'Test for domain BACKEND'))
        self.assertEqual(mock_send.call_count, 1)
        self.assertEqual(mock_send.call_args[0][0].pk, self.backend8.pk)

        # Test sending to verified number with a contact-level backend granted to the domain by another domain
        self.backend8.name = 'BACKEND8'
        self.backend8.save()

        with patch(
            'corehq.messaging.smsbackends.test.models.SQLTestSMSBackend.send',
            autospec=True
        ) as mock_send:
            self.assertTrue(send_sms_to_verified_number(verified_number, 'Test for shared domain BACKEND'))
        self.assertEqual(mock_send.call_count, 1)
        self.assertEqual(mock_send.call_args[0][0].pk, self.backend9.pk)

        # Test sending to verified number with a contact-level global backend
        self.backend9.name = 'BACKEND9'
        self.backend9.save()

        with patch(
            'corehq.messaging.smsbackends.test.models.SQLTestSMSBackend.send',
            autospec=True
        ) as mock_send:
            self.assertTrue(send_sms_to_verified_number(verified_number, 'Test for global BACKEND'))
        self.assertEqual(mock_send.call_count, 1)
        self.assertEqual(mock_send.call_args[0][0].pk, self.backend10.pk)

        # Test raising exception if contact-level backend is not found
        self.backend10.name = 'BACKEND10'
        self.backend10.save()

        with self.assertRaises(BadSMSConfigException):
            send_sms_to_verified_number(verified_number, 'Test for unknown BACKEND')

    def __test_send_sms_with_backend(self):
        with patch(
            'corehq.messaging.smsbackends.test.models.SQLTestSMSBackend.send',
            autospec=True
        ) as mock_send:
            self.assertTrue(
                send_sms_with_backend(self.domain, '+15551234567', 'Test for BACKEND3', self.backend3.couch_id)
            )
        self.assertEqual(mock_send.call_count, 1)
        self.assertEqual(mock_send.call_args[0][0].pk, self.backend3.pk)

    def __test_send_sms_with_backend_name(self):
        with patch(
            'corehq.messaging.smsbackends.test.models.SQLTestSMSBackend.send',
            autospec=True
        ) as mock_send:
            self.assertTrue(
                send_sms_with_backend_name(self.domain, '+15551234567', 'Test for BACKEND3', 'BACKEND3')
            )
        self.assertEqual(mock_send.call_count, 1)
        self.assertEqual(mock_send.call_args[0][0].pk, self.backend3.pk)

    def test_choosing_appropriate_backend_for_outgoing(self):
        self.__test_global_backend_map()
        self.__test_domain_default()
        self.__test_shared_backend()
        self.__test_verified_number_with_map()
        self.__test_contact_level_backend()
        self.__test_send_sms_with_backend()
        self.__test_send_sms_with_backend_name()
    def test_case_phone_number_updates(self):
        case = CommCareCase(
            domain='case-phone-number-test',
            name='TEST1'
        )
        case.save()
        self.assertIsNone(self.get_case_verified_number(case))

        case.set_case_property('contact_phone_number', '99987658765')
        case.save()
        self.assertIsNone(self.get_case_verified_number(case))

        case.set_case_property('contact_phone_number_is_verified', '1')
        case.save()
        self.assertPhoneNumberDetails(case, '99987658765', None, None, _rev='1')
        _id = self.get_case_verified_number(case)._id

        case.set_case_property('contact_phone_number', '99987698769')
        case.save()
        self.assertPhoneNumberDetails(case, '99987698769', None, None, _id=_id, _rev='2')

        case.set_case_property('contact_backend_id', 'sms-backend')
        case.save()
        self.assertPhoneNumberDetails(case, '99987698769', 'sms-backend', None, _id=_id, _rev='3')

        case.set_case_property('contact_ivr_backend_id', 'ivr-backend')
        case.save()
        self.assertPhoneNumberDetails(case, '99987698769', 'sms-backend', 'ivr-backend', _id=_id, _rev='4')

        # If nothing changes, the phone entry should not be saved
        case.save()
        self.assertTrue(self.get_case_verified_number(case)._rev.startswith('4-'))

        # If phone entry is ahead of the case in terms of contact_last_modified, no update should happen
        v = self.get_case_verified_number(case)
        v.contact_last_modified += timedelta(days=1)
        v.save()
        self.assertTrue(v._rev.startswith('5-'))

        case.set_case_property('contact_phone_number', '99912341234')
        case.save()
        self.assertTrue(self.get_case_verified_number(case)._rev.startswith('5-'))

        self.get_case_verified_number(case).delete()
        case.delete()
Example #24
0
class AllBackendTest(BaseSMSTest):
    def setUp(self):
        super(AllBackendTest, self).setUp()
        backend_api.TEST = True

        self.domain_obj = Domain(name='all-backend-test')
        self.domain_obj.save()
        self.create_account_and_subscription(self.domain_obj.name)
        self.domain_obj = Domain.get(self.domain_obj._id)

        self.test_phone_number = '99912345'
        self.contact1 = CommCareCase(domain=self.domain_obj.name)
        self.contact1.set_case_property('contact_phone_number', self.test_phone_number)
        self.contact1.set_case_property('contact_phone_number_is_verified', '1')
        self.contact1.save()
        self.contact1 = CommConnectCase.wrap(self.contact1.to_json())

        # For use with megamobile only
        self.contact2 = CommCareCase(domain=self.domain_obj.name)
        self.contact2.set_case_property('contact_phone_number', '63%s' % self.test_phone_number)
        self.contact2.set_case_property('contact_phone_number_is_verified', '1')
        self.contact2.save()
        self.contact2 = CommConnectCase.wrap(self.contact2.to_json())

        self.unicel_backend = UnicelBackend(name='UNICEL', is_global=True)
        self.unicel_backend.save()

        self.mach_backend = MachBackend(name='MACH', is_global=True)
        self.mach_backend.save()

        self.tropo_backend = TropoBackend(name='TROPO', is_global=True)
        self.tropo_backend.save()

        self.http_backend = HttpBackend(name='HTTP', is_global=True)
        self.http_backend.save()

        self.telerivet_backend = TelerivetBackend(name='TELERIVET', is_global=True,
            webhook_secret='telerivet-webhook-secret')
        self.telerivet_backend.save()

        self.test_backend = TestSMSBackend(name='TEST', is_global=True)
        self.test_backend.save()

        self.grapevine_backend = GrapevineBackend(name='GRAPEVINE', is_global=True)
        self.grapevine_backend.save()

        self.twilio_backend = TwilioBackend(name='TWILIO', is_global=True)
        self.twilio_backend.save()

        self.megamobile_backend = MegamobileBackend(name='MEGAMOBILE', is_global=True)
        self.megamobile_backend.save()

        self.smsgh_backend = SMSGHBackend(name='SMSGH', is_global=True)
        self.smsgh_backend.save()

        self.apposit_backend = AppositBackend(name='APPOSIT', is_global=True)
        self.apposit_backend.save()

    def _test_outbound_backend(self, backend, msg_text, mock_send):
        self.domain_obj.default_sms_backend_id = backend._id
        self.domain_obj.save()

        send_sms(self.domain_obj.name, None, self.test_phone_number, msg_text)
        sms = SMS.objects.get(
            domain=self.domain_obj.name,
            direction='O',
            text=msg_text
        )

        self.assertTrue(mock_send.called)
        msg_arg = mock_send.call_args[0][0]
        self.assertEqual(msg_arg.date, sms.date)

    def _verify_inbound_request(self, backend_api_id, msg_text):
        sms = SMS.objects.get(
            domain=self.domain_obj.name,
            direction='I',
            text=msg_text
        )
        self.assertEqual(sms.backend_api, backend_api_id)

    def _simulate_inbound_request_with_payload(self, url,
            content_type, payload):
        response = Client().post(url, payload, content_type=content_type)
        self.assertEqual(response.status_code, 200)

    def _simulate_inbound_request(self, url, phone_param,
            msg_param, msg_text, post=False, additional_params=None):
        fcn = Client().post if post else Client().get

        payload = {
            phone_param: self.test_phone_number,
            msg_param: msg_text,
        }

        if additional_params:
            payload.update(additional_params)

        response = fcn(url, payload)
        self.assertEqual(response.status_code, 200)

    @patch('corehq.messaging.smsbackends.unicel.api.UnicelBackend.send')
    @patch('corehq.messaging.smsbackends.mach.api.MachBackend.send')
    @patch('corehq.messaging.smsbackends.tropo.api.TropoBackend.send')
    @patch('corehq.messaging.smsbackends.http.api.HttpBackend.send')
    @patch('corehq.messaging.smsbackends.telerivet.models.TelerivetBackend.send')
    @patch('corehq.messaging.smsbackends.test.api.TestSMSBackend.send')
    @patch('corehq.messaging.smsbackends.grapevine.api.GrapevineBackend.send')
    @patch('corehq.messaging.smsbackends.twilio.models.TwilioBackend.send')
    @patch('corehq.messaging.smsbackends.megamobile.api.MegamobileBackend.send')
    @patch('corehq.messaging.smsbackends.smsgh.models.SMSGHBackend.send')
    @patch('corehq.messaging.smsbackends.apposit.models.AppositBackend.send')
    def test_outbound_sms(
            self,
            apposit_send,
            smsgh_send,
            megamobile_send,
            twilio_send,
            grapevine_send,
            test_send,
            telerivet_send,
            http_send,
            tropo_send,
            mach_send,
            unicel_send):
        self._test_outbound_backend(self.unicel_backend, 'unicel test', unicel_send)
        self._test_outbound_backend(self.mach_backend, 'mach test', mach_send)
        self._test_outbound_backend(self.tropo_backend, 'tropo test', tropo_send)
        self._test_outbound_backend(self.http_backend, 'http test', http_send)
        self._test_outbound_backend(self.telerivet_backend, 'telerivet test', telerivet_send)
        self._test_outbound_backend(self.test_backend, 'test test', test_send)
        self._test_outbound_backend(self.grapevine_backend, 'grapevine test', grapevine_send)
        self._test_outbound_backend(self.twilio_backend, 'twilio test', twilio_send)
        self._test_outbound_backend(self.megamobile_backend, 'megamobile test', megamobile_send)
        self._test_outbound_backend(self.smsgh_backend, 'smsgh test', smsgh_send)
        self._test_outbound_backend(self.apposit_backend, 'apposit test', apposit_send)

    def test_unicel_inbound_sms(self):
        self._simulate_inbound_request('/unicel/in/', phone_param=InboundParams.SENDER,
            msg_param=InboundParams.MESSAGE, msg_text='unicel test')

        self._verify_inbound_request(self.unicel_backend.get_api_id(), 'unicel test')

    def test_tropo_inbound_sms(self):
        tropo_data = {'session': {'from': {'id': self.test_phone_number}, 'initialText': 'tropo test'}}
        self._simulate_inbound_request_with_payload('/tropo/sms/',
            content_type='text/json', payload=json.dumps(tropo_data))

        self._verify_inbound_request(self.tropo_backend.get_api_id(), 'tropo test')

    def test_telerivet_inbound_sms(self):
        additional_params = {
            'event': 'incoming_message',
            'message_type': 'sms',
            'secret': self.telerivet_backend.webhook_secret
        }
        self._simulate_inbound_request('/telerivet/in/', phone_param='from_number_e164',
            msg_param='content', msg_text='telerivet test', post=True,
            additional_params=additional_params)

        self._verify_inbound_request(self.telerivet_backend.get_api_id(), 'telerivet test')

    @override_settings(SIMPLE_API_KEYS={'grapevine-test': 'grapevine-api-key'})
    def test_grapevine_inbound_sms(self):
        xml = """
        <gviSms>
            <smsDateTime>2015-10-12T12:00:00</smsDateTime>
            <cellNumber>99912345</cellNumber>
            <content>grapevine test</content>
        </gviSms>
        """
        payload = urlencode({'XML': xml})
        self._simulate_inbound_request_with_payload(
            '/gvi/api/sms/?apiuser=grapevine-test&apikey=grapevine-api-key',
            content_type='application/x-www-form-urlencoded', payload=payload)

        self._verify_inbound_request(self.grapevine_backend.get_api_id(), 'grapevine test')

    def test_twilio_inbound_sms(self):
        self._simulate_inbound_request('/twilio/sms/', phone_param='From',
            msg_param='Body', msg_text='twilio test', post=True)

        self._verify_inbound_request(self.twilio_backend.get_api_id(), 'twilio test')

    def test_megamobile_inbound_sms(self):
        self._simulate_inbound_request('/megamobile/sms/', phone_param='cel',
            msg_param='msg', msg_text='megamobile test')

        self._verify_inbound_request(self.megamobile_backend.get_api_id(), 'megamobile test')

    def test_sislog_inbound_sms(self):
        self._simulate_inbound_request('/sislog/in/', phone_param='sender',
            msg_param='msgdata', msg_text='sislog test')

        self._verify_inbound_request('SISLOG', 'sislog test')

    def test_yo_inbound_sms(self):
        self._simulate_inbound_request('/yo/sms/', phone_param='sender',
            msg_param='message', msg_text='yo test')

        self._verify_inbound_request('YO', 'yo test')

    def test_smsgh_inbound_sms(self):
        user = ApiUser.create('smsgh-api-key', 'smsgh-api-key', permissions=[PERMISSION_POST_SMS])
        user.save()

        self._simulate_inbound_request('/smsgh/sms/smsgh-api-key/', phone_param='snr',
            msg_param='msg', msg_text='smsgh test')

        self._verify_inbound_request('SMSGH', 'smsgh test')

        user.delete()

    def test_apposit_inbound_sms(self):
        user = ApiUser.create('apposit-api-key', 'apposit-api-key', permissions=[PERMISSION_POST_SMS])
        user.save()

        self._simulate_inbound_request(
            '/apposit/in/apposit-api-key/',
            phone_param='fromAddress',
            msg_param='content',
            msg_text='apposit test',
            post=True,
            additional_params={'channel': 'SMS'}
        )
        self._verify_inbound_request('APPOSIT', 'apposit test')

        user.delete()

    def tearDown(self):
        backend_api.TEST = False
        self.contact1.get_verified_number().delete()
        self.contact1.delete()
        self.contact2.get_verified_number().delete()
        self.contact2.delete()
        self.domain_obj.delete()
        self.unicel_backend.delete()
        self.mach_backend.delete()
        self.tropo_backend.delete()
        self.http_backend.delete()
        self.telerivet_backend.delete()
        self.test_backend.delete()
        self.grapevine_backend.delete()
        self.twilio_backend.delete()
        self.megamobile_backend.delete()
        self.smsgh_backend.delete()
        self.apposit_backend.delete()
        super(AllBackendTest, self).tearDown()
Example #25
0
class BackendTestCase(TestCase):
    def setUp(self):
        self.domain = "test-domain"
        self.domain2 = "test-domain2"

        self.domain_obj = Domain(name=self.domain)
        self.domain_obj.save()
        self.domain_obj = Domain.get(self.domain_obj._id) # Prevent resource conflict

        self.backend1 = TestCaseBackend(name="BACKEND1",is_global=True)
        self.backend1.save()

        self.backend2 = TestCaseBackend(name="BACKEND2",is_global=True)
        self.backend2.save()

        self.backend3 = TestCaseBackend(name="BACKEND3",is_global=True)
        self.backend3.save()

        self.backend4 = TestCaseBackend(name="BACKEND4",is_global=True)
        self.backend4.save()

        self.backend5 = TestCaseBackend(name="BACKEND5",domain=self.domain,is_global=False,authorized_domains=[])
        self.backend5.save()

        self.backend6 = TestCaseBackend(name="BACKEND6",domain=self.domain2,is_global=False,authorized_domains=[self.domain])
        self.backend6.save()

        self.backend7 = TestCaseBackend(name="BACKEND7",domain=self.domain2,is_global=False,authorized_domains=[])
        self.backend7.save()
        
        self.backend8 = TestCaseBackend(name="BACKEND",domain=self.domain,is_global=False,authorized_domains=[])
        self.backend8.save()

        self.backend9 = TestCaseBackend(name="BACKEND",domain=self.domain2,is_global=False,authorized_domains=[self.domain])
        self.backend9.save()

        self.backend10 = TestCaseBackend(name="BACKEND",is_global=True)
        self.backend10.save()

        self.backend_mapping1 = BackendMapping(is_global=True,prefix="*",backend_id=self.backend1._id)
        self.backend_mapping1.save()

        self.backend_mapping2 = BackendMapping(is_global=True,prefix="1",backend_id=self.backend2._id)
        self.backend_mapping2.save()

        self.backend_mapping3 = BackendMapping(is_global=True,prefix="91",backend_id=self.backend3._id)
        self.backend_mapping3.save()

        self.backend_mapping4 = BackendMapping(is_global=True,prefix="265",backend_id=self.backend4._id)
        self.backend_mapping4.save()

        self.case = CommCareCase(domain=self.domain)
        self.case.set_case_property("contact_phone_number","15551234567")
        self.case.set_case_property("contact_phone_number_is_verified", "1")
        self.case.save()

        self.contact = CommConnectCase.wrap(self.case.to_json())

        settings.SMS_LOADED_BACKENDS.append("corehq.apps.sms.tests.TestCaseBackend")

    def tearDown(self):
        self.backend1.delete_invoke_doc()
        self.backend1.delete()
        self.backend_mapping1.delete()

        self.backend2.delete_invoke_doc()
        self.backend2.delete()
        self.backend_mapping2.delete()

        self.backend3.delete_invoke_doc()
        self.backend3.delete()
        self.backend_mapping3.delete()

        self.backend4.delete_invoke_doc()
        self.backend4.delete()
        self.backend_mapping4.delete()

        self.backend5.delete_invoke_doc()
        self.backend5.delete()

        self.backend6.delete_invoke_doc()
        self.backend6.delete()

        self.backend7.delete_invoke_doc()
        self.backend7.delete()

        self.contact.delete_verified_number()
        self.case.delete()

        self.domain_obj.delete()

        settings.SMS_LOADED_BACKENDS.pop()

    def test_backend(self):
        # Test the backend map

        self.assertTrue(send_sms(self.domain, None, "15551234567", "Test for BACKEND2"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertTrue(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend2.delete_invoke_doc()
        self.assertFalse(self.backend2.invoke_doc_exists())

        self.assertTrue(send_sms(self.domain, None, "9100000000", "Test for BACKEND3"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertTrue(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend3.delete_invoke_doc()
        self.assertFalse(self.backend3.invoke_doc_exists())

        self.assertTrue(send_sms(self.domain, None, "26500000000", "Test for BACKEND4"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertTrue(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend4.delete_invoke_doc()
        self.assertFalse(self.backend4.invoke_doc_exists())

        self.assertTrue(send_sms(self.domain, None, "25800000000", "Test for BACKEND1"))
        self.assertTrue(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend1.delete_invoke_doc()
        self.assertFalse(self.backend1.invoke_doc_exists())

        # Test overriding with a domain-level backend

        self.domain_obj.default_sms_backend_id = self.backend5._id
        self.domain_obj.save()

        self.assertTrue(send_sms(self.domain, None, "15551234567", "Test for BACKEND5"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertTrue(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend5.delete_invoke_doc()
        self.assertFalse(self.backend5.invoke_doc_exists())

        # Test use of backend that another domain owns but has granted access

        self.domain_obj.default_sms_backend_id = self.backend6._id
        self.domain_obj.save()

        self.assertTrue(send_sms(self.domain, None, "25800000000", "Test for BACKEND6"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertTrue(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend6.delete_invoke_doc()
        self.assertFalse(self.backend6.invoke_doc_exists())

        # Test backend access control

        self.domain_obj.default_sms_backend_id = self.backend7._id
        self.domain_obj.save()

        self.assertFalse(send_sms(self.domain, None, "25800000000", "Test for BACKEND7"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())

        # Test sending to verified number with backend map

        self.domain_obj.default_sms_backend_id = None
        self.domain_obj.save()

        verified_number = self.contact.get_verified_number()
        self.assertTrue(verified_number is not None)
        self.assertTrue(verified_number.backend_id is None)
        self.assertEqual(verified_number.phone_number, "15551234567")

        self.assertTrue(send_sms_to_verified_number(verified_number, "Test for BACKEND2"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertTrue(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend2.delete_invoke_doc()
        self.assertFalse(self.backend2.invoke_doc_exists())

        # Test sending to verified number with default domain backend

        self.domain_obj.default_sms_backend_id = self.backend5._id
        self.domain_obj.save()

        self.assertTrue(send_sms_to_verified_number(verified_number, "Test for BACKEND5"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertTrue(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend5.delete_invoke_doc()
        self.assertFalse(self.backend5.invoke_doc_exists())

        # Test sending to verified number with a contact-level backend owned by the domain

        self.case.set_case_property("contact_backend_id", "BACKEND")
        self.case.save()
        self.contact = CommConnectCase.wrap(self.case.to_json())
        verified_number = self.contact.get_verified_number()
        self.assertTrue(verified_number is not None)
        self.assertEqual(verified_number.backend_id, "BACKEND")
        self.assertEqual(verified_number.phone_number, "15551234567")

        self.assertTrue(send_sms_to_verified_number(verified_number, "Test for BACKEND"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertTrue(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend8.delete_invoke_doc()
        self.assertFalse(self.backend8.invoke_doc_exists())

        # Test sending to verified number with a contact-level backend granted to the domain by another domain

        self.backend8.delete()

        self.assertTrue(send_sms_to_verified_number(verified_number, "Test for BACKEND"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertTrue(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend9.delete_invoke_doc()
        self.assertFalse(self.backend9.invoke_doc_exists())

        # Test sending to verified number with a contact-level global backend

        self.backend9.delete()

        self.assertTrue(send_sms_to_verified_number(verified_number, "Test for BACKEND"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertTrue(self.backend10.invoke_doc_exists())
        self.backend10.delete_invoke_doc()
        self.assertFalse(self.backend10.invoke_doc_exists())

        # Test raising exception if contact-level backend is not found

        self.backend10.delete()

        try:
            self.assertTrue(send_sms_to_verified_number(verified_number, "Test for BACKEND"))
        except BadSMSConfigException:
            pass
        else:
            self.assertTrue(False)

        # Test send_sms_with_backend

        self.assertTrue(send_sms_with_backend(self.domain, "+15551234567", "Test for BACKEND3", self.backend3._id))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertTrue(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.backend3.delete_invoke_doc()
        self.assertFalse(self.backend3.invoke_doc_exists())

        # Test send_sms_with_backend_name

        self.assertTrue(send_sms_with_backend_name(self.domain, "+15551234567", "Test for BACKEND3", "BACKEND3"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertTrue(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.backend3.delete_invoke_doc()
        self.assertFalse(self.backend3.invoke_doc_exists())
Example #26
0
class BackendTestCase(BaseSMSTest):
    def get_or_create_site(self):
        site, created = Site.objects.get_or_create(id=settings.SITE_ID)
        if created:
            site.domain = 'localhost'
            site.name = 'localhost'
            site.save()
        return (site, created)

    def setUp(self):
        super(BackendTestCase, self).setUp()

        self.domain = "test-domain"
        self.domain2 = "test-domain2"

        self.site, self.site_created = self.get_or_create_site()

        self.domain_obj = Domain(name=self.domain)
        self.domain_obj.save()

        self.create_account_and_subscription(self.domain_obj.name)
        self.domain_obj = Domain.get(self.domain_obj._id) # Prevent resource conflict

        self.backend1 = TestCaseBackend(name="BACKEND1",is_global=True)
        self.backend1.save()

        self.backend2 = TestCaseBackend(name="BACKEND2",is_global=True)
        self.backend2.save()

        self.backend3 = TestCaseBackend(name="BACKEND3",is_global=True)
        self.backend3.save()

        self.backend4 = TestCaseBackend(name="BACKEND4",is_global=True)
        self.backend4.save()

        self.backend5 = TestCaseBackend(name="BACKEND5",domain=self.domain,is_global=False,authorized_domains=[])
        self.backend5.save()

        self.backend6 = TestCaseBackend(name="BACKEND6",domain=self.domain2,is_global=False,authorized_domains=[self.domain])
        self.backend6.save()

        self.backend7 = TestCaseBackend(name="BACKEND7",domain=self.domain2,is_global=False,authorized_domains=[])
        self.backend7.save()
        
        self.backend8 = TestCaseBackend(name="BACKEND",domain=self.domain,is_global=False,authorized_domains=[])
        self.backend8.save()

        self.backend9 = TestCaseBackend(name="BACKEND",domain=self.domain2,is_global=False,authorized_domains=[self.domain])
        self.backend9.save()

        self.backend10 = TestCaseBackend(name="BACKEND",is_global=True)
        self.backend10.save()

        self.backend_mapping1 = BackendMapping(is_global=True,prefix="*",backend_id=self.backend1._id)
        self.backend_mapping1.save()

        self.backend_mapping2 = BackendMapping(is_global=True,prefix="1",backend_id=self.backend2._id)
        self.backend_mapping2.save()

        self.backend_mapping3 = BackendMapping(is_global=True,prefix="91",backend_id=self.backend3._id)
        self.backend_mapping3.save()

        self.backend_mapping4 = BackendMapping(is_global=True,prefix="265",backend_id=self.backend4._id)
        self.backend_mapping4.save()

        self.backend_mapping5 = BackendMapping(is_global=True, prefix="256", backend_id=self.backend5._id)
        self.backend_mapping5.save()

        self.backend_mapping6 = BackendMapping(is_global=True, prefix="25670", backend_id=self.backend6._id)
        self.backend_mapping6.save()

        self.backend_mapping7 = BackendMapping(is_global=True, prefix="25675", backend_id=self.backend7._id)
        self.backend_mapping7.save()

        self.case = CommCareCase(domain=self.domain)
        self.case.set_case_property("contact_phone_number","15551234567")
        self.case.set_case_property("contact_phone_number_is_verified", "1")
        self.case.save()

        self.contact = CommConnectCase.wrap(self.case.to_json())

        settings.SMS_LOADED_BACKENDS.append("corehq.apps.sms.tests.TestCaseBackend")

    def tearDown(self):
        self.backend1.delete_invoke_doc()
        self.backend1.delete()
        self.backend_mapping1.delete()

        self.backend2.delete_invoke_doc()
        self.backend2.delete()
        self.backend_mapping2.delete()

        self.backend3.delete_invoke_doc()
        self.backend3.delete()
        self.backend_mapping3.delete()

        self.backend4.delete_invoke_doc()
        self.backend4.delete()
        self.backend_mapping4.delete()

        self.backend5.delete_invoke_doc()
        self.backend5.delete()
        self.backend_mapping5.delete()

        self.backend6.delete_invoke_doc()
        self.backend6.delete()
        self.backend_mapping6.delete()

        self.backend7.delete_invoke_doc()
        self.backend7.delete()
        self.backend_mapping7.delete()

        self.contact.delete_verified_number()
        self.case.delete()

        self.domain_obj.delete()

        if self.site_created:
            self.site.delete()

        settings.SMS_LOADED_BACKENDS.pop()

        super(BackendTestCase, self).tearDown()

    def test_multiple_country_prefixes(self):
        self.assertEqual(MobileBackend.auto_load('256800000000')._id, self.backend5._id)
        self.assertEqual(MobileBackend.auto_load('256700000000')._id, self.backend6._id)
        self.assertEqual(MobileBackend.auto_load('256750000000')._id, self.backend7._id)

    def test_backend(self):
        # Test the backend map

        self.assertTrue(send_sms(self.domain, None, "15551234567", "Test for BACKEND2"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertTrue(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend2.delete_invoke_doc()
        self.assertFalse(self.backend2.invoke_doc_exists())

        self.assertTrue(send_sms(self.domain, None, "9100000000", "Test for BACKEND3"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertTrue(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend3.delete_invoke_doc()
        self.assertFalse(self.backend3.invoke_doc_exists())

        self.assertTrue(send_sms(self.domain, None, "26500000000", "Test for BACKEND4"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertTrue(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend4.delete_invoke_doc()
        self.assertFalse(self.backend4.invoke_doc_exists())

        self.assertTrue(send_sms(self.domain, None, "25800000000", "Test for BACKEND1"))
        self.assertTrue(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend1.delete_invoke_doc()
        self.assertFalse(self.backend1.invoke_doc_exists())

        # Test overriding with a domain-level backend

        self.domain_obj = Domain.get(self.domain_obj._id)  # Prevent resource conflict
        self.domain_obj.default_sms_backend_id = self.backend5._id
        self.domain_obj.save()

        self.assertTrue(send_sms(self.domain, None, "15551234567", "Test for BACKEND5"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertTrue(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend5.delete_invoke_doc()
        self.assertFalse(self.backend5.invoke_doc_exists())

        # Test use of backend that another domain owns but has granted access

        self.domain_obj.default_sms_backend_id = self.backend6._id
        self.domain_obj.save()

        self.assertTrue(send_sms(self.domain, None, "25800000000", "Test for BACKEND6"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertTrue(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend6.delete_invoke_doc()
        self.assertFalse(self.backend6.invoke_doc_exists())

        # Test backend access control

        self.domain_obj.default_sms_backend_id = self.backend7._id
        self.domain_obj.save()

        self.assertFalse(send_sms(self.domain, None, "25800000000", "Test for BACKEND7"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())

        # Test sending to verified number with backend map

        self.domain_obj.default_sms_backend_id = None
        self.domain_obj.save()

        verified_number = self.contact.get_verified_number()
        self.assertTrue(verified_number is not None)
        self.assertTrue(verified_number.backend_id is None)
        self.assertEqual(verified_number.phone_number, "15551234567")

        self.assertTrue(send_sms_to_verified_number(verified_number, "Test for BACKEND2"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertTrue(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend2.delete_invoke_doc()
        self.assertFalse(self.backend2.invoke_doc_exists())

        # Test sending to verified number with default domain backend

        self.domain_obj.default_sms_backend_id = self.backend5._id
        self.domain_obj.save()

        self.assertTrue(send_sms_to_verified_number(verified_number, "Test for BACKEND5"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertTrue(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertFalse(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend5.delete_invoke_doc()
        self.assertFalse(self.backend5.invoke_doc_exists())

        # Test sending to verified number with a contact-level backend owned by the domain

        self.case.set_case_property("contact_backend_id", "BACKEND")
        self.case.save()
        self.contact = CommConnectCase.wrap(self.case.to_json())
        verified_number = self.contact.get_verified_number()
        self.assertTrue(verified_number is not None)
        self.assertEqual(verified_number.backend_id, "BACKEND")
        self.assertEqual(verified_number.phone_number, "15551234567")

        self.assertTrue(send_sms_to_verified_number(verified_number, "Test for BACKEND"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertTrue(self.backend8.invoke_doc_exists())
        self.assertFalse(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend8.delete_invoke_doc()
        self.assertFalse(self.backend8.invoke_doc_exists())

        # Test sending to verified number with a contact-level backend granted to the domain by another domain

        self.backend8.delete()

        self.assertTrue(send_sms_to_verified_number(verified_number, "Test for BACKEND"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertTrue(self.backend9.invoke_doc_exists())
        self.assertFalse(self.backend10.invoke_doc_exists())
        self.backend9.delete_invoke_doc()
        self.assertFalse(self.backend9.invoke_doc_exists())

        # Test sending to verified number with a contact-level global backend

        self.backend9.delete()

        self.assertTrue(send_sms_to_verified_number(verified_number, "Test for BACKEND"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertFalse(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.assertTrue(self.backend10.invoke_doc_exists())
        self.backend10.delete_invoke_doc()
        self.assertFalse(self.backend10.invoke_doc_exists())

        # Test raising exception if contact-level backend is not found

        self.backend10.delete()

        try:
            self.assertTrue(send_sms_to_verified_number(verified_number, "Test for BACKEND"))
        except BadSMSConfigException:
            pass
        else:
            self.assertTrue(False)

        # Test send_sms_with_backend

        self.assertTrue(send_sms_with_backend(self.domain, "+15551234567", "Test for BACKEND3", self.backend3._id))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertTrue(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.backend3.delete_invoke_doc()
        self.assertFalse(self.backend3.invoke_doc_exists())

        # Test send_sms_with_backend_name

        self.assertTrue(send_sms_with_backend_name(self.domain, "+15551234567", "Test for BACKEND3", "BACKEND3"))
        self.assertFalse(self.backend1.invoke_doc_exists())
        self.assertFalse(self.backend2.invoke_doc_exists())
        self.assertTrue(self.backend3.invoke_doc_exists())
        self.assertFalse(self.backend4.invoke_doc_exists())
        self.assertFalse(self.backend5.invoke_doc_exists())
        self.assertFalse(self.backend6.invoke_doc_exists())
        self.assertFalse(self.backend7.invoke_doc_exists())
        self.backend3.delete_invoke_doc()
        self.assertFalse(self.backend3.invoke_doc_exists())

    def test_sms_registration(self):
        formatted_username = format_username("tester", self.domain)

        incoming("+9991234567", "JOIN {} WORKER tester".format(self.domain), "TEST_CASE_BACKEND")
        # Test without mobile worker registration enabled
        self.assertIsNone(CommCareUser.get_by_username(formatted_username))

        # Enable mobile worker registration
        setattr(self.domain_obj, "sms_mobile_worker_registration_enabled", True)
        self.domain_obj.save()

        incoming("+9991234567", "JOIN {} WORKER tester".format(self.domain), "TEST_CASE_BACKEND")
        self.assertIsNotNone(CommCareUser.get_by_username(formatted_username))

        # Test a duplicate registration
        prev_num_users = num_mobile_users(self.domain)
        incoming("+9991234568", "JOIN {} WORKER tester".format(self.domain), "TEST_CASE_BACKEND")
        current_num_users = num_mobile_users(self.domain)
        self.assertEqual(prev_num_users, current_num_users)
Example #27
0
class KooKooTestCase(TouchformsTestCase):
    """
    Must be run manually (see corehq.apps.sms.tests.util.TouchformsTestCase)
    """
    def setUp(self):
        super(KooKooTestCase, self).setUp()
        self.ivr_backend = MobileBackend(
            _id="MOBILE_BACKEND_KOOKOO",
            outbound_module="corehq.apps.kookoo.api",
            outbound_params={
                "is_test": True,
                "api_key": "xyz"
            },
        )
        self.ivr_backend.save()

        self.user1 = self.create_mobile_worker("user1",
                                               "123",
                                               "91001",
                                               save_vn=False)
        self.user2 = self.create_mobile_worker("user2",
                                               "123",
                                               "91002",
                                               save_vn=False)
        self.create_group("group1", [self.user1, self.user2])

        self.case = CommCareCase(
            domain=self.domain,
            type="participant",
            owner_id=self.groups[0]._id,
        )
        self.case.set_case_property("contact_phone_number", "91000")
        self.case.set_case_property("contact_phone_number_is_verified", "1")
        self.case.set_case_property("contact_ivr_backend_id",
                                    "MOBILE_BACKEND_KOOKOO")
        self.case.save()

        dirname = os.path.dirname(os.path.abspath(__file__))
        self.load_app("app1.json", dirname)
        self.load_app("app2.json", dirname)

        self.reminder1 = CaseReminderHandler(
            domain=self.domain,
            active=True,
            case_type="participant",
            method=METHOD_IVR_SURVEY,
            recipient=RECIPIENT_CASE,
            sample_id=None,
            user_group_id=None,
            user_id=None,
            case_id=None,
            reminder_type=REMINDER_TYPE_DEFAULT,
            submit_partial_forms=True,
            include_case_side_effects=False,
            max_question_retries=5,
            start_condition_type=CASE_CRITERIA,
            start_property="name",
            start_value="case1",
            start_date=None,
            start_offset=0,
            start_match_type=MATCH_EXACT,
            events=[
                CaseReminderEvent(
                    day_num=0,
                    fire_time=time(12, 0),
                    fire_time_type=FIRE_TIME_DEFAULT,
                    callback_timeout_intervals=[30],
                    form_unique_id=self.apps[0].modules[0].forms[0].unique_id,
                ),
                CaseReminderEvent(
                    day_num=0,
                    fire_time=time(13, 0),
                    fire_time_type=FIRE_TIME_DEFAULT,
                    callback_timeout_intervals=[30],
                    form_unique_id=self.apps[0].modules[0].forms[1].unique_id,
                ),
            ],
            schedule_length=1,
            event_interpretation=EVENT_AS_SCHEDULE,
            max_iteration_count=7,
            until=None,
            force_surveys_to_use_triggered_case=False,
        )
        self.reminder1.save()

        self.reminder2 = CaseReminderHandler(
            domain=self.domain,
            active=True,
            case_type="participant",
            method=METHOD_IVR_SURVEY,
            recipient=RECIPIENT_OWNER,
            sample_id=None,
            user_group_id=None,
            user_id=None,
            case_id=None,
            reminder_type=REMINDER_TYPE_DEFAULT,
            submit_partial_forms=True,
            include_case_side_effects=True,
            max_question_retries=5,
            start_condition_type=CASE_CRITERIA,
            start_property="name",
            start_value="case2",
            start_date=None,
            start_offset=0,
            start_match_type=MATCH_EXACT,
            events=[
                CaseReminderEvent(
                    day_num=0,
                    fire_time=time(12, 0),
                    fire_time_type=FIRE_TIME_DEFAULT,
                    callback_timeout_intervals=[30, 30],
                    form_unique_id=self.apps[1].modules[0].forms[0].unique_id,
                ),
            ],
            schedule_length=1,
            event_interpretation=EVENT_AS_SCHEDULE,
            max_iteration_count=7,
            until=None,
            force_surveys_to_use_triggered_case=False,
        )
        self.reminder2.save()

    def kookoo_in(self, params):
        """
        params should be a dictionary containing:
        event, cid, sid, and (optionally) data
        """
        params = urllib.urlencode(params)
        url = "%s/kookoo/ivr/" % self.live_server_url
        return urllib2.urlopen("%s?%s" % (url, params)).read()

    def kookoo_finished(self, params):
        """
        params should be a dictionary containing:
        sid, status, and duration
        """
        params = urllib.urlencode(params)
        url = "%s/kookoo/ivr_finished/" % self.live_server_url
        return urllib2.urlopen(url, params).read()

    def testOutbound(self):
        # Send an outbound call using self.reminder1 to self.case
        # and answer it
        CaseReminderHandler.now = datetime(2014, 6, 23, 10, 0)
        self.case.name = "case1"
        self.case.save()
        CaseReminderHandler.now = datetime(2014, 6, 23, 12, 0)
        CaseReminderHandler.fire_reminders()
        reminder = self.reminder1.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 23, 12, 30))

        call = self.get_last_outbound_call(self.case)
        self.assertTrue(call.use_precached_first_response)

        kookoo_session_id = call.gateway_session_id[7:]
        resp = self.kookoo_in({
            "cid": "0000",
            "sid": kookoo_session_id,
            "event": "NewCall",
        })
        self.assertEqual(
            resp, '<response sid="%s"><collectdtmf l="1" o="3000">'
            '<playtext>How do you feel today? Press 1 for good, 2 for bad.'
            '</playtext></collectdtmf></response>' % kookoo_session_id)

        resp = self.kookoo_in({
            "cid": "0000",
            "sid": kookoo_session_id,
            "event": "GotDTMF",
            "data": "1",
        })
        self.assertEqual(
            resp, '<response sid="%s"><collectdtmf l="1" o="3000">'
            '<playtext>Did you remember to take your meds today? Press 1 for yes, 2 for no.'
            '</playtext></collectdtmf></response>' % kookoo_session_id)

        resp = self.kookoo_in({
            "cid": "0000",
            "sid": kookoo_session_id,
            "event": "GotDTMF",
            "data": "2",
        })
        self.assertEqual(
            resp,
            '<response sid="%s"><hangup/></response>' % kookoo_session_id)

        self.kookoo_finished({
            "sid": kookoo_session_id,
            "status": "answered",
            "duration": "20",
        })

        call = CallLog.get(call._id)
        self.assertTrue(call.answered)
        self.assertEqual(call.duration, 20)

        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "how_feel", "1")
        self.assertFormQuestionEquals(form, "take_meds", "2")
        case = CommCareCase.get(self.case._id)
        self.assertCasePropertyEquals(case, "how_feel", "1")
        self.assertCasePropertyEquals(case, "take_meds", "2")

        CaseReminderHandler.now = datetime(2014, 6, 23, 12, 30)
        CaseReminderHandler.fire_reminders()

        reminder = self.reminder1.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 23, 13, 0))

        last_call = self.get_last_outbound_call(self.case)
        self.assertEqual(call._id, last_call._id)

        # Move on to the second event which now uses an all-label form and
        # should not precache the first ivr response
        CaseReminderHandler.now = datetime(2014, 6, 23, 13, 0)
        CaseReminderHandler.fire_reminders()

        reminder = self.reminder1.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 23, 13, 30))

        call = self.get_last_outbound_call(self.case)
        self.assertFalse(call.use_precached_first_response)

        kookoo_session_id = call.gateway_session_id[7:]
        resp = self.kookoo_in({
            "cid": "0000",
            "sid": kookoo_session_id,
            "event": "NewCall",
        })
        self.assertEqual(
            resp, '<response sid="%s">'
            '<playtext>This is just a reminder to take your meds.'
            '</playtext><hangup/></response>' % kookoo_session_id)

        self.kookoo_finished({
            "sid": kookoo_session_id,
            "status": "answered",
            "duration": "5",
        })

        call = CallLog.get(call._id)
        self.assertTrue(call.answered)
        self.assertEqual(call.duration, 5)

        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "label", "ok")

        CaseReminderHandler.now = datetime(2014, 6, 23, 13, 30)
        CaseReminderHandler.fire_reminders()

        reminder = self.reminder1.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 24, 12, 0))

        last_call = self.get_last_outbound_call(self.case)
        self.assertEqual(call._id, last_call._id)

        # Now test sending outbound calls to a group of users (the owners
        # of the case)

        # Allow sending to unverified numbers
        self.domain_obj = Domain.get(self.domain_obj._id)
        self.domain_obj.send_to_duplicated_case_numbers = True
        self.domain_obj.save()

        CaseReminderHandler.now = datetime(2014, 6, 24, 10, 0)
        self.case = CommCareCase.get(self.case._id)
        self.case.name = "case2"
        self.case.save()
        reminder = self.reminder2.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 24, 12, 0))

        CaseReminderHandler.now = datetime(2014, 6, 24, 12, 0)
        CaseReminderHandler.fire_reminders()
        reminder = self.reminder2.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 24, 12, 30))

        call1 = self.get_last_outbound_call(self.user1)
        self.assertTrue(call1.use_precached_first_response)
        self.assertFalse(call1.answered)

        call2 = self.get_last_outbound_call(self.user2)
        self.assertTrue(call2.use_precached_first_response)
        self.assertFalse(call2.answered)

        old_call1 = call1
        old_call2 = call2

        CaseReminderHandler.now = datetime(2014, 6, 24, 12, 30)
        CaseReminderHandler.fire_reminders()
        reminder = self.reminder2.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 24, 13, 0))

        call1 = self.get_last_outbound_call(self.user1)
        self.assertTrue(call1.use_precached_first_response)
        self.assertNotEqual(call1._id, old_call1._id)

        call2 = self.get_last_outbound_call(self.user2)
        self.assertTrue(call2.use_precached_first_response)
        self.assertFalse(call2.answered)
        self.assertNotEqual(call2._id, old_call2._id)

        kookoo_session_id = call1.gateway_session_id[7:]
        resp = self.kookoo_in({
            "cid": "0001",
            "sid": kookoo_session_id,
            "event": "NewCall",
        })
        self.assertEqual(
            resp, '<response sid="%s"><collectdtmf l="1" o="3000">'
            '<playtext>How do you feel today? Press 1 for good, 2 for bad.'
            '</playtext></collectdtmf></response>' % kookoo_session_id)

        resp = self.kookoo_in({
            "cid": "0001",
            "sid": kookoo_session_id,
            "event": "GotDTMF",
            "data": "2",
        })
        self.assertEqual(
            resp, '<response sid="%s"><collectdtmf l="1" o="3000">'
            '<playtext>Did you remember to take your meds today? Press 1 for yes, 2 for no.'
            '</playtext></collectdtmf></response>' % kookoo_session_id)

        resp = self.kookoo_in({
            "cid": "0001",
            "sid": kookoo_session_id,
            "event": "GotDTMF",
            "data": "1",
        })
        self.assertEqual(
            resp,
            '<response sid="%s"><hangup/></response>' % kookoo_session_id)

        self.kookoo_finished({
            "sid": kookoo_session_id,
            "status": "answered",
            "duration": "20",
        })
        call1 = CallLog.get(call1._id)
        self.assertTrue(call1.answered)
        self.assertEqual(call1.duration, 20)

        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "how_feel", "2")
        self.assertFormQuestionEquals(form, "take_meds", "1")
        self.assertEqual(form.form["meta"]["userID"], self.user1._id)
        case = CommCareCase.get(self.case._id)
        self.assertCasePropertyEquals(case, "how_feel", "2")
        self.assertCasePropertyEquals(case, "take_meds", "1")
        self.assertEqual(case.user_id, self.user1._id)

        old_call1 = call1
        old_call2 = call2

        CaseReminderHandler.now = datetime(2014, 6, 24, 13, 0)
        CaseReminderHandler.fire_reminders()
        reminder = self.reminder2.get_reminder(self.case)
        self.assertEquals(reminder.next_fire, datetime(2014, 6, 25, 12, 0))

        call1 = self.get_last_outbound_call(self.user1)
        # No new call for user1 since it was already answered
        self.assertEqual(call1._id, old_call1._id)

        call2 = self.get_last_outbound_call(self.user2)
        self.assertTrue(call2.use_precached_first_response)
        self.assertNotEqual(call2._id, old_call2._id)

        kookoo_session_id = call2.gateway_session_id[7:]
        resp = self.kookoo_in({
            "cid": "0002",
            "sid": kookoo_session_id,
            "event": "NewCall",
        })
        self.assertEqual(
            resp, '<response sid="%s"><collectdtmf l="1" o="3000">'
            '<playtext>How do you feel today? Press 1 for good, 2 for bad.'
            '</playtext></collectdtmf></response>' % kookoo_session_id)

        resp = self.kookoo_in({
            "cid": "0002",
            "sid": kookoo_session_id,
            "event": "GotDTMF",
            "data": "1",
        })
        self.assertEqual(
            resp, '<response sid="%s"><collectdtmf l="1" o="3000">'
            '<playtext>Did you remember to take your meds today? Press 1 for yes, 2 for no.'
            '</playtext></collectdtmf></response>' % kookoo_session_id)

        resp = self.kookoo_in({
            "cid": "0002",
            "sid": kookoo_session_id,
            "event": "GotDTMF",
            "data": "2",
        })
        self.assertEqual(
            resp,
            '<response sid="%s"><hangup/></response>' % kookoo_session_id)

        self.kookoo_finished({
            "sid": kookoo_session_id,
            "status": "answered",
            "duration": "20",
        })
        call2 = CallLog.get(call2._id)
        self.assertTrue(call2.answered)
        self.assertEqual(call2.duration, 20)

        form = self.get_last_form_submission()
        self.assertFormQuestionEquals(form, "how_feel", "1")
        self.assertFormQuestionEquals(form, "take_meds", "2")
        self.assertEqual(form.form["meta"]["userID"], self.user2._id)
        case = CommCareCase.get(self.case._id)
        self.assertCasePropertyEquals(case, "how_feel", "1")
        self.assertCasePropertyEquals(case, "take_meds", "2")
        self.assertEqual(case.user_id, self.user2._id)

    def tearDown(self):
        self.ivr_backend.delete()
        super(KooKooTestCase, self).tearDown()