from typing import Type import pytest from auto_archiver.core import Media from auto_archiver.modules.s3_storage import S3Storage class TestS3Storage: """ Test suite for S3Storage. """ module_name: str = "s3_storage" storage: Type[S3Storage] config: dict = { "path_generator": "flat", "filename_generator": "static", "bucket": "test-bucket", "region": "test-region", "key": "test-key", "secret": "test-secret", "random_no_duplicate": False, "endpoint_url": "https://{region}.example.com", "cdn_url": "https://cdn.example.com/{key}", "private": False, } @pytest.fixture(autouse=True) def setup_storage(self, setup_module, mocker): self.s3 = S3Storage() self.storage = setup_module(self.module_name, self.config) def test_client_initialization(self): """Test that S3 client is initialized with correct parameters""" assert self.storage.s3 is not None assert self.storage.s3.meta.region_name == "test-region" def test_get_cdn_url_generation(self): """Test CDN URL formatting""" media = Media("test.txt") media._key = "path/to/file.txt" url = self.storage.get_cdn_url(media) assert url == "https://cdn.example.com/path/to/file.txt" media._key = "another/path.jpg" assert self.storage.get_cdn_url(media) == "https://cdn.example.com/another/path.jpg" def test_uploadf_sets_acl_public(self, mocker): media = Media("test.png") mock_file = mocker.MagicMock() mock_s3_upload = mocker.patch.object(self.storage.s3, "upload_fileobj") mocker.patch.object(self.storage, "is_upload_needed", return_value=True) self.storage.uploadf(mock_file, media) mock_s3_upload.assert_called_once_with( mock_file, Bucket="test-bucket", Key=media.key, ExtraArgs={"ACL": "public-read", "ContentType": "image/png"}, ) def test_uploadf_detects_charset_for_text_files(self, mocker): media = Media("test.txt") mock_file = mocker.MagicMock() mock_s3_upload = mocker.patch.object(self.storage.s3, "upload_fileobj") mocker.patch.object(self.storage, "is_upload_needed", return_value=True) self.storage.uploadf(mock_file, media) mock_s3_upload.assert_called_once_with( mock_file, Bucket="test-bucket", Key=media.key, ExtraArgs={"ACL": "public-read", "ContentType": "text/plain; charset=utf-8"}, ) def test_upload_decision_logic(self, mocker): """Test is_upload_needed under different conditions""" media = Media("test.txt") assert self.storage.is_upload_needed(media) is True self.storage.random_no_duplicate = True mocker.patch( "auto_archiver.modules.s3_storage.s3_storage.calculate_file_hash", return_value="beepboop123beepboop123beepboop123", ) mock_file_in_folder = mocker.patch.object(self.storage, "file_in_folder", return_value="existing_key.txt") assert self.storage.is_upload_needed(media) is False assert media.key == "existing_key.txt" mock_file_in_folder.assert_called_with("no-dups/beepboop123beepboop123be") def test_skips_upload_when_duplicate_exists(self, mocker): """Test that upload skips when file_in_folder finds existing object""" self.storage.random_no_duplicate = True mocker.patch.object(S3Storage, "file_in_folder", return_value="existing_folder/existing_file.txt") media = Media("test.txt") media._key = "original_path.txt" mocker.patch( "auto_archiver.modules.s3_storage.s3_storage.calculate_file_hash", return_value="beepboop123beepboop123beepboop123", ) assert self.storage.is_upload_needed(media) is False assert media.key == "existing_folder/existing_file.txt" assert media.get("previously archived") is True mock_upload = mocker.patch.object(self.storage.s3, "upload_fileobj") result = self.storage.uploadf(None, media) mock_upload.assert_not_called() assert result is True def test_uploads_with_correct_parameters(self, mocker): media = Media("test.txt") media._key = "original_key.txt" mocker.patch.object(S3Storage, "is_upload_needed", return_value=True) media.mimetype = "image/png" mock_file = mocker.MagicMock() mock_upload = mocker.patch.object(self.storage.s3, "upload_fileobj") self.storage.uploadf(mock_file, media) mock_upload.assert_called_once_with( mock_file, Bucket="test-bucket", Key="original_key.txt", ExtraArgs={"ACL": "public-read", "ContentType": "image/png"}, ) def test_file_in_folder_exists(self, mocker): mocker.patch.object(self.storage.s3, "list_objects", return_value={"Contents": [{"Key": "path/to/file.txt"}]}) assert self.storage.file_in_folder("path/to/") == "path/to/file.txt"