修复一些已知问题
This commit is contained in:
@@ -8,6 +8,7 @@ from app.features.memoir.asset_resolver import (
|
||||
collect_asset_ids_from_markdown,
|
||||
resolve_asset_refs_in_markdown,
|
||||
split_markdown_by_asset_refs,
|
||||
strip_asset_image_refs_from_markdown,
|
||||
strip_legacy_image_placeholders,
|
||||
)
|
||||
from app.features.memoir.models import Chapter
|
||||
@@ -53,6 +54,22 @@ class AssetResolverTest(unittest.TestCase):
|
||||
ids = collect_asset_ids_for_chapter(ch)
|
||||
self.assertEqual(ids, {"a1", "cov1"})
|
||||
|
||||
def test_strip_asset_image_refs_removes_all_and_collapses_blank_lines(self):
|
||||
md = (
|
||||
"第一段\n\n\n\n第二段\n\n\n"
|
||||
"\n\n第三段"
|
||||
)
|
||||
out = strip_asset_image_refs_from_markdown(md)
|
||||
self.assertNotIn("asset://", out)
|
||||
self.assertIn("第一段", out)
|
||||
self.assertIn("第二段", out)
|
||||
self.assertIn("第三段", out)
|
||||
self.assertNotIn("\n\n\n", out)
|
||||
|
||||
def test_strip_asset_image_refs_empty(self):
|
||||
self.assertEqual(strip_asset_image_refs_from_markdown(""), "")
|
||||
self.assertEqual(strip_asset_image_refs_from_markdown(" "), "")
|
||||
|
||||
def test_collect_asset_ids_includes_linked_story_markdown(self):
|
||||
ch = SimpleNamespace(
|
||||
canonical_markdown="",
|
||||
|
||||
@@ -134,6 +134,103 @@ class GenerateStoryImageTaskTest(unittest.TestCase):
|
||||
acquire_lock_mock.assert_called_once()
|
||||
release_lock_mock.assert_called_once()
|
||||
|
||||
@patch("app.tasks.story_image_tasks.release_redis_lock")
|
||||
@patch(
|
||||
"app.tasks.story_image_tasks.acquire_redis_lock",
|
||||
return_value=SimpleNamespace(key="lock:story-image:story-1"),
|
||||
)
|
||||
@patch("app.tasks.story_image_tasks._claim_story_image_intent_sync")
|
||||
@patch("app.tasks.story_image_tasks.get_sync_db")
|
||||
@patch("app.tasks.story_image_tasks.TencentCosStorageService")
|
||||
@patch("app.tasks.story_image_tasks.get_image_generator")
|
||||
@patch("app.features.memoir.memoir_images.settings.MemoirImageSettings.from_env")
|
||||
@patch("app.tasks.story_image_tasks.uuid.uuid4")
|
||||
def test_generate_story_image_strips_existing_asset_refs_before_backfill(
|
||||
self,
|
||||
uuid4_mock,
|
||||
settings_from_env,
|
||||
get_image_generator_mock,
|
||||
storage_cls,
|
||||
get_sync_db_mock,
|
||||
claim_intent_mock,
|
||||
acquire_lock_mock,
|
||||
release_lock_mock,
|
||||
):
|
||||
uuid4_mock.side_effect = [
|
||||
_FakeUUID("claim-token"),
|
||||
_FakeUUID("new-asset-uuid"),
|
||||
_FakeUUID("version-uuid"),
|
||||
]
|
||||
settings_from_env.return_value = SimpleNamespace(
|
||||
provider="liblib",
|
||||
default_style="watercolor",
|
||||
default_size="1024x1024",
|
||||
)
|
||||
|
||||
intent = SimpleNamespace(
|
||||
id="intent-1",
|
||||
prompt_brief="院子里的藤椅",
|
||||
style_profile="watercolor",
|
||||
story_version_id="ver-1",
|
||||
caption="主插图",
|
||||
status="processing",
|
||||
)
|
||||
story = SimpleNamespace(
|
||||
id="story-1",
|
||||
user_id="user-1",
|
||||
title="童年的院子",
|
||||
stage="childhood",
|
||||
)
|
||||
db_claim = Mock()
|
||||
claim_intent_mock.return_value = (intent, story)
|
||||
|
||||
intent_db = SimpleNamespace(
|
||||
id="intent-1",
|
||||
story_version_id="ver-1",
|
||||
caption="主插图",
|
||||
prompt_brief="院子里的藤椅",
|
||||
status="processing",
|
||||
style_profile="watercolor",
|
||||
claim_token="claim-token",
|
||||
asset_id=None,
|
||||
error=None,
|
||||
updated_at=None,
|
||||
)
|
||||
story_db = SimpleNamespace(
|
||||
id="story-1",
|
||||
current_version_id="ver-1",
|
||||
canonical_markdown="第一段\n\n第二段",
|
||||
)
|
||||
version_db = SimpleNamespace(
|
||||
id="ver-1",
|
||||
markdown_snapshot=("第一段\n\n\n\n第二段"),
|
||||
)
|
||||
version_max_result = Mock()
|
||||
version_max_result.scalar.return_value = 1
|
||||
db_persist = Mock()
|
||||
db_persist.get.side_effect = [intent_db, story_db, version_db]
|
||||
db_persist.execute.return_value = version_max_result
|
||||
|
||||
get_sync_db_mock.side_effect = [_mock_db_cm(db_claim), _mock_db_cm(db_persist)]
|
||||
|
||||
generator = get_image_generator_mock.return_value
|
||||
generator.generate.return_value = ImageResult(
|
||||
status=TaskStatus.COMPLETED,
|
||||
task_id="task-1",
|
||||
image_url="https://provider.example.com/story.png",
|
||||
)
|
||||
generator.download_image.return_value = _png_bytes()
|
||||
storage_cls.from_env.return_value.upload_bytes.return_value = (
|
||||
"https://cos.example.com/stories/u1/s1.png"
|
||||
)
|
||||
|
||||
result = generate_story_image.run("story-1")
|
||||
|
||||
self.assertEqual(result["status"], "success")
|
||||
self.assertEqual(story_db.canonical_markdown.count("asset://"), 1)
|
||||
self.assertIn("asset://new-asset-uuid", story_db.canonical_markdown)
|
||||
self.assertNotIn("old-stale-id", story_db.canonical_markdown)
|
||||
|
||||
@patch("app.tasks.story_image_tasks.acquire_redis_lock", return_value=None)
|
||||
@patch("app.tasks.story_image_tasks.get_sync_db")
|
||||
@patch("app.tasks.story_image_tasks.get_image_generator")
|
||||
|
||||
Reference in New Issue
Block a user