222 lines
7.4 KiB
Python
222 lines
7.4 KiB
Python
"""Tests for socket API endpoints."""
|
|
|
|
from unittest.mock import AsyncMock, patch
|
|
|
|
import pytest
|
|
from httpx import AsyncClient
|
|
|
|
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,
|
|
) -> None:
|
|
"""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) -> None:
|
|
"""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,
|
|
) -> None:
|
|
"""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,
|
|
) -> None:
|
|
"""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) -> None:
|
|
"""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,
|
|
) -> None:
|
|
"""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) -> None:
|
|
"""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,
|
|
) -> None:
|
|
"""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,
|
|
) -> None:
|
|
"""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,
|
|
) -> None:
|
|
"""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,
|
|
) -> None:
|
|
"""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
|