2026-06-28 08:28:42 +00:00
|
|
|
|
package copymission
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
|
|
|
|
libkg "haixun-backend/internal/library/knowledge"
|
|
|
|
|
|
missionentity "haixun-backend/internal/model/copy_mission/domain/entity"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
func TestMatrixKnowledgeItems_PrefersGraphSelection(t *testing.T) {
|
|
|
|
|
|
nodes := []libkg.Node{
|
|
|
|
|
|
{Label: "痛點A", NodeKind: "pain", SelectedForScan: true, PlacementValue: "細節A"},
|
|
|
|
|
|
{Label: "周邊B", NodeKind: "context", SelectedForScan: false},
|
|
|
|
|
|
}
|
|
|
|
|
|
items := MatrixKnowledgeItems(nil, nil, nodes, nil)
|
|
|
|
|
|
if len(items) != 1 {
|
|
|
|
|
|
t.Fatalf("items = %v, want 1 selected graph node", items)
|
|
|
|
|
|
}
|
|
|
|
|
|
if items[0] != "痛點A|細節A" {
|
|
|
|
|
|
t.Fatalf("items[0] = %q", items[0])
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func TestMatrixKnowledgeItems_UsesMissionSelectionOnly(t *testing.T) {
|
|
|
|
|
|
items := MatrixKnowledgeItems(
|
|
|
|
|
|
[]string{"受眾問題:怎麼選"},
|
|
|
|
|
|
[]string{"內容支柱:懶人包"},
|
|
|
|
|
|
nil,
|
|
|
|
|
|
nil,
|
|
|
|
|
|
)
|
|
|
|
|
|
if len(items) != 1 || items[0] != "受眾問題:怎麼選" {
|
|
|
|
|
|
t.Fatalf("items = %v", items)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func TestMatrixKnowledgeItems_MergesGraphAndMission(t *testing.T) {
|
|
|
|
|
|
nodes := []libkg.Node{
|
|
|
|
|
|
{
|
|
|
|
|
|
Label: "備孕營養",
|
|
|
|
|
|
PlacementValue: "葉酸與鋅很重要",
|
|
|
|
|
|
SelectedForScan: true,
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
Label: "未勾選",
|
|
|
|
|
|
PlacementValue: "不應出現",
|
|
|
|
|
|
SelectedForScan: false,
|
|
|
|
|
|
DerivedTags: libkg.DerivedTags{
|
|
|
|
|
|
Relevance: []string{"備孕飲食"},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
}
|
|
|
|
|
|
items := MatrixKnowledgeItems(
|
|
|
|
|
|
[]string{"手動補充:睡前習慣"},
|
|
|
|
|
|
nil,
|
|
|
|
|
|
nodes,
|
|
|
|
|
|
[]string{"備孕飲食"},
|
|
|
|
|
|
)
|
|
|
|
|
|
if len(items) != 2 {
|
|
|
|
|
|
t.Fatalf("items = %v", items)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func TestMatrixKnowledgeItems_IgnoresUnselectedTagMatches(t *testing.T) {
|
|
|
|
|
|
nodes := []libkg.Node{
|
|
|
|
|
|
{
|
|
|
|
|
|
Label: "備孕營養",
|
|
|
|
|
|
PlacementValue: "葉酸與鋅很重要",
|
|
|
|
|
|
SelectedForScan: false,
|
|
|
|
|
|
DerivedTags: libkg.DerivedTags{
|
|
|
|
|
|
Relevance: []string{"備孕飲食"},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
}
|
|
|
|
|
|
items := MatrixKnowledgeItems(nil, nil, nodes, []string{"備孕飲食"})
|
|
|
|
|
|
if len(items) != 0 {
|
|
|
|
|
|
t.Fatalf("items = %v, want none without explicit selection", items)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func TestBuildResearchMapFromGraph_RespectsManualDeselection(t *testing.T) {
|
|
|
|
|
|
prev := missionentity.ResearchMap{
|
|
|
|
|
|
KnowledgeItems: []string{"圖譜痛點:細節"},
|
|
|
|
|
|
SelectedKnowledgeItems: []string{},
|
|
|
|
|
|
}
|
|
|
|
|
|
out := BuildResearchMapFromGraph(prev, []libkg.Node{
|
|
|
|
|
|
{Label: "圖譜痛點", NodeKind: "pain", SelectedForScan: true, PlacementValue: "細節"},
|
|
|
|
|
|
}, nil)
|
|
|
|
|
|
if len(out.SelectedKnowledgeItems) != 0 {
|
|
|
|
|
|
t.Fatalf("selected = %v, want manual deselection honored", out.SelectedKnowledgeItems)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func TestBuildResearchMapFromGraph_PreservesManualKnowledge(t *testing.T) {
|
|
|
|
|
|
prev := missionentity.ResearchMap{
|
|
|
|
|
|
KnowledgeItems: []string{"手動知識:睡前"},
|
|
|
|
|
|
SelectedKnowledgeItems: []string{"手動知識:睡前"},
|
|
|
|
|
|
}
|
|
|
|
|
|
out := BuildResearchMapFromGraph(prev, []libkg.Node{
|
|
|
|
|
|
{Label: "圖譜痛點", NodeKind: "pain", SelectedForScan: true, PlacementValue: "細節"},
|
|
|
|
|
|
}, nil)
|
|
|
|
|
|
if len(out.KnowledgeItems) != 2 {
|
|
|
|
|
|
t.Fatalf("knowledge_items = %v", out.KnowledgeItems)
|
|
|
|
|
|
}
|
|
|
|
|
|
if len(out.SelectedKnowledgeItems) != 2 {
|
|
|
|
|
|
t.Fatalf("selected = %v", out.SelectedKnowledgeItems)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func TestApplyDefaultNodeSelectionPreserving(t *testing.T) {
|
|
|
|
|
|
nodes := []libkg.Node{
|
|
|
|
|
|
{ID: "keep", Label: "已勾", NodeKind: "context", SelectedForScan: false},
|
|
|
|
|
|
{ID: "new", Label: "新痛點", NodeKind: "pain", SelectedForScan: false},
|
|
|
|
|
|
}
|
|
|
|
|
|
ApplyDefaultNodeSelectionPreserving(nodes, map[string]bool{"keep": true})
|
|
|
|
|
|
if !nodes[0].SelectedForScan {
|
|
|
|
|
|
t.Fatal("expected preserved selection on existing node")
|
|
|
|
|
|
}
|
|
|
|
|
|
if !nodes[1].SelectedForScan {
|
|
|
|
|
|
t.Fatal("expected default selection on new pain node")
|
|
|
|
|
|
}
|
2026-07-06 06:13:14 +00:00
|
|
|
|
}
|