Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,5 @@ jobs:
run: |
python -m behave tests/e2e/numbers/features
python -m behave tests/e2e/sms/features
python -m behave tests/e2e/conversation/features
python -m behave tests/e2e/number-lookup/features
26 changes: 26 additions & 0 deletions examples/snippets/conversation/messages/delete/snippet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"""
Sinch Python Snippet

TODO: Update links when v2 is released.
This snippet is available at https://github.com/sinch/sinch-sdk-python/blob/v2.0/docs/snippets/
"""

import os
from dotenv import load_dotenv
from sinch import SinchClient

load_dotenv()

sinch_client = SinchClient(
project_id=os.environ.get("SINCH_PROJECT_ID") or "MY_PROJECT_ID",
key_id=os.environ.get("SINCH_KEY_ID") or "MY_KEY_ID",
key_secret=os.environ.get("SINCH_KEY_SECRET") or "MY_KEY_SECRET",
conversation_region=os.environ.get("SINCH_CONVERSATION_REGION") or "MY_CONVERSATION_REGION"
)

# The ID of the message to delete
message_id = "MESSAGE_ID"

sinch_client.conversation.messages.delete(message_id=message_id)

print("Message deleted successfully")
26 changes: 26 additions & 0 deletions examples/snippets/conversation/messages/get/snippet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"""
Sinch Python Snippet

TODO: Update links when v2 is released.
This snippet is available at https://github.com/sinch/sinch-sdk-python/blob/v2.0/docs/snippets/
"""

import os
from dotenv import load_dotenv
from sinch import SinchClient

load_dotenv()

sinch_client = SinchClient(
project_id=os.environ.get("SINCH_PROJECT_ID") or "MY_PROJECT_ID",
key_id=os.environ.get("SINCH_KEY_ID") or "MY_KEY_ID",
key_secret=os.environ.get("SINCH_KEY_SECRET") or "MY_KEY_SECRET",
conversation_region=os.environ.get("SINCH_CONVERSATION_REGION") or "MY_CONVERSATION_REGION"
)

# The ID of the message to retrieve
message_id = "MESSAGE_ID"

response = sinch_client.conversation.messages.get(message_id=message_id)

print(f"Message details:\n{response}")
29 changes: 29 additions & 0 deletions examples/snippets/conversation/messages/update/snippet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""
Sinch Python Snippet

TODO: Update links when v2 is released.
This snippet is available at https://github.com/sinch/sinch-sdk-python/blob/v2.0/docs/snippets/
"""

import os
from dotenv import load_dotenv
from sinch import SinchClient

load_dotenv()

sinch_client = SinchClient(
project_id=os.environ.get("SINCH_PROJECT_ID") or "MY_PROJECT_ID",
key_id=os.environ.get("SINCH_KEY_ID") or "MY_KEY_ID",
key_secret=os.environ.get("SINCH_KEY_SECRET") or "MY_KEY_SECRET",
conversation_region=os.environ.get("SINCH_CONVERSATION_REGION") or "MY_CONVERSATION_REGION"
)

# The ID of the message to update
message_id = "MESSAGE_ID"

response = sinch_client.conversation.messages.update(
message_id=message_id,
metadata="metadata value set from Python SDK snippet"
)

print(f"Updated message:\n{response}")
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import pytest
from pydantic import ValidationError
from sinch.domains.conversation.models.v1.messages.internal.request import (
MessageIdRequest,
)


def test_message_id_request_expects_accepts_snake_case_input():
"""
Test that the model accepts snake_case input when allow_population_by_field_name is True.
"""
request = MessageIdRequest(message_id="CAPYLAKE123456789ABCDEFGHIJKL")

assert request.message_id == "CAPYLAKE123456789ABCDEFGHIJKL"


@pytest.mark.parametrize("messages_source", ["CONVERSATION_SOURCE", "DISPATCH_SOURCE"])
def test_message_id_request_expects_accepts_messages_source(messages_source):
"""
Test that the model accepts messages_source with different values.
"""
request = MessageIdRequest(
message_id="CAPYPOUND123456789ABCDEFGHIJKLM",
messages_source=messages_source
)

assert request.message_id == "CAPYPOUND123456789ABCDEFGHIJKLM"
assert request.messages_source == messages_source


def test_message_id_request_expects_validation_error_for_missing_field():
"""
Test that the model raises a ValidationError when a required field is missing.
"""
data = {}

with pytest.raises(ValidationError) as excinfo:
MessageIdRequest(**data)

error_message = str(excinfo.value)

assert "Field required" in error_message or "field required" in error_message
assert "messageId" in error_message or "message_id" in error_message
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import pytest
from pydantic import ValidationError
from sinch.domains.conversation.models.v1.messages.internal.request import (
UpdateMessageMetadataRequest,
)


@pytest.mark.parametrize("messages_source", ["CONVERSATION_SOURCE", "DISPATCH_SOURCE"])
def test_update_message_metadata_request_expects_accepts_messages_source(messages_source):
"""
Test that the model accepts messages_source with different values.
"""
request = UpdateMessageMetadataRequest(
message_id="CAPY123456789ABCDEFGHIJKLMNOP",
metadata="test_metadata",
messages_source=messages_source
)

assert request.message_id == "CAPY123456789ABCDEFGHIJKLMNOP"
assert request.metadata == "test_metadata"
assert request.messages_source == messages_source


def test_update_message_metadata_request_expects_validation_error_for_missing_message_id():
"""
Test that the model raises a ValidationError when message_id field is missing.
"""
data = {
"metadata": "test_metadata"
}

with pytest.raises(ValidationError) as excinfo:
UpdateMessageMetadataRequest(**data)

error_message = str(excinfo.value)

assert "Field required" in error_message or "field required" in error_message
assert "messageId" in error_message or "message_id" in error_message


def test_update_message_metadata_request_expects_validation_error_for_missing_metadata():
"""
Test that the model raises a ValidationError when metadata field is missing.
"""
data = {
"message_id": "CAPY123456789ABCDEFGHIJKLMNOP"
}

with pytest.raises(ValidationError) as excinfo:
UpdateMessageMetadataRequest(**data)

error_message = str(excinfo.value)

assert "Field required" in error_message or "field required" in error_message
assert "metadata" in error_message
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

@pytest.fixture
def card_app_message_data():
"""Test data for CardAppMessage from Java SDK."""
return {
"card_message": {
"title": "title value",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

@pytest.fixture
def carousel_app_message_data():
"""Test data for CarouselAppMessage from Java SDK."""
return {
"carousel_message": {
"cards": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

@pytest.fixture
def choice_app_message_data():
"""Test data for ChoiceAppMessage from Java SDK."""
return {
"choice_message": {
"text_message": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

@pytest.fixture
def contact_info_app_message_data():
"""Test data for ContactInfoAppMessage from Java SDK."""
return {
"contact_info_message": {
"name": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

@pytest.fixture
def list_app_message_data():
"""Test data for ListAppMessage from Java SDK."""
return {
"list_message": {
"title": "a list message title value",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

@pytest.fixture
def location_app_message_data():
"""Test data for LocationAppMessage from Java SDK."""
return {
"location_message": {
"coordinates": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

@pytest.fixture
def media_app_message_data():
"""Test data for MediaAppMessage from Java SDK."""
return {
"media_message": {
"url": "an url value",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import pytest
from sinch.domains.conversation.models.v1.messages.categories.app.app_message import (
CardAppMessage,
)


@pytest.fixture
def card_app_message_with_omni_override_card_data():
return {
"card_message": {
"title": "title value",
"description": "description value",
"media_message": {
"url": "an url value",
"thumbnail_url": "another url",
"filename_override": "filename override value"
},
"height": "MEDIUM",
"choices": [
{
"text_message": {
"text": "This is a text message."
},
"postback_data": "postback_data text"
}
]
},
"explicit_channel_omni_message": {
"KAKAOTALK": {
"card_message": {
"title": "title value",
"description": "description value",
"media_message": {
"url": "an url value",
"thumbnail_url": "another url",
"filename_override": "filename override value"
},
"height": "MEDIUM",
"choices": [
{
"text_message": {
"text": "This is a text message."
},
"postback_data": "postback_data text"
},
{
"call_message": {
"title": "title value",
"phone_number": "phone number value"
},
"postback_data": "postback_data call"
},
{
"location_message": {
"coordinates": {
"latitude": 47.6279809,
"longitude": -2.8229159
},
"title": "title value",
"label": "label value"
},
"postback_data": "postback_data location"
},
{
"url_message": {
"title": "title value",
"url": "an url value"
},
"postback_data": "postback_data url"
},
{
"calendar_message": {
"title": "Calendar Message Example",
"event_start": "2023-10-01T10:00:00Z",
"event_end": "2023-10-01T11:00:00Z",
"event_title": "Team Meeting",
"event_description": "Monthly team sync-up",
"fallback_url": "https://calendar.example.com/event/12345"
},
"postback_data": "postback calendar_message data value"
},
{
"share_location_message": {
"title": "Share Location Example",
"fallback_url": "https://maps.example.com/?q=37.7749,-122.4194"
},
"postback_data": "postback share_location_message data value"
}
]
}
}
},
"agent": {
"display_name": "display_name value",
"type": "BOT",
"picture_url": "picture_url value"
}
}


def test_parsing_card_app_message_with_omni_override_card_expects_correct_fields(
card_app_message_with_omni_override_card_data,
):
"""Test that CardAppMessage with OmniMessageOverrideCard is parsed correctly."""
parsed_response = CardAppMessage.model_validate(
card_app_message_with_omni_override_card_data
)

assert isinstance(parsed_response, CardAppMessage)
assert parsed_response.card_message is not None
assert parsed_response.explicit_channel_omni_message is not None
assert "KAKAOTALK" in parsed_response.explicit_channel_omni_message
omni_override = parsed_response.explicit_channel_omni_message["KAKAOTALK"]
assert omni_override.card_message is not None
assert omni_override.card_message.title == "title value"
assert omni_override.card_message.description == "description value"
assert omni_override.card_message.height == "MEDIUM"
assert len(omni_override.card_message.choices) == 6
assert parsed_response.agent is not None
Loading