Files
sundynix-agentix/sundynix-mcp-go/internal/office/unioffice_test.go
T
Blizzard 9b0520e020 test(backend): 编排引擎/DSL/docx/报告导出 首批 Go 单测(19 用例,纯逻辑无依赖)
补齐核心后端逻辑的自动化测试,全部纯函数级、不依赖 docker/NATS/LLM,毫秒级跑完,
把"手动起全栈 curl 验证"变成 `go test`:

- dispatcher/internal/eino (graph_test.go)
  evalCondition(各运算符+refs/tools/answer/profile 关键字+兜底)、resolveOperand、
  aggregate(拼接/去重合并/默认/全空)、branchNode(真假边标签精确选路 + 无标签退回边序 +
  单边剪枝)、cstr/cbool/countLines/labelOf/targetsOf。
- dispatcher/internal/dsl (compile_test.go)
  Topo(线性序 + 有环不丢节点)、Compile(system/query/tools 抽取 + 无输入兜底 + 空图用原文)、
  ToolBinding(tool/retriever/非工具)、Parse(合法/非法)。
- mcp-go/internal/office (unioffice_test.go)
  RenderReport 产物为合法 docx(zip 三部件 + 标题/章节文本 + XML 转义)、escapeXML。
- mcp-go/internal/mcp (report_test.go)
  reportMarkdown(标题+多章 / 无标题)。
- gateway/internal/dsl (parser_test.go)
  ParseAndAssemble(task_ 前缀 + Graph 透传 + Meta 初始化 + 空/非法报错)。

`go test ./...` 各模块全绿。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 14:13:13 +08:00

57 lines
1.5 KiB
Go

package office
import (
"archive/zip"
"bytes"
"context"
"io"
"strings"
"testing"
)
func TestRenderReport_ValidDocx(t *testing.T) {
secs := []Section{
{Heading: "第一章", Body: "正文内容 A&B"},
{Heading: "第二章", Body: "正文 <内容> B"},
}
data, err := NewRenderer().RenderReport(context.Background(), "测试报告", secs)
if err != nil {
t.Fatalf("RenderReport err: %v", err)
}
zr, err := zip.NewReader(bytes.NewReader(data), int64(len(data)))
if err != nil {
t.Fatalf("产物不是合法 zip/docx: %v", err)
}
parts := map[string]string{}
for _, f := range zr.File {
rc, _ := f.Open()
b, _ := io.ReadAll(rc)
rc.Close()
parts[f.Name] = string(b)
}
for _, need := range []string{"[Content_Types].xml", "_rels/.rels", "word/document.xml"} {
if _, ok := parts[need]; !ok {
t.Errorf("docx 缺少部件 %s", need)
}
}
doc := parts["word/document.xml"]
if !strings.Contains(doc, "测试报告") || !strings.Contains(doc, "第一章") || !strings.Contains(doc, "第二章") {
t.Error("document.xml 应含标题与各章标题")
}
// XML 特殊字符必须转义,避免破坏文档。
if strings.Contains(doc, "A&B") || !strings.Contains(doc, "A&amp;B") {
t.Error("正文 & 应被转义为 &amp;")
}
if strings.Contains(doc, "<内容>") || !strings.Contains(doc, "&lt;内容&gt;") {
t.Error("正文尖括号应被转义")
}
}
func TestEscapeXML(t *testing.T) {
got := escapeXML(`a&b<c>"d'`)
want := "a&amp;b&lt;c&gt;&quot;d&apos;"
if got != want {
t.Errorf("escapeXML = %q, want %q", got, want)
}
}