fix: ruff lint + format fixes in tests, ESLint fixes in frontend
This commit is contained in:
@@ -1,12 +1,9 @@
|
||||
"""Additional tests to improve coverage for copilot_service functions."""
|
||||
|
||||
import json
|
||||
import uuid
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
import pytest
|
||||
import pytest_asyncio
|
||||
from sqlalchemy import select
|
||||
|
||||
from app.models.copilot import CopilotChat, CopilotRole, CopilotSession
|
||||
from app.services import copilot_service
|
||||
@@ -18,18 +15,18 @@ class TestCopilotServiceCoverage:
|
||||
@pytest.mark.asyncio
|
||||
async def test_chat_calls_openrouter_and_persists(self, db_session, admin_user):
|
||||
"""chat() calls _call_openrouter_chat and persists both messages."""
|
||||
mock_content = json.dumps({
|
||||
"response": "Ich suche LKWs.",
|
||||
"actions": [{"type": "search_vehicles", "params": {"type": "lkw"}}],
|
||||
})
|
||||
mock_content = json.dumps(
|
||||
{
|
||||
"response": "Ich suche LKWs.",
|
||||
"actions": [{"type": "search_vehicles", "params": {"type": "lkw"}}],
|
||||
}
|
||||
)
|
||||
with patch(
|
||||
"app.services.copilot_service._call_openrouter_chat",
|
||||
new_callable=AsyncMock,
|
||||
return_value=mock_content,
|
||||
) as mock_chat:
|
||||
result = await copilot_service.chat(
|
||||
db_session, admin_user.id, "Zeige LKWs"
|
||||
)
|
||||
result = await copilot_service.chat(db_session, admin_user.id, "Zeige LKWs")
|
||||
|
||||
assert mock_chat.call_count == 1
|
||||
assert result["response"] == "Ich suche LKWs."
|
||||
@@ -57,7 +54,9 @@ class TestCopilotServiceCoverage:
|
||||
assert result["session_id"] == str(session.id)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_chat_with_invalid_session_id_creates_new(self, db_session, admin_user):
|
||||
async def test_chat_with_invalid_session_id_creates_new(
|
||||
self, db_session, admin_user
|
||||
):
|
||||
"""chat() with invalid session_id creates a new session."""
|
||||
mock_content = json.dumps({"response": "OK", "actions": []})
|
||||
with patch(
|
||||
@@ -79,9 +78,7 @@ class TestCopilotServiceCoverage:
|
||||
new_callable=AsyncMock,
|
||||
return_value="Das ist kein JSON.",
|
||||
):
|
||||
result = await copilot_service.chat(
|
||||
db_session, admin_user.id, "Hallo"
|
||||
)
|
||||
result = await copilot_service.chat(db_session, admin_user.id, "Hallo")
|
||||
|
||||
assert result["response"] == "Das ist kein JSON."
|
||||
assert result["actions"] == []
|
||||
@@ -89,10 +86,18 @@ class TestCopilotServiceCoverage:
|
||||
@pytest.mark.asyncio
|
||||
async def test_chat_with_code_fence_response(self, db_session, admin_user):
|
||||
"""chat() handles markdown code-fenced JSON response."""
|
||||
content = "```json\n" + json.dumps({
|
||||
"response": "Test",
|
||||
"actions": [{"type": "search_contacts", "params": {"search": "Mueller"}}],
|
||||
}) + "\n```"
|
||||
content = (
|
||||
"```json\n"
|
||||
+ json.dumps(
|
||||
{
|
||||
"response": "Test",
|
||||
"actions": [
|
||||
{"type": "search_contacts", "params": {"search": "Mueller"}}
|
||||
],
|
||||
}
|
||||
)
|
||||
+ "\n```"
|
||||
)
|
||||
with patch(
|
||||
"app.services.copilot_service._call_openrouter_chat",
|
||||
new_callable=AsyncMock,
|
||||
@@ -157,7 +162,9 @@ class TestCopilotServiceCoverage:
|
||||
assert msg.session_id == session1.id
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_history_with_invalid_session_id_ignores_filter(self, db_session, admin_user):
|
||||
async def test_get_history_with_invalid_session_id_ignores_filter(
|
||||
self, db_session, admin_user
|
||||
):
|
||||
"""get_history() ignores invalid session_id and returns all."""
|
||||
session = CopilotSession(user_id=admin_user.id, title="Test")
|
||||
db_session.add(session)
|
||||
@@ -268,7 +275,9 @@ class TestCopilotServiceCoverage:
|
||||
)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_execute_confirmed_action_create_vehicle_missing_fields(self, db_session):
|
||||
async def test_execute_confirmed_action_create_vehicle_missing_fields(
|
||||
self, db_session
|
||||
):
|
||||
"""execute_confirmed_action raises ValueError for missing required fields."""
|
||||
with pytest.raises(ValueError, match="Missing required fields"):
|
||||
await copilot_service.execute_confirmed_action(
|
||||
@@ -287,8 +296,14 @@ class TestCopilotServiceCoverage:
|
||||
@pytest.mark.asyncio
|
||||
async def test_transcribe_audio_with_api_key_calls_openrouter(self):
|
||||
"""transcribe_audio calls OpenRouter when API key is set."""
|
||||
with patch("app.services.copilot_service.settings") as mock_settings, \
|
||||
patch("app.services.copilot_service._call_openrouter_chat", new_callable=AsyncMock, return_value=" Transkribierter Text ") as mock_chat:
|
||||
with (
|
||||
patch("app.services.copilot_service.settings") as mock_settings,
|
||||
patch(
|
||||
"app.services.copilot_service._call_openrouter_chat",
|
||||
new_callable=AsyncMock,
|
||||
return_value=" Transkribierter Text ",
|
||||
) as mock_chat,
|
||||
):
|
||||
mock_settings.OPENROUTER_API_KEY = "test-key"
|
||||
result = await copilot_service.transcribe_audio(b"fake-audio", "audio/webm")
|
||||
|
||||
@@ -298,8 +313,14 @@ class TestCopilotServiceCoverage:
|
||||
@pytest.mark.asyncio
|
||||
async def test_transcribe_audio_api_error_returns_error_message(self):
|
||||
"""transcribe_audio returns error message on API failure."""
|
||||
with patch("app.services.copilot_service.settings") as mock_settings, \
|
||||
patch("app.services.copilot_service._call_openrouter_chat", new_callable=AsyncMock, side_effect=Exception("API error")):
|
||||
with (
|
||||
patch("app.services.copilot_service.settings") as mock_settings,
|
||||
patch(
|
||||
"app.services.copilot_service._call_openrouter_chat",
|
||||
new_callable=AsyncMock,
|
||||
side_effect=Exception("API error"),
|
||||
),
|
||||
):
|
||||
mock_settings.OPENROUTER_API_KEY = "test-key"
|
||||
result = await copilot_service.transcribe_audio(b"fake-audio")
|
||||
|
||||
@@ -313,14 +334,17 @@ class TestCopilotServiceCoverage:
|
||||
audio_b64 = base64.b64encode(b"fake-audio").decode("utf-8")
|
||||
mock_content = json.dumps({"response": "Antwort", "actions": []})
|
||||
|
||||
with patch(
|
||||
"app.services.copilot_service.transcribe_audio",
|
||||
new_callable=AsyncMock,
|
||||
return_value="Transkription",
|
||||
), patch(
|
||||
"app.services.copilot_service._call_openrouter_chat",
|
||||
new_callable=AsyncMock,
|
||||
return_value=mock_content,
|
||||
with (
|
||||
patch(
|
||||
"app.services.copilot_service.transcribe_audio",
|
||||
new_callable=AsyncMock,
|
||||
return_value="Transkription",
|
||||
),
|
||||
patch(
|
||||
"app.services.copilot_service._call_openrouter_chat",
|
||||
new_callable=AsyncMock,
|
||||
return_value=mock_content,
|
||||
),
|
||||
):
|
||||
result = await copilot_service.voice_chat(
|
||||
db_session, admin_user.id, audio_b64
|
||||
@@ -337,7 +361,9 @@ class TestCopilotServiceCoverage:
|
||||
"""_call_openrouter_chat raises ValueError when no API key."""
|
||||
with patch("app.services.copilot_service.settings") as mock_settings:
|
||||
mock_settings.OPENROUTER_API_KEY = ""
|
||||
with pytest.raises(ValueError, match="OPENROUTER_API_KEY is not configured"):
|
||||
with pytest.raises(
|
||||
ValueError, match="OPENROUTER_API_KEY is not configured"
|
||||
):
|
||||
await copilot_service._call_openrouter_chat([])
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -349,8 +375,10 @@ class TestCopilotServiceCoverage:
|
||||
}
|
||||
mock_response.raise_for_status = MagicMock()
|
||||
|
||||
with patch("app.services.copilot_service.settings") as mock_settings, \
|
||||
patch("app.services.copilot_service.httpx.AsyncClient") as mock_client_cls:
|
||||
with (
|
||||
patch("app.services.copilot_service.settings") as mock_settings,
|
||||
patch("app.services.copilot_service.httpx.AsyncClient") as mock_client_cls,
|
||||
):
|
||||
mock_settings.OPENROUTER_API_KEY = "test-key"
|
||||
mock_settings.OPENROUTER_BASE_URL = "https://openrouter.ai/api/v1"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user