CounterDroneBackend/test/unit/CounterDrone.Core.Tests/StandardPdfTemplateTests.cs
tian 8bcf4cf675 VERSION 0.12.0 — PDF 导出 + 报告模板架构 + 对接文档 V2.0
- PdfSharpCore 1.3.64 引入(纯托管,Unity IL2CPP 兼容,+9 DLL)
- ReportData 结构化模型 + MarkdownRenderer + StandardPdfTemplate
- IReportService.ExportReport(id, format) 按需导出 PDF/MD
- 仿真后自动生成 MD 到 reports 目录,PDF 按需调用
- CJK 字体嵌入(SimHei),IPathProvider + GetFontPath
- ReportGenerator 重构为构建 ReportData,去掉 emoji
- check_unity_build.ps1 修复 -quit 参数缺失导致超时
- 对接文档 V2.0:坐标系/3D 可视化/完整枚举/Manager 签名/模型字段
- 262 测试全部通过
2026-06-20 11:57:38 +08:00

122 lines
4.5 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using CounterDrone.Core;
using CounterDrone.Core.Reporting;
using Xunit;
namespace CounterDrone.Core.Tests
{
public class StandardPdfTemplateTests : IDisposable
{
private readonly string _testDir;
public StandardPdfTemplateTests()
{
_testDir = Path.Combine(Path.GetTempPath(), $"cd_pdf_{Guid.NewGuid():N}");
var paths = new TestPathProvider(_testDir);
}
public void Dispose()
{
if (Directory.Exists(_testDir)) Directory.Delete(_testDir, true);
}
private static ReportData CreateSampleReport()
{
return new ReportData
{
Title = "仿真评估报告",
Header = new List<MetaItem>
{
new() { Label = "任务名称", Value = "城市防御测试" },
new() { Label = "任务编号", Value = "SIM-001" },
new() { Label = "仿真耗时", Value = "45.0 秒" },
},
Sections = new List<ReportSection>
{
new()
{
Title = "一、仿真结果",
Blocks = new List<ReportBlock>
{
new KeyValueBlock
{
LabelHeader = "统计项",
Items = new List<MetaItem>
{
new() { Label = "无人机总数", Value = "3" },
new() { Label = "被摧毁", Value = "3" },
new() { Label = "弹药发射", Value = "6" },
},
},
new TextBlock { Text = "对抗结果:✅ 成功拦截", Bold = true },
},
},
new()
{
Title = "六、事件时序",
Blocks = new List<ReportBlock>
{
new TableBlock
{
Headers = new[] { "时间(s)", "事件", "详情", "火力单元" },
Rows = new List<string[]>
{
new[] { "1.50", "🚀 弹药发射", "第 1 发 · 发射", "#1" },
new[] { "5.00", "☁️ 云团生成", "云团 #1 · 生成", "-" },
new[] { "8.30", "💥 目标击毁", "目标被摧毁", "-" },
},
},
},
},
},
};
}
[Fact]
public void Render_ReturnsValidPdf()
{
var paths = new TestPathProvider(_testDir);
var template = new StandardPdfTemplate(paths.GetFontPath(), "CJK");
var pdf = template.Render(CreateSampleReport());
Assert.NotEmpty(pdf);
// PDF 文件头:%PDF
Assert.Equal(0x25, pdf[0]); // %
Assert.Equal(0x50, pdf[1]); // P
Assert.Equal(0x44, pdf[2]); // D
Assert.Equal(0x46, pdf[3]); // F
}
[Fact]
public void Render_MultiplePages_HandlesLongContent()
{
var data = CreateSampleReport();
// 添加大量事件行以触发分页
var eventRows = new List<string[]>();
for (int i = 0; i < 200; i++)
eventRows.Add(new[] { $"{i * 0.1:F1}", "🚀 弹药发射", $"第 {i + 1} 发 · 测试事件 {i}", $"#{(i % 3) + 1}" });
data.Sections.Add(new ReportSection
{
Title = "大量事件",
Blocks = new List<ReportBlock>
{
new TableBlock
{
Headers = new[] { "时间(s)", "事件", "详情", "单元" },
Rows = eventRows,
},
},
});
var paths = new TestPathProvider(_testDir);
var template = new StandardPdfTemplate(paths.GetFontPath(), "CJK");
var pdf = template.Render(data);
Assert.NotEmpty(pdf);
Assert.True(pdf.Length > 10000, $"PDF 应有多个页面,大小 {pdf.Length} bytes");
}
}
}