@@ -384,7 +384,7 @@ async def test_url_extraction(self, _mock_google_token):
384384
385385class TestSheetsWriteTool :
386386 @pytest .mark .asyncio
387- async def test_write_overwrite (self , _mock_google_token ):
387+ async def test_write_overwrite_confirmed (self , _mock_google_token ):
388388 mock_resp = _mock_response (
389389 {
390390 "updatedRange" : "Sheet1!A1:B3" ,
@@ -399,6 +399,51 @@ async def test_write_overwrite(self, _mock_google_token):
399399 SheetsWriteInput (
400400 spreadsheet_id = "abc123def456ghi789jkl012mno345pqr678stu901v" ,
401401 data = [{"name" : "Alice" }, {"name" : "Bob" }],
402+ confirm_overwrite = True ,
403+ )
404+ )
405+
406+ assert "Wrote" in result [0 ].text
407+
408+ @pytest .mark .asyncio
409+ async def test_write_overwrite_warns_if_existing_data (self , _mock_google_token ):
410+ """Writing without confirm_overwrite warns when range has data."""
411+ read_resp = _mock_response ({"values" : [["name" ], ["Alice" ]]})
412+
413+ with patch .object (
414+ httpx .AsyncClient , "get" , new_callable = AsyncMock , return_value = read_resp
415+ ):
416+ result = await sheets_write (
417+ SheetsWriteInput (
418+ spreadsheet_id = "abc123def456ghi789jkl012mno345pqr678stu901v" ,
419+ data = [{"name" : "Bob" }],
420+ )
421+ )
422+
423+ assert "already contains" in result [0 ].text
424+ assert "confirm_overwrite" in result [0 ].text
425+
426+ @pytest .mark .asyncio
427+ async def test_write_overwrite_proceeds_on_empty_range (self , _mock_google_token ):
428+ """Writing without confirm_overwrite proceeds when range is empty."""
429+ read_resp = _mock_response ({}) # empty range
430+ write_resp = _mock_response ({"updatedRange" : "Sheet1!A1:B2" , "updatedRows" : 2 })
431+
432+ with (
433+ patch .object (
434+ httpx .AsyncClient , "get" , new_callable = AsyncMock , return_value = read_resp
435+ ),
436+ patch .object (
437+ httpx .AsyncClient ,
438+ "put" ,
439+ new_callable = AsyncMock ,
440+ return_value = write_resp ,
441+ ),
442+ ):
443+ result = await sheets_write (
444+ SheetsWriteInput (
445+ spreadsheet_id = "abc123def456ghi789jkl012mno345pqr678stu901v" ,
446+ data = [{"name" : "Bob" }],
402447 )
403448 )
404449
@@ -432,15 +477,27 @@ async def test_write_append(self, _mock_google_token):
432477class TestSheetsCreateTool :
433478 @pytest .mark .asyncio
434479 async def test_create_empty (self , _mock_google_token ):
435- mock_resp = _mock_response (
480+ list_resp = _mock_response ({"files" : []}) # no duplicates
481+ create_resp = _mock_response (
436482 {
437483 "spreadsheetId" : "new-id-123" ,
438484 "spreadsheetUrl" : "https://docs.google.com/spreadsheets/d/new-id-123" ,
439485 }
440486 )
441487
442- with patch .object (
443- httpx .AsyncClient , "post" , new_callable = AsyncMock , return_value = mock_resp
488+ with (
489+ patch .object (
490+ httpx .AsyncClient ,
491+ "get" ,
492+ new_callable = AsyncMock ,
493+ return_value = list_resp ,
494+ ),
495+ patch .object (
496+ httpx .AsyncClient ,
497+ "post" ,
498+ new_callable = AsyncMock ,
499+ return_value = create_resp ,
500+ ),
444501 ):
445502 result = await sheets_create (SheetsCreateInput (title = "Test" ))
446503
@@ -451,6 +508,7 @@ async def test_create_empty(self, _mock_google_token):
451508
452509 @pytest .mark .asyncio
453510 async def test_create_with_data (self , _mock_google_token ):
511+ list_resp = _mock_response ({"files" : []}) # no duplicates
454512 create_resp = _mock_response (
455513 {
456514 "spreadsheetId" : "new-id-456" ,
@@ -460,6 +518,12 @@ async def test_create_with_data(self, _mock_google_token):
460518 write_resp = _mock_response ({"updatedRows" : 2 })
461519
462520 with (
521+ patch .object (
522+ httpx .AsyncClient ,
523+ "get" ,
524+ new_callable = AsyncMock ,
525+ return_value = list_resp ,
526+ ),
463527 patch .object (
464528 httpx .AsyncClient ,
465529 "post" ,
@@ -480,6 +544,19 @@ async def test_create_with_data(self, _mock_google_token):
480544 data = json .loads (result [0 ].text )
481545 assert data ["rows_written" ] == 1
482546
547+ @pytest .mark .asyncio
548+ async def test_create_rejects_duplicate_title (self , _mock_google_token ):
549+ """sheets_create warns when a spreadsheet with the same title exists."""
550+ list_resp = _mock_response ({"files" : [{"id" : "existing-id" , "name" : "Budget" }]})
551+
552+ with patch .object (
553+ httpx .AsyncClient , "get" , new_callable = AsyncMock , return_value = list_resp
554+ ):
555+ result = await sheets_create (SheetsCreateInput (title = "Budget" ))
556+
557+ assert "already exists" in result [0 ].text
558+ assert "existing-id" in result [0 ].text
559+
483560
484561class TestSheetsInfoTool :
485562 @pytest .mark .asyncio
0 commit comments