mirror of
https://github.com/Second-Hand-Friends/kleinanzeigen-bot.git
synced 2026-03-12 02:31:45 +01:00
fix: continue own-ad extraction when links are incomplete (#854)
This commit is contained in:
@@ -703,6 +703,58 @@ class TestAdExtractorNavigation:
|
||||
# Pagination should stop (TimeoutError in callback returns True)
|
||||
assert refs == []
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_extract_own_ads_urls_skips_single_item_timeout(self, test_extractor:extract_module.AdExtractor) -> None:
|
||||
"""Timeout on one ad item should skip that item but keep extracting others."""
|
||||
ad_list_container_mock = MagicMock()
|
||||
first_item = MagicMock()
|
||||
second_item = MagicMock()
|
||||
valid_link = MagicMock()
|
||||
valid_link.attrs = {"href": "/s-anzeige/ok/999"}
|
||||
|
||||
with (
|
||||
patch.object(test_extractor, "web_open", new_callable = AsyncMock),
|
||||
patch.object(test_extractor, "web_sleep", new_callable = AsyncMock),
|
||||
patch.object(test_extractor, "web_scroll_page_down", new_callable = AsyncMock),
|
||||
patch.object(test_extractor, "web_find_all", new_callable = AsyncMock, return_value = [first_item, second_item]),
|
||||
patch.object(
|
||||
test_extractor,
|
||||
"web_find",
|
||||
new_callable = AsyncMock,
|
||||
side_effect = [ad_list_container_mock, TimeoutError(), ad_list_container_mock, TimeoutError(), valid_link],
|
||||
),
|
||||
):
|
||||
refs = await test_extractor.extract_own_ads_urls()
|
||||
|
||||
assert refs == ["/s-anzeige/ok/999"]
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_extract_own_ads_urls_skips_single_item_without_href(self, test_extractor:extract_module.AdExtractor) -> None:
|
||||
"""Anchor without href should be skipped instead of adding a 'None' entry."""
|
||||
ad_list_container_mock = MagicMock()
|
||||
first_item = MagicMock()
|
||||
second_item = MagicMock()
|
||||
missing_href_link = MagicMock()
|
||||
missing_href_link.attrs = {}
|
||||
valid_link = MagicMock()
|
||||
valid_link.attrs = {"href": "/s-anzeige/ok/999"}
|
||||
|
||||
with (
|
||||
patch.object(test_extractor, "web_open", new_callable = AsyncMock),
|
||||
patch.object(test_extractor, "web_sleep", new_callable = AsyncMock),
|
||||
patch.object(test_extractor, "web_scroll_page_down", new_callable = AsyncMock),
|
||||
patch.object(test_extractor, "web_find_all", new_callable = AsyncMock, return_value = [first_item, second_item]),
|
||||
patch.object(
|
||||
test_extractor,
|
||||
"web_find",
|
||||
new_callable = AsyncMock,
|
||||
side_effect = [ad_list_container_mock, TimeoutError(), ad_list_container_mock, missing_href_link, valid_link],
|
||||
),
|
||||
):
|
||||
refs = await test_extractor.extract_own_ads_urls()
|
||||
|
||||
assert refs == ["/s-anzeige/ok/999"]
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_extract_own_ads_urls_generic_exception_in_callback(self, test_extractor:extract_module.AdExtractor) -> None:
|
||||
"""Test that generic Exception in extract_page_refs callback continues pagination."""
|
||||
|
||||
Reference in New Issue
Block a user