@@ -362,6 +362,45 @@ def test_empty_response_on_random_page_raises_mediawiki_error(self, mock_get):
362362 assert exc_info .value .errors ['code' ] == '429'
363363 assert exc_info .value .errors ['info' ] == 'Too Many Requests'
364364
365+ @patch ('philosophy.requests.get' )
366+ def test_figure_caption_link_ignored (self , mock_get ):
367+ # Wikipedia now uses <figure>/<figcaption> for image thumbnails.
368+ # Links inside captions must be skipped; the real first link follows.
369+ html = (
370+ '<div>'
371+ '<figure class="mw-default-size" typeof="mw:File/Thumb">'
372+ '<a href="/wiki/File:Foo.jpg" class="mw-file-description"><img/></a>'
373+ '<figcaption>A caption with a <a href="/wiki/Rotary_dial">rotary dial</a></figcaption>'
374+ '</figure>'
375+ '<p>Text with a <a href="/wiki/Philosophy">Philosophy</a> link.</p>'
376+ '</div>'
377+ )
378+ mock_get .side_effect = [
379+ _parse ('Telephone' , html ),
380+ _parse ('Philosophy' , NO_WIKI_LINKS ),
381+ ]
382+ result = list (trace (page = 'Telephone' ))
383+ assert result == ['Telephone' , 'Philosophy' ]
384+
385+ @patch ('philosophy.requests.get' )
386+ def test_figure_without_figcaption_link_ignored (self , mock_get ):
387+ # Links directly inside <figure> (e.g. the file-description wrapper)
388+ # should also be skipped.
389+ html = (
390+ '<div>'
391+ '<figure typeof="mw:File/Thumb">'
392+ '<a href="/wiki/File:Foo.jpg" class="mw-file-description"><img/></a>'
393+ '</figure>'
394+ '<p><a href="/wiki/Philosophy">Philosophy</a></p>'
395+ '</div>'
396+ )
397+ mock_get .side_effect = [
398+ _parse ('Start Page' , html ),
399+ _parse ('Philosophy' , NO_WIKI_LINKS ),
400+ ]
401+ result = list (trace (page = 'Start Page' ))
402+ assert result == ['Start Page' , 'Philosophy' ]
403+
365404 @patch ('philosophy.requests.get' )
366405 def test_whole_page_retry_propagates_loop (self , mock_get ):
367406 # section=0 has no links → whole_page retry; the retry chain loops
0 commit comments