Add comprehensive test suite: 219 new tests across backend and frontend
Backend (103 tests): - Unit tests for listing_service, export_service, district_service - Regression tests for API response contracts and query parameter validation - Integration tests for API workflows, Redis listing cache, listing processor pipeline, and repository advanced queries - E2E tests for streaming with filters, batching, caching, and task management Frontend (116 tests): - Service tests for apiClient, streamingService, taskService, listingService, healthService - Hook tests for useTaskProgress (WebSocket + polling) - Component tests for PropertyCard, FilterPanel, Header, ListView, TaskProgressDrawer, TaskIndicator, StreamingProgressBar, HealthIndicator - E2E tests for filter-stream-display flow Infrastructure: - Add pytest-xdist and test markers (regression, integration, e2e) - Add conftest fixtures: fake_redis, rent_listing_factory, seeded_repository - Add vitest + testing-library + MSW for frontend testing
This commit is contained in:
parent
a3ac9cc060
commit
8d22c97320
36 changed files with 5447 additions and 19 deletions
|
|
@ -1,7 +1,8 @@
|
|||
"""Shared pytest fixtures for the test suite."""
|
||||
from datetime import datetime
|
||||
from typing import AsyncGenerator, Generator
|
||||
from typing import Any, AsyncGenerator, Callable, Generator
|
||||
import pytest
|
||||
import fakeredis
|
||||
from sqlalchemy import Engine
|
||||
from sqlmodel import SQLModel, Session, create_engine
|
||||
from httpx import ASGITransport, AsyncClient
|
||||
|
|
@ -184,3 +185,59 @@ async def async_client(
|
|||
|
||||
# Clean up dependency overrides
|
||||
app.dependency_overrides.clear()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def fake_redis() -> Generator[fakeredis.FakeRedis, None, None]:
|
||||
"""Create a fakeredis client, flushed after each test."""
|
||||
client = fakeredis.FakeRedis(decode_responses=True)
|
||||
yield client
|
||||
client.flushall()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def rent_listing_factory() -> Callable[..., RentListing]:
|
||||
"""Factory function that creates RentListing with overridable defaults."""
|
||||
_counter = 0
|
||||
|
||||
def _create(**overrides: Any) -> RentListing:
|
||||
nonlocal _counter
|
||||
_counter += 1
|
||||
defaults: dict[str, Any] = dict(
|
||||
id=_counter,
|
||||
price=2000.0,
|
||||
number_of_bedrooms=2,
|
||||
square_meters=55.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(),
|
||||
)
|
||||
defaults.update(overrides)
|
||||
return RentListing(**defaults)
|
||||
|
||||
return _create
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def seeded_repository(
|
||||
in_memory_engine: Engine,
|
||||
rent_listing_factory: Callable[..., RentListing],
|
||||
) -> ListingRepository:
|
||||
"""Repository with 10 pre-seeded listings (varied price/bedrooms/sqm)."""
|
||||
repo = ListingRepository(engine=in_memory_engine)
|
||||
listings = [
|
||||
rent_listing_factory(id=100 + i, price=1000 + i * 300, number_of_bedrooms=(i % 4) + 1, square_meters=30 + i * 10)
|
||||
for i in range(10)
|
||||
]
|
||||
await repo.upsert_listings(listings)
|
||||
return repo
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue