feat: simplify SOP to immediate-effect configuration
This commit is contained in:
71
internal/scenario/contract_test.go
Normal file
71
internal/scenario/contract_test.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package scenario
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestValidateContractInput(t *testing.T) {
|
||||
valid := contractInput{
|
||||
OutputSchema: map[string]interface{}{"fields": []interface{}{
|
||||
map[string]interface{}{"key": "matched_topics", "source": "derived", "source_field": "topics"},
|
||||
}},
|
||||
ResultSchema: map[string]interface{}{"fields": []interface{}{
|
||||
map[string]interface{}{"key": "selected_products", "name": "成交商品", "type": "array", "items": map[string]interface{}{"type": "string"}},
|
||||
}},
|
||||
Rules: []ruleInput{{
|
||||
RuleKey: "match_topic", Name: "匹配主题",
|
||||
Condition: map[string]interface{}{"field": "product_tags", "operator": "contains", "value": "hot"},
|
||||
Actions: []map[string]interface{}{{"operation": "append", "field": "topics", "value": "topic_hot"}},
|
||||
}},
|
||||
AllowedOrigins: []string{"https://crm.example.com"},
|
||||
}
|
||||
if err := validateContractInput(valid); err != nil {
|
||||
t.Fatalf("valid contract rejected: %v", err)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
edit func(*contractInput)
|
||||
want string
|
||||
}{
|
||||
{name: "duplicate output", edit: func(input *contractInput) {
|
||||
input.OutputSchema["fields"] = append(input.OutputSchema["fields"].([]interface{}), map[string]interface{}{"key": "matched_topics"})
|
||||
}, want: "输出字段标识"},
|
||||
{name: "invalid source", edit: func(input *contractInput) {
|
||||
input.OutputSchema["fields"].([]interface{})[0].(map[string]interface{})["source"] = "script"
|
||||
}, want: "不支持的来源"},
|
||||
{name: "invalid condition", edit: func(input *contractInput) { input.Rules[0].Condition = map[string]interface{}{"all": []interface{}{}} }, want: "非空数组"},
|
||||
{name: "invalid action", edit: func(input *contractInput) { input.Rules[0].Actions[0]["operation"] = "execute" }, want: "不支持的动作"},
|
||||
{name: "invalid origin", edit: func(input *contractInput) { input.AllowedOrigins = []string{"crm.example.com"} }, want: "完整的 http/https Origin"},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
input := cloneContractInput(valid)
|
||||
test.edit(&input)
|
||||
if err := validateContractInput(input); err == nil || !strings.Contains(err.Error(), test.want) {
|
||||
t.Fatalf("error = %v, want containing %q", err, test.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func cloneContractInput(input contractInput) contractInput {
|
||||
field := input.OutputSchema["fields"].([]interface{})[0].(map[string]interface{})
|
||||
fieldCopy := map[string]interface{}{}
|
||||
for key, value := range field {
|
||||
fieldCopy[key] = value
|
||||
}
|
||||
rule := input.Rules[0]
|
||||
condition := map[string]interface{}{}
|
||||
for key, value := range rule.Condition {
|
||||
condition[key] = value
|
||||
}
|
||||
action := map[string]interface{}{}
|
||||
for key, value := range rule.Actions[0] {
|
||||
action[key] = value
|
||||
}
|
||||
rule.Condition = condition
|
||||
rule.Actions = []map[string]interface{}{action}
|
||||
return contractInput{OutputSchema: map[string]interface{}{"fields": []interface{}{fieldCopy}}, ResultSchema: input.ResultSchema, Rules: []ruleInput{rule}, AllowedOrigins: append([]string{}, input.AllowedOrigins...)}
|
||||
}
|
||||
Reference in New Issue
Block a user