119 lines
4.5 KiB
Go
119 lines
4.5 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"testing"
|
|
|
|
"git.iwork-ai.com/xdc/iqudo-top1/internal/model"
|
|
"git.iwork-ai.com/xdc/iqudo-top1/internal/sop"
|
|
"gorm.io/datatypes"
|
|
)
|
|
|
|
func TestPetDoctorSOPPassesPublishValidation(t *testing.T) {
|
|
fields := petFieldModels()
|
|
nodes := petNodeModels(petNodes())
|
|
edges := petEdgeModels(petEdges())
|
|
if len(fields) != 13 || len(nodes) != 5 || len(edges) != 4 {
|
|
t.Fatalf("unexpected definition size: fields=%d nodes=%d edges=%d", len(fields), len(nodes), len(edges))
|
|
}
|
|
|
|
problems := sop.ValidateForPublish("start", nodes, edges, sop.ValidationContext{
|
|
Fields: fields,
|
|
KnowledgeItems: []model.KnowledgeItem{
|
|
{Base: model.Base{ID: 1}, ItemKey: "consultation_boundary", Type: "guidance", Status: "active"},
|
|
{Base: model.Base{ID: 2}, ItemKey: "emergency_guidance", Type: "guidance", Status: "active"},
|
|
{Base: model.Base{ID: 3}, ItemKey: "medication_safety", Type: "guidance", Status: "active"},
|
|
{Base: model.Base{ID: 4}, ItemKey: "safety_net", Type: "guidance", Status: "active"},
|
|
{Base: model.Base{ID: 5}, ItemKey: "soft_stool", Type: "symptom", Status: "active"},
|
|
{Base: model.Base{ID: 6}, ItemKey: "poor_appetite", Type: "symptom", Status: "active"},
|
|
{Base: model.Base{ID: 7}, ItemKey: "ask_stool", Type: "copy", Status: "active"},
|
|
{Base: model.Base{ID: 8}, ItemKey: "gi_discomfort", Type: "disease", Status: "active"},
|
|
{Base: model.Base{ID: 9}, ItemKey: "gut_plan", Type: "plan", Status: "active"},
|
|
{Base: model.Base{ID: 10}, ItemKey: "gut_product", Type: "product", Status: "active"},
|
|
},
|
|
KnowledgeRelations: []model.KnowledgeRelation{
|
|
{FromKnowledgeID: 5, ToKnowledgeID: 7, RelationType: "recommended_copy"},
|
|
{FromKnowledgeID: 5, ToKnowledgeID: 8, RelationType: "possible_disease"},
|
|
{FromKnowledgeID: 5, ToKnowledgeID: 9, RelationType: "recommended_plan"},
|
|
{FromKnowledgeID: 8, ToKnowledgeID: 7, RelationType: "recommended_copy"},
|
|
{FromKnowledgeID: 8, ToKnowledgeID: 9, RelationType: "recommended_plan"},
|
|
{FromKnowledgeID: 8, ToKnowledgeID: 10, RelationType: "recommended_product"},
|
|
},
|
|
})
|
|
if len(problems) > 0 {
|
|
t.Fatalf("pet doctor SOP should be publishable, got: %v", problems)
|
|
}
|
|
}
|
|
|
|
func TestPetDoctorSOPIsFiveStepLinearFlow(t *testing.T) {
|
|
wantNodes := []string{"start", "pet_info", "symptom", "recommend_product", "finish"}
|
|
for index, node := range petNodes() {
|
|
if node.Key != wantNodes[index] {
|
|
t.Fatalf("node %d = %s, want %s", index, node.Key, wantNodes[index])
|
|
}
|
|
}
|
|
wantEdges := [][2]string{{"start", "pet_info"}, {"pet_info", "symptom"}, {"symptom", "recommend_product"}, {"recommend_product", "finish"}}
|
|
for index, edge := range petEdges() {
|
|
if edge.Source != wantEdges[index][0] || edge.Target != wantEdges[index][1] {
|
|
t.Fatalf("edge %d = %s -> %s", index, edge.Source, edge.Target)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestPetKnowledgeKeyIsStableAndTypeScoped(t *testing.T) {
|
|
if petKnowledgeKey("symptom", "腹泻") != petKnowledgeKey("symptom", " 腹泻 ") {
|
|
t.Fatal("key should ignore surrounding whitespace")
|
|
}
|
|
if petKnowledgeKey("symptom", "腹泻") == petKnowledgeKey("disease", "腹泻") {
|
|
t.Fatal("key should include knowledge type")
|
|
}
|
|
}
|
|
|
|
func petFieldModels() []model.ScenarioField {
|
|
definitions := petFieldDefinitions()
|
|
fields := make([]model.ScenarioField, 0, len(definitions))
|
|
for _, definition := range definitions {
|
|
options, _ := json.Marshal(definition.Options)
|
|
validation, _ := json.Marshal(definition.Validation)
|
|
fields = append(fields, model.ScenarioField{
|
|
FieldKey: definition.Key,
|
|
FieldName: definition.Name,
|
|
SourcePath: definition.SourcePath,
|
|
FieldType: definition.Type,
|
|
Required: definition.Required,
|
|
Options: datatypes.JSON(options),
|
|
Validation: datatypes.JSON(validation),
|
|
})
|
|
}
|
|
return fields
|
|
}
|
|
|
|
func petNodeModels(definitions []nodeDefinition) []model.SOPNode {
|
|
nodes := make([]model.SOPNode, 0, len(definitions))
|
|
for _, definition := range definitions {
|
|
config, _ := json.Marshal(definition.Config)
|
|
nodes = append(nodes, model.SOPNode{
|
|
NodeKey: definition.Key,
|
|
Type: definition.Type,
|
|
Title: definition.Title,
|
|
Content: definition.Content,
|
|
Config: datatypes.JSON(config),
|
|
})
|
|
}
|
|
return nodes
|
|
}
|
|
|
|
func petEdgeModels(definitions []edgeDefinition) []model.SOPEdge {
|
|
edges := make([]model.SOPEdge, 0, len(definitions))
|
|
for _, definition := range definitions {
|
|
condition, _ := json.Marshal(definition.Condition)
|
|
edges = append(edges, model.SOPEdge{
|
|
SourceNodeKey: definition.Source,
|
|
TargetNodeKey: definition.Target,
|
|
Condition: datatypes.JSON(condition),
|
|
Priority: definition.Priority,
|
|
})
|
|
}
|
|
return edges
|
|
}
|