@@ -37,6 +37,7 @@ const mockClineProvider = {
3737 getCurrentTask : vi . fn ( ) ,
3838 getTaskWithId : vi . fn ( ) ,
3939 createTaskWithHistoryItem : vi . fn ( ) ,
40+ updateTaskHistory : vi . fn ( ) ,
4041} as unknown as ClineProvider
4142
4243import { t } from "../../../i18n"
@@ -708,3 +709,188 @@ describe("webviewMessageHandler - mcpEnabled", () => {
708709 expect ( mockClineProvider . postStateToWebview ) . toHaveBeenCalledTimes ( 1 )
709710 } )
710711} )
712+
713+ describe ( "webviewMessageHandler - updateTaskTitle" , ( ) => {
714+ beforeEach ( ( ) => {
715+ vi . clearAllMocks ( )
716+ // Mock getGlobalState to return a task history
717+ vi . mocked ( mockClineProvider . contextProxy . getValue ) . mockReturnValue ( [
718+ {
719+ id : "task-1" ,
720+ ts : 123456789 ,
721+ task : "Original task text" ,
722+ title : "Original title" ,
723+ } ,
724+ {
725+ id : "task-2" ,
726+ ts : 987654321 ,
727+ task : "Another task" ,
728+ // No title
729+ } ,
730+ ] )
731+ } )
732+
733+ it ( "should update task title when task exists" , async ( ) => {
734+ // Mock updateTaskHistory to succeed
735+ vi . mocked ( mockClineProvider . updateTaskHistory ) . mockResolvedValue ( [ ] )
736+
737+ await webviewMessageHandler ( mockClineProvider , {
738+ type : "updateTaskTitle" ,
739+ taskId : "task-1" ,
740+ title : "New updated title" ,
741+ } )
742+
743+ // Verify updateTaskHistory was called with the updated task
744+ expect ( mockClineProvider . updateTaskHistory ) . toHaveBeenCalledWith ( {
745+ id : "task-1" ,
746+ ts : 123456789 ,
747+ task : "Original task text" ,
748+ title : "New updated title" ,
749+ } )
750+
751+ // Verify state was posted to webview
752+ expect ( mockClineProvider . postStateToWebview ) . toHaveBeenCalled ( )
753+ } )
754+
755+ it ( "should clear task title when empty string is provided" , async ( ) => {
756+ vi . mocked ( mockClineProvider . updateTaskHistory ) . mockResolvedValue ( [ ] )
757+
758+ await webviewMessageHandler ( mockClineProvider , {
759+ type : "updateTaskTitle" ,
760+ taskId : "task-1" ,
761+ title : "" ,
762+ } )
763+
764+ // Verify updateTaskHistory was called with undefined title
765+ expect ( mockClineProvider . updateTaskHistory ) . toHaveBeenCalledWith ( {
766+ id : "task-1" ,
767+ ts : 123456789 ,
768+ task : "Original task text" ,
769+ title : undefined ,
770+ } )
771+
772+ expect ( mockClineProvider . postStateToWebview ) . toHaveBeenCalled ( )
773+ } )
774+
775+ it ( "should add title to task that didn't have one" , async ( ) => {
776+ vi . mocked ( mockClineProvider . updateTaskHistory ) . mockResolvedValue ( [ ] )
777+
778+ await webviewMessageHandler ( mockClineProvider , {
779+ type : "updateTaskTitle" ,
780+ taskId : "task-2" ,
781+ title : "Brand new title" ,
782+ } )
783+
784+ // Verify updateTaskHistory was called with the new title
785+ expect ( mockClineProvider . updateTaskHistory ) . toHaveBeenCalledWith ( {
786+ id : "task-2" ,
787+ ts : 987654321 ,
788+ task : "Another task" ,
789+ title : "Brand new title" ,
790+ } )
791+
792+ expect ( mockClineProvider . postStateToWebview ) . toHaveBeenCalled ( )
793+ } )
794+
795+ it ( "should not update when task is not found" , async ( ) => {
796+ await webviewMessageHandler ( mockClineProvider , {
797+ type : "updateTaskTitle" ,
798+ taskId : "non-existent-task" ,
799+ title : "Some title" ,
800+ } )
801+
802+ // Verify updateTaskHistory was NOT called
803+ expect ( mockClineProvider . updateTaskHistory ) . not . toHaveBeenCalled ( )
804+
805+ // State should not be posted either
806+ expect ( mockClineProvider . postStateToWebview ) . not . toHaveBeenCalled ( )
807+ } )
808+
809+ it ( "should not update when taskId is missing" , async ( ) => {
810+ await webviewMessageHandler ( mockClineProvider , {
811+ type : "updateTaskTitle" ,
812+ // No taskId provided
813+ title : "Some title" ,
814+ } )
815+
816+ // Verify updateTaskHistory was NOT called
817+ expect ( mockClineProvider . updateTaskHistory ) . not . toHaveBeenCalled ( )
818+
819+ // State should not be posted either
820+ expect ( mockClineProvider . postStateToWebview ) . not . toHaveBeenCalled ( )
821+ } )
822+
823+ it ( "should handle empty task history gracefully" , async ( ) => {
824+ // Mock empty task history
825+ vi . mocked ( mockClineProvider . contextProxy . getValue ) . mockReturnValue ( undefined )
826+
827+ await webviewMessageHandler ( mockClineProvider , {
828+ type : "updateTaskTitle" ,
829+ taskId : "task-1" ,
830+ title : "New title" ,
831+ } )
832+
833+ // Verify updateTaskHistory was NOT called
834+ expect ( mockClineProvider . updateTaskHistory ) . not . toHaveBeenCalled ( )
835+
836+ // State should not be posted either
837+ expect ( mockClineProvider . postStateToWebview ) . not . toHaveBeenCalled ( )
838+ } )
839+
840+ it ( "should handle null task history gracefully" , async ( ) => {
841+ // Mock null task history
842+ vi . mocked ( mockClineProvider . contextProxy . getValue ) . mockReturnValue ( null )
843+
844+ await webviewMessageHandler ( mockClineProvider , {
845+ type : "updateTaskTitle" ,
846+ taskId : "task-1" ,
847+ title : "New title" ,
848+ } )
849+
850+ // Verify updateTaskHistory was NOT called
851+ expect ( mockClineProvider . updateTaskHistory ) . not . toHaveBeenCalled ( )
852+
853+ // State should not be posted either
854+ expect ( mockClineProvider . postStateToWebview ) . not . toHaveBeenCalled ( )
855+ } )
856+
857+ it ( "should trim whitespace from title" , async ( ) => {
858+ vi . mocked ( mockClineProvider . updateTaskHistory ) . mockResolvedValue ( [ ] )
859+
860+ await webviewMessageHandler ( mockClineProvider , {
861+ type : "updateTaskTitle" ,
862+ taskId : "task-1" ,
863+ title : " Trimmed Title " ,
864+ } )
865+
866+ // Verify updateTaskHistory was called with trimmed title
867+ expect ( mockClineProvider . updateTaskHistory ) . toHaveBeenCalledWith ( {
868+ id : "task-1" ,
869+ ts : 123456789 ,
870+ task : "Original task text" ,
871+ title : "Trimmed Title" ,
872+ } )
873+
874+ expect ( mockClineProvider . postStateToWebview ) . toHaveBeenCalled ( )
875+ } )
876+
877+ it ( "should handle whitespace-only title as empty" , async ( ) => {
878+ vi . mocked ( mockClineProvider . updateTaskHistory ) . mockResolvedValue ( [ ] )
879+
880+ await webviewMessageHandler ( mockClineProvider , {
881+ type : "updateTaskTitle" ,
882+ taskId : "task-1" ,
883+ title : " " ,
884+ } )
885+
886+ // Verify updateTaskHistory was called with undefined (cleared title)
887+ expect ( mockClineProvider . updateTaskHistory ) . toHaveBeenCalledWith ( {
888+ id : "task-1" ,
889+ ts : 123456789 ,
890+ task : "Original task text" ,
891+ title : undefined ,
892+ } )
893+
894+ expect ( mockClineProvider . postStateToWebview ) . toHaveBeenCalled ( )
895+ } )
896+ } )
0 commit comments