package handoff import ( "context" "testing" ) type fakeARI struct { redirects int continues int fail bool } func (f *fakeARI) RedirectChannel(ctx context.Context, channelID string, endpoint string) error { f.redirects++ if f.fail { return context.Canceled } return nil } func (f *fakeARI) ContinueInDialplan(ctx context.Context, channelID, dialplanContext, extension string, priority int) error { f.continues++ if f.fail { return context.Canceled } return nil } func TestManagerDisabledStub(t *testing.T) { ari := &fakeARI{} m := NewManager(DefaultConfig(), SafeExecutor{ARI: ari}) _, res, err := m.Request(context.Background(), RequestInput{CallID: "c1", AsteriskChannelID: "c1", State: "READY_TO_HELP", Route: "test", Language: "ru", ReasonCode: HandoffReasonUserRequested}) if err != nil || res.Status != HandoffStatusStubbed || res.TransferAttempted || ari.redirects != 0 || ari.continues != 0 { t.Fatalf("bad stub result: %+v err=%v ari=%+v", res, err, ari) } } func TestManagerRedirectAndContinue(t *testing.T) { ari := &fakeARI{} m := NewManager(Config{Mode: HandoffModeARIRedirect, Enabled: true, TargetEndpoint: "PJSIP/operator", AllowInTestRouteOnly: true, DialplanPriority: 1, MaxSummaryChars: 500}, SafeExecutor{ARI: ari}) _, res, err := m.Request(context.Background(), RequestInput{CallID: "c1", AsteriskChannelID: "c1", State: "READY_TO_HELP", Route: "test", Language: "ru", ReasonCode: HandoffReasonUserRequested}) if err != nil || !res.TransferSucceeded || ari.redirects != 1 { t.Fatalf("redirect failed: %+v err=%v ari=%+v", res, err, ari) } ari = &fakeARI{} m = NewManager(Config{Mode: HandoffModeDialplanContinue, Enabled: true, DialplanContext: "ctx", DialplanExtension: "100", DialplanPriority: 1, AllowInTestRouteOnly: true, MaxSummaryChars: 500}, SafeExecutor{ARI: ari}) _, res, err = m.Request(context.Background(), RequestInput{CallID: "c2", AsteriskChannelID: "c2", State: "READY_TO_HELP", Route: "test", Language: "ru", ReasonCode: HandoffReasonUserRequested}) if err != nil || !res.TransferSucceeded || ari.continues != 1 { t.Fatalf("continue failed: %+v err=%v ari=%+v", res, err, ari) } } func TestManagerSanitizesSummaryAndDeduplicates(t *testing.T) { m := NewManager(DefaultConfig(), nil) req, _, err := m.Request(context.Background(), RequestInput{CallID: "c1", AsteriskChannelID: "c1", State: "READY_TO_HELP", Route: "test", Language: "ru", Summary: "+77011234567 wants operator", ReasonCode: HandoffReasonUserRequested}) if err != nil { t.Fatal(err) } if req.Summary == "+77011234567 wants operator" { t.Fatalf("summary not sanitized: %q", req.Summary) } _, res, _ := m.Request(context.Background(), RequestInput{CallID: "c1", AsteriskChannelID: "c1", State: "HANDOFF", Route: "test", Language: "ru", ReasonCode: HandoffReasonUserRequested}) if res.MessageKey != "handoff.already_requested" { t.Fatalf("duplicate not idempotent: %+v", res) } }