mirror of
https://github.com/xlorepdarkhelm/numinar-coding-project.git
synced 2026-09-07 03:58:24 -04:00
226 lines
8.1 KiB
Python
226 lines
8.1 KiB
Python
"""Unit tests for the backend.routers.invitees module."""
|
|
|
|
from typing import Any
|
|
from unittest.mock import ANY
|
|
from unittest.mock import AsyncMock
|
|
from unittest.mock import MagicMock
|
|
from unittest.mock import patch
|
|
|
|
import pytest
|
|
from httpx import AsyncClient
|
|
from sqlalchemy.exc import SQLAlchemyError
|
|
|
|
from backend.models import Booking
|
|
from backend.models import Invitee
|
|
from backend.models import InviteeList
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.parametrize("mock_logger", ["backend.routers.invitees"], indirect=True)
|
|
async def test_get_invitees_for_booking_success(
|
|
client: AsyncClient,
|
|
sample_booking: Booking,
|
|
sample_invitees: InviteeList,
|
|
mock_logger: MagicMock,
|
|
) -> None:
|
|
"""Test successful retrieval of all invitees for a booking.
|
|
|
|
Via GET /invitees/booking/{booking_id}. Verifies that the endpoint returns the
|
|
expected list of users with a 200 status.
|
|
|
|
Args:
|
|
client: The FastAPI test client for making HTTP requests.
|
|
sample_booking: The mocked booking object.
|
|
sample_invitees: The mocked list of invitees to return.
|
|
mock_logger: The mocked logger instance.
|
|
"""
|
|
with patch(
|
|
"backend.routers.invitees.get_invitees_for_booking", new=AsyncMock()
|
|
) as mock_get_invitees:
|
|
mock_get_invitees.return_value = sample_invitees
|
|
response = await client.get(f"/invitees/booking/{sample_booking.id}")
|
|
assert response.status_code == 200
|
|
assert response.json() == [
|
|
{
|
|
"id": invitee.id,
|
|
"booking_id": invitee.booking_id,
|
|
"user_email": invitee.user_email,
|
|
"user": {"name": invitee.user.name, "email": invitee.user.email},
|
|
}
|
|
for invitee in sample_invitees
|
|
]
|
|
mock_get_invitees.assert_called_once_with(ANY, sample_booking.id)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.parametrize("mock_logger", ["backend.routers.invitees"], indirect=True)
|
|
async def test_get_invitees_for_booking_empty(
|
|
client: AsyncClient, mock_logger: MagicMock
|
|
) -> None:
|
|
"""Test retrieval of invitees when none exist for a booking.
|
|
|
|
Via GET /invitees/booking/{booking_id}. Verifies that the endpoint returns an
|
|
empty list with a 200 status.
|
|
|
|
Args:
|
|
client: The FastAPI test client for making HTTP requests.
|
|
mock_logger: The mocked logger instance.
|
|
"""
|
|
booking_id = 1
|
|
with patch(
|
|
"backend.routers.invitees.get_invitees_for_booking", new=AsyncMock()
|
|
) as mock_get_invitees:
|
|
mock_get_invitees.return_value = []
|
|
response = await client.get(f"/invitees/booking/{booking_id}")
|
|
assert response.status_code == 200
|
|
assert response.json() == []
|
|
mock_get_invitees.assert_called_once_with(ANY, booking_id)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.parametrize("mock_logger", ["backend.routers.invitees"], indirect=True)
|
|
async def test_get_invitees_for_booking_database_error(
|
|
client: AsyncClient, mock_logger: MagicMock
|
|
) -> None:
|
|
"""Test handling of database errors in GET /invitees/booking/{booking_id}.
|
|
|
|
Verifies that the endpoint returns a 500 status on database failure.
|
|
|
|
Args:
|
|
client: The FastAPI test client for making HTTP requests.
|
|
mock_logger: The mocked logger instance.
|
|
"""
|
|
booking_id = 1
|
|
with patch(
|
|
"backend.routers.invitees.get_invitees_for_booking", new=AsyncMock()
|
|
) as mock_get_invitees:
|
|
mock_get_invitees.side_effect = SQLAlchemyError()
|
|
response = await client.get(f"/invitees/booking/{booking_id}")
|
|
assert response.status_code == 500
|
|
assert "detail" in response.json()
|
|
mock_get_invitees.assert_called_once_with(ANY, booking_id)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.parametrize("mock_logger", ["backend.routers.invitees"], indirect=True)
|
|
async def test_add_invitee_success(
|
|
client: AsyncClient,
|
|
sample_invitee: Invitee,
|
|
mock_logger: MagicMock,
|
|
) -> None:
|
|
"""Test successful addition of an invitee to a booking.
|
|
|
|
Via POST /invitees/booking/{booking_id}. Verifies that the endpoint returns the
|
|
created invitee with a 201 status.
|
|
|
|
Args:
|
|
client: The FastAPI test client for making HTTP requests.
|
|
sample_invitee: The mocked invitee object.
|
|
mock_logger: The mocked logger instance.
|
|
"""
|
|
invitee_data: dict[str, Any] = {
|
|
"booking_id": sample_invitee.booking_id,
|
|
"user_email": sample_invitee.user_email,
|
|
}
|
|
with patch(
|
|
"backend.routers.invitees.add_invitee_to_booking", new=AsyncMock()
|
|
) as mock_add_invitee:
|
|
mock_add_invitee.return_value = sample_invitee
|
|
response = await client.post(
|
|
f"/invitees/booking/{sample_invitee.booking_id}", json=invitee_data
|
|
)
|
|
assert response.status_code == 201
|
|
result = response.json()
|
|
assert result["booking_id"] == sample_invitee.booking_id
|
|
assert result["user_email"] == sample_invitee.user_email
|
|
mock_add_invitee.assert_called_once_with(
|
|
ANY, sample_invitee.booking_id, sample_invitee.user_email
|
|
)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.parametrize("mock_logger", ["backend.routers.invitees"], indirect=True)
|
|
async def test_add_invitee_database_error(
|
|
client: AsyncClient, mock_logger: MagicMock
|
|
) -> None:
|
|
"""Test handling of database errors in POST /invitees/booking/{booking_id}.
|
|
|
|
Verifies that the endpoint returns a 400 status on database failure.
|
|
|
|
Args:
|
|
client: The FastAPI test client for making HTTP requests.
|
|
mock_logger: The mocked logger instance.
|
|
"""
|
|
booking_id = 1
|
|
invitee_data: dict[str, Any] = {
|
|
"booking_id": booking_id,
|
|
"user_email": "user1@example.com",
|
|
}
|
|
with patch(
|
|
"backend.routers.invitees.add_invitee_to_booking", new=AsyncMock()
|
|
) as mock_add_invitee:
|
|
mock_add_invitee.side_effect = SQLAlchemyError()
|
|
response = await client.post(
|
|
f"/invitees/booking/{booking_id}", json=invitee_data
|
|
)
|
|
assert response.status_code == 400
|
|
assert "detail" in response.json()
|
|
mock_add_invitee.assert_called_once_with(
|
|
ANY, booking_id, invitee_data["user_email"]
|
|
)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.parametrize("mock_logger", ["backend.routers.invitees"], indirect=True)
|
|
async def test_remove_invitee_success(
|
|
client: AsyncClient, mock_logger: MagicMock
|
|
) -> None:
|
|
"""Test successful removal of an invitee from a booking.
|
|
|
|
Via DELETE /invitees/booking/{booking_id}/user/{user_email}. Verifies that the
|
|
endpoint returns a 204 status on successful deletion.
|
|
|
|
Args:
|
|
client: The FastAPI test client for making HTTP requests.
|
|
mock_logger: The mocked logger instance.
|
|
"""
|
|
booking_id = 1
|
|
user_email = "user1@example.com"
|
|
with patch(
|
|
"backend.routers.invitees.remove_invitee_from_booking", new=AsyncMock()
|
|
) as mock_remove_invitee:
|
|
response = await client.delete(
|
|
f"/invitees/booking/{booking_id}/user/{user_email}"
|
|
)
|
|
assert response.status_code == 204
|
|
assert response.text == ""
|
|
mock_remove_invitee.assert_called_once_with(ANY, booking_id, user_email)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.parametrize("mock_logger", ["backend.routers.invitees"], indirect=True)
|
|
async def test_remove_invitee_database_error(
|
|
client: AsyncClient, mock_logger: MagicMock
|
|
) -> None:
|
|
"""Test handling of database errors for delete.
|
|
|
|
Via DELETE /invitees/booking/{booking_id}/user/{user_email}. Verifies that the
|
|
endpoint returns a 500 status on database failure.
|
|
|
|
Args:
|
|
client: The FastAPI test client for making HTTP requests.
|
|
mock_logger: The mocked logger instance.
|
|
"""
|
|
booking_id = 1
|
|
user_email = "user1@example.com"
|
|
with patch(
|
|
"backend.routers.invitees.remove_invitee_from_booking", new=AsyncMock()
|
|
) as mock_remove_invitee:
|
|
mock_remove_invitee.side_effect = SQLAlchemyError()
|
|
response = await client.delete(
|
|
f"/invitees/booking/{booking_id}/user/{user_email}"
|
|
)
|
|
assert response.status_code == 500
|
|
assert "detail" in response.json()
|
|
mock_remove_invitee.assert_called_once_with(ANY, booking_id, user_email)
|