186 lines
5.4 KiB
Python
186 lines
5.4 KiB
Python
"""Shared pytest fixtures for the test suite."""
|
|
from datetime import datetime
|
|
from typing import AsyncGenerator, Generator
|
|
import pytest
|
|
from sqlalchemy import Engine
|
|
from sqlmodel import SQLModel, Session, create_engine
|
|
from httpx import ASGITransport, AsyncClient
|
|
|
|
from models.listing import (
|
|
BuyListing,
|
|
FurnishType,
|
|
ListingSite,
|
|
RentListing,
|
|
Listing,
|
|
)
|
|
from repositories.listing_repository import ListingRepository
|
|
from api.auth import User
|
|
|
|
|
|
@pytest.fixture
|
|
def in_memory_engine() -> Generator[Engine, None, None]:
|
|
"""Create an in-memory SQLite engine for testing."""
|
|
engine = create_engine(
|
|
"sqlite:///:memory:",
|
|
echo=False,
|
|
connect_args={"check_same_thread": False},
|
|
)
|
|
SQLModel.metadata.create_all(engine)
|
|
yield engine
|
|
SQLModel.metadata.drop_all(engine)
|
|
|
|
|
|
@pytest.fixture
|
|
def listing_repository(in_memory_engine: Engine) -> ListingRepository:
|
|
"""Create a ListingRepository with the in-memory engine."""
|
|
return ListingRepository(engine=in_memory_engine)
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_rent_listing() -> RentListing:
|
|
"""Create a sample RentListing for testing."""
|
|
return RentListing(
|
|
id=12345678,
|
|
price=2500.0,
|
|
number_of_bedrooms=2,
|
|
square_meters=65.0,
|
|
agency="Test Agency",
|
|
council_tax_band="C",
|
|
longitude=-0.1276,
|
|
latitude=51.5074,
|
|
price_history_json="[]",
|
|
listing_site=ListingSite.RIGHTMOVE,
|
|
last_seen=datetime.now(),
|
|
photo_thumbnail="https://example.com/photo.jpg",
|
|
floorplan_image_paths=[],
|
|
additional_info={"property": {"visible": True}},
|
|
routing_info_json=None,
|
|
furnish_type=FurnishType.FURNISHED,
|
|
available_from=datetime.now(),
|
|
)
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_buy_listing() -> BuyListing:
|
|
"""Create a sample BuyListing for testing."""
|
|
return BuyListing(
|
|
id=87654321,
|
|
price=450000.0,
|
|
number_of_bedrooms=3,
|
|
square_meters=95.0,
|
|
agency="Test Estate Agents",
|
|
council_tax_band="D",
|
|
longitude=-0.1180,
|
|
latitude=51.5100,
|
|
price_history_json="[]",
|
|
listing_site=ListingSite.RIGHTMOVE,
|
|
last_seen=datetime.now(),
|
|
photo_thumbnail="https://example.com/buy_photo.jpg",
|
|
floorplan_image_paths=[],
|
|
additional_info={"property": {"visible": True}},
|
|
routing_info_json=None,
|
|
service_charge=1500.0,
|
|
lease_left=90,
|
|
)
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_rent_listings() -> list[RentListing]:
|
|
"""Create multiple sample RentListings for testing filters."""
|
|
now = datetime.now()
|
|
return [
|
|
RentListing(
|
|
id=1,
|
|
price=1500.0,
|
|
number_of_bedrooms=1,
|
|
square_meters=40.0,
|
|
agency="Agency A",
|
|
council_tax_band="B",
|
|
longitude=-0.1,
|
|
latitude=51.5,
|
|
price_history_json="[]",
|
|
listing_site=ListingSite.RIGHTMOVE,
|
|
last_seen=now,
|
|
photo_thumbnail=None,
|
|
floorplan_image_paths=[],
|
|
additional_info={"property": {"visible": True}},
|
|
routing_info_json=None,
|
|
furnish_type=FurnishType.FURNISHED,
|
|
available_from=now,
|
|
),
|
|
RentListing(
|
|
id=2,
|
|
price=2000.0,
|
|
number_of_bedrooms=2,
|
|
square_meters=55.0,
|
|
agency="Agency B",
|
|
council_tax_band="C",
|
|
longitude=-0.12,
|
|
latitude=51.51,
|
|
price_history_json="[]",
|
|
listing_site=ListingSite.RIGHTMOVE,
|
|
last_seen=now,
|
|
photo_thumbnail=None,
|
|
floorplan_image_paths=[],
|
|
additional_info={"property": {"visible": True}},
|
|
routing_info_json=None,
|
|
furnish_type=FurnishType.UNFURNISHED,
|
|
available_from=now,
|
|
),
|
|
RentListing(
|
|
id=3,
|
|
price=3000.0,
|
|
number_of_bedrooms=3,
|
|
square_meters=80.0,
|
|
agency="Agency C",
|
|
council_tax_band="D",
|
|
longitude=-0.14,
|
|
latitude=51.52,
|
|
price_history_json="[]",
|
|
listing_site=ListingSite.RIGHTMOVE,
|
|
last_seen=now,
|
|
photo_thumbnail=None,
|
|
floorplan_image_paths=[],
|
|
additional_info={"property": {"visible": True}},
|
|
routing_info_json=None,
|
|
furnish_type=FurnishType.FURNISHED,
|
|
available_from=now,
|
|
),
|
|
]
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_user() -> User:
|
|
"""Create a mock user for API tests."""
|
|
return User(
|
|
sub="test-user-id",
|
|
email="test@example.com",
|
|
name="Test User",
|
|
)
|
|
|
|
|
|
@pytest.fixture
|
|
async def async_client(
|
|
in_memory_engine: Engine, mock_user: User
|
|
) -> AsyncGenerator[AsyncClient, None]:
|
|
"""Create an AsyncClient for API testing with mock auth."""
|
|
from api.app import app
|
|
from api.auth import get_current_user
|
|
|
|
# Override dependencies
|
|
app.dependency_overrides[get_current_user] = lambda: mock_user
|
|
|
|
# Patch the engine used by the repository
|
|
original_engine = None
|
|
try:
|
|
from database import engine as db_engine
|
|
original_engine = db_engine
|
|
except Exception:
|
|
pass
|
|
|
|
transport = ASGITransport(app=app)
|
|
async with AsyncClient(transport=transport, base_url="http://test") as client:
|
|
yield client
|
|
|
|
# Clean up dependency overrides
|
|
app.dependency_overrides.clear()
|