@@ -246,9 +246,12 @@ def test_the_format_asks_git_for_the_hash_and_the_body(self):
246246 self .assertEqual (main .COMMIT_LOG_FORMAT , "--pretty=format:%H%x00%B%x00" )
247247 self .assertNotIn ("\x00 " , main .COMMIT_LOG_FORMAT )
248248
249- def test_an_empty_message_does_not_shift_the_hashes_after_it (self ):
249+ def test_an_empty_message_is_kept_and_does_not_shift_the_hashes (self ):
250250 output = f"{ SHA_A } \x00 \n \x00 \n { SHA_B } \x00 feat: second\n \x00 "
251- self .assertEqual (main .parse_commit_messages (output ), [(SHA_B , "feat: second" )])
251+ self .assertEqual (
252+ main .parse_commit_messages (output ),
253+ [(SHA_A , "" ), (SHA_B , "feat: second" )],
254+ )
252255
253256 def test_empty_output_is_no_commits (self ):
254257 self .assertEqual (main .parse_commit_messages ("" ), [])
@@ -2540,6 +2543,7 @@ def test_updates_existing_comment_when_changed(self):
25402543 def test_skips_when_comment_is_up_to_date (self ):
25412544 body = main .render_pr_comment ([fail_scope ()])
25422545 existing = MagicMock (body = body )
2546+ existing .user .type = "Bot"
25432547 mock_pull_request = MagicMock ()
25442548 mock_pull_request .get_comments .return_value = [existing ]
25452549 mock_repo = MagicMock ()
@@ -2989,6 +2993,14 @@ def test_bot_comment_from_an_older_version_is_adopted(self):
29892993 self .assertIs (target , legacy )
29902994 self .assertEqual (stale , [])
29912995
2996+ def test_human_comment_with_the_marker_is_never_touched (self ):
2997+ """A person can paste the marker too, e.g. quoting a report."""
2998+ quoted = self ._comment (f"{ main .COMMENT_MARKER } \n quoted" , user_type = "User" )
2999+ mine = self ._comment (f"{ main .COMMENT_MARKER } \n report" )
3000+ self .assertEqual (main ._find_own_comments ([quoted , mine ]), (mine , []))
3001+ self .assertEqual (main ._find_own_comments ([mine , quoted ]), (mine , []))
3002+ self .assertEqual (main ._find_own_comments ([quoted ]), (None , []))
3003+
29923004 def test_no_comments_yields_nothing_to_update (self ):
29933005 target , stale = main ._find_own_comments ([])
29943006 self .assertIsNone (target )
@@ -4181,3 +4193,116 @@ def test_a_missing_pygithub_warns(self):
41814193
41824194if __name__ == "__main__" :
41834195 unittest .main ()
4196+
4197+
4198+ class TestBooleanInputs (unittest .TestCase ):
4199+ """A boolean input is true or false; anything else fails the step."""
4200+
4201+ def setUp (self ):
4202+ main .INVALID_FLAGS .clear ()
4203+ self .addCleanup (main .INVALID_FLAGS .clear )
4204+
4205+ def test_true_and_false_in_any_case_and_padding (self ):
4206+ for value , expected in (
4207+ ("true" , True ),
4208+ (" True " , True ),
4209+ ("FALSE" , False ),
4210+ ("false" , False ),
4211+ ):
4212+ with patch .dict (os .environ , {"MESSAGE" : value }):
4213+ self .assertIs (main .env_flag ("MESSAGE" ), expected , value )
4214+ self .assertEqual (main .INVALID_FLAGS , [])
4215+
4216+ def test_unset_input_takes_the_default (self ):
4217+ with patch .dict (os .environ , {}, clear = True ):
4218+ self .assertFalse (main .env_flag ("MESSAGE" ))
4219+ self .assertEqual (main .INVALID_FLAGS , [])
4220+
4221+ def test_other_values_are_recorded (self ):
4222+ for value in ("yes" , "on" , "1" , "maybe" ):
4223+ with patch .dict (os .environ , {"MESSAGE" : value }):
4224+ self .assertFalse (main .env_flag ("MESSAGE" ))
4225+ self .assertEqual (
4226+ main .INVALID_FLAGS ,
4227+ [
4228+ ("MESSAGE" , "yes" ),
4229+ ("MESSAGE" , "on" ),
4230+ ("MESSAGE" , "1" ),
4231+ ("MESSAGE" , "maybe" ),
4232+ ],
4233+ )
4234+
4235+ def test_invalid_input_fails_before_any_check (self ):
4236+ main .INVALID_FLAGS .append (("PR_TITLE" , "yes" ))
4237+ out = io .StringIO ()
4238+ with (
4239+ patch ("sys.stdout" , out ),
4240+ patch ("main.run_commit_check" ) as run ,
4241+ self .assertRaises (SystemExit ) as cm ,
4242+ ):
4243+ main .main ()
4244+ self .assertEqual (cm .exception .code , 1 )
4245+ run .assert_not_called ()
4246+ self .assertIn (
4247+ "::error::Input pr-title must be true or false, got 'yes'" , out .getvalue ()
4248+ )
4249+
4250+
4251+ class TestPrCommentApiUrl (unittest .TestCase ):
4252+ """The PR comment goes to the same API host as every other call (GHES)."""
4253+
4254+ def test_comment_client_uses_github_api_url (self ):
4255+ github_module = MagicMock ()
4256+ pull_request = MagicMock ()
4257+ pull_request .get_comments .return_value = []
4258+ github_module .Github .return_value .get_repo .return_value .get_issue .return_value = pull_request
4259+ with (
4260+ patch ("main.PR_COMMENTS_ENABLED" , True ),
4261+ patch ("main.is_fork_pr_with_readonly_token" , return_value = False ),
4262+ patch ("main.get_pr_number" , return_value = 7 ),
4263+ patch .dict (
4264+ os .environ ,
4265+ {
4266+ "GITHUB_EVENT_NAME" : "pull_request" ,
4267+ "GITHUB_TOKEN" : "t" ,
4268+ "GITHUB_REPOSITORY" : "o/r" ,
4269+ "GITHUB_API_URL" : "https://ghe.example.com/api/v3" ,
4270+ },
4271+ ),
4272+ patch .dict (sys .modules , {"github" : github_module }),
4273+ ):
4274+ main .add_pr_comments ([fail_scope ()])
4275+ _ , kwargs = github_module .Github .call_args
4276+ self .assertEqual (kwargs ["base_url" ], "https://ghe.example.com/api/v3" )
4277+
4278+
4279+ class TestEmptyCommitMessage (unittest .TestCase ):
4280+ """An empty message is checked as empty, never as HEAD's message."""
4281+
4282+ def test_an_empty_message_goes_to_the_cli_as_an_empty_file (self ):
4283+ seen : list [tuple [list [str ], str | None , str ]] = []
4284+
4285+ def run (command , ** kwargs ):
4286+ path = command [- 1 ]
4287+ with open (path , encoding = "utf-8" ) as f :
4288+ seen .append ((command , kwargs .get ("input" ), f .read ()))
4289+ return MagicMock (
4290+ returncode = 1 ,
4291+ stdout = json_output (make_check ("allow_empty_commits" , status = "fail" )),
4292+ stderr = "" ,
4293+ )
4294+
4295+ with (
4296+ patch ("main.subprocess.run" , side_effect = run ),
4297+ patch ("main._local_author" , return_value = None ),
4298+ ):
4299+ results = main .run_pr_message_checks ([("a1" , "" )])
4300+ command , piped , content = seen [0 ]
4301+ self .assertEqual (command [:4 ], ["commit-check" , "--format" , "json" , "--message" ])
4302+ self .assertIsNone (piped )
4303+ self .assertEqual (content , "" )
4304+ self .assertFalse (os .path .exists (command [- 1 ]))
4305+ self .assertEqual (
4306+ [(s .label , s .sha , s .status ) for s in results ],
4307+ [("Commit 1/1" , "a1" , "fail" )],
4308+ )
0 commit comments