"""Tests for derived story generation statuses.""" from types import SimpleNamespace from app.services.story_status import ( StoryAssetStatus, StoryGenerationStatus, resolve_story_generation_status, sync_story_status, ) def make_story(**overrides): data = { "story_text": "Once upon a time.", "pages": None, "cover_prompt": "A warm forest cover", "image_url": None, "generation_status": "narrative_ready", "text_status": "ready", "image_status": "not_requested", "audio_status": "not_requested", "last_error": None, } data.update(overrides) return SimpleNamespace(**data) def test_text_story_without_assets_is_partial_ready(): story = make_story() sync_story_status(story) assert story.text_status == "ready" assert story.generation_status == StoryGenerationStatus.PARTIAL_READY.value def test_text_story_with_all_assets_is_completed(): story = make_story( image_url="https://example.com/cover.png", image_status="ready", audio_status="ready", ) assert resolve_story_generation_status(story) == StoryGenerationStatus.COMPLETED def test_failed_asset_keeps_readable_story_degraded(): story = make_story(image_status="failed", last_error="cover failed") sync_story_status(story) assert story.text_status == "ready" assert story.generation_status == StoryGenerationStatus.DEGRADED_COMPLETED.value assert story.last_error == "cover failed" def test_storybook_missing_page_image_is_partial_ready(): story = make_story( story_text=None, pages=[ { "page_number": 1, "text": "Page one", "image_prompt": "Page one image", "image_url": "https://example.com/page-1.png", }, { "page_number": 2, "text": "Page two", "image_prompt": "Page two image", "image_url": None, }, ], cover_prompt="Storybook cover", image_url="https://example.com/cover.png", image_status="not_requested", ) assert resolve_story_generation_status(story) == StoryGenerationStatus.PARTIAL_READY def test_storybook_with_all_images_is_completed(): story = make_story( story_text=None, pages=[ { "page_number": 1, "text": "Page one", "image_prompt": "Page one image", "image_url": "https://example.com/page-1.png", }, ], cover_prompt="Storybook cover", image_url="https://example.com/cover.png", image_status="ready", audio_status="not_requested", ) assert resolve_story_generation_status(story) == StoryGenerationStatus.COMPLETED def test_missing_narrative_sets_text_failed(): story = make_story(story_text=None, pages=None) sync_story_status(story, image_status=StoryAssetStatus.NOT_REQUESTED) assert story.text_status == "failed" assert story.generation_status == StoryGenerationStatus.FAILED.value