def send_message(self, flow, message, restart_participants=False, contact=None, initiate_flow=False, assert_reply=True): """ Starts the flow, sends the message, returns the reply """ if not contact: contact = self.contact try: if contact.is_test: Contact.set_simulation(True) incoming = self.create_msg(direction=INCOMING, contact=contact, text=message) # start the flow if initiate_flow: flow.start(groups=[], contacts=[contact], restart_participants=restart_participants, start_msg=incoming) else: flow.start(groups=[], contacts=[contact], restart_participants=restart_participants) self.assertTrue(flow.find_and_handle(incoming)) # our message should have gotten a reply if assert_reply: reply = Msg.objects.get(response_to=incoming) self.assertEquals(contact, reply.contact) return reply.text return None finally: Contact.set_simulation(False)
def send_message( self, flow, message, restart_participants=False, contact=None, initiate_flow=False, assert_reply=True, assert_handle=True, ): """ Starts the flow, sends the message, returns the reply """ if not contact: contact = self.contact try: if contact.is_test: Contact.set_simulation(True) incoming = self.create_msg( direction=INCOMING, contact=contact, contact_urn=contact.get_urn(), text=message ) # start the flow if initiate_flow: flow.start( groups=[], contacts=[contact], restart_participants=restart_participants, start_msg=incoming ) else: flow.start(groups=[], contacts=[contact], restart_participants=restart_participants) (handled, msgs) = Flow.find_and_handle(incoming) Msg.mark_handled(incoming) if assert_handle: self.assertTrue(handled, "'%s' did not handle message as expected" % flow.name) else: self.assertFalse(handled, "'%s' handled message, was supposed to ignore" % flow.name) # our message should have gotten a reply if assert_reply: replies = Msg.objects.filter(response_to=incoming).order_by("pk") self.assertGreaterEqual(len(replies), 1) if len(replies) == 1: self.assertEqual(contact, replies.first().contact) return replies.first().text # if it's more than one, send back a list of replies return [reply.text for reply in replies] else: # assert we got no reply replies = Msg.objects.filter(response_to=incoming).order_by("pk") self.assertFalse(replies) return None finally: Contact.set_simulation(False)
def test_twilio_failed_auth(self): def create(self, to=None, from_=None, url=None, status_callback=None): from twilio import TwilioRestException raise TwilioRestException(403, 'http://twilio.com', code=20003) MockTwilioClient.MockCalls.create = create # connect it and check our client is configured self.org.connect_twilio("TEST_SID", "TEST_TOKEN", self.admin) self.org.save() # import an ivr flow self.import_file('call_me_maybe') flow = Flow.objects.filter(name='Call me maybe').first() user_settings = self.admin.get_settings() user_settings.tel = '+18005551212' user_settings.save() test_contact = Contact.get_test_contact(self.admin) Contact.set_simulation(True) flow.start([], [test_contact]) log = ActionLog.objects.all().order_by('-pk').first() self.assertEquals( log.text, 'Call ended. Could not authenticate with your Twilio account. ' 'Check your token and try again.')
def test_rule_first_ivr_flow(self): # connect it and check our client is configured self.org.connect_twilio("TEST_SID", "TEST_TOKEN") self.org.save() # import an ivr flow self.import_file('rule-first-ivr') flow = Flow.objects.filter(name='Rule First IVR').first() user_settings = self.admin.get_settings() user_settings.tel = '+18005551212' user_settings.save() # start our flow` eric = self.create_contact('Eric Newcomer', number='+13603621737') eric.is_test = True eric.save() Contact.set_simulation(True) flow.start([], [eric]) # should be using the usersettings number in test mode self.assertEquals('Placing test call to +1 800-555-1212', ActionLog.objects.all().first().text) # we should have an outbound ivr call now call = IVRCall.objects.filter(direction=OUTGOING).first() self.assertEquals(0, call.get_duration()) self.assertIsNotNone(call) self.assertEquals('CallSid', call.external_id) # after a call is picked up, twilio will call back to our server post_data = dict(CallSid='CallSid', CallStatus='in-progress', CallDuration=20) response = self.client.post(reverse('ivr.ivrcall_handle', args=[call.pk]), post_data) self.assertContains(response, '<Say>Thanks for calling!</Say>')
def test_twilio_failed_auth(self): def create(self, to=None, from_=None, url=None, status_callback=None): from twilio import TwilioRestException raise TwilioRestException(403, 'http://twilio.com', code=20003) MockTwilioClient.MockCalls.create = create # connect it and check our client is configured self.org.connect_twilio("TEST_SID", "TEST_TOKEN") self.org.save() # import an ivr flow self.import_file('call-me-maybe') flow = Flow.objects.filter(name='Call me maybe').first() user_settings = self.admin.get_settings() user_settings.tel = '+18005551212' user_settings.save() test_contact = Contact.get_test_contact(self.admin) Contact.set_simulation(True) flow.start([], [test_contact]) log = ActionLog.objects.all().order_by('-pk').first() self.assertEquals(log.text, 'Call ended. Could not authenticate with your Twilio account. ' 'Check your token and try again.')
def send(self, message, contact=None): if not contact: contact = self.contact if contact.is_test: Contact.set_simulation(True) incoming = self.create_msg(direction=INCOMING, contact=contact, text=message) Flow.find_and_handle(incoming) return Msg.all_messages.filter(response_to=incoming).order_by('pk').first()
def setUp(self): # if we are super verbose, turn on debug for sql queries if self.get_verbosity() > 2: settings.DEBUG = True self.clear_cache() self.superuser = User.objects.create_superuser(username="******", email="*****@*****.**", password="******") # create different user types self.non_org_user = self.create_user("NonOrg") self.user = self.create_user("User") self.editor = self.create_user("Editor") self.admin = self.create_user("Administrator") self.surveyor = self.create_user("Surveyor") # setup admin boundaries for Rwanda self.country = AdminBoundary.objects.create(osm_id='171496', name='Rwanda', level=0) self.state1 = AdminBoundary.objects.create(osm_id='1708283', name='Kigali City', level=1, parent=self.country) self.state2 = AdminBoundary.objects.create(osm_id='171591', name='Eastern Province', level=1, parent=self.country) self.district1 = AdminBoundary.objects.create(osm_id='1711131', name='Gatsibo', level=2, parent=self.state2) self.district2 = AdminBoundary.objects.create(osm_id='1711163', name='Kayônza', level=2, parent=self.state2) self.district3 = AdminBoundary.objects.create(osm_id='3963734', name='Nyarugenge', level=2, parent=self.state1) self.district4 = AdminBoundary.objects.create(osm_id='1711142', name='Rwamagana', level=2, parent=self.state2) self.ward1 = AdminBoundary.objects.create(osm_id='171113181', name='Kageyo', level=3, parent=self.district1) self.ward2 = AdminBoundary.objects.create(osm_id='171116381', name='Kabare', level=3, parent=self.district2) self.ward3 = AdminBoundary.objects.create(osm_id='171114281', name='Bukure', level=3, parent=self.district4) self.org = Org.objects.create(name="Temba", timezone="Africa/Kigali", country=self.country, brand=settings.DEFAULT_BRAND, created_by=self.user, modified_by=self.user) self.org.initialize(topup_size=1000) # add users to the org self.user.set_org(self.org) self.org.viewers.add(self.user) self.editor.set_org(self.org) self.org.editors.add(self.editor) self.admin.set_org(self.org) self.org.administrators.add(self.admin) self.surveyor.set_org(self.org) self.org.surveyors.add(self.surveyor) self.superuser.set_org(self.org) # welcome topup with 1000 credits self.welcome_topup = self.org.topups.all()[0] # a single Android channel self.channel = Channel.create(self.org, self.user, 'RW', 'A', name="Test Channel", address="+250785551212", device="Nexus 5X", secret="12345", gcm_id="123") # reset our simulation to False Contact.set_simulation(False)
def setUp(self): # if we are super verbose, turn on debug for sql queries if self.get_verbosity() > 2: settings.DEBUG = True self.clear_cache() self.superuser = User.objects.create_superuser(username="******", email="*****@*****.**", password="******") # create different user types self.non_org_user = self.create_user("NonOrg") self.user = self.create_user("User") self.editor = self.create_user("Editor") self.admin = self.create_user("Administrator") self.surveyor = self.create_user("Surveyor") # setup admin boundaries for Rwanda self.country = AdminBoundary.objects.create(osm_id='171496', name='Rwanda', level=0) self.state1 = AdminBoundary.objects.create(osm_id='1708283', name='Kigali City', level=1, parent=self.country) self.state2 = AdminBoundary.objects.create(osm_id='171591', name='Eastern Province', level=1, parent=self.country) self.district1 = AdminBoundary.objects.create(osm_id='1711131', name='Gatsibo', level=2, parent=self.state2) self.district2 = AdminBoundary.objects.create(osm_id='1711163', name='Kayônza', level=2, parent=self.state2) self.district3 = AdminBoundary.objects.create(osm_id='3963734', name='Nyarugenge', level=2, parent=self.state1) self.district4 = AdminBoundary.objects.create(osm_id='1711142', name='Rwamagana', level=2, parent=self.state2) self.ward1 = AdminBoundary.objects.create(osm_id='171113181', name='Kageyo', level=3, parent=self.district1) self.ward2 = AdminBoundary.objects.create(osm_id='171116381', name='Kabare', level=3, parent=self.district2) self.ward3 = AdminBoundary.objects.create(osm_id='171114281', name='Bukure', level=3, parent=self.district4) self.org = Org.objects.create(name="Temba", timezone=pytz.timezone("Africa/Kigali"), country=self.country, brand=settings.DEFAULT_BRAND, created_by=self.user, modified_by=self.user) self.org.initialize(topup_size=1000) # add users to the org self.user.set_org(self.org) self.org.viewers.add(self.user) self.editor.set_org(self.org) self.org.editors.add(self.editor) self.admin.set_org(self.org) self.org.administrators.add(self.admin) self.surveyor.set_org(self.org) self.org.surveyors.add(self.surveyor) self.superuser.set_org(self.org) # welcome topup with 1000 credits self.welcome_topup = self.org.topups.all()[0] # a single Android channel self.channel = Channel.create(self.org, self.user, 'RW', 'A', name="Test Channel", address="+250785551212", device="Nexus 5X", secret="12345", gcm_id="123") # reset our simulation to False Contact.set_simulation(False)
def send(self, message, contact=None): if not contact: contact = self.contact if contact.is_test: Contact.set_simulation(True) incoming = self.create_msg(direction=INCOMING, contact=contact, text=message) Flow.find_and_handle(incoming) return Msg.all_messages.filter( response_to=incoming).order_by('pk').first()
def send(self, message, contact=None): if not contact: contact = self.contact if contact.is_test: Contact.set_simulation(True) incoming = self.create_msg(direction=INCOMING, contact=contact, text=message) # evaluate the inbound message against our triggers first from temba.triggers.models import Trigger if not Trigger.find_and_handle(incoming): Flow.find_and_handle(incoming) return Msg.objects.filter(response_to=incoming).order_by('pk').first()
def send_message(self, flow, message, restart_participants=False, contact=None, initiate_flow=False, assert_reply=True): """ Starts the flow, sends the message, returns the reply """ if not contact: contact = self.contact try: if contact.is_test: Contact.set_simulation(True) incoming = self.create_msg(direction=INCOMING, contact=contact, text=message) # start the flow if initiate_flow: flow.start(groups=[], contacts=[contact], restart_participants=restart_participants, start_msg=incoming) else: flow.start(groups=[], contacts=[contact], restart_participants=restart_participants) self.assertTrue( flow.find_and_handle(incoming), "'%s' did not handle message as expected" % flow.name) # our message should have gotten a reply if assert_reply: replies = Msg.objects.filter( response_to=incoming).order_by('pk') self.assertGreaterEqual(len(replies), 1) if len(replies) == 1: self.assertEquals(contact, replies.first().contact) return replies.first().text # if it's more than one, send back a list of replies return [reply.text for reply in replies] return None finally: Contact.set_simulation(False)
def setUp(self): self.clear_cache() self.superuser = User.objects.create_superuser(username="******", email="*****@*****.**", password="******") # some users not tied to our org self.non_org_user = self.create_user("NonOrg") self.non_org_manager = self.create_user("NonOrgManager") # our three user types inside our org self.user = self.create_user("User") self.root = self.create_user("Root") self.root.groups.add(Group.objects.get(name="Alpha")) self.admin = self.create_user("Administrator") # setup admin boundaries for Rwanda self.country = AdminBoundary.objects.create(osm_id='171496', name='Rwanda', level=0) state1 = AdminBoundary.objects.create(osm_id='1708283', name='Kigali City', level=1, parent=self.country) state2 = AdminBoundary.objects.create(osm_id='171591', name='Eastern Province', level=1, parent=self.country) AdminBoundary.objects.create(osm_id='1711131', name='Gatsibo', level=2, parent=state2) AdminBoundary.objects.create(osm_id='1711163', name='Kayonza', level=2, parent=state2) AdminBoundary.objects.create(osm_id='60485579', name='Kigali', level=2, parent=state1) AdminBoundary.objects.create(osm_id='1711142', name='Rwamagana', level=2, parent=state2) self.org = Org.objects.create(name="Temba", timezone="Africa/Kigali", country=self.country, created_by=self.user, modified_by=self.user) self.org.initialize() # add users to the org self.org.administrators.add(self.admin) self.admin.set_org(self.org) self.org.administrators.add(self.root) self.root.set_org(self.org) self.user.set_org(self.org) self.superuser.set_org(self.org) # welcome topup with 1000 credits self.welcome_topup = self.org.topups.all()[0] # a single Android channel self.channel = Channel.objects.create(org=self.org, name="Test Channel", address="+250785551212", country='RW', channel_type='A', secret="12345", gcm_id="123", created_by=self.user, modified_by=self.user) # reset our simulation to False Contact.set_simulation(False)
def setUp(self): self.clear_cache() self.superuser = User.objects.create_superuser(username="******", email="*****@*****.**", password="******") # create different user types self.non_org_user = self.create_user("NonOrg") self.user = self.create_user("User") self.editor = self.create_user("Editor") self.admin = self.create_user("Administrator") self.surveyor = self.create_user("Surveyor") # setup admin boundaries for Rwanda self.country = AdminBoundary.objects.create(osm_id='171496', name='Rwanda', level=0) self.state1 = AdminBoundary.objects.create(osm_id='1708283', name='Kigali City', level=1, parent=self.country) self.state2 = AdminBoundary.objects.create(osm_id='171591', name='Eastern Province', level=1, parent=self.country) self.district1 = AdminBoundary.objects.create(osm_id='1711131', name='Gatsibo', level=2, parent=self.state2) self.district2 = AdminBoundary.objects.create(osm_id='1711163', name='Kayonza', level=2, parent=self.state2) self.district3 = AdminBoundary.objects.create(osm_id='60485579', name='Kigali', level=2, parent=self.state1) self.district4 = AdminBoundary.objects.create(osm_id='1711142', name='Rwamagana', level=2, parent=self.state2) self.org = Org.objects.create(name="Temba", timezone="Africa/Kigali", country=self.country, created_by=self.user, modified_by=self.user) self.org.initialize() # add users to the org self.user.set_org(self.org) self.org.viewers.add(self.user) self.editor.set_org(self.org) self.org.editors.add(self.editor) self.admin.set_org(self.org) self.org.administrators.add(self.admin) self.surveyor.set_org(self.org) self.org.surveyors.add(self.surveyor) self.superuser.set_org(self.org) # welcome topup with 1000 credits self.welcome_topup = self.org.topups.all()[0] # a single Android channel self.channel = Channel.create(self.org, self.user, 'RW', 'A', name="Test Channel", address="+250785551212", secret="12345", gcm_id="123") # reset our simulation to False Contact.set_simulation(False)
def test_rule_first_ivr_flow(self): # connect it and check our client is configured self.org.connect_twilio("TEST_SID", "TEST_TOKEN") self.org.save() # import an ivr flow self.import_file('rule-first-ivr') flow = Flow.objects.filter(name='Rule First IVR').first() user_settings = self.admin.get_settings() user_settings.tel = '+18005551212' user_settings.save() # start our flow eric = self.create_contact('Eric Newcomer', number='+13603621737') eric.is_test = True eric.save() Contact.set_simulation(True) flow.start([], [eric]) # should be using the usersettings number in test mode self.assertEquals('Placing test call to +1 800-555-1212', ActionLog.objects.all().first().text) # we should have an outbound ivr call now call = IVRCall.objects.filter(direction=OUTGOING).first() self.assertEquals(0, call.get_duration()) self.assertIsNotNone(call) self.assertEquals('CallSid', call.external_id) # after a call is picked up, twilio will call back to our server post_data = dict(CallSid='CallSid', CallStatus='in-progress', CallDuration=20) response = self.client.post( reverse('ivr.ivrcall_handle', args=[call.pk]), post_data) self.assertContains(response, '<Say>Thanks for calling!</Say>') # make sure a message from the person on the call goes to the # inbox since our flow doesn't handle text messages msg = self.create_msg(direction='I', contact=eric, text="message during phone call") self.assertFalse(Flow.find_and_handle(msg))
def send_message(self, flow, message, restart_participants=False, contact=None, initiate_flow=False, assert_reply=True): """ Starts the flow, sends the message, returns the reply """ if not contact: contact = self.contact try: if contact.is_test: Contact.set_simulation(True) incoming = self.create_msg(direction=INCOMING, contact=contact, text=message) # start the flow if initiate_flow: flow.start(groups=[], contacts=[contact], restart_participants=restart_participants, start_msg=incoming) else: flow.start(groups=[], contacts=[contact], restart_participants=restart_participants) self.assertTrue(flow.find_and_handle(incoming)) # our message should have gotten a reply if assert_reply: replies = Msg.objects.filter(response_to=incoming).order_by('pk') self.assertGreaterEqual(len(replies), 1) if len(replies) == 1: self.assertEquals(contact, replies.first().contact) return replies.first().text # if it's more than one, send back a list of replies return [reply.text for reply in replies] return None finally: Contact.set_simulation(False)
def test_rule_first_ivr_flow(self): # connect it and check our client is configured self.org.connect_twilio("TEST_SID", "TEST_TOKEN") self.org.save() # import an ivr flow flow = self.get_flow('rule-first-ivr') user_settings = self.admin.get_settings() user_settings.tel = '+18005551212' user_settings.save() # start our flow test_contact = Contact.get_test_contact(self.admin) Contact.set_simulation(True) flow.start([], [test_contact]) # should be using the usersettings number in test mode self.assertEquals('Placing test call to +1 800-555-1212', ActionLog.objects.all().first().text) # we should have an outbound ivr call now call = IVRCall.objects.filter(direction=OUTGOING).first() self.assertEquals(0, call.get_duration()) self.assertIsNotNone(call) self.assertEquals('CallSid', call.external_id) # after a call is picked up, twilio will call back to our server post_data = dict(CallSid='CallSid', CallStatus='in-progress', CallDuration=20) response = self.client.post(reverse('ivr.ivrcall_handle', args=[call.pk]), post_data) self.assertContains(response, '<Say>Thanks for calling!</Say>') # make sure a message from the person on the call goes to the # inbox since our flow doesn't handle text messages msg = self.create_msg(direction='I', contact=test_contact, text="message during phone call") self.assertFalse(Flow.find_and_handle(msg))
def __call__(self, request): Contact.set_simulation(False) response = self.get_response(request) return response
def process_request(self, request): Contact.set_simulation(False) return None
def setUp(self): self.maxDiff = 4096 self.mock_server = mock_server # if we are super verbose, turn on debug for sql queries if self.get_verbosity() > 2: settings.DEBUG = True # make sure we start off without any service users Group.objects.get(name="Service Users").user_set.clear() self.clear_cache() self.create_anonymous_user() self.superuser = User.objects.create_superuser(username="******", email="*****@*****.**", password="******") # create different user types self.non_org_user = self.create_user("NonOrg") self.user = self.create_user("User") self.editor = self.create_user("Editor") self.admin = self.create_user("Administrator") self.surveyor = self.create_user("Surveyor") self.customer_support = self.create_user("support", ("Customer Support",)) # setup admin boundaries for Rwanda self.country = AdminBoundary.create(osm_id="171496", name="Rwanda", level=0) self.state1 = AdminBoundary.create(osm_id="1708283", name="Kigali City", level=1, parent=self.country) self.state2 = AdminBoundary.create(osm_id="171591", name="Eastern Province", level=1, parent=self.country) self.district1 = AdminBoundary.create(osm_id="R1711131", name="Gatsibo", level=2, parent=self.state2) self.district2 = AdminBoundary.create(osm_id="1711163", name="Kayônza", level=2, parent=self.state2) self.district3 = AdminBoundary.create(osm_id="3963734", name="Nyarugenge", level=2, parent=self.state1) self.district4 = AdminBoundary.create(osm_id="1711142", name="Rwamagana", level=2, parent=self.state2) self.ward1 = AdminBoundary.create(osm_id="171113181", name="Kageyo", level=3, parent=self.district1) self.ward2 = AdminBoundary.create(osm_id="171116381", name="Kabare", level=3, parent=self.district2) self.ward3 = AdminBoundary.create(osm_id="VMN.49.1_1", name="Bukure", level=3, parent=self.district4) self.country.update_path() self.org = Org.objects.create( name="Temba", timezone=pytz.timezone("Africa/Kigali"), country=self.country, brand=settings.DEFAULT_BRAND, created_by=self.user, modified_by=self.user, ) self.org.initialize(topup_size=1000) # add users to the org self.user.set_org(self.org) self.org.viewers.add(self.user) self.editor.set_org(self.org) self.org.editors.add(self.editor) self.admin.set_org(self.org) self.org.administrators.add(self.admin) self.surveyor.set_org(self.org) self.org.surveyors.add(self.surveyor) self.superuser.set_org(self.org) # welcome topup with 1000 credits self.welcome_topup = self.org.topups.all()[0] # a single Android channel self.channel = Channel.create( self.org, self.user, "RW", "A", name="Test Channel", address="+250785551212", device="Nexus 5X", secret="12345", gcm_id="123", ) # don't cache anon user between tests from temba import utils utils._anon_user = None clear_flow_users() # reset our simulation to False Contact.set_simulation(False)
def test_ivr_options(self): # should be able to create an ivr flow self.assertTrue(self.org.supports_ivr()) self.assertTrue(self.admin.groups.filter(name="Beta")) self.assertContains(self.client.get(reverse('flows.flow_create')), 'Phone Call') # no twilio config yet self.assertFalse(self.org.is_connected_to_twilio()) self.assertIsNone(self.org.get_twilio_client()) # connect it and check our client is configured self.org.connect_twilio("TEST_SID", "TEST_TOKEN") self.org.save() self.assertTrue(self.org.is_connected_to_twilio()) self.assertIsNotNone(self.org.get_twilio_client()) # import an ivr flow self.import_file('call-me-maybe') # make sure our flow is there as expected flow = Flow.objects.filter(name='Call me maybe').first() self.assertEquals('callme', flow.triggers.all().first().keyword) user_settings = self.admin.get_settings() user_settings.tel = '+18005551212' user_settings.save() # start our flow` eric = self.create_contact('Eric Newcomer', number='+13603621737') eric.is_test = True eric.save() Contact.set_simulation(True) flow.start([], [eric]) # should be using the usersettings number in test mode self.assertEquals('Placing test call to +1 800-555-1212', ActionLog.objects.all().first().text) # we should have an outbound ivr call now call = IVRCall.objects.filter(direction=OUTGOING).first() self.assertEquals(0, call.get_duration()) self.assertIsNotNone(call) self.assertEquals('CallSid', call.external_id) # after a call is picked up, twilio will call back to our server post_data = dict(CallSid='CallSid', CallStatus='in-progress', CallDuration=20) response = self.client.post(reverse('ivr.ivrcall_handle', args=[call.pk]), post_data) self.assertContains(response, '<Say>Would you like me to call you? Press one for yes, two for no, or three for maybe.</Say>') # updated our status and duration accordingly call = IVRCall.objects.get(pk=call.pk) self.assertEquals(20, call.duration) self.assertEquals(IN_PROGRESS, call.status) # should mention our our action log that we read a message to them run = FlowRun.objects.all().first() logs = ActionLog.objects.filter(run=run).order_by('-pk') self.assertEquals(2, len(logs)) self.assertEquals('Read message "Would you like me to call you? Press one for yes, two for no, or three for maybe."', logs.first().text) # press the number 4 (unexpected) response = self.client.post(reverse('ivr.ivrcall_handle', args=[call.pk]), dict(Digits=4)) self.assertContains(response, '<Say>Press one, two, or three. Thanks.</Say>') # now let's have them press the number 3 (for maybe) response = self.client.post(reverse('ivr.ivrcall_handle', args=[call.pk]), dict(Digits=3)) self.assertContains(response, '<Say>This might be crazy.</Say>') # twilio would then disconnect the user and notify us of a completed call self.client.post(reverse('ivr.ivrcall_handle', args=[call.pk]), dict(CallStatus='completed')) self.assertEquals(COMPLETED, IVRCall.objects.get(pk=call.pk).status) # simulation gets flipped off by middleware, and this unhandled message doesn't flip it back on self.assertFalse(Contact.get_simulation()) # test other our call status mappings with twilio def test_status_update(call_to_update, twilio_status, temba_status): call_to_update.update_status(twilio_status, 0) call_to_update.save() self.assertEquals(temba_status, IVRCall.objects.get(pk=call_to_update.pk).status) test_status_update(call, 'queued', QUEUED) test_status_update(call, 'ringing', RINGING) test_status_update(call, 'canceled', CANCELED) test_status_update(call, 'busy', BUSY) test_status_update(call, 'failed', FAILED) test_status_update(call, 'no-answer', NO_ANSWER) # explicitly hanging up an in progress call should remove it call.update_status('in-progress', 0) call.save() IVRCall.hangup_test_call(flow) self.assertIsNone(IVRCall.objects.filter(pk=call.pk).first())
def test_runs(self): url = reverse('api.v2.runs') self.assertEndpointAccess(url) flow1 = self.create_flow(uuid_start=0) flow2 = Flow.copy(flow1, self.user) joe_run1, = flow1.start([], [self.joe]) frank_run1, = flow1.start([], [self.frank]) self.create_msg(direction='I', contact=self.joe, text="it is blue").handle() self.create_msg(direction='I', contact=self.frank, text="Indigo").handle() joe_run2, = flow1.start([], [self.joe], restart_participants=True) frank_run2, = flow1.start([], [self.frank], restart_participants=True) joe_run3, = flow2.start([], [self.joe], restart_participants=True) # add a test contact run Contact.set_simulation(True) flow2.start([], [self.test_contact]) Contact.set_simulation(False) # add a run for another org flow3 = self.create_flow(org=self.org2, user=self.admin2, uuid_start=10000) flow3.start([], [self.hans]) # refresh runs which will have been modified by being interrupted joe_run1.refresh_from_db() joe_run2.refresh_from_db() frank_run1.refresh_from_db() # no filtering with self.assertNumQueries(NUM_BASE_REQUEST_QUERIES + 6): response = self.fetchJSON(url) self.assertEqual(response.status_code, 200) self.assertEqual(response.json['next'], None) self.assertResultsById(response, [joe_run3, frank_run2, frank_run1, joe_run2, joe_run1]) joe_run1_steps = list(joe_run1.steps.order_by('pk')) frank_run2_steps = list(frank_run2.steps.order_by('pk')) self.assertEqual(response.json['results'][1], { 'id': frank_run2.pk, 'flow': {'uuid': flow1.uuid, 'name': "Color Flow"}, 'contact': {'uuid': self.frank.uuid, 'name': self.frank.name}, 'responded': False, 'steps': [ { 'node': "00000000-00000000-00000000-00000001", 'arrived_on': format_datetime(frank_run2_steps[0].arrived_on), 'left_on': format_datetime(frank_run2_steps[0].left_on), 'text': "What is your favorite color?", 'value': None, 'category': None, 'type': 'actionset' }, { 'node': "00000000-00000000-00000000-00000005", 'arrived_on': format_datetime(frank_run2_steps[1].arrived_on), 'left_on': None, 'text': None, 'value': None, 'category': None, 'type': 'ruleset' } ], 'created_on': format_datetime(frank_run2.created_on), 'modified_on': format_datetime(frank_run2.modified_on), 'exited_on': None, 'exit_type': None }) self.assertEqual(response.json['results'][4], { 'id': joe_run1.pk, 'flow': {'uuid': flow1.uuid, 'name': "Color Flow"}, 'contact': {'uuid': self.joe.uuid, 'name': self.joe.name}, 'responded': True, 'steps': [ { 'node': "00000000-00000000-00000000-00000001", 'arrived_on': format_datetime(joe_run1_steps[0].arrived_on), 'left_on': format_datetime(joe_run1_steps[0].left_on), 'text': "What is your favorite color?", 'value': None, 'category': None, 'type': 'actionset' }, { 'node': "00000000-00000000-00000000-00000005", 'arrived_on': format_datetime(joe_run1_steps[1].arrived_on), 'left_on': format_datetime(joe_run1_steps[1].left_on), 'text': 'it is blue', 'value': 'blue', 'category': "Blue", 'type': 'ruleset' }, { 'node': "00000000-00000000-00000000-00000003", 'arrived_on': format_datetime(joe_run1_steps[2].arrived_on), 'left_on': format_datetime(joe_run1_steps[2].left_on), 'text': 'Blue is sad. :(', 'value': None, 'category': None, 'type': 'actionset' } ], 'created_on': format_datetime(joe_run1.created_on), 'modified_on': format_datetime(joe_run1.modified_on), 'exited_on': format_datetime(joe_run1.exited_on), 'exit_type': 'completed' }) # filter by id response = self.fetchJSON(url, 'id=%d' % frank_run2.pk) self.assertResultsById(response, [frank_run2]) # filter by flow response = self.fetchJSON(url, 'flow=%s' % flow1.uuid) self.assertResultsById(response, [frank_run2, frank_run1, joe_run2, joe_run1]) # doesn't work if flow is inactive flow1.is_active = False flow1.save() response = self.fetchJSON(url, 'flow=%s' % flow1.uuid) self.assertResultsById(response, []) # restore to active flow1.is_active = True flow1.save() # filter by invalid flow response = self.fetchJSON(url, 'flow=invalid') self.assertResultsById(response, []) # filter by flow + responded response = self.fetchJSON(url, 'flow=%s&responded=TrUe' % flow1.uuid) self.assertResultsById(response, [frank_run1, joe_run1]) # filter by contact response = self.fetchJSON(url, 'contact=%s' % self.joe.uuid) self.assertResultsById(response, [joe_run3, joe_run2, joe_run1]) # filter by invalid contact response = self.fetchJSON(url, 'contact=invalid') self.assertResultsById(response, []) # filter by contact + responded response = self.fetchJSON(url, 'contact=%s&responded=yes' % self.joe.uuid) self.assertResultsById(response, [joe_run1]) # filter by after response = self.fetchJSON(url, 'after=%s' % format_datetime(frank_run1.modified_on)) self.assertResultsById(response, [joe_run3, frank_run2, frank_run1]) # filter by before response = self.fetchJSON(url, 'before=%s' % format_datetime(frank_run1.modified_on)) self.assertResultsById(response, [frank_run1, joe_run2, joe_run1]) # filter by invalid before response = self.fetchJSON(url, 'before=longago') self.assertResultsById(response, []) # filter by invalid after response = self.fetchJSON(url, 'before=%s&after=thefuture' % format_datetime(frank_run1.modified_on)) self.assertResultsById(response, []) # can't filter by both contact and flow together response = self.fetchJSON(url, 'contact=%s&flow=%s' % (self.joe.uuid, flow1.uuid)) self.assertResponseError(response, None, "You may only specify one of the contact, flow parameters")
def test_ivr_options(self): # should be able to create an ivr flow self.assertTrue(self.org.supports_ivr()) self.assertTrue(self.admin.groups.filter(name="Beta")) self.assertContains(self.client.get(reverse('flows.flow_create')), 'Phone Call') # no twilio config yet self.assertFalse(self.org.is_connected_to_twilio()) self.assertIsNone(self.org.get_twilio_client()) # connect it and check our client is configured self.org.connect_twilio("TEST_SID", "TEST_TOKEN") self.org.save() self.assertTrue(self.org.is_connected_to_twilio()) self.assertIsNotNone(self.org.get_twilio_client()) # import an ivr flow self.import_file('call-me-maybe') # make sure our flow is there as expected flow = Flow.objects.filter(name='Call me maybe').first() self.assertEquals('callme', flow.triggers.all().first().keyword) user_settings = self.admin.get_settings() user_settings.tel = '+18005551212' user_settings.save() # start our flow` eric = self.create_contact('Eric Newcomer', number='+13603621737') eric.is_test = True eric.save() Contact.set_simulation(True) flow.start([], [eric]) # should be using the usersettings number in test mode self.assertEquals('Placing test call to +1 800-555-1212', ActionLog.objects.all().first().text) # we should have an outbound ivr call now call = IVRCall.objects.filter(direction=OUTGOING).first() self.assertEquals(0, call.get_duration()) self.assertIsNotNone(call) self.assertEquals('CallSid', call.external_id) # after a call is picked up, twilio will call back to our server post_data = dict(CallSid='CallSid', CallStatus='in-progress', CallDuration=20) response = self.client.post( reverse('ivr.ivrcall_handle', args=[call.pk]), post_data) self.assertContains( response, '<Say>Would you like me to call you? Press one for yes, two for no, or three for maybe.</Say>' ) # updated our status and duration accordingly call = IVRCall.objects.get(pk=call.pk) self.assertEquals(20, call.duration) self.assertEquals(IN_PROGRESS, call.status) # should mention our our action log that we read a message to them run = FlowRun.objects.all().first() logs = ActionLog.objects.filter(run=run).order_by('-pk') self.assertEquals(2, len(logs)) self.assertEquals( 'Read message "Would you like me to call you? Press one for yes, two for no, or three for maybe."', logs.first().text) # press the number 4 (unexpected) response = self.client.post( reverse('ivr.ivrcall_handle', args=[call.pk]), dict(Digits=4)) self.assertContains(response, '<Say>Press one, two, or three. Thanks.</Say>') # now let's have them press the number 3 (for maybe) response = self.client.post( reverse('ivr.ivrcall_handle', args=[call.pk]), dict(Digits=3)) self.assertContains(response, '<Say>This might be crazy.</Say>') # twilio would then disconnect the user and notify us of a completed call self.client.post(reverse('ivr.ivrcall_handle', args=[call.pk]), dict(CallStatus='completed')) self.assertEquals(COMPLETED, IVRCall.objects.get(pk=call.pk).status) # simulation gets flipped off by middleware, and this unhandled message doesn't flip it back on self.assertFalse(Contact.get_simulation()) # test other our call status mappings with twilio def test_status_update(call_to_update, twilio_status, temba_status): call_to_update.update_status(twilio_status, 0) call_to_update.save() self.assertEquals(temba_status, IVRCall.objects.get(pk=call_to_update.pk).status) test_status_update(call, 'queued', QUEUED) test_status_update(call, 'ringing', RINGING) test_status_update(call, 'canceled', CANCELED) test_status_update(call, 'busy', BUSY) test_status_update(call, 'failed', FAILED) test_status_update(call, 'no-answer', NO_ANSWER) # explicitly hanging up an in progress call should remove it call.update_status('in-progress', 0) call.save() IVRCall.hangup_test_call(flow) self.assertIsNone(IVRCall.objects.filter(pk=call.pk).first())
def test_ivr_flow(self): # should be able to create an ivr flow self.assertTrue(self.org.supports_ivr()) self.assertTrue(self.admin.groups.filter(name="Beta")) self.assertContains(self.client.get(reverse('flows.flow_create')), 'Phone Call') # no twilio config yet self.assertFalse(self.org.is_connected_to_twilio()) self.assertIsNone(self.org.get_twilio_client()) # connect it and check our client is configured self.org.connect_twilio("TEST_SID", "TEST_TOKEN", self.admin) self.org.save() self.assertTrue(self.org.is_connected_to_twilio()) self.assertIsNotNone(self.org.get_twilio_client()) # import an ivr flow self.import_file('call_me_maybe') # make sure our flow is there as expected flow = Flow.objects.filter(name='Call me maybe').first() self.assertEquals( 'callme', flow.triggers.filter(trigger_type='K').first().keyword) user_settings = self.admin.get_settings() user_settings.tel = '+18005551212' user_settings.save() # start our flow as a test contact test_contact = Contact.get_test_contact(self.admin) Contact.set_simulation(True) flow.start([], [test_contact]) call = IVRCall.objects.filter(direction=OUTGOING).first() # should be using the usersettings number in test mode self.assertEquals('Placing test call to +1 800-555-1212', ActionLog.objects.all().first().text) # explicitly hanging up on a test call should remove it call.update_status('in-progress', 0) call.save() IVRCall.hangup_test_call(flow) self.assertTrue(IVRCall.objects.filter(pk=call.pk).first()) ActionLog.objects.all().delete() IVRCall.objects.all().delete() # now pretend we are a normal caller eric = self.create_contact('Eric Newcomer', number='+13603621737') Contact.set_simulation(False) flow.start([], [eric], restart_participants=True) # we should have an outbound ivr call now call = IVRCall.objects.filter(direction=OUTGOING).first() self.assertEquals(0, call.get_duration()) self.assertIsNotNone(call) self.assertEquals('CallSid', call.external_id) # after a call is picked up, twilio will call back to our server post_data = dict(CallSid='CallSid', CallStatus='in-progress', CallDuration=20) response = self.client.post( reverse('ivr.ivrcall_handle', args=[call.pk]), post_data) self.assertContains( response, '<Say>Would you like me to call you? Press one for yes, two for no, or three for maybe.</Say>' ) self.assertEquals(1, Msg.all_messages.filter(msg_type=IVR).count()) self.assertEquals(1, self.org.get_credits_used()) # make sure a message from the person on the call goes to the # inbox since our flow doesn't handle text messages msg = self.create_msg(direction='I', contact=eric, text="message during phone call") self.assertFalse(Flow.find_and_handle(msg)) # updated our status and duration accordingly call = IVRCall.objects.get(pk=call.pk) self.assertEquals(20, call.duration) self.assertEquals(IN_PROGRESS, call.status) # don't press any numbers, but # instead response = self.client.post( reverse('ivr.ivrcall_handle', args=[call.pk]) + "?empty=1", dict()) self.assertContains(response, '<Say>Press one, two, or three. Thanks.</Say>') self.assertEquals(4, self.org.get_credits_used()) # press the number 4 (unexpected) response = self.client.post( reverse('ivr.ivrcall_handle', args=[call.pk]), dict(Digits=4)) # our inbound message should be handled msg = Msg.current_messages.filter( text='4', msg_type=IVR).order_by('-created_on').first() self.assertEqual('H', msg.status) self.assertContains(response, '<Say>Press one, two, or three. Thanks.</Say>') self.assertEquals(6, self.org.get_credits_used()) # two more messages, one inbound and it's response self.assertEquals(5, Msg.all_messages.filter(msg_type=IVR).count()) # now let's have them press the number 3 (for maybe) response = self.client.post( reverse('ivr.ivrcall_handle', args=[call.pk]), dict(Digits=3)) self.assertContains(response, '<Say>This might be crazy.</Say>') messages = Msg.all_messages.filter(msg_type=IVR).order_by('pk') self.assertEquals(7, messages.count()) self.assertEquals(8, self.org.get_credits_used()) for msg in messages: self.assertEquals(1, msg.steps.all().count(), msg="Message '%s' not attached to step" % msg.text) # twilio would then disconnect the user and notify us of a completed call self.client.post(reverse('ivr.ivrcall_handle', args=[call.pk]), dict(CallStatus='completed')) call = IVRCall.objects.get(pk=call.pk) self.assertEquals(COMPLETED, call.status) self.assertFalse(FlowRun.objects.filter(call=call).first().is_active) # simulation gets flipped off by middleware, and this unhandled message doesn't flip it back on self.assertFalse(Contact.get_simulation()) # also shouldn't have any ActionLogs for non-test users self.assertEquals(0, ActionLog.objects.all().count()) self.assertEquals(1, flow.get_completed_runs()) # should still have no active runs self.assertEquals(0, FlowRun.objects.filter(is_active=True).count()) # and we've exited the flow step = FlowStep.objects.all().order_by('-pk').first() self.assertTrue(step.left_on) # test other our call status mappings with twilio def test_status_update(call_to_update, twilio_status, temba_status): call_to_update.update_status(twilio_status, 0) call_to_update.save() self.assertEquals(temba_status, IVRCall.objects.get(pk=call_to_update.pk).status) test_status_update(call, 'queued', QUEUED) test_status_update(call, 'ringing', RINGING) test_status_update(call, 'canceled', CANCELED) test_status_update(call, 'busy', BUSY) test_status_update(call, 'failed', FAILED) test_status_update(call, 'no-answer', NO_ANSWER) FlowStep.objects.all().delete() IVRCall.objects.all().delete() # try sending callme trigger from temba.msgs.models import INCOMING msg = self.create_msg(direction=INCOMING, contact=eric, text="callme") # make sure if we are started with a message we still create a normal voice run flow.start([], [eric], restart_participants=True, start_msg=msg) # we should have an outbound ivr call now, and no steps yet call = IVRCall.objects.filter(direction=OUTGOING).first() self.assertIsNotNone(call) self.assertEquals(0, FlowStep.objects.all().count()) # after a call is picked up, twilio will call back to our server post_data = dict(CallSid='CallSid', CallStatus='in-progress', CallDuration=20) self.client.post(reverse('ivr.ivrcall_handle', args=[call.pk]), post_data) # should have two flow steps (the outgoing messages, and the step to handle the response) steps = FlowStep.objects.all().order_by('pk') # the first step has exactly one message which is an outgoing IVR message self.assertEquals(1, steps.first().messages.all().count()) self.assertEquals( 1, steps.first().messages.filter(direction=OUTGOING, msg_type=IVR).count()) # the next step shouldn't have any messages yet since they haven't pressed anything self.assertEquals(0, steps[1].messages.all().count()) # try updating our status to completed for a test contact Contact.set_simulation(True) flow.start([], [test_contact]) call = IVRCall.objects.filter( direction=OUTGOING).order_by('-pk').first() call.update_status('completed', 30) call.save() call.refresh_from_db() self.assertEqual(ActionLog.objects.all().order_by('-pk').first().text, 'Call ended.') self.assertEqual(call.duration, 30) # now look at implied duration call.update_status('in-progress', None) call.save() call.refresh_from_db() self.assertIsNotNone(call.get_duration())
def setUp(self): self.clear_cache() self.superuser = User.objects.create_superuser(username="******", email="*****@*****.**", password="******") # some users not tied to our org self.non_org_user = self.create_user("NonOrg") self.non_org_manager = self.create_user("NonOrgManager") # our three user types inside our org self.user = self.create_user("User") self.root = self.create_user("Root") self.root.groups.add(Group.objects.get(name="Alpha")) self.admin = self.create_user("Administrator") # setup admin boundaries for Rwanda self.country = AdminBoundary.objects.create(osm_id='171496', name='Rwanda', level=0) state1 = AdminBoundary.objects.create(osm_id='1708283', name='Kigali City', level=1, parent=self.country) state2 = AdminBoundary.objects.create(osm_id='171591', name='Eastern Province', level=1, parent=self.country) AdminBoundary.objects.create(osm_id='1711131', name='Gatsibo', level=2, parent=state2) AdminBoundary.objects.create(osm_id='1711163', name='Kayonza', level=2, parent=state2) AdminBoundary.objects.create(osm_id='60485579', name='Kigali', level=2, parent=state1) AdminBoundary.objects.create(osm_id='1711142', name='Rwamagana', level=2, parent=state2) self.org = Org.objects.create(name="Temba", timezone="Africa/Kigali", country=self.country, created_by=self.user, modified_by=self.user) # add users to the org self.org.administrators.add(self.admin) self.admin.set_org(self.org) self.org.administrators.add(self.root) self.root.set_org(self.org) self.user.set_org(self.org) self.superuser.set_org(self.org) # welcome topup with 1000 credits self.welcome_topup = self.org.create_welcome_topup(self.admin) # a single Android channel self.channel = Channel.objects.create(org=self.org, name="Test Channel", address="+250785551212", country='RW', channel_type='A', secret="12345", gcm_id="123", created_by=self.user, modified_by=self.user) # reset our simulation to False Contact.set_simulation(False)
def test_ivr_flow(self): # should be able to create an ivr flow self.assertTrue(self.org.supports_ivr()) self.assertTrue(self.admin.groups.filter(name="Beta")) self.assertContains(self.client.get(reverse('flows.flow_create')), 'Phone Call') # no twilio config yet self.assertFalse(self.org.is_connected_to_twilio()) self.assertIsNone(self.org.get_twilio_client()) # connect it and check our client is configured self.org.connect_twilio("TEST_SID", "TEST_TOKEN") self.org.save() self.assertTrue(self.org.is_connected_to_twilio()) self.assertIsNotNone(self.org.get_twilio_client()) # import an ivr flow self.import_file('call-me-maybe') # make sure our flow is there as expected flow = Flow.objects.filter(name='Call me maybe').first() self.assertEquals('callme', flow.triggers.filter(trigger_type='K').first().keyword) user_settings = self.admin.get_settings() user_settings.tel = '+18005551212' user_settings.save() # start our flow as a test contact test_contact = Contact.get_test_contact(self.admin) Contact.set_simulation(True) flow.start([], [test_contact]) call = IVRCall.objects.filter(direction=OUTGOING).first() # should be using the usersettings number in test mode self.assertEquals('Placing test call to +1 800-555-1212', ActionLog.objects.all().first().text) # explicitly hanging up on a test call should remove it call.update_status('in-progress', 0) call.save() IVRCall.hangup_test_call(flow) self.assertIsNone(IVRCall.objects.filter(pk=call.pk).first()) ActionLog.objects.all().delete() IVRCall.objects.all().delete() # now pretend we are a normal caller eric = self.create_contact('Eric Newcomer', number='+13603621737') Contact.set_simulation(False) flow.start([], [eric], restart_participants=True) # we should have an outbound ivr call now call = IVRCall.objects.filter(direction=OUTGOING).first() self.assertEquals(0, call.get_duration()) self.assertIsNotNone(call) self.assertEquals('CallSid', call.external_id) # after a call is picked up, twilio will call back to our server post_data = dict(CallSid='CallSid', CallStatus='in-progress', CallDuration=20) response = self.client.post(reverse('ivr.ivrcall_handle', args=[call.pk]), post_data) self.assertContains(response, '<Say>Would you like me to call you? Press one for yes, two for no, or three for maybe.</Say>') self.assertEquals(1, Msg.all_messages.filter(msg_type=IVR).count()) self.assertEquals(1, self.org.get_credits_used()) # make sure a message from the person on the call goes to the # inbox since our flow doesn't handle text messages msg = self.create_msg(direction='I', contact=eric, text="message during phone call") self.assertFalse(Flow.find_and_handle(msg)) # updated our status and duration accordingly call = IVRCall.objects.get(pk=call.pk) self.assertEquals(20, call.duration) self.assertEquals(IN_PROGRESS, call.status) # press the number 4 (unexpected) response = self.client.post(reverse('ivr.ivrcall_handle', args=[call.pk]), dict(Digits=4)) self.assertContains(response, '<Say>Press one, two, or three. Thanks.</Say>') self.assertEquals(4, self.org.get_credits_used()) # two more messages, one inbound and it's response self.assertEquals(3, Msg.all_messages.filter(msg_type=IVR).count()) # now let's have them press the number 3 (for maybe) response = self.client.post(reverse('ivr.ivrcall_handle', args=[call.pk]), dict(Digits=3)) self.assertContains(response, '<Say>This might be crazy.</Say>') messages = Msg.all_messages.filter(msg_type=IVR).order_by('pk') self.assertEquals(5, messages.count()) self.assertEquals(6, self.org.get_credits_used()) for msg in messages: self.assertEquals(1, msg.steps.all().count(), msg="Message '%s' not attached to step" % msg.text) # twilio would then disconnect the user and notify us of a completed call self.client.post(reverse('ivr.ivrcall_handle', args=[call.pk]), dict(CallStatus='completed')) call = IVRCall.objects.get(pk=call.pk) self.assertEquals(COMPLETED, call.status) self.assertFalse(FlowRun.objects.filter(call=call).first().is_active) # simulation gets flipped off by middleware, and this unhandled message doesn't flip it back on self.assertFalse(Contact.get_simulation()) # also shouldn't have any ActionLogs for non-test users self.assertEquals(0, ActionLog.objects.all().count()) self.assertEquals(1, flow.get_completed_runs()) # should still have no active runs self.assertEquals(0, FlowRun.objects.filter(is_active=True).count()) # and we've exited the flow step = FlowStep.objects.all().order_by('-pk').first() self.assertTrue(step.left_on) # test other our call status mappings with twilio def test_status_update(call_to_update, twilio_status, temba_status): call_to_update.update_status(twilio_status, 0) call_to_update.save() self.assertEquals(temba_status, IVRCall.objects.get(pk=call_to_update.pk).status) test_status_update(call, 'queued', QUEUED) test_status_update(call, 'ringing', RINGING) test_status_update(call, 'canceled', CANCELED) test_status_update(call, 'busy', BUSY) test_status_update(call, 'failed', FAILED) test_status_update(call, 'no-answer', NO_ANSWER) FlowStep.objects.all().delete() IVRCall.objects.all().delete() # try sending callme trigger from temba.msgs.models import INCOMING msg = self.create_msg(direction=INCOMING, contact=eric, text="callme") # make sure if we are started with a message we still create a normal voice run flow.start([], [eric], restart_participants=True, start_msg=msg) # we should have an outbound ivr call now, and no steps yet call = IVRCall.objects.filter(direction=OUTGOING).first() self.assertIsNotNone(call) self.assertEquals(0, FlowStep.objects.all().count()) # after a call is picked up, twilio will call back to our server post_data = dict(CallSid='CallSid', CallStatus='in-progress', CallDuration=20) self.client.post(reverse('ivr.ivrcall_handle', args=[call.pk]), post_data) # should have two flow steps (the outgoing messages, and the step to handle the response) steps = FlowStep.objects.all().order_by('pk') # the first step has exactly one message which is an outgoing IVR message self.assertEquals(1, steps.first().messages.all().count()) self.assertEquals(1, steps.first().messages.filter(direction=OUTGOING, msg_type=IVR).count()) # the next step shouldn't have any messages yet since they haven't pressed anything self.assertEquals(0, steps[1].messages.all().count()) # try updating our status to completed for a test contact Contact.set_simulation(True) flow.start([], [test_contact]) call = IVRCall.objects.filter(direction=OUTGOING).order_by('-pk').first() call.update_status('completed', 30) call.save() call.refresh_from_db() self.assertEqual(ActionLog.objects.all().order_by('-pk').first().text, 'Call ended.') self.assertEqual(call.duration, 30) # now look at implied duration call.update_status('in-progress', None) call.save() call.refresh_from_db() self.assertIsNotNone(call.get_duration())
def setUp(self): self.maxDiff = 4096 self.mock_server = mock_server # if we are super verbose, turn on debug for sql queries if self.get_verbosity() > 2: settings.DEBUG = True # make sure we start off without any service users Group.objects.get(name="Service Users").user_set.clear() self.clear_cache() self.create_anonymous_user() self.superuser = User.objects.create_superuser(username="******", email="*****@*****.**", password="******") # create different user types self.non_org_user = self.create_user("NonOrg") self.user = self.create_user("User") self.editor = self.create_user("Editor") self.admin = self.create_user("Administrator") self.surveyor = self.create_user("Surveyor") self.customer_support = self.create_user("support", ("Customer Support", )) # setup admin boundaries for Rwanda self.country = AdminBoundary.create(osm_id="171496", name="Rwanda", level=0) self.state1 = AdminBoundary.create(osm_id="1708283", name="Kigali City", level=1, parent=self.country) self.state2 = AdminBoundary.create(osm_id="171591", name="Eastern Province", level=1, parent=self.country) self.district1 = AdminBoundary.create(osm_id="1711131", name="Gatsibo", level=2, parent=self.state2) self.district2 = AdminBoundary.create(osm_id="1711163", name="Kayônza", level=2, parent=self.state2) self.district3 = AdminBoundary.create(osm_id="3963734", name="Nyarugenge", level=2, parent=self.state1) self.district4 = AdminBoundary.create(osm_id="1711142", name="Rwamagana", level=2, parent=self.state2) self.ward1 = AdminBoundary.create(osm_id="171113181", name="Kageyo", level=3, parent=self.district1) self.ward2 = AdminBoundary.create(osm_id="171116381", name="Kabare", level=3, parent=self.district2) self.ward3 = AdminBoundary.create(osm_id="171114281", name="Bukure", level=3, parent=self.district4) self.country.update_path() self.org = Org.objects.create( name="Temba", timezone=pytz.timezone("Africa/Kigali"), country=self.country, brand=settings.DEFAULT_BRAND, created_by=self.user, modified_by=self.user, ) self.org.initialize(topup_size=1000) # add users to the org self.user.set_org(self.org) self.org.viewers.add(self.user) self.editor.set_org(self.org) self.org.editors.add(self.editor) self.admin.set_org(self.org) self.org.administrators.add(self.admin) self.surveyor.set_org(self.org) self.org.surveyors.add(self.surveyor) self.superuser.set_org(self.org) # welcome topup with 1000 credits self.welcome_topup = self.org.topups.all()[0] # a single Android channel self.channel = Channel.create( self.org, self.user, "RW", "A", name="Test Channel", address="+250785551212", device="Nexus 5X", secret="12345", gcm_id="123", ) # don't cache anon user between tests from temba import utils utils._anon_user = None clear_flow_users() # reset our simulation to False Contact.set_simulation(False)