@@ -113,10 +113,11 @@ describe("EpicTools", () => {
113113 expect ( mockToolRead . mock . calls ?. [ 0 ] ?. [ 0 ] ) . toBe ( "epics-get-by-id" ) ;
114114 expect ( mockToolRead . mock . calls ?. [ 1 ] ?. [ 0 ] ) . toBe ( "epics-search" ) ;
115115
116- expect ( mockToolWrite ) . toHaveBeenCalledTimes ( 3 ) ;
116+ expect ( mockToolWrite ) . toHaveBeenCalledTimes ( 4 ) ;
117117 expect ( mockToolWrite . mock . calls ?. [ 0 ] ?. [ 0 ] ) . toBe ( "epics-create" ) ;
118118 expect ( mockToolWrite . mock . calls ?. [ 1 ] ?. [ 0 ] ) . toBe ( "epics-update" ) ;
119- expect ( mockToolWrite . mock . calls ?. [ 2 ] ?. [ 0 ] ) . toBe ( "epics-delete" ) ;
119+ expect ( mockToolWrite . mock . calls ?. [ 2 ] ?. [ 0 ] ) . toBe ( "epics-create-comment" ) ;
120+ expect ( mockToolWrite . mock . calls ?. [ 3 ] ?. [ 0 ] ) . toBe ( "epics-delete" ) ;
120121 } ) ;
121122 } ) ;
122123
@@ -425,6 +426,102 @@ describe("EpicTools", () => {
425426 } ) ;
426427 } ) ;
427428
429+ describe ( "createEpicComment method" , ( ) => {
430+ const getEpicMock = mock ( async ( id : number ) => mockEpics . find ( ( epic ) => epic . id === id ) ) ;
431+ const createEpicCommentMock = mock ( async ( _id : number , _params : { text : string } ) => ( {
432+ id : 100 ,
433+ text : "Test comment" ,
434+ app_url : "https://app.shortcut.com/test/epic/1/comments/100" ,
435+ } ) ) ;
436+
437+ beforeEach ( ( ) => {
438+ createEpicCommentMock . mockClear ( ) ;
439+ } ) ;
440+
441+ test ( "should create a comment on an epic" , async ( ) => {
442+ const mockClient = createMockClient ( {
443+ getEpic : getEpicMock ,
444+ createEpicComment : createEpicCommentMock ,
445+ } ) ;
446+ const epicTools = new EpicTools ( mockClient ) ;
447+ const result = await epicTools . createEpicComment ( {
448+ epicPublicId : 1 ,
449+ text : "Test comment" ,
450+ } ) ;
451+
452+ expect ( getTextContent ( result ) ) . toBe (
453+ "Created comment on epic 1. Comment URL: https://app.shortcut.com/test/epic/1/comments/100." ,
454+ ) ;
455+ expect ( createEpicCommentMock ) . toHaveBeenCalledTimes ( 1 ) ;
456+ expect ( createEpicCommentMock . mock . calls ?. [ 0 ] ?. [ 0 ] ) . toBe ( 1 ) ;
457+ expect ( createEpicCommentMock . mock . calls ?. [ 0 ] ?. [ 1 ] ) . toMatchObject ( {
458+ text : "Test comment" ,
459+ } ) ;
460+ } ) ;
461+
462+ test ( "should throw error when epic is not found" , async ( ) => {
463+ const mockClient = createMockClient ( {
464+ getEpic : mock ( async ( ) => null ) ,
465+ createEpicComment : createEpicCommentMock ,
466+ } ) ;
467+ const epicTools = new EpicTools ( mockClient ) ;
468+
469+ await expect ( ( ) =>
470+ epicTools . createEpicComment ( {
471+ epicPublicId : 999 ,
472+ text : "Test comment" ,
473+ } ) ,
474+ ) . toThrow ( "Failed to retrieve Shortcut epic with public ID: 999" ) ;
475+ } ) ;
476+
477+ test ( "should throw error when text is empty" , async ( ) => {
478+ const mockClient = createMockClient ( {
479+ getEpic : getEpicMock ,
480+ createEpicComment : createEpicCommentMock ,
481+ } ) ;
482+ const epicTools = new EpicTools ( mockClient ) ;
483+
484+ await expect ( ( ) =>
485+ epicTools . createEpicComment ( {
486+ epicPublicId : 1 ,
487+ text : "" ,
488+ } ) ,
489+ ) . toThrow ( "Epic comment text is required" ) ;
490+ } ) ;
491+
492+ test ( "should create a reply to an existing comment" , async ( ) => {
493+ const createEpicCommentCommentMock = mock (
494+ async ( _epicId : number , _commentId : number , _params : { text : string } ) => ( {
495+ id : 200 ,
496+ text : "Reply comment" ,
497+ app_url : "https://app.shortcut.com/test/epic/1/comments/200" ,
498+ } ) ,
499+ ) ;
500+ const mockClient = createMockClient ( {
501+ getEpic : getEpicMock ,
502+ createEpicComment : createEpicCommentMock ,
503+ createEpicCommentComment : createEpicCommentCommentMock ,
504+ } ) ;
505+ const epicTools = new EpicTools ( mockClient ) ;
506+ const result = await epicTools . createEpicComment ( {
507+ epicPublicId : 1 ,
508+ replyToCommentId : 100 ,
509+ text : "Reply comment" ,
510+ } ) ;
511+
512+ expect ( getTextContent ( result ) ) . toBe (
513+ "Created comment on epic 1. Comment URL: https://app.shortcut.com/test/epic/1/comments/200." ,
514+ ) ;
515+ expect ( createEpicCommentMock ) . not . toHaveBeenCalled ( ) ;
516+ expect ( createEpicCommentCommentMock ) . toHaveBeenCalledTimes ( 1 ) ;
517+ expect ( createEpicCommentCommentMock . mock . calls ?. [ 0 ] ?. [ 0 ] ) . toBe ( 1 ) ;
518+ expect ( createEpicCommentCommentMock . mock . calls ?. [ 0 ] ?. [ 1 ] ) . toBe ( 100 ) ;
519+ expect ( createEpicCommentCommentMock . mock . calls ?. [ 0 ] ?. [ 2 ] ) . toMatchObject ( {
520+ text : "Reply comment" ,
521+ } ) ;
522+ } ) ;
523+ } ) ;
524+
428525 describe ( "deleteEpic method" , ( ) => {
429526 const getEpicMock = mock ( async ( id : number ) => mockEpics . find ( ( epic ) => epic . id === id ) ) ;
430527 const deleteEpicMock = mock ( async ( _id : number ) => undefined ) ;
0 commit comments