from unittest import mock import pytest from ows_text_campaigns.api.schemas import TwilioInboundMessageBody from ows_text_campaigns.artist.models import ArtistPhoneNumber, ArtistSettings from ows_text_campaigns.twilio.handlers.inbound import TwilioInboundMessageHandler from ows_text_campaigns.twilio.models import TwilioAccount from tests.unit.types import CreateModel, CreatePgModel class TestTwilioInboundMessageHandler: @pytest.mark.db def test_handler_greetings( self, handler: TwilioInboundMessageHandler, create_pg_model: CreatePgModel, create_model: CreateModel, twilio_client_mock: mock.MagicMock, kafka_client_mock: mock.MagicMock, dynamodb_client_mock: mock.MagicMock, ) -> None: account = create_pg_model(TwilioAccount) dynamodb_client_mock.get_fan_state.return_value = "greetings" global_participant_id = "artist-123" create_model( ArtistSettings, global_participant_id=global_participant_id, ) artist_phone_number = create_model( ArtistPhoneNumber, global_participant_id=global_participant_id, phone_number="+1234567890", ) body = TwilioInboundMessageBody.model_validate( { "AccountSid": account.account_sid, "To": artist_phone_number.phone_number, "From": "+12345678901", "Body": "Hello, this is a test message.", } ) handler.handle(body) twilio_client_mock.send_message.assert_called_with( request=mock.ANY, auth=(account.account_sid, account.auth_token) ) assert kafka_client_mock.send_event_message.call_count == 1 assert kafka_client_mock.send_fan_state.call_count == 1 assert dynamodb_client_mock.get_fan_state.call_count == 1 assert dynamodb_client_mock.set_fan_state.call_count == 1 @pytest.mark.db def test_handler_opt_in_asked( self, handler: TwilioInboundMessageHandler, create_pg_model: CreatePgModel, create_model: CreateModel, twilio_client_mock: mock.MagicMock, kafka_client_mock: mock.MagicMock, dynamodb_client_mock: mock.MagicMock, ) -> None: account = create_pg_model(TwilioAccount) dynamodb_client_mock.get_fan_state.return_value = "opt_in_asked" global_participant_id = "artist-123" create_model( ArtistSettings, global_participant_id=global_participant_id, ) artist_phone_number = create_model( ArtistPhoneNumber, global_participant_id=global_participant_id, phone_number="+1234567890", ) body = TwilioInboundMessageBody.model_validate( { "AccountSid": account.account_sid, "To": artist_phone_number.phone_number, "From": "+12345678901", "Body": "yes", } ) handler.handle(body) twilio_client_mock.send_message.assert_called_with( request=mock.ANY, auth=(account.account_sid, account.auth_token) ) assert kafka_client_mock.send_event_message.call_count == 1 assert kafka_client_mock.send_fan_state.call_count == 1 assert dynamodb_client_mock.get_fan_state.call_count == 1 assert dynamodb_client_mock.set_fan_state.call_count == 1 @pytest.mark.db def test_handler_opted_in_random_message( self, handler: TwilioInboundMessageHandler, create_pg_model: CreatePgModel, create_model: CreateModel, twilio_client_mock: mock.MagicMock, kafka_client_mock: mock.MagicMock, dynamodb_client_mock: mock.MagicMock, ) -> None: account = create_pg_model(TwilioAccount) dynamodb_client_mock.get_fan_state.return_value = "opted_in" global_participant_id = "artist-123" create_model( ArtistSettings, global_participant_id=global_participant_id, ) artist_phone_number = create_model( ArtistPhoneNumber, global_participant_id=global_participant_id, phone_number="+1234567890", ) body = TwilioInboundMessageBody.model_validate( { "AccountSid": account.account_sid, "To": artist_phone_number.phone_number, "From": "+12345678901", "Body": "hi", } ) handler.handle(body) assert twilio_client_mock.send_message.call_count == 0 assert kafka_client_mock.send_event_message.call_count == 1 assert kafka_client_mock.send_fan_state.call_count == 0 assert dynamodb_client_mock.get_fan_state.call_count == 1 assert dynamodb_client_mock.set_fan_state.call_count == 0 @pytest.mark.db def test_handler_opted_in_info_message( self, handler: TwilioInboundMessageHandler, create_pg_model: CreatePgModel, create_model: CreateModel, twilio_client_mock: mock.MagicMock, kafka_client_mock: mock.MagicMock, dynamodb_client_mock: mock.MagicMock, ) -> None: account = create_pg_model(TwilioAccount) dynamodb_client_mock.get_fan_state.return_value = "opted_in" global_participant_id = "artist-123" create_model( ArtistSettings, global_participant_id=global_participant_id, ) artist_phone_number = create_model( ArtistPhoneNumber, global_participant_id=global_participant_id, phone_number="+1234567890", ) body = TwilioInboundMessageBody.model_validate( { "AccountSid": account.account_sid, "To": artist_phone_number.phone_number, "From": "+12345678901", "Body": "info", } ) handler.handle(body) assert twilio_client_mock.send_message.call_count == 1 assert kafka_client_mock.send_event_message.call_count == 1 assert kafka_client_mock.send_fan_state.call_count == 0 assert dynamodb_client_mock.get_fan_state.call_count == 1 assert dynamodb_client_mock.set_fan_state.call_count == 0 @pytest.mark.db def test_handler_opted_in_opt_out( self, handler: TwilioInboundMessageHandler, create_pg_model: CreatePgModel, create_model: CreateModel, twilio_client_mock: mock.MagicMock, kafka_client_mock: mock.MagicMock, dynamodb_client_mock: mock.MagicMock, ) -> None: account = create_pg_model(TwilioAccount) dynamodb_client_mock.get_fan_state.return_value = "opted_in" global_participant_id = "artist-123" create_model( ArtistSettings, global_participant_id=global_participant_id, ) artist_phone_number = create_model( ArtistPhoneNumber, global_participant_id=global_participant_id, phone_number="+1234567890", ) body = TwilioInboundMessageBody.model_validate( { "AccountSid": account.account_sid, "To": artist_phone_number.phone_number, "From": "+12345678901", "Body": "stop", } ) handler.handle(body) assert twilio_client_mock.send_message.call_count == 0 assert kafka_client_mock.send_event_message.call_count == 1 assert kafka_client_mock.send_fan_state.call_count == 1 assert dynamodb_client_mock.get_fan_state.call_count == 1 assert dynamodb_client_mock.set_fan_state.call_count == 1