227 lines
8 KiB
Python
227 lines
8 KiB
Python
"""Unit tests for ListingRepository."""
|
|
from datetime import datetime, timedelta
|
|
import pytest
|
|
from sqlalchemy import Engine
|
|
|
|
from models.listing import (
|
|
FurnishType,
|
|
ListingType,
|
|
QueryParameters,
|
|
RentListing,
|
|
)
|
|
from repositories.listing_repository import ListingRepository
|
|
|
|
|
|
class TestListingRepository:
|
|
"""Tests for ListingRepository methods."""
|
|
|
|
async def test_get_listings_empty_db(
|
|
self, listing_repository: ListingRepository
|
|
) -> None:
|
|
"""Test that get_listings returns empty list for empty database."""
|
|
listings = await listing_repository.get_listings()
|
|
assert listings == []
|
|
|
|
async def test_get_listings_returns_inserted_listings(
|
|
self,
|
|
listing_repository: ListingRepository,
|
|
sample_rent_listing: RentListing,
|
|
) -> None:
|
|
"""Test that get_listings returns listings that were inserted."""
|
|
await listing_repository.upsert_listings([sample_rent_listing])
|
|
listings = await listing_repository.get_listings()
|
|
assert len(listings) == 1
|
|
assert listings[0].id == sample_rent_listing.id
|
|
|
|
async def test_upsert_listings_creates_new(
|
|
self,
|
|
listing_repository: ListingRepository,
|
|
sample_rent_listing: RentListing,
|
|
) -> None:
|
|
"""Test that upsert_listings creates new listings."""
|
|
result = await listing_repository.upsert_listings([sample_rent_listing])
|
|
assert len(result) == 1
|
|
assert result[0].id == sample_rent_listing.id
|
|
|
|
# Verify it's in the database
|
|
listings = await listing_repository.get_listings()
|
|
assert len(listings) == 1
|
|
|
|
async def test_upsert_listings_updates_existing(
|
|
self,
|
|
listing_repository: ListingRepository,
|
|
sample_rent_listing: RentListing,
|
|
) -> None:
|
|
"""Test that upsert_listings updates existing listings."""
|
|
# Insert initial listing
|
|
await listing_repository.upsert_listings([sample_rent_listing])
|
|
|
|
# Update the listing
|
|
sample_rent_listing.price = 3000.0
|
|
await listing_repository.upsert_listings([sample_rent_listing])
|
|
|
|
# Verify update
|
|
listings = await listing_repository.get_listings()
|
|
assert len(listings) == 1
|
|
assert listings[0].price == 3000.0
|
|
|
|
async def test_mark_seen_updates_timestamp(
|
|
self,
|
|
listing_repository: ListingRepository,
|
|
sample_rent_listing: RentListing,
|
|
) -> None:
|
|
"""Test that mark_seen updates the last_seen timestamp."""
|
|
# Set an old timestamp
|
|
old_time = datetime.now() - timedelta(days=7)
|
|
sample_rent_listing.last_seen = old_time
|
|
await listing_repository.upsert_listings([sample_rent_listing])
|
|
|
|
# Mark as seen
|
|
await listing_repository.mark_seen(sample_rent_listing.id)
|
|
|
|
# Verify timestamp was updated
|
|
listings = await listing_repository.get_listings()
|
|
assert len(listings) == 1
|
|
assert listings[0].last_seen > old_time
|
|
|
|
async def test_mark_seen_nonexistent_listing(
|
|
self, listing_repository: ListingRepository
|
|
) -> None:
|
|
"""Test that mark_seen handles nonexistent listings gracefully."""
|
|
# Should not raise an exception
|
|
await listing_repository.mark_seen(999999)
|
|
|
|
async def test_get_listings_with_only_ids(
|
|
self,
|
|
listing_repository: ListingRepository,
|
|
sample_rent_listings: list[RentListing],
|
|
) -> None:
|
|
"""Test that get_listings filters by only_ids."""
|
|
await listing_repository.upsert_listings(sample_rent_listings)
|
|
|
|
# Request only specific IDs
|
|
listings = await listing_repository.get_listings(only_ids=[1, 3])
|
|
assert len(listings) == 2
|
|
listing_ids = [l.id for l in listings]
|
|
assert 1 in listing_ids
|
|
assert 3 in listing_ids
|
|
assert 2 not in listing_ids
|
|
|
|
async def test_get_listings_with_limit(
|
|
self,
|
|
listing_repository: ListingRepository,
|
|
sample_rent_listings: list[RentListing],
|
|
) -> None:
|
|
"""Test that get_listings respects limit parameter."""
|
|
await listing_repository.upsert_listings(sample_rent_listings)
|
|
|
|
listings = await listing_repository.get_listings(limit=2)
|
|
assert len(listings) == 2
|
|
|
|
|
|
class TestListingRepositoryFilters:
|
|
"""Tests for ListingRepository query parameter filtering."""
|
|
|
|
async def test_filter_by_bedrooms(
|
|
self,
|
|
listing_repository: ListingRepository,
|
|
sample_rent_listings: list[RentListing],
|
|
) -> None:
|
|
"""Test filtering by bedroom count."""
|
|
await listing_repository.upsert_listings(sample_rent_listings)
|
|
|
|
query_params = QueryParameters(
|
|
listing_type=ListingType.RENT,
|
|
min_bedrooms=2,
|
|
max_bedrooms=2,
|
|
)
|
|
listings = await listing_repository.get_listings(query_parameters=query_params)
|
|
assert len(listings) == 1
|
|
assert listings[0].number_of_bedrooms == 2
|
|
|
|
async def test_filter_by_price_range(
|
|
self,
|
|
listing_repository: ListingRepository,
|
|
sample_rent_listings: list[RentListing],
|
|
) -> None:
|
|
"""Test filtering by price range."""
|
|
await listing_repository.upsert_listings(sample_rent_listings)
|
|
|
|
query_params = QueryParameters(
|
|
listing_type=ListingType.RENT,
|
|
min_price=1800,
|
|
max_price=2500,
|
|
)
|
|
listings = await listing_repository.get_listings(query_parameters=query_params)
|
|
assert len(listings) == 1
|
|
assert listings[0].price == 2000.0
|
|
|
|
async def test_filter_by_min_sqm(
|
|
self,
|
|
listing_repository: ListingRepository,
|
|
sample_rent_listings: list[RentListing],
|
|
) -> None:
|
|
"""Test filtering by minimum square meters."""
|
|
await listing_repository.upsert_listings(sample_rent_listings)
|
|
|
|
query_params = QueryParameters(
|
|
listing_type=ListingType.RENT,
|
|
min_sqm=60,
|
|
)
|
|
listings = await listing_repository.get_listings(query_parameters=query_params)
|
|
assert len(listings) == 1
|
|
assert listings[0].square_meters == 80.0
|
|
|
|
async def test_filter_by_furnish_type(
|
|
self,
|
|
listing_repository: ListingRepository,
|
|
sample_rent_listings: list[RentListing],
|
|
) -> None:
|
|
"""Test filtering by furnish type."""
|
|
await listing_repository.upsert_listings(sample_rent_listings)
|
|
|
|
query_params = QueryParameters(
|
|
listing_type=ListingType.RENT,
|
|
furnish_types=[FurnishType.UNFURNISHED],
|
|
)
|
|
listings = await listing_repository.get_listings(query_parameters=query_params)
|
|
assert len(listings) == 1
|
|
assert listings[0].furnish_type == FurnishType.UNFURNISHED
|
|
|
|
async def test_filter_by_last_seen_days(
|
|
self,
|
|
listing_repository: ListingRepository,
|
|
sample_rent_listings: list[RentListing],
|
|
) -> None:
|
|
"""Test filtering by last_seen_days."""
|
|
# Make one listing old
|
|
sample_rent_listings[0].last_seen = datetime.now() - timedelta(days=30)
|
|
await listing_repository.upsert_listings(sample_rent_listings)
|
|
|
|
query_params = QueryParameters(
|
|
listing_type=ListingType.RENT,
|
|
last_seen_days=7,
|
|
)
|
|
listings = await listing_repository.get_listings(query_parameters=query_params)
|
|
# Only 2 should be recent enough
|
|
assert len(listings) == 2
|
|
|
|
async def test_combined_filters(
|
|
self,
|
|
listing_repository: ListingRepository,
|
|
sample_rent_listings: list[RentListing],
|
|
) -> None:
|
|
"""Test combining multiple filters."""
|
|
await listing_repository.upsert_listings(sample_rent_listings)
|
|
|
|
query_params = QueryParameters(
|
|
listing_type=ListingType.RENT,
|
|
min_bedrooms=1,
|
|
max_bedrooms=2,
|
|
min_price=1000,
|
|
max_price=2500,
|
|
furnish_types=[FurnishType.FURNISHED, FurnishType.UNFURNISHED],
|
|
)
|
|
listings = await listing_repository.get_listings(query_parameters=query_params)
|
|
# Should match listings with 1-2 bedrooms in price range
|
|
assert len(listings) == 2
|