Files
conference-room-booking-system/backend/tests/routers/test_rooms.py
2025-08-25 21:38:31 -04:00

241 lines
8.0 KiB
Python

"""Unit tests for the backend.routers.rooms 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 NoResultFound
from backend.models import Room
from backend.services.rooms import RoomList
@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: MagicMock
) -> None:
"""Test successful retrieval of all rooms via GET /rooms/.
Verifies that the endpoint returns the expected list of rooms with a 200 status.
"""
with patch("backend.routers.rooms.get_rooms", new=AsyncMock()) as mock_get_rooms:
mock_get_rooms.return_value = sample_rooms
response = client.get("/rooms/")
assert response.status_code == 200
assert response.json() == [
{
"id": 1,
"name": "Room 1",
"location": "Building A",
"equipment": "Projector",
"capacity": 10,
},
{
"id": 2,
"name": "Room 2",
"location": "Building B",
"equipment": "Whiteboard",
"capacity": 15,
},
]
mock_get_rooms.assert_called_once()
@pytest.mark.asyncio
@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.
"""
with patch("backend.routers.rooms.get_rooms", new=AsyncMock()) as mock_get_rooms:
mock_get_rooms.return_value = []
response = client.get("/rooms/")
assert response.status_code == 200
assert response.json() == []
mock_get_rooms.assert_called_once()
@pytest.mark.asyncio
@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.
"""
room_id = 1
room = Room(
id=room_id,
name="Room 1",
location="Building A",
equipment="Projector",
capacity=10,
)
with patch("backend.routers.rooms.get_room", new=AsyncMock()) as mock_get_room:
mock_get_room.return_value = room
response = client.get(f"/rooms/{room_id}")
assert response.status_code == 200
assert response.json() == {
"id": room_id,
"name": "Room 1",
"location": "Building A",
"equipment": "Projector",
"capacity": 10,
}
mock_get_room.assert_called_once_with(ANY, room_id)
@pytest.mark.asyncio
@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.
"""
room_id = 999
with patch("backend.routers.rooms.get_room", new=AsyncMock()) as mock_get_room:
mock_get_room.side_effect = NoResultFound(f"Room with id {room_id} not found")
response = client.get(f"/rooms/{room_id}")
assert response.status_code == 404
assert "detail" in response.json()
mock_get_room.assert_called_once_with(ANY, room_id)
@pytest.mark.asyncio
@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.
"""
room_data: dict[str, Any] = {
"id": 3,
"name": "Room 3",
"location": "Building C",
"equipment": "TV",
"capacity": 20,
}
created_room = Room(**room_data)
with patch("backend.routers.rooms.new_room", new=AsyncMock()) as mock_new_room:
mock_new_room.return_value = created_room
response = client.post("/rooms/", json=room_data)
assert response.status_code == 201
assert response.json() == room_data
mock_new_room.assert_called_once()
@pytest.mark.asyncio
@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.
"""
room_id = 1
update_data: dict[str, Any] = {
"name": "Updated Room",
"location": "Building D",
"equipment": "Monitor",
"capacity": 25,
}
updated_room = Room(id=room_id, **update_data)
with patch(
"backend.routers.rooms.update_room", new=AsyncMock()
) as mock_update_room:
mock_update_room.return_value = updated_room
response = client.put(f"/rooms/{room_id}", json=update_data)
assert response.status_code == 200
assert response.json() == {
"id": room_id,
"name": "Updated Room",
"location": "Building D",
"equipment": "Monitor",
"capacity": 25,
}
mock_update_room.assert_called_once_with(ANY, room_id, **update_data)
@pytest.mark.asyncio
@pytest.mark.parametrize("mock_logger", ["backend.routers.rooms"], indirect=True)
async def test_update_room_not_found(
client: TestClient, mock_logger: MagicMock
) -> None:
"""Test handling of non-existent room in PUT /rooms/{room_id}.
Verifies that the endpoint returns a 404 status when the room is not found.
"""
room_id = 999
update_data: dict[str, Any] = {
"name": "Updated Room",
"location": "Building D",
"equipment": "Monitor",
"capacity": 25,
}
with patch(
"backend.routers.rooms.update_room", new=AsyncMock()
) as mock_update_room:
mock_update_room.side_effect = ValueError()
response = client.put(f"/rooms/{room_id}", json=update_data)
assert response.status_code == 404
assert "detail" in response.json()
mock_update_room.assert_called_once_with(ANY, room_id, **update_data)
@pytest.mark.asyncio
@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.
"""
room_id = 1
with patch(
"backend.routers.rooms.delete_room", new=AsyncMock()
) as mock_delete_room:
response = client.delete(f"/rooms/{room_id}")
assert response.status_code == 204
assert response.text == ""
mock_delete_room.assert_called_once_with(ANY, room_id)
@pytest.mark.asyncio
@pytest.mark.parametrize("mock_logger", ["backend.routers.rooms"], indirect=True)
async def test_delete_room_not_found(
client: TestClient, mock_logger: MagicMock
) -> None:
"""Test handling of non-existent room in DELETE /rooms/{room_id}.
Verifies that the endpoint returns a 404 status when the room is not found.
"""
room_id = 999
with patch(
"backend.routers.rooms.delete_room", new=AsyncMock()
) as mock_delete_room:
mock_delete_room.side_effect = ValueError()
response = client.delete(f"/rooms/{room_id}")
assert response.status_code == 404
assert "detail" in response.json()
mock_delete_room.assert_called_once_with(ANY, room_id)