from pathlib import Path import sys import pytest sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "api")) pytest.importorskip("pptx") from insurance.ppt.template_asset_service import ( parse_template_pptx, resolve_template_asset, ) @pytest.mark.parametrize( ("asset_id", "expected_slides"), [ ("builtin://single_savings.pptx", 20), ("builtin://multi_savings_comparison.pptx", 17), ("builtin://savings_iul_comprehensive.pptx", 18), ], ) def test_builtin_ppt_templates_are_parseable(asset_id, expected_slides): path = resolve_template_asset(asset_id) assert path assert Path(path).is_file() parsed = parse_template_pptx(path) assert parsed["slideCount"] == expected_slides assert parsed["slidesConfig"][0]["pageType"] == "cover" assert parsed["slidesConfig"][-1]["pageType"] == "closing" def test_template_asset_resolver_blocks_parent_traversal(): with pytest.raises(ValueError, match="路径非法"): resolve_template_asset("builtin://../outside.pptx") def test_renderer_can_reuse_builtin_template_master(tmp_path): from insurance.ppt.scripts.fast_pptx_renderer import render_deck source_path = resolve_template_asset("builtin://single_savings.pptx") output_path = tmp_path / "rendered.pptx" result = render_deck({ "products": [{ "kind": "savings", "productName": "测试储蓄计划", "insured": {"age": 35}, "policy": { "currency": "USD", "annualPremium": 50000, "payYears": 5, }, "benefitRows": [], "withdrawalRows": [], }], "company": {}, "scenarioSlides": [ {"pageType": "cover", "title": "测试模板"}, {"pageType": "closing", "title": "下一步"}, ], "templateConfig": {"sourceTemplatePath": source_path}, }, str(output_path), "deepblue") assert result["ok"] is True assert result["slides"] == 2 assert output_path.is_file()