402 lines
14 KiB
Python
402 lines
14 KiB
Python
"""Tests for VLC player API endpoints."""
|
|
|
|
from unittest.mock import AsyncMock
|
|
|
|
import pytest
|
|
from fastapi import FastAPI
|
|
from httpx import AsyncClient
|
|
|
|
from app.api.v1.sounds import get_vlc_player
|
|
from app.models.user import User
|
|
|
|
|
|
class TestVLCEndpoints:
|
|
"""Test VLC player API endpoints."""
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_play_sound_with_vlc_success(
|
|
self,
|
|
test_app: FastAPI,
|
|
authenticated_client: AsyncClient,
|
|
authenticated_user: User,
|
|
) -> None:
|
|
"""Test successful sound playback via VLC."""
|
|
# Set up mock VLC service
|
|
mock_vlc_service = AsyncMock()
|
|
|
|
# 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
|
|
|
|
try:
|
|
response = await authenticated_client.post("/api/v1/sounds/play/1")
|
|
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
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 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
|
|
test_app.dependency_overrides.pop(get_vlc_player, None)
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_play_sound_with_vlc_sound_not_found(
|
|
self,
|
|
test_app: FastAPI,
|
|
authenticated_client: AsyncClient,
|
|
authenticated_user: User,
|
|
) -> None:
|
|
"""Test VLC playback when sound is not found."""
|
|
from fastapi import HTTPException
|
|
|
|
# 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
|
|
|
|
try:
|
|
response = await authenticated_client.post("/api/v1/sounds/play/999")
|
|
|
|
assert response.status_code == 404
|
|
data = response.json()
|
|
assert "Sound with ID 999 not found" in data["detail"]
|
|
finally:
|
|
# Clean up dependency overrides
|
|
test_app.dependency_overrides.pop(get_vlc_player, None)
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_play_sound_with_vlc_launch_failure(
|
|
self,
|
|
test_app: FastAPI,
|
|
authenticated_client: AsyncClient,
|
|
authenticated_user: User,
|
|
) -> None:
|
|
"""Test VLC playback when VLC launch fails."""
|
|
from fastapi import HTTPException
|
|
|
|
# Set up mock VLC service
|
|
mock_vlc_service = AsyncMock()
|
|
|
|
# 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",
|
|
)
|
|
|
|
# Override dependencies
|
|
test_app.dependency_overrides[get_vlc_player] = lambda: mock_vlc_service
|
|
|
|
try:
|
|
response = await authenticated_client.post("/api/v1/sounds/play/1")
|
|
|
|
assert response.status_code == 500
|
|
data = response.json()
|
|
assert "Failed to launch VLC for sound playback" in data["detail"]
|
|
finally:
|
|
# Clean up dependency overrides
|
|
test_app.dependency_overrides.pop(get_vlc_player, None)
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_play_sound_with_vlc_service_exception(
|
|
self,
|
|
test_app: FastAPI,
|
|
authenticated_client: AsyncClient,
|
|
authenticated_user: User,
|
|
) -> None:
|
|
"""Test VLC playback when service raises an exception."""
|
|
# Set up mock VLC service
|
|
mock_vlc_service = AsyncMock()
|
|
|
|
# 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
|
|
|
|
try:
|
|
response = await authenticated_client.post("/api/v1/sounds/play/1")
|
|
|
|
assert response.status_code == 500
|
|
data = response.json()
|
|
assert "Failed to play sound" in data["detail"]
|
|
finally:
|
|
# Clean up dependency overrides
|
|
test_app.dependency_overrides.pop(get_vlc_player, None)
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_play_sound_with_vlc_unauthenticated(
|
|
self,
|
|
client: AsyncClient,
|
|
) -> None:
|
|
"""Test VLC playback without authentication."""
|
|
response = await client.post("/api/v1/sounds/play/1")
|
|
assert response.status_code == 401
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_stop_all_vlc_instances_success(
|
|
self,
|
|
test_app: FastAPI,
|
|
authenticated_client: AsyncClient,
|
|
authenticated_user: User,
|
|
) -> None:
|
|
"""Test successful stopping of all VLC instances."""
|
|
# Set up mock
|
|
mock_vlc_service = AsyncMock()
|
|
mock_result = {
|
|
"success": True,
|
|
"processes_found": 3,
|
|
"processes_killed": 3,
|
|
"processes_remaining": 0,
|
|
"message": "Killed 3 VLC processes",
|
|
}
|
|
mock_vlc_service.stop_all_vlc_instances.return_value = mock_result
|
|
|
|
# Override dependency
|
|
test_app.dependency_overrides[get_vlc_player] = lambda: mock_vlc_service
|
|
|
|
try:
|
|
response = await authenticated_client.post("/api/v1/sounds/stop")
|
|
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["success"] is True
|
|
assert data["processes_found"] == 3
|
|
assert data["processes_killed"] == 3
|
|
assert data["processes_remaining"] == 0
|
|
assert "Killed 3 VLC processes" in data["message"]
|
|
|
|
# Verify service call
|
|
mock_vlc_service.stop_all_vlc_instances.assert_called_once()
|
|
finally:
|
|
# Clean up dependency override
|
|
test_app.dependency_overrides.pop(get_vlc_player, None)
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_stop_all_vlc_instances_no_processes(
|
|
self,
|
|
test_app: FastAPI,
|
|
authenticated_client: AsyncClient,
|
|
authenticated_user: User,
|
|
) -> None:
|
|
"""Test stopping VLC instances when none are running."""
|
|
# Set up mock
|
|
mock_vlc_service = AsyncMock()
|
|
mock_result = {
|
|
"success": True,
|
|
"processes_found": 0,
|
|
"processes_killed": 0,
|
|
"message": "No VLC processes found",
|
|
}
|
|
mock_vlc_service.stop_all_vlc_instances.return_value = mock_result
|
|
|
|
# Override dependency
|
|
test_app.dependency_overrides[get_vlc_player] = lambda: mock_vlc_service
|
|
|
|
try:
|
|
response = await authenticated_client.post("/api/v1/sounds/stop")
|
|
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["success"] is True
|
|
assert data["processes_found"] == 0
|
|
assert data["processes_killed"] == 0
|
|
assert data["message"] == "No VLC processes found"
|
|
finally:
|
|
# Clean up dependency override
|
|
test_app.dependency_overrides.pop(get_vlc_player, None)
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_stop_all_vlc_instances_partial_success(
|
|
self,
|
|
test_app: FastAPI,
|
|
authenticated_client: AsyncClient,
|
|
authenticated_user: User,
|
|
) -> None:
|
|
"""Test stopping VLC instances with partial success."""
|
|
# Set up mock
|
|
mock_vlc_service = AsyncMock()
|
|
mock_result = {
|
|
"success": True,
|
|
"processes_found": 3,
|
|
"processes_killed": 2,
|
|
"processes_remaining": 1,
|
|
"message": "Killed 2 VLC processes",
|
|
}
|
|
mock_vlc_service.stop_all_vlc_instances.return_value = mock_result
|
|
|
|
# Override dependency
|
|
test_app.dependency_overrides[get_vlc_player] = lambda: mock_vlc_service
|
|
|
|
try:
|
|
response = await authenticated_client.post("/api/v1/sounds/stop")
|
|
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["success"] is True
|
|
assert data["processes_found"] == 3
|
|
assert data["processes_killed"] == 2
|
|
assert data["processes_remaining"] == 1
|
|
finally:
|
|
# Clean up dependency override
|
|
test_app.dependency_overrides.pop(get_vlc_player, None)
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_stop_all_vlc_instances_failure(
|
|
self,
|
|
test_app: FastAPI,
|
|
authenticated_client: AsyncClient,
|
|
authenticated_user: User,
|
|
) -> None:
|
|
"""Test stopping VLC instances when service fails."""
|
|
# Set up mock
|
|
mock_vlc_service = AsyncMock()
|
|
mock_result = {
|
|
"success": False,
|
|
"processes_found": 0,
|
|
"processes_killed": 0,
|
|
"error": "Command failed",
|
|
"message": "Failed to stop VLC processes",
|
|
}
|
|
mock_vlc_service.stop_all_vlc_instances.return_value = mock_result
|
|
|
|
# Override dependency
|
|
test_app.dependency_overrides[get_vlc_player] = lambda: mock_vlc_service
|
|
|
|
try:
|
|
response = await authenticated_client.post("/api/v1/sounds/stop")
|
|
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["success"] is False
|
|
assert data["error"] == "Command failed"
|
|
assert data["message"] == "Failed to stop VLC processes"
|
|
finally:
|
|
# Clean up dependency override
|
|
test_app.dependency_overrides.pop(get_vlc_player, None)
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_stop_all_vlc_instances_service_exception(
|
|
self,
|
|
test_app: FastAPI,
|
|
authenticated_client: AsyncClient,
|
|
authenticated_user: User,
|
|
) -> None:
|
|
"""Test stopping VLC instances when service raises an exception."""
|
|
# Set up mock to raise an exception
|
|
mock_vlc_service = AsyncMock()
|
|
mock_vlc_service.stop_all_vlc_instances.side_effect = Exception("Service error")
|
|
|
|
# Override dependency
|
|
test_app.dependency_overrides[get_vlc_player] = lambda: mock_vlc_service
|
|
|
|
try:
|
|
response = await authenticated_client.post("/api/v1/sounds/stop")
|
|
|
|
assert response.status_code == 500
|
|
data = response.json()
|
|
assert "Failed to stop VLC instances" in data["detail"]
|
|
finally:
|
|
# Clean up dependency override
|
|
test_app.dependency_overrides.pop(get_vlc_player, None)
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_stop_all_vlc_instances_unauthenticated(
|
|
self,
|
|
client: AsyncClient,
|
|
) -> None:
|
|
"""Test stopping VLC instances without authentication."""
|
|
response = await client.post("/api/v1/sounds/stop")
|
|
assert response.status_code == 401
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_vlc_endpoints_with_admin_user(
|
|
self,
|
|
test_app: FastAPI,
|
|
authenticated_admin_client: AsyncClient,
|
|
admin_user: User,
|
|
) -> None:
|
|
"""Test VLC endpoints work with admin user."""
|
|
# Set up mock VLC service
|
|
mock_vlc_service = AsyncMock()
|
|
|
|
# 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
|
|
|
|
try:
|
|
response = await authenticated_admin_client.post("/api/v1/sounds/play/1")
|
|
|
|
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
|
|
test_app.dependency_overrides.pop(get_vlc_player, None)
|
|
|
|
# Test stop-all endpoint with admin
|
|
mock_vlc_service_2 = AsyncMock()
|
|
mock_result = {
|
|
"success": True,
|
|
"processes_found": 1,
|
|
"processes_killed": 1,
|
|
"processes_remaining": 0,
|
|
"message": "Killed 1 VLC processes",
|
|
}
|
|
mock_vlc_service_2.stop_all_vlc_instances.return_value = mock_result
|
|
|
|
# Override dependency for stop-all test
|
|
test_app.dependency_overrides[get_vlc_player] = lambda: mock_vlc_service_2
|
|
|
|
try:
|
|
response = await authenticated_admin_client.post("/api/v1/sounds/stop")
|
|
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert data["success"] is True
|
|
assert data["processes_killed"] == 1
|
|
finally:
|
|
# Clean up dependency override
|
|
test_app.dependency_overrides.pop(get_vlc_player, None)
|