实现了统一的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>
147 lines
4.5 KiB
Python
147 lines
4.5 KiB
Python
"""
|
|
FontResolver 跨域引用测试
|
|
"""
|
|
|
|
import pytest
|
|
from utils.font_resolver import FontResolver
|
|
from core.elements import FontConfig
|
|
|
|
|
|
class TestFontResolverCrossDomain:
|
|
"""FontResolver 跨域引用测试类"""
|
|
|
|
def test_document_scope_can_reference_template_fonts(self):
|
|
"""测试文档作用域可以引用模板库字体"""
|
|
doc_fonts = {
|
|
"title": {"family": "Arial", "size": 44}
|
|
}
|
|
template_fonts = {
|
|
"base": {"family": "SimSun", "size": 18}
|
|
}
|
|
|
|
resolver = FontResolver(
|
|
fonts=doc_fonts,
|
|
scope="document",
|
|
template_fonts=template_fonts
|
|
)
|
|
|
|
# 引用模板库字体
|
|
result = resolver.resolve_font("@base")
|
|
assert result.family == "SimSun"
|
|
assert result.size == 18
|
|
|
|
def test_document_scope_prioritizes_document_fonts(self):
|
|
"""测试文档作用域优先使用文档字体"""
|
|
doc_fonts = {
|
|
"title": {"family": "Arial", "size": 44}
|
|
}
|
|
template_fonts = {
|
|
"title": {"family": "SimSun", "size": 36}
|
|
}
|
|
|
|
resolver = FontResolver(
|
|
fonts=doc_fonts,
|
|
scope="document",
|
|
template_fonts=template_fonts
|
|
)
|
|
|
|
# 同名字体优先使用文档的
|
|
result = resolver.resolve_font("@title")
|
|
assert result.family == "Arial"
|
|
assert result.size == 44
|
|
|
|
def test_template_scope_cannot_reference_document_fonts(self):
|
|
"""测试模板库作用域不能引用文档字体"""
|
|
doc_fonts = {
|
|
"title": {"family": "Arial", "size": 44}
|
|
}
|
|
template_fonts = {
|
|
"base": {"family": "SimSun", "size": 18}
|
|
}
|
|
|
|
resolver = FontResolver(
|
|
fonts=template_fonts,
|
|
scope="template",
|
|
template_fonts=template_fonts
|
|
)
|
|
|
|
# 尝试引用文档字体应该失败
|
|
with pytest.raises(ValueError, match="引用的字体配置不存在"):
|
|
resolver.resolve_font("@title")
|
|
|
|
def test_template_scope_can_reference_template_fonts(self):
|
|
"""测试模板库作用域可以引用模板库字体"""
|
|
template_fonts = {
|
|
"base": {"family": "SimSun", "size": 18},
|
|
"title": {"parent": "@base", "size": 36}
|
|
}
|
|
|
|
resolver = FontResolver(
|
|
fonts=template_fonts,
|
|
scope="template",
|
|
template_fonts=template_fonts
|
|
)
|
|
|
|
# 引用模板库字体
|
|
result = resolver.resolve_font("@title")
|
|
assert result.family == "SimSun"
|
|
assert result.size == 36
|
|
|
|
def test_cross_domain_circular_reference_detection(self):
|
|
"""测试跨域循环引用检测"""
|
|
doc_fonts = {
|
|
"a": {"parent": "@b"}
|
|
}
|
|
template_fonts = {
|
|
"b": {"parent": "@a"}
|
|
}
|
|
|
|
resolver = FontResolver(
|
|
fonts=doc_fonts,
|
|
scope="document",
|
|
template_fonts=template_fonts
|
|
)
|
|
|
|
# 应该检测到跨域循环引用
|
|
with pytest.raises(ValueError, match="检测到.*字体引用循环"):
|
|
resolver.resolve_font("@a")
|
|
|
|
def test_document_parent_can_reference_template_fonts(self):
|
|
"""测试文档字体的 parent 可以引用模板库字体"""
|
|
doc_fonts = {
|
|
"custom": {"parent": "@base", "bold": True}
|
|
}
|
|
template_fonts = {
|
|
"base": {"family": "SimSun", "size": 18}
|
|
}
|
|
|
|
resolver = FontResolver(
|
|
fonts=doc_fonts,
|
|
scope="document",
|
|
template_fonts=template_fonts
|
|
)
|
|
|
|
result = resolver.resolve_font("@custom")
|
|
assert result.family == "SimSun"
|
|
assert result.size == 18
|
|
assert result.bold is True
|
|
|
|
def test_template_parent_cannot_reference_document_fonts(self):
|
|
"""测试模板库字体的 parent 不能引用文档字体"""
|
|
doc_fonts = {
|
|
"doc-base": {"family": "Arial", "size": 18}
|
|
}
|
|
template_fonts = {
|
|
"custom": {"parent": "@doc-base", "bold": True}
|
|
}
|
|
|
|
resolver = FontResolver(
|
|
fonts=template_fonts,
|
|
scope="template",
|
|
template_fonts=template_fonts
|
|
)
|
|
|
|
# 应该失败
|
|
with pytest.raises(ValueError, match="模板元素不能引用文档的字体配置"):
|
|
resolver.resolve_font("@custom")
|