baodan/tests/poster_render_validation_test.py

92 lines
4.0 KiB
Python
Raw Normal View History

2026-07-31 21:42:32 +08:00
"""最终海报文件校验与画布分流回归测试。"""
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)
2026-07-31 21:42:32 +08:00
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
2026-07-31 21:42:32 +08:00
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
主要修复: 海报加载失败根因:html-to-image 给 blob: 底图地址追加缓存参数,导致地址失效。现已关闭该行为。 合成失败后再次点击“重新生成”,会复用已有 AI 底图,只重试浏览器合成和上传,避免重复调用 AI。 增加底图加载、图表超时、导出失败、尺寸越界等分阶段错误提示。 修复计划书 (cid:数字) 字体乱码被误判为正常文本的问题,现在会正确转入 OCR。 增加繁体中文 OCR 运行支持。 补齐 SIUL 文件名中的确定字段,并且不会覆盖正文已识别数据。 增加“首期规划保费/償還至形成基金所需保費”等保费标签识别。 修正 IUL 年龄、保额、退保价值、缴费期、公司信息等字段映射。 LLM 返回空对象或缺字段时不再视为成功。 增加错误利益数值和年龄/保单年度错位校验。 修复依赖版本降级导致 API/Worker 无法启动的风险。 真实计划书复验结果: 产品:Manulife SIUL 3 投保年龄:48 岁 性别:女性 吸烟状态:非吸烟 币种:USD 基本保额:3,000,000 年缴保费:80,060 缴费期:5 年 利益演示:识别到 10 行 验证结果: 后端相关回归测试:91 passed 前端生产构建:通过 API、数据库、Redis、存储、数据表健康检查:全部正常 Celery Worker:已重启并连接 Redis 真实 PDF:确认进入 OCR,不再使用 (cid:...) 乱码 前端构建目录由运行容器挂载,修复已生效
2026-07-31 23:35:45 +08:00
def test_failed_client_composition_reuses_existing_background_and_exposes_stage_error():
page = (ROOT / "frontend/src/pages/PosterPage.vue").read_text(encoding="utf-8")
exporter = (ROOT / "frontend/src/utils/poster-exporter.ts").read_text(encoding="utf-8")
assert "retryExistingComposite" in page
assert "系统不会重新生成 AI 底图" in page
assert "BACKGROUND_DECODE_FAILED" in page
assert "ASSET_WAIT_FAILED" in page
assert "RENDER_UPLOAD_FAILED" in page
assert "CHART_RENDER_TIMEOUT" in exporter
assert "OUTPUT_HEIGHT_UNSAFE" in exporter
assert "cacheBust: false" in exporter