feat(tradein/scraper-kit): migrate cian/yandex price-history & session to kit (#2306) #2324
1 changed files with 17 additions and 2 deletions
|
|
@ -235,6 +235,7 @@ async def test_backfill_yandex_addresses_error_on_non_200():
|
||||||
async def test_cian_price_history_saves_changes():
|
async def test_cian_price_history_saves_changes():
|
||||||
"""Happy path: fetch returns DetailEnrichment with price_changes → saved."""
|
"""Happy path: fetch returns DetailEnrichment with price_changes → saved."""
|
||||||
from app.services.cian_price_history import backfill_cian_price_history
|
from app.services.cian_price_history import backfill_cian_price_history
|
||||||
|
from app.services.scraper_adapters import RealScraperConfig
|
||||||
from app.services.scrapers.cian_detail import DetailEnrichment
|
from app.services.scrapers.cian_detail import DetailEnrichment
|
||||||
|
|
||||||
enrichment = DetailEnrichment(
|
enrichment = DetailEnrichment(
|
||||||
|
|
@ -277,6 +278,12 @@ async def test_cian_price_history_saves_changes():
|
||||||
assert result.saved == 2 # 2 price_changes
|
assert result.saved == 2 # 2 price_changes
|
||||||
assert result.errors == 0
|
assert result.errors == 0
|
||||||
mock_fetch.assert_called_once()
|
mock_fetch.assert_called_once()
|
||||||
|
# #2306 regression guard: kit fetch_detail silently drops the Cian proxy
|
||||||
|
# (direct connection, #806 ban risk) unless config=RealScraperConfig() is
|
||||||
|
# passed at the call site — assert_called_once() alone wouldn't catch someone
|
||||||
|
# dropping that kwarg later.
|
||||||
|
_, call_kwargs = mock_fetch.call_args
|
||||||
|
assert isinstance(call_kwargs.get("config"), RealScraperConfig)
|
||||||
mock_save.assert_called_once()
|
mock_save.assert_called_once()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -284,6 +291,7 @@ async def test_cian_price_history_saves_changes():
|
||||||
async def test_cian_price_history_skips_no_changes():
|
async def test_cian_price_history_skips_no_changes():
|
||||||
"""Fetch succeeds but no price_changes → skipped (not error)."""
|
"""Fetch succeeds but no price_changes → skipped (not error)."""
|
||||||
from app.services.cian_price_history import backfill_cian_price_history
|
from app.services.cian_price_history import backfill_cian_price_history
|
||||||
|
from app.services.scraper_adapters import RealScraperConfig
|
||||||
from app.services.scrapers.cian_detail import DetailEnrichment
|
from app.services.scrapers.cian_detail import DetailEnrichment
|
||||||
|
|
||||||
enrichment = DetailEnrichment(cian_id=111, price_changes=[])
|
enrichment = DetailEnrichment(cian_id=111, price_changes=[])
|
||||||
|
|
@ -296,7 +304,7 @@ async def test_cian_price_history_skips_no_changes():
|
||||||
"app.services.cian_price_history.fetch_detail",
|
"app.services.cian_price_history.fetch_detail",
|
||||||
new_callable=AsyncMock,
|
new_callable=AsyncMock,
|
||||||
return_value=enrichment,
|
return_value=enrichment,
|
||||||
),
|
) as mock_fetch,
|
||||||
patch("app.services.cian_price_history.save_detail_enrichment") as mock_save,
|
patch("app.services.cian_price_history.save_detail_enrichment") as mock_save,
|
||||||
patch("app.services.cian_price_history.get_scraper_delay", return_value=0.0),
|
patch("app.services.cian_price_history.get_scraper_delay", return_value=0.0),
|
||||||
):
|
):
|
||||||
|
|
@ -309,12 +317,16 @@ async def test_cian_price_history_skips_no_changes():
|
||||||
assert result.skipped == 1
|
assert result.skipped == 1
|
||||||
assert result.saved == 0
|
assert result.saved == 0
|
||||||
mock_save.assert_not_called()
|
mock_save.assert_not_called()
|
||||||
|
# #2306 regression guard — see test_cian_price_history_saves_changes.
|
||||||
|
_, call_kwargs = mock_fetch.call_args
|
||||||
|
assert isinstance(call_kwargs.get("config"), RealScraperConfig)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_cian_price_history_handles_fetch_none():
|
async def test_cian_price_history_handles_fetch_none():
|
||||||
"""fetch_detail returns None → errors+1, no crash."""
|
"""fetch_detail returns None → errors+1, no crash."""
|
||||||
from app.services.cian_price_history import backfill_cian_price_history
|
from app.services.cian_price_history import backfill_cian_price_history
|
||||||
|
from app.services.scraper_adapters import RealScraperConfig
|
||||||
|
|
||||||
mock_db = MagicMock()
|
mock_db = MagicMock()
|
||||||
rows = [{"id": 30, "source_url": "https://ekb.cian.ru/sale/flat/999/"}]
|
rows = [{"id": 30, "source_url": "https://ekb.cian.ru/sale/flat/999/"}]
|
||||||
|
|
@ -324,7 +336,7 @@ async def test_cian_price_history_handles_fetch_none():
|
||||||
"app.services.cian_price_history.fetch_detail",
|
"app.services.cian_price_history.fetch_detail",
|
||||||
new_callable=AsyncMock,
|
new_callable=AsyncMock,
|
||||||
return_value=None,
|
return_value=None,
|
||||||
),
|
) as mock_fetch,
|
||||||
patch("app.services.cian_price_history.get_scraper_delay", return_value=0.0),
|
patch("app.services.cian_price_history.get_scraper_delay", return_value=0.0),
|
||||||
):
|
):
|
||||||
mock_mappings = MagicMock()
|
mock_mappings = MagicMock()
|
||||||
|
|
@ -335,6 +347,9 @@ async def test_cian_price_history_handles_fetch_none():
|
||||||
|
|
||||||
assert result.errors == 1
|
assert result.errors == 1
|
||||||
assert result.saved == 0
|
assert result.saved == 0
|
||||||
|
# #2306 regression guard — see test_cian_price_history_saves_changes.
|
||||||
|
_, call_kwargs = mock_fetch.call_args
|
||||||
|
assert isinstance(call_kwargs.get("config"), RealScraperConfig)
|
||||||
|
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue