Add tests for extraction API endpoints and enhance existing tests
- Implement tests for admin extraction API endpoints including status retrieval, deletion of extractions, and permission checks. - Add tests for user extraction deletion, ensuring proper handling of permissions and non-existent extractions. - Enhance sound endpoint tests to include duplicate handling in responses. - Refactor favorite service tests to utilize mock dependencies for better maintainability and clarity. - Update sound scanner tests to improve file handling and ensure proper deletion of associated files.
This commit is contained in:
@@ -541,3 +541,143 @@ class TestExtractionService:
|
||||
assert result[0]["id"] == 1
|
||||
assert result[0]["status"] == "pending"
|
||||
assert result[0]["user_name"] == "Test User"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_delete_extraction_with_sound(self, extraction_service, test_user):
|
||||
"""Test deleting extraction with associated sound and files."""
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
# Create temporary directories for testing
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
temp_dir_path = Path(temp_dir)
|
||||
|
||||
# Set up temporary directories
|
||||
original_dir = temp_dir_path / "originals" / "extracted"
|
||||
normalized_dir = temp_dir_path / "normalized" / "extracted"
|
||||
thumbnail_dir = temp_dir_path / "thumbnails"
|
||||
|
||||
original_dir.mkdir(parents=True)
|
||||
normalized_dir.mkdir(parents=True)
|
||||
thumbnail_dir.mkdir(parents=True)
|
||||
|
||||
# Create test files
|
||||
audio_file = original_dir / "test_audio.mp3"
|
||||
normalized_file = normalized_dir / "test_audio.mp3"
|
||||
thumbnail_file = thumbnail_dir / "test_thumb.jpg"
|
||||
|
||||
audio_file.write_text("audio content")
|
||||
normalized_file.write_text("normalized content")
|
||||
thumbnail_file.write_text("thumbnail content")
|
||||
|
||||
# Create extraction and sound records
|
||||
extraction = Extraction(
|
||||
id=1,
|
||||
url="https://example.com/video",
|
||||
user_id=test_user.id,
|
||||
status="completed",
|
||||
sound_id=1,
|
||||
)
|
||||
|
||||
sound = Sound(
|
||||
id=1,
|
||||
type="EXT",
|
||||
name="Test Audio",
|
||||
filename="test_audio.mp3",
|
||||
duration=60000,
|
||||
size=2048,
|
||||
hash="test_hash",
|
||||
is_normalized=True,
|
||||
normalized_filename="test_audio.mp3",
|
||||
thumbnail="test_thumb.jpg",
|
||||
is_deletable=True,
|
||||
is_music=True,
|
||||
)
|
||||
|
||||
# Mock repository methods
|
||||
extraction_service.extraction_repo.get_by_id = AsyncMock(return_value=extraction)
|
||||
extraction_service.sound_repo.get_by_id = AsyncMock(return_value=sound)
|
||||
extraction_service.extraction_repo.delete = AsyncMock()
|
||||
extraction_service.sound_repo.delete = AsyncMock()
|
||||
extraction_service.session.commit = AsyncMock()
|
||||
extraction_service.session.rollback = AsyncMock()
|
||||
|
||||
# Monkey patch the paths in the service method
|
||||
import app.services.extraction
|
||||
original_path_class = app.services.extraction.Path
|
||||
|
||||
def mock_path(*args: str):
|
||||
path_str = str(args[0])
|
||||
if path_str == "sounds/originals/extracted":
|
||||
return original_dir
|
||||
if path_str == "sounds/normalized/extracted":
|
||||
return normalized_dir
|
||||
if path_str.endswith("thumbnails"):
|
||||
return thumbnail_dir
|
||||
return original_path_class(*args)
|
||||
|
||||
# Mock the Path constructor and settings
|
||||
with patch("app.services.extraction.Path", side_effect=mock_path), \
|
||||
patch("app.services.extraction.settings") as mock_settings:
|
||||
mock_settings.EXTRACTION_THUMBNAILS_DIR = str(thumbnail_dir)
|
||||
|
||||
# Test deletion
|
||||
result = await extraction_service.delete_extraction(1, test_user.id)
|
||||
|
||||
assert result is True
|
||||
|
||||
# Verify repository calls
|
||||
extraction_service.extraction_repo.get_by_id.assert_called_once_with(1)
|
||||
extraction_service.sound_repo.get_by_id.assert_called_once_with(1)
|
||||
extraction_service.extraction_repo.delete.assert_called_once_with(extraction)
|
||||
extraction_service.sound_repo.delete.assert_called_once_with(sound)
|
||||
extraction_service.session.commit.assert_called_once()
|
||||
|
||||
# Verify files were deleted
|
||||
assert not audio_file.exists()
|
||||
assert not normalized_file.exists()
|
||||
assert not thumbnail_file.exists()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_delete_extraction_not_found(self, extraction_service, test_user):
|
||||
"""Test deleting non-existent extraction."""
|
||||
extraction_service.extraction_repo.get_by_id = AsyncMock(return_value=None)
|
||||
|
||||
result = await extraction_service.delete_extraction(999, test_user.id)
|
||||
|
||||
assert result is False
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_delete_extraction_permission_denied(self, extraction_service, test_user):
|
||||
"""Test deleting extraction owned by another user."""
|
||||
extraction = Extraction(
|
||||
id=1,
|
||||
url="https://example.com/video",
|
||||
user_id=999, # Different user ID
|
||||
status="completed",
|
||||
)
|
||||
|
||||
extraction_service.extraction_repo.get_by_id = AsyncMock(return_value=extraction)
|
||||
|
||||
with pytest.raises(ValueError, match="You don't have permission"):
|
||||
await extraction_service.delete_extraction(1, test_user.id)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_delete_extraction_admin(self, extraction_service, test_user):
|
||||
"""Test admin deleting any extraction."""
|
||||
extraction = Extraction(
|
||||
id=1,
|
||||
url="https://example.com/video",
|
||||
user_id=999, # Different user ID
|
||||
status="completed",
|
||||
)
|
||||
|
||||
extraction_service.extraction_repo.get_by_id = AsyncMock(return_value=extraction)
|
||||
extraction_service.extraction_repo.delete = AsyncMock()
|
||||
extraction_service.session.commit = AsyncMock()
|
||||
|
||||
# Admin deletion (user_id=None)
|
||||
result = await extraction_service.delete_extraction(1, None)
|
||||
|
||||
assert result is True
|
||||
extraction_service.extraction_repo.delete.assert_called_once_with(extraction)
|
||||
|
||||
Reference in New Issue
Block a user