feat: 为metadata、模板和幻灯片添加description字段支持
添加可选的description字段用于文档目的,不影响渲染输出。 主要更改: - core/presentation.py: 添加metadata.description属性 - core/template.py: 添加template.description属性 - tests: 添加16个新测试用例验证description功能 - docs: 更新README.md和README_DEV.md文档 - specs: 新增page-description规范文件
This commit is contained in:
@@ -600,3 +600,161 @@ slides:
|
||||
assert result["elements"][1].content == "Template2"
|
||||
assert result["elements"][2].content == "Custom1"
|
||||
assert result["elements"][3].content == "Custom2"
|
||||
|
||||
|
||||
# ============= Description 字段测试 =============
|
||||
|
||||
|
||||
class TestPresentationDescription:
|
||||
"""Presentation description 字段测试类"""
|
||||
|
||||
def test_metadata_with_description(self, temp_dir):
|
||||
"""测试 metadata 包含 description 字段时正确加载"""
|
||||
yaml_content = """
|
||||
metadata:
|
||||
title: "测试演示文稿"
|
||||
description: "这是关于项目年度总结的演示文稿"
|
||||
size: "16:9"
|
||||
slides:
|
||||
- elements: []
|
||||
"""
|
||||
yaml_path = temp_dir / "test.yaml"
|
||||
yaml_path.write_text(yaml_content)
|
||||
|
||||
pres = Presentation(str(yaml_path))
|
||||
|
||||
assert pres.description == "这是关于项目年度总结的演示文稿"
|
||||
|
||||
def test_metadata_without_description(self, temp_dir):
|
||||
"""测试 metadata 不包含 description 字段时正常工作"""
|
||||
yaml_content = """
|
||||
metadata:
|
||||
title: "测试演示文稿"
|
||||
size: "16:9"
|
||||
slides:
|
||||
- elements: []
|
||||
"""
|
||||
yaml_path = temp_dir / "test.yaml"
|
||||
yaml_path.write_text(yaml_content)
|
||||
|
||||
pres = Presentation(str(yaml_path))
|
||||
|
||||
assert pres.description is None
|
||||
|
||||
def test_metadata_description_empty_string(self, temp_dir):
|
||||
"""测试 metadata description 为空字符串时正常工作"""
|
||||
yaml_content = """
|
||||
metadata:
|
||||
title: "测试演示文稿"
|
||||
description: ""
|
||||
size: "16:9"
|
||||
slides:
|
||||
- elements: []
|
||||
"""
|
||||
yaml_path = temp_dir / "test.yaml"
|
||||
yaml_path.write_text(yaml_content)
|
||||
|
||||
pres = Presentation(str(yaml_path))
|
||||
|
||||
assert pres.description == ""
|
||||
|
||||
def test_metadata_description_chinese_characters(self, temp_dir):
|
||||
"""测试 metadata description 包含中文字符时正确处理"""
|
||||
yaml_content = """
|
||||
metadata:
|
||||
title: "测试"
|
||||
description: "这是关于项目的演示文稿,包含中文和特殊字符:测试、验证、确认"
|
||||
size: "16:9"
|
||||
slides:
|
||||
- elements: []
|
||||
"""
|
||||
yaml_path = temp_dir / "test.yaml"
|
||||
yaml_path.write_text(yaml_content)
|
||||
|
||||
pres = Presentation(str(yaml_path))
|
||||
|
||||
assert "这是关于项目的演示文稿" in pres.description
|
||||
assert "中文" in pres.description
|
||||
|
||||
|
||||
class TestSlideDescription:
|
||||
"""Slide description 字段测试类"""
|
||||
|
||||
def test_slide_with_description(self, sample_yaml):
|
||||
"""测试幻灯片包含 description 字段时正确加载"""
|
||||
pres = Presentation(str(sample_yaml))
|
||||
|
||||
slide_data = {
|
||||
"description": "介绍项目背景和目标",
|
||||
"elements": [
|
||||
{"type": "text", "content": "Test", "box": [0, 0, 1, 1], "font": {}}
|
||||
]
|
||||
}
|
||||
|
||||
result = pres.render_slide(slide_data)
|
||||
|
||||
assert result["description"] == "介绍项目背景和目标"
|
||||
|
||||
def test_slide_without_description(self, sample_yaml):
|
||||
"""测试幻灯片不包含 description 字段时正常工作"""
|
||||
pres = Presentation(str(sample_yaml))
|
||||
|
||||
slide_data = {
|
||||
"elements": [
|
||||
{"type": "text", "content": "Test", "box": [0, 0, 1, 1], "font": {}}
|
||||
]
|
||||
}
|
||||
|
||||
result = pres.render_slide(slide_data)
|
||||
|
||||
assert result["description"] is None
|
||||
|
||||
def test_slide_description_empty_string(self, sample_yaml):
|
||||
"""测试幻灯片 description 为空字符串时正常工作"""
|
||||
pres = Presentation(str(sample_yaml))
|
||||
|
||||
slide_data = {
|
||||
"description": "",
|
||||
"elements": [
|
||||
{"type": "text", "content": "Test", "box": [0, 0, 1, 1], "font": {}}
|
||||
]
|
||||
}
|
||||
|
||||
result = pres.render_slide(slide_data)
|
||||
|
||||
assert result["description"] == ""
|
||||
|
||||
def test_slide_description_chinese_characters(self, sample_yaml):
|
||||
"""测试幻灯片 description 包含中文字符时正确处理"""
|
||||
pres = Presentation(str(sample_yaml))
|
||||
|
||||
slide_data = {
|
||||
"description": "这是幻灯片描述,包含中文内容",
|
||||
"elements": [
|
||||
{"type": "text", "content": "Test", "box": [0, 0, 1, 1], "font": {}}
|
||||
]
|
||||
}
|
||||
|
||||
result = pres.render_slide(slide_data)
|
||||
|
||||
assert "这是幻灯片描述" in result["description"]
|
||||
assert "中文" in result["description"]
|
||||
|
||||
def test_slide_description_does_not_affect_rendering(self, sample_yaml):
|
||||
"""测试 description 不影响渲染输出"""
|
||||
pres = Presentation(str(sample_yaml))
|
||||
|
||||
slide_data = {
|
||||
"description": "这段描述不应该影响渲染",
|
||||
"elements": [
|
||||
{"type": "text", "content": "Test Content", "box": [0, 0, 1, 1], "font": {}}
|
||||
]
|
||||
}
|
||||
|
||||
result = pres.render_slide(slide_data)
|
||||
|
||||
# description 字段存在但不影响元素渲染
|
||||
assert result["description"] == "这段描述不应该影响渲染"
|
||||
assert len(result["elements"]) == 1
|
||||
assert result["elements"][0].content == "Test Content"
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import pytest
|
||||
from pathlib import Path
|
||||
from loaders.yaml_loader import YAMLError
|
||||
from core.template import Template
|
||||
from core.presentation import Presentation
|
||||
|
||||
|
||||
# ============= 模板初始化测试 =============
|
||||
@@ -892,3 +893,165 @@ slides:
|
||||
slide_data = pres.data['slides'][0]
|
||||
rendered = pres.render_slide(slide_data)
|
||||
assert len(rendered['elements']) == 1
|
||||
|
||||
|
||||
# ============= Description 字段测试 =============
|
||||
|
||||
|
||||
class TestTemplateDescription:
|
||||
"""Template description 字段测试类"""
|
||||
|
||||
def test_template_with_description(self, temp_dir):
|
||||
"""测试模板包含 description 字段时正确加载"""
|
||||
template_content = """
|
||||
description: "用于章节标题页的模板,包含主标题和副标题"
|
||||
vars:
|
||||
- name: title
|
||||
required: true
|
||||
- name: subtitle
|
||||
required: false
|
||||
default: ""
|
||||
elements:
|
||||
- type: text
|
||||
content: "{title}"
|
||||
box: [1, 1, 8, 1]
|
||||
font:
|
||||
size: 44
|
||||
bold: true
|
||||
- type: text
|
||||
content: "{subtitle}"
|
||||
box: [1, 2, 8, 1]
|
||||
font:
|
||||
size: 24
|
||||
"""
|
||||
template_path = temp_dir / "test-template.yaml"
|
||||
template_path.write_text(template_content)
|
||||
|
||||
template = Template("test-template", templates_dir=temp_dir)
|
||||
|
||||
assert template.description == "用于章节标题页的模板,包含主标题和副标题"
|
||||
|
||||
def test_template_without_description(self, sample_template):
|
||||
"""测试模板不包含 description 字段时正常工作"""
|
||||
template = Template("title-slide", templates_dir=sample_template)
|
||||
|
||||
assert template.description is None
|
||||
|
||||
def test_template_description_empty_string(self, temp_dir):
|
||||
"""测试模板 description 为空字符串时正常工作"""
|
||||
template_content = """
|
||||
description: ""
|
||||
vars:
|
||||
- name: title
|
||||
elements:
|
||||
- type: text
|
||||
content: "{title}"
|
||||
box: [1, 1, 8, 1]
|
||||
font: {}
|
||||
"""
|
||||
template_path = temp_dir / "test-template.yaml"
|
||||
template_path.write_text(template_content)
|
||||
|
||||
template = Template("test-template", templates_dir=temp_dir)
|
||||
|
||||
assert template.description == ""
|
||||
|
||||
def test_template_description_chinese_characters(self, temp_dir):
|
||||
"""测试模板 description 包含中文字符时正确处理"""
|
||||
template_content = """
|
||||
description: "这是中文模板描述,用于标题页面"
|
||||
vars:
|
||||
- name: title
|
||||
elements:
|
||||
- type: text
|
||||
content: "{title}"
|
||||
box: [1, 1, 8, 1]
|
||||
font: {}
|
||||
"""
|
||||
template_path = temp_dir / "test-template.yaml"
|
||||
template_path.write_text(template_content)
|
||||
|
||||
template = Template("test-template", templates_dir=temp_dir)
|
||||
|
||||
assert "这是中文模板描述" in template.description
|
||||
assert "标题页面" in template.description
|
||||
|
||||
def test_template_description_multiline(self, temp_dir):
|
||||
"""测试模板 description 支持多行文本"""
|
||||
template_content = """
|
||||
description: |
|
||||
这是一个多行描述。
|
||||
第一行说明模板的用途。
|
||||
第二行说明使用场景。
|
||||
vars:
|
||||
- name: title
|
||||
elements:
|
||||
- type: text
|
||||
content: "{title}"
|
||||
box: [1, 1, 8, 1]
|
||||
font: {}
|
||||
"""
|
||||
template_path = temp_dir / "test-template.yaml"
|
||||
template_path.write_text(template_content)
|
||||
|
||||
template = Template("test-template", templates_dir=temp_dir)
|
||||
|
||||
# 多行文本应该被正确读取
|
||||
assert "这是一个多行描述" in template.description
|
||||
assert "第一行说明模板的用途" in template.description
|
||||
assert "第二行说明使用场景" in template.description
|
||||
|
||||
def test_inline_template_with_description(self, temp_dir):
|
||||
"""测试内联模板包含 description 字段"""
|
||||
yaml_content = """
|
||||
metadata:
|
||||
size: "16:9"
|
||||
|
||||
templates:
|
||||
test-template:
|
||||
description: "内联模板描述"
|
||||
vars:
|
||||
- name: title
|
||||
elements:
|
||||
- type: text
|
||||
content: "{title}"
|
||||
box: [1, 1, 8, 1]
|
||||
font: {}
|
||||
|
||||
slides:
|
||||
- template: test-template
|
||||
vars:
|
||||
title: "Test"
|
||||
"""
|
||||
yaml_path = temp_dir / "test.yaml"
|
||||
yaml_path.write_text(yaml_content)
|
||||
|
||||
pres = Presentation(str(yaml_path))
|
||||
template = pres.get_template("test-template")
|
||||
|
||||
assert template.description == "内联模板描述"
|
||||
|
||||
def test_template_description_does_not_affect_rendering(self, temp_dir):
|
||||
"""测试 description 不影响模板渲染"""
|
||||
template_content = """
|
||||
description: "这段描述不应该影响渲染"
|
||||
vars:
|
||||
- name: title
|
||||
elements:
|
||||
- type: text
|
||||
content: "{title}"
|
||||
box: [1, 1, 8, 1]
|
||||
font:
|
||||
size: 44
|
||||
"""
|
||||
template_path = temp_dir / "test-template.yaml"
|
||||
template_path.write_text(template_content)
|
||||
|
||||
template = Template("test-template", templates_dir=temp_dir)
|
||||
|
||||
# 渲染应该正常工作,description 不影响结果
|
||||
result = template.render({"title": "Test Title"})
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0]["content"] == "Test Title"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user