package graph import ( "strings" "testing" "github.com/aisim/kb-cli/internal/vault" ) func TestBuildGraph(t *testing.T) { files := []*vault.FileMeta{ { Path: "FAQ/充装类/001-test.md", Title: "测试FAQ", Section: "FAQ", Tags: []string{"充装", "智能枪"}, Entities: []string{"YSP-35.5"}, Wikilinks: []string{}, Content: "测试内容", }, { Path: "知识/002-配置.md", Title: "充装规格配置", Section: "知识", Tags: []string{"充装"}, Entities: []string{}, Wikilinks: []string{}, Content: "配置内容", }, } g := BuildGraph(files) // 2 个文件节点 + 2 个 tag 虚拟节点(充装、智能枪)+ 1 个 entity 虚拟节点 if len(g.Nodes) != 5 { t.Errorf("node count = %d, want 5", len(g.Nodes)) } // 验证虚拟节点 path 命名空间与 NodeType tagCount, entityCount, fileCount := 0, 0, 0 for _, n := range g.Nodes { switch n.NodeType { case "tag": tagCount++ if !strings.HasPrefix(n.Path, "tag:") { t.Errorf("tag node path = %q, want prefix tag:", n.Path) } case "entity": entityCount++ if !strings.HasPrefix(n.Path, "entity:") { t.Errorf("entity node path = %q, want prefix entity:", n.Path) } case "file": fileCount++ default: t.Errorf("unexpected node_type %q for %s", n.NodeType, n.Path) } } if tagCount != 2 || entityCount != 1 || fileCount != 2 { t.Errorf("file/tag/entity = %d/%d/%d, want 2/2/1", fileCount, tagCount, entityCount) } // 应该有 3 条边:2条 tag + 1条 entity tagEdges := 0 entityEdges := 0 for _, e := range g.Edges { if e.Relation == "tag" { tagEdges++ } if e.Relation == "entity" { entityEdges++ } } if tagEdges != 3 { // 充装 + 智能枪 + 充装(第二个文件) t.Errorf("tag edges = %d, want 3", tagEdges) } if entityEdges != 1 { t.Errorf("entity edges = %d, want 1", entityEdges) } }