feat: add unified generation entrypoint

This commit is contained in:
2026-04-18 12:55:20 +08:00
parent 9e1a17fa67
commit e201fa3358
10 changed files with 358 additions and 67 deletions

View File

@@ -367,6 +367,135 @@ class TestGenerateFull:
assert call_kwargs["education_theme"] == "勇气与友谊"
class TestUnifiedGenerations:
"""Tests for the target unified generation API."""
def test_create_generation_without_auth(self, client: TestClient):
response = client.post(
"/api/generations",
json={"output_mode": "story", "type": "keywords", "data": "小兔子, 森林"},
)
assert response.status_code == 401
def test_create_story_generation_success(
self,
auth_client: TestClient,
mock_text_provider,
mock_image_provider,
):
response = auth_client.post(
"/api/generations",
json={
"output_mode": "story",
"type": "keywords",
"data": "小兔子, 森林, 勇气",
"generate_images": True,
},
)
assert response.status_code == 200
data = response.json()
assert data["id"] is not None
assert data["mode"] == "generated"
assert data["story_text"] == "从前有一只小兔子。"
assert data["image_url"] == "https://example.com/image.png"
assert data["cover_url"] == "https://example.com/image.png"
assert data["pages"] is None
assert data["generation_status"] == "completed"
assert data["image_status"] == "ready"
assert data["audio_status"] == "not_requested"
assert data["errors"] == {}
def test_create_story_generation_without_assets(
self,
auth_client: TestClient,
mock_text_provider,
):
response = auth_client.post(
"/api/generations",
json={
"output_mode": "story",
"type": "keywords",
"data": "小兔子, 森林",
"generate_images": False,
},
)
assert response.status_code == 200
data = response.json()
assert data["mode"] == "generated"
assert data["image_url"] is None
assert data["generation_status"] == "narrative_ready"
assert data["image_status"] == "not_requested"
def test_create_storybook_generation_success(self, auth_client: TestClient):
with patch(
"app.services.story_service.generate_storybook",
new_callable=AsyncMock,
) as mock_storybook:
with patch(
"app.services.story_service.generate_image",
new_callable=AsyncMock,
) as mock_image:
mock_storybook.return_value = build_storybook_output()
mock_image.side_effect = [
"https://example.com/storybook-cover.png",
"https://example.com/storybook-page-1.png",
"https://example.com/storybook-page-2.png",
]
response = auth_client.post(
"/api/generations",
json={
"output_mode": "storybook",
"type": "keywords",
"data": "森林, 发光, 友情",
"page_count": 6,
"generate_images": True,
},
)
assert response.status_code == 200
data = response.json()
assert data["id"] is not None
assert data["mode"] == "storybook"
assert data["story_text"] is None
assert len(data["pages"]) == 2
assert data["cover_url"] == "https://example.com/storybook-cover.png"
assert data["image_url"] == "https://example.com/storybook-cover.png"
assert data["main_character"] == "小兔子露露"
assert data["art_style"] == "温暖水彩"
assert data["generation_status"] == "completed"
assert data["image_status"] == "ready"
assert data["audio_status"] == "not_requested"
def test_get_generation_alias(self, auth_client: TestClient, test_story):
response = auth_client.get(f"/api/generations/{test_story.id}")
assert response.status_code == 200
data = response.json()
assert data["id"] == test_story.id
assert data["title"] == test_story.title
assert data["mode"] == "generated"
def test_retry_generation_assets_alias(
self,
auth_client: TestClient,
degraded_story_with_text,
mock_image_provider,
):
response = auth_client.post(
f"/api/generations/{degraded_story_with_text.id}/retry-assets",
json={"assets": ["image"]},
)
assert response.status_code == 200
data = response.json()
assert data["image_url"] == "https://example.com/image.png"
assert data["generation_status"] == "completed"
assert data["image_status"] == "ready"
class TestImageGenerateSuccess:
"""Tests for successful cover generation."""