48 lines
1.7 KiB
Go
48 lines
1.7 KiB
Go
package contract
|
|
|
|
import (
|
|
"encoding/json"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestRejectedFeedbackRequiresReasonAndPreservesOriginalType(t *testing.T) {
|
|
for _, kind := range []string{"task.control", "call.execute", "sip.config"} {
|
|
t.Run(kind, func(t *testing.T) {
|
|
body := map[string]any{"event_id": "original-event", "event_type": kind, "dispatcher_id": "c046b893-8628-4589-ae50-619d049248a6", "payload": map[string]any{"status": "rejected", "reason_message": "/issued_at: required field missing"}}
|
|
if kind != "sip.config" {
|
|
body["tenant_id"] = 1005
|
|
}
|
|
if kind == "call.execute" {
|
|
body["payload"].(map[string]any)["reason_code"] = nil
|
|
}
|
|
if kind == "task.control" {
|
|
body["payload"].(map[string]any)["reason_code"] = "invalid_data"
|
|
}
|
|
raw, err := json.Marshal(body)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := ValidateCurrent("mq", raw); err != nil {
|
|
t.Fatalf("rejection without source timestamp was rejected: %v", err)
|
|
}
|
|
delete(body["payload"].(map[string]any), "reason_message")
|
|
raw, err = json.Marshal(body)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if ValidateCurrent("mq", raw) == nil {
|
|
t.Fatal("reason-less rejection accepted")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestInvalidMessageReasonNamesMissingFieldWithoutLeakingValues(t *testing.T) {
|
|
raw := []byte(`{"event_id":"original-event","event_type":"task.control","dispatcher_id":"c046b893-8628-4589-ae50-619d049248a6","tenant_id":1005,"payload":{"task_id":"5","action":"resume","reason":"PRIVATE-CONTROL-TEXT"}}`)
|
|
err := ValidateCurrent("mq", raw)
|
|
if err == nil || !strings.Contains(err.Error(), "issued_at") || strings.Contains(err.Error(), "PRIVATE-CONTROL-TEXT") {
|
|
t.Fatalf("missing safe actionable rejection details: %v", err)
|
|
}
|
|
}
|