"""S3/SILO media storage wiring (no live SILO required).""" from __future__ import annotations from pathlib import Path from unittest.mock import MagicMock, patch from django.core.files.base import ContentFile from django.core.files.storage import FileSystemStorage from django.core.management import call_command from django.core.management.base import CommandError from django.test import SimpleTestCase, TestCase, override_settings class S3MediaSettingsTests(SimpleTestCase): def test_use_s3_media_false_without_endpoint(self): from django.conf import settings self.assertFalse(settings.USE_S3_MEDIA) @override_settings( USE_S3_MEDIA=True, STORAGES={ 'default': { 'BACKEND': 'django.core.files.storage.InMemoryStorage', }, 'staticfiles': { 'BACKEND': 'django.contrib.staticfiles.storage.StaticFilesStorage', }, }, ) def test_default_storage_uses_configured_backend_when_s3_flag_on(self): from django.core.files.storage import default_storage name = default_storage.save('s3-test/hello.txt', ContentFile(b'hi')) self.assertTrue(default_storage.exists(name)) self.assertEqual(default_storage.open(name).read(), b'hi') class SyncMediaToS3CommandTests(TestCase): def test_requires_s3_config(self): with self.assertRaises(CommandError) as ctx: call_command('sync_media_to_s3') self.assertIn('S3 media is not configured', str(ctx.exception)) @override_settings(USE_S3_MEDIA=True, MEDIA_ROOT='/tmp/acore-media-missing-xyz') def test_missing_media_root(self): with self.assertRaises(CommandError) as ctx: call_command('sync_media_to_s3') self.assertIn('MEDIA_ROOT does not exist', str(ctx.exception)) def test_dry_run_lists_files(self): media = Path(self._media_dir()) (media / 'employees').mkdir(parents=True) (media / 'employees' / 'a.jpg').write_bytes(b'\xff\xd8') mock_storage = MagicMock(spec=FileSystemStorage) mock_storage.exists.return_value = False with override_settings(USE_S3_MEDIA=True, MEDIA_ROOT=str(media)), \ patch('core.management.commands.sync_media_to_s3.default_storage', mock_storage): call_command('sync_media_to_s3', '--dry-run') mock_storage.save.assert_not_called() def test_upload_calls_storage_save(self): media = Path(self._media_dir()) (media / 'x').mkdir(parents=True) (media / 'x' / 'f.bin').write_bytes(b'abc') mock_storage = MagicMock() mock_storage.exists.return_value = False mock_storage.save.side_effect = lambda name, content: name with override_settings(USE_S3_MEDIA=True, MEDIA_ROOT=str(media)), \ patch('core.management.commands.sync_media_to_s3.default_storage', mock_storage): call_command('sync_media_to_s3') mock_storage.save.assert_called_once() args, _kwargs = mock_storage.save.call_args self.assertEqual(args[0], 'x/f.bin') def _media_dir(self) -> str: import tempfile return tempfile.mkdtemp(prefix='acore-media-test-')