""" Tests for ContentGenerator service. """ import pytest from unittest.mock import MagicMock, patch, AsyncMock class TestContentGenerator: """Tests for the ContentGenerator class.""" @pytest.fixture def generator(self, mock_settings): """Create a ContentGenerator instance with mocked client.""" with patch('app.services.content_generator.OpenAI') as mock_openai: mock_client = MagicMock() mock_response = MagicMock() mock_response.choices = [MagicMock()] mock_response.choices[0].message.content = "Test content #AI #Tech" mock_client.chat.completions.create.return_value = mock_response mock_openai.return_value = mock_client from app.services.content_generator import ContentGenerator gen = ContentGenerator() gen._client = mock_client yield gen @pytest.mark.asyncio async def test_generate_tip_tech(self, generator): """Test generating a tech tip.""" result = await generator.generate_tip_tech( category="seguridad", platform="x" ) assert result is not None assert len(result) > 0 generator.client.chat.completions.create.assert_called_once() @pytest.mark.asyncio async def test_generate_tip_tech_with_template(self, generator): """Test generating a tech tip with a template.""" result = await generator.generate_tip_tech( category="productividad", platform="threads", template="Tip del día: {tip}" ) assert result is not None call_args = generator.client.chat.completions.create.call_args assert "template" in str(call_args).lower() or "TEMPLATE" in str(call_args) @pytest.mark.asyncio async def test_generate_product_post(self, generator, sample_product): """Test generating a product post.""" result = await generator.generate_product_post( product=sample_product, platform="instagram" ) assert result is not None call_args = generator.client.chat.completions.create.call_args messages = call_args.kwargs.get('messages', call_args[1].get('messages', [])) # Verify product info was included in prompt user_message = messages[-1]['content'] assert sample_product['name'] in user_message # Price is formatted with commas, check for the value assert "15,999" in user_message or "15999" in user_message @pytest.mark.asyncio async def test_generate_service_post(self, generator, sample_service): """Test generating a service post.""" result = await generator.generate_service_post( service=sample_service, platform="facebook" ) assert result is not None call_args = generator.client.chat.completions.create.call_args messages = call_args.kwargs.get('messages', call_args[1].get('messages', [])) user_message = messages[-1]['content'] assert sample_service['name'] in user_message @pytest.mark.asyncio async def test_generate_thread(self, generator): """Test generating a thread.""" generator.client.chat.completions.create.return_value.choices[0].message.content = \ "1/ Post uno\n2/ Post dos\n3/ Post tres" result = await generator.generate_thread( topic="Cómo proteger tu contraseña", num_posts=3 ) assert isinstance(result, list) assert len(result) == 3 @pytest.mark.asyncio async def test_generate_response_suggestion(self, generator, sample_interaction): """Test generating response suggestions.""" generator.client.chat.completions.create.return_value.choices[0].message.content = \ "1. Respuesta corta\n2. Respuesta media\n3. Respuesta larga" result = await generator.generate_response_suggestion( interaction_content=sample_interaction['content'], interaction_type=sample_interaction['type'] ) assert isinstance(result, list) assert len(result) <= 3 @pytest.mark.asyncio async def test_adapt_content_for_platform(self, generator): """Test adapting content for different platforms.""" original = "Este es un tip muy largo sobre seguridad informática con muchos detalles" result = await generator.adapt_content_for_platform( content=original, target_platform="x" ) assert result is not None call_args = generator.client.chat.completions.create.call_args messages = call_args.kwargs.get('messages', call_args[1].get('messages', [])) user_message = messages[-1]['content'] assert "280" in user_message # X character limit def test_get_system_prompt(self, generator, mock_settings): """Test that system prompt includes business info.""" prompt = generator._get_system_prompt() assert mock_settings.BUSINESS_NAME in prompt assert mock_settings.BUSINESS_LOCATION in prompt def test_lazy_initialization_without_api_key(self): """Test that client raises error without API key.""" with patch('app.services.content_generator.settings') as mock: mock.DEEPSEEK_API_KEY = None from app.services.content_generator import ContentGenerator gen = ContentGenerator() with pytest.raises(ValueError, match="DEEPSEEK_API_KEY"): _ = gen.client class TestCharacterLimits: """Tests for character limit handling.""" @pytest.mark.parametrize("platform,expected_limit", [ ("x", 280), ("threads", 500), ("instagram", 2200), ("facebook", 500), ]) @pytest.mark.asyncio async def test_platform_character_limits(self, platform, expected_limit, mock_settings): """Test that correct character limits are used per platform.""" with patch('app.services.content_generator.OpenAI') as mock_openai: mock_client = MagicMock() mock_response = MagicMock() mock_response.choices = [MagicMock()] mock_response.choices[0].message.content = "Test" mock_client.chat.completions.create.return_value = mock_response mock_openai.return_value = mock_client from app.services.content_generator import ContentGenerator gen = ContentGenerator() gen._client = mock_client await gen.generate_tip_tech("test", platform) call_args = mock_client.chat.completions.create.call_args messages = call_args.kwargs.get('messages', call_args[1].get('messages', [])) user_message = messages[-1]['content'] assert str(expected_limit) in user_message