import pytest from unittest.mock import patch, MagicMock from app.services.ai_vision import analyze_image, summarize_url, draft_task, _extract_json def test_extract_json(): text = '```json {"key": "value"} ```' assert _extract_json(text) == {"key": "value"} text = 'Here is the result: {"a": 1}' assert _extract_json(text) == {"a": 1} assert _extract_json("Invalid") is None @pytest.mark.asyncio @patch("app.services.ai_vision._generate") @patch("app.services.ai_vision._read_image") @patch("app.services.ai_vision.settings") async def test_analyze_image_success(mock_settings, mock_read_image, mock_generate): mock_settings.AI_ENABLED = True mock_settings.AI_PROVIDER = "gemini" mock_settings.AI_TAGS_MIN = 5 mock_settings.AI_TAGS_MAX = 10 mock_read_image.return_value = (b"fake_bytes", "image/jpeg") mock_generate.return_value = { "text": '{"description": "A test image", "tags": ["tag1", "tag2"], "confidence": 0.9}', "usage": (10, 20) } result = await analyze_image("fake/path.jpg") assert result["description"] == "A test image" assert "tag1" in result["tags"] assert result["prompt_tokens"] == 10 @pytest.mark.asyncio @patch("app.services.ai_vision._generate") @patch("app.services.ai_vision.settings") async def test_summarize_url_success(mock_settings, mock_generate): mock_settings.AI_ENABLED = True mock_generate.return_value = { "text": '{"summary": "A summary", "tags": ["s1", "s2"]}', "usage": (5, 5) } result = await summarize_url("http://url", "content") assert result["summary"] == "A summary" assert "s1" in result["tags"] @pytest.mark.asyncio @patch("app.services.ai_vision._generate") @patch("app.services.ai_vision.settings") async def test_draft_task_success(mock_settings, mock_generate): mock_settings.AI_ENABLED = True mock_generate.return_value = { "text": '{"title": "Task Title", "description": "Task Desc", "steps": ["S1"]}', "usage": (5, 5) } result = await draft_task("Fix bug", "Context") assert result["title"] == "Task Title" assert "S1" in result["steps"]