def test_ussd_trigger_flow(self): # start a session callback_url = reverse('handlers.vumi_handler', args=['receive', self.channel.uuid]) ussd_code = "*111#" data = dict(timestamp="2016-04-18 03:54:20.570618", message_id="123456", from_addr="+250788383383", content="None", transport_type='ussd', session_event="new", to_addr=ussd_code) response = self.client.post(callback_url, json.dumps(data), content_type="application/json") flow = self.get_flow('ussd_trigger_flow') self.assertEquals(0, flow.runs.all().count()) trigger, _ = Trigger.objects.get_or_create( channel=self.channel, keyword=ussd_code, flow=flow, created_by=self.user, modified_by=self.user, org=self.org, trigger_type=Trigger.TYPE_USSD_PULL) # now we added the trigger, let's reinitiate the session response = self.client.post(callback_url, json.dumps(data), content_type="application/json") msg = Msg.objects.all().first() self.assertEqual("Please enter a phone number", msg.text) from_addr = "+250788383383" data = dict(timestamp="2016-04-18 03:54:20.570618", message_id="123456", from_addr=from_addr, content="250788123123", to_addr="*113#", transport_type='ussd') response = self.client.post(callback_url, json.dumps(data), content_type="application/json") self.assertEqual(response.status_code, 200) msg = Msg.objects.all().order_by('-created_on').first() # We should get the final message self.assertEqual("Thank you", msg.text) # Check the new contact was created new_contact = Contact.from_urn(self.org, "tel:+250788123123") self.assertIsNotNone(new_contact)
def clean(self): country = self.org.get_country_code() # validate URN fields for field_key, value in self.cleaned_data.iteritems(): if field_key.startswith('__urn__') and value: scheme = field_key[7:field_key.rfind('__')] norm_scheme, norm_path = ContactURN.normalize_urn(scheme, value, country) existing = Contact.from_urn(self.org, norm_scheme, norm_path) if existing and existing != self.instance: self._errors[field_key] = _("Used by another contact") elif not ContactURN.validate_urn(norm_scheme, norm_path): self._errors[field_key] = _("Invalid format") return self.cleaned_data
def validate_urns(self, value): org = self.context['org'] # this field isn't allowed if we are looking up by URN in the URL if 'urns__urn' in self.context['lookup_values']: raise serializers.ValidationError("Field not allowed when using URN in URL") # or for updates by anonymous organizations (we do allow creation of contacts with URNs) if org.is_anon and self.instance: raise serializers.ValidationError("Updating URNs not allowed for anonymous organizations") # if creating a contact, URNs can't belong to other contacts if not self.instance: for urn in value: if Contact.from_urn(org, urn): raise serializers.ValidationError("URN belongs to another contact: %s" % urn) return value
def clean(self): channel = self.org.get_receive_channel(TEL_SCHEME) country = channel.country if channel else None # validate URN fields for field_key, value in self.cleaned_data.iteritems(): if field_key.startswith('__urn__') and value: scheme = field_key[7:] norm_scheme, norm_path = ContactURN.normalize_urn(scheme, value, country) existing = Contact.from_urn(self.org, norm_scheme, norm_path) if existing and existing != self.instance: self._errors[field_key] = _("Used by another contact") elif not ContactURN.validate_urn(norm_scheme, norm_path): self._errors[field_key] = _("Invalid format") return self.cleaned_data
def validate_urns(self, value): org = self.context['org'] # this field isn't allowed if we are looking up by URN in the URL if 'urns__urn' in self.context['lookup_values']: raise serializers.ValidationError("Field not allowed when using URN in URL") # or for updates by anonymous organizations (we do allow creation of contacts with URNs) if org.is_anon and self.instance: raise serializers.ValidationError("Updating URNs not allowed for anonymous organizations") # if creating a contact, URNs can't belong to other contacts if not self.instance: for urn in value: if Contact.from_urn(org, urn): raise serializers.ValidationError("URN belongs to another contact: %s" % urn) return value
def clean(self): channel = self.org.get_receive_channel(TEL_SCHEME) country = channel.country if channel else None # validate URN fields for field_key, value in self.cleaned_data.iteritems(): if field_key.startswith('__urn__') and value: scheme = field_key[7:] norm_scheme, norm_path = ContactURN.normalize_urn(scheme, value, country) existing = Contact.from_urn(self.org, norm_scheme, norm_path) if existing and existing != self.instance: self._errors[field_key] = _("Used by another contact") elif not ContactURN.validate_urn(norm_scheme, norm_path): self._errors[field_key] = _("Invalid format") return self.cleaned_data
def validate(self, data): org = self.context['org'] # we don't allow updating of contact URNs for anon orgs - tho we do allow creation of contacts with URNs if org.is_anon and self.instance and data.get('urns'): raise serializers.ValidationError("Updating contact URNs not allowed for anonymous organizations") # if creating a contact, urns can't include URNs which are already taken if not self.instance and 'urns' in data: country_code = org.get_country_code() for urn in data['urns']: if Contact.from_urn(org, urn, country_code): raise serializers.ValidationError("Contact URN belongs to another contact: %s" % urn) # if contact is blocked, they can't be added to groups if self.instance and (self.instance.is_blocked or self.instance.is_stopped) and data['groups']: raise serializers.ValidationError("Blocked or stopped contacts can't be added to groups") return data
def validate(self, data): org = self.context['org'] # we don't allow updating of contact URNs for anon orgs - tho we do allow creation of contacts with URNs if org.is_anon and self.instance and data.get('urns'): raise serializers.ValidationError("Updating contact URNs not allowed for anonymous organizations") # if creating a contact, urns can't include URNs which are already taken if not self.instance and 'urns' in data: country_code = org.get_country_code() for urn in data['urns']: if Contact.from_urn(org, urn, country_code): raise serializers.ValidationError("Contact URN belongs to another contact: %s" % urn) # if contact is blocked, they can't be added to groups if self.instance and (self.instance.is_blocked or self.instance.is_stopped) and data['groups']: raise serializers.ValidationError("Blocked or stopped contacts can't be added to groups") return data
def test_new_conversation_trigger(self): self.login(self.admin) flow = self.create_flow() flow2 = self.create_flow() # see if we list new conversation triggers on the trigger page create_trigger_url = reverse('triggers.trigger_create', args=[]) response = self.client.get(create_trigger_url) self.assertNotContains(response, "conversation is started") # create a facebook channel fb_channel = Channel.add_facebook_channel(self.org, self.user, 'Temba', 1001, 'fb_token') # should now be able to create one response = self.client.get(create_trigger_url) self.assertContains(response, "conversation is started") # go create it with patch('requests.post') as mock_post: mock_post.return_value = MockResponse(200, '{"message": "Success"}') response = self.client.post(reverse('triggers.trigger_new_conversation', args=[]), data=dict(channel=fb_channel.id, flow=flow.id)) self.assertEqual(response.status_code, 200) self.assertEqual(mock_post.call_count, 1) # check that it is right trigger = Trigger.objects.get(trigger_type=Trigger.TYPE_NEW_CONVERSATION, is_active=True, is_archived=False) self.assertEqual(trigger.channel, fb_channel) self.assertEqual(trigger.flow, flow) # try to create another one, fails as we already have a trigger for that channel response = self.client.post(reverse('triggers.trigger_new_conversation', args=[]), data=dict(channel=fb_channel.id, flow=flow2.id)) self.assertEqual(response.status_code, 200) self.assertFormError(response, 'form', 'channel', 'Trigger with this Channel already exists.') # ok, trigger a facebook event data = json.loads("""{ "object": "page", "entry": [ { "id": "620308107999975", "time": 1467841778778, "messaging": [ { "sender":{ "id":"1001" }, "recipient":{ "id":"%s" }, "timestamp":1458692752478, "postback":{ "payload":"get_started" } } ] } ] } """ % fb_channel.address) with patch('requests.get') as mock_get: mock_get.return_value = MockResponse(200, '{"first_name": "Ben","last_name": "Haggerty"}') callback_url = reverse('handlers.facebook_handler', args=[fb_channel.uuid]) response = self.client.post(callback_url, json.dumps(data), content_type="application/json") self.assertEqual(response.status_code, 200) # should have a new flow run for Ben contact = Contact.from_urn(self.org, 'facebook:1001') self.assertTrue(contact.name, "Ben Haggerty") run = FlowRun.objects.get(contact=contact) self.assertEqual(run.flow, flow) # archive our trigger, should unregister our callback with patch('requests.post') as mock_post: mock_post.return_value = MockResponse(200, '{"message": "Success"}') Trigger.apply_action_archive(self.admin, Trigger.objects.filter(pk=trigger.pk)) self.assertEqual(response.status_code, 200) self.assertEqual(mock_post.call_count, 1) trigger.refresh_from_db() self.assertTrue(trigger.is_archived)
def validate_urn(self, value): if self.context['org'].is_anon: raise serializers.ValidationError("Referencing by URN not allowed for anonymous organizations") self.instance = Contact.from_urn(self.context['org'], value) return value
def test_new_conversation_trigger(self): self.login(self.admin) flow = self.create_flow() flow2 = self.create_flow() # see if we list new conversation triggers on the trigger page create_trigger_url = reverse('triggers.trigger_create', args=[]) response = self.client.get(create_trigger_url) self.assertNotContains(response, "conversation is started") # create a facebook channel fb_channel = Channel.add_facebook_channel(self.org, self.user, 'Temba', 1001, 'fb_token') # should now be able to create one response = self.client.get(create_trigger_url) self.assertContains(response, "conversation is started") # go create it with patch('requests.post') as mock_post: mock_post.return_value = MockResponse(200, '{"message": "Success"}') response = self.client.post(reverse('triggers.trigger_new_conversation', args=[]), data=dict(channel=fb_channel.id, flow=flow.id)) self.assertEqual(response.status_code, 200) self.assertEqual(mock_post.call_count, 1) # check that it is right trigger = Trigger.objects.get(trigger_type=Trigger.TYPE_NEW_CONVERSATION, is_active=True, is_archived=False) self.assertEqual(trigger.channel, fb_channel) self.assertEqual(trigger.flow, flow) # try to create another one, fails as we already have a trigger for that channel response = self.client.post(reverse('triggers.trigger_new_conversation', args=[]), data=dict(channel=fb_channel.id, flow=flow2.id)) self.assertEqual(response.status_code, 200) self.assertFormError(response, 'form', 'channel', 'Trigger with this Channel already exists.') # ok, trigger a facebook event data = json.loads("""{ "object": "page", "entry": [ { "id": "620308107999975", "time": 1467841778778, "messaging": [ { "sender":{ "id":"1001" }, "recipient":{ "id":"%s" }, "timestamp":1458692752478, "postback":{ "payload":"get_started" } } ] } ] } """ % fb_channel.address) with patch('requests.get') as mock_get: mock_get.return_value = MockResponse(200, '{"first_name": "Ben","last_name": "Haggerty"}') callback_url = reverse('handlers.facebook_handler', args=[fb_channel.uuid]) response = self.client.post(callback_url, json.dumps(data), content_type="application/json") self.assertEqual(response.status_code, 200) # should have a new flow run for Ben contact = Contact.from_urn(self.org, 'facebook:1001') self.assertTrue(contact.name, "Ben Haggerty") run = FlowRun.objects.get(contact=contact) self.assertEqual(run.flow, flow) # archive our trigger, should unregister our callback with patch('requests.post') as mock_post: mock_post.return_value = MockResponse(200, '{"message": "Success"}') Trigger.apply_action_archive(self.admin, Trigger.objects.filter(pk=trigger.pk)) self.assertEqual(response.status_code, 200) self.assertEqual(mock_post.call_count, 1) trigger.refresh_from_db() self.assertTrue(trigger.is_archived)
def validate_urn(self, value): if self.context['org'].is_anon: raise serializers.ValidationError("Referencing by URN not allowed for anonymous organizations") self.instance = Contact.from_urn(self.context['org'], value) return value