"""Tests for VLC player API endpoints.""" from unittest.mock import AsyncMock, patch import pytest from httpx import AsyncClient from app.models.sound import Sound 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, authenticated_client: AsyncClient, authenticated_user: User, ): """Test successful sound playback via VLC.""" # Mock the VLC player service and sound repository methods with patch("app.services.vlc_player.VLCPlayerService.play_sound") as mock_play_sound: mock_play_sound.return_value = True with patch("app.repositories.sound.SoundRepository.get_by_id") as mock_get_by_id: mock_sound = Sound( id=1, type="SDB", name="Test Sound", filename="test.mp3", duration=5000, size=1024, hash="test_hash", ) mock_get_by_id.return_value = mock_sound response = await authenticated_client.post("/api/v1/sounds/vlc/play/1") assert response.status_code == 200 data = response.json() assert data["success"] is True assert data["sound_id"] == 1 assert data["sound_name"] == "Test Sound" assert "Test Sound" in data["message"] # Verify service calls mock_get_by_id.assert_called_once_with(1) mock_play_sound.assert_called_once_with(mock_sound) @pytest.mark.asyncio async def test_play_sound_with_vlc_sound_not_found( self, authenticated_client: AsyncClient, authenticated_user: User, ): """Test VLC playback when sound is not found.""" # Mock the sound repository to return None with patch("app.repositories.sound.SoundRepository.get_by_id") as mock_get_by_id: mock_get_by_id.return_value = None response = await authenticated_client.post("/api/v1/sounds/vlc/play/999") assert response.status_code == 404 data = response.json() assert "Sound with ID 999 not found" in data["detail"] @pytest.mark.asyncio async def test_play_sound_with_vlc_launch_failure( self, authenticated_client: AsyncClient, authenticated_user: User, ): """Test VLC playback when VLC launch fails.""" # Mock the VLC player service to fail with patch("app.services.vlc_player.VLCPlayerService.play_sound") as mock_play_sound: mock_play_sound.return_value = False with patch("app.repositories.sound.SoundRepository.get_by_id") as mock_get_by_id: mock_sound = Sound( id=1, type="SDB", name="Test Sound", filename="test.mp3", duration=5000, size=1024, hash="test_hash", ) mock_get_by_id.return_value = mock_sound response = await authenticated_client.post("/api/v1/sounds/vlc/play/1") assert response.status_code == 500 data = response.json() assert "Failed to launch VLC for sound playback" in data["detail"] @pytest.mark.asyncio async def test_play_sound_with_vlc_service_exception( self, authenticated_client: AsyncClient, authenticated_user: User, ): """Test VLC playback when service raises an exception.""" # Mock the sound repository to raise an exception with patch("app.repositories.sound.SoundRepository.get_by_id") as mock_get_by_id: mock_get_by_id.side_effect = Exception("Database error") response = await authenticated_client.post("/api/v1/sounds/vlc/play/1") assert response.status_code == 500 data = response.json() assert "Failed to play sound" in data["detail"] @pytest.mark.asyncio async def test_play_sound_with_vlc_unauthenticated( self, client: AsyncClient, ): """Test VLC playback without authentication.""" response = await client.post("/api/v1/sounds/vlc/play/1") assert response.status_code == 401 @pytest.mark.asyncio async def test_stop_all_vlc_instances_success( self, authenticated_client: AsyncClient, authenticated_user: User, ): """Test successful stopping of all VLC instances.""" # Mock the VLC player service with patch("app.services.vlc_player.VLCPlayerService.stop_all_vlc_instances") as mock_stop_all: mock_result = { "success": True, "processes_found": 3, "processes_killed": 3, "processes_remaining": 0, "message": "Killed 3 VLC processes", } mock_stop_all.return_value = mock_result response = await authenticated_client.post("/api/v1/sounds/vlc/stop-all") 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_stop_all.assert_called_once() @pytest.mark.asyncio async def test_stop_all_vlc_instances_no_processes( self, authenticated_client: AsyncClient, authenticated_user: User, ): """Test stopping VLC instances when none are running.""" # Mock the VLC player service with patch("app.services.vlc_player.VLCPlayerService.stop_all_vlc_instances") as mock_stop_all: mock_result = { "success": True, "processes_found": 0, "processes_killed": 0, "message": "No VLC processes found", } mock_stop_all.return_value = mock_result response = await authenticated_client.post("/api/v1/sounds/vlc/stop-all") 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" @pytest.mark.asyncio async def test_stop_all_vlc_instances_partial_success( self, authenticated_client: AsyncClient, authenticated_user: User, ): """Test stopping VLC instances with partial success.""" # Mock the VLC player service with patch("app.services.vlc_player.VLCPlayerService.stop_all_vlc_instances") as mock_stop_all: mock_result = { "success": True, "processes_found": 3, "processes_killed": 2, "processes_remaining": 1, "message": "Killed 2 VLC processes", } mock_stop_all.return_value = mock_result response = await authenticated_client.post("/api/v1/sounds/vlc/stop-all") 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 @pytest.mark.asyncio async def test_stop_all_vlc_instances_failure( self, authenticated_client: AsyncClient, authenticated_user: User, ): """Test stopping VLC instances when service fails.""" # Mock the VLC player service with patch("app.services.vlc_player.VLCPlayerService.stop_all_vlc_instances") as mock_stop_all: mock_result = { "success": False, "processes_found": 0, "processes_killed": 0, "error": "Command failed", "message": "Failed to stop VLC processes", } mock_stop_all.return_value = mock_result response = await authenticated_client.post("/api/v1/sounds/vlc/stop-all") 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" @pytest.mark.asyncio async def test_stop_all_vlc_instances_service_exception( self, authenticated_client: AsyncClient, authenticated_user: User, ): """Test stopping VLC instances when service raises an exception.""" # Mock the VLC player service to raise an exception with patch("app.services.vlc_player.VLCPlayerService.stop_all_vlc_instances") as mock_stop_all: mock_stop_all.side_effect = Exception("Service error") response = await authenticated_client.post("/api/v1/sounds/vlc/stop-all") assert response.status_code == 500 data = response.json() assert "Failed to stop VLC instances" in data["detail"] @pytest.mark.asyncio async def test_stop_all_vlc_instances_unauthenticated( self, client: AsyncClient, ): """Test stopping VLC instances without authentication.""" response = await client.post("/api/v1/sounds/vlc/stop-all") assert response.status_code == 401 @pytest.mark.asyncio async def test_vlc_endpoints_with_admin_user( self, authenticated_admin_client: AsyncClient, admin_user: User, ): """Test VLC endpoints work with admin user.""" # Test play endpoint with admin with patch("app.services.vlc_player.VLCPlayerService.play_sound") as mock_play_sound: mock_play_sound.return_value = True with patch("app.repositories.sound.SoundRepository.get_by_id") as mock_get_by_id: mock_sound = Sound( id=1, type="SDB", name="Admin Test Sound", filename="admin_test.mp3", duration=3000, size=512, hash="admin_hash", ) mock_get_by_id.return_value = mock_sound response = await authenticated_admin_client.post("/api/v1/sounds/vlc/play/1") assert response.status_code == 200 data = response.json() assert data["success"] is True assert data["sound_name"] == "Admin Test Sound" # Test stop-all endpoint with admin with patch("app.services.vlc_player.VLCPlayerService.stop_all_vlc_instances") as mock_stop_all: mock_result = { "success": True, "processes_found": 1, "processes_killed": 1, "processes_remaining": 0, "message": "Killed 1 VLC processes", } mock_stop_all.return_value = mock_result response = await authenticated_admin_client.post("/api/v1/sounds/vlc/stop-all") assert response.status_code == 200 data = response.json() assert data["success"] is True assert data["processes_killed"] == 1