@@ -242,3 +242,162 @@ def test_file_write_alternative_rejection(mock_user_input, temp_file):
242242
243243 # Verify file was not created
244244 assert not os .path .exists (temp_file )
245+
246+
247+ @patch ("strands_tools.file_write.get_user_input" )
248+ def test_file_write_append_mode (mock_user_input , temp_file ):
249+ """Test appending content to existing file."""
250+ mock_user_input .return_value = "y"
251+
252+ # Write initial content
253+ with open (temp_file , "w" ) as f :
254+ f .write ("Initial content\n " )
255+
256+ # Append using the tool
257+ tool_use = {
258+ "toolUseId" : "test-append" ,
259+ "input" : {"path" : temp_file , "content" : "Appended content\n " , "mode" : "append" },
260+ }
261+
262+ result = file_write .file_write (tool = tool_use )
263+ assert result ["status" ] == "success"
264+
265+ # Verify both contents are present
266+ with open (temp_file , "r" ) as f :
267+ content = f .read ()
268+ assert "Initial content\n " in content
269+ assert "Appended content\n " in content
270+ assert content == "Initial content\n Appended content\n "
271+
272+
273+ @patch ("strands_tools.file_write.get_user_input" )
274+ def test_file_write_append_mode_new_file (mock_user_input , temp_file ):
275+ """Test that append mode creates file if it doesn't exist."""
276+ mock_user_input .return_value = "y"
277+
278+ # Ensure file doesn't exist
279+ assert not os .path .exists (temp_file )
280+
281+ # Append to non-existent file
282+ tool_use = {
283+ "toolUseId" : "test-append-new" ,
284+ "input" : {"path" : temp_file , "content" : "New file content\n " , "mode" : "append" },
285+ }
286+
287+ result = file_write .file_write (tool = tool_use )
288+ assert result ["status" ] == "success"
289+
290+ # Verify file was created with content
291+ assert os .path .exists (temp_file )
292+ with open (temp_file , "r" ) as f :
293+ assert f .read () == "New file content\n "
294+
295+
296+ @patch ("strands_tools.file_write.get_user_input" )
297+ def test_file_write_default_mode_overwrites (mock_user_input , temp_file ):
298+ """Test that default mode (write) overwrites existing content."""
299+ mock_user_input .return_value = "y"
300+
301+ # Write initial content
302+ with open (temp_file , "w" ) as f :
303+ f .write ("Original content\n " )
304+
305+ # Write without specifying mode (should default to overwrite)
306+ tool_use = {
307+ "toolUseId" : "test-default-overwrite" ,
308+ "input" : {"path" : temp_file , "content" : "New content\n " },
309+ }
310+
311+ result = file_write .file_write (tool = tool_use )
312+ assert result ["status" ] == "success"
313+
314+ # Verify original content was overwritten
315+ with open (temp_file , "r" ) as f :
316+ content = f .read ()
317+ assert content == "New content\n "
318+ assert "Original content" not in content
319+
320+
321+ @patch ("strands_tools.file_write.get_user_input" )
322+ def test_file_write_write_mode_explicit (mock_user_input , temp_file ):
323+ """Test that explicit write mode overwrites existing content."""
324+ mock_user_input .return_value = "y"
325+
326+ # Write initial content
327+ with open (temp_file , "w" ) as f :
328+ f .write ("Original content\n " )
329+
330+ # Write with explicit write mode
331+ tool_use = {
332+ "toolUseId" : "test-write-mode" ,
333+ "input" : {"path" : temp_file , "content" : "Replacement content\n " , "mode" : "write" },
334+ }
335+
336+ result = file_write .file_write (tool = tool_use )
337+ assert result ["status" ] == "success"
338+
339+ # Verify original content was overwritten
340+ with open (temp_file , "r" ) as f :
341+ content = f .read ()
342+ assert content == "Replacement content\n "
343+ assert "Original content" not in content
344+
345+
346+ def test_file_write_invalid_mode (temp_file ):
347+ """Test error handling for invalid mode values."""
348+ tool_use = {
349+ "toolUseId" : "test-invalid-mode" ,
350+ "input" : {"path" : temp_file , "content" : "Test content" , "mode" : "invalid" },
351+ }
352+
353+ result = file_write .file_write (tool = tool_use )
354+
355+ # Verify the error was handled correctly
356+ assert result ["status" ] == "error"
357+ assert "Invalid mode" in result ["content" ][0 ]["text" ]
358+ assert "invalid" in result ["content" ][0 ]["text" ]
359+
360+
361+ @patch .dict ("os.environ" , {"BYPASS_TOOL_CONSENT" : "true" })
362+ def test_file_write_append_via_agent (agent , temp_file ):
363+ """Test append mode via the agent interface."""
364+ # Write initial content
365+ with open (temp_file , "w" ) as f :
366+ f .write ("First line\n " )
367+
368+ # Append via agent
369+ result = agent .tool .file_write (path = temp_file , content = "Second line\n " , mode = "append" )
370+
371+ # Verify success
372+ result_text = extract_result_text (result )
373+ assert "File write success" in result_text
374+
375+ # Verify both lines are present
376+ with open (temp_file , "r" ) as f :
377+ content = f .read ()
378+ assert "First line\n " in content
379+ assert "Second line\n " in content
380+
381+
382+ @patch ("strands_tools.file_write.get_user_input" )
383+ def test_file_write_append_multiple_times (mock_user_input , temp_file ):
384+ """Test appending multiple times to the same file."""
385+ mock_user_input .return_value = "y"
386+
387+ # Write initial content
388+ with open (temp_file , "w" ) as f :
389+ f .write ("Line 1\n " )
390+
391+ # Append multiple times
392+ for i in range (2 , 5 ):
393+ tool_use = {
394+ "toolUseId" : f"test-append-{ i } " ,
395+ "input" : {"path" : temp_file , "content" : f"Line { i } \n " , "mode" : "append" },
396+ }
397+ result = file_write .file_write (tool = tool_use )
398+ assert result ["status" ] == "success"
399+
400+ # Verify all lines are present in order
401+ with open (temp_file , "r" ) as f :
402+ content = f .read ()
403+ assert content == "Line 1\n Line 2\n Line 3\n Line 4\n "
0 commit comments