自动高度 自定义高度:1920–30000px,默认 4500px 自定义高度会同步影响画布预览、任务快照、renderDocument、历史恢复和最终 PNG。若内容超过指定高度,系统会阻止导出并提示最低所需高度,不会静默裁掉底部内容。 关键修改: [PosterCreativePanel.vue (line 51)](D:/work/code/python/coding/baodanagent/frontend/src/components/poster/workspace/PosterCreativePanel.vue:51) [PosterHtmlCanvas.vue (line 1)](D:/work/code/python/coding/baodanagent/frontend/src/components/poster/long/PosterHtmlCanvas.vue:1) [poster-exporter.ts (line 95)](D:/work/code/python/coding/baodanagent/frontend/src/utils/poster-exporter.ts:95) [format_registry.py (line 17)](D:/work/code/python/coding/baodanagent/api/insurance/poster/format_registry.py:17) [render_validation.py (line 13)](D:/work/code/python/coding/baodanagent/api/insurance/poster/render_validation.py:13) 验证结果:33 项海报测试通过、Vue 类型检查通过、生产构建通过、UI 静态检查通过
78 lines
3.4 KiB
Python
78 lines
3.4 KiB
Python
"""最终海报文件校验与画布分流回归测试。"""
|
|
import io
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
from PIL import Image
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
sys.path.insert(0, str(ROOT / "api"))
|
|
|
|
|
|
def _png(width: int, height: int) -> bytes:
|
|
buffer = io.BytesIO()
|
|
Image.new("RGB", (width, height), "white").save(buffer, format="PNG")
|
|
return buffer.getvalue()
|
|
|
|
|
|
def test_single_rendered_png_requires_exact_output_dimensions():
|
|
from insurance.poster.render_validation import validate_rendered_png
|
|
|
|
result = validate_rendered_png(_png(1024, 1536), "single_2_3")
|
|
assert result == {"width": 1024, "height": 1536, "format": "PNG"}
|
|
|
|
|
|
def test_wrong_dimensions_and_corrupt_png_are_rejected():
|
|
from insurance.poster.render_validation import PosterRenderValidationError, validate_rendered_png
|
|
|
|
with pytest.raises(PosterRenderValidationError, match="尺寸不匹配"):
|
|
validate_rendered_png(_png(1024, 1400), "single_2_3")
|
|
with pytest.raises(PosterRenderValidationError, match="无法解码"):
|
|
validate_rendered_png(b"\x89PNG\r\n\x1a\nnot-a-real-png", "single_2_3")
|
|
|
|
|
|
def test_long_rendered_png_requires_exact_width_and_safe_height():
|
|
from insurance.poster.render_validation import PosterRenderValidationError, validate_rendered_png
|
|
|
|
assert validate_rendered_png(_png(1242, 3600), "long_1242_auto")["height"] == 3600
|
|
with pytest.raises(PosterRenderValidationError, match="宽度不匹配"):
|
|
validate_rendered_png(_png(1080, 3600), "long_1242_auto")
|
|
|
|
|
|
def test_custom_long_height_requires_exact_output_height():
|
|
from insurance.poster.render_validation import PosterRenderValidationError, validate_rendered_png
|
|
|
|
result = validate_rendered_png(_png(1242, 4500), "long_1242_auto", expected_height=4500)
|
|
assert result["height"] == 4500
|
|
with pytest.raises(PosterRenderValidationError, match="自定义高度"):
|
|
validate_rendered_png(_png(1242, 4600), "long_1242_auto", expected_height=4500)
|
|
|
|
|
|
def test_single_and_long_use_separate_canvas_components():
|
|
stage = (ROOT / "frontend/src/components/poster/workspace/PosterStage.vue").read_text(encoding="utf-8")
|
|
single_canvas = ROOT / "frontend/src/components/poster/single/PosterSingleCanvas.vue"
|
|
|
|
assert single_canvas.exists()
|
|
assert "<PosterSingleCanvas" in stage
|
|
assert "v-if=\"draft.outputMode === 'single'\"" in stage
|
|
assert "<PosterHtmlCanvas" in stage
|
|
|
|
|
|
def test_long_editor_exposes_custom_height_without_silent_crop():
|
|
creative = (ROOT / "frontend/src/components/poster/workspace/PosterCreativePanel.vue").read_text(encoding="utf-8")
|
|
stage = (ROOT / "frontend/src/components/poster/workspace/PosterStage.vue").read_text(encoding="utf-8")
|
|
exporter = (ROOT / "frontend/src/utils/poster-exporter.ts").read_text(encoding="utf-8")
|
|
|
|
assert "自定义高度" in creative
|
|
assert ':custom-output-height="draft.longHeightMode === \'custom\' ? draft.customLongHeight : null"' in stage
|
|
assert "当前内容超出自定义高度" in exporter
|
|
|
|
|
|
def test_background_generation_does_not_claim_final_poster_is_done():
|
|
celery_source = (ROOT / "api/insurance/generation/celery_tasks.py").read_text(encoding="utf-8")
|
|
service_source = (ROOT / "api/insurance/poster/service.py").read_text(encoding="utf-8")
|
|
|
|
assert 'record.task_status = "background_ready"' in celery_source
|
|
assert 'record.task_status = "done"' in service_source
|