from pathlib import Path from PIL import Image, ImageDraw, ImageFont from app.service.promotion_poster_renderer import PromotionPosterRenderer def _draft(style_code: str) -> dict[str, object]: return { "style_code": style_code, "title": "测试基金产品推介材料", "chapters": [ {"title": "产品基本信息", "body": "基金类型:混合型\n运作方式:开放式"}, {"title": "投资范围、策略与限制", "body": "股票和债券,长期配置"}, {"title": "管理人及投研团队", "body": "管理人:测试基金管理有限公司"}, {"title": "收益与风险指标", "body": "产品收益 8%,最大回撤 -5%,夏普比率 0.8"}, ], } def test_poster_renderer_creates_readable_dark_reference_style(tmp_path: Path) -> None: output = tmp_path / "dark-poster.png" result = PromotionPosterRenderer().render( _draft("balanced_allocation"), output, ) assert result == str(output) with Image.open(output) as image: assert image.size == (1800, 2600) assert image.getpixel((10, 10)) == (14, 59, 102) def test_poster_renderer_creates_readable_warm_reference_style(tmp_path: Path) -> None: output = tmp_path / "warm-poster.png" PromotionPosterRenderer().render( _draft("steady_professional"), output, ) with Image.open(output) as image: assert image.size == (1800, 2600) assert image.getpixel((10, 10)) == (201, 76, 47) def test_poster_renderer_uses_theme_panels_instead_of_white(tmp_path: Path) -> None: output = tmp_path / "theme-panel-poster.png" PromotionPosterRenderer().render( _draft("balanced_allocation"), output, ) with Image.open(output) as image: assert image.getpixel((120, 620)) == (220, 234, 243) assert image.getpixel((600, 1200)) == (220, 234, 243) assert image.getpixel((120, 620)) != (255, 255, 255) def test_poster_renderer_fills_ai_background_and_footer_without_white_bands( tmp_path: Path, ) -> None: background = tmp_path / "square-background.png" output = tmp_path / "filled-poster.png" Image.new("RGB", (1024, 1024), color=(80, 92, 106)).save(background) PromotionPosterRenderer().render( _draft("balanced_allocation"), output, background_path=str(background), ) with Image.open(output) as image: assert image.getpixel((900, 2450)) != (255, 255, 255) assert image.getpixel((900, 2570)) != (255, 255, 255) def test_long_strategy_text_changes_ai_50_50_ratio_and_fits_panel() -> None: renderer = PromotionPosterRenderer() image = Image.new("RGB", (1800, 2600), "white") draw = ImageDraw.Draw(image) font = ImageFont.truetype(r"C:\Windows\Fonts\msyh.ttc", 24) strategy = "围绕宏观周期、估值水平和基本面趋势开展多资产配置," * 20 ratio, fitted_font = renderer._resolve_two_column_layout( draw, "基金类型:混合型", strategy, total_width=1620, height=320, requested_ratio=0.5, font=font, ) right_width = 1620 - 54 - int((1620 - 54) * ratio) - 68 assert ratio == 0.4 assert renderer._text_fits(draw, strategy, right_width, 260, fitted_font)