Skip to content

Commit 138cce1

Browse files
fix: address CodeRabbit PR feedback
- test_auth_routes.py: Complete incomplete tests for /auth/me endpoint with proper assertions and dependency overrides - test_downloader.py: Remove unused dataclass import - test_feed_sync.py: Strengthen assertion in test_add_podcast_existing_returns_info - test_mcp_server.py: Fix empty test to verify module has main entry point, remove unused limit variable - test_podcast_routes.py: Mock httpx.AsyncClient in test_search_limit_clamping for deterministic testing - test_workers.py: Fix test_read_mp3_tags to test actual method behavior with a dummy file instead of mocking the method itself
1 parent 986bd67 commit 138cce1

File tree

6 files changed

+69
-36
lines changed

6 files changed

+69
-36
lines changed

tests/test_auth_routes.py

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -290,9 +290,10 @@ def test_logout_with_cookie_domain(self, app, mock_config):
290290
class TestMeRoute:
291291
"""Tests for /auth/me endpoint."""
292292

293-
@patch("src.web.auth_routes.get_current_user")
294-
def test_me_returns_user_info(self, mock_get_user, app, mock_repository):
293+
def test_me_returns_user_info(self, app, mock_repository):
295294
"""Test /me returns current user info."""
295+
from src.web.auth import get_current_user
296+
296297
mock_current_user = {
297298
"sub": "user-123",
298299
"email": "test@example.com",
@@ -305,20 +306,41 @@ def test_me_returns_user_info(self, mock_get_user, app, mock_repository):
305306
mock_repository.get_user.return_value = mock_db_user
306307

307308
# Override dependency
308-
app.dependency_overrides[
309-
__import__("src.web.auth", fromlist=["get_current_user"]).get_current_user
310-
] = lambda: mock_current_user
309+
app.dependency_overrides[get_current_user] = lambda: mock_current_user
311310

312311
client = TestClient(app, raise_server_exceptions=False)
312+
response = client.get("/auth/me")
313+
314+
assert response.status_code == 200
315+
data = response.json()
316+
assert data["email"] == "test@example.com"
317+
assert data["is_admin"] is False
313318

314-
# Mock the dependency for this specific test
315-
with patch("src.web.auth.get_current_user", return_value=mock_current_user):
316-
# We need to override at the route level
317-
pass
319+
# Clean up override
320+
app.dependency_overrides.clear()
318321

319-
@patch("src.web.auth_routes.get_current_user")
320-
def test_me_returns_admin_status(self, mock_get_user, app, mock_repository):
322+
def test_me_returns_admin_status(self, app, mock_repository):
321323
"""Test /me returns admin status from database."""
324+
from src.web.auth import get_current_user
325+
326+
mock_current_user = {
327+
"sub": "admin-123",
328+
"email": "admin@example.com",
329+
"name": "Admin User",
330+
}
331+
322332
mock_db_user = Mock()
323333
mock_db_user.is_admin = True
324334
mock_repository.get_user.return_value = mock_db_user
335+
336+
app.dependency_overrides[get_current_user] = lambda: mock_current_user
337+
338+
client = TestClient(app, raise_server_exceptions=False)
339+
response = client.get("/auth/me")
340+
341+
assert response.status_code == 200
342+
data = response.json()
343+
assert data["is_admin"] is True
344+
345+
# Clean up override
346+
app.dependency_overrides.clear()

tests/test_downloader.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
from datetime import datetime
66
from pathlib import Path
77
from unittest.mock import Mock, patch, MagicMock
8-
from dataclasses import dataclass
98

109
from src.podcast.downloader import EpisodeDownloader, DownloadResult
1110

tests/test_feed_sync.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,10 @@ def test_add_podcast_existing_returns_info(self, sync_service, mock_repository):
145145

146146
result = sync_service.add_podcast_from_url("https://example.com/feed.xml")
147147

148-
# Should return info about existing podcast
149-
assert result.get("error") is not None or result.get("podcast_id") == "existing-id"
148+
# Should return info about existing podcast with error message
149+
assert result["podcast_id"] == "existing-id"
150+
assert result["title"] == "Existing Podcast"
151+
assert "already exists" in result["error"]
150152

151153
def test_add_podcast_parse_error(self, sync_service, mock_repository):
152154
"""Test adding a podcast when parsing fails."""

tests/test_mcp_server.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,12 @@ def mock_config(self):
5656
config.GEMINI_FILE_SEARCH_STORE_NAME = "test-store"
5757
return config
5858

59-
def test_get_rag_context_decorator_exists(self):
60-
"""Test that get_rag_context tool is defined."""
61-
# Import the module to verify the tool decorator structure
62-
with patch("src.mcp_server.MCP"):
63-
with patch("src.mcp_server.Config"):
64-
pass # Module structure verified
59+
def test_mcp_server_module_has_main(self):
60+
"""Test that mcp_server module has expected entry point."""
61+
import src.mcp_server
62+
# Verify main entry point exists and is callable
63+
assert hasattr(src.mcp_server, "main")
64+
assert callable(src.mcp_server.main)
6565

6666
@patch("src.mcp_server.GeminiSearchManager")
6767
def test_search_manager_created_with_config(self, mock_search_manager_class, mock_config):
@@ -311,12 +311,11 @@ def test_search_podcasts_no_limit(self, mock_search_manager_class, mock_config):
311311
mock_search_manager_class.return_value = mock_manager
312312

313313
query = "search"
314-
limit = None
315314

316315
search_manager = mock_search_manager_class(config=mock_config, dry_run=False)
317316
results = search_manager.search_transcriptions(query, print_results=False)
318317

319-
# No limit applied
318+
# No limit applied - all results returned
320319
response = {
321320
"query": query,
322321
"results": results,

tests/test_podcast_routes.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -771,15 +771,26 @@ def test_search_http_error(self, mock_client_class, client):
771771

772772
assert response.status_code == 502
773773

774-
def test_search_limit_clamping(self, client):
774+
@patch("src.web.podcast_routes.httpx.AsyncClient")
775+
def test_search_limit_clamping(self, mock_client_class, client):
775776
"""Test search limit is clamped between 1 and 50."""
776777
test_client, _ = client
777778

778-
# This test just verifies the endpoint handles limit param
779-
# The actual clamping is tested when the iTunes API is called
779+
mock_response = Mock()
780+
mock_response.json.return_value = {"results": []}
781+
mock_response.raise_for_status = Mock()
782+
783+
mock_async_client = MagicMock()
784+
mock_async_client.__aenter__ = AsyncMock(return_value=mock_async_client)
785+
mock_async_client.__aexit__ = AsyncMock(return_value=None)
786+
mock_async_client.get = AsyncMock(return_value=mock_response)
787+
mock_client_class.return_value = mock_async_client
788+
789+
# Request with limit > 50 should be clamped
780790
response = test_client.get("/api/podcasts/search?q=test&limit=100")
781-
# Will fail because iTunes API isn't mocked, but request is valid
782-
assert response.status_code in [200, 500, 502]
791+
assert response.status_code == 200
792+
# Verify the request was made (clamping happens internally)
793+
mock_async_client.get.assert_called_once()
783794

784795

785796
class TestImportOPMLEndpoint:

tests/test_workers.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -680,15 +680,15 @@ def test_get_pending_count(self, metadata_worker, mock_repository):
680680
assert count == 2
681681
mock_repository.get_episodes_pending_metadata.assert_called_with(limit=1000)
682682

683-
def test_read_mp3_tags_success(self, metadata_worker, tmp_path):
684-
"""Test reading MP3 tags - mock the mutagen import."""
685-
with patch("src.workflow.workers.metadata.MetadataWorker._read_mp3_tags") as mock_read:
686-
mock_read.return_value = {"artist": "Test Artist", "album": "Test Album"}
687-
688-
tags = metadata_worker._read_mp3_tags("/path/to/file.mp3")
689-
690-
assert tags["artist"] == "Test Artist"
691-
assert tags["album"] == "Test Album"
683+
def test_read_mp3_tags_returns_dict(self, metadata_worker, tmp_path):
684+
"""Test that _read_mp3_tags returns a dictionary for valid MP3 files."""
685+
# Create a dummy file (not a real MP3, so mutagen will fail gracefully)
686+
dummy_file = tmp_path / "test.mp3"
687+
dummy_file.write_bytes(b"fake mp3 content")
688+
689+
# The method should return empty dict for invalid MP3 files
690+
tags = metadata_worker._read_mp3_tags(str(dummy_file))
691+
assert isinstance(tags, dict)
692692

693693
def test_read_mp3_tags_no_file(self, metadata_worker):
694694
"""Test reading MP3 tags when file doesn't exist."""

0 commit comments

Comments
 (0)