"""Tests for socket API endpoints.""" import pytest from httpx import AsyncClient from unittest.mock import AsyncMock, patch from app.models.user import User @pytest.fixture def mock_socket_manager(): """Mock socket manager for testing.""" with patch('app.api.v1.socket.socket_manager') as mock: mock.get_connected_users.return_value = ["1", "2", "3"] mock.send_to_user = AsyncMock(return_value=True) mock.broadcast_to_all = AsyncMock() yield mock class TestSocketEndpoints: """Test socket API endpoints.""" @pytest.mark.asyncio async def test_get_socket_status_authenticated(self, authenticated_client: AsyncClient, authenticated_user: User, mock_socket_manager): """Test getting socket status for authenticated user.""" response = await authenticated_client.get("/api/v1/socket/status") assert response.status_code == 200 data = response.json() assert "connected" in data assert "user_id" in data assert "total_connected" in data assert data["user_id"] == authenticated_user.id assert data["total_connected"] == 3 assert isinstance(data["connected"], bool) @pytest.mark.asyncio async def test_get_socket_status_unauthenticated(self, client: AsyncClient): """Test getting socket status without authentication.""" response = await client.get("/api/v1/socket/status") assert response.status_code == 401 @pytest.mark.asyncio async def test_send_message_to_user_success(self, authenticated_client: AsyncClient, authenticated_user: User, mock_socket_manager): """Test sending message to specific user successfully.""" target_user_id = 2 message = "Hello there!" response = await authenticated_client.post( "/api/v1/socket/send-message", params={"target_user_id": target_user_id, "message": message} ) assert response.status_code == 200 data = response.json() assert data["success"] is True assert data["target_user_id"] == target_user_id assert data["message"] == "Message sent" # Verify socket manager was called correctly mock_socket_manager.send_to_user.assert_called_once_with( str(target_user_id), "user_message", { "from_user_id": authenticated_user.id, "from_user_name": authenticated_user.name, "message": message, } ) @pytest.mark.asyncio async def test_send_message_to_user_not_connected(self, authenticated_client: AsyncClient, authenticated_user: User, mock_socket_manager): """Test sending message to user who is not connected.""" target_user_id = 999 message = "Hello there!" # Mock user not connected mock_socket_manager.send_to_user.return_value = False response = await authenticated_client.post( "/api/v1/socket/send-message", params={"target_user_id": target_user_id, "message": message} ) assert response.status_code == 200 data = response.json() assert data["success"] is False assert data["target_user_id"] == target_user_id assert data["message"] == "User not connected" @pytest.mark.asyncio async def test_send_message_unauthenticated(self, client: AsyncClient): """Test sending message without authentication.""" response = await client.post( "/api/v1/socket/send-message", params={"target_user_id": 1, "message": "test"} ) assert response.status_code == 401 @pytest.mark.asyncio async def test_broadcast_message_success(self, authenticated_client: AsyncClient, authenticated_user: User, mock_socket_manager): """Test broadcasting message to all users successfully.""" message = "Important announcement!" response = await authenticated_client.post( "/api/v1/socket/broadcast", params={"message": message} ) assert response.status_code == 200 data = response.json() assert data["success"] is True assert data["message"] == "Message broadcasted to all users" # Verify socket manager was called correctly mock_socket_manager.broadcast_to_all.assert_called_once_with( "broadcast_message", { "from_user_id": authenticated_user.id, "from_user_name": authenticated_user.name, "message": message, } ) @pytest.mark.asyncio async def test_broadcast_message_unauthenticated(self, client: AsyncClient): """Test broadcasting message without authentication.""" response = await client.post( "/api/v1/socket/broadcast", params={"message": "test"} ) assert response.status_code == 401 @pytest.mark.asyncio async def test_send_message_missing_parameters(self, authenticated_client: AsyncClient, authenticated_user: User): """Test sending message with missing parameters.""" # Missing target_user_id response = await authenticated_client.post( "/api/v1/socket/send-message", params={"message": "test"} ) assert response.status_code == 422 # Missing message response = await authenticated_client.post( "/api/v1/socket/send-message", params={"target_user_id": 1} ) assert response.status_code == 422 @pytest.mark.asyncio async def test_broadcast_message_missing_parameters(self, authenticated_client: AsyncClient, authenticated_user: User): """Test broadcasting message with missing parameters.""" response = await authenticated_client.post("/api/v1/socket/broadcast") assert response.status_code == 422 @pytest.mark.asyncio async def test_send_message_invalid_user_id(self, authenticated_client: AsyncClient, authenticated_user: User): """Test sending message with invalid user ID.""" response = await authenticated_client.post( "/api/v1/socket/send-message", params={"target_user_id": "invalid", "message": "test"} ) assert response.status_code == 422 @pytest.mark.asyncio async def test_socket_status_shows_user_connection(self, authenticated_client: AsyncClient, authenticated_user: User, mock_socket_manager): """Test that socket status correctly shows if user is connected.""" # Test when user is connected mock_socket_manager.get_connected_users.return_value = [str(authenticated_user.id), "2", "3"] response = await authenticated_client.get("/api/v1/socket/status") data = response.json() assert data["connected"] is True # Test when user is not connected mock_socket_manager.get_connected_users.return_value = ["2", "3", "4"] response = await authenticated_client.get("/api/v1/socket/status") data = response.json() assert data["connected"] is False