mirror of
https://github.com/xlorepdarkhelm/numinar-coding-project.git
synced 2026-08-19 14:08:56 -04:00
Added tests for the invitees router.
Signed-off-by: Cliff Hill <xlorep@darkhelm.org>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
"""SQL Database services for managing bookings."""
|
||||
"""SQL Database services for managing invitees."""
|
||||
|
||||
import logging
|
||||
from typing import cast
|
||||
|
||||
@@ -1,16 +1,24 @@
|
||||
"""Test configuration and fixtures for the backend tests."""
|
||||
|
||||
import logging
|
||||
from collections.abc import Generator
|
||||
from datetime import datetime
|
||||
from unittest.mock import AsyncMock
|
||||
from unittest.mock import MagicMock
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from backend.main import app
|
||||
|
||||
|
||||
type MockLogger = MagicMock
|
||||
from backend.models import Booking
|
||||
from backend.models import Invitee
|
||||
from backend.models import Room
|
||||
from backend.models import User
|
||||
from backend.services.bookings import BookingList
|
||||
from backend.services.rooms import RoomList
|
||||
from backend.services.users import UserList
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -23,3 +31,95 @@ def async_session() -> AsyncSession:
|
||||
def client() -> TestClient:
|
||||
"""Fixture to provide a FastAPI TestClient for testing endpoints."""
|
||||
return TestClient(app)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_logger(request: pytest.FixtureRequest) -> Generator[MagicMock, None, None]:
|
||||
"""Fixture to mock a logger for a specified module path.
|
||||
|
||||
Args:
|
||||
request: Pytest request object, used to pass the module path for patching.
|
||||
Provide the path via `request.param` when using the fixture.
|
||||
"""
|
||||
# Default path if none provided, or use the parameterized path
|
||||
module_path = getattr(request, "param", "backend") + ".logger"
|
||||
|
||||
mock_logger_instance = MagicMock(spec=logging.Logger)
|
||||
with patch(module_path, mock_logger_instance):
|
||||
yield mock_logger_instance
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_users() -> UserList:
|
||||
"""Fixture to provide sample User objects for testing."""
|
||||
return [
|
||||
User(email="user1@example.com", name="User One"),
|
||||
User(email="user2@example.com", name="User Two"),
|
||||
]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_rooms() -> RoomList:
|
||||
"""Fixture to provide sample Room objects for testing."""
|
||||
return [
|
||||
Room(
|
||||
id=1,
|
||||
name="Room 1",
|
||||
location="Building A",
|
||||
equipment="Projector",
|
||||
capacity=10,
|
||||
),
|
||||
Room(
|
||||
id=2,
|
||||
name="Room 2",
|
||||
location="Building B",
|
||||
equipment="Whiteboard",
|
||||
capacity=15,
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_room(sample_rooms: RoomList) -> Room:
|
||||
"""Fixture to provide a sample Room object for testing."""
|
||||
return sample_rooms[0]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_bookings(sample_room: Room) -> BookingList:
|
||||
"""Fixture to provide sample Booking objects for testing."""
|
||||
booking1 = Booking(
|
||||
room_id=1,
|
||||
start_time=datetime.fromisoformat("2025-08-25T10:00:00"),
|
||||
end_time=datetime.fromisoformat("2025-08-25T11:00:00"),
|
||||
)
|
||||
booking1.id = 1 # Manually set ID for testing purposes
|
||||
booking1.room = sample_room # Attach room relationship
|
||||
booking2 = Booking(
|
||||
room_id=1,
|
||||
start_time=datetime.fromisoformat("2025-08-25T12:00:00"),
|
||||
end_time=datetime.fromisoformat("2025-08-25T13:00:00"),
|
||||
)
|
||||
booking2.id = 2 # Manually set ID for testing purposes
|
||||
booking2.room = sample_room # Attach room relationship
|
||||
return [booking1, booking2]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_booking(sample_bookings: BookingList) -> Booking:
|
||||
"""Fixture to provide a sample Booking object for testing."""
|
||||
return sample_bookings[0]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_invitees(sample_booking: Booking, sample_users: UserList) -> list[Invitee]:
|
||||
"""Fixture to provide sample Invitee objects for testing."""
|
||||
invitee1 = Invitee(booking_id=1, user_email="user1@example.com")
|
||||
invitee1.id = 1
|
||||
invitee1.booking = sample_booking
|
||||
invitee1.user = sample_users[0]
|
||||
invitee2 = Invitee(booking_id=1, user_email="user2@example.com")
|
||||
invitee2.id = 2
|
||||
invitee2.booking = sample_booking
|
||||
invitee2.user = sample_users[1]
|
||||
return [invitee1, invitee2]
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
"""Unit tests for the backend.routers.bookings module."""
|
||||
|
||||
import logging
|
||||
from collections.abc import Generator
|
||||
from datetime import datetime
|
||||
from typing import Any
|
||||
from unittest.mock import ANY
|
||||
@@ -18,52 +16,11 @@ from backend.models import Booking
|
||||
from backend.models import Room
|
||||
from backend.services.bookings import BookingList
|
||||
|
||||
from ..conftest import MockLogger
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def mock_logger() -> Generator[MockLogger, None, None]:
|
||||
"""Fixture to mock the logger used in the bookings service."""
|
||||
mock_logger_instance = MagicMock(spec=logging.Logger)
|
||||
with patch("backend.routers.bookings.logger", mock_logger_instance):
|
||||
yield mock_logger_instance
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_room() -> Room:
|
||||
"""Fixture to provide a sample Room object for testing."""
|
||||
return Room(
|
||||
id=1,
|
||||
name="Test Room",
|
||||
location="Building A",
|
||||
equipment="Projector, Whiteboard",
|
||||
capacity=10,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_bookings(sample_room: Room) -> BookingList:
|
||||
"""Fixture to provide sample Booking objects for testing."""
|
||||
booking1 = Booking(
|
||||
room_id=1,
|
||||
start_time=datetime.fromisoformat("2025-08-25T10:00:00"),
|
||||
end_time=datetime.fromisoformat("2025-08-25T11:00:00"),
|
||||
)
|
||||
booking1.id = 1 # Manually set ID for testing purposes
|
||||
booking1.room = sample_room # Attach room relationship
|
||||
booking2 = Booking(
|
||||
room_id=1,
|
||||
start_time=datetime.fromisoformat("2025-08-25T12:00:00"),
|
||||
end_time=datetime.fromisoformat("2025-08-25T13:00:00"),
|
||||
)
|
||||
booking2.id = 2 # Manually set ID for testing purposes
|
||||
booking2.room = sample_room # Attach room relationship
|
||||
return [booking1, booking2]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.routers.bookings"], indirect=True)
|
||||
async def test_get_bookings_for_room_success(
|
||||
client: TestClient, sample_bookings: BookingList, mock_logger: MockLogger
|
||||
client: TestClient, sample_bookings: BookingList, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test successful retrieval of all bookings for a room via GET /bookings/room/{room_id}.
|
||||
|
||||
@@ -96,8 +53,9 @@ async def test_get_bookings_for_room_success(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.routers.bookings"], indirect=True)
|
||||
async def test_get_bookings_for_room_empty(
|
||||
client: TestClient, mock_logger: MockLogger
|
||||
client: TestClient, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test retrieval of bookings when none exist for a room via GET /bookings/room/{room_id}.
|
||||
|
||||
@@ -117,8 +75,9 @@ async def test_get_bookings_for_room_empty(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.routers.bookings"], indirect=True)
|
||||
async def test_get_bookings_for_room_database_error(
|
||||
client: TestClient, mock_logger: MockLogger
|
||||
client: TestClient, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of database errors in GET /bookings/room/{room_id}.
|
||||
|
||||
@@ -138,8 +97,9 @@ async def test_get_bookings_for_room_database_error(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.routers.bookings"], indirect=True)
|
||||
async def test_get_booking_success(
|
||||
client: TestClient, sample_room: Room, mock_logger: MockLogger
|
||||
client: TestClient, sample_room: Room, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test successful retrieval of a booking by ID via GET /bookings/{booking_id}.
|
||||
|
||||
@@ -171,8 +131,9 @@ async def test_get_booking_success(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.routers.bookings"], indirect=True)
|
||||
async def test_get_booking_not_found(
|
||||
client: TestClient, mock_logger: MockLogger
|
||||
client: TestClient, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of non-existent booking in GET /bookings/{booking_id}.
|
||||
|
||||
@@ -192,8 +153,9 @@ async def test_get_booking_not_found(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.routers.bookings"], indirect=True)
|
||||
async def test_get_booking_database_error(
|
||||
client: TestClient, mock_logger: MockLogger
|
||||
client: TestClient, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of database errors in GET /bookings/{booking_id}.
|
||||
|
||||
@@ -213,8 +175,9 @@ async def test_get_booking_database_error(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.routers.bookings"], indirect=True)
|
||||
async def test_create_booking_success(
|
||||
client: TestClient, sample_room: Room, mock_logger: MockLogger
|
||||
client: TestClient, sample_room: Room, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test successful creation of a new booking via POST /bookings/.
|
||||
|
||||
@@ -246,8 +209,9 @@ async def test_create_booking_success(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.routers.bookings"], indirect=True)
|
||||
async def test_create_booking_database_error(
|
||||
client: TestClient, mock_logger: MockLogger
|
||||
client: TestClient, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of database errors in POST /bookings/.
|
||||
|
||||
@@ -271,8 +235,9 @@ async def test_create_booking_database_error(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.routers.bookings"], indirect=True)
|
||||
async def test_update_booking_success(
|
||||
client: TestClient, sample_room: Room, mock_logger: MockLogger
|
||||
client: TestClient, sample_room: Room, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test successful update of a booking via PUT /bookings/{booking_id}.
|
||||
|
||||
@@ -307,8 +272,9 @@ async def test_update_booking_success(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.routers.bookings"], indirect=True)
|
||||
async def test_update_booking_not_found(
|
||||
client: TestClient, mock_logger: MockLogger
|
||||
client: TestClient, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of non-existent booking in PUT /bookings/{booking_id}.
|
||||
|
||||
@@ -335,8 +301,9 @@ async def test_update_booking_not_found(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.routers.bookings"], indirect=True)
|
||||
async def test_update_booking_database_error(
|
||||
client: TestClient, mock_logger: MockLogger
|
||||
client: TestClient, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of database errors in PUT /bookings/{booking_id}.
|
||||
|
||||
@@ -363,8 +330,9 @@ async def test_update_booking_database_error(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.routers.bookings"], indirect=True)
|
||||
async def test_delete_booking_success(
|
||||
client: TestClient, mock_logger: MockLogger
|
||||
client: TestClient, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test successful deletion of a booking via DELETE /bookings/{booking_id}.
|
||||
|
||||
@@ -382,8 +350,9 @@ async def test_delete_booking_success(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.routers.bookings"], indirect=True)
|
||||
async def test_delete_booking_not_found(
|
||||
client: TestClient, mock_logger: MockLogger
|
||||
client: TestClient, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of non-existent booking in DELETE /bookings/{booking_id}.
|
||||
|
||||
@@ -403,8 +372,9 @@ async def test_delete_booking_not_found(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.routers.bookings"], indirect=True)
|
||||
async def test_delete_booking_database_error(
|
||||
client: TestClient, mock_logger: MockLogger
|
||||
client: TestClient, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of database errors in DELETE /bookings/{booking_id}.
|
||||
|
||||
|
||||
210
backend/tests/routers/test_invitees.py
Normal file
210
backend/tests/routers/test_invitees.py
Normal file
@@ -0,0 +1,210 @@
|
||||
"""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 fastapi.testclient import TestClient
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
|
||||
from backend.models import Booking
|
||||
from backend.models import Invitee
|
||||
from backend.services.invitees import UserList
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.routers.invitees"], indirect=True)
|
||||
async def test_get_invitees_for_booking_success(
|
||||
client: TestClient, sample_users: UserList, 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.
|
||||
"""
|
||||
booking_id = 1
|
||||
with patch(
|
||||
"backend.routers.invitees.get_invitees_for_booking", new=AsyncMock()
|
||||
) as mock_get_invitees:
|
||||
mock_get_invitees.return_value = sample_users
|
||||
|
||||
response = client.get(f"/invitees/booking/{booking_id}")
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json() == [
|
||||
{"email": "user1@example.com", "name": "User One"},
|
||||
{"email": "user2@example.com", "name": "User Two"},
|
||||
]
|
||||
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_empty(
|
||||
client: TestClient, 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.
|
||||
"""
|
||||
booking_id = 1
|
||||
with patch(
|
||||
"backend.routers.invitees.get_invitees_for_booking", new=AsyncMock()
|
||||
) as mock_get_invitees:
|
||||
mock_get_invitees.return_value = []
|
||||
|
||||
response = 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: TestClient, 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.
|
||||
"""
|
||||
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 = 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: TestClient,
|
||||
sample_booking: Booking,
|
||||
sample_users: UserList,
|
||||
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.
|
||||
"""
|
||||
booking_id = 1
|
||||
invitee_data: dict[str, Any] = {
|
||||
"booking_id": booking_id,
|
||||
"user_email": "user1@example.com",
|
||||
}
|
||||
created_invitee = Invitee(**invitee_data)
|
||||
created_invitee.id = 1
|
||||
created_invitee.booking = sample_booking
|
||||
created_invitee.user = sample_users[0]
|
||||
with patch(
|
||||
"backend.routers.invitees.add_invitee_to_booking", new=AsyncMock()
|
||||
) as mock_add_invitee:
|
||||
mock_add_invitee.return_value = created_invitee
|
||||
|
||||
response = client.post(f"/invitees/booking/{booking_id}", json=invitee_data)
|
||||
|
||||
assert response.status_code == 201
|
||||
assert response.json() == {
|
||||
"id": 1,
|
||||
"booking_id": booking_id,
|
||||
"user_email": "user1@example.com",
|
||||
"booking": {
|
||||
"id": 1,
|
||||
"room_id": 1,
|
||||
"start_time": "2025-08-25T10:00:00",
|
||||
"end_time": "2025-08-25T11:00:00",
|
||||
},
|
||||
"user": {
|
||||
"email": "user1@example.com",
|
||||
"name": "User One",
|
||||
},
|
||||
}
|
||||
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_add_invitee_database_error(
|
||||
client: TestClient, 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.
|
||||
"""
|
||||
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 = 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: TestClient, 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.
|
||||
"""
|
||||
booking_id = 1
|
||||
user_email = "user1@example.com"
|
||||
with patch(
|
||||
"backend.routers.invitees.remove_invitee_from_booking", new=AsyncMock()
|
||||
) as mock_remove_invitee:
|
||||
response = 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: TestClient, 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.
|
||||
"""
|
||||
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 = 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)
|
||||
@@ -1,7 +1,5 @@
|
||||
"""Unit tests for the backend.routers.rooms module."""
|
||||
|
||||
import logging
|
||||
from collections.abc import Generator
|
||||
from typing import Any
|
||||
from unittest.mock import ANY
|
||||
from unittest.mock import AsyncMock
|
||||
@@ -15,41 +13,11 @@ from sqlalchemy.exc import NoResultFound
|
||||
from backend.models import Room
|
||||
from backend.services.rooms import RoomList
|
||||
|
||||
from ..conftest import MockLogger
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def mock_logger() -> Generator[MockLogger, None, None]:
|
||||
"""Fixture to mock the logger used in the rooms service."""
|
||||
mock_logger_instance = MagicMock(spec=logging.Logger)
|
||||
with patch("backend.routers.rooms.logger", mock_logger_instance):
|
||||
yield mock_logger_instance
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_rooms() -> RoomList:
|
||||
"""Fixture to provide sample Room objects for testing."""
|
||||
return [
|
||||
Room(
|
||||
id=1,
|
||||
name="Room 1",
|
||||
location="Building A",
|
||||
equipment="Projector",
|
||||
capacity=10,
|
||||
),
|
||||
Room(
|
||||
id=2,
|
||||
name="Room 2",
|
||||
location="Building B",
|
||||
equipment="Whiteboard",
|
||||
capacity=15,
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.routers.rooms"], indirect=True)
|
||||
async def test_get_rooms_success(
|
||||
client: TestClient, sample_rooms: RoomList, mock_logger: MockLogger
|
||||
client: TestClient, sample_rooms: RoomList, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test successful retrieval of all rooms via GET /rooms/.
|
||||
|
||||
@@ -81,7 +49,8 @@ async def test_get_rooms_success(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_rooms_empty(client: TestClient, mock_logger: MockLogger) -> None:
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.routers.rooms"], indirect=True)
|
||||
async def test_get_rooms_empty(client: TestClient, mock_logger: MagicMock) -> None:
|
||||
"""Test retrieval of rooms when none exist via GET /rooms/.
|
||||
|
||||
Verifies that the endpoint returns an empty list with a 200 status.
|
||||
@@ -97,7 +66,8 @@ async def test_get_rooms_empty(client: TestClient, mock_logger: MockLogger) -> N
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_room_success(client: TestClient, mock_logger: MockLogger) -> None:
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.routers.rooms"], indirect=True)
|
||||
async def test_get_room_success(client: TestClient, mock_logger: MagicMock) -> None:
|
||||
"""Test successful retrieval of a room by ID via GET /rooms/{room_id}.
|
||||
|
||||
Verifies that the endpoint returns the correct room with a 200 status.
|
||||
@@ -127,7 +97,8 @@ async def test_get_room_success(client: TestClient, mock_logger: MockLogger) ->
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_room_not_found(client: TestClient, mock_logger: MockLogger) -> None:
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.routers.rooms"], indirect=True)
|
||||
async def test_get_room_not_found(client: TestClient, mock_logger: MagicMock) -> None:
|
||||
"""Test handling of non-existent room in GET /rooms/{room_id}.
|
||||
|
||||
Verifies that the endpoint returns a 404 status when the room is not found.
|
||||
@@ -144,7 +115,8 @@ async def test_get_room_not_found(client: TestClient, mock_logger: MockLogger) -
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_new_room_success(client: TestClient, mock_logger: MockLogger) -> None:
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.routers.rooms"], indirect=True)
|
||||
async def test_new_room_success(client: TestClient, mock_logger: MagicMock) -> None:
|
||||
"""Test successful creation of a new room via POST /rooms/.
|
||||
|
||||
Verifies that the endpoint returns the created room with a 201 status.
|
||||
@@ -168,7 +140,8 @@ async def test_new_room_success(client: TestClient, mock_logger: MockLogger) ->
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_room_success(client: TestClient, mock_logger: MockLogger) -> None:
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.routers.rooms"], indirect=True)
|
||||
async def test_update_room_success(client: TestClient, mock_logger: MagicMock) -> None:
|
||||
"""Test successful update of a room via PUT /rooms/{room_id}.
|
||||
|
||||
Verifies that the endpoint returns the updated room with a 200 status.
|
||||
@@ -200,8 +173,9 @@ async def test_update_room_success(client: TestClient, mock_logger: MockLogger)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.routers.rooms"], indirect=True)
|
||||
async def test_update_room_not_found(
|
||||
client: TestClient, mock_logger: MockLogger
|
||||
client: TestClient, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of non-existent room in PUT /rooms/{room_id}.
|
||||
|
||||
@@ -227,7 +201,8 @@ async def test_update_room_not_found(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_delete_room_success(client: TestClient, mock_logger: MockLogger) -> None:
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.routers.rooms"], indirect=True)
|
||||
async def test_delete_room_success(client: TestClient, mock_logger: MagicMock) -> None:
|
||||
"""Test successful deletion of a room via DELETE /rooms/{room_id}.
|
||||
|
||||
Verifies that the endpoint returns a 204 status on successful deletion.
|
||||
@@ -244,8 +219,9 @@ async def test_delete_room_success(client: TestClient, mock_logger: MockLogger)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.routers.rooms"], indirect=True)
|
||||
async def test_delete_room_not_found(
|
||||
client: TestClient, mock_logger: MockLogger
|
||||
client: TestClient, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of non-existent room in DELETE /rooms/{room_id}.
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
"""Unit tests for the backend.routers.users module."""
|
||||
|
||||
import logging
|
||||
from collections.abc import Generator
|
||||
from unittest.mock import ANY
|
||||
from unittest.mock import AsyncMock
|
||||
from unittest.mock import MagicMock
|
||||
@@ -15,29 +13,11 @@ from sqlalchemy.exc import SQLAlchemyError
|
||||
from backend.models import User
|
||||
from backend.services.users import UserList
|
||||
|
||||
from ..conftest import MockLogger
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def mock_logger() -> Generator[MockLogger, None, None]:
|
||||
"""Fixture to mock the logger used in the users service."""
|
||||
mock_logger_instance = MagicMock(spec=logging.Logger)
|
||||
with patch("backend.services.users.logger", mock_logger_instance):
|
||||
yield mock_logger_instance
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_users() -> UserList:
|
||||
"""Fixture to provide sample User objects for testing."""
|
||||
return [
|
||||
User(email="user1@example.com", name="User One"),
|
||||
User(email="user2@example.com", name="User Two"),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.routers.users"], indirect=True)
|
||||
async def test_read_users_success(
|
||||
client: TestClient, sample_users: UserList, mock_logger: MockLogger
|
||||
client: TestClient, sample_users: UserList, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test successful retrieval of all users via GET /users/.
|
||||
|
||||
@@ -57,7 +37,8 @@ async def test_read_users_success(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_read_users_empty(client: TestClient, mock_logger: MockLogger) -> None:
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.routers.users"], indirect=True)
|
||||
async def test_read_users_empty(client: TestClient, mock_logger: MagicMock) -> None:
|
||||
"""Test retrieval of users when none exist via GET /users/.
|
||||
|
||||
Verifies that the endpoint returns an empty list with a 200 status.
|
||||
@@ -73,8 +54,9 @@ async def test_read_users_empty(client: TestClient, mock_logger: MockLogger) ->
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.routers.users"], indirect=True)
|
||||
async def test_read_users_database_error(
|
||||
client: TestClient, mock_logger: MockLogger
|
||||
client: TestClient, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of database errors in GET /users/.
|
||||
|
||||
@@ -91,6 +73,7 @@ async def test_read_users_database_error(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.routers.users"], indirect=True)
|
||||
@pytest.mark.parametrize(
|
||||
"email, expected_name",
|
||||
[
|
||||
@@ -100,7 +83,7 @@ async def test_read_users_database_error(
|
||||
ids=["user1", "user2"],
|
||||
)
|
||||
async def test_read_user_success(
|
||||
client: TestClient, email: str, expected_name: str, mock_logger: MockLogger
|
||||
client: TestClient, email: str, expected_name: str, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test successful retrieval of a user by email via GET /users/{email}.
|
||||
|
||||
@@ -118,13 +101,14 @@ async def test_read_user_success(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.routers.users"], indirect=True)
|
||||
@pytest.mark.parametrize(
|
||||
"email",
|
||||
["nonexistent@example.com", "invalid@domain.com"],
|
||||
ids=["nonexistent_email", "invalid_email"],
|
||||
)
|
||||
async def test_read_user_not_found(
|
||||
client: TestClient, email: str, mock_logger: MockLogger
|
||||
client: TestClient, email: str, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of non-existent user in GET /users/{email}.
|
||||
|
||||
@@ -141,8 +125,9 @@ async def test_read_user_not_found(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.routers.users"], indirect=True)
|
||||
async def test_read_user_database_error(
|
||||
client: TestClient, mock_logger: MockLogger
|
||||
client: TestClient, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of database errors in GET /users/{email}.
|
||||
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
"""Unit tests for the backend.services.bookings module."""
|
||||
|
||||
import logging
|
||||
from collections.abc import Generator
|
||||
from datetime import datetime
|
||||
from typing import Any
|
||||
from unittest.mock import AsyncMock
|
||||
from unittest.mock import MagicMock
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
from sqlalchemy import delete
|
||||
@@ -24,38 +21,11 @@ from backend.services.bookings import get_bookings_for_room
|
||||
from backend.services.bookings import new_booking
|
||||
from backend.services.bookings import update_booking
|
||||
|
||||
from ..conftest import MockLogger
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def mock_logger() -> Generator[MockLogger, None, None]:
|
||||
"""Fixture to mock the logger used in the bookings service."""
|
||||
mock_logger_instance = MagicMock(spec=logging.Logger)
|
||||
with patch("backend.services.bookings.logger", mock_logger_instance):
|
||||
yield mock_logger_instance
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_bookings() -> BookingList:
|
||||
"""Fixture to provide sample Booking objects for testing."""
|
||||
booking1 = Booking(
|
||||
room_id=1,
|
||||
start_time=datetime(2025, 8, 24, 10, 0),
|
||||
end_time=datetime(2025, 8, 24, 12, 0),
|
||||
)
|
||||
booking1.id = 1
|
||||
booking2 = Booking(
|
||||
room_id=1,
|
||||
start_time=datetime(2025, 8, 24, 13, 0),
|
||||
end_time=datetime(2025, 8, 24, 15, 0),
|
||||
)
|
||||
booking2.id = 2
|
||||
return [booking1, booking2]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.bookings"], indirect=True)
|
||||
async def test_get_bookings_for_room_success(
|
||||
async_session: AsyncSession, sample_bookings: BookingList, mock_logger: MockLogger
|
||||
async_session: AsyncSession, sample_bookings: BookingList, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test successful retrieval of all bookings for a room.
|
||||
|
||||
@@ -80,8 +50,9 @@ async def test_get_bookings_for_room_success(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.bookings"], indirect=True)
|
||||
async def test_get_bookings_for_room_empty(
|
||||
async_session: AsyncSession, mock_logger: MockLogger
|
||||
async_session: AsyncSession, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test retrieval of bookings when none exist for the room.
|
||||
|
||||
@@ -104,8 +75,9 @@ async def test_get_bookings_for_room_empty(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.bookings"], indirect=True)
|
||||
async def test_get_bookings_for_room_database_error(
|
||||
async_session: AsyncSession, mock_logger: MockLogger
|
||||
async_session: AsyncSession, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of database errors in get_bookings_for_room.
|
||||
|
||||
@@ -120,6 +92,7 @@ async def test_get_bookings_for_room_database_error(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.bookings"], indirect=True)
|
||||
@pytest.mark.parametrize(
|
||||
"booking_id, expected_room_id",
|
||||
[
|
||||
@@ -132,7 +105,7 @@ async def test_get_booking_success(
|
||||
async_session: AsyncSession,
|
||||
booking_id: int,
|
||||
expected_room_id: int,
|
||||
mock_logger: MockLogger,
|
||||
mock_logger: MagicMock,
|
||||
) -> None:
|
||||
"""Test successful retrieval of a booking by ID.
|
||||
|
||||
@@ -157,13 +130,14 @@ async def test_get_booking_success(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.bookings"], indirect=True)
|
||||
@pytest.mark.parametrize(
|
||||
"booking_id",
|
||||
[999, -1],
|
||||
ids=["nonexistent_id", "invalid_id"],
|
||||
)
|
||||
async def test_get_booking_not_found(
|
||||
async_session: AsyncSession, mock_logger: MockLogger, booking_id: int
|
||||
async_session: AsyncSession, mock_logger: MagicMock, booking_id: int
|
||||
) -> None:
|
||||
"""Test handling of non-existent booking in get_booking.
|
||||
|
||||
@@ -180,8 +154,9 @@ async def test_get_booking_not_found(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.bookings"], indirect=True)
|
||||
async def test_get_booking_database_error(
|
||||
async_session: AsyncSession, mock_logger: MockLogger
|
||||
async_session: AsyncSession, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of database errors in get_booking.
|
||||
|
||||
@@ -199,8 +174,9 @@ async def test_get_booking_database_error(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.bookings"], indirect=True)
|
||||
async def test_new_booking_success(
|
||||
async_session: AsyncSession, mock_logger: MockLogger
|
||||
async_session: AsyncSession, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test successful creation of a new booking.
|
||||
|
||||
@@ -223,8 +199,9 @@ async def test_new_booking_success(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.bookings"], indirect=True)
|
||||
async def test_new_booking_database_error(
|
||||
async_session: AsyncSession, mock_logger: MockLogger
|
||||
async_session: AsyncSession, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of database errors in new_booking.
|
||||
|
||||
@@ -248,8 +225,9 @@ async def test_new_booking_database_error(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.bookings"], indirect=True)
|
||||
async def test_update_booking_success(
|
||||
async_session: AsyncSession, mock_logger: MockLogger
|
||||
async_session: AsyncSession, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test successful update of a booking.
|
||||
|
||||
@@ -284,8 +262,9 @@ async def test_update_booking_success(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.bookings"], indirect=True)
|
||||
async def test_update_booking_not_found(
|
||||
async_session: AsyncSession, mock_logger: MockLogger
|
||||
async_session: AsyncSession, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of non-existent booking in update_booking.
|
||||
|
||||
@@ -311,8 +290,9 @@ async def test_update_booking_not_found(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.bookings"], indirect=True)
|
||||
async def test_update_booking_database_error(
|
||||
async_session: AsyncSession, mock_logger: MockLogger
|
||||
async_session: AsyncSession, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of database errors in update_booking.
|
||||
|
||||
@@ -337,8 +317,9 @@ async def test_update_booking_database_error(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.bookings"], indirect=True)
|
||||
async def test_delete_booking_success(
|
||||
async_session: AsyncSession, mock_logger: MockLogger
|
||||
async_session: AsyncSession, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test successful deletion of a booking.
|
||||
|
||||
@@ -359,8 +340,9 @@ async def test_delete_booking_success(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.bookings"], indirect=True)
|
||||
async def test_delete_booking_not_found(
|
||||
async_session: AsyncSession, mock_logger: MockLogger
|
||||
async_session: AsyncSession, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of non-existent booking in delete_booking.
|
||||
|
||||
@@ -381,8 +363,9 @@ async def test_delete_booking_not_found(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.bookings"], indirect=True)
|
||||
async def test_delete_booking_database_error(
|
||||
async_session: AsyncSession, mock_logger: MockLogger
|
||||
async_session: AsyncSession, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of database errors in delete_booking.
|
||||
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
"""Unit tests for the backend.services.invitees module."""
|
||||
|
||||
import logging
|
||||
from collections.abc import Generator
|
||||
from unittest.mock import AsyncMock
|
||||
from unittest.mock import MagicMock
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
from sqlalchemy import delete
|
||||
@@ -13,35 +10,16 @@ from sqlalchemy.exc import SQLAlchemyError
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from backend.models import Invitee
|
||||
from backend.models import User
|
||||
from backend.services.invitees import UserList
|
||||
from backend.services.invitees import add_invitee_to_booking
|
||||
from backend.services.invitees import get_invitees_for_booking
|
||||
from backend.services.invitees import remove_invitee_from_booking
|
||||
|
||||
from ..conftest import MockLogger
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def mock_logger() -> Generator[MockLogger, None, None]:
|
||||
"""Fixture to mock the logger used in the invitees service."""
|
||||
mock_logger_instance = MagicMock(spec=logging.Logger)
|
||||
with patch("backend.services.invitees.logger", mock_logger_instance):
|
||||
yield mock_logger_instance
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_invitees() -> UserList:
|
||||
"""Fixture to provide sample User objects for testing invitees."""
|
||||
return [
|
||||
User(email="user1@example.com", name="User One"),
|
||||
User(email="user2@example.com", name="User Two"),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.invitees"], indirect=True)
|
||||
async def test_get_invitees_for_booking_success(
|
||||
async_session: AsyncSession, sample_invitees: UserList, mock_logger: MockLogger
|
||||
async_session: AsyncSession, sample_invitees: UserList, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test successful retrieval of all invitees for a booking.
|
||||
|
||||
@@ -66,8 +44,9 @@ async def test_get_invitees_for_booking_success(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.invitees"], indirect=True)
|
||||
async def test_get_invitees_for_booking_empty(
|
||||
async_session: AsyncSession, mock_logger: MockLogger
|
||||
async_session: AsyncSession, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test retrieval of invitees when none exist for the booking.
|
||||
|
||||
@@ -90,8 +69,9 @@ async def test_get_invitees_for_booking_empty(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.invitees"], indirect=True)
|
||||
async def test_get_invitees_for_booking_database_error(
|
||||
async_session: AsyncSession, mock_logger: MockLogger
|
||||
async_session: AsyncSession, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of database errors in get_invitees_for_booking.
|
||||
|
||||
@@ -106,6 +86,7 @@ async def test_get_invitees_for_booking_database_error(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.invitees"], indirect=True)
|
||||
@pytest.mark.parametrize(
|
||||
"booking_id, user_email",
|
||||
[
|
||||
@@ -118,7 +99,7 @@ async def test_add_invitee_to_booking_success(
|
||||
async_session: AsyncSession,
|
||||
booking_id: int,
|
||||
user_email: str,
|
||||
mock_logger: MockLogger,
|
||||
mock_logger: MagicMock,
|
||||
) -> None:
|
||||
"""Test successful addition of an invitee to a booking.
|
||||
|
||||
@@ -141,8 +122,9 @@ async def test_add_invitee_to_booking_success(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.invitees"], indirect=True)
|
||||
async def test_add_invitee_to_booking_database_error(
|
||||
async_session: AsyncSession, mock_logger: MockLogger
|
||||
async_session: AsyncSession, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of database errors in add_invitee_to_booking.
|
||||
|
||||
@@ -163,6 +145,7 @@ async def test_add_invitee_to_booking_database_error(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.invitees"], indirect=True)
|
||||
@pytest.mark.parametrize(
|
||||
"booking_id, user_email",
|
||||
[
|
||||
@@ -175,7 +158,7 @@ async def test_remove_invitee_from_booking_success(
|
||||
async_session: AsyncSession,
|
||||
booking_id: int,
|
||||
user_email: str,
|
||||
mock_logger: MockLogger,
|
||||
mock_logger: MagicMock,
|
||||
) -> None:
|
||||
"""Test successful removal of an invitee from a booking.
|
||||
|
||||
@@ -197,8 +180,9 @@ async def test_remove_invitee_from_booking_success(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.invitees"], indirect=True)
|
||||
async def test_remove_invitee_from_booking_database_error(
|
||||
async_session: AsyncSession, mock_logger: MockLogger
|
||||
async_session: AsyncSession, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of database errors in remove_invitee_from_booking.
|
||||
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
"""Unit tests for the backend.services.rooms module."""
|
||||
|
||||
import logging
|
||||
from collections.abc import Generator
|
||||
from typing import Any
|
||||
from unittest.mock import AsyncMock
|
||||
from unittest.mock import MagicMock
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
from sqlalchemy import delete
|
||||
@@ -23,41 +20,11 @@ from backend.services.rooms import get_rooms
|
||||
from backend.services.rooms import new_room
|
||||
from backend.services.rooms import update_room
|
||||
|
||||
from ..conftest import MockLogger
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def mock_logger() -> Generator[MockLogger, None, None]:
|
||||
"""Fixture to mock the logger used in the rooms service."""
|
||||
mock_logger_instance = MagicMock(spec=logging.Logger)
|
||||
with patch("backend.services.rooms.logger", mock_logger_instance):
|
||||
yield mock_logger_instance
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_rooms() -> RoomList:
|
||||
"""Fixture to provide sample Room objects for testing."""
|
||||
return [
|
||||
Room(
|
||||
id=1,
|
||||
name="Room A",
|
||||
location="Building 1",
|
||||
equipment="Projector",
|
||||
capacity=10,
|
||||
),
|
||||
Room(
|
||||
id=2,
|
||||
name="Room B",
|
||||
location="Building 2",
|
||||
equipment="Whiteboard",
|
||||
capacity=20,
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.rooms"], indirect=True)
|
||||
async def test_get_rooms_success(
|
||||
async_session: AsyncSession, sample_rooms: RoomList, mock_logger: MockLogger
|
||||
async_session: AsyncSession, sample_rooms: RoomList, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test successful retrieval of all rooms from the database.
|
||||
|
||||
@@ -79,8 +46,9 @@ async def test_get_rooms_success(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.rooms"], indirect=True)
|
||||
async def test_get_rooms_empty(
|
||||
async_session: AsyncSession, mock_logger: MockLogger
|
||||
async_session: AsyncSession, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test retrieval of rooms when the database is empty.
|
||||
|
||||
@@ -100,8 +68,9 @@ async def test_get_rooms_empty(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.rooms"], indirect=True)
|
||||
async def test_get_rooms_database_error(
|
||||
async_session: AsyncSession, mock_logger: MockLogger
|
||||
async_session: AsyncSession, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of database errors in get_rooms.
|
||||
|
||||
@@ -115,6 +84,7 @@ async def test_get_rooms_database_error(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.rooms"], indirect=True)
|
||||
@pytest.mark.parametrize(
|
||||
"room_id, expected_name",
|
||||
[
|
||||
@@ -127,7 +97,7 @@ async def test_get_room_success(
|
||||
async_session: AsyncSession,
|
||||
room_id: int,
|
||||
expected_name: str,
|
||||
mock_logger: MockLogger,
|
||||
mock_logger: MagicMock,
|
||||
) -> None:
|
||||
"""Test successful retrieval of a room by ID.
|
||||
|
||||
@@ -153,13 +123,14 @@ async def test_get_room_success(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.rooms"], indirect=True)
|
||||
@pytest.mark.parametrize(
|
||||
"room_id",
|
||||
[999, -1],
|
||||
ids=["nonexistent_id", "invalid_id"],
|
||||
)
|
||||
async def test_get_room_not_found(
|
||||
async_session: AsyncSession, mock_logger: MockLogger, room_id: int
|
||||
async_session: AsyncSession, mock_logger: MagicMock, room_id: int
|
||||
) -> None:
|
||||
"""Test handling of non-existent room in get_room.
|
||||
|
||||
@@ -176,8 +147,9 @@ async def test_get_room_not_found(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.rooms"], indirect=True)
|
||||
async def test_get_room_database_error(
|
||||
async_session: AsyncSession, mock_logger: MockLogger
|
||||
async_session: AsyncSession, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of database errors in get_room.
|
||||
|
||||
@@ -195,8 +167,9 @@ async def test_get_room_database_error(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.rooms"], indirect=True)
|
||||
async def test_new_room_success(
|
||||
async_session: AsyncSession, mock_logger: MockLogger
|
||||
async_session: AsyncSession, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test successful creation of a new room.
|
||||
|
||||
@@ -216,8 +189,9 @@ async def test_new_room_success(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.rooms"], indirect=True)
|
||||
async def test_new_room_database_error(
|
||||
async_session: AsyncSession, mock_logger: MockLogger
|
||||
async_session: AsyncSession, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of database errors in new_room.
|
||||
|
||||
@@ -239,8 +213,9 @@ async def test_new_room_database_error(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.rooms"], indirect=True)
|
||||
async def test_update_room_success(
|
||||
async_session: AsyncSession, mock_logger: MockLogger
|
||||
async_session: AsyncSession, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test successful update of a room.
|
||||
|
||||
@@ -275,8 +250,9 @@ async def test_update_room_success(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.rooms"], indirect=True)
|
||||
async def test_update_room_not_found(
|
||||
async_session: AsyncSession, mock_logger: MockLogger
|
||||
async_session: AsyncSession, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of non-existent room in update_room.
|
||||
|
||||
@@ -303,8 +279,9 @@ async def test_update_room_not_found(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.rooms"], indirect=True)
|
||||
async def test_update_room_database_error(
|
||||
async_session: AsyncSession, mock_logger: MockLogger
|
||||
async_session: AsyncSession, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of database errors in update_room.
|
||||
|
||||
@@ -330,8 +307,9 @@ async def test_update_room_database_error(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.rooms"], indirect=True)
|
||||
async def test_delete_room_success(
|
||||
async_session: AsyncSession, mock_logger: MockLogger
|
||||
async_session: AsyncSession, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test successful deletion of a room.
|
||||
|
||||
@@ -352,8 +330,9 @@ async def test_delete_room_success(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.rooms"], indirect=True)
|
||||
async def test_delete_room_not_found(
|
||||
async_session: AsyncSession, mock_logger: MockLogger
|
||||
async_session: AsyncSession, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of non-existent room in delete_room.
|
||||
|
||||
@@ -374,8 +353,9 @@ async def test_delete_room_not_found(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.rooms"], indirect=True)
|
||||
async def test_delete_room_database_error(
|
||||
async_session: AsyncSession, mock_logger: MockLogger
|
||||
async_session: AsyncSession, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of database errors in delete_room.
|
||||
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
"""Unit tests for the backend.services.users module."""
|
||||
|
||||
import logging
|
||||
from collections.abc import Generator
|
||||
from unittest.mock import AsyncMock
|
||||
from unittest.mock import MagicMock
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
from sqlalchemy import select
|
||||
@@ -17,29 +14,11 @@ from backend.services.users import UserList
|
||||
from backend.services.users import get_user
|
||||
from backend.services.users import get_users
|
||||
|
||||
from ..conftest import MockLogger
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def mock_logger() -> Generator[MockLogger, None, None]:
|
||||
"""Fixture to mock the logger used in the users service."""
|
||||
mock_logger_instance = MagicMock(spec=logging.Logger)
|
||||
with patch("backend.services.users.logger", mock_logger_instance):
|
||||
yield mock_logger_instance
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_users() -> UserList:
|
||||
"""Fixture to provide sample User objects for testing."""
|
||||
return [
|
||||
User(email="user1@example.com", name="User One"),
|
||||
User(email="user2@example.com", name="User Two"),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.users"], indirect=True)
|
||||
async def test_get_users_success(
|
||||
async_session: AsyncSession, sample_users: UserList, mock_logger: MockLogger
|
||||
async_session: AsyncSession, sample_users: UserList, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test successful retrieval of all users from the database.
|
||||
|
||||
@@ -61,8 +40,9 @@ async def test_get_users_success(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.users"], indirect=True)
|
||||
async def test_get_users_empty(
|
||||
async_session: AsyncSession, mock_logger: MockLogger
|
||||
async_session: AsyncSession, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test retrieval of users when the database is empty.
|
||||
|
||||
@@ -82,8 +62,9 @@ async def test_get_users_empty(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.users"], indirect=True)
|
||||
async def test_get_users_database_error(
|
||||
async_session: AsyncSession, mock_logger: MockLogger
|
||||
async_session: AsyncSession, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of database errors in get_users.
|
||||
|
||||
@@ -97,6 +78,7 @@ async def test_get_users_database_error(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.users"], indirect=True)
|
||||
@pytest.mark.parametrize(
|
||||
"email, expected_name",
|
||||
[
|
||||
@@ -106,7 +88,7 @@ async def test_get_users_database_error(
|
||||
ids=["user1", "user2"],
|
||||
)
|
||||
async def test_get_user_success(
|
||||
async_session: AsyncSession, email: str, expected_name: str, mock_logger: MockLogger
|
||||
async_session: AsyncSession, email: str, expected_name: str, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test successful retrieval of a user by email.
|
||||
|
||||
@@ -126,6 +108,7 @@ async def test_get_user_success(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.users"], indirect=True)
|
||||
@pytest.mark.parametrize(
|
||||
"email",
|
||||
[
|
||||
@@ -135,7 +118,7 @@ async def test_get_user_success(
|
||||
ids=["nonexistent_email", "invalid_email"],
|
||||
)
|
||||
async def test_get_user_not_found(
|
||||
async_session: AsyncSession, mock_logger: MockLogger, email: str
|
||||
async_session: AsyncSession, mock_logger: MagicMock, email: str
|
||||
) -> None:
|
||||
"""Test handling of non-existent user in get_user.
|
||||
|
||||
@@ -152,8 +135,9 @@ async def test_get_user_not_found(
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("mock_logger", ["backend.services.users"], indirect=True)
|
||||
async def test_get_user_database_error(
|
||||
async_session: AsyncSession, mock_logger: MockLogger
|
||||
async_session: AsyncSession, mock_logger: MagicMock
|
||||
) -> None:
|
||||
"""Test handling of database errors in get_user.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user