- Remove multi-marketplace from Phase 3 - Add FastAPI web UI on port 8766 with basic auth - Add 6 Jinja2 templates (dashboard, keywords, users, ads, stats) - Add pytest test suite (45 tests, 49% coverage) - Add GitHub Actions CI/CD workflow - Update docker-compose.yml to expose web UI port - Update Dockerfile to include tests
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
"""Shared pytest fixtures for the willhaben-tracker test suite."""
|
||||
|
||||
from datetime import datetime, timezone
|
||||
from unittest.mock import AsyncMock, MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
def pytest_configure(config):
|
||||
"""Enable asyncio auto mode for all async tests."""
|
||||
config.addinivalue_line("markers", "asyncio: mark test as async")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_pool():
|
||||
"""Mock asyncpg.Pool with fetch/fetchrow/execute/fetchval methods."""
|
||||
pool = MagicMock()
|
||||
pool.fetch = AsyncMock(return_value=[])
|
||||
pool.fetchrow = AsyncMock(return_value=None)
|
||||
pool.execute = AsyncMock(return_value=None)
|
||||
pool.fetchval = AsyncMock(return_value=None)
|
||||
return pool
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_bot():
|
||||
"""Mock ExtBot with send_message/send_photo methods."""
|
||||
bot = MagicMock()
|
||||
bot.send_message = AsyncMock(return_value=MagicMock(message_id=123))
|
||||
bot.send_photo = AsyncMock(return_value=MagicMock(message_id=123))
|
||||
return bot
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_ad_data():
|
||||
"""Sample willhaben ad JSON dict matching the API response format."""
|
||||
return {
|
||||
"id": "12345678",
|
||||
"description": "A used bicycle",
|
||||
"attributes": {
|
||||
"attribute": [
|
||||
{"name": "HEADING", "values": ["Mountain Bike 2024"]},
|
||||
{"name": "PRICE/AMOUNT", "values": ["250"]},
|
||||
{"name": "LOCATION", "values": ["Vienna"]},
|
||||
{"name": "POSTCODE", "values": ["1010"]},
|
||||
{"name": "SEO_URL", "values": ["mountain-bike-2024/12345678"]},
|
||||
{"name": "PUBLISHED_String", "values": ["2024-01-15T10:30:00Z"]},
|
||||
{"name": "CHANGED_String", "values": ["2024-01-15T12:00:00Z"]},
|
||||
]
|
||||
},
|
||||
"advertImageList": {
|
||||
"advertImage": [
|
||||
{"referenceImageUrl": "https://img.willhaben.at/img123.jpg"}
|
||||
]
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_fields():
|
||||
"""Sample extracted ad fields dict as returned by extract_ad_fields()."""
|
||||
return {
|
||||
"wh_ad_id": "12345678",
|
||||
"title": "Mountain Bike 2024",
|
||||
"price": 250.0,
|
||||
"location": "Vienna",
|
||||
"url": "https://www.willhaben.at/iad/mountain-bike-2024/12345678",
|
||||
"published_at": datetime(2024, 1, 15, 10, 30, 0, tzinfo=timezone.utc),
|
||||
"main_image_url": "https://img.willhaben.at/img123.jpg",
|
||||
"postcode": "1010",
|
||||
"modified_at": datetime(2024, 1, 15, 12, 0, 0, tzinfo=timezone.utc),
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_kw_row():
|
||||
"""Sample keyword row dict with filter settings."""
|
||||
return {
|
||||
"id": "kw-uuid-123",
|
||||
"keyword": "bike",
|
||||
"price_min": None,
|
||||
"price_max": None,
|
||||
"allowed_postcodes": None,
|
||||
}
|
||||
Reference in New Issue
Block a user