@@ -576,3 +576,243 @@ describe("webviewMessageHandler - message dialog preferences", () => {
576576 } )
577577 } )
578578} )
579+
580+ describe ( "webviewMessageHandler - requestTaskMessages" , ( ) => {
581+ beforeEach ( ( ) => {
582+ vi . clearAllMocks ( )
583+ // Mock a current Cline instance with many messages
584+ const mockCline = {
585+ taskId : "test-task-id" ,
586+ apiConversationHistory : [ ] ,
587+ clineMessages : Array . from ( { length : 150 } , ( _ , i ) => ( {
588+ ts : i + 1000 ,
589+ type : "say" ,
590+ say : "assistant" ,
591+ text : `Message ${ i + 1 } ` ,
592+ partial : false ,
593+ } ) ) ,
594+ }
595+ vi . mocked ( mockClineProvider . getCurrentCline ) . mockReturnValue ( mockCline as any )
596+ } )
597+
598+ it ( "should return paginated messages with correct offset and limit" , async ( ) => {
599+ await webviewMessageHandler ( mockClineProvider , {
600+ type : "requestTaskMessages" ,
601+ offset : 0 ,
602+ limit : 50 ,
603+ } )
604+
605+ expect ( mockClineProvider . getCurrentCline ) . toHaveBeenCalled ( )
606+ expect ( mockClineProvider . postMessageToWebview ) . toHaveBeenCalledWith ( {
607+ type : "taskMessagesResponse" ,
608+ messages : expect . arrayContaining ( [
609+ expect . objectContaining ( { text : "Message 101" } ) , // 150 - 50 + 1
610+ expect . objectContaining ( { text : "Message 102" } ) ,
611+ // ... up to Message 150
612+ ] ) ,
613+ totalMessages : 150 ,
614+ hasMore : true ,
615+ } )
616+
617+ // Verify we got exactly 50 messages
618+ const call = vi . mocked ( mockClineProvider . postMessageToWebview ) . mock . calls [ 0 ]
619+ const response = call ?. [ 0 ] as any
620+ expect ( response . messages ) . toHaveLength ( 50 )
621+ expect ( response . messages [ 0 ] . text ) . toBe ( "Message 101" )
622+ expect ( response . messages [ 49 ] . text ) . toBe ( "Message 150" )
623+ } )
624+
625+ it ( "should return older messages when offset is increased" , async ( ) => {
626+ await webviewMessageHandler ( mockClineProvider , {
627+ type : "requestTaskMessages" ,
628+ offset : 50 ,
629+ limit : 50 ,
630+ } )
631+
632+ expect ( mockClineProvider . postMessageToWebview ) . toHaveBeenCalledWith ( {
633+ type : "taskMessagesResponse" ,
634+ messages : expect . arrayContaining ( [
635+ expect . objectContaining ( { text : "Message 51" } ) , // 150 - 50 - 50 + 1
636+ expect . objectContaining ( { text : "Message 52" } ) ,
637+ // ... up to Message 100
638+ ] ) ,
639+ totalMessages : 150 ,
640+ hasMore : true ,
641+ } )
642+
643+ // Verify we got exactly 50 messages
644+ const call = vi . mocked ( mockClineProvider . postMessageToWebview ) . mock . calls [ 0 ]
645+ const response = call ?. [ 0 ] as any
646+ expect ( response . messages ) . toHaveLength ( 50 )
647+ expect ( response . messages [ 0 ] . text ) . toBe ( "Message 51" )
648+ expect ( response . messages [ 49 ] . text ) . toBe ( "Message 100" )
649+ } )
650+
651+ it ( "should set hasMore to false when all messages are loaded" , async ( ) => {
652+ await webviewMessageHandler ( mockClineProvider , {
653+ type : "requestTaskMessages" ,
654+ offset : 100 ,
655+ limit : 50 ,
656+ } )
657+
658+ expect ( mockClineProvider . postMessageToWebview ) . toHaveBeenCalledWith ( {
659+ type : "taskMessagesResponse" ,
660+ messages : expect . arrayContaining ( [
661+ expect . objectContaining ( { text : "Message 1" } ) ,
662+ expect . objectContaining ( { text : "Message 2" } ) ,
663+ // ... up to Message 50
664+ ] ) ,
665+ totalMessages : 150 ,
666+ hasMore : false , // No more messages to load
667+ } )
668+
669+ // Verify we got exactly 50 messages
670+ const call = vi . mocked ( mockClineProvider . postMessageToWebview ) . mock . calls [ 0 ]
671+ const response = call ?. [ 0 ] as any
672+ expect ( response . messages ) . toHaveLength ( 50 )
673+ expect ( response . messages [ 0 ] . text ) . toBe ( "Message 1" )
674+ expect ( response . messages [ 49 ] . text ) . toBe ( "Message 50" )
675+ } )
676+
677+ it ( "should handle partial page at the beginning" , async ( ) => {
678+ await webviewMessageHandler ( mockClineProvider , {
679+ type : "requestTaskMessages" ,
680+ offset : 140 ,
681+ limit : 50 ,
682+ } )
683+
684+ expect ( mockClineProvider . postMessageToWebview ) . toHaveBeenCalledWith ( {
685+ type : "taskMessagesResponse" ,
686+ messages : expect . arrayContaining ( [
687+ expect . objectContaining ( { text : "Message 1" } ) ,
688+ expect . objectContaining ( { text : "Message 2" } ) ,
689+ // ... up to Message 10
690+ ] ) ,
691+ totalMessages : 150 ,
692+ hasMore : false ,
693+ } )
694+
695+ // Verify we got only 10 messages (the remaining ones)
696+ const call = vi . mocked ( mockClineProvider . postMessageToWebview ) . mock . calls [ 0 ]
697+ const response = call ?. [ 0 ] as any
698+ expect ( response . messages ) . toHaveLength ( 10 )
699+ expect ( response . messages [ 0 ] . text ) . toBe ( "Message 1" )
700+ expect ( response . messages [ 9 ] . text ) . toBe ( "Message 10" )
701+ } )
702+
703+ it ( "should handle task with fewer messages than limit" , async ( ) => {
704+ // Mock a current Cline with only 30 messages
705+ const mockCline = {
706+ taskId : "test-task-id" ,
707+ apiConversationHistory : [ ] ,
708+ clineMessages : Array . from ( { length : 30 } , ( _ , i ) => ( {
709+ ts : i + 1000 ,
710+ type : "say" ,
711+ say : "assistant" ,
712+ text : `Message ${ i + 1 } ` ,
713+ partial : false ,
714+ } ) ) ,
715+ }
716+ vi . mocked ( mockClineProvider . getCurrentCline ) . mockReturnValue ( mockCline as any )
717+
718+ await webviewMessageHandler ( mockClineProvider , {
719+ type : "requestTaskMessages" ,
720+ offset : 0 ,
721+ limit : 50 ,
722+ } )
723+
724+ expect ( mockClineProvider . postMessageToWebview ) . toHaveBeenCalledWith ( {
725+ type : "taskMessagesResponse" ,
726+ messages : expect . arrayContaining ( [
727+ expect . objectContaining ( { text : "Message 1" } ) ,
728+ expect . objectContaining ( { text : "Message 30" } ) ,
729+ ] ) ,
730+ totalMessages : 30 ,
731+ hasMore : false , // All messages loaded in first request
732+ } )
733+
734+ // Verify we got all 30 messages
735+ const call = vi . mocked ( mockClineProvider . postMessageToWebview ) . mock . calls [ 0 ]
736+ const response = call ?. [ 0 ] as any
737+ expect ( response . messages ) . toHaveLength ( 30 )
738+ } )
739+
740+ it ( "should handle no current Cline instance" , async ( ) => {
741+ vi . mocked ( mockClineProvider . getCurrentCline ) . mockReturnValue ( undefined )
742+
743+ await webviewMessageHandler ( mockClineProvider , {
744+ type : "requestTaskMessages" ,
745+ offset : 0 ,
746+ limit : 50 ,
747+ } )
748+
749+ expect ( mockClineProvider . postMessageToWebview ) . toHaveBeenCalledWith ( {
750+ type : "taskMessagesResponse" ,
751+ messages : [ ] ,
752+ totalMessages : 0 ,
753+ hasMore : false ,
754+ } )
755+ } )
756+
757+ it ( "should handle Cline with no messages" , async ( ) => {
758+ const mockCline = {
759+ taskId : "test-task-id" ,
760+ apiConversationHistory : [ ] ,
761+ clineMessages : [ ] ,
762+ }
763+ vi . mocked ( mockClineProvider . getCurrentCline ) . mockReturnValue ( mockCline as any )
764+
765+ await webviewMessageHandler ( mockClineProvider , {
766+ type : "requestTaskMessages" ,
767+ offset : 0 ,
768+ limit : 50 ,
769+ } )
770+
771+ expect ( mockClineProvider . postMessageToWebview ) . toHaveBeenCalledWith ( {
772+ type : "taskMessagesResponse" ,
773+ messages : [ ] ,
774+ totalMessages : 0 ,
775+ hasMore : false ,
776+ } )
777+ } )
778+
779+ it ( "should handle offset beyond message count" , async ( ) => {
780+ await webviewMessageHandler ( mockClineProvider , {
781+ type : "requestTaskMessages" ,
782+ offset : 200 , // Beyond 150 messages
783+ limit : 50 ,
784+ } )
785+
786+ const call = vi . mocked ( mockClineProvider . postMessageToWebview ) . mock . calls [ 0 ]
787+ const response = call ?. [ 0 ] as any
788+
789+ expect ( response ) . toEqual ( {
790+ type : "taskMessagesResponse" ,
791+ messages : [ ] ,
792+ totalMessages : 150 ,
793+ hasMore : false ,
794+ } )
795+ } )
796+
797+ it ( "should handle undefined clineMessages" , async ( ) => {
798+ const mockCline = {
799+ taskId : "test-task-id" ,
800+ apiConversationHistory : [ ] ,
801+ clineMessages : undefined ,
802+ }
803+ vi . mocked ( mockClineProvider . getCurrentCline ) . mockReturnValue ( mockCline as any )
804+
805+ await webviewMessageHandler ( mockClineProvider , {
806+ type : "requestTaskMessages" ,
807+ offset : 0 ,
808+ limit : 50 ,
809+ } )
810+
811+ expect ( mockClineProvider . postMessageToWebview ) . toHaveBeenCalledWith ( {
812+ type : "taskMessagesResponse" ,
813+ messages : [ ] ,
814+ totalMessages : 0 ,
815+ hasMore : false ,
816+ } )
817+ } )
818+ } )
0 commit comments