1
0
Files
PPTX/tests/integration/test_presentation.py
lanyuanxiaoyao 98098dc911 feat: 实现模板库metadata和跨域字体引用系统
实现了统一的metadata结构和字体作用域系统,支持文档和模板库之间的单向字体引用。

主要变更:
- 模板库必须包含metadata字段(包括size、fonts、fonts_default)
- 实现文档和模板库的size一致性校验
- 实现字体作用域系统(文档可引用模板库字体,反之不可)
- 实现跨域循环引用检测
- 实现fonts_default级联规则(模板库→文档→系统默认)
- 添加错误代码常量(SIZE_MISMATCH、FONT_NOT_FOUND等)
- 更新文档和开发者指南

测试覆盖:
- 新增33个测试(单元测试20个,集成测试13个)
- 所有457个测试通过

Breaking Changes:
- 模板库文件必须包含metadata字段
- 模板库metadata.size为必填字段
- 文档和模板库的size必须一致

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-05 18:12:05 +08:00

242 lines
6.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Presentation 类集成测试
测试 Presentation 类的模板加载和幻灯片渲染功能
"""
import pytest
from pathlib import Path
from core.presentation import Presentation
class TestPresentationInit:
"""Presentation 初始化测试"""
def test_init_with_yaml(self, sample_yaml):
"""测试使用 YAML 文件初始化"""
pres = Presentation(str(sample_yaml))
assert pres.data is not None
assert "slides" in pres.data
def test_render_simple_slide(self, sample_yaml):
"""测试渲染简单幻灯片"""
pres = Presentation(str(sample_yaml))
slide_data = pres.data["slides"][0]
rendered = pres.render_slide(slide_data)
assert "elements" in rendered
assert len(rendered["elements"]) > 0
def test_render_slide_with_template(self, temp_dir, sample_template):
"""测试渲染使用模板的幻灯片"""
yaml_content = f"""
metadata:
size: "16:9"
slides:
- template: title-slide
vars:
title: "Test Title"
subtitle: "Test Subtitle"
"""
yaml_path = temp_dir / "test.yaml"
yaml_path.write_text(yaml_content)
pres = Presentation(str(yaml_path), str(sample_template))
slide_data = pres.data["slides"][0]
rendered = pres.render_slide(slide_data)
# 模板变量应该被替换
elements = rendered["elements"]
title_elem = next(
e for e in elements if e.type == "text" and "Test Title" in e.content
)
assert title_elem is not None
def test_render_slide_with_conditional_element(self, temp_dir, sample_template):
"""测试条件渲染元素"""
# 有 subtitle 的情况
yaml_with = f"""
metadata:
size: "16:9"
slides:
- template: title-slide
vars:
title: "Test"
subtitle: "With Subtitle"
"""
yaml_path_with = temp_dir / "test_with.yaml"
yaml_path_with.write_text(yaml_with)
pres_with = Presentation(str(yaml_path_with), str(sample_template))
slide_data = pres_with.data["slides"][0]
rendered_with = pres_with.render_slide(slide_data)
# 应该有 2 个元素title 和 subtitle 都显示)
assert len(rendered_with["elements"]) == 2
# 没有 subtitle 的情况
yaml_without = f"""
metadata:
size: "16:9"
slides:
- template: title-slide
vars:
title: "Test"
"""
yaml_path_without = temp_dir / "test_without.yaml"
yaml_path_without.write_text(yaml_without)
pres_without = Presentation(str(yaml_path_without), str(sample_template))
slide_data = pres_without.data["slides"][0]
rendered_without = pres_without.render_slide(slide_data)
# 应该只有 1 个元素subtitle 不显示)
assert len(rendered_without["elements"]) == 1
def test_render_slide_with_variables(self, temp_dir, sample_template):
"""测试变量传递"""
yaml_content = f"""
metadata:
size: "16:9"
slides:
- template: title-slide
vars:
title: "My Title"
subtitle: "My Subtitle"
"""
yaml_path = temp_dir / "test.yaml"
yaml_path.write_text(yaml_content)
pres = Presentation(str(yaml_path), str(sample_template))
slide_data = pres.data["slides"][0]
rendered = pres.render_slide(slide_data)
# 检查变量是否被正确替换
elements = rendered["elements"]
assert any("My Title" in e.content for e in elements)
assert any("My Subtitle" in e.content for e in elements)
class TestPresentationWithoutTemplate:
"""无模板的演示文稿测试"""
def test_render_direct_elements(self, temp_dir):
"""测试直接渲染元素(不使用模板)"""
yaml_content = """
metadata:
size: "16:9"
slides:
- elements:
- type: text
box: [1, 1, 8, 1]
content: "Direct Text"
font:
size: 24
"""
yaml_path = temp_dir / "test.yaml"
yaml_path.write_text(yaml_content)
pres = Presentation(str(yaml_path))
slide_data = pres.data["slides"][0]
rendered = pres.render_slide(slide_data)
# 元素应该直接被渲染
assert len(rendered["elements"]) == 1
assert rendered["elements"][0].content == "Direct Text"
class TestPresentationPathResolution:
"""路径解析测试"""
def test_relative_path_resolution(self, temp_dir):
"""测试相对路径解析(子目录场景)"""
# 创建子目录结构
subdir = temp_dir / "subdir"
subdir.mkdir()
yaml_content = """
metadata:
size: "16:9"
slides:
- elements:
- type: text
box: [1, 1, 8, 1]
content: "Test"
"""
yaml_path = subdir / "test.yaml"
yaml_path.write_text(yaml_content)
# 使用相对路径初始化
import os
original_cwd = os.getcwd()
try:
os.chdir(temp_dir)
pres = Presentation("subdir/test.yaml")
# 验证路径已被解析为绝对路径
assert pres.pres_base_dir.is_absolute()
assert pres.pres_base_dir == subdir
finally:
os.chdir(original_cwd)
def test_template_path_resolution(self, temp_dir):
"""测试模板路径解析(子目录场景)"""
# 创建子目录结构
doc_dir = temp_dir / "docs"
template_dir = temp_dir / "templates"
doc_dir.mkdir()
template_dir.mkdir()
# 创建模板库文件
template_content = """
metadata:
size: "16:9"
templates:
test-template:
vars:
- name: title
required: true
elements:
- type: text
box: [1, 1, 8, 1]
content: "{title}"
"""
template_path = template_dir / "templates.yaml"
template_path.write_text(template_content)
# 创建文档文件
yaml_content = """
metadata:
size: "16:9"
slides:
- template: test-template
vars:
title: "Test Title"
"""
yaml_path = doc_dir / "test.yaml"
yaml_path.write_text(yaml_content)
# 使用相对路径初始化
import os
original_cwd = os.getcwd()
try:
os.chdir(temp_dir)
pres = Presentation("docs/test.yaml", template_file="templates/templates.yaml")
# 验证路径已被解析为绝对路径
assert pres.pres_base_dir.is_absolute()
assert pres.template_base_dir.is_absolute()
assert pres.pres_base_dir == doc_dir
assert pres.template_base_dir == template_dir
finally:
os.chdir(original_cwd)