@@ -394,7 +394,7 @@ describe("pr_review_buffer (factory pattern)", () => {
394394 expect ( callArgs . body ) . toContain ( "test-workflow" ) ;
395395 } ) ;
396396
397- it ( "should skip footer when setIncludeFooter(false ) is called" , async ( ) => {
397+ it ( "should skip footer when setIncludeFooter('none' ) is called" , async ( ) => {
398398 buffer . addComment ( { path : "test.js" , line : 1 , body : "comment" } ) ;
399399 buffer . setReviewMetadata ( "Review body" , "COMMENT" ) ;
400400 buffer . setReviewContext ( {
@@ -409,7 +409,7 @@ describe("pr_review_buffer (factory pattern)", () => {
409409 workflowSource : "owner/repo/workflows/test.md@v1" ,
410410 workflowSourceURL : "https://github.com/owner/repo/blob/main/test.md" ,
411411 } ) ;
412- buffer . setIncludeFooter ( false ) ;
412+ buffer . setIncludeFooter ( "none" ) ;
413413
414414 mockGithub . rest . pulls . createReview . mockResolvedValue ( {
415415 data : {
@@ -503,7 +503,7 @@ describe("pr_review_buffer (factory pattern)", () => {
503503 } ) ;
504504
505505 describe ( "reset" , ( ) => {
506- it ( "should clear all state including includeFooter " , ( ) => {
506+ it ( "should clear all state including footer mode " , ( ) => {
507507 buffer . addComment ( { path : "test.js" , line : 1 , body : "comment" } ) ;
508508 buffer . setReviewMetadata ( "body" , "APPROVE" ) ;
509509 buffer . setReviewContext ( {
@@ -512,7 +512,7 @@ describe("pr_review_buffer (factory pattern)", () => {
512512 pullRequestNumber : 1 ,
513513 pullRequest : { head : { sha : "abc" } } ,
514514 } ) ;
515- buffer . setIncludeFooter ( false ) ;
515+ buffer . setFooterMode ( "none" ) ;
516516
517517 buffer . reset ( ) ;
518518
@@ -521,7 +521,7 @@ describe("pr_review_buffer (factory pattern)", () => {
521521 expect ( buffer . hasReviewMetadata ( ) ) . toBe ( false ) ;
522522 expect ( buffer . getReviewContext ( ) ) . toBeNull ( ) ;
523523
524- // After reset, footer should be re-enabled (default: true )
524+ // After reset, footer should be "always" (default)
525525 // Verify by submitting a review with footer context and checking body
526526 buffer . addComment ( { path : "test.js" , line : 1 , body : "comment" } ) ;
527527 buffer . setReviewMetadata ( "Review after reset" , "COMMENT" ) ;
@@ -545,9 +545,209 @@ describe("pr_review_buffer (factory pattern)", () => {
545545 return buffer . submitReview ( ) . then ( result => {
546546 expect ( result . success ) . toBe ( true ) ;
547547 const callArgs = mockGithub . rest . pulls . createReview . mock . calls [ 0 ] [ 0 ] ;
548- // Footer should be included since includeFooter was reset to true
548+ // Footer should be included since footer mode was reset to "always"
549549 expect ( callArgs . body ) . toContain ( "test-workflow" ) ;
550550 } ) ;
551551 } ) ;
552552 } ) ;
553+
554+ describe ( "footer mode" , ( ) => {
555+ it ( "should support 'always' mode (default)" , async ( ) => {
556+ buffer . addComment ( { path : "test.js" , line : 1 , body : "comment" } ) ;
557+ buffer . setReviewMetadata ( "" , "APPROVE" ) ; // Empty body
558+ buffer . setReviewContext ( {
559+ repo : "owner/repo" ,
560+ repoParts : { owner : "owner" , repo : "repo" } ,
561+ pullRequestNumber : 42 ,
562+ pullRequest : { head : { sha : "abc123" } } ,
563+ } ) ;
564+ buffer . setFooterContext ( {
565+ workflowName : "test-workflow" ,
566+ runUrl : "https://github.com/owner/repo/actions/runs/123" ,
567+ workflowSource : "owner/repo/workflows/test.md@v1" ,
568+ workflowSourceURL : "https://github.com/owner/repo/blob/main/test.md" ,
569+ } ) ;
570+ buffer . setFooterMode ( "always" ) ;
571+
572+ mockGithub . rest . pulls . createReview . mockResolvedValue ( {
573+ data : {
574+ id : 500 ,
575+ html_url : "https://github.com/owner/repo/pull/42#pullrequestreview-500" ,
576+ } ,
577+ } ) ;
578+
579+ const result = await buffer . submitReview ( ) ;
580+
581+ expect ( result . success ) . toBe ( true ) ;
582+ const callArgs = mockGithub . rest . pulls . createReview . mock . calls [ 0 ] [ 0 ] ;
583+ // Footer should be included even with empty body
584+ expect ( callArgs . body ) . toContain ( "test-workflow" ) ;
585+ } ) ;
586+
587+ it ( "should support 'none' mode" , async ( ) => {
588+ buffer . addComment ( { path : "test.js" , line : 1 , body : "comment" } ) ;
589+ buffer . setReviewMetadata ( "Review body" , "COMMENT" ) ;
590+ buffer . setReviewContext ( {
591+ repo : "owner/repo" ,
592+ repoParts : { owner : "owner" , repo : "repo" } ,
593+ pullRequestNumber : 42 ,
594+ pullRequest : { head : { sha : "abc123" } } ,
595+ } ) ;
596+ buffer . setFooterContext ( {
597+ workflowName : "test-workflow" ,
598+ runUrl : "https://github.com/owner/repo/actions/runs/123" ,
599+ workflowSource : "owner/repo/workflows/test.md@v1" ,
600+ workflowSourceURL : "https://github.com/owner/repo/blob/main/test.md" ,
601+ } ) ;
602+ buffer . setFooterMode ( "none" ) ;
603+
604+ mockGithub . rest . pulls . createReview . mockResolvedValue ( {
605+ data : {
606+ id : 501 ,
607+ html_url : "https://github.com/owner/repo/pull/42#pullrequestreview-501" ,
608+ } ,
609+ } ) ;
610+
611+ const result = await buffer . submitReview ( ) ;
612+
613+ expect ( result . success ) . toBe ( true ) ;
614+ const callArgs = mockGithub . rest . pulls . createReview . mock . calls [ 0 ] [ 0 ] ;
615+ // Footer should not be included
616+ expect ( callArgs . body ) . toBe ( "Review body" ) ;
617+ expect ( callArgs . body ) . not . toContain ( "test-workflow" ) ;
618+ } ) ;
619+
620+ it ( "should support 'if-body' mode with non-empty body" , async ( ) => {
621+ buffer . addComment ( { path : "test.js" , line : 1 , body : "comment" } ) ;
622+ buffer . setReviewMetadata ( "Review body" , "COMMENT" ) ;
623+ buffer . setReviewContext ( {
624+ repo : "owner/repo" ,
625+ repoParts : { owner : "owner" , repo : "repo" } ,
626+ pullRequestNumber : 42 ,
627+ pullRequest : { head : { sha : "abc123" } } ,
628+ } ) ;
629+ buffer . setFooterContext ( {
630+ workflowName : "test-workflow" ,
631+ runUrl : "https://github.com/owner/repo/actions/runs/123" ,
632+ workflowSource : "owner/repo/workflows/test.md@v1" ,
633+ workflowSourceURL : "https://github.com/owner/repo/blob/main/test.md" ,
634+ } ) ;
635+ buffer . setFooterMode ( "if-body" ) ;
636+
637+ mockGithub . rest . pulls . createReview . mockResolvedValue ( {
638+ data : {
639+ id : 502 ,
640+ html_url : "https://github.com/owner/repo/pull/42#pullrequestreview-502" ,
641+ } ,
642+ } ) ;
643+
644+ const result = await buffer . submitReview ( ) ;
645+
646+ expect ( result . success ) . toBe ( true ) ;
647+ const callArgs = mockGithub . rest . pulls . createReview . mock . calls [ 0 ] [ 0 ] ;
648+ // Footer should be included because body is non-empty
649+ expect ( callArgs . body ) . toContain ( "Review body" ) ;
650+ expect ( callArgs . body ) . toContain ( "test-workflow" ) ;
651+ } ) ;
652+
653+ it ( "should support 'if-body' mode with empty body" , async ( ) => {
654+ buffer . addComment ( { path : "test.js" , line : 1 , body : "comment" } ) ;
655+ buffer . setReviewMetadata ( "" , "APPROVE" ) ; // Empty body
656+ buffer . setReviewContext ( {
657+ repo : "owner/repo" ,
658+ repoParts : { owner : "owner" , repo : "repo" } ,
659+ pullRequestNumber : 42 ,
660+ pullRequest : { head : { sha : "abc123" } } ,
661+ } ) ;
662+ buffer . setFooterContext ( {
663+ workflowName : "test-workflow" ,
664+ runUrl : "https://github.com/owner/repo/actions/runs/123" ,
665+ workflowSource : "owner/repo/workflows/test.md@v1" ,
666+ workflowSourceURL : "https://github.com/owner/repo/blob/main/test.md" ,
667+ } ) ;
668+ buffer . setFooterMode ( "if-body" ) ;
669+
670+ mockGithub . rest . pulls . createReview . mockResolvedValue ( {
671+ data : {
672+ id : 503 ,
673+ html_url : "https://github.com/owner/repo/pull/42#pullrequestreview-503" ,
674+ } ,
675+ } ) ;
676+
677+ const result = await buffer . submitReview ( ) ;
678+
679+ expect ( result . success ) . toBe ( true ) ;
680+ const callArgs = mockGithub . rest . pulls . createReview . mock . calls [ 0 ] [ 0 ] ;
681+ // Footer should NOT be included because body is empty
682+ // Body should be undefined (not included in API call) when empty
683+ expect ( callArgs . body ) . toBeUndefined ( ) ;
684+ expect ( callArgs . body || "" ) . not . toContain ( "test-workflow" ) ;
685+ } ) ;
686+
687+ it ( "should support 'if-body' mode with whitespace-only body" , async ( ) => {
688+ buffer . addComment ( { path : "test.js" , line : 1 , body : "comment" } ) ;
689+ buffer . setReviewMetadata ( " \n " , "APPROVE" ) ; // Whitespace-only body
690+ buffer . setReviewContext ( {
691+ repo : "owner/repo" ,
692+ repoParts : { owner : "owner" , repo : "repo" } ,
693+ pullRequestNumber : 42 ,
694+ pullRequest : { head : { sha : "abc123" } } ,
695+ } ) ;
696+ buffer . setFooterContext ( {
697+ workflowName : "test-workflow" ,
698+ runUrl : "https://github.com/owner/repo/actions/runs/123" ,
699+ workflowSource : "owner/repo/workflows/test.md@v1" ,
700+ workflowSourceURL : "https://github.com/owner/repo/blob/main/test.md" ,
701+ } ) ;
702+ buffer . setFooterMode ( "if-body" ) ;
703+
704+ mockGithub . rest . pulls . createReview . mockResolvedValue ( {
705+ data : {
706+ id : 504 ,
707+ html_url : "https://github.com/owner/repo/pull/42#pullrequestreview-504" ,
708+ } ,
709+ } ) ;
710+
711+ const result = await buffer . submitReview ( ) ;
712+
713+ expect ( result . success ) . toBe ( true ) ;
714+ const callArgs = mockGithub . rest . pulls . createReview . mock . calls [ 0 ] [ 0 ] ;
715+ // Footer should NOT be included because body is whitespace-only (trimmed length is 0)
716+ // Original whitespace body is preserved in the API call
717+ expect ( callArgs . body ) . toBe ( " \n " ) ;
718+ expect ( callArgs . body ) . not . toContain ( "test-workflow" ) ;
719+ } ) ;
720+
721+ it ( "should default to 'always' for invalid string mode" , async ( ) => {
722+ buffer . addComment ( { path : "test.js" , line : 1 , body : "comment" } ) ;
723+ buffer . setReviewMetadata ( "" , "APPROVE" ) ;
724+ buffer . setReviewContext ( {
725+ repo : "owner/repo" ,
726+ repoParts : { owner : "owner" , repo : "repo" } ,
727+ pullRequestNumber : 42 ,
728+ pullRequest : { head : { sha : "abc123" } } ,
729+ } ) ;
730+ buffer . setFooterContext ( {
731+ workflowName : "test-workflow" ,
732+ runUrl : "https://github.com/owner/repo/actions/runs/123" ,
733+ workflowSource : "owner/repo/workflows/test.md@v1" ,
734+ workflowSourceURL : "https://github.com/owner/repo/blob/main/test.md" ,
735+ } ) ;
736+ buffer . setFooterMode ( "invalid-mode" ) ;
737+
738+ mockGithub . rest . pulls . createReview . mockResolvedValue ( {
739+ data : {
740+ id : 507 ,
741+ html_url : "https://github.com/owner/repo/pull/42#pullrequestreview-507" ,
742+ } ,
743+ } ) ;
744+
745+ const result = await buffer . submitReview ( ) ;
746+
747+ expect ( result . success ) . toBe ( true ) ;
748+ const callArgs = mockGithub . rest . pulls . createReview . mock . calls [ 0 ] [ 0 ] ;
749+ // Should default to "always" and include footer
750+ expect ( callArgs . body ) . toContain ( "test-workflow" ) ;
751+ } ) ;
752+ } ) ;
553753} ) ;
0 commit comments