"""Tests for AI title generation core (docs/11 §17).""" import shutil import sys import tempfile import unittest from pathlib import Path from PIL import Image sys.path.insert(0, str(Path(__file__).parent.parent / "src")) class TestAiTitleCore(unittest.TestCase): def setUp(self): self.tmp = Path(tempfile.mkdtemp()) def tearDown(self): shutil.rmtree(str(self.tmp), ignore_errors=True) def _make_image(self, path): Image.new("RGB", (32, 32), (120, 80, 40)).save(str(path), format="PNG") def _task(self, garment_path, title="占位标题", product_id=""): from core.models import OutfitTask return OutfitTask(row_index=2, title=title, product_id=product_id, garment_path=str(garment_path)) def test_render_title_prompt_replaces_placeholders(self): from core.ai_title import render_title_prompt task = self._task("g.png", title="旧标题", product_id="TY001") out = render_title_prompt("参考 {title} / {product_id}", task) self.assertEqual(out, "参考 旧标题 / TY001") def test_generate_title_single_file_success(self): from core.ai_title import generate_title garment = self.tmp / "shirt.png" self._make_image(garment) client = _RecordingTextClient("纯棉短袖T恤") result = generate_title(self._task(garment), "起个标题 {title}", model_config={}, api_client=client) self.assertTrue(result.success, result.error) self.assertEqual(result.generated_title, "纯棉短袖T恤") self.assertEqual(client.image_paths, [str(garment)]) def test_generate_title_directory_uses_first_image(self): from core.ai_title import generate_title d = self.tmp / "FG201" d.mkdir() for name in ("b.png", "a.png", "c.png"): self._make_image(d / name) client = _RecordingTextClient("印花连衣裙") result = generate_title(self._task(str(d) + "/"), "话术", model_config={}, api_client=client) self.assertTrue(result.success, result.error) # Sorted: a.png is the first reference image. self.assertEqual(client.image_paths, [str(d / "a.png")]) def test_generate_title_empty_directory_fails(self): from core.ai_title import generate_title d = self.tmp / "empty" d.mkdir() result = generate_title(self._task(str(d) + "/"), "话术", model_config={}, api_client=_RecordingTextClient("x")) self.assertFalse(result.success) self.assertIn("没有图片", result.error) def test_generate_title_client_error_aggregated(self): from core.ai_title import generate_title garment = self.tmp / "shirt.png" self._make_image(garment) result = generate_title(self._task(garment), "话术", model_config={}, api_client=_FailingTextClient()) self.assertFalse(result.success) self.assertIn("boom", result.error) class _RecordingTextClient: def __init__(self, title): self._title = title self.image_paths = [] def generate_text(self, prompt, image_path=None, resolution="1K"): self.image_paths.append(str(image_path)) return self._title class _FailingTextClient: def generate_text(self, prompt, image_path=None, resolution="1K"): raise RuntimeError("boom") if __name__ == "__main__": unittest.main()