@@ -45,6 +45,7 @@ async def test_fetch_api_data_success(enricher, mock_github_client):
4545
4646@pytest .mark .asyncio
4747async def test_enrich_event_data (enricher , mock_task , mock_github_client ):
48+ mock_github_client .get_pull_request .return_value = {"number" : 1 , "user" : {"login" : "author" }}
4849 mock_github_client .get_pull_request_reviews .return_value = []
4950 mock_github_client .get_pull_request_files .return_value = [
5051 {"filename" : "test.py" , "status" : "added" , "additions" : 10 , "deletions" : 0 , "patch" : "+print('hello')" }
@@ -61,6 +62,53 @@ async def test_enrich_event_data(enricher, mock_task, mock_github_client):
6162 assert "diff_summary" in event_data
6263
6364
65+ @pytest .mark .asyncio
66+ async def test_enrich_event_data_refreshes_pr_details (enricher , mock_task , mock_github_client ):
67+ """Stale webhook requested_reviewers is replaced by fresh PR details from the API.
68+
69+ Simulates the synchronize+review_requested race: the webhook payload's
70+ requested_reviewers is empty, but a fresh GET /pulls/:num shows alice was
71+ requested. The enricher must surface the fresh state so CODEOWNERS rules
72+ don't false-positive.
73+ """
74+ mock_task .payload ["pull_request" ] = {
75+ "number" : 1 ,
76+ "user" : {"login" : "author" },
77+ "requested_reviewers" : [],
78+ "requested_teams" : [],
79+ }
80+ mock_github_client .get_pull_request .return_value = {
81+ "number" : 1 ,
82+ "user" : {"login" : "author" },
83+ "requested_reviewers" : [{"login" : "alice" }],
84+ "requested_teams" : [],
85+ }
86+ mock_github_client .get_pull_request_reviews .return_value = []
87+ mock_github_client .get_pull_request_files .return_value = []
88+
89+ event_data = await enricher .enrich_event_data (mock_task , "fake_token" )
90+
91+ assert event_data ["pull_request_details" ]["requested_reviewers" ] == [{"login" : "alice" }]
92+ mock_github_client .get_pull_request .assert_called_once_with ("owner/repo" , 1 , 12345 )
93+
94+
95+ @pytest .mark .asyncio
96+ async def test_enrich_event_data_falls_back_to_webhook_pr_when_refresh_fails (enricher , mock_task , mock_github_client ):
97+ """If the refresh API call fails or returns None, the webhook payload PR data is kept."""
98+ mock_task .payload ["pull_request" ] = {
99+ "number" : 1 ,
100+ "user" : {"login" : "author" },
101+ "requested_reviewers" : [{"login" : "bob" }],
102+ }
103+ mock_github_client .get_pull_request .return_value = None
104+ mock_github_client .get_pull_request_reviews .return_value = []
105+ mock_github_client .get_pull_request_files .return_value = []
106+
107+ event_data = await enricher .enrich_event_data (mock_task , "fake_token" )
108+
109+ assert event_data ["pull_request_details" ]["requested_reviewers" ] == [{"login" : "bob" }]
110+
111+
64112@pytest .mark .asyncio
65113async def test_fetch_acknowledgments (enricher , mock_github_client ):
66114 mock_github_client .get_issue_comments .return_value = [
0 commit comments