104 lines
3.6 KiB
Go
104 lines
3.6 KiB
Go
package postgres
|
|
|
|
import (
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
|
|
"gitea.zheromiku.top/Weknora/dobotai-platform/internal/feedback"
|
|
)
|
|
|
|
func TestFeedbackAnswerLookupRequiresExactDeliveredCard(t *testing.T) {
|
|
sql := strings.ToUpper(findFeedbackAnswerSQL)
|
|
for _, fragment := range []string{
|
|
"FROM MESSAGES M", "JOIN TURNS T", "T.TENANT_KEY=M.TENANT_KEY", "T.CHANNEL=M.CHANNEL",
|
|
"T.ANSWER_MESSAGE_ID=M.ID", "M.TENANT_KEY=$1", "M.CHANNEL=$2", "M.PROVIDER_MESSAGE_ID=$3",
|
|
"M.DIRECTION='OUTBOUND'", "M.ROLE='ASSISTANT'", "M.STATUS='SENT'", "M.DELIVERY_METHOD='CARD'",
|
|
"T.STATUS='SUCCEEDED'",
|
|
} {
|
|
if !strings.Contains(sql, fragment) {
|
|
t.Errorf("answer lookup missing %q", fragment)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFeedbackActorAndStateSQLAreTenantChannelSafe(t *testing.T) {
|
|
actor := strings.ToUpper(upsertFeedbackActorSQL)
|
|
for _, fragment := range []string{
|
|
"INSERT INTO CHANNEL_ACTORS", "TENANT_KEY", "CHANNEL", "EXTERNAL_ACTOR_ID",
|
|
"ON CONFLICT (TENANT_KEY,CHANNEL,EXTERNAL_ACTOR_ID)", "RETURNING ID",
|
|
} {
|
|
if !strings.Contains(actor, fragment) {
|
|
t.Errorf("actor upsert missing %q", fragment)
|
|
}
|
|
}
|
|
lookup := strings.ToUpper(findFeedbackStateSQL)
|
|
for _, fragment := range []string{"TENANT_KEY=$1", "CHANNEL=$2", "ANSWER_MESSAGE_ID=$3", "ACTOR_ID=$4", "FOR UPDATE"} {
|
|
if !strings.Contains(lookup, fragment) {
|
|
t.Errorf("feedback lookup missing %q", fragment)
|
|
}
|
|
}
|
|
update := strings.ToUpper(updateFeedbackStateSQL)
|
|
for _, fragment := range []string{"VALUE=$1", "REASON_CODE=$2", "SOURCE=$3", "UPDATED_AT=NOW()", "ID=$4", "TENANT_KEY=$5", "CHANNEL=$6", "ANSWER_MESSAGE_ID=$7", "ACTOR_ID=$8"} {
|
|
if !strings.Contains(update, fragment) {
|
|
t.Errorf("feedback update missing %q", fragment)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFeedbackStoreUsesShortSerializedTransaction(t *testing.T) {
|
|
data, err := os.ReadFile("feedback.go")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
source := strings.ToUpper(string(data))
|
|
for _, fragment := range []string{"BEGINTX", "PG_ADVISORY_XACT_LOCK", "ROLLBACK", "COMMIT"} {
|
|
if !strings.Contains(source, fragment) {
|
|
t.Errorf("feedback store missing transaction fragment %q", fragment)
|
|
}
|
|
}
|
|
for _, forbidden := range []string{"SESSIONWEBHOOK", "ACCESS_TOKEN", "RAW_CALLBACK", "RAW_PAYLOAD", "CORP_ID", "EXTENSION"} {
|
|
if strings.Contains(source, forbidden) {
|
|
t.Errorf("feedback store contains forbidden %q", forbidden)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSameFeedbackState(t *testing.T) {
|
|
if !sameFeedbackState(feedback.ValueDown, feedback.ReasonUnclear, feedback.ValueDown, feedback.ReasonUnclear) {
|
|
t.Fatal("identical feedback must be replayed")
|
|
}
|
|
if sameFeedbackState(feedback.ValueDown, feedback.ReasonUnclear, feedback.ValueDown, feedback.ReasonOther) {
|
|
t.Fatal("reason change must be a state change")
|
|
}
|
|
if sameFeedbackState(feedback.ValueDown, "", feedback.ValueUp, "") {
|
|
t.Fatal("value change must be a state change")
|
|
}
|
|
}
|
|
|
|
func TestFeedbackDownvoteEnsuresIdempotentSupportCaseInsideTransaction(t *testing.T) {
|
|
data, err := os.ReadFile("feedback.go")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
source := strings.ToUpper(string(data))
|
|
for _, required := range []string{
|
|
"ENSUREFEEDBACKSUPPORTCASE",
|
|
"SELECT ID FROM COVERAGE_DECISIONS",
|
|
"TENANT_KEY=$1 AND CHANNEL=$2 AND TURN_ID=$3",
|
|
"INSERT INTO SUPPORT_CASES",
|
|
"TRIGGER_TYPE",
|
|
"TRIGGER_FEEDBACK_ID",
|
|
"'FEEDBACK_DOWN'",
|
|
"ON CONFLICT (TENANT_KEY,CHANNEL,TURN_ID) DO NOTHING",
|
|
"FAQEXPORTSTATUS(S.FAQEXPORTENABLED)",
|
|
} {
|
|
if !strings.Contains(source, required) {
|
|
t.Errorf("feedback support wiring missing %q", required)
|
|
}
|
|
}
|
|
if strings.Count(source, "ENSUREFEEDBACKSUPPORTCASE") < 4 {
|
|
t.Fatal("create, replay, and changed-down paths must all ensure the same idempotent support case")
|
|
}
|
|
}
|