"""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 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 def async_session() -> AsyncSession: """Fixture to provide a mocked AsyncSession for database interactions.""" return AsyncMock(spec=AsyncSession) @pytest.fixture 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]