@@ -41,7 +41,6 @@ const loadConfig = getLoadConfigMock();
4141const loadWebMedia = getLoadWebMediaMock ( ) ;
4242const readChannelAllowFromStore = getReadChannelAllowFromStoreMock ( ) ;
4343const PUZZLE_EMOJI = "\u{1F9E9}" ;
44- const CROSS_MARK_EMOJI = "\u{274C}" ;
4544const INFO_EMOJI = "\u{2139}\u{FE0F}" ;
4645const CHECK_MARK_EMOJI = "\u{2705}" ;
4746const THUMBS_UP_EMOJI = "\u{1F44D}" ;
@@ -501,9 +500,10 @@ describe("createTelegramBot", () => {
501500 expect ( answerCallbackQuerySpy ) . toHaveBeenCalledWith ( "cbq-approve-blocked" ) ;
502501 } ) ;
503502
504- it ( "does not leak raw approval callback errors back into Telegram chat" , async ( ) => {
503+ it ( "keeps approval callback resolution failures out of Telegram chat before retry " , async ( ) => {
505504 onSpy . mockClear ( ) ;
506505 sendMessageSpy . mockClear ( ) ;
506+ editMessageReplyMarkupSpy . mockClear ( ) ;
507507 resolveExecApprovalSpy . mockClear ( ) ;
508508 resolveExecApprovalSpy . mockRejectedValueOnce ( new Error ( "gateway secret detail" ) ) ;
509509
@@ -525,26 +525,27 @@ describe("createTelegramBot", () => {
525525 ctx : Record < string , unknown > ,
526526 ) => Promise < void > ;
527527
528- await callbackHandler ( {
529- callbackQuery : {
530- id : "cbq-approve-error" ,
531- data : "/approve 138e9b8c allow-once" ,
532- from : { id : 9 , first_name : "Ada" , username : "ada_bot" } ,
533- message : {
534- chat : { id : 1234 , type : "private" } ,
535- date : 1736380800 ,
536- message_id : 25 ,
537- text : "Approval required." ,
528+ await expect (
529+ callbackHandler ( {
530+ callbackQuery : {
531+ id : "cbq-approve-error" ,
532+ data : "/approve 138e9b8c allow-once" ,
533+ from : { id : 9 , first_name : "Ada" , username : "ada_bot" } ,
534+ message : {
535+ chat : { id : 1234 , type : "private" } ,
536+ date : 1736380800 ,
537+ message_id : 25 ,
538+ text : "Approval required." ,
539+ } ,
538540 } ,
539- } ,
540- me : { username : "openclaw_bot" } ,
541- getFile : async ( ) => ( { download : async ( ) => new Uint8Array ( ) } ) ,
542- } ) ;
541+ me : { username : "openclaw_bot" } ,
542+ getFile : async ( ) => ( { download : async ( ) => new Uint8Array ( ) } ) ,
543+ } ) ,
544+ ) . rejects . toThrow ( "gateway secret detail" ) ;
543545
544- expect ( sendMessageSpy ) . toHaveBeenCalledTimes ( 1 ) ;
545- expect ( sendMessageSpy . mock . calls [ 0 ] ?. [ 1 ] ) . toBe (
546- `${ CROSS_MARK_EMOJI } Failed to submit approval. Please try again or contact an admin.` ,
547- ) ;
546+ expect ( sendMessageSpy ) . not . toHaveBeenCalled ( ) ;
547+ expect ( editMessageReplyMarkupSpy ) . not . toHaveBeenCalled ( ) ;
548+ expect ( answerCallbackQuerySpy ) . toHaveBeenCalledWith ( "cbq-approve-error" ) ;
548549 } ) ;
549550
550551 it ( "allows exec approval callbacks from target-only Telegram recipients" , async ( ) => {
@@ -608,12 +609,13 @@ describe("createTelegramBot", () => {
608609 expect ( answerCallbackQuerySpy ) . toHaveBeenCalledWith ( "cbq-approve-target" ) ;
609610 } ) ;
610611
611- it ( "does not allow target-only recipients to use legacy plugin fallback ids " , async ( ) => {
612+ it ( "keeps legacy plugin fallback approval failures retryable for target-only recipients " , async ( ) => {
612613 onSpy . mockClear ( ) ;
613614 editMessageReplyMarkupSpy . mockClear ( ) ;
614615 editMessageTextSpy . mockClear ( ) ;
615616 resolveExecApprovalSpy . mockClear ( ) ;
616617 replySpy . mockClear ( ) ;
618+ sendMessageSpy . mockClear ( ) ;
617619 resolveExecApprovalSpy . mockRejectedValueOnce ( new Error ( "unknown or expired approval id" ) ) ;
618620
619621 loadConfig . mockReturnValue ( {
@@ -637,21 +639,23 @@ describe("createTelegramBot", () => {
637639 ) => Promise < void > ;
638640 expect ( callbackHandler ) . toBeDefined ( ) ;
639641
640- await callbackHandler ( {
641- callbackQuery : {
642- id : "cbq-legacy-plugin-fallback-blocked" ,
643- data : "/approve 138e9b8c allow-once" ,
644- from : { id : 9 , first_name : "Ada" , username : "ada_bot" } ,
645- message : {
646- chat : { id : 1234 , type : "private" } ,
647- date : 1736380800 ,
648- message_id : 25 ,
649- text : "Legacy plugin approval required." ,
642+ await expect (
643+ callbackHandler ( {
644+ callbackQuery : {
645+ id : "cbq-legacy-plugin-fallback-blocked" ,
646+ data : "/approve 138e9b8c allow-once" ,
647+ from : { id : 9 , first_name : "Ada" , username : "ada_bot" } ,
648+ message : {
649+ chat : { id : 1234 , type : "private" } ,
650+ date : 1736380800 ,
651+ message_id : 25 ,
652+ text : "Legacy plugin approval required." ,
653+ } ,
650654 } ,
651- } ,
652- me : { username : "openclaw_bot" } ,
653- getFile : async ( ) => ( { download : async ( ) => new Uint8Array ( ) } ) ,
654- } ) ;
655+ me : { username : "openclaw_bot" } ,
656+ getFile : async ( ) => ( { download : async ( ) => new Uint8Array ( ) } ) ,
657+ } ) ,
658+ ) . rejects . toThrow ( "unknown or expired approval id" ) ;
655659
656660 expect ( resolveExecApprovalSpy ) . toHaveBeenCalledWith ( {
657661 cfg : expect . objectContaining ( {
@@ -669,11 +673,7 @@ describe("createTelegramBot", () => {
669673 } ) ;
670674 expect ( editMessageReplyMarkupSpy ) . not . toHaveBeenCalled ( ) ;
671675 expect ( replySpy ) . not . toHaveBeenCalled ( ) ;
672- expect ( sendMessageSpy ) . toHaveBeenCalledWith (
673- 1234 ,
674- `${ CROSS_MARK_EMOJI } Failed to submit approval. Please try again or contact an admin.` ,
675- undefined ,
676- ) ;
676+ expect ( sendMessageSpy ) . not . toHaveBeenCalled ( ) ;
677677 expect ( answerCallbackQuerySpy ) . toHaveBeenCalledWith ( "cbq-legacy-plugin-fallback-blocked" ) ;
678678 } ) ;
679679
0 commit comments