package support import ( "encoding/json" "errors" "fmt" "testing" "github.com/google/uuid" ) func TestNormalizeTags(t *testing.T) { t.Parallel() got, err := normalizeTags([]string{" Billing ", "BILLING", "woo-commerce", ""}) if err != nil { t.Fatal(err) } if len(got) != 2 || got[0] != "billing" || got[1] != "woo-commerce" { t.Fatalf("got %#v", got) } _, err = normalizeTags([]string{"Bad Tag!"}) if !errors.Is(err, ErrInvalidTag) { t.Fatalf("err=%v", err) } tooMany := make([]string, maxTags+1) for i := range tooMany { tooMany[i] = fmt.Sprintf("tag%d", i) } _, err = normalizeTags(tooMany) if !errors.Is(err, ErrTooManyTags) { t.Fatalf("err=%v", err) } } func TestNormalizeRelatedSKU(t *testing.T) { t.Parallel() got, err := normalizeRelatedSKU(" SKU-1 ") if err != nil || got != "SKU-1" { t.Fatalf("got %q err=%v", got, err) } long := string(make([]rune, maxRelatedSKULen+1)) for i := range long { long = long[:i] + "x" + long[i+1:] } _, err = normalizeRelatedSKU(long) if !errors.Is(err, ErrInvalidRelatedSKU) { t.Fatalf("err=%v", err) } } func TestNormalizeCategoryExpanded(t *testing.T) { t.Parallel() for _, slug := range []string{"integrations", "processing", "export", "billing_credits", "migration"} { got, err := normalizeCategory(slug) if err != nil || got != slug { t.Fatalf("%s: got %q err=%v", slug, got, err) } } } func TestCreateInputRejectsBadTags(t *testing.T) { t.Parallel() s := NewService(nil) _, err := s.Create(t.Context(), uuid.New(), uuid.New(), CreateInput{ Subject: "Help", Body: "body", Tags: []string{"not valid"}, }) if !errors.Is(err, ErrInvalidTag) { t.Fatalf("err=%v", err) } if msg, ok := ClientError(err); !ok || msg == "" { t.Fatalf("ClientError missing for tags") } } func TestRedactCustomerContextForUser(t *testing.T) { t.Parallel() raw := json.RawMessage(`{"company_name":"Acme","user_email":"a@b.c","signals":{"open_ticket_count":2}}`) out := redactCustomerContextForUser(raw) var m map[string]any if err := json.Unmarshal(out, &m); err != nil { t.Fatal(err) } if _, ok := m["signals"]; ok { t.Fatal("signals should be redacted") } if _, ok := m["user_email"]; ok { t.Fatal("user_email should be redacted") } if m["company_name"] != "Acme" { t.Fatalf("company_name=%v", m["company_name"]) } } func TestRecordAutoReplyOutcomeRejectsBadStatus(t *testing.T) { t.Parallel() s := NewService(nil) err := s.RecordAutoReplyOutcome(t.Context(), uuid.New(), "nope", false, nil, nil, ActivityAutoReply) if !errors.Is(err, ErrInvalidStatus) { t.Fatalf("err=%v", err) } } func TestAdminUpdateInputAutoReplyFlag(t *testing.T) { t.Parallel() disabled := true in := AdminUpdateInput{AutoReplyDisabled: &disabled, SetTags: true, Tags: []string{"urgent"}} tags, err := normalizeTags(in.Tags) if err != nil { t.Fatal(err) } if len(tags) != 1 || tags[0] != "urgent" { t.Fatalf("%#v", tags) } if in.AutoReplyDisabled == nil || !*in.AutoReplyDisabled { t.Fatal("flag") } }