feat: Enhance WebSocket sound playback with credit validation and refactor related methods
This commit is contained in:
@@ -6,8 +6,7 @@ import pytest
|
||||
from fastapi import FastAPI
|
||||
from httpx import AsyncClient
|
||||
|
||||
from app.api.v1.sounds import get_credit_service, get_sound_repository, get_vlc_player
|
||||
from app.models.sound import Sound
|
||||
from app.api.v1.sounds import get_vlc_player
|
||||
from app.models.user import User
|
||||
|
||||
|
||||
@@ -22,32 +21,21 @@ class TestVLCEndpoints:
|
||||
authenticated_user: User,
|
||||
) -> None:
|
||||
"""Test successful sound playback via VLC."""
|
||||
# Set up mocks
|
||||
# Set up mock VLC service
|
||||
mock_vlc_service = AsyncMock()
|
||||
mock_repo = AsyncMock()
|
||||
mock_credit_service = AsyncMock()
|
||||
|
||||
# Set up test data
|
||||
mock_sound = Sound(
|
||||
id=1,
|
||||
type="SDB",
|
||||
name="Test Sound",
|
||||
filename="test.mp3",
|
||||
duration=5000,
|
||||
size=1024,
|
||||
hash="test_hash",
|
||||
)
|
||||
|
||||
# Configure mocks
|
||||
mock_repo.get_by_id.return_value = mock_sound
|
||||
mock_credit_service.validate_and_reserve_credits.return_value = None
|
||||
mock_credit_service.deduct_credits.return_value = None
|
||||
mock_vlc_service.play_sound.return_value = True
|
||||
# Set up expected response from the service method
|
||||
expected_response = {
|
||||
"message": "Sound 'Test Sound' is now playing via VLC",
|
||||
"sound_id": 1,
|
||||
"sound_name": "Test Sound",
|
||||
"success": True,
|
||||
"credits_deducted": 1,
|
||||
}
|
||||
mock_vlc_service.play_sound_with_credits.return_value = expected_response
|
||||
|
||||
# Override dependencies
|
||||
test_app.dependency_overrides[get_vlc_player] = lambda: mock_vlc_service
|
||||
test_app.dependency_overrides[get_sound_repository] = lambda: mock_repo
|
||||
test_app.dependency_overrides[get_credit_service] = lambda: mock_credit_service
|
||||
|
||||
try:
|
||||
response = await authenticated_client.post("/api/v1/sounds/play/1")
|
||||
@@ -57,15 +45,17 @@ class TestVLCEndpoints:
|
||||
assert data["sound_id"] == 1
|
||||
assert data["sound_name"] == "Test Sound"
|
||||
assert "Test Sound" in data["message"]
|
||||
assert data["success"] is True
|
||||
assert data["credits_deducted"] == 1
|
||||
|
||||
# Verify service calls
|
||||
mock_repo.get_by_id.assert_called_once_with(1)
|
||||
mock_vlc_service.play_sound.assert_called_once_with(mock_sound)
|
||||
# Verify service method was called with correct parameters
|
||||
mock_vlc_service.play_sound_with_credits.assert_called_once_with(
|
||||
1,
|
||||
authenticated_user.id,
|
||||
)
|
||||
finally:
|
||||
# Clean up dependency overrides (except get_db which is needed for other tests)
|
||||
# Clean up dependency overrides
|
||||
test_app.dependency_overrides.pop(get_vlc_player, None)
|
||||
test_app.dependency_overrides.pop(get_sound_repository, None)
|
||||
test_app.dependency_overrides.pop(get_credit_service, None)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_play_sound_with_vlc_sound_not_found(
|
||||
@@ -75,18 +65,19 @@ class TestVLCEndpoints:
|
||||
authenticated_user: User,
|
||||
) -> None:
|
||||
"""Test VLC playback when sound is not found."""
|
||||
# Set up mocks
|
||||
mock_vlc_service = AsyncMock()
|
||||
mock_repo = AsyncMock()
|
||||
mock_credit_service = AsyncMock()
|
||||
from fastapi import HTTPException
|
||||
|
||||
# Configure mocks
|
||||
mock_repo.get_by_id.return_value = None
|
||||
# Set up mock VLC service
|
||||
mock_vlc_service = AsyncMock()
|
||||
|
||||
# Configure mock to raise HTTPException for sound not found
|
||||
mock_vlc_service.play_sound_with_credits.side_effect = HTTPException(
|
||||
status_code=404,
|
||||
detail="Sound with ID 999 not found",
|
||||
)
|
||||
|
||||
# Override dependencies
|
||||
test_app.dependency_overrides[get_vlc_player] = lambda: mock_vlc_service
|
||||
test_app.dependency_overrides[get_sound_repository] = lambda: mock_repo
|
||||
test_app.dependency_overrides[get_credit_service] = lambda: mock_credit_service
|
||||
|
||||
try:
|
||||
response = await authenticated_client.post("/api/v1/sounds/play/999")
|
||||
@@ -95,10 +86,8 @@ class TestVLCEndpoints:
|
||||
data = response.json()
|
||||
assert "Sound with ID 999 not found" in data["detail"]
|
||||
finally:
|
||||
# Clean up dependency overrides (except get_db which is needed for other tests)
|
||||
# Clean up dependency overrides
|
||||
test_app.dependency_overrides.pop(get_vlc_player, None)
|
||||
test_app.dependency_overrides.pop(get_sound_repository, None)
|
||||
test_app.dependency_overrides.pop(get_credit_service, None)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_play_sound_with_vlc_launch_failure(
|
||||
@@ -108,32 +97,19 @@ class TestVLCEndpoints:
|
||||
authenticated_user: User,
|
||||
) -> None:
|
||||
"""Test VLC playback when VLC launch fails."""
|
||||
# Set up mocks
|
||||
from fastapi import HTTPException
|
||||
|
||||
# Set up mock VLC service
|
||||
mock_vlc_service = AsyncMock()
|
||||
mock_repo = AsyncMock()
|
||||
mock_credit_service = AsyncMock()
|
||||
|
||||
# Set up test data
|
||||
mock_sound = Sound(
|
||||
id=1,
|
||||
type="SDB",
|
||||
name="Test Sound",
|
||||
filename="test.mp3",
|
||||
duration=5000,
|
||||
size=1024,
|
||||
hash="test_hash",
|
||||
# Configure mock to raise HTTPException for VLC launch failure
|
||||
mock_vlc_service.play_sound_with_credits.side_effect = HTTPException(
|
||||
status_code=500,
|
||||
detail="Failed to launch VLC for sound playback",
|
||||
)
|
||||
|
||||
# Configure mocks
|
||||
mock_repo.get_by_id.return_value = mock_sound
|
||||
mock_credit_service.validate_and_reserve_credits.return_value = None
|
||||
mock_credit_service.deduct_credits.return_value = None
|
||||
mock_vlc_service.play_sound.return_value = False
|
||||
|
||||
# Override dependencies
|
||||
test_app.dependency_overrides[get_vlc_player] = lambda: mock_vlc_service
|
||||
test_app.dependency_overrides[get_sound_repository] = lambda: mock_repo
|
||||
test_app.dependency_overrides[get_credit_service] = lambda: mock_credit_service
|
||||
|
||||
try:
|
||||
response = await authenticated_client.post("/api/v1/sounds/play/1")
|
||||
@@ -142,10 +118,8 @@ class TestVLCEndpoints:
|
||||
data = response.json()
|
||||
assert "Failed to launch VLC for sound playback" in data["detail"]
|
||||
finally:
|
||||
# Clean up dependency overrides (except get_db which is needed for other tests)
|
||||
# Clean up dependency overrides
|
||||
test_app.dependency_overrides.pop(get_vlc_player, None)
|
||||
test_app.dependency_overrides.pop(get_sound_repository, None)
|
||||
test_app.dependency_overrides.pop(get_credit_service, None)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_play_sound_with_vlc_service_exception(
|
||||
@@ -155,18 +129,16 @@ class TestVLCEndpoints:
|
||||
authenticated_user: User,
|
||||
) -> None:
|
||||
"""Test VLC playback when service raises an exception."""
|
||||
# Set up mocks
|
||||
# Set up mock VLC service
|
||||
mock_vlc_service = AsyncMock()
|
||||
mock_repo = AsyncMock()
|
||||
mock_credit_service = AsyncMock()
|
||||
|
||||
# Configure mocks
|
||||
mock_repo.get_by_id.side_effect = Exception("Database error")
|
||||
# Configure mock to raise a generic exception
|
||||
mock_vlc_service.play_sound_with_credits.side_effect = Exception(
|
||||
"Database error",
|
||||
)
|
||||
|
||||
# Override dependencies
|
||||
test_app.dependency_overrides[get_vlc_player] = lambda: mock_vlc_service
|
||||
test_app.dependency_overrides[get_sound_repository] = lambda: mock_repo
|
||||
test_app.dependency_overrides[get_credit_service] = lambda: mock_credit_service
|
||||
|
||||
try:
|
||||
response = await authenticated_client.post("/api/v1/sounds/play/1")
|
||||
@@ -175,10 +147,8 @@ class TestVLCEndpoints:
|
||||
data = response.json()
|
||||
assert "Failed to play sound" in data["detail"]
|
||||
finally:
|
||||
# Clean up dependency overrides (except get_db which is needed for other tests)
|
||||
# Clean up dependency overrides
|
||||
test_app.dependency_overrides.pop(get_vlc_player, None)
|
||||
test_app.dependency_overrides.pop(get_sound_repository, None)
|
||||
test_app.dependency_overrides.pop(get_credit_service, None)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_play_sound_with_vlc_unauthenticated(
|
||||
@@ -373,32 +343,21 @@ class TestVLCEndpoints:
|
||||
admin_user: User,
|
||||
) -> None:
|
||||
"""Test VLC endpoints work with admin user."""
|
||||
# Set up mocks
|
||||
# Set up mock VLC service
|
||||
mock_vlc_service = AsyncMock()
|
||||
mock_repo = AsyncMock()
|
||||
mock_credit_service = AsyncMock()
|
||||
|
||||
# Set up test data
|
||||
mock_sound = Sound(
|
||||
id=1,
|
||||
type="SDB",
|
||||
name="Admin Test Sound",
|
||||
filename="admin_test.mp3",
|
||||
duration=3000,
|
||||
size=512,
|
||||
hash="admin_hash",
|
||||
)
|
||||
|
||||
# Configure mocks
|
||||
mock_repo.get_by_id.return_value = mock_sound
|
||||
mock_credit_service.validate_and_reserve_credits.return_value = None
|
||||
mock_credit_service.deduct_credits.return_value = None
|
||||
mock_vlc_service.play_sound.return_value = True
|
||||
# Set up expected response from the service method
|
||||
expected_response = {
|
||||
"message": "Sound 'Admin Test Sound' is now playing via VLC",
|
||||
"sound_id": 1,
|
||||
"sound_name": "Admin Test Sound",
|
||||
"success": True,
|
||||
"credits_deducted": 1,
|
||||
}
|
||||
mock_vlc_service.play_sound_with_credits.return_value = expected_response
|
||||
|
||||
# Override dependencies
|
||||
test_app.dependency_overrides[get_vlc_player] = lambda: mock_vlc_service
|
||||
test_app.dependency_overrides[get_sound_repository] = lambda: mock_repo
|
||||
test_app.dependency_overrides[get_credit_service] = lambda: mock_credit_service
|
||||
|
||||
try:
|
||||
response = await authenticated_admin_client.post("/api/v1/sounds/play/1")
|
||||
@@ -406,11 +365,15 @@ class TestVLCEndpoints:
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["sound_name"] == "Admin Test Sound"
|
||||
|
||||
# Verify service method was called with admin user ID
|
||||
mock_vlc_service.play_sound_with_credits.assert_called_once_with(
|
||||
1,
|
||||
admin_user.id,
|
||||
)
|
||||
finally:
|
||||
# Clean up dependency overrides (except get_db which is needed for other tests)
|
||||
# Clean up dependency overrides
|
||||
test_app.dependency_overrides.pop(get_vlc_player, None)
|
||||
test_app.dependency_overrides.pop(get_sound_repository, None)
|
||||
test_app.dependency_overrides.pop(get_credit_service, None)
|
||||
|
||||
# Test stop-all endpoint with admin
|
||||
mock_vlc_service_2 = AsyncMock()
|
||||
|
||||
Reference in New Issue
Block a user