From 847df229716ae4044eddc27ed0997fa5c9ba6de1 Mon Sep 17 00:00:00 2001 From: maxkahan Date: Wed, 10 Apr 2024 02:49:46 +0100 Subject: [PATCH] test message models --- messages/src/vonage_messages/__init__.py | 37 +- messages/src/vonage_messages/errors.py | 5 - messages/src/vonage_messages/messages.py | 4 +- messages/src/vonage_messages/models/BUILD | 2 +- .../src/vonage_messages/models/__init__.py | 2 +- .../models/{message.py => base_message.py} | 0 .../src/vonage_messages/models/messenger.py | 12 +- messages/src/vonage_messages/models/mms.py | 2 +- messages/src/vonage_messages/models/sms.py | 2 +- messages/src/vonage_messages/models/viber.py | 4 +- .../src/vonage_messages/models/whatsapp.py | 28 +- messages/tests/BUILD | 4 + .../{test_verify_v2.py => _test_verify_v2.py} | 0 messages/tests/test_messenger_models.py | 224 ++++++++++ messages/tests/test_mms_models.py | 210 ++++++++++ messages/tests/test_models.py | 14 - messages/tests/test_sms_models.py | 54 +++ messages/tests/test_viber_models.py | 243 +++++++++++ messages/tests/test_whatsapp_models.py | 384 ++++++++++++++++++ pants.toml | 3 + vonage/src/vonage/__init__.py | 2 + vonage/src/vonage/vonage.py | 2 + 22 files changed, 1165 insertions(+), 73 deletions(-) delete mode 100644 messages/src/vonage_messages/errors.py rename messages/src/vonage_messages/models/{message.py => base_message.py} (100%) rename messages/tests/{test_verify_v2.py => _test_verify_v2.py} (100%) create mode 100644 messages/tests/test_messenger_models.py create mode 100644 messages/tests/test_mms_models.py delete mode 100644 messages/tests/test_models.py create mode 100644 messages/tests/test_sms_models.py create mode 100644 messages/tests/test_viber_models.py create mode 100644 messages/tests/test_whatsapp_models.py diff --git a/messages/src/vonage_messages/__init__.py b/messages/src/vonage_messages/__init__.py index 06fbfd9e..e1aa8216 100644 --- a/messages/src/vonage_messages/__init__.py +++ b/messages/src/vonage_messages/__init__.py @@ -1,27 +1,12 @@ -# from .enums import ChannelType, Locale -# from .errors import VerifyError -# from .requests import ( -# EmailChannel, -# SilentAuthChannel, -# SmsChannel, -# VerifyRequest, -# VoiceChannel, -# WhatsappChannel, -# ) -# from .responses import CheckCodeResponse, StartVerificationResponse -# from .verify_v2 import VerifyV2 +from . import models +from .enums import ChannelType, EncodingType, MessageType, WebhookVersion +from .messages import Messages -# __all__ = [ -# 'VerifyV2', -# 'VerifyError', -# 'ChannelType', -# 'CheckCodeResponse', -# 'Locale', -# 'VerifyRequest', -# 'SilentAuthChannel', -# 'SmsChannel', -# 'WhatsappChannel', -# 'VoiceChannel', -# 'EmailChannel', -# 'StartVerificationResponse', -# ] +__all__ = [ + 'models', + 'Messages', + 'ChannelType', + 'MessageType', + 'WebhookVersion', + 'EncodingType', +] diff --git a/messages/src/vonage_messages/errors.py b/messages/src/vonage_messages/errors.py deleted file mode 100644 index e3506baa..00000000 --- a/messages/src/vonage_messages/errors.py +++ /dev/null @@ -1,5 +0,0 @@ -from vonage_utils.errors import VonageError - - -class MessagesError(VonageError): - """Indicates an error when using the Vonage Verify API.""" diff --git a/messages/src/vonage_messages/messages.py b/messages/src/vonage_messages/messages.py index 34b0d314..98ce25c0 100644 --- a/messages/src/vonage_messages/messages.py +++ b/messages/src/vonage_messages/messages.py @@ -1,7 +1,7 @@ from pydantic import validate_call from vonage_http_client.http_client import HttpClient -from .models.sms import BaseMessage +from .models import BaseMessage from .responses import MessageUuid @@ -22,7 +22,7 @@ def send(self, message: BaseMessage) -> MessageUuid: """Send a message using Vonage's Messages API. Args: - message (Message): The message to be sent. + message (BaseMessage): The message to be sent. Returns: MessageUuid: The unique identifier of the sent message. diff --git a/messages/src/vonage_messages/models/BUILD b/messages/src/vonage_messages/models/BUILD index db46e8d6..62f5decc 100644 --- a/messages/src/vonage_messages/models/BUILD +++ b/messages/src/vonage_messages/models/BUILD @@ -1 +1 @@ -python_sources() +python_sources(name='models') diff --git a/messages/src/vonage_messages/models/__init__.py b/messages/src/vonage_messages/models/__init__.py index b9f1eb21..75a192be 100644 --- a/messages/src/vonage_messages/models/__init__.py +++ b/messages/src/vonage_messages/models/__init__.py @@ -1,4 +1,4 @@ -from .message import BaseMessage +from .base_message import BaseMessage from .messenger import ( MessengerAudio, MessengerFile, diff --git a/messages/src/vonage_messages/models/message.py b/messages/src/vonage_messages/models/base_message.py similarity index 100% rename from messages/src/vonage_messages/models/message.py rename to messages/src/vonage_messages/models/base_message.py diff --git a/messages/src/vonage_messages/models/messenger.py b/messages/src/vonage_messages/models/messenger.py index 59d9e52b..465d1d3d 100644 --- a/messages/src/vonage_messages/models/messenger.py +++ b/messages/src/vonage_messages/models/messenger.py @@ -3,7 +3,7 @@ from pydantic import BaseModel, Field, model_validator from ..enums import ChannelType, MessageType -from .message import BaseMessage +from .base_message import BaseMessage class MessengerResource(BaseModel): @@ -30,24 +30,24 @@ class BaseMessenger(BaseMessage): class MessengerText(BaseMessenger): text: str = Field(..., max_length=640) - type: MessageType = MessageType.TEXT + message_type: MessageType = MessageType.TEXT class MessengerImage(BaseMessenger): image: MessengerResource - type: MessageType = MessageType.IMAGE + message_type: MessageType = MessageType.IMAGE class MessengerAudio(BaseMessenger): audio: MessengerResource - type: MessageType = MessageType.AUDIO + message_type: MessageType = MessageType.AUDIO class MessengerVideo(BaseMessenger): video: MessengerResource - type: MessageType = MessageType.VIDEO + message_type: MessageType = MessageType.VIDEO class MessengerFile(BaseMessenger): file: MessengerResource - type: MessageType = MessageType.FILE + message_type: MessageType = MessageType.FILE diff --git a/messages/src/vonage_messages/models/mms.py b/messages/src/vonage_messages/models/mms.py index 0f5709a7..b72c5ac8 100644 --- a/messages/src/vonage_messages/models/mms.py +++ b/messages/src/vonage_messages/models/mms.py @@ -4,7 +4,7 @@ from vonage_utils.types.phone_number import PhoneNumber from ..enums import ChannelType, MessageType -from .message import BaseMessage +from .base_message import BaseMessage class MmsResource(BaseModel): diff --git a/messages/src/vonage_messages/models/sms.py b/messages/src/vonage_messages/models/sms.py index b747b7ee..01bc453a 100644 --- a/messages/src/vonage_messages/models/sms.py +++ b/messages/src/vonage_messages/models/sms.py @@ -4,7 +4,7 @@ from vonage_utils.types.phone_number import PhoneNumber from ..enums import ChannelType, EncodingType, MessageType -from .message import BaseMessage +from .base_message import BaseMessage class SmsOptions(BaseModel): diff --git a/messages/src/vonage_messages/models/viber.py b/messages/src/vonage_messages/models/viber.py index 85199bed..49239bc5 100644 --- a/messages/src/vonage_messages/models/viber.py +++ b/messages/src/vonage_messages/models/viber.py @@ -3,7 +3,7 @@ from pydantic import BaseModel, Field, field_validator from ..enums import ChannelType, MessageType -from .message import BaseMessage +from .base_message import BaseMessage class ViberAction(BaseModel): @@ -77,7 +77,7 @@ def validate_file_size(cls, value): class ViberVideo(BaseViber): video: ViberVideoResource - viber_service: Optional[ViberVideoOptions] = None + viber_service: ViberVideoOptions message_type: MessageType = MessageType.VIDEO diff --git a/messages/src/vonage_messages/models/whatsapp.py b/messages/src/vonage_messages/models/whatsapp.py index 4e9cc153..b94dd75d 100644 --- a/messages/src/vonage_messages/models/whatsapp.py +++ b/messages/src/vonage_messages/models/whatsapp.py @@ -1,10 +1,10 @@ -from typing import Literal, Optional, Union +from typing import List, Literal, Optional, Union from pydantic import BaseModel, ConfigDict, Field from vonage_utils.types.phone_number import PhoneNumber from ..enums import ChannelType, MessageType -from .message import BaseMessage +from .base_message import BaseMessage class WhatsappContext(BaseModel): @@ -13,13 +13,13 @@ class WhatsappContext(BaseModel): class BaseWhatsapp(BaseMessage): from_: Union[PhoneNumber, str] = Field(..., serialization_alias='from') - context: WhatsappContext + context: Optional[WhatsappContext] = None channel: ChannelType = ChannelType.WHATSAPP class WhatsappText(BaseWhatsapp): text: str = Field(..., max_length=4096) - type: MessageType = MessageType.TEXT + message_type: MessageType = MessageType.TEXT class WhatsappImageResource(BaseModel): @@ -29,7 +29,7 @@ class WhatsappImageResource(BaseModel): class WhatsappImage(BaseWhatsapp): image: WhatsappImageResource - type: MessageType = MessageType.IMAGE + message_type: MessageType = MessageType.IMAGE class WhatsappAudioResource(BaseModel): @@ -38,7 +38,7 @@ class WhatsappAudioResource(BaseModel): class WhatsappAudio(BaseWhatsapp): audio: WhatsappAudioResource - type: MessageType = MessageType.AUDIO + message_type: MessageType = MessageType.AUDIO class WhatsappVideoResource(BaseModel): @@ -48,7 +48,7 @@ class WhatsappVideoResource(BaseModel): class WhatsappVideo(BaseWhatsapp): video: WhatsappVideoResource - type: MessageType = MessageType.VIDEO + message_type: MessageType = MessageType.VIDEO class WhatsappFileResource(BaseModel): @@ -59,25 +59,25 @@ class WhatsappFileResource(BaseModel): class WhatsappFile(BaseWhatsapp): file: WhatsappFileResource - type: MessageType = MessageType.FILE + message_type: MessageType = MessageType.FILE class WhatsappTemplateResource(BaseModel): name: str - parameters: Optional[list] = None + parameters: Optional[List[str]] = None model_config = ConfigDict(extra='allow') class WhatsappTemplateSettings(BaseModel): - locale: str = 'en_US' + locale: Optional[str] = 'en_US' policy: Optional[Literal['deterministic']] = None class WhatsappTemplate(BaseWhatsapp): template: WhatsappTemplateResource - whatsapp: WhatsappTemplateSettings - type: MessageType = MessageType.TEMPLATE + whatsapp: WhatsappTemplateSettings = WhatsappTemplateSettings() + message_type: MessageType = MessageType.TEMPLATE class WhatsappStickerUrl(BaseModel): @@ -90,9 +90,9 @@ class WhatsappStickerId(BaseModel): class WhatsappSticker(BaseWhatsapp): sticker: Union[WhatsappStickerUrl, WhatsappStickerId] - type: MessageType = MessageType.STICKER + message_type: MessageType = MessageType.STICKER class WhatsappCustom(BaseWhatsapp): custom: Optional[dict] = None - type: MessageType = MessageType.CUSTOM + message_type: MessageType = MessageType.CUSTOM diff --git a/messages/tests/BUILD b/messages/tests/BUILD index 72fce921..ea1c26ad 100644 --- a/messages/tests/BUILD +++ b/messages/tests/BUILD @@ -1 +1,5 @@ python_tests(dependencies=['messages', 'testutils']) + +python_sources( + name="tests0", +) diff --git a/messages/tests/test_verify_v2.py b/messages/tests/_test_verify_v2.py similarity index 100% rename from messages/tests/test_verify_v2.py rename to messages/tests/_test_verify_v2.py diff --git a/messages/tests/test_messenger_models.py b/messages/tests/test_messenger_models.py new file mode 100644 index 00000000..e3dc141d --- /dev/null +++ b/messages/tests/test_messenger_models.py @@ -0,0 +1,224 @@ +from pytest import raises +from vonage_messages.enums import WebhookVersion +from vonage_messages.models import ( + MessengerAudio, + MessengerFile, + MessengerImage, + MessengerOptions, + MessengerResource, + MessengerText, + MessengerVideo, +) + + +def test_messenger_options_validator(): + with raises(ValueError): + MessengerOptions(category='message_tag') + + +def test_create_messenger_text(): + messenger_model = MessengerText( + to='1234567890', from_='1234567890', text='Hello, World!' + ) + messenger_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'text': 'Hello, World!', + 'channel': 'messenger', + 'message_type': 'text', + } + + assert messenger_model.model_dump(by_alias=True, exclude_none=True) == messenger_dict + + +def test_create_messenger_text_all_fields(): + messenger_model = MessengerText( + to='1234567890', + from_='1234567890', + text='Hello, World!', + messenger=MessengerOptions(category='message_tag', tag='tag'), + client_ref='client-ref', + webhook_url='https://example.com', + webhook_version=WebhookVersion.V1, + ) + messenger_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'text': 'Hello, World!', + 'messenger': {'category': 'message_tag', 'tag': 'tag'}, + 'client_ref': 'client-ref', + 'webhook_url': 'https://example.com', + 'webhook_version': 'v1', + 'channel': 'messenger', + 'message_type': 'text', + } + + assert messenger_model.model_dump(by_alias=True) == messenger_dict + + +def test_create_messenger_image(): + messenger_model = MessengerImage( + to='1234567890', + from_='1234567890', + image=MessengerResource(url='https://example.com/image.jpg'), + ) + messenger_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'image': {'url': 'https://example.com/image.jpg'}, + 'channel': 'messenger', + 'message_type': 'image', + } + + assert messenger_model.model_dump(by_alias=True, exclude_none=True) == messenger_dict + + +def test_create_messenger_image_all_fields(): + messenger_model = MessengerImage( + to='1234567890', + from_='1234567890', + image=MessengerResource(url='https://example.com/image.jpg'), + messenger=MessengerOptions(category='message_tag', tag='tag'), + client_ref='client-ref', + webhook_url='https://example.com', + webhook_version=WebhookVersion.V1, + ) + messenger_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'image': {'url': 'https://example.com/image.jpg'}, + 'messenger': {'category': 'message_tag', 'tag': 'tag'}, + 'client_ref': 'client-ref', + 'webhook_url': 'https://example.com', + 'webhook_version': 'v1', + 'channel': 'messenger', + 'message_type': 'image', + } + + assert messenger_model.model_dump(by_alias=True) == messenger_dict + + +def test_create_messenger_audio(): + messenger_model = MessengerAudio( + to='1234567890', + from_='1234567890', + audio=MessengerResource(url='https://example.com/audio.mp3'), + ) + messenger_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'audio': {'url': 'https://example.com/audio.mp3'}, + 'channel': 'messenger', + 'message_type': 'audio', + } + + assert messenger_model.model_dump(by_alias=True, exclude_none=True) == messenger_dict + + +def test_create_messenger_audio_all_fields(): + messenger_model = MessengerAudio( + to='1234567890', + from_='1234567890', + audio=MessengerResource(url='https://example.com/audio.mp3'), + messenger=MessengerOptions(category='message_tag', tag='tag'), + client_ref='client-ref', + webhook_url='https://example.com', + webhook_version=WebhookVersion.V1, + ) + messenger_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'audio': {'url': 'https://example.com/audio.mp3'}, + 'messenger': {'category': 'message_tag', 'tag': 'tag'}, + 'client_ref': 'client-ref', + 'webhook_url': 'https://example.com', + 'webhook_version': 'v1', + 'channel': 'messenger', + 'message_type': 'audio', + } + + assert messenger_model.model_dump(by_alias=True) == messenger_dict + + +def test_create_messenger_video(): + messenger_model = MessengerVideo( + to='1234567890', + from_='1234567890', + video=MessengerResource(url='https://example.com/video.mp4'), + ) + messenger_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'video': {'url': 'https://example.com/video.mp4'}, + 'channel': 'messenger', + 'message_type': 'video', + } + + assert messenger_model.model_dump(by_alias=True, exclude_none=True) == messenger_dict + + +def test_create_messenger_video_all_fields(): + messenger_model = MessengerVideo( + to='1234567890', + from_='1234567890', + video=MessengerResource(url='https://example.com/video.mp4'), + messenger=MessengerOptions(category='message_tag', tag='tag'), + client_ref='client-ref', + webhook_url='https://example.com', + webhook_version=WebhookVersion.V1, + ) + messenger_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'video': {'url': 'https://example.com/video.mp4'}, + 'messenger': {'category': 'message_tag', 'tag': 'tag'}, + 'client_ref': 'client-ref', + 'webhook_url': 'https://example.com', + 'webhook_version': 'v1', + 'channel': 'messenger', + 'message_type': 'video', + } + + assert messenger_model.model_dump(by_alias=True) == messenger_dict + + +def test_create_messenger_file(): + messenger_model = MessengerFile( + to='1234567890', + from_='1234567890', + file=MessengerResource(url='https://example.com/file.pdf'), + ) + messenger_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'file': {'url': 'https://example.com/file.pdf'}, + 'channel': 'messenger', + 'message_type': 'file', + } + + assert messenger_model.model_dump(by_alias=True, exclude_none=True) == messenger_dict + + +def test_create_messenger_file_all_fields(): + messenger_model = MessengerFile( + to='1234567890', + from_='1234567890', + file=MessengerResource(url='https://example.com/file.pdf'), + messenger=MessengerOptions(category='message_tag', tag='tag'), + client_ref='client-ref', + webhook_url='https://example.com', + webhook_version=WebhookVersion.V1, + ) + messenger_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'file': {'url': 'https://example.com/file.pdf'}, + 'messenger': {'category': 'message_tag', 'tag': 'tag'}, + 'client_ref': 'client-ref', + 'webhook_url': 'https://example.com', + 'webhook_version': 'v1', + 'channel': 'messenger', + 'message_type': 'file', + } + + assert messenger_model.model_dump(by_alias=True) == messenger_dict diff --git a/messages/tests/test_mms_models.py b/messages/tests/test_mms_models.py new file mode 100644 index 00000000..4bf75979 --- /dev/null +++ b/messages/tests/test_mms_models.py @@ -0,0 +1,210 @@ +from vonage_messages.enums import WebhookVersion +from vonage_messages.models import MmsAudio, MmsImage, MmsResource, MmsVcard, MmsVideo + + +def test_create_mms_image(): + mms_model = MmsImage( + to='1234567890', + from_='1234567890', + image=MmsResource( + url='https://example.com/image.jpg', + ), + ) + mms_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'image': { + 'url': 'https://example.com/image.jpg', + }, + 'channel': 'mms', + 'message_type': 'image', + } + + assert mms_model.model_dump(by_alias=True, exclude_none=True) == mms_dict + + +def test_create_mms_image_all_fields(): + mms_model = MmsImage( + to='1234567890', + from_='1234567890', + image=MmsResource( + url='https://example.com/image.jpg', + caption='Image caption', + ), + client_ref='client-ref', + webhook_url='https://example.com', + webhook_version=WebhookVersion.V1, + ttl=600, + ) + mms_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'image': { + 'url': 'https://example.com/image.jpg', + 'caption': 'Image caption', + }, + 'client_ref': 'client-ref', + 'webhook_url': 'https://example.com', + 'webhook_version': 'v1', + 'ttl': 600, + 'channel': 'mms', + 'message_type': 'image', + } + + assert mms_model.model_dump(by_alias=True) == mms_dict + + +def test_create_mms_vcard(): + mms_model = MmsVcard( + to='1234567890', + from_='1234567890', + vcard=MmsResource( + url='https://example.com/vcard.vcf', + ), + ) + mms_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'vcard': { + 'url': 'https://example.com/vcard.vcf', + }, + 'channel': 'mms', + 'message_type': 'vcard', + } + + assert mms_model.model_dump(by_alias=True, exclude_none=True) == mms_dict + + +def test_create_mms_vcard_all_fields(): + mms_model = MmsVcard( + to='1234567890', + from_='1234567890', + vcard=MmsResource( + url='https://example.com/vcard.vcf', + caption='Vcard caption', + ), + client_ref='client-ref', + webhook_url='https://example.com', + webhook_version=WebhookVersion.V1, + ttl=600, + ) + mms_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'vcard': { + 'url': 'https://example.com/vcard.vcf', + 'caption': 'Vcard caption', + }, + 'client_ref': 'client-ref', + 'webhook_url': 'https://example.com', + 'webhook_version': 'v1', + 'ttl': 600, + 'channel': 'mms', + 'message_type': 'vcard', + } + + assert mms_model.model_dump(by_alias=True) == mms_dict + + +def test_create_mms_audio(): + mms_model = MmsAudio( + to='1234567890', + from_='1234567890', + audio=MmsResource( + url='https://example.com/audio.mp3', + ), + ) + mms_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'audio': { + 'url': 'https://example.com/audio.mp3', + }, + 'channel': 'mms', + 'message_type': 'audio', + } + + assert mms_model.model_dump(by_alias=True, exclude_none=True) == mms_dict + + +def test_create_mms_audio_all_fields(): + mms_model = MmsAudio( + to='1234567890', + from_='1234567890', + audio=MmsResource( + url='https://example.com/audio.mp3', + caption='Audio caption', + ), + client_ref='client-ref', + webhook_url='https://example.com', + webhook_version=WebhookVersion.V1, + ttl=600, + ) + mms_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'audio': { + 'url': 'https://example.com/audio.mp3', + 'caption': 'Audio caption', + }, + 'client_ref': 'client-ref', + 'webhook_url': 'https://example.com', + 'webhook_version': 'v1', + 'ttl': 600, + 'channel': 'mms', + 'message_type': 'audio', + } + + assert mms_model.model_dump(by_alias=True) == mms_dict + + +def test_create_mms_video(): + mms_model = MmsVideo( + to='1234567890', + from_='1234567890', + video=MmsResource( + url='https://example.com/video.mp4', + ), + ) + mms_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'video': { + 'url': 'https://example.com/video.mp4', + }, + 'channel': 'mms', + 'message_type': 'video', + } + + assert mms_model.model_dump(by_alias=True, exclude_none=True) == mms_dict + + +def test_create_mms_video_all_fields(): + mms_model = MmsVideo( + to='1234567890', + from_='1234567890', + video=MmsResource( + url='https://example.com/video.mp4', + caption='Video caption', + ), + client_ref='client-ref', + webhook_url='https://example.com', + webhook_version=WebhookVersion.V1, + ttl=600, + ) + mms_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'video': { + 'url': 'https://example.com/video.mp4', + 'caption': 'Video caption', + }, + 'client_ref': 'client-ref', + 'webhook_url': 'https://example.com', + 'webhook_version': 'v1', + 'ttl': 600, + 'channel': 'mms', + 'message_type': 'video', + } + + assert mms_model.model_dump(by_alias=True) == mms_dict diff --git a/messages/tests/test_models.py b/messages/tests/test_models.py deleted file mode 100644 index 2ab6aee0..00000000 --- a/messages/tests/test_models.py +++ /dev/null @@ -1,14 +0,0 @@ -from vonage_verify_v2.enums import ChannelType -from vonage_verify_v2.requests import * - - -def test_create_silent_auth_channel(): - params = { - 'channel': ChannelType.SILENT_AUTH, - 'to': '1234567890', - 'redirect_url': 'https://example.com', - 'sandbox': True, - } - channel = SilentAuthChannel(**params) - - assert channel.model_dump() == params diff --git a/messages/tests/test_sms_models.py b/messages/tests/test_sms_models.py new file mode 100644 index 00000000..ce5012fe --- /dev/null +++ b/messages/tests/test_sms_models.py @@ -0,0 +1,54 @@ +from vonage_messages.enums import EncodingType, WebhookVersion +from vonage_messages.models import Sms, SmsOptions + + +def test_create_sms(): + sms_model = Sms( + to='1234567890', + from_='1234567890', + text='Hello, World!', + ) + sms_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'text': 'Hello, World!', + 'channel': 'sms', + 'message_type': 'text', + } + + assert sms_model.model_dump(by_alias=True, exclude_none=True) == sms_dict + + +def test_create_sms_all_fields(): + sms_model = Sms( + to='1234567890', + from_='1234567890', + text='Hello, World!', + sms=SmsOptions( + encoding_type=EncodingType.TEXT, + content_id='content-id', + entity_id='entity-id', + ), + client_ref='client-ref', + webhook_url='https://example.com', + webhook_version=WebhookVersion.V1, + ttl=600, + ) + sms_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'text': 'Hello, World!', + 'sms': { + 'encoding_type': 'text', + 'content_id': 'content-id', + 'entity_id': 'entity-id', + }, + 'client_ref': 'client-ref', + 'webhook_url': 'https://example.com', + 'webhook_version': 'v1', + 'ttl': 600, + 'channel': 'sms', + 'message_type': 'text', + } + + assert sms_model.model_dump(by_alias=True) == sms_dict diff --git a/messages/tests/test_viber_models.py b/messages/tests/test_viber_models.py new file mode 100644 index 00000000..f2fa7476 --- /dev/null +++ b/messages/tests/test_viber_models.py @@ -0,0 +1,243 @@ +from pytest import raises +from vonage_messages.enums import WebhookVersion +from vonage_messages.models import ( + ViberAction, + ViberFile, + ViberFileOptions, + ViberFileResource, + ViberImage, + ViberImageOptions, + ViberImageResource, + ViberText, + ViberTextOptions, + ViberVideo, + ViberVideoOptions, + ViberVideoResource, +) + + +def test_viber_video_options_validator(): + with raises(ValueError): + ViberVideoOptions(duration='601', file_size='10') + + with raises(ValueError): + ViberVideoOptions(duration='100', file_size='201') + + +def test_create_viber_text(): + viber_model = ViberText(to='1234567890', from_='1234567890', text='Hello, World!') + viber_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'text': 'Hello, World!', + 'channel': 'viber_service', + 'message_type': 'text', + } + + assert viber_model.model_dump(by_alias=True, exclude_none=True) == viber_dict + + +def test_create_viber_text_all_fields(): + viber_model = ViberText( + to='1234567890', + from_='1234567890', + text='Hello, World!', + viber_service=ViberTextOptions( + category='transaction', + ttl=30, + type='string', + action=ViberAction(url='https://example.com', text='text'), + ), + client_ref='client-ref', + webhook_url='https://example.com', + webhook_version=WebhookVersion.V1, + ) + viber_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'text': 'Hello, World!', + 'viber_service': { + 'category': 'transaction', + 'ttl': 30, + 'type': 'string', + 'action': {'url': 'https://example.com', 'text': 'text'}, + }, + 'client_ref': 'client-ref', + 'webhook_url': 'https://example.com', + 'webhook_version': 'v1', + 'channel': 'viber_service', + 'message_type': 'text', + } + + assert viber_model.model_dump(by_alias=True) == viber_dict + + +def test_create_viber_image(): + viber_model = ViberImage( + to='1234567890', + from_='1234567890', + image=ViberImageResource(url='https://example.com/image.jpg'), + ) + viber_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'image': {'url': 'https://example.com/image.jpg'}, + 'channel': 'viber_service', + 'message_type': 'image', + } + + assert viber_model.model_dump(by_alias=True, exclude_none=True) == viber_dict + + +def test_create_viber_image_all_fields(): + viber_model = ViberImage( + to='1234567890', + from_='1234567890', + image=ViberImageResource(url='https://example.com/image.jpg', caption='caption'), + viber_service=ViberImageOptions( + category='transaction', + ttl=30, + type='string', + action=ViberAction(url='https://example.com', text='text'), + ), + client_ref='client-ref', + webhook_url='https://example.com', + webhook_version=WebhookVersion.V1, + ) + viber_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'image': {'url': 'https://example.com/image.jpg', 'caption': 'caption'}, + 'viber_service': { + 'category': 'transaction', + 'ttl': 30, + 'type': 'string', + 'action': {'url': 'https://example.com', 'text': 'text'}, + }, + 'client_ref': 'client-ref', + 'webhook_url': 'https://example.com', + 'webhook_version': 'v1', + 'channel': 'viber_service', + 'message_type': 'image', + } + + assert viber_model.model_dump(by_alias=True) == viber_dict + + +def test_create_viber_video(): + viber_model = ViberVideo( + to='1234567890', + from_='1234567890', + video=ViberVideoResource( + url='https://example.com/video.mp4', thumb_url='https://example.com/thumb.jpg' + ), + viber_service=ViberVideoOptions(duration='100', file_size='10'), + ) + viber_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'video': { + 'url': 'https://example.com/video.mp4', + 'thumb_url': 'https://example.com/thumb.jpg', + }, + 'viber_service': {'duration': '100', 'file_size': '10'}, + 'channel': 'viber_service', + 'message_type': 'video', + } + + assert viber_model.model_dump(by_alias=True, exclude_none=True) == viber_dict + + +def test_create_viber_video_all_fields(): + viber_model = ViberVideo( + to='1234567890', + from_='1234567890', + video=ViberVideoResource( + url='https://example.com/video.mp4', + thumb_url='https://example.com/thumb.jpg', + caption='caption', + ), + viber_service=ViberVideoOptions( + duration='100', + file_size='10', + category='transaction', + ttl=30, + type='string', + ), + client_ref='client-ref', + webhook_url='https://example.com', + webhook_version=WebhookVersion.V1, + ) + viber_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'video': { + 'url': 'https://example.com/video.mp4', + 'thumb_url': 'https://example.com/thumb.jpg', + 'caption': 'caption', + }, + 'viber_service': { + 'duration': '100', + 'file_size': '10', + 'category': 'transaction', + 'ttl': 30, + 'type': 'string', + }, + 'client_ref': 'client-ref', + 'webhook_url': 'https://example.com', + 'webhook_version': 'v1', + 'channel': 'viber_service', + 'message_type': 'video', + } + + assert viber_model.model_dump(by_alias=True) == viber_dict + + +def test_create_viber_file(): + viber_model = ViberFile( + to='1234567890', + from_='1234567890', + file=ViberFileResource(url='https://example.com/file.pdf'), + ) + viber_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'file': {'url': 'https://example.com/file.pdf'}, + 'channel': 'viber_service', + 'message_type': 'file', + } + + assert viber_model.model_dump(by_alias=True, exclude_none=True) == viber_dict + + +def test_create_viber_file_all_fields(): + viber_model = ViberFile( + to='1234567890', + from_='1234567890', + file=ViberFileResource(url='https://example.com/file.pdf', name='file.pdf'), + viber_service=ViberFileOptions( + category='transaction', + ttl=30, + type='string', + ), + client_ref='client-ref', + webhook_url='https://example.com', + webhook_version=WebhookVersion.V1, + ) + viber_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'file': {'url': 'https://example.com/file.pdf', 'name': 'file.pdf'}, + 'viber_service': { + 'category': 'transaction', + 'ttl': 30, + 'type': 'string', + }, + 'client_ref': 'client-ref', + 'webhook_url': 'https://example.com', + 'webhook_version': 'v1', + 'channel': 'viber_service', + 'message_type': 'file', + } + + assert viber_model.model_dump(by_alias=True) == viber_dict diff --git a/messages/tests/test_whatsapp_models.py b/messages/tests/test_whatsapp_models.py new file mode 100644 index 00000000..6a47c5c5 --- /dev/null +++ b/messages/tests/test_whatsapp_models.py @@ -0,0 +1,384 @@ +from copy import deepcopy + +from vonage_messages.enums import WebhookVersion +from vonage_messages.models import ( + WhatsappAudio, + WhatsappAudioResource, + WhatsappContext, + WhatsappCustom, + WhatsappFile, + WhatsappFileResource, + WhatsappImage, + WhatsappImageResource, + WhatsappSticker, + WhatsappStickerId, + WhatsappStickerUrl, + WhatsappTemplate, + WhatsappTemplateResource, + WhatsappTemplateSettings, + WhatsappText, + WhatsappVideo, + WhatsappVideoResource, +) + + +def test_whatsapp_text(): + whatsapp_model = WhatsappText( + to='1234567890', + from_='1234567890', + text='Hello, World!', + ) + whatsapp_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'text': 'Hello, World!', + 'channel': 'whatsapp', + 'message_type': 'text', + } + + assert whatsapp_model.model_dump(by_alias=True, exclude_none=True) == whatsapp_dict + + +def test_whatsapp_text_all_fields(): + whatsapp_model = WhatsappText( + to='1234567890', + from_='1234567890', + text='Hello, World!', + context=WhatsappContext( + message_uuid='uuid', + ), + client_ref='client-ref', + webhook_url='https://example.com', + webhook_version=WebhookVersion.V1, + ) + whatsapp_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'text': 'Hello, World!', + 'context': {'message_uuid': 'uuid'}, + 'client_ref': 'client-ref', + 'webhook_url': 'https://example.com', + 'webhook_version': 'v1', + 'channel': 'whatsapp', + 'message_type': 'text', + } + + assert whatsapp_model.model_dump(by_alias=True) == whatsapp_dict + whatsapp_pre_dict = deepcopy(whatsapp_dict) + whatsapp_pre_dict['from_'] = '1234567890' + whatsapp_model_from_dict = WhatsappText(**whatsapp_pre_dict) + assert whatsapp_model_from_dict.model_dump(by_alias=True) == whatsapp_dict + + +def test_whatsapp_image(): + whatsapp_model = WhatsappImage( + to='1234567890', + from_='1234567890', + image=WhatsappImageResource(url='https://example.com/image.jpg'), + ) + whatsapp_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'image': {'url': 'https://example.com/image.jpg'}, + 'channel': 'whatsapp', + 'message_type': 'image', + } + + assert whatsapp_model.model_dump(by_alias=True, exclude_none=True) == whatsapp_dict + + +def test_whatsapp_image_all_fields(): + whatsapp_model = WhatsappImage( + to='1234567890', + from_='1234567890', + image=WhatsappImageResource( + url='https://example.com/image.jpg', + caption='Image caption', + ), + context=WhatsappContext( + message_uuid='uuid', + ), + client_ref='client-ref', + webhook_url='https://example.com', + webhook_version=WebhookVersion.V1, + ) + whatsapp_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'image': { + 'url': 'https://example.com/image.jpg', + 'caption': 'Image caption', + }, + 'context': {'message_uuid': 'uuid'}, + 'client_ref': 'client-ref', + 'webhook_url': 'https://example.com', + 'webhook_version': 'v1', + 'channel': 'whatsapp', + 'message_type': 'image', + } + + assert whatsapp_model.model_dump(by_alias=True) == whatsapp_dict + + +def test_whatsapp_audio(): + whatsapp_model = WhatsappAudio( + to='1234567890', + from_='1234567890', + audio=WhatsappAudioResource(url='https://example.com/audio.mp3'), + ) + whatsapp_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'audio': {'url': 'https://example.com/audio.mp3'}, + 'channel': 'whatsapp', + 'message_type': 'audio', + } + + assert whatsapp_model.model_dump(by_alias=True, exclude_none=True) == whatsapp_dict + + +def test_whatsapp_audio_all_fields(): + whatsapp_model = WhatsappAudio( + to='1234567890', + from_='1234567890', + audio=WhatsappAudioResource( + url='https://example.com/audio.mp3', + ), + context=WhatsappContext( + message_uuid='uuid', + ), + client_ref='client-ref', + webhook_url='https://example.com', + webhook_version=WebhookVersion.V1, + ) + whatsapp_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'audio': {'url': 'https://example.com/audio.mp3'}, + 'context': {'message_uuid': 'uuid'}, + 'client_ref': 'client-ref', + 'webhook_url': 'https://example.com', + 'webhook_version': 'v1', + 'channel': 'whatsapp', + 'message_type': 'audio', + } + + assert whatsapp_model.model_dump(by_alias=True) == whatsapp_dict + + +def test_whatsapp_video(): + whatsapp_model = WhatsappVideo( + to='1234567890', + from_='1234567890', + video=WhatsappVideoResource(url='https://example.com/video.mp4'), + ) + whatsapp_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'video': {'url': 'https://example.com/video.mp4'}, + 'channel': 'whatsapp', + 'message_type': 'video', + } + + assert whatsapp_model.model_dump(by_alias=True, exclude_none=True) == whatsapp_dict + + +def test_whatsapp_video_all_fields(): + whatsapp_model = WhatsappVideo( + to='1234567890', + from_='1234567890', + video=WhatsappVideoResource( + url='https://example.com/video.mp4', + caption='Video caption', + ), + context=WhatsappContext( + message_uuid='uuid', + ), + client_ref='client-ref', + webhook_url='https://example.com', + webhook_version=WebhookVersion.V1, + ) + whatsapp_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'video': { + 'url': 'https://example.com/video.mp4', + 'caption': 'Video caption', + }, + 'context': {'message_uuid': 'uuid'}, + 'client_ref': 'client-ref', + 'webhook_url': 'https://example.com', + 'webhook_version': 'v1', + 'channel': 'whatsapp', + 'message_type': 'video', + } + + assert whatsapp_model.model_dump(by_alias=True) == whatsapp_dict + + +def test_whatsapp_file(): + whatsapp_model = WhatsappFile( + to='1234567890', + from_='1234567890', + file=WhatsappFileResource(url='https://example.com/file.pdf'), + ) + whatsapp_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'file': {'url': 'https://example.com/file.pdf'}, + 'channel': 'whatsapp', + 'message_type': 'file', + } + + assert whatsapp_model.model_dump(by_alias=True, exclude_none=True) == whatsapp_dict + + +def test_whatsapp_file_all_fields(): + whatsapp_model = WhatsappFile( + to='1234567890', + from_='1234567890', + file=WhatsappFileResource( + url='https://example.com/file.pdf', + caption='File caption', + name='file.pdf', + ), + context=WhatsappContext( + message_uuid='uuid', + ), + client_ref='client-ref', + webhook_url='https://example.com', + webhook_version=WebhookVersion.V1, + ) + whatsapp_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'file': { + 'url': 'https://example.com/file.pdf', + 'caption': 'File caption', + 'name': 'file.pdf', + }, + 'context': {'message_uuid': 'uuid'}, + 'client_ref': 'client-ref', + 'webhook_url': 'https://example.com', + 'webhook_version': 'v1', + 'channel': 'whatsapp', + 'message_type': 'file', + } + + assert whatsapp_model.model_dump(by_alias=True) == whatsapp_dict + + +def test_whatsapp_template(): + whatsapp_model = WhatsappTemplate( + to='1234567890', + from_='1234567890', + template=WhatsappTemplateResource(name='template'), + ) + whatsapp_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'template': {'name': 'template'}, + 'whatsapp': {'locale': 'en_US'}, + 'channel': 'whatsapp', + 'message_type': 'template', + } + + assert whatsapp_model.model_dump(by_alias=True, exclude_none=True) == whatsapp_dict + + +def test_whatsapp_template_all_fields(): + whatsapp_model = WhatsappTemplate( + to='1234567890', + from_='1234567890', + template=WhatsappTemplateResource( + name='template', parameters=['param1', 'param2'] + ), + whatsapp=WhatsappTemplateSettings(locale='es_ES', policy='deterministic'), + context=WhatsappContext(message_uuid='uuid'), + client_ref='client-ref', + webhook_url='https://example.com', + webhook_version=WebhookVersion.V1, + ) + whatsapp_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'template': {'name': 'template', 'parameters': ['param1', 'param2']}, + 'whatsapp': {'locale': 'es_ES', 'policy': 'deterministic'}, + 'context': {'message_uuid': 'uuid'}, + 'client_ref': 'client-ref', + 'webhook_url': 'https://example.com', + 'webhook_version': 'v1', + 'channel': 'whatsapp', + 'message_type': 'template', + } + + assert whatsapp_model.model_dump(by_alias=True) == whatsapp_dict + + +def test_whatsapp_sticker_url(): + whatsapp_model = WhatsappSticker( + to='1234567890', + from_='1234567890', + sticker=WhatsappStickerUrl(url='https://example.com/sticker.webp'), + ) + whatsapp_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'sticker': {'url': 'https://example.com/sticker.webp'}, + 'channel': 'whatsapp', + 'message_type': 'sticker', + } + + assert whatsapp_model.model_dump(by_alias=True, exclude_none=True) == whatsapp_dict + + +def test_whatsapp_sticker_id(): + whatsapp_model = WhatsappSticker( + to='1234567890', from_='1234567890', sticker=WhatsappStickerId(id='sticker-id') + ) + whatsapp_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'sticker': {'id': 'sticker-id'}, + 'channel': 'whatsapp', + 'message_type': 'sticker', + } + + assert whatsapp_model.model_dump(by_alias=True, exclude_none=True) == whatsapp_dict + + +def test_whatsapp_custom(): + whatsapp_model = WhatsappCustom(to='1234567890', from_='1234567890') + whatsapp_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'channel': 'whatsapp', + 'message_type': 'custom', + } + + assert whatsapp_model.model_dump(by_alias=True, exclude_none=True) == whatsapp_dict + + +def test_whatsapp_custom_all_fields(): + whatsapp_model = WhatsappCustom( + to='1234567890', + from_='1234567890', + custom={'key': 'value'}, + context=WhatsappContext(message_uuid='uuid'), + client_ref='client-ref', + webhook_url='https://example.com', + webhook_version=WebhookVersion.V1, + ) + whatsapp_dict = { + 'to': '1234567890', + 'from': '1234567890', + 'custom': {'key': 'value'}, + 'context': {'message_uuid': 'uuid'}, + 'client_ref': 'client-ref', + 'webhook_url': 'https://example.com', + 'webhook_version': 'v1', + 'channel': 'whatsapp', + 'message_type': 'custom', + } + + assert whatsapp_model.model_dump(by_alias=True) == whatsapp_dict diff --git a/pants.toml b/pants.toml index a9c671a5..15e17b66 100644 --- a/pants.toml +++ b/pants.toml @@ -32,12 +32,15 @@ report = ['html', 'console'] filter = [ 'vonage/src', 'http_client/src', + 'messages/src', 'number_insight_v2/src', 'sms/src', 'users/src', 'utils/src', 'testutils', 'verify/src', + 'verify_v2/src', + 'vonage_utils/src', ] [black] diff --git a/vonage/src/vonage/__init__.py b/vonage/src/vonage/__init__.py index 62747843..4005985f 100644 --- a/vonage/src/vonage/__init__.py +++ b/vonage/src/vonage/__init__.py @@ -3,6 +3,7 @@ from .vonage import ( Auth, HttpClientOptions, + Messages, NumberInsightV2, Sms, Users, @@ -15,6 +16,7 @@ 'Vonage', 'Auth', 'HttpClientOptions', + 'Messages', 'NumberInsightV2', 'Sms', 'Users', diff --git a/vonage/src/vonage/vonage.py b/vonage/src/vonage/vonage.py index 92b2d9a5..e8d18a7f 100644 --- a/vonage/src/vonage/vonage.py +++ b/vonage/src/vonage/vonage.py @@ -1,6 +1,7 @@ from typing import Optional from vonage_http_client import Auth, HttpClient, HttpClientOptions +from vonage_messages import Messages from vonage_number_insight_v2 import NumberInsightV2 from vonage_sms import Sms from vonage_users import Users @@ -28,6 +29,7 @@ def __init__( ): self._http_client = HttpClient(auth, http_client_options, __version__) + self.messages = Messages(self._http_client) self.number_insight_v2 = NumberInsightV2(self._http_client) self.sms = Sms(self._http_client) self.users = Users(self._http_client)