diff --git a/sdk/communication/azure-communication-messages/CHANGELOG.md b/sdk/communication/azure-communication-messages/CHANGELOG.md index f7283cd41edf..8762127e8ccc 100644 --- a/sdk/communication/azure-communication-messages/CHANGELOG.md +++ b/sdk/communication/azure-communication-messages/CHANGELOG.md @@ -1,6 +1,6 @@ # Release History -## 1.0.0 (2024-02-01) +## 1.0.0 (2024-03-25) This is the GA release of Azure Communication Messages Python SDK. For more information, please see the [README][read_me]. diff --git a/sdk/communication/azure-communication-messages/assets.json b/sdk/communication/azure-communication-messages/assets.json index 29fbe8eb70f6..770b23e9293d 100644 --- a/sdk/communication/azure-communication-messages/assets.json +++ b/sdk/communication/azure-communication-messages/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "python", "TagPrefix": "python/communication/azure-communication-messages", - "Tag": "python/communication/azure-communication-messages_1c6b0f13ac" + "Tag": "python/communication/azure-communication-messages_22ab5a97f3" } diff --git a/sdk/communication/azure-communication-messages/dev_requirements.txt b/sdk/communication/azure-communication-messages/dev_requirements.txt index 9222a2a6b95b..3f40ebef83f7 100644 --- a/sdk/communication/azure-communication-messages/dev_requirements.txt +++ b/sdk/communication/azure-communication-messages/dev_requirements.txt @@ -2,7 +2,7 @@ -e ../../../tools/azure-sdk-tools ../../core/azure-core ../../identity/azure-identity -aiohttp +aiohttp>=3.0 aiounittest>=1.4 pytest-tornasync==0.6.0.post2 retry>=0.9.2 \ No newline at end of file diff --git a/sdk/communication/azure-communication-messages/tests/_decorators.py b/sdk/communication/azure-communication-messages/tests/_decorators.py new file mode 100644 index 000000000000..aadf9f57f154 --- /dev/null +++ b/sdk/communication/azure-communication-messages/tests/_decorators.py @@ -0,0 +1,30 @@ +# ------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for +# license information. +# -------------------------------------------------------------------------- + +import os +from typing import Callable, Any + +from devtools_testutils import is_live, is_live_and_not_recording, trim_kwargs_from_test_function +from azure.communication.messages._shared.utils import parse_connection_str + +class MessagesPreparers(object): + + @staticmethod + def messages_test_decorator(func: Callable[[], object], **kwargs: Any): + def wrapper(self, *args, **kwargs): + if is_live() or is_live_and_not_recording(): + self.connection_string = os.getenv("COMMUNICATION_LIVETEST_DYNAMIC_CONNECTION_STRING") + endpoint, _ = parse_connection_str(self.connection_string) + self.resource_name = endpoint.split(".")[0] + + else: + self.connection_string = "endpoint=https://sanitized.unitedstates.communication.azure.com/;accesskey=fake===" + self.resource_name = "sanitized" + + func(self, *args, **kwargs) + + return wrapper + diff --git a/sdk/communication/azure-communication-messages/tests/_messages_test_case.py b/sdk/communication/azure-communication-messages/tests/_messages_test_case.py new file mode 100644 index 000000000000..dfcaa01dc616 --- /dev/null +++ b/sdk/communication/azure-communication-messages/tests/_messages_test_case.py @@ -0,0 +1,35 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +from abc import abstractmethod +from retry import retry +import warnings +from _shared.utils import get_http_logging_policy +from azure.communication.messages import ( + NotificationMessagesClient, + MessageTemplateClient, +) +from devtools_testutils import AzureRecordedTestCase + +class MessagesRecordedTestCase(AzureRecordedTestCase): + + def create_notification_message_client(self) -> NotificationMessagesClient: + return NotificationMessagesClient.from_connection_string( + conn_str=self.connection_string, http_logging_policy=get_http_logging_policy() + ) + + def create_notification_message_client_from_token(self) -> NotificationMessagesClient: + return NotificationMessagesClient.from_token_credentials( + endpoint=self.endpoint_str, http_logging_policy=get_http_logging_policy() + ) + + def create_message_template_client(self) -> MessageTemplateClient: + return MessageTemplateClient.from_connection_string( + conn_str=self.connection_string, http_logging_policy=get_http_logging_policy() + ) + + def create_message_template_client_from_token(self) -> MessageTemplateClient: + return MessageTemplateClient.from_token_credentials( + endpoint=self.endpoint_str, http_logging_policy=get_http_logging_policy() + ) \ No newline at end of file diff --git a/sdk/communication/azure-communication-messages/tests/conftest.py b/sdk/communication/azure-communication-messages/tests/conftest.py index 57c030fe834b..e3524c0d8e35 100644 --- a/sdk/communication/azure-communication-messages/tests/conftest.py +++ b/sdk/communication/azure-communication-messages/tests/conftest.py @@ -52,7 +52,8 @@ def start_proxy(test_proxy): add_general_string_sanitizer(target=resource_name, value="sanitized") add_general_regex_sanitizer(regex=connection_str, value=FAKE_CONNECTION_STRING) add_general_regex_sanitizer(regex=endpoint, value=FAKE_ENDPOINT) - + + add_general_string_sanitizer(target="8f8c29b2-c2e4-4340-bb28-3009c8a57283", value="sanitized") add_body_key_sanitizer(json_path="channel_registration_id", value="sanitized") add_body_key_sanitizer(json_path="*.channel_registration_id", value="sanitized") add_body_key_sanitizer(json_path="*..channel_registration_id", value="sanitized") @@ -65,6 +66,9 @@ def start_proxy(test_proxy): add_body_key_sanitizer(json_path="media_uri", value="sanitized") add_body_key_sanitizer(json_path="*.media_uri", value="sanitized") add_body_key_sanitizer(json_path="*..media_uri", value="sanitized") + add_body_key_sanitizer(json_path="id", value="sanitized") + add_body_key_sanitizer(json_path="*.id", value="sanitized") + add_body_key_sanitizer(json_path="*..id", value="sanitized") add_body_key_sanitizer(json_path="repeatability-request-id", value="sanitized") add_body_key_sanitizer(json_path="*.repeatability-request-id", value="sanitized") add_body_key_sanitizer(json_path="*..repeatability-request-id", value="sanitized") diff --git a/sdk/communication/azure-communication-messages/tests/test_messages_client.py b/sdk/communication/azure-communication-messages/tests/test_messages_client.py new file mode 100644 index 000000000000..fdb7c6ef037b --- /dev/null +++ b/sdk/communication/azure-communication-messages/tests/test_messages_client.py @@ -0,0 +1,168 @@ +# ------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for +# license information. +# -------------------------------------------------------------------------- + +import os +from typing import List +from devtools_testutils import recorded_by_proxy +from _decorators import MessagesPreparers +from azure.core.credentials import AccessToken +from azure.communication.messages import NotificationMessagesClient +from azure.communication.messages.models import ( + TextNotificationContent, + ImageNotificationContent, + TemplateNotificationContent, + MessageReceipt, + MessageTemplate, + MessageTemplateText, + MessageTemplateBindings, + MessageTemplateValue, + WhatsAppMessageTemplateBindings, + WhatsAppMessageTemplateBindingsComponent + ) +from _shared.utils import get_http_logging_policy +from _messages_test_case import MessagesRecordedTestCase +from azure.communication.messages._shared.utils import parse_connection_str + +class TestNotificationMessageClientForText(MessagesRecordedTestCase): + + @MessagesPreparers.messages_test_decorator + @recorded_by_proxy + def test_text_send_message(self): + phone_number: str = "+14254360097" + raised = False + + text_options = TextNotificationContent( + channel_registration_id="b045be8c-45cd-492a-b2a2-47bae7c36959", + to= [phone_number], + content="Thanks for your feedback Hello.") + + message_response : MessageReceipt = None + message_client: NotificationMessagesClient = self.create_notification_message_client() + + try: + with message_client: + message_responses = message_client.send(text_options) + message_response = message_responses.receipts[0] + except: + raised = True + raise + assert raised is False + assert message_response.message_id is not None + assert message_response.to is not None + + + @MessagesPreparers.messages_test_decorator + @recorded_by_proxy + def test_template_send_message(self): + phone_number: str = "+14254360097" + input_template: MessageTemplate = MessageTemplate( + name="gathering_invitation", + language="ca") + raised = False + + message_client: NotificationMessagesClient = self.create_notification_message_client() + + template_options = TemplateNotificationContent( + channel_registration_id="b045be8c-45cd-492a-b2a2-47bae7c36959", + to=[phone_number], + template=input_template) + + message_response : MessageReceipt = None + + try: + with message_client: + message_responses = message_client.send(template_options) + message_response = message_responses.receipts[0] + except: + raised = True + raise + assert raised is False + assert message_response.message_id is not None + assert message_response.to is not None + + + @MessagesPreparers.messages_test_decorator + @recorded_by_proxy + def test_template_with_parameters_send_message(self): + + phone_number: str = "+14254360097" + parammeter1 = MessageTemplateText ( + name="first", + text="11-18-2024" + ) + + input_template: MessageTemplate = MessageTemplate( + name="gathering_invitation", + language="en_US", + template_values= [parammeter1], + bindings=WhatsAppMessageTemplateBindings + ( + body= [ WhatsAppMessageTemplateBindingsComponent(ref_value="first")] + ) + ) + raised = False + + template_options = TemplateNotificationContent( + channel_registration_id="b045be8c-45cd-492a-b2a2-47bae7c36959", + to=[phone_number], + template=input_template) + + message_response : MessageReceipt = None + message_client: NotificationMessagesClient = self.create_notification_message_client() + + try: + with message_client: + message_responses = message_client.send(template_options) + message_response = message_responses.receipts[0] + except: + raised = True + raise + assert raised is False + assert message_response.message_id is not None + assert message_response.to is not None + + @MessagesPreparers.messages_test_decorator + @recorded_by_proxy + def test_image_send_message(self): + phone_number: str = "+14254360097" + input_media_uri: str = "https://aka.ms/acsicon1" + raised = False + + template_options = ImageNotificationContent( + channel_registration_id="b045be8c-45cd-492a-b2a2-47bae7c36959", + to=[phone_number], + media_uri=input_media_uri) + + message_response : MessageReceipt = None + message_client: NotificationMessagesClient = self.create_notification_message_client() + + try: + with message_client: + message_responses = message_client.send(template_options) + message_response = message_responses.receipts[0] + except: + raised = True + raise + assert raised is False + assert message_response.message_id is not None + assert message_response.to is not None + + + @MessagesPreparers.messages_test_decorator + @recorded_by_proxy + def test_download_media(self): + phone_number: str = "+14254360097" + input_media_id: str = "8f8c29b2-c2e4-4340-bb28-3009c8a57283" + raised = False + message_client: NotificationMessagesClient = self.create_notification_message_client() + try: + with message_client: + media_stream = message_client.download_media(input_media_id) + except: + raised = True + raise + assert raised is False + assert media_stream is not None \ No newline at end of file diff --git a/sdk/communication/azure-communication-messages/tests/test_messages_client_async.py b/sdk/communication/azure-communication-messages/tests/test_messages_client_async.py index 5fcc64ac816a..1db009a8ad2b 100644 --- a/sdk/communication/azure-communication-messages/tests/test_messages_client_async.py +++ b/sdk/communication/azure-communication-messages/tests/test_messages_client_async.py @@ -156,7 +156,7 @@ async def test_image_send_message_async(self): @recorded_by_proxy_async async def test_download_media_async(self): phone_number: str = "+14254360097" - input_media_id: str = "315a0b04-d80d-4573-bcf1-1ce33d3f19f0" + input_media_id: str = "8f8c29b2-c2e4-4340-bb28-3009c8a57283" raised = False message_client: NotificationMessagesClient = self.create_notification_message_client() try: diff --git a/sdk/communication/azure-communication-messages/tests/test_messages_template_client.py b/sdk/communication/azure-communication-messages/tests/test_messages_template_client.py new file mode 100644 index 000000000000..c4ebb00328e5 --- /dev/null +++ b/sdk/communication/azure-communication-messages/tests/test_messages_template_client.py @@ -0,0 +1,35 @@ +# ------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for +# license information. +# -------------------------------------------------------------------------- + +from devtools_testutils import recorded_by_proxy +from _decorators import MessagesPreparers +from azure.communication.messages.models import ( + MessageTemplateItem, + MessageTemplate + ) +from _shared.utils import get_http_logging_policy +from _messages_test_case import MessagesRecordedTestCase +from azure.communication.messages._shared.utils import parse_connection_str + +class TestMessageTemplateClientToGetTemplates(MessagesRecordedTestCase): + + @MessagesPreparers.messages_test_decorator + @recorded_by_proxy + def test_get_templates(self): + channel_id = "b045be8c-45cd-492a-b2a2-47bae7c36959" + raised = False + + message_template_client = self.create_message_template_client() + + try: + with message_template_client: + message_template_item_list = message_template_client.list_templates(channel_id) + except: + raised = True + raise + + assert raised is False + assert message_template_item_list is not None