Refactor test cases for improved readability and consistency
- Adjusted function signatures in various test files to enhance clarity by aligning parameters. - Updated patching syntax for better readability across test cases. - Improved formatting and spacing in test assertions and mock setups. - Ensured consistent use of async/await patterns in async test functions. - Enhanced comments for better understanding of test intentions.
This commit is contained in:
@@ -1 +1 @@
|
||||
"""Tests for admin API endpoints."""
|
||||
"""Tests for admin API endpoints."""
|
||||
|
||||
@@ -73,7 +73,9 @@ class TestAdminSoundEndpoints:
|
||||
) as mock_scan:
|
||||
mock_scan.return_value = mock_results
|
||||
|
||||
response = await authenticated_admin_client.post("/api/v1/admin/sounds/scan")
|
||||
response = await authenticated_admin_client.post(
|
||||
"/api/v1/admin/sounds/scan",
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
@@ -114,6 +116,7 @@ class TestAdminSoundEndpoints:
|
||||
) -> None:
|
||||
"""Test scanning sounds with non-admin user."""
|
||||
from fastapi import HTTPException
|
||||
|
||||
from app.core.dependencies import get_admin_user
|
||||
|
||||
# Override the admin dependency to raise 403 for non-admin users
|
||||
@@ -150,7 +153,9 @@ class TestAdminSoundEndpoints:
|
||||
) as mock_scan:
|
||||
mock_scan.side_effect = Exception("Directory not found")
|
||||
|
||||
response = await authenticated_admin_client.post("/api/v1/admin/sounds/scan")
|
||||
response = await authenticated_admin_client.post(
|
||||
"/api/v1/admin/sounds/scan",
|
||||
)
|
||||
|
||||
assert response.status_code == 500
|
||||
data = response.json()
|
||||
@@ -300,7 +305,9 @@ class TestAdminSoundEndpoints:
|
||||
assert len(results["files"]) == 3
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_normalize_all_sounds_unauthenticated(self, client: AsyncClient) -> None:
|
||||
async def test_normalize_all_sounds_unauthenticated(
|
||||
self, client: AsyncClient,
|
||||
) -> None:
|
||||
"""Test normalizing sounds without authentication."""
|
||||
response = await client.post("/api/v1/admin/sounds/normalize/all")
|
||||
|
||||
@@ -316,6 +323,7 @@ class TestAdminSoundEndpoints:
|
||||
) -> None:
|
||||
"""Test normalizing sounds with non-admin user."""
|
||||
from fastapi import HTTPException
|
||||
|
||||
from app.core.dependencies import get_admin_user
|
||||
|
||||
# Override the admin dependency to raise 403 for non-admin users
|
||||
@@ -331,7 +339,8 @@ class TestAdminSoundEndpoints:
|
||||
base_url="http://test",
|
||||
) as client:
|
||||
response = await client.post(
|
||||
"/api/v1/admin/sounds/normalize/all", headers=headers,
|
||||
"/api/v1/admin/sounds/normalize/all",
|
||||
headers=headers,
|
||||
)
|
||||
|
||||
assert response.status_code == 403
|
||||
@@ -405,7 +414,9 @@ class TestAdminSoundEndpoints:
|
||||
|
||||
# Verify the service was called with correct type
|
||||
mock_normalize.assert_called_once_with(
|
||||
sound_type="SDB", force=False, one_pass=None,
|
||||
sound_type="SDB",
|
||||
force=False,
|
||||
one_pass=None,
|
||||
)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -491,7 +502,7 @@ class TestAdminSoundEndpoints:
|
||||
) -> None:
|
||||
"""Test getting extraction processor status."""
|
||||
with patch(
|
||||
"app.services.extraction_processor.extraction_processor.get_status"
|
||||
"app.services.extraction_processor.extraction_processor.get_status",
|
||||
) as mock_get_status:
|
||||
mock_status = {
|
||||
"is_running": True,
|
||||
@@ -502,7 +513,7 @@ class TestAdminSoundEndpoints:
|
||||
mock_get_status.return_value = mock_status
|
||||
|
||||
response = await authenticated_admin_client.get(
|
||||
"/api/v1/admin/sounds/extract/status"
|
||||
"/api/v1/admin/sounds/extract/status",
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
@@ -511,7 +522,8 @@ class TestAdminSoundEndpoints:
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_extraction_processor_status_unauthenticated(
|
||||
self, client: AsyncClient
|
||||
self,
|
||||
client: AsyncClient,
|
||||
) -> None:
|
||||
"""Test getting extraction processor status without authentication."""
|
||||
response = await client.get("/api/v1/admin/sounds/extract/status")
|
||||
@@ -528,6 +540,7 @@ class TestAdminSoundEndpoints:
|
||||
) -> None:
|
||||
"""Test getting extraction processor status with non-admin user."""
|
||||
from fastapi import HTTPException
|
||||
|
||||
from app.core.dependencies import get_admin_user
|
||||
|
||||
# Override the admin dependency to raise 403 for non-admin users
|
||||
@@ -543,7 +556,8 @@ class TestAdminSoundEndpoints:
|
||||
base_url="http://test",
|
||||
) as client:
|
||||
response = await client.get(
|
||||
"/api/v1/admin/sounds/extract/status", headers=headers
|
||||
"/api/v1/admin/sounds/extract/status",
|
||||
headers=headers,
|
||||
)
|
||||
|
||||
assert response.status_code == 403
|
||||
@@ -551,4 +565,4 @@ class TestAdminSoundEndpoints:
|
||||
assert "Not enough permissions" in data["detail"]
|
||||
|
||||
# Clean up override
|
||||
test_app.dependency_overrides.pop(get_admin_user, None)
|
||||
test_app.dependency_overrides.pop(get_admin_user, None)
|
||||
|
||||
@@ -54,7 +54,11 @@ class TestApiTokenEndpoints:
|
||||
|
||||
expires_at_str = data["expires_at"]
|
||||
# Handle both ISO format with/without timezone info
|
||||
if expires_at_str.endswith("Z") or "+" in expires_at_str or expires_at_str.count("-") > 2:
|
||||
if (
|
||||
expires_at_str.endswith("Z")
|
||||
or "+" in expires_at_str
|
||||
or expires_at_str.count("-") > 2
|
||||
):
|
||||
expires_at = datetime.fromisoformat(expires_at_str)
|
||||
else:
|
||||
# Naive datetime, assume UTC
|
||||
@@ -84,7 +88,11 @@ class TestApiTokenEndpoints:
|
||||
|
||||
expires_at_str = data["expires_at"]
|
||||
# Handle both ISO format with/without timezone info
|
||||
if expires_at_str.endswith("Z") or "+" in expires_at_str or expires_at_str.count("-") > 2:
|
||||
if (
|
||||
expires_at_str.endswith("Z")
|
||||
or "+" in expires_at_str
|
||||
or expires_at_str.count("-") > 2
|
||||
):
|
||||
expires_at = datetime.fromisoformat(expires_at_str)
|
||||
else:
|
||||
# Naive datetime, assume UTC
|
||||
@@ -116,7 +124,9 @@ class TestApiTokenEndpoints:
|
||||
assert response.status_code == 422
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_generate_api_token_unauthenticated(self, client: AsyncClient) -> None:
|
||||
async def test_generate_api_token_unauthenticated(
|
||||
self, client: AsyncClient,
|
||||
) -> None:
|
||||
"""Test API token generation without authentication."""
|
||||
response = await client.post(
|
||||
"/api/v1/auth/api-token",
|
||||
@@ -186,7 +196,9 @@ class TestApiTokenEndpoints:
|
||||
assert data["is_expired"] is True
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_api_token_status_unauthenticated(self, client: AsyncClient) -> None:
|
||||
async def test_get_api_token_status_unauthenticated(
|
||||
self, client: AsyncClient,
|
||||
) -> None:
|
||||
"""Test getting API token status without authentication."""
|
||||
response = await client.get("/api/v1/auth/api-token/status")
|
||||
assert response.status_code == 401
|
||||
@@ -264,7 +276,9 @@ class TestApiTokenEndpoints:
|
||||
assert "email" in data
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_api_token_authentication_invalid_token(self, client: AsyncClient) -> None:
|
||||
async def test_api_token_authentication_invalid_token(
|
||||
self, client: AsyncClient,
|
||||
) -> None:
|
||||
"""Test authentication with invalid API token."""
|
||||
headers = {"API-TOKEN": "invalid_token"}
|
||||
response = await client.get("/api/v1/auth/me", headers=headers)
|
||||
@@ -297,7 +311,9 @@ class TestApiTokenEndpoints:
|
||||
assert "API token has expired" in data["detail"]
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_api_token_authentication_empty_token(self, client: AsyncClient) -> None:
|
||||
async def test_api_token_authentication_empty_token(
|
||||
self, client: AsyncClient,
|
||||
) -> None:
|
||||
"""Test authentication with empty API-TOKEN header."""
|
||||
# Empty token
|
||||
headers = {"API-TOKEN": ""}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
"""Tests for extraction API endpoints."""
|
||||
|
||||
|
||||
import pytest
|
||||
from httpx import AsyncClient
|
||||
|
||||
@@ -10,7 +9,9 @@ class TestExtractionEndpoints:
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_extraction_success(
|
||||
self, test_client: AsyncClient, auth_cookies: dict[str, str],
|
||||
self,
|
||||
test_client: AsyncClient,
|
||||
auth_cookies: dict[str, str],
|
||||
) -> None:
|
||||
"""Test successful extraction creation."""
|
||||
# Set cookies on client instance to avoid deprecation warning
|
||||
@@ -26,7 +27,9 @@ class TestExtractionEndpoints:
|
||||
assert response.status_code in [200, 400, 500] # Allow any non-auth error
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_extraction_unauthenticated(self, test_client: AsyncClient) -> None:
|
||||
async def test_create_extraction_unauthenticated(
|
||||
self, test_client: AsyncClient,
|
||||
) -> None:
|
||||
"""Test extraction creation without authentication."""
|
||||
response = await test_client.post(
|
||||
"/api/v1/sounds/extract",
|
||||
@@ -37,7 +40,9 @@ class TestExtractionEndpoints:
|
||||
assert response.status_code == 401
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_extraction_unauthenticated(self, test_client: AsyncClient) -> None:
|
||||
async def test_get_extraction_unauthenticated(
|
||||
self, test_client: AsyncClient,
|
||||
) -> None:
|
||||
"""Test extraction retrieval without authentication."""
|
||||
response = await test_client.get("/api/v1/sounds/extract/1")
|
||||
|
||||
@@ -46,7 +51,9 @@ class TestExtractionEndpoints:
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_processor_status_moved_to_admin(
|
||||
self, test_client: AsyncClient, admin_cookies: dict[str, str],
|
||||
self,
|
||||
test_client: AsyncClient,
|
||||
admin_cookies: dict[str, str],
|
||||
) -> None:
|
||||
"""Test that processor status endpoint was moved to admin."""
|
||||
# Set cookies on client instance to avoid deprecation warning
|
||||
@@ -61,7 +68,9 @@ class TestExtractionEndpoints:
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_user_extractions(
|
||||
self, test_client: AsyncClient, auth_cookies: dict[str, str],
|
||||
self,
|
||||
test_client: AsyncClient,
|
||||
auth_cookies: dict[str, str],
|
||||
) -> None:
|
||||
"""Test getting user extractions."""
|
||||
# Set cookies on client instance to avoid deprecation warning
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
"""Tests for playlist API endpoints."""
|
||||
|
||||
|
||||
import pytest
|
||||
import pytest_asyncio
|
||||
from httpx import AsyncClient
|
||||
@@ -348,7 +347,8 @@ class TestPlaylistEndpoints:
|
||||
}
|
||||
|
||||
response = await authenticated_client.put(
|
||||
f"/api/v1/playlists/{playlist_id}", json=payload,
|
||||
f"/api/v1/playlists/{playlist_id}",
|
||||
json=payload,
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
@@ -386,7 +386,8 @@ class TestPlaylistEndpoints:
|
||||
payload = {"name": "Updated Playlist", "description": "Updated description"}
|
||||
|
||||
response = await authenticated_client.put(
|
||||
f"/api/v1/playlists/{playlist_id}", json=payload,
|
||||
f"/api/v1/playlists/{playlist_id}",
|
||||
json=payload,
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
@@ -613,7 +614,8 @@ class TestPlaylistEndpoints:
|
||||
payload = {"sound_id": sound_id}
|
||||
|
||||
response = await authenticated_client.post(
|
||||
f"/api/v1/playlists/{playlist_id}/sounds", json=payload,
|
||||
f"/api/v1/playlists/{playlist_id}/sounds",
|
||||
json=payload,
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
@@ -670,7 +672,8 @@ class TestPlaylistEndpoints:
|
||||
payload = {"sound_id": sound_id, "position": 5}
|
||||
|
||||
response = await authenticated_client.post(
|
||||
f"/api/v1/playlists/{playlist_id}/sounds", json=payload,
|
||||
f"/api/v1/playlists/{playlist_id}/sounds",
|
||||
json=payload,
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
@@ -718,13 +721,15 @@ class TestPlaylistEndpoints:
|
||||
|
||||
# Add sound first time
|
||||
response = await authenticated_client.post(
|
||||
f"/api/v1/playlists/{playlist_id}/sounds", json=payload,
|
||||
f"/api/v1/playlists/{playlist_id}/sounds",
|
||||
json=payload,
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
# Try to add same sound again
|
||||
response = await authenticated_client.post(
|
||||
f"/api/v1/playlists/{playlist_id}/sounds", json=payload,
|
||||
f"/api/v1/playlists/{playlist_id}/sounds",
|
||||
json=payload,
|
||||
)
|
||||
assert response.status_code == 400
|
||||
assert "already in this playlist" in response.json()["detail"]
|
||||
@@ -758,7 +763,8 @@ class TestPlaylistEndpoints:
|
||||
payload = {"sound_id": 99999}
|
||||
|
||||
response = await authenticated_client.post(
|
||||
f"/api/v1/playlists/{playlist_id}/sounds", json=payload,
|
||||
f"/api/v1/playlists/{playlist_id}/sounds",
|
||||
json=payload,
|
||||
)
|
||||
|
||||
assert response.status_code == 404
|
||||
@@ -806,7 +812,8 @@ class TestPlaylistEndpoints:
|
||||
# Add sound first
|
||||
payload = {"sound_id": sound_id}
|
||||
await authenticated_client.post(
|
||||
f"/api/v1/playlists/{playlist_id}/sounds", json=payload,
|
||||
f"/api/v1/playlists/{playlist_id}/sounds",
|
||||
json=payload,
|
||||
)
|
||||
|
||||
# Remove sound
|
||||
@@ -918,11 +925,15 @@ class TestPlaylistEndpoints:
|
||||
# Reorder sounds - use positions that don't cause constraints
|
||||
# When swapping, we need to be careful about unique constraints
|
||||
payload = {
|
||||
"sound_positions": [[sound1_id, 10], [sound2_id, 5]], # Use different positions to avoid constraints
|
||||
"sound_positions": [
|
||||
[sound1_id, 10],
|
||||
[sound2_id, 5],
|
||||
], # Use different positions to avoid constraints
|
||||
}
|
||||
|
||||
response = await authenticated_client.put(
|
||||
f"/api/v1/playlists/{playlist_id}/sounds/reorder", json=payload,
|
||||
f"/api/v1/playlists/{playlist_id}/sounds/reorder",
|
||||
json=payload,
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
@@ -158,7 +158,9 @@ class TestSocketEndpoints:
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_send_message_missing_parameters(
|
||||
self, authenticated_client: AsyncClient, authenticated_user: User,
|
||||
self,
|
||||
authenticated_client: AsyncClient,
|
||||
authenticated_user: User,
|
||||
) -> None:
|
||||
"""Test sending message with missing parameters."""
|
||||
# Missing target_user_id
|
||||
@@ -177,7 +179,9 @@ class TestSocketEndpoints:
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_broadcast_message_missing_parameters(
|
||||
self, authenticated_client: AsyncClient, authenticated_user: User,
|
||||
self,
|
||||
authenticated_client: AsyncClient,
|
||||
authenticated_user: User,
|
||||
) -> None:
|
||||
"""Test broadcasting message with missing parameters."""
|
||||
response = await authenticated_client.post("/api/v1/socket/broadcast")
|
||||
@@ -185,7 +189,9 @@ class TestSocketEndpoints:
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_send_message_invalid_user_id(
|
||||
self, authenticated_client: AsyncClient, authenticated_user: User,
|
||||
self,
|
||||
authenticated_client: AsyncClient,
|
||||
authenticated_user: User,
|
||||
) -> None:
|
||||
"""Test sending message with invalid user ID."""
|
||||
response = await authenticated_client.post(
|
||||
|
||||
@@ -35,10 +35,10 @@ class TestSoundEndpoints:
|
||||
|
||||
with (
|
||||
patch(
|
||||
"app.services.extraction.ExtractionService.create_extraction"
|
||||
"app.services.extraction.ExtractionService.create_extraction",
|
||||
) as mock_create,
|
||||
patch(
|
||||
"app.services.extraction_processor.extraction_processor.queue_extraction"
|
||||
"app.services.extraction_processor.extraction_processor.queue_extraction",
|
||||
) as mock_queue,
|
||||
):
|
||||
mock_create.return_value = mock_extraction_info
|
||||
@@ -53,7 +53,10 @@ class TestSoundEndpoints:
|
||||
data = response.json()
|
||||
assert data["message"] == "Extraction queued successfully"
|
||||
assert data["extraction"]["id"] == 1
|
||||
assert data["extraction"]["url"] == "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
|
||||
assert (
|
||||
data["extraction"]["url"]
|
||||
== "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
|
||||
)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_extraction_unauthenticated(self, client: AsyncClient) -> None:
|
||||
@@ -75,7 +78,7 @@ class TestSoundEndpoints:
|
||||
) -> None:
|
||||
"""Test extraction creation with invalid URL."""
|
||||
with patch(
|
||||
"app.services.extraction.ExtractionService.create_extraction"
|
||||
"app.services.extraction.ExtractionService.create_extraction",
|
||||
) as mock_create:
|
||||
mock_create.side_effect = ValueError("Invalid URL")
|
||||
|
||||
@@ -107,7 +110,7 @@ class TestSoundEndpoints:
|
||||
}
|
||||
|
||||
with patch(
|
||||
"app.services.extraction.ExtractionService.get_extraction_by_id"
|
||||
"app.services.extraction.ExtractionService.get_extraction_by_id",
|
||||
) as mock_get:
|
||||
mock_get.return_value = mock_extraction_info
|
||||
|
||||
@@ -128,7 +131,7 @@ class TestSoundEndpoints:
|
||||
) -> None:
|
||||
"""Test getting non-existent extraction."""
|
||||
with patch(
|
||||
"app.services.extraction.ExtractionService.get_extraction_by_id"
|
||||
"app.services.extraction.ExtractionService.get_extraction_by_id",
|
||||
) as mock_get:
|
||||
mock_get.return_value = None
|
||||
|
||||
@@ -169,7 +172,7 @@ class TestSoundEndpoints:
|
||||
]
|
||||
|
||||
with patch(
|
||||
"app.services.extraction.ExtractionService.get_user_extractions"
|
||||
"app.services.extraction.ExtractionService.get_user_extractions",
|
||||
) as mock_get:
|
||||
mock_get.return_value = mock_extractions
|
||||
|
||||
@@ -202,7 +205,9 @@ class TestSoundEndpoints:
|
||||
|
||||
with (
|
||||
patch("app.repositories.sound.SoundRepository.get_by_id") as mock_get_sound,
|
||||
patch("app.services.credit.CreditService.validate_and_reserve_credits") as mock_validate,
|
||||
patch(
|
||||
"app.services.credit.CreditService.validate_and_reserve_credits",
|
||||
) as mock_validate,
|
||||
patch("app.services.vlc_player.VLCPlayerService.play_sound") as mock_play,
|
||||
patch("app.services.credit.CreditService.deduct_credits") as mock_deduct,
|
||||
):
|
||||
@@ -227,7 +232,9 @@ class TestSoundEndpoints:
|
||||
authenticated_user: User,
|
||||
) -> None:
|
||||
"""Test playing non-existent sound with VLC."""
|
||||
with patch("app.repositories.sound.SoundRepository.get_by_id") as mock_get_sound:
|
||||
with patch(
|
||||
"app.repositories.sound.SoundRepository.get_by_id",
|
||||
) as mock_get_sound:
|
||||
mock_get_sound.return_value = None
|
||||
|
||||
response = await authenticated_client.post("/api/v1/sounds/play/999")
|
||||
@@ -259,11 +266,14 @@ class TestSoundEndpoints:
|
||||
|
||||
with (
|
||||
patch("app.repositories.sound.SoundRepository.get_by_id") as mock_get_sound,
|
||||
patch("app.services.credit.CreditService.validate_and_reserve_credits") as mock_validate,
|
||||
patch(
|
||||
"app.services.credit.CreditService.validate_and_reserve_credits",
|
||||
) as mock_validate,
|
||||
):
|
||||
mock_get_sound.return_value = mock_sound
|
||||
mock_validate.side_effect = InsufficientCreditsError(
|
||||
required=1, available=0
|
||||
required=1,
|
||||
available=0,
|
||||
)
|
||||
|
||||
response = await authenticated_client.post("/api/v1/sounds/play/1")
|
||||
@@ -286,7 +296,7 @@ class TestSoundEndpoints:
|
||||
}
|
||||
|
||||
with patch(
|
||||
"app.services.vlc_player.VLCPlayerService.stop_all_vlc_instances"
|
||||
"app.services.vlc_player.VLCPlayerService.stop_all_vlc_instances",
|
||||
) as mock_stop:
|
||||
mock_stop.return_value = mock_result
|
||||
|
||||
@@ -295,4 +305,4 @@ class TestSoundEndpoints:
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["message"] == "All VLC instances stopped"
|
||||
assert data["stopped_count"] == 3
|
||||
assert data["stopped_count"] == 3
|
||||
|
||||
Reference in New Issue
Block a user