"""封面闸门:canonical 未落库时须用物化正文计数 asset://。""" from unittest.mock import MagicMock, patch from app.features.memoir.cover_eligibility import ( chapter_eligible_for_cover_by_inline_body_image_count, chapter_needs_cover_enqueue, count_chapter_inline_body_images, effective_chapter_markdown_for_cover_gates, ) def test_effective_markdown_falls_back_to_materialize_when_canonical_empty() -> None: ch = MagicMock() ch.canonical_markdown = "" ch.story_links = [MagicMock()] with patch( "app.features.memoir.chapter_markdown_compose.materialize_chapter_markdown_from_loaded_chapter", return_value="正文\n\n![x](asset://a1)", ): assert "asset://" in effective_chapter_markdown_for_cover_gates(ch) def test_count_uses_effective_when_canonical_empty() -> None: ch = MagicMock() ch.canonical_markdown = "" ch.story_links = [MagicMock()] with patch( "app.features.memoir.chapter_markdown_compose.materialize_chapter_markdown_from_loaded_chapter", return_value="![alt](asset://id1)", ): assert count_chapter_inline_body_images(ch) == 1 def test_eligible_with_explicit_markdown_override() -> None: ch = MagicMock() ch.canonical_markdown = "" assert chapter_eligible_for_cover_by_inline_body_image_count( ch, markdown="![a](asset://x)" ) def test_needs_cover_enqueue_uses_materialized_body() -> None: ch = MagicMock() ch.canonical_markdown = "" ch.cover_asset_id = None ch.story_links = [MagicMock(story=MagicMock())] link = ch.story_links[0] link.story = MagicMock() with patch( "app.features.memoir.chapter_markdown_compose.materialize_chapter_markdown_from_loaded_chapter", return_value="故事\n\n![a](asset://z)", ): assert chapter_needs_cover_enqueue(ch) is True