"""章节读路径 prepare_chapter_read_view:不写库、临时物化串用于列表/详情。""" from unittest.mock import MagicMock, patch from app.features.memoir.reading_segment_materialize import ( chapter_meets_minimum_display, ) from app.features.memoir.service import prepare_chapter_read_view def test_prepare_not_dirty_no_override() -> None: ch = MagicMock() ch.markdown_compose_dirty = False ch.reading_segments_json = None ch.story_links = [MagicMock()] c, md = prepare_chapter_read_view(ch) assert c is ch assert md is None def test_prepare_dirty_with_snapshot_no_override() -> None: ch = MagicMock() ch.markdown_compose_dirty = True ch.reading_segments_json = [{"story_id": "s1", "body_markdown": "x" * 400}] ch.story_links = [MagicMock()] c, md = prepare_chapter_read_view(ch) assert md is None def test_prepare_dirty_no_snapshot_no_links_no_override() -> None: ch = MagicMock() ch.markdown_compose_dirty = True ch.reading_segments_json = None ch.story_links = [] c, md = prepare_chapter_read_view(ch) assert md is None def test_prepare_dirty_no_snapshot_with_links_uses_materialize() -> None: ch = MagicMock() ch.markdown_compose_dirty = True ch.reading_segments_json = None ch.story_links = [MagicMock()] fake_md = "正文" * 200 with patch( "app.features.memoir.service.materialize_chapter_markdown_from_loaded_chapter", return_value=fake_md, ) as m: c, md = prepare_chapter_read_view(ch) m.assert_called_once_with(ch) assert md == fake_md.strip() assert c is ch def test_chapter_meets_minimum_uses_override() -> None: ch = MagicMock() ch.canonical_markdown = "" long_md = "字" * 400 assert ( chapter_meets_minimum_display(ch, canonical_markdown_override=long_md) is True ) assert chapter_meets_minimum_display(ch, canonical_markdown_override="短") is False