Files
group_fqcd_jr/tests/unit/service/test_promotion_renderer.py
T

94 lines
3.5 KiB
Python
Raw Normal View History

2026-09-11 16:57:47 +08:00
from pathlib import Path
from PIL import Image
from pptx import Presentation
from app.service.promotion_pdf_adapter import PromotionPdfAdapter
from app.service.promotion_renderer import PromotionPptxRenderer
def _draft(style_code: str = "balanced_allocation") -> dict[str, object]:
return {
"style_code": style_code,
"subtitle": "测试产品 产品推介材料",
"chapters": [
{"title": "测试产品", "body": "仅供合规审核和专业投顾使用"},
{"title": "产品基本信息", "body": "基金类型:混合型\n运作方式:开放式"},
{"title": "收益与风险指标", "body": "最大回撤反映历史区间内的最大跌幅。"},
{
"title": "风险揭示",
"body": (
"基金的过往业绩并不预示其未来表现,"
"基金管理人管理的其他基金的业绩并不构成基金业绩表现的保证。"
),
},
],
}
def test_renderer_creates_readable_pptx_with_fixed_slide_order(tmp_path: Path) -> None:
output = tmp_path / "material.pptx"
result = PromotionPptxRenderer().render(_draft(), output)
assert result == str(output)
assert output.is_file()
presentation = Presentation(output)
assert len(presentation.slides) == 4
titles = [
slide.shapes[1].text
for slide in presentation.slides
if len(slide.shapes) > 1 and hasattr(slide.shapes[1], "text")
]
assert titles[:3] == ["测试产品", "产品基本信息", "收益与风险指标"]
def test_renderer_keeps_style_code_outside_content_layout(tmp_path: Path) -> None:
first = tmp_path / "first.pptx"
second = tmp_path / "second.pptx"
PromotionPptxRenderer().render(_draft("steady_professional"), first)
changed = _draft("steady_professional")
changed["chapters"] = [
{"title": "另一个标题", "body": "内容发生变化"},
{"title": "第二页", "body": "第二组内容"},
]
PromotionPptxRenderer().render(changed, second)
first_presentation = Presentation(first)
second_presentation = Presentation(second)
assert first_presentation.slide_width == second_presentation.slide_width
assert first_presentation.slide_height == second_presentation.slide_height
def test_pdf_adapter_does_not_claim_conversion_without_converter() -> None:
adapter = PromotionPdfAdapter(enabled=False)
assert adapter.convert("missing.pptx", "output.pdf") is None
def test_renderer_preserves_photo_aspect_ratio(tmp_path: Path) -> None:
photo = tmp_path / "manager.png"
Image.new("RGB", (800, 600), color="white").save(photo)
output = tmp_path / "material-with-photo.pptx"
PromotionPptxRenderer().render(_draft(), output, photo_path=str(photo))
presentation = Presentation(output)
picture = next(shape for shape in presentation.slides[0].shapes if shape.shape_type == 13)
assert round(picture.width / picture.height, 2) == round(800 / 600, 2)
def test_renderer_applies_reference_palette_to_cover_and_content_slides(
tmp_path: Path,
) -> None:
output = tmp_path / "styled-material.pptx"
PromotionPptxRenderer().render(_draft("steady_professional"), output)
presentation = Presentation(output)
cover = presentation.slides[0]
content = presentation.slides[1]
assert cover.shapes[0].fill.fore_color.rgb == (201, 76, 47)
assert content.shapes[0].fill.fore_color.rgb == (255, 249, 242)