@@ -280,3 +280,94 @@ def test_get_request_headers_with_empty_token(self, monkeypatch):
280280 assert "Authorization" not in headers
281281 assert headers ["Accept" ] == "application/vnd.github.v3+json"
282282 assert headers ["User-Agent" ] == "Haystack/GitHubFileEditor"
283+
284+ @pytest .mark .parametrize (
285+ "file_b64,original,expected" ,
286+ [
287+ ("SGVsbG8gV29ybGQ=" , "missing" , "Error: Original string not found in file" ),
288+ ("SGVsbG8gSGVsbG8=" , "Hello" , "Error: Original string appears multiple times. Please provide more context" ),
289+ ],
290+ )
291+ @patch ("requests.get" )
292+ def test_run_edit_string_edge_cases (self , mock_get , file_b64 , original , expected , monkeypatch ):
293+ monkeypatch .setenv ("GITHUB_TOKEN" , "test-token" )
294+ mock_get .return_value .json .return_value = {"content" : file_b64 , "sha" : "abc123" }
295+ mock_get .return_value .raise_for_status .return_value = None
296+
297+ editor = GitHubFileEditor ()
298+ result = editor .run (
299+ command = Command .EDIT ,
300+ payload = {"path" : "f.txt" , "original" : original , "replacement" : "X" , "message" : "m" },
301+ repo = "owner/repo" ,
302+ branch = "main" ,
303+ )
304+ assert result ["result" ] == expected
305+
306+ @patch ("requests.get" )
307+ def test_run_undo_not_last_user (self , mock_get , monkeypatch ):
308+ monkeypatch .setenv ("GITHUB_TOKEN" , "test-token" )
309+
310+ mock_get .return_value .raise_for_status .return_value = None
311+ mock_get .return_value .json .side_effect = [
312+ [{"author" : {"login" : "different_user" }, "sha" : "sha1" }],
313+ {"login" : "another_user" },
314+ ]
315+
316+ editor = GitHubFileEditor ()
317+ result = editor .run (command = Command .UNDO , payload = {"message" : "m" }, repo = "owner/repo" , branch = "main" )
318+ assert result ["result" ] == "Error: Last commit was not made by the current user"
319+
320+ @pytest .mark .parametrize (
321+ "kwargs,expected_substring" ,
322+ [
323+ ({"command" : Command .EDIT , "payload" : {}}, "Error: No repository specified" ),
324+ (
325+ {"command" : "bogus" , "payload" : {}, "repo" : "owner/repo" },
326+ None ,
327+ ),
328+ ],
329+ )
330+ def test_run_validation_errors (self , kwargs , expected_substring , monkeypatch ):
331+ monkeypatch .setenv ("GITHUB_TOKEN" , "test-token" )
332+ editor = GitHubFileEditor ()
333+ if expected_substring is None :
334+ with pytest .raises (ValueError ):
335+ editor .run (** kwargs )
336+ else :
337+ result = editor .run (** kwargs )
338+ assert expected_substring in result ["result" ]
339+
340+ @patch ("requests.get" )
341+ def test_run_command_as_string (self , mock_get , monkeypatch ):
342+ monkeypatch .setenv ("GITHUB_TOKEN" , "test-token" )
343+ mock_get .return_value .json .return_value = {"content" : "SGVsbG8=" , "sha" : "abc" }
344+ mock_get .return_value .raise_for_status .return_value = None
345+
346+ editor = GitHubFileEditor (repo = "owner/repo" )
347+ with patch .object (editor , "_update_file" , return_value = True ):
348+ result = editor .run (
349+ command = "EDIT" ,
350+ payload = {"path" : "f.txt" , "original" : "Hello" , "replacement" : "Hi" , "message" : "m" },
351+ )
352+ assert result ["result" ] == "Edit successful"
353+
354+ @pytest .mark .parametrize (
355+ "command,payload" ,
356+ [
357+ (Command .UNDO , {"message" : "m" }),
358+ (Command .CREATE , {"path" : "n.txt" , "content" : "x" , "message" : "m" }),
359+ (Command .DELETE , {"path" : "n.txt" , "message" : "m" }),
360+ ],
361+ )
362+ @patch ("requests.get" )
363+ def test_run_command_error_handling_no_raise (self , mock_get , command , payload , monkeypatch ):
364+ monkeypatch .setenv ("GITHUB_TOKEN" , "test-token" )
365+ mock_get .side_effect = requests .RequestException ("API Error" )
366+
367+ editor = GitHubFileEditor (raise_on_failure = False )
368+ with (
369+ patch ("requests.put" , side_effect = requests .RequestException ("API Error" )),
370+ patch ("requests.delete" , side_effect = requests .RequestException ("API Error" )),
371+ ):
372+ result = editor .run (command = command , payload = payload , repo = "owner/repo" , branch = "main" )
373+ assert "Error: API Error" in result ["result" ]
0 commit comments