Exemplo n.º 1
0
    def test_refresh_templates_task(self, mock_get_api_templates,
                                    update_local_templates_mock, mock_health):
        TemplateTranslation.objects.all().delete()
        Channel.objects.all().delete()

        channel = self.create_channel(
            "D3",
            "360Dialog channel",
            address="1234",
            country="BR",
            config={
                Channel.CONFIG_BASE_URL: "https://example.com/whatsapp",
                Channel.CONFIG_AUTH_TOKEN: "123456789",
            },
        )

        self.login(self.admin)
        mock_get_api_templates.side_effect = [([], False),
                                              Exception("foo"),
                                              ([{
                                                  "name": "hello"
                                              }], True)]

        update_local_templates_mock.return_value = None

        mock_health.return_value = MockResponse(
            200, '{"meta": {"api_status": "stable", "version": "2.35.4"}}')

        # should skip if locked
        r = get_redis_connection()
        with r.lock("refresh_whatsapp_templates", timeout=1800):
            refresh_whatsapp_templates()
            self.assertEqual(0, mock_get_api_templates.call_count)
            self.assertEqual(0, update_local_templates_mock.call_count)

        # should skip if fail with API
        refresh_whatsapp_templates()

        mock_get_api_templates.assert_called_with(channel)
        self.assertEqual(1, mock_get_api_templates.call_count)
        self.assertEqual(0, update_local_templates_mock.call_count)

        # any exception
        refresh_whatsapp_templates()

        mock_get_api_templates.assert_called_with(channel)
        self.assertEqual(2, mock_get_api_templates.call_count)
        self.assertEqual(0, update_local_templates_mock.call_count)

        # now it should refresh
        refresh_whatsapp_templates()

        mock_get_api_templates.assert_called_with(channel)
        self.assertEqual(3, mock_get_api_templates.call_count)
        update_local_templates_mock.assert_called_once_with(
            channel, [{
                "name": "hello"
            }])
Exemplo n.º 2
0
    def test_refresh_templates_task(self, mock_get_api_templates,
                                    update_local_templates_mock):
        TemplateTranslation.objects.all().delete()
        Channel.objects.all().delete()

        # channel has namespace in the channel config
        channel = self.create_channel("WA",
                                      "Channel",
                                      "1234",
                                      config={"fb_namespace": "foo_namespace"})

        self.login(self.admin)
        mock_get_api_templates.side_effect = [([], False),
                                              Exception("foo"),
                                              ([{
                                                  "name": "hello"
                                              }], True)]

        update_local_templates_mock.return_value = None

        # should skip if locked
        r = get_redis_connection()
        with r.lock("refresh_whatsapp_templates", timeout=1800):
            refresh_whatsapp_templates()
            self.assertEqual(0, mock_get_api_templates.call_count)
            self.assertEqual(0, update_local_templates_mock.call_count)

        # should skip if fail with API
        refresh_whatsapp_templates()

        mock_get_api_templates.assert_called_with(channel)
        self.assertEqual(1, mock_get_api_templates.call_count)
        self.assertEqual(0, update_local_templates_mock.call_count)

        # any exception
        refresh_whatsapp_templates()

        mock_get_api_templates.assert_called_with(channel)
        self.assertEqual(2, mock_get_api_templates.call_count)
        self.assertEqual(0, update_local_templates_mock.call_count)

        # now it should refresh
        refresh_whatsapp_templates()

        mock_get_api_templates.assert_called_with(channel)
        self.assertEqual(3, mock_get_api_templates.call_count)
        update_local_templates_mock.assert_called_once_with(
            channel, [{
                "name": "hello"
            }])
Exemplo n.º 3
0
    def test_refresh_templates_task(self, mock_get_api_templates, update_local_templates_mock, mock_health):
        TemplateTranslation.objects.all().delete()
        Channel.objects.all().delete()

        # channel has namespace in the channel config
        channel = self.create_channel("WA", "Channel", "1234", config={"fb_namespace": "foo_namespace"})

        self.login(self.admin)
        mock_get_api_templates.side_effect = [
            ([], False),
            Exception("foo"),
            ([{"name": "hello"}], True),
            ([{"name": "hello"}], True),
        ]
        mock_health.return_value = {"meta": {"api_status": "stable", "version": "v2.35.2"}}
        update_local_templates_mock.return_value = None

        # should skip if locked
        r = get_redis_connection()
        with r.lock("refresh_whatsapp_templates", timeout=1800):
            refresh_whatsapp_templates()
            self.assertEqual(0, mock_get_api_templates.call_count)
            self.assertEqual(0, update_local_templates_mock.call_count)

        # should skip if fail with API
        refresh_whatsapp_templates()

        mock_get_api_templates.assert_called_with(channel)
        self.assertEqual(1, mock_get_api_templates.call_count)
        self.assertEqual(0, update_local_templates_mock.call_count)
        self.assertFalse(mock_health.called)

        # any exception
        refresh_whatsapp_templates()

        mock_get_api_templates.assert_called_with(channel)
        self.assertEqual(2, mock_get_api_templates.call_count)
        self.assertEqual(0, update_local_templates_mock.call_count)
        self.assertFalse(mock_health.called)

        # now it should refresh
        refresh_whatsapp_templates()

        mock_get_api_templates.assert_called_with(channel)
        self.assertEqual(3, mock_get_api_templates.call_count)
        update_local_templates_mock.assert_called_once_with(channel, [{"name": "hello"}])
        self.assertFalse(mock_health.called)

        channel.config.update(version="v1.0.0")
        channel.save()

        channel.refresh_from_db()

        # now it should refresh
        refresh_whatsapp_templates()

        mock_get_api_templates.assert_called_with(channel)
        self.assertEqual(4, mock_get_api_templates.call_count)
        self.assertTrue(mock_health.called)

        channel.refresh_from_db()

        self.assertEqual("v2.35.2", channel.config.get("version"))
Exemplo n.º 4
0
    def test_claim(self, mock_health):
        mock_health.return_value = {"meta": {"api_status": "stable", "version": "v2.35.2"}}
        TemplateTranslation.objects.all().delete()
        Channel.objects.all().delete()

        url = reverse("channels.types.whatsapp.claim")
        self.login(self.admin)

        response = self.client.get(reverse("channels.channel_claim"))
        self.assertNotContains(response, url)

        response = self.client.get(url)
        self.assertEqual(200, response.status_code)
        post_data = response.context["form"].initial

        post_data["number"] = "1234"
        post_data["username"] = "******"
        post_data["password"] = "******"
        post_data["country"] = "RW"
        post_data["base_url"] = "https://nyaruka.com/whatsapp"
        post_data["facebook_namespace"] = "my-custom-app"
        post_data["facebook_business_id"] = "1234"
        post_data["facebook_access_token"] = "token123"
        post_data["facebook_template_list_domain"] = "graph.facebook.com"

        # will fail with invalid phone number
        response = self.client.post(url, post_data)
        self.assertFormError(response, "form", None, ["Please enter a valid phone number"])

        # valid number
        post_data["number"] = "0788123123"

        # try once with an error
        with patch("requests.post") as mock_post:
            mock_post.return_value = MockResponse(400, '{ "error": "true" }')
            response = self.client.post(url, post_data)
            self.assertEqual(200, response.status_code)
            self.assertFalse(Channel.objects.all())

            self.assertContains(response, "check username and password")

        # Uncomment this when we activate back the checking of Facebook templates
        # # then FB failure
        # with patch("requests.post") as mock_post:
        #     with patch("requests.get") as mock_get:
        #         mock_post.return_value = MockResponse(200, '{"users": [{"token": "abc123"}]}')
        #         mock_get.return_value = MockResponse(400, '{"data": []}')
        #
        #         response = self.client.post(url, post_data)
        #         self.assertEqual(200, response.status_code)
        #         self.assertFalse(Channel.objects.all())
        #         mock_get.assert_called_with(
        #             "https://graph.facebook.com/v3.3/1234/message_templates", params={"access_token": "token123"}
        #         )
        #
        #         self.assertContains(response, "check user id and access token")

        # then success
        with patch("requests.post") as mock_post, patch("requests.get") as mock_get, patch(
            "requests.patch"
        ) as mock_patch:
            mock_post.return_value = MockResponse(200, '{"users": [{"token": "abc123"}]}')
            mock_get.return_value = MockResponse(200, '{"data": []}')
            mock_patch.return_value = MockResponse(200, '{"data": []}')

            response = self.client.post(url, post_data)
            self.assertEqual(302, response.status_code)

        channel = Channel.objects.get()

        self.assertEqual("graph.facebook.com", channel.config[CONFIG_FB_TEMPLATE_LIST_DOMAIN])
        self.assertEqual("temba", channel.config[Channel.CONFIG_USERNAME])
        self.assertEqual("tembapasswd", channel.config[Channel.CONFIG_PASSWORD])
        self.assertEqual("abc123", channel.config[Channel.CONFIG_AUTH_TOKEN])
        self.assertEqual("https://nyaruka.com/whatsapp", channel.config[Channel.CONFIG_BASE_URL])

        self.assertEqual("+250788123123", channel.address)
        self.assertEqual("RW", channel.country)
        self.assertEqual("WA", channel.channel_type)
        self.assertEqual(45, channel.tps)
        self.assertTrue(channel.get_type().has_attachment_support(channel))

        # test activating the channel
        with patch("requests.patch") as mock_patch:
            mock_patch.side_effect = [MockResponse(200, '{ "error": false }'), MockResponse(200, '{ "error": false }')]
            WhatsAppType().activate(channel)
            self.assertEqual(
                mock_patch.call_args_list[0][1]["json"]["webhooks"]["url"],
                "https://%s%s"
                % (channel.org.get_brand_domain(), reverse("courier.wa", args=[channel.uuid, "receive"])),
            )
            self.assertEqual(
                mock_patch.call_args_list[1][1]["json"]["messaging_api_rate_limit"], ["15", "54600", "1000000"]
            )

        with patch("requests.patch") as mock_patch:
            mock_patch.side_effect = [MockResponse(400, '{ "error": true }')]

            try:
                WhatsAppType().activate(channel)
                self.fail("Should have thrown error activating channel")
            except ValidationError:
                pass

        with patch("requests.patch") as mock_patch:
            mock_patch.side_effect = [
                MockResponse(200, '{ "error": "false" }'),
                MockResponse(400, '{ "error": "true" }'),
            ]

            try:
                WhatsAppType().activate(channel)
                self.fail("Should have thrown error activating channel")
            except ValidationError:
                pass

        # ok, test our refreshing
        refresh_url = reverse("channels.types.whatsapp.refresh", args=[channel.uuid])
        resp = self.client.get(refresh_url)
        self.assertEqual(405, resp.status_code)

        with patch("requests.post") as mock_post:
            mock_post.side_effect = [MockResponse(200, '{ "error": false }')]
            self.assertFalse(channel.http_logs.filter(log_type=HTTPLog.WHATSAPP_CONTACTS_REFRESHED, is_error=False))
            self.create_contact("Joe", urns=["whatsapp:250788382382"])
            self.client.post(refresh_url)

            self.assertEqual(mock_post.call_args_list[0][1]["json"]["contacts"], ["+250788382382"])
            self.assertTrue(channel.http_logs.filter(log_type=HTTPLog.WHATSAPP_CONTACTS_REFRESHED, is_error=False))

        with patch("requests.post") as mock_post:
            mock_post.side_effect = [MockResponse(400, '{ "error": true }')]
            self.assertFalse(channel.http_logs.filter(log_type=HTTPLog.WHATSAPP_CONTACTS_REFRESHED, is_error=True))
            refresh_whatsapp_contacts(channel.id)
            self.assertTrue(channel.http_logs.filter(log_type=HTTPLog.WHATSAPP_CONTACTS_REFRESHED, is_error=True))

        # clear our FB ids, should cause refresh to be noop (but not fail)
        del channel.config[CONFIG_FB_BUSINESS_ID]
        channel.save(update_fields=["config", "modified_on"])
        refresh_whatsapp_templates()

        # deactivate our channel
        channel.release(self.admin)