import base64
import pytest
from server.deepsearch.common.exception.exceptions import ReportConvertValidationException
from server.deepsearch.core.manager.report_manager.report_bundle import build_report_bundle
def test_build_report_bundle_writes_infer_and_chart_assets(tmp_path):
"""Validate that report bundle assembly writes inference and chart files.
Args:
tmp_path: pytest 提供的临时目录。
Returns:
None.
"""
final_result = {
"response_content": "正文[结论](#inference:0)\n\n",
"infer_messages": [
{
"id": 0,
"html_base64": base64.b64encode(b"<html>infer</html>").decode("utf-8"),
}
],
"chart_messages": [
{
"chart_id": "chart_0",
"base64": base64.b64encode(b"fakepng").decode("utf-8"),
}
],
"warning_info": "",
"exception_info": "",
}
bundle = build_report_bundle(final_result, tmp_path)
assert bundle.markdown_path.exists()
assert (bundle.root_dir / "infer" / "inference_0.html").exists()
assert (bundle.root_dir / "charts" / "chart_0.png").exists()
assert "infer/inference_0.html" in bundle.markdown_path.read_text(encoding="utf-8")
def test_build_report_bundle_rewrites_chart_placeholders(tmp_path):
"""Validate that VLM chart placeholders are rewritten to bundled image paths.
Args:
tmp_path: pytest 提供的临时目录。
Returns:
None.
"""
final_result = {
"response_content": "(#insertChart:chart_0)\n<font size=2>**图表标题**: 图表说明</font>",
"infer_messages": [],
"chart_messages": [
{
"chart_id": "chart_0",
"chart_title": "图表标题",
"base64": base64.b64encode(b"fakepng").decode("utf-8"),
}
],
"warning_info": "",
"exception_info": "",
}
bundle = build_report_bundle(final_result, tmp_path)
markdown_text = bundle.markdown_path.read_text(encoding="utf-8")
assert "" in markdown_text
assert "(#insertChart:chart_0)" not in markdown_text
def test_build_report_bundle_strips_internal_citation_markers(tmp_path):
"""Validate bundled report markdown hides internal citation control markers.
Args:
tmp_path: pytest 提供的临时目录。
Returns:
None.
"""
final_result = {
"response_content": (
"正文[checked_citation:4][[5]](https://example.com/source)"
"以及旧格式[citation:2]"
),
"infer_messages": [],
"chart_messages": [],
"warning_info": "",
"exception_info": "",
}
bundle = build_report_bundle(final_result, tmp_path)
markdown_text = bundle.markdown_path.read_text(encoding="utf-8")
assert "checked_citation" not in markdown_text
assert "[citation:2]" not in markdown_text
assert "[[5]](https://example.com/source)" in markdown_text
def test_build_report_bundle_raises_validation_exception_when_response_content_empty(tmp_path):
"""Validate empty response_content is treated as a validation error.
Args:
tmp_path: pytest 提供的临时目录。
Returns:
None.
"""
final_result = {
"response_content": "",
"infer_messages": [],
"chart_messages": [],
"warning_info": "",
"exception_info": "",
}
with pytest.raises(ReportConvertValidationException):
build_report_bundle(final_result, tmp_path)
def test_build_report_bundle_raises_validation_exception_when_chart_base64_invalid(tmp_path):
"""Validate invalid chart payloads are surfaced as validation errors.
Args:
tmp_path: pytest 提供的临时目录。
Returns:
None.
"""
final_result = {
"response_content": "(#insertChart:chart_0)",
"infer_messages": [],
"chart_messages": [
{
"chart_id": "chart_0",
"chart_title": "图表标题",
"base64": "not-a-valid-base64$$$",
}
],
"warning_info": "",
"exception_info": "",
}
with pytest.raises(ReportConvertValidationException):
build_report_bundle(final_result, tmp_path)
def test_build_report_bundle_raises_validation_exception_when_chart_id_is_unsafe(tmp_path):
"""Validate chart asset identifiers reject path traversal characters.
Args:
tmp_path: pytest 提供的临时目录。
Returns:
None.
"""
final_result = {
"response_content": "(#insertChart:../../../tmp/escape)",
"infer_messages": [],
"chart_messages": [
{
"chart_id": "../../../tmp/escape",
"chart_title": "图表标题",
"base64": base64.b64encode(b"fakepng").decode("utf-8"),
}
],
"warning_info": "",
"exception_info": "",
}
with pytest.raises(ReportConvertValidationException):
build_report_bundle(final_result, tmp_path)
def test_build_report_bundle_raises_validation_exception_when_chart_placeholder_is_unsafe(tmp_path):
"""Validate chart placeholders reject unsafe path-like identifiers.
Args:
tmp_path: pytest 提供的临时目录。
Returns:
None.
"""
final_result = {
"response_content": "(#insertChart:../../../tmp/escape)",
"infer_messages": [],
"chart_messages": [],
"warning_info": "",
"exception_info": "",
}
with pytest.raises(ReportConvertValidationException):
build_report_bundle(final_result, tmp_path)
def test_build_report_bundle_raises_validation_exception_when_chart_messages_is_not_a_list(tmp_path):
"""Validate malformed chart_messages containers are treated as validation errors.
Args:
tmp_path: pytest 提供的临时目录。
Returns:
None.
"""
final_result = {
"response_content": "正文",
"infer_messages": [],
"chart_messages": "not-a-list",
"warning_info": "",
"exception_info": "",
}
with pytest.raises(ReportConvertValidationException):
build_report_bundle(final_result, tmp_path)