package run import ( "encoding/json" "testing" "git.iwork-ai.com/xdc/iqudo-top1/internal/model" ) func TestRenderKnowledgeContent(t *testing.T) { got := string(renderKnowledgeContent([]byte(`{"template":"您好{{input.name}},标签:{{derived.tags}}"}`), map[string]interface{}{"name": "王女士", "tags": []interface{}{"高意向", "复购"}})) want := `{"template":"您好王女士,标签:高意向、复购"}` if got != want { t.Fatalf("got %s want %s", got, want) } } func TestRenderKnowledgeContentSupportsFormNamespace(t *testing.T) { got := string(renderKnowledgeContent([]byte(`{"template":"结果:{{form.call_result}}"}`), runtimeContext(nil, nil, map[string]interface{}{"call_result": "已接受"}))) if got != `{"template":"结果:已接受"}` { t.Fatalf("got %s", got) } } func TestTemplateNamespacesDoNotOverwriteEachOther(t *testing.T) { context := runtimeContext(map[string]interface{}{"status": "input"}, map[string]interface{}{"status": "derived"}, map[string]interface{}{"status": "form"}) got := string(renderKnowledgeContent([]byte(`{"template":"{{input.status}}/{{derived.status}}/{{form.status}}"}`), context)) if got != `{"template":"input/derived/form"}` { t.Fatalf("got %s", got) } } func TestKnowledgeRelationCondition(t *testing.T) { condition := json.RawMessage(`{"field":"derived.segment","operator":"equals","value":"vip"}`) matched, err := matchCondition(condition, map[string]interface{}{"segment": "vip"}) if err != nil || !matched { t.Fatalf("matched=%v err=%v", matched, err) } matched, err = matchCondition(condition, map[string]interface{}{"segment": "normal"}) if err != nil || matched { t.Fatalf("matched=%v err=%v", matched, err) } } func TestSnapshotRelationsHonorSelector(t *testing.T) { snapshot := knowledgeSnapshot{Relations: []model.KnowledgeRelation{ {FromKnowledgeID: 1, ToKnowledgeID: 2, RelationType: "recommended_copy"}, {FromKnowledgeID: 1, ToKnowledgeID: 3, RelationType: "internal_note"}, }} raw, err := json.Marshal(snapshot) if err != nil { t.Fatal(err) } parsed, err := parseKnowledgeSnapshot(raw) if err != nil { t.Fatal(err) } selector := knowledgeSelector{RelationTypes: []string{"recommended_copy"}} filtered := make([]model.KnowledgeRelation, 0) for _, relation := range parsed.Relations { if len(selector.RelationTypes) == 0 || containsString(selector.RelationTypes, relation.RelationType) { filtered = append(filtered, relation) } } if len(filtered) != 1 || filtered[0].RelationType != "recommended_copy" { t.Fatalf("filtered relations = %#v", filtered) } } func TestKnowledgeSelectorWithoutCandidateKeysReturnsEmpty(t *testing.T) { outputs, err := loadKnowledgeOutputsForScenario(nil, 1, 1, map[string]interface{}{}, knowledgeSelector{DerivedField: "matched", KnowledgeTypes: []string{"symptom"}}) if err != nil { t.Fatal(err) } if len(outputs) != 0 { t.Fatalf("outputs = %#v", outputs) } } func TestKnowledgeCandidateMatchesKeyOrDisplayName(t *testing.T) { item := model.KnowledgeItem{ItemKey: "xlsx_symptom_123", Name: "腹泻"} if !knowledgeCandidateMatches(map[string]bool{"腹泻": true}, item) { t.Fatal("display name should match an external symptom tag") } if !knowledgeCandidateMatches(map[string]bool{"xlsx_symptom_123": true}, item) { t.Fatal("item key should remain supported") } }