feat: move unified generation to background worker
This commit is contained in:
@@ -430,6 +430,8 @@ class TestGenerateFull:
|
||||
class TestUnifiedGenerations:
|
||||
"""Tests for the target unified generation API."""
|
||||
|
||||
TASK_DELAY_PATH = "app.tasks.generation_workflow.run_generation_workflow_task.delay"
|
||||
|
||||
def test_create_generation_without_auth(self, client: TestClient):
|
||||
response = client.post(
|
||||
"/api/generations",
|
||||
@@ -443,60 +445,64 @@ class TestUnifiedGenerations:
|
||||
mock_text_provider,
|
||||
mock_image_provider,
|
||||
):
|
||||
response = auth_client.post(
|
||||
"/api/generations",
|
||||
json={
|
||||
"output_mode": "story",
|
||||
"type": "keywords",
|
||||
"data": "小兔子, 森林, 勇气",
|
||||
"generate_images": True,
|
||||
},
|
||||
)
|
||||
with patch(self.TASK_DELAY_PATH) as mock_delay:
|
||||
response = auth_client.post(
|
||||
"/api/generations",
|
||||
json={
|
||||
"output_mode": "story",
|
||||
"type": "keywords",
|
||||
"data": "小兔子, 森林, 勇气",
|
||||
"generate_images": True,
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.status_code == 202
|
||||
assert "Deprecation" not in response.headers
|
||||
data = response.json()
|
||||
assert data["id"] is not None
|
||||
assert data["id"] is 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["story_text"] is None
|
||||
assert data["image_url"] is None
|
||||
assert data["cover_url"] is None
|
||||
assert data["pages"] is None
|
||||
assert data["generation_status"] == "partial_ready"
|
||||
assert data["image_status"] == "ready"
|
||||
assert data["generation_status"] == "queued"
|
||||
assert data["text_status"] == "generating"
|
||||
assert data["image_status"] == "not_requested"
|
||||
assert data["audio_status"] == "not_requested"
|
||||
assert data["errors"] == {}
|
||||
mock_delay.assert_called_once_with(data["generation_job_id"])
|
||||
|
||||
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,
|
||||
},
|
||||
)
|
||||
with patch(self.TASK_DELAY_PATH) as mock_delay:
|
||||
response = auth_client.post(
|
||||
"/api/generations",
|
||||
json={
|
||||
"output_mode": "story",
|
||||
"type": "keywords",
|
||||
"data": "小兔子, 森林",
|
||||
"generate_images": False,
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.status_code == 202
|
||||
data = response.json()
|
||||
assert data["mode"] == "generated"
|
||||
assert data["image_url"] is None
|
||||
assert data["generation_status"] == "partial_ready"
|
||||
assert data["generation_status"] == "queued"
|
||||
assert data["text_status"] == "generating"
|
||||
assert data["image_status"] == "not_requested"
|
||||
mock_delay.assert_called_once_with(data["generation_job_id"])
|
||||
|
||||
def test_create_story_generation_image_failure(
|
||||
self,
|
||||
auth_client: TestClient,
|
||||
mock_text_provider,
|
||||
):
|
||||
with patch("app.services.story_service.generate_image", new_callable=AsyncMock) as mock_img:
|
||||
mock_img.side_effect = Exception("Image API error")
|
||||
|
||||
with patch(self.TASK_DELAY_PATH) as mock_delay:
|
||||
response = auth_client.post(
|
||||
"/api/generations",
|
||||
json={
|
||||
@@ -507,55 +513,45 @@ class TestUnifiedGenerations:
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.status_code == 202
|
||||
data = response.json()
|
||||
assert data["image_url"] is None
|
||||
assert data["generation_status"] == "degraded_completed"
|
||||
assert data["image_status"] == "failed"
|
||||
assert data["generation_status"] == "queued"
|
||||
assert data["text_status"] == "generating"
|
||||
assert data["image_status"] == "not_requested"
|
||||
assert data["audio_status"] == "not_requested"
|
||||
assert "Image API error" in data["errors"]["image"]
|
||||
assert "Image API error" in data["last_error"]
|
||||
assert data["errors"] == {}
|
||||
assert data["last_error"] is None
|
||||
mock_delay.assert_called_once_with(data["generation_job_id"])
|
||||
|
||||
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",
|
||||
]
|
||||
with patch(self.TASK_DELAY_PATH) as mock_delay:
|
||||
response = auth_client.post(
|
||||
"/api/generations",
|
||||
json={
|
||||
"output_mode": "storybook",
|
||||
"type": "keywords",
|
||||
"data": "森林, 发光, 友情",
|
||||
"page_count": 6,
|
||||
"generate_images": True,
|
||||
},
|
||||
)
|
||||
|
||||
response = auth_client.post(
|
||||
"/api/generations",
|
||||
json={
|
||||
"output_mode": "storybook",
|
||||
"type": "keywords",
|
||||
"data": "森林, 发光, 友情",
|
||||
"page_count": 6,
|
||||
"generate_images": True,
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.status_code == 202
|
||||
data = response.json()
|
||||
assert data["id"] is not None
|
||||
assert data["id"] is 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["pages"] is None
|
||||
assert data["cover_url"] is None
|
||||
assert data["image_url"] is None
|
||||
assert data["main_character"] is None
|
||||
assert data["art_style"] is None
|
||||
assert data["generation_status"] == "queued"
|
||||
assert data["text_status"] == "generating"
|
||||
assert data["image_status"] == "not_requested"
|
||||
assert data["audio_status"] == "not_requested"
|
||||
mock_delay.assert_called_once_with(data["generation_job_id"])
|
||||
|
||||
def test_get_generation_alias(self, auth_client: TestClient, test_story):
|
||||
response = auth_client.get(f"/api/generations/{test_story.id}")
|
||||
|
||||
Reference in New Issue
Block a user