"""Регрессия на размер страницы Avito SERP. Замер живьём 2026-08-21 (tradein-browser / camoufox, JS исполняется): страница выдачи отдаёт 59-60 уникальных `data-item-id`. Константа стояла 50 — то есть `ceil(total / PAGE)` завышал число страниц примерно на 17 %, и каждый лишний запрос — лишний шанс словить SERP firewall. Тест намеренно проверяет НЕ только значение, но и то, что константа по-прежнему участвует в расчёте страниц: иначе правку значения легко потерять при рефакторинге, оставив мёртвую константу. """ from __future__ import annotations import ast import math from pathlib import Path from scraper_kit.providers.avito import serp _SERP_SOURCE = Path(serp.__file__) def test_offers_per_page_matches_live_measurement() -> None: """60, а не 50 — замер 2026-08-21 через реальный браузер.""" assert serp._AVITO_OFFERS_PER_PAGE == 60 def test_pages_needed_arithmetic_uses_the_constant() -> None: """`ceil(total / PAGE)` при 60 даёт меньше страниц, чем при 50. Закрепляет направление эффекта: занижение размера страницы ЗАВЫШАЛО число запрашиваемых страниц. В PR-разборе это было сформулировано наоборот, и тест существует, чтобы неверная трактовка не вернулась. """ total = 1000 assert math.ceil(total / 60) == 17 assert math.ceil(total / 50) == 20 assert math.ceil(total / serp._AVITO_OFFERS_PER_PAGE) == 17 def test_constant_is_still_wired_into_pagination() -> None: """Константа реально используется, а не осталась мёртвой после правки.""" tree = ast.parse(_SERP_SOURCE.read_text(encoding="utf-8")) uses = sum( 1 for node in ast.walk(tree) if isinstance(node, ast.Name) and node.id == "_AVITO_OFFERS_PER_PAGE" ) # 1 присваивание + минимум два места расчёта (pages_needed в бисекции и в # пагинации листа); если станет меньше — кто-то отвязал константу. assert uses >= 3, f"_AVITO_OFFERS_PER_PAGE упоминается {uses} раз, ожидалось >= 3" def test_no_stale_fifty_in_page_size_comment() -> None: """Комментарий рядом с константой не должен утверждать «~50 карточек».""" src = _SERP_SOURCE.read_text(encoding="utf-8") marker = "_AVITO_OFFERS_PER_PAGE = " idx = src.index(marker) preceding = src[max(0, idx - 1200) : idx] assert "~50 карточек" not in preceding