Exemple #1
0
    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')
Exemple #2
0
    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)
Exemple #3
0
    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)
Exemple #4
0
    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")
Exemple #5
0
    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)
Exemple #6
0
    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)
Exemple #7
0
    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
            )