Prepare mobile de parser preview

This commit is contained in:
qananasikq
2026-04-27 12:08:24 +03:00
commit 1eb7c8735a
76 changed files with 17855 additions and 0 deletions

113
tests/test_utils.py Normal file
View File

@@ -0,0 +1,113 @@
from __future__ import annotations
import unittest
from iaai_scraper.core.utils import deep_find_key
from iaai_scraper.core.config import (
IAAI_DEFAULT_MAKES,
_LARGE_MAKES,
_YEAR_SPLITS,
ProxyConfig,
build_listing_segments_for_makes,
parse_listing_segments,
)
class TestDeepFindKey(unittest.TestCase):
def test_finds_nested_and_respects_depth(self) -> None:
payload = {
"root": {
"target": "a",
"nested": [{"target": "b"}, {"x": 1}],
}
}
self.assertEqual(deep_find_key(payload, {"target"}), ["a", "b"])
deep_payload = {"l1": {"l2": {"l3": {"target": "value"}}}}
self.assertEqual(deep_find_key(deep_payload, {"target"}, max_depth=2), [])
self.assertEqual(deep_find_key(deep_payload, {"target"}, max_depth=8), ["value"])
class TestParseListingSegments(unittest.TestCase):
def test_empty_and_invalid_return_empty(self) -> None:
self.assertEqual(parse_listing_segments(""), [])
self.assertEqual(parse_listing_segments(" "), [])
self.assertEqual(parse_listing_segments("invalid"), [])
def test_auto_segments_complete_coverage(self) -> None:
"""auto: все бренды покрыты, крупные разбиты по годам, годы без дыр."""
segs = parse_listing_segments("auto")
# Точное число сегментов.
expected = len(_LARGE_MAKES) * len(_YEAR_SPLITS) + (len(IAAI_DEFAULT_MAKES) - len(_LARGE_MAKES))
self.assertEqual(len(segs), expected)
# Все бренды из списка присутствуют.
makes_in_segments = {s["make"] for s in segs}
for make in IAAI_DEFAULT_MAKES:
self.assertIn(make, makes_in_segments)
# Крупные бренды разбиты на 3 сегмента с годами.
toyota = [s for s in segs if s["make"] == "TOYOTA"]
self.assertEqual(len(toyota), 3)
for s in toyota:
self.assertIsNotNone(s["year_min"])
# Мелкие бренды без годов.
lexus = [s for s in segs if s["make"] == "LEXUS"]
self.assertEqual(len(lexus), 1)
self.assertIsNone(lexus[0]["year_min"])
# Годовые диапазоны покрывают 1950-2027.
years = set()
for yr_min, yr_max in _YEAR_SPLITS:
years.update(range(yr_min, yr_max + 1))
for year in range(1950, 2027):
self.assertIn(year, years)
def test_json_input_formats(self) -> None:
# Массив строк.
segs = parse_listing_segments('["toyota", "ford"]')
self.assertEqual(len(segs), 2)
self.assertEqual(segs[0]["make"], "TOYOTA")
# Массив объектов с годами.
segs = parse_listing_segments('[{"make":"BMW","year_min":2020,"year_max":2025}]')
self.assertEqual(segs[0]["make"], "BMW")
self.assertEqual(segs[0]["year_min"], 2020)
self.assertEqual(segs[0]["year_max"], 2025)
def test_build_listing_segments_for_makes(self) -> None:
segs = build_listing_segments_for_makes(["toyota", "Lexus", "TOYOTA", " "])
toyota = [s for s in segs if s["make"] == "TOYOTA"]
lexus = [s for s in segs if s["make"] == "LEXUS"]
self.assertEqual(len(toyota), len(_YEAR_SPLITS))
self.assertEqual(len(lexus), 1)
self.assertIsNone(lexus[0]["year_min"])
class TestProxyConfig(unittest.TestCase):
def test_requests_proxy_url_includes_encoded_credentials(self) -> None:
cfg = ProxyConfig(
server="http://144.31.139.6:3128",
username="carsproxy",
password="pass@word:with/slash",
)
self.assertEqual(
cfg.to_requests_proxy_url(),
"http://carsproxy:pass%40word%3Awith%2Fslash@144.31.139.6:3128",
)
self.assertEqual(
cfg.to_requests_proxies(),
{
"http": "http://carsproxy:pass%40word%3Awith%2Fslash@144.31.139.6:3128",
"https": "http://carsproxy:pass%40word%3Awith%2Fslash@144.31.139.6:3128",
},
)
if __name__ == "__main__":
unittest.main()