@@ -46,6 +46,21 @@ def test_cli_keyboard_interrupt(mock_parse_args, mock_assistant, capsys):
46
46
captured = capsys .readouterr ()
47
47
assert "Program interrupted by user" in captured .out
48
48
49
+ def test_run_keyboard_interrupt (assistant , capsys ):
50
+ """Test that KeyboardInterrupt is handled properly in GitCommitAssistant.run"""
51
+ changes = [Change (file = "test.py" , status = "modified" , diff = "test diff" , insertions = 1 , deletions = 0 )]
52
+
53
+ with patch .multiple (
54
+ assistant .git_ops ,
55
+ get_unstaged_changes = lambda : changes ,
56
+ get_current_branch = lambda : "main"
57
+ ):
58
+ with patch .object (assistant .ai_analyzer , 'analyze_changes' , side_effect = KeyboardInterrupt ()):
59
+ with pytest .raises (SystemExit ):
60
+ assistant .run ()
61
+
62
+ captured = capsys .readouterr ()
63
+ assert "Operation cancelled by user" in captured .out
49
64
50
65
def test_run_no_changes (assistant ):
51
66
with patch ("aicmt.git_operations.GitOperations.get_unstaged_changes" , return_value = []):
@@ -115,6 +130,24 @@ def test_run_push_error(mock_confirm, assistant):
115
130
with patch .multiple (assistant .cli , display_commit_groups = lambda x : commit_groups , confirm_push = lambda : True ):
116
131
assistant .run ()
117
132
133
+ @patch ("aicmt.cli.parse_args" )
134
+ @patch ("aicmt.cli.GitCommitAssistant" )
135
+ def test_cli_runtime_error (mock_assistant , mock_parse_args , capsys ):
136
+ # Mock GitCommitAssistant to raise a runtime error
137
+ mock_instance = mock_assistant .return_value
138
+ mock_instance .run .side_effect = Exception ("Simulated runtime error" )
139
+
140
+ # Call cli function and expect system exit
141
+ with pytest .raises (SystemExit ) as exc_info :
142
+ cli ()
143
+
144
+ # Check exit code
145
+ assert exc_info .value .code == 1
146
+
147
+ # Check error message
148
+ captured = capsys .readouterr ()
149
+ assert "Runtime Error: Simulated runtime error" in captured .out
150
+
118
151
119
152
@patch ("rich.prompt.Confirm.ask" )
120
153
def test_run_no_approved_groups (mock_confirm , assistant ):
@@ -128,3 +161,84 @@ def test_run_no_approved_groups(mock_confirm, assistant):
128
161
with patch .multiple (assistant .ai_analyzer , analyze_changes = lambda x : commit_groups ):
129
162
with patch .multiple (assistant .cli , display_commit_groups = lambda x : []):
130
163
assistant .run ()
164
+
165
+ def test_commit_creation_failure (assistant , capsys ):
166
+ changes = [Change (file = "test.py" , status = "modified" , diff = "test diff" , insertions = 1 , deletions = 0 )]
167
+ commit_groups = [{"files" : ["test.py" ], "commit_message" : "test commit" , "description" : "test description" }]
168
+
169
+ with patch .multiple (
170
+ assistant .git_ops ,
171
+ get_unstaged_changes = lambda : changes ,
172
+ get_current_branch = lambda : "main" ,
173
+ stage_files = lambda x : None ,
174
+ commit_changes = lambda x : exec ('raise Exception("Failed to create commit")' )
175
+ ):
176
+ with patch .multiple (assistant .ai_analyzer , analyze_changes = lambda x : commit_groups ):
177
+ with patch .multiple (assistant .cli , display_commit_groups = lambda x : commit_groups ):
178
+ with pytest .raises (SystemExit ):
179
+ assistant .run ()
180
+
181
+ captured = capsys .readouterr ()
182
+ assert "Failed to create commit" in captured .out
183
+
184
+
185
+ def test_push_confirmation_declined (assistant ):
186
+ changes = [Change (file = "test.py" , status = "modified" , diff = "test diff" , insertions = 1 , deletions = 0 )]
187
+ commit_groups = [{"files" : ["test.py" ], "commit_message" : "test commit" , "description" : "test description" }]
188
+
189
+ with patch .multiple (
190
+ assistant .git_ops ,
191
+ get_unstaged_changes = lambda : changes ,
192
+ get_current_branch = lambda : "main" ,
193
+ stage_files = lambda x : None ,
194
+ commit_changes = lambda x : None
195
+ ):
196
+ with patch .multiple (assistant .ai_analyzer , analyze_changes = lambda x : commit_groups ):
197
+ with patch .multiple (
198
+ assistant .cli ,
199
+ display_commit_groups = lambda x : commit_groups ,
200
+ confirm_push = lambda : False
201
+ ):
202
+ assistant .run ()
203
+
204
+
205
+ def test_push_changes_failure (assistant ):
206
+ changes = [Change (file = "test.py" , status = "modified" , diff = "test diff" , insertions = 1 , deletions = 0 )]
207
+ commit_groups = [{"files" : ["test.py" ], "commit_message" : "test commit" , "description" : "test description" }]
208
+
209
+ with patch .multiple (
210
+ assistant .git_ops ,
211
+ get_unstaged_changes = lambda : changes ,
212
+ get_current_branch = lambda : "main" ,
213
+ stage_files = lambda x : None ,
214
+ commit_changes = lambda x : None ,
215
+ push_changes = lambda : exec ('raise Exception("Failed to push commits")' )
216
+ ):
217
+ with patch .multiple (assistant .ai_analyzer , analyze_changes = lambda x : commit_groups ):
218
+ with patch .multiple (
219
+ assistant .cli ,
220
+ display_commit_groups = lambda x : commit_groups ,
221
+ confirm_push = lambda : True
222
+ ):
223
+ assistant .run ()
224
+
225
+ def test_push_changes_network_error (assistant ):
226
+ """Test push changes fails due to network error"""
227
+ changes = [Change (file = "test.py" , status = "modified" , diff = "test diff" , insertions = 1 , deletions = 0 )]
228
+ commit_groups = [{"files" : ["test.py" ], "commit_message" : "test commit" , "description" : "test description" }]
229
+
230
+ with patch .multiple (
231
+ assistant .git_ops ,
232
+ get_unstaged_changes = lambda : changes ,
233
+ get_current_branch = lambda : "main" ,
234
+ stage_files = lambda x : None ,
235
+ commit_changes = lambda x : None ,
236
+ push_changes = lambda : exec ('raise ConnectionError("Network connection failed")' )
237
+ ):
238
+ with patch .multiple (assistant .ai_analyzer , analyze_changes = lambda x : commit_groups ):
239
+ with patch .multiple (
240
+ assistant .cli ,
241
+ display_commit_groups = lambda x : commit_groups ,
242
+ confirm_push = lambda : True
243
+ ):
244
+ assistant .run ()
0 commit comments