"""叙事分区、口述过短回退、配图字数门闸(纯函数/无 DB)。""" import pytest from app.agents.memoir.prompts import format_narrative_user_content from app.features.memoir import story_pipeline_sync as sps def test_format_narrative_user_content_oral_only() -> None: assert format_narrative_user_content("hello", "") == "【本段用户口述】\nhello" def test_format_narrative_user_content_with_evidence() -> None: out = format_narrative_user_content("口述A", "摘录B") assert "【本段用户口述】" in out assert "口述A" in out assert "摘录B" in out assert "非本段口述" in out def test_should_fallback_to_transcript_short_md( monkeypatch: pytest.MonkeyPatch, ) -> None: monkeypatch.setattr(sps.settings, "memoir_narrative_fallback_body_ratio", 0.5) monkeypatch.setattr(sps.settings, "memoir_narrative_fallback_min_chars", 20) oral = "我一九九九年出生在上海,后来全家搬到苏州生活了好几年。" assert sps._should_fallback_to_transcript("1999", oral) is True assert sps._should_fallback_to_transcript(oral, oral) is False def test_apply_narrative_fallbacks_merge_shrink_appends_oral() -> None: """整篇合并 JSON 输出过短:保留旧文并拼本段口述。""" long_existing = "x" * 500 raw = '{"paragraphs": [{"content": "短"}]}' out, _ft = sps._apply_narrative_fallbacks( raw, "新口述补充", long_existing, chapter_category="childhood", ) assert long_existing in out assert "新口述补充" in out def test_apply_narrative_fallbacks_json_too_short_returns_oral( monkeypatch: pytest.MonkeyPatch, ) -> None: monkeypatch.setattr(sps.settings, "memoir_narrative_fallback_body_ratio", 0.5) monkeypatch.setattr(sps.settings, "memoir_narrative_fallback_min_chars", 20) oral = "我1999年出生在上海,小学时爷爷常带我去河边散步。" raw = '{"paragraphs": [{"content": "1999"}]}' out, _ft = sps._apply_narrative_fallbacks( raw, oral, "", chapter_category="childhood", ) assert out.strip() == oral def test_memoir_image_settings_min_body_field() -> None: from app.features.memoir.memoir_images.settings import MemoirImageSettings cfg = MemoirImageSettings(story_image_min_body_chars=799) assert cfg.story_image_min_body_chars == 799