import unittest from unittest.mock import MagicMock from encar_scraper.encar import EncarMapper, EncarScraper, ENCAR_DETAIL_URL_TEMPLATE class TestEncarMapper(unittest.TestCase): def test_map_to_car_record(self): payload = { "Id": 41421262, "Manufacturer": "Hyundai", "Model": "G90 (RS4)", "FormYear": "2023", "Price": 8590, "Mileage": 37923, "Photos": [ {"location": "/carpicture01/pic4141/41412663_001.jpg", "ordering": 1}, {"location": "/carpicture01/pic4141/41412663_003.jpg", "ordering": 3}, ], } record = EncarMapper().map_to_car_record( ENCAR_DETAIL_URL_TEMPLATE.format(vehicle_id="41421262"), payload, ) self.assertEqual(record.origin_id, "encar:41421262") self.assertEqual(record.parser_id, "encar:41421262") self.assertEqual(record.brand, "Hyundai") # Скобки удаляются — на оригинальном сайте Encar их нет. self.assertEqual(record.model, "G90") self.assertEqual(record.year, 2023) self.assertEqual(record.price, 85900000) # 8590 만원 × 10000 self.assertEqual(record.mileage, 37923) self.assertEqual(record.country, "KR") self.assertEqual(record.currency, "KRW") self.assertEqual(len(record.images), 2) self.assertTrue(record.images[0].fullres_image.endswith("_001.jpg")) def test_extract_vehicle_id_from_url(self): url = ENCAR_DETAIL_URL_TEMPLATE.format(vehicle_id="41421262") self.assertEqual(EncarMapper()._extract_vehicle_id(url), "41421262") def test_map_to_car_record_uses_base_model_without_trim(self): payload = { "Id": 41854374, "Manufacturer": "현대", "Model": "Genesis", "Badge": "BH330 Grand", "BadgeDetail": "Prime팩", "FormYear": "2011", "Price": 1200, "Mileage": 100000, "Photos": [ {"location": "/carpicture01/pic4185/41854374_001.jpg", "ordering": 1}, ], } record = EncarMapper().map_to_car_record( ENCAR_DETAIL_URL_TEMPLATE.format(vehicle_id="41854374"), payload, ) self.assertEqual(record.brand, "Hyundai") self.assertEqual(record.model, "Genesis") self.assertEqual(record.origin_id, "encar:41854374") def test_map_to_car_record_resolves_numeric_id_from_photos(self): payload = { "Id": "car-BOqLLkjkgbpStlVJEJvbRG", "Manufacturer": "Kia", "Model": "K3", "FormYear": "2018", "Price": 990, "Mileage": 75000, "Photos": [ {"location": "/carpicture01/pic4187/41878507_001.jpg", "ordering": 1}, ], } record = EncarMapper().map_to_car_record("", payload) self.assertEqual(record.origin_id, "encar:41878507") self.assertEqual(record.parser_id, "encar:41878507") self.assertIn("carid=41878507", record.origin_url) def test_translate_model_keeps_english_text(self): mapper = EncarMapper() self.assertEqual(mapper._translate_model("All New Carnival"), "All New Carnival") self.assertEqual(mapper._translate_model("New Kia Ray"), "New Kia Ray") self.assertEqual(mapper._translate_model("K5 Hybrid 3rd gen"), "K5 Hybrid 3rd gen") def test_translate_model_handles_korean_fragments(self): mapper = EncarMapper() cases = { # Скобки и их содержимое отбрасываются как на сайте Encar. "5시리즈 (G30)": "5 Series", "S-클래스 W223": "S-Class W223", "Sonata 디 엣지(DN8)": "Sonata The Edge", "렉스턴 Sport 칸": "Rexton Sport Khan", "티볼리 Air": "Tivoli Air", "코란도 투리스모": "Korando Turismo", "Kia Carnival 4세대": "Kia Carnival 4th gen", "Cadillac 에스컬레이드 5세대": "Cadillac Escalade 5th gen", "K7 프리미어": "K7 Premier", } for raw, expected in cases.items(): with self.subTest(raw=raw): self.assertEqual(mapper._translate_model(raw), expected) def test_translate_model_drops_untranslated_korean(self): mapper = EncarMapper() cases = { # "레이" (Ray) не должен резать слово "슈팅브레이크" изнутри. "슈팅브레이크": "", "The New G70 슈팅브레이크": "The New G70", "G70 (슈팅브레이크)": "G70", } for raw, expected in cases.items(): with self.subTest(raw=raw): self.assertEqual(mapper._translate_model(raw), expected) class TestEncarScraper(unittest.TestCase): def test_collect_listing_limits_results(self): scraper = EncarScraper() scraper._fetch_listing_page = MagicMock(side_effect=[ {"SearchResults": [{"Id": 1}, {"Id": 2}]}, ]) result = scraper.collect_listing(limit=1, page_size=2) self.assertEqual(result["items_collected"], 1) self.assertEqual(result["vehicle_urls"], [ENCAR_DETAIL_URL_TEMPLATE.format(vehicle_id="1")]) def test_scrape_vehicle_detail_raises_without_id(self): scraper = EncarScraper() with self.assertRaises(ValueError): scraper.scrape_vehicle_detail("https://www.encar.com/invalid") if __name__ == "__main__": unittest.main()