Files
ozon-seller-kit/server/tests/test_single_image_edit.py
T
2026-09-27 22:41:33 +08:00

82 lines
3.8 KiB
Python

"""单张编辑的新参数必须进入同一次生图任务,且主图顺序与尺寸准确。"""
from __future__ import annotations
import sys
import unittest
from pathlib import Path
from types import SimpleNamespace
from unittest.mock import AsyncMock, patch
from fastapi import HTTPException
SERVER_DIR = Path(__file__).resolve().parents[1]
if str(SERVER_DIR) not in sys.path:
sys.path.insert(0, str(SERVER_DIR))
from api.suite import suite_image_edit, _with_dimensions
from schemas.suite import ImageEditSingleRequest, ProductDimensions
from services.generator import _image_size
from services.prompts.common import build_context
from services.prompts.single_edit import build_single_edit_prompt
class SingleEditRequestTests(unittest.IsolatedAsyncioTestCase):
async def test_main_and_two_auxiliary_images_keep_order_in_one_item(self) -> None:
request = ImageEditSingleRequest(
main_image_url="main", reference_image_urls=["detail", "scene"],
prompt="替换背景", model="gpt-image-2@pcore", translate_text=True,
target_language="ar", background="reference", ratio="4:5",
)
job = AsyncMock(return_value=SimpleNamespace(id="task-id"))
with patch("api.suite.create_image_job", job):
response = await suite_image_edit(request)
self.assertEqual(response.suite_id, "task-id")
payload = job.await_args.kwargs
self.assertEqual(payload["ratio"], "4:5")
self.assertEqual(payload["lang"], "ar")
self.assertEqual(payload["provider"], "pcore")
self.assertEqual(payload["model"], "gpt-image-2")
self.assertEqual(len(payload["item_payloads"]), 1)
self.assertEqual([image["url"] for image in payload["request_payload"]["ref_images"]], ["main", "detail", "scene"])
self.assertTrue(payload["request_payload"]["single_edit"]["translate_text"])
async def test_structured_edit_rejects_other_provider(self) -> None:
with self.assertRaises(HTTPException) as raised:
await suite_image_edit(ImageEditSingleRequest(
main_image_url="main", model="nano-banana-2",
))
self.assertEqual(raised.exception.status_code, 400)
class SingleEditPromptTests(unittest.TestCase):
def test_translation_background_and_partial_dimensions_share_one_prompt(self) -> None:
context = build_context(_with_dimensions(
{"title": "AI 精修"}, ProductDimensions(width=8, unit="cm"), required=True,
))
prompt = build_single_edit_prompt(
requirements="保留商品颜色", config={"translate_text": True, "target_language": "ar", "background": "scene", "background_description": "warm kitchen"},
context=context, style_set=2, style_prompt=None, ratio="3:4", is_size_chart=True, reference_count=2,
)
self.assertIn("Image 1 is the fixed main product image", prompt)
self.assertIn("Images 2 through 3 are auxiliary", prompt)
self.assertIn("Arabic", prompt)
self.assertIn("right-to-left", prompt)
self.assertIn("warm kitchen", prompt)
self.assertIn("width: 8.0 cm", prompt)
self.assertIn("Do not draw, label, or show an arrow for: length, height", prompt)
def test_four_to_five_size_does_not_fall_back_to_square(self) -> None:
for provider, is_wan, model in (
("pcore", True, "gpt-image-2"),
("rightapi", True, "gpt-image-2"),
("doubao", True, "seedream"),
("tongyi", True, "wan2.6-image"),
("tongyi", False, "qwen-image-3.0-pro"),
):
with self.subTest(provider=provider, model=model):
width, height = map(int, _image_size(provider, "4:5", is_wan, model).replace("*", "x").split("x"))
self.assertEqual(width * 5, height * 4)
if __name__ == "__main__":
unittest.main()