160 lines
5.7 KiB
Python
160 lines
5.7 KiB
Python
import io
|
|
import os
|
|
import sys
|
|
import unittest
|
|
from unittest import mock
|
|
|
|
sys.path.insert(0, os.path.dirname(__file__))
|
|
|
|
from _helpers import TempDirMixin
|
|
|
|
from app import db, image_studio, image_studio_export, image_studio_generation, image_studio_images
|
|
|
|
|
|
class ImageStudioE2ETests(TempDirMixin, unittest.TestCase):
|
|
def _png_bytes(self, color=(80, 130, 220)):
|
|
from PIL import Image
|
|
|
|
output = io.BytesIO()
|
|
Image.new("RGB", (32, 32), color).save(output, format="PNG")
|
|
return output.getvalue()
|
|
|
|
def _config(self, temp_dir):
|
|
return {
|
|
"data_dir": temp_dir,
|
|
"db_path": os.path.join(temp_dir, "cmshopee.db"),
|
|
"image_dir": os.path.join(temp_dir, "images"),
|
|
"ai": {
|
|
"backend": "cmhub",
|
|
"image_concurrency": 2,
|
|
"retry": 0,
|
|
"resolution": "1k",
|
|
"jpg_quality": 90,
|
|
"cmhub": {
|
|
"base_url": "https://cmhub.example.com",
|
|
"image_alias": "image-hd",
|
|
"connect_timeout": 3,
|
|
"download_with_curl": "false",
|
|
},
|
|
},
|
|
}
|
|
|
|
def _runtime(self):
|
|
return {
|
|
"base_url": "https://cmhub.example.com",
|
|
"api_key": "sk-test",
|
|
"alias": "image-hd",
|
|
"connect_timeout": 3,
|
|
"use_system_proxy": False,
|
|
"download_with_curl": "false",
|
|
}
|
|
|
|
def test_mock_ai_studio_project_to_export_flow(self):
|
|
with self.make_temp_dir() as temp_dir:
|
|
cfg = self._config(temp_dir)
|
|
db.init_db(cfg["db_path"])
|
|
project = image_studio.create_or_get_project(
|
|
account_alias="alias",
|
|
account_slug="alias_slug",
|
|
item_id="51100639510",
|
|
draft_prompt="完整提示词",
|
|
path=cfg["db_path"],
|
|
)
|
|
original = image_studio.sync_original_asset_urls(
|
|
project.id,
|
|
[{"index": 1, "src": "https://cdn.example.com/original.png"}],
|
|
path=cfg["db_path"],
|
|
)[0]
|
|
|
|
remote = image_studio_images.RemoteImage(
|
|
url=original.remote_url,
|
|
content=self._png_bytes(),
|
|
content_type="image/png",
|
|
final_url=original.remote_url,
|
|
redirected=False,
|
|
)
|
|
with mock.patch("app.image_studio_images.download_remote_image", return_value=remote):
|
|
source = image_studio_images.download_original_asset(
|
|
original.id,
|
|
path=cfg["db_path"],
|
|
config=cfg,
|
|
)
|
|
|
|
submitted = []
|
|
|
|
def fake_submit(method, url, api_key, **kwargs):
|
|
task_id = f"cmhub-task-{len(submitted) + 1}"
|
|
submitted.append(task_id)
|
|
return {
|
|
"task_id": task_id,
|
|
"status": "queued",
|
|
"call_id": f"call-{len(submitted)}",
|
|
"points_cost": 2,
|
|
"points_balance": 100 - len(submitted) * 2,
|
|
}
|
|
|
|
def fake_poll(method, url, api_key, **kwargs):
|
|
task_id = url.rsplit("/", 1)[-1]
|
|
return {
|
|
"task_id": task_id,
|
|
"status": "succeeded",
|
|
"result": {"image_url": f"https://cdn.example.com/{task_id}.png"},
|
|
}
|
|
|
|
with mock.patch("app.image_studio_generation._runtime", return_value=self._runtime()), \
|
|
mock.patch(
|
|
"app.image_studio_generation.ai._cmhub_call_with_retry",
|
|
side_effect=fake_submit,
|
|
), \
|
|
mock.patch("app.image_studio_generation.ai._cmhub_call_once", side_effect=fake_poll), \
|
|
mock.patch(
|
|
"app.image_studio_generation.ai._download_cmhub_image_with_retry",
|
|
return_value=(self._png_bytes(color=(10, 200, 120)), 0.1),
|
|
):
|
|
summary = image_studio_generation.generate_image_jobs(
|
|
project.id,
|
|
source.id,
|
|
"完整提示词",
|
|
2,
|
|
config=cfg,
|
|
path=cfg["db_path"],
|
|
)
|
|
|
|
self.assertEqual(2, summary["success"])
|
|
generated = image_studio.list_assets(project.id, kind="generated_main", path=cfg["db_path"])
|
|
self.assertEqual(2, len(generated))
|
|
image_studio.replace_selections(
|
|
project.id,
|
|
"main",
|
|
[asset.id for asset in generated],
|
|
path=cfg["db_path"],
|
|
)
|
|
image_studio.replace_selections(project.id, "detail", [source.id], path=cfg["db_path"])
|
|
|
|
export_parent = os.path.join(temp_dir, "exports")
|
|
os.makedirs(export_parent)
|
|
result = image_studio_export.export_project_selection(
|
|
project.id,
|
|
export_parent,
|
|
path=cfg["db_path"],
|
|
config=cfg,
|
|
)
|
|
|
|
self.assertEqual(2, result.main_count)
|
|
self.assertEqual(1, result.detail_count)
|
|
self.assertEqual(
|
|
[
|
|
"51100639510_主图_1.jpg",
|
|
"51100639510_主图_2.jpg",
|
|
"51100639510_详情图_1.jpg",
|
|
],
|
|
[os.path.basename(item.output_path) for item in result.files],
|
|
)
|
|
self.assertTrue(all(os.path.isfile(item.output_path) for item in result.files))
|
|
|
|
self.assert_removed(temp_dir)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|