def test_download_media(self): self.org.connect_twilio("TEST_SID", "TEST_TOKEN", self.admin) self.org.save() with patch('requests.get') as response: mock1 = MockResponse(404, 'No such file') mock2 = MockResponse(200, 'Fake VCF Bits') mock2.add_header('Content-Type', 'text/x-vcard') mock2.add_header('Content-Disposition', 'inline') response.side_effect = (mock1, mock2) twilio_client = self.org.get_twilio_client() with patch('temba.orgs.models.Org.save_media') as mock_save_media: mock_save_media.return_value = 'SAVED' output = twilio_client.download_media( 'http://api.twilio.com/ASID/Media/SID') self.assertIsNotNone(output) self.assertEqual(output, 'text/x-vcard:SAVED') # saved_media was called with a file as first argument and the guessed extension as second argument self.assertIsInstance(mock_save_media.call_args_list[0][0][0], File) self.assertEqual(mock_save_media.call_args_list[0][0][1], 'vcf')
def test_non_blocking_rule_ivr(self): self.org.connect_twilio("TEST_SID", "TEST_TOKEN", self.admin) self.org.save() # flow goes: passive -> recording -> msg flow = self.get_flow('non_blocking_rule_ivr') print json.dumps(flow.as_json(), indent=2) # start marshall in the flow eminem = self.create_contact('Eminem', '+12345') flow.start(groups=[], contacts=[eminem]) call = IVRCall.objects.filter(direction=OUTGOING).first() self.assertNotEquals(call, None) # 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 steps so far, right up to the recording self.assertEquals(2, FlowStep.objects.all().count()) # no outbound yet self.assertEquals( None, Msg.all_messages.filter(direction='O', contact=eminem).first()) # now pretend we got a recording from temba.tests import MockResponse with patch('requests.get') as response: mock = MockResponse(200, 'Fake Recording Bits') mock.add_header('Content-Disposition', 'filename="audio0000.wav"') mock.add_header('Content-Type', 'audio/x-wav') response.return_value = mock self.client.post( reverse('ivr.ivrcall_handle', args=[call.pk]), dict(CallStatus='in-progress', Digits='#', RecordingUrl='http://api.twilio.com/ASID/Recordings/SID', RecordingSid='FAKESID')) # now we should have an outbound message self.assertEquals( 'Hi there Eminem', Msg.all_messages.filter(direction='O', contact=eminem).first().text)
def test_non_blocking_rule_ivr(self): self.org.connect_twilio("TEST_SID", "TEST_TOKEN", self.admin) self.org.save() # flow goes: passive -> recording -> msg flow = self.get_flow("non_blocking_rule_ivr") print json.dumps(flow.as_json(), indent=2) # start marshall in the flow eminem = self.create_contact("Eminem", "+12345") flow.start(groups=[], contacts=[eminem]) call = IVRCall.objects.filter(direction=OUTGOING).first() self.assertNotEquals(call, None) # 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 steps so far, right up to the recording self.assertEquals(2, FlowStep.objects.all().count()) # no outbound yet self.assertEquals(None, Msg.all_messages.filter(direction="O", contact=eminem).first()) # now pretend we got a recording from temba.tests import MockResponse with patch("requests.get") as response: mock = MockResponse(200, "Fake Recording Bits") mock.add_header("Content-Disposition", 'filename="audio0000.wav"') mock.add_header("Content-Type", "audio/x-wav") response.return_value = mock self.client.post( reverse("ivr.ivrcall_handle", args=[call.pk]), dict( CallStatus="in-progress", Digits="#", RecordingUrl="http://api.twilio.com/ASID/Recordings/SID", RecordingSid="FAKESID", ), ) # now we should have an outbound message self.assertEquals("Hi there Eminem", Msg.all_messages.filter(direction="O", contact=eminem).first().text)
def test_download_media(self): self.org.connect_twilio("TEST_SID", "TEST_TOKEN", self.admin) self.org.save() with patch("requests.get") as response: mock1 = MockResponse(404, "No such file") mock2 = MockResponse(200, "Fake VCF Bits") mock2.add_header("Content-Type", "text/x-vcard") mock2.add_header("Content-Disposition", "inline") response.side_effect = (mock1, mock2) twilio_client = self.org.get_twilio_client() with patch("temba.orgs.models.Org.save_media") as mock_save_media: mock_save_media.return_value = "SAVED" output = twilio_client.download_media("http://api.twilio.com/ASID/Media/SID") self.assertIsNotNone(output) self.assertEqual(output, "text/x-vcard:SAVED") # saved_media was called with a file as first argument and the guessed extension as second argument self.assertIsInstance(mock_save_media.call_args_list[0][0][0], File) self.assertEqual(mock_save_media.call_args_list[0][0][1], "vcf")
def test_ivr_recording(self): # create our ivr setup self.org.connect_twilio("TEST_SID", "TEST_TOKEN", self.admin) self.org.save() self.import_file('capture_recording') flow = Flow.objects.filter(name='Capture Recording').first() # start our flow contact = self.create_contact('Chuck D', number='+13603621737') flow.start([], [contact]) call = IVRCall.objects.filter(direction=OUTGOING).first() # 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>Please make a recording after the tone.</Say>') # simulate the caller making a recording and then hanging up, first they'll give us the # recording (they give us a call status of completed at the same time) from temba.tests import MockResponse with patch('requests.get') as response: mock1 = MockResponse(404, 'No such file') mock2 = MockResponse(200, 'Fake Recording Bits') mock2.add_header('Content-Type', 'audio/x-wav') response.side_effect = (mock1, mock2) self.client.post( reverse('ivr.ivrcall_handle', args=[call.pk]), dict(CallStatus='completed', Digits='hangup', RecordingUrl='http://api.twilio.com/ASID/Recordings/SID', RecordingSid='FAKESID')) # we should have captured the recording, and ended the call call = IVRCall.objects.get(pk=call.pk) self.assertEquals(COMPLETED, call.status) # twilio will also send us a final completion message with the call duration (status of completed again) self.client.post(reverse('ivr.ivrcall_handle', args=[call.pk]), dict(CallStatus='completed', CallDuration='15')) call = IVRCall.objects.get(pk=call.pk) self.assertEquals(COMPLETED, call.status) self.assertEquals(15, call.duration) messages = Msg.all_messages.filter(msg_type=IVR).order_by('pk') self.assertEquals(4, messages.count()) self.assertEquals(4, self.org.get_credits_used()) # we should have played a recording from the contact back to them outbound_msg = messages[1] self.assertTrue(outbound_msg.media.startswith('audio/x-wav:https://')) self.assertTrue(outbound_msg.media.endswith('.wav')) self.assertTrue(outbound_msg.text.startswith('https://')) self.assertTrue(outbound_msg.text.endswith('.wav')) media_msg = messages[2] self.assertTrue(media_msg.media.startswith('audio/x-wav:https://')) self.assertTrue(media_msg.media.endswith('.wav')) self.assertTrue(media_msg.text.startswith('https://')) self.assertTrue(media_msg.text.endswith('.wav')) (host, directory, filename) = media_msg.media.rsplit('/', 2) recording = '%s/%s/%s/media/%s/%s' % (settings.MEDIA_ROOT, settings.STORAGE_ROOT_DIR, self.org.pk, directory, filename) self.assertTrue(os.path.isfile(recording)) from temba.flows.models import FlowStep steps = FlowStep.objects.all() self.assertEquals(4, steps.count()) # each of our steps should have exactly one message for step in steps: self.assertEquals( 1, step.messages.all().count(), msg="Step '%s' does not have excatly one message" % step) # each message should have exactly one step for msg in messages: self.assertEquals( 1, msg.steps.all().count(), msg="Message '%s' is not attached to exaclty one step" % msg.text)
def test_ivr_recording(self): # create our ivr setup self.org.connect_twilio("TEST_SID", "TEST_TOKEN") self.org.save() self.import_file('capture-recording') flow = Flow.objects.filter(name='Capture Recording').first() # start our flow contact = self.create_contact('Chuck D', number='+13603621737') flow.start([], [contact]) call = IVRCall.objects.filter(direction=OUTGOING).first() # 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>Please make a recording after the tone.</Say>') # simulate the caller making a recording and then hanging up, first they'll give us the # recording (they give us a call status of completed at the same time) from temba.tests import MockResponse with patch('requests.get') as response: mock = MockResponse(200, 'Fake Recording Bits') mock.add_header('Content-Type', 'audio/x-wav') response.return_value = mock self.client.post(reverse('ivr.ivrcall_handle', args=[call.pk]), dict(CallStatus='completed', Digits='hangup', RecordingUrl='http://api.twilio.com/ASID/Recordings/SID', RecordingSid='FAKESID')) # we should have captured the recording, and ended the call call = IVRCall.objects.get(pk=call.pk) self.assertEquals(COMPLETED, call.status) # twilio will also send us a final completion message with the call duration (status of completed again) self.client.post(reverse('ivr.ivrcall_handle', args=[call.pk]), dict(CallStatus='completed', CallDuration='15')) call = IVRCall.objects.get(pk=call.pk) self.assertEquals(COMPLETED, call.status) self.assertEquals(15, call.duration) messages = Msg.all_messages.filter(msg_type=IVR).order_by('pk') self.assertEquals(4, messages.count()) self.assertEquals(4, self.org.get_credits_used()) # we should have played a recording from the contact back to them outbound_msg = messages[1] self.assertTrue(outbound_msg.media.startswith('audio/x-wav:https://')) self.assertTrue(outbound_msg.media.endswith('.wav')) self.assertTrue(outbound_msg.text.startswith('https://')) self.assertTrue(outbound_msg.text.endswith('.wav')) media_msg = messages[2] self.assertTrue(media_msg.media.startswith('audio/x-wav:https://')) self.assertTrue(media_msg.media.endswith('.wav')) self.assertTrue(media_msg.text.startswith('https://')) self.assertTrue(media_msg.text.endswith('.wav')) (host, directory, filename) = media_msg.media.rsplit('/', 2) recording = '%s/%s/%s/media/%s/%s' % (settings.MEDIA_ROOT, settings.STORAGE_ROOT_DIR, self.org.pk, directory, filename) self.assertTrue(os.path.isfile(recording)) from temba.flows.models import FlowStep steps = FlowStep.objects.all() self.assertEquals(4, steps.count()) # each of our steps should have exactly one message for step in steps: self.assertEquals(1, step.messages.all().count(), msg="Step '%s' does not have excatly one message" % step) # each message should have exactly one step for msg in messages: self.assertEquals(1, msg.steps.all().count(), msg="Message '%s' is not attached to exaclty one step" % msg.text)
def test_ivr_recording(self): # create our ivr setup self.org.connect_twilio("TEST_SID", "TEST_TOKEN", self.admin) self.org.save() self.import_file("capture_recording") flow = Flow.objects.filter(name="Capture Recording").first() # start our flow contact = self.create_contact("Chuck D", number="+13603621737") flow.start([], [contact]) call = IVRCall.objects.filter(direction=OUTGOING).first() # 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>Please make a recording after the tone.</Say>") # simulate the caller making a recording and then hanging up, first they'll give us the # recording (they give us a call status of completed at the same time) from temba.tests import MockResponse with patch("requests.get") as response: mock1 = MockResponse(404, "No such file") mock2 = MockResponse(200, "Fake Recording Bits") mock2.add_header("Content-Type", "audio/x-wav") response.side_effect = (mock1, mock2) self.client.post( reverse("ivr.ivrcall_handle", args=[call.pk]), dict( CallStatus="completed", Digits="hangup", RecordingUrl="http://api.twilio.com/ASID/Recordings/SID", RecordingSid="FAKESID", ), ) # we should have captured the recording, and ended the call call = IVRCall.objects.get(pk=call.pk) self.assertEquals(COMPLETED, call.status) # twilio will also send us a final completion message with the call duration (status of completed again) self.client.post(reverse("ivr.ivrcall_handle", args=[call.pk]), dict(CallStatus="completed", CallDuration="15")) call = IVRCall.objects.get(pk=call.pk) self.assertEquals(COMPLETED, call.status) self.assertEquals(15, call.duration) messages = Msg.all_messages.filter(msg_type=IVR).order_by("pk") self.assertEquals(4, messages.count()) self.assertEquals(4, self.org.get_credits_used()) # we should have played a recording from the contact back to them outbound_msg = messages[1] self.assertTrue(outbound_msg.media.startswith("audio/x-wav:https://")) self.assertTrue(outbound_msg.media.endswith(".wav")) self.assertTrue(outbound_msg.text.startswith("https://")) self.assertTrue(outbound_msg.text.endswith(".wav")) media_msg = messages[2] self.assertTrue(media_msg.media.startswith("audio/x-wav:https://")) self.assertTrue(media_msg.media.endswith(".wav")) self.assertTrue(media_msg.text.startswith("https://")) self.assertTrue(media_msg.text.endswith(".wav")) (host, directory, filename) = media_msg.media.rsplit("/", 2) recording = "%s/%s/%s/media/%s/%s" % ( settings.MEDIA_ROOT, settings.STORAGE_ROOT_DIR, self.org.pk, directory, filename, ) self.assertTrue(os.path.isfile(recording)) from temba.flows.models import FlowStep steps = FlowStep.objects.all() self.assertEquals(4, steps.count()) # each of our steps should have exactly one message for step in steps: self.assertEquals(1, step.messages.all().count(), msg="Step '%s' does not have excatly one message" % step) # each message should have exactly one step for msg in messages: self.assertEquals( 1, msg.steps.all().count(), msg="Message '%s' is not attached to exaclty one step" % msg.text )