@@ -937,6 +937,192 @@ func TestManager_PlaceholderConsumedByResponse(t *testing.T) {
937937 }
938938}
939939
940+ func TestSendMessage_Synchronous (t * testing.T ) {
941+ m := newTestManager ()
942+
943+ var received []bus.OutboundMessage
944+ ch := & mockChannel {
945+ sendFn : func (_ context.Context , msg bus.OutboundMessage ) error {
946+ received = append (received , msg )
947+ return nil
948+ },
949+ }
950+
951+ w := & channelWorker {
952+ ch : ch ,
953+ limiter : rate .NewLimiter (rate .Inf , 1 ),
954+ }
955+ m .channels ["test" ] = ch
956+ m .workers ["test" ] = w
957+
958+ msg := bus.OutboundMessage {
959+ Channel : "test" ,
960+ ChatID : "123" ,
961+ Content : "hello world" ,
962+ ReplyToMessageID : "msg-456" ,
963+ }
964+
965+ err := m .SendMessage (context .Background (), msg )
966+ if err != nil {
967+ t .Fatalf ("expected no error, got %v" , err )
968+ }
969+
970+ // SendMessage is synchronous — message should already be delivered
971+ if len (received ) != 1 {
972+ t .Fatalf ("expected 1 message sent, got %d" , len (received ))
973+ }
974+ if received [0 ].ReplyToMessageID != "msg-456" {
975+ t .Fatalf ("expected ReplyToMessageID msg-456, got %s" , received [0 ].ReplyToMessageID )
976+ }
977+ if received [0 ].Content != "hello world" {
978+ t .Fatalf ("expected content 'hello world', got %s" , received [0 ].Content )
979+ }
980+ }
981+
982+ func TestSendMessage_UnknownChannel (t * testing.T ) {
983+ m := newTestManager ()
984+
985+ msg := bus.OutboundMessage {
986+ Channel : "nonexistent" ,
987+ ChatID : "123" ,
988+ Content : "hello" ,
989+ }
990+
991+ err := m .SendMessage (context .Background (), msg )
992+ if err == nil {
993+ t .Fatal ("expected error for unknown channel" )
994+ }
995+ }
996+
997+ func TestSendMessage_NoWorker (t * testing.T ) {
998+ m := newTestManager ()
999+
1000+ ch := & mockChannel {
1001+ sendFn : func (_ context.Context , _ bus.OutboundMessage ) error { return nil },
1002+ }
1003+ m .channels ["test" ] = ch
1004+ // No worker registered
1005+
1006+ msg := bus.OutboundMessage {
1007+ Channel : "test" ,
1008+ ChatID : "123" ,
1009+ Content : "hello" ,
1010+ }
1011+
1012+ err := m .SendMessage (context .Background (), msg )
1013+ if err == nil {
1014+ t .Fatal ("expected error when no worker exists" )
1015+ }
1016+ }
1017+
1018+ func TestSendMessage_WithRetry (t * testing.T ) {
1019+ m := newTestManager ()
1020+
1021+ var callCount int
1022+ ch := & mockChannel {
1023+ sendFn : func (_ context.Context , _ bus.OutboundMessage ) error {
1024+ callCount ++
1025+ if callCount == 1 {
1026+ return fmt .Errorf ("transient: %w" , ErrTemporary )
1027+ }
1028+ return nil
1029+ },
1030+ }
1031+
1032+ w := & channelWorker {
1033+ ch : ch ,
1034+ limiter : rate .NewLimiter (rate .Inf , 1 ),
1035+ }
1036+ m .channels ["test" ] = ch
1037+ m .workers ["test" ] = w
1038+
1039+ msg := bus.OutboundMessage {
1040+ Channel : "test" ,
1041+ ChatID : "123" ,
1042+ Content : "retry me" ,
1043+ }
1044+
1045+ err := m .SendMessage (context .Background (), msg )
1046+ if err != nil {
1047+ t .Fatalf ("expected no error, got %v" , err )
1048+ }
1049+
1050+ if callCount != 2 {
1051+ t .Fatalf ("expected 2 Send calls (1 failure + 1 success), got %d" , callCount )
1052+ }
1053+ }
1054+
1055+ func TestSendMessage_WithSplitting (t * testing.T ) {
1056+ m := newTestManager ()
1057+
1058+ var received []string
1059+ ch := & mockChannelWithLength {
1060+ mockChannel : mockChannel {
1061+ sendFn : func (_ context.Context , msg bus.OutboundMessage ) error {
1062+ received = append (received , msg .Content )
1063+ return nil
1064+ },
1065+ },
1066+ maxLen : 5 ,
1067+ }
1068+
1069+ w := & channelWorker {
1070+ ch : ch ,
1071+ limiter : rate .NewLimiter (rate .Inf , 1 ),
1072+ }
1073+ m .channels ["test" ] = ch
1074+ m .workers ["test" ] = w
1075+
1076+ msg := bus.OutboundMessage {
1077+ Channel : "test" ,
1078+ ChatID : "123" ,
1079+ Content : "hello world" ,
1080+ }
1081+
1082+ err := m .SendMessage (context .Background (), msg )
1083+ if err != nil {
1084+ t .Fatalf ("expected no error, got %v" , err )
1085+ }
1086+
1087+ if len (received ) < 2 {
1088+ t .Fatalf ("expected message to be split into at least 2 chunks, got %d" , len (received ))
1089+ }
1090+ }
1091+
1092+ func TestSendMessage_PreservesOrdering (t * testing.T ) {
1093+ m := newTestManager ()
1094+
1095+ var order []string
1096+ ch := & mockChannel {
1097+ sendFn : func (_ context.Context , msg bus.OutboundMessage ) error {
1098+ order = append (order , msg .Content )
1099+ return nil
1100+ },
1101+ }
1102+
1103+ w := & channelWorker {
1104+ ch : ch ,
1105+ limiter : rate .NewLimiter (rate .Inf , 1 ),
1106+ }
1107+ m .channels ["test" ] = ch
1108+ m .workers ["test" ] = w
1109+
1110+ // Send two messages sequentially — they must arrive in order
1111+ _ = m .SendMessage (context .Background (), bus.OutboundMessage {
1112+ Channel : "test" , ChatID : "1" , Content : "first" ,
1113+ })
1114+ _ = m .SendMessage (context .Background (), bus.OutboundMessage {
1115+ Channel : "test" , ChatID : "1" , Content : "second" ,
1116+ })
1117+
1118+ if len (order ) != 2 {
1119+ t .Fatalf ("expected 2 messages, got %d" , len (order ))
1120+ }
1121+ if order [0 ] != "first" || order [1 ] != "second" {
1122+ t .Fatalf ("expected [first, second], got %v" , order )
1123+ }
1124+ }
1125+
9401126func TestManager_SendPlaceholder (t * testing.T ) {
9411127 mgr := & Manager {
9421128 channels : make (map [string ]Channel ),
0 commit comments