@@ -42,17 +42,26 @@ def test_generate_prompt_text_files(ai_service, mock_git_file):
4242
4343def test_generate_prompt_binary_files (ai_service , mock_git_file ):
4444 """Test prompt generation for binary files."""
45- files = [mock_git_file ("image.png" , size = 1024 )]
46- diff = "Binary files changed"
45+ files = [mock_git_file ("image.png" , size = 1024 , hash_ = "abc123" )]
46+ prompt = ai_service .generate_prompt ("" , files )
47+ assert "image.png" in prompt
48+ assert "binary file changes" in prompt
4749
48- prompt = ai_service .generate_prompt (diff , files )
4950
51+ def test_generate_prompt_mixed_files (ai_service , mock_git_file ):
52+ """Prompt should mention both binary and text changes."""
53+ files = [
54+ mock_git_file ("image.png" , size = 1024 , hash_ = "abc123" ),
55+ mock_git_file ("test.py" ),
56+ ]
57+ diff = "diff content"
58+ prompt = ai_service .generate_prompt (diff , files )
5059 assert "image.png" in prompt
51- assert "Binary files changed" in prompt
60+ assert "test.py" in prompt
61+ assert "Binary files" in prompt
5262
5363
54- @patch ("requests.post" )
55- def test_generate_commit_message_success (mock_post , ai_service , mock_git_file ):
64+ def test_generate_commit_message_success (ai_service , mock_git_file ):
5665 """Test successful commit message generation."""
5766 mock_response = {
5867 "choices" : [
@@ -76,20 +85,25 @@ def test_generate_commit_message_success(mock_post, ai_service, mock_git_file):
7685 "usage" : {"prompt_tokens" : 100 , "completion_tokens" : 50 , "total_tokens" : 150 },
7786 }
7887
79- mock_post .return_value = MagicMock (status_code = 200 , json = lambda : mock_response )
88+ ai_service .session .post = MagicMock (
89+ return_value = MagicMock (status_code = 200 , json = lambda : mock_response )
90+ )
8091
81- suggestion , usage = ai_service .generate_commit_message ("test diff" , [mock_git_file ("test.py" )])
92+ suggestion , usage = ai_service .generate_commit_message (
93+ "test diff" , [mock_git_file ("test.py" )]
94+ )
8295
8396 assert isinstance (suggestion , CommitSuggestion )
8497 assert suggestion .title == "✨ feat: add new feature"
8598 assert usage .total_tokens == 150
8699
87100
88- @patch ("requests.post" )
89- def test_generate_commit_message_api_error (mock_post , ai_service , mock_git_file ):
101+ def test_generate_commit_message_api_error (ai_service , mock_git_file ):
90102 """Test handling of API errors."""
91- mock_post .return_value = MagicMock (
92- status_code = 400 , json = lambda : {"error" : {"message" : "API Error" }}
103+ ai_service .session .post = MagicMock (
104+ return_value = MagicMock (
105+ status_code = 400 , json = lambda : {"error" : {"message" : "API Error" }}
106+ )
93107 )
94108
95109 with pytest .raises (ValueError ) as exc_info :
@@ -98,33 +112,72 @@ def test_generate_commit_message_api_error(mock_post, ai_service, mock_git_file)
98112 assert "API Error" in str (exc_info .value )
99113
100114
101- @patch ("requests.post" )
102- def test_generate_commit_message_invalid_json (mock_post , ai_service , mock_git_file ):
115+ def test_generate_commit_message_invalid_json (ai_service , mock_git_file ):
103116 """Test handling of invalid JSON response."""
104117 mock_response = {
105118 "choices" : [{"message" : {"content" : "Invalid JSON" }}],
106119 "usage" : {"prompt_tokens" : 100 , "completion_tokens" : 50 , "total_tokens" : 150 },
107120 }
108121
109- mock_post .return_value = MagicMock (status_code = 200 , json = lambda : mock_response )
122+ ai_service .session .post = MagicMock (
123+ return_value = MagicMock (status_code = 200 , json = lambda : mock_response )
124+ )
110125
111126 with pytest .raises (ValueError ) as exc_info :
112127 ai_service .generate_commit_message ("test diff" , [mock_git_file ("test.py" )])
113128
114129 assert "Failed to parse AI response" in str (exc_info .value )
115130
116131
117- @patch ("requests.post" )
118- def test_generate_commit_message_network_error (mock_post , ai_service , mock_git_file ):
132+ def test_generate_commit_message_network_error (ai_service , mock_git_file ):
119133 """Test handling of network errors."""
120- mock_post .side_effect = requests .exceptions .RequestException ("Network Error" )
134+ ai_service .session .post = MagicMock (
135+ side_effect = requests .exceptions .RequestException ("Network Error" )
136+ )
121137
122138 with pytest .raises (ValueError ) as exc_info :
123139 ai_service .generate_commit_message ("test diff" , [mock_git_file ("test.py" )])
124140
125141 assert "Network Error" in str (exc_info .value )
126142
127143
144+ @patch ("time.sleep" , return_value = None )
145+ def test_generate_commit_message_retries (mock_sleep , ai_service , mock_git_file ):
146+ """Temporary failures should be retried."""
147+ mock_response = {
148+ "choices" : [
149+ {
150+ "message" : {
151+ "content" : json .dumps (
152+ {
153+ "title" : "✨ feat: retry success" ,
154+ "body" : {
155+ "Features" : {
156+ "emoji" : "✨" ,
157+ "changes" : ["Added new functionality" ],
158+ }
159+ },
160+ "summary" : "Added new feature" ,
161+ }
162+ )
163+ }
164+ }
165+ ],
166+ "usage" : {"prompt_tokens" : 1 , "completion_tokens" : 1 , "total_tokens" : 2 },
167+ }
168+ ai_service .session .post = MagicMock (
169+ side_effect = [
170+ requests .exceptions .RequestException ("temp" ),
171+ MagicMock (status_code = 200 , json = lambda : mock_response ),
172+ ]
173+ )
174+ suggestion , _ = ai_service .generate_commit_message (
175+ "diff" , [mock_git_file ("test.py" )]
176+ )
177+ assert suggestion .title == "✨ feat: retry success"
178+ assert ai_service .session .post .call_count == 2
179+
180+
128181def test_format_commit_message ():
129182 """Test commit message formatting."""
130183 suggestion = CommitSuggestion (
@@ -146,3 +199,17 @@ def test_ai_service_missing_api_key():
146199 AIService (api_key = None )
147200
148201 assert "API key is required" in str (exc_info .value )
202+
203+
204+ @patch ("time.sleep" , return_value = None )
205+ def test_generate_commit_message_retries_exhausted (
206+ mock_sleep , ai_service , mock_git_file
207+ ):
208+ """Should raise error after exhausting all retries."""
209+ ai_service .session .post = MagicMock (
210+ side_effect = requests .exceptions .RequestException ("temp" )
211+ )
212+ with pytest .raises (ValueError ) as exc_info :
213+ ai_service .generate_commit_message ("diff" , [mock_git_file ("test.py" )])
214+ assert "API Request failed" in str (exc_info .value )
215+ assert ai_service .session .post .call_count == 3
0 commit comments