wrongmove/crawler/tests/conftest.py

187 lines
5.4 KiB
Python
Raw Normal View History

"""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()