@@ -308,6 +308,29 @@ def test_run_returns_empty_when_all_filtered(self, tmp_path, mock_s3_storage, mo
308308 assert out ["documents" ] == []
309309 mock_s3_storage .download .assert_not_called ()
310310
311+ def test_download_writes_to_temp_path_then_renames (self , tmp_path , mock_boto3_session ):
312+ d = S3Downloader (file_root_path = str (tmp_path ))
313+
314+ final_path = tmp_path / "test.pdf"
315+ captured_paths = []
316+
317+ def fake_download (key , local_file_path : Path ):
318+ captured_paths .append (Path (local_file_path ))
319+ assert not final_path .exists (), "final path must not exist while download is in progress"
320+ Path (local_file_path ).write_bytes (b"complete content" )
321+
322+ mock_storage = MagicMock (spec = S3Storage )
323+ mock_storage .download .side_effect = fake_download
324+ d ._storage = mock_storage
325+
326+ d .run (documents = [Document (meta = {"file_name" : "test.pdf" })])
327+
328+ assert len (captured_paths ) == 1
329+ assert captured_paths [0 ] != final_path
330+ assert captured_paths [0 ].name .startswith ("test.pdf.tmp-" )
331+ assert final_path .exists ()
332+ assert final_path .read_bytes () == b"complete content"
333+
311334 def test_cleanup_cache_evicts_old_files (self , tmp_path , mock_s3_storage , mock_boto3_session ):
312335 d = S3Downloader (file_root_path = str (tmp_path ), max_cache_size = 1 )
313336 d ._storage = mock_s3_storage
0 commit comments