from django.test import TestCase, override_settings from django.core.files.uploadedfile import SimpleUploadedFile from django.contrib.auth import get_user_model from django.contrib.contenttypes.models import ContentType from django.utils import timezone from datetime import datetime from PIL import Image, ExifTags import io from .models import Photo from parks.models import Park User = get_user_model() class PhotoModelTests(TestCase): def setUp(self): # Create a test user self.user = User.objects.create_user( username='testuser', password='testpass123' ) # Create a test park for photo association self.park = Park.objects.create( name='Test Park', slug='test-park' ) self.content_type = ContentType.objects.get_for_model(Park) def create_test_image_with_exif(self, date_taken=None): """Helper method to create a test image with EXIF data""" # Create a test image image = Image.new('RGB', (100, 100), color='red') image_io = io.BytesIO() # Add EXIF data if date_taken is provided if date_taken: exif_dict = { "0th": {}, "Exif": { ExifTags.Base.DateTimeOriginal: date_taken.strftime("%Y:%m:%d %H:%M:%S").encode() } } image.save(image_io, 'JPEG', exif=exif_dict) else: image.save(image_io, 'JPEG') image_io.seek(0) return SimpleUploadedFile( 'test.jpg', image_io.getvalue(), content_type='image/jpeg' ) def test_photo_creation(self): """Test basic photo creation""" photo = Photo.objects.create( image=SimpleUploadedFile( 'test.jpg', b'dummy image data', content_type='image/jpeg' ), caption='Test Caption', uploaded_by=self.user, content_type=self.content_type, object_id=self.park.pk ) self.assertEqual(photo.caption, 'Test Caption') self.assertEqual(photo.uploaded_by, self.user) self.assertIsNone(photo.date_taken) def test_exif_date_extraction(self): """Test EXIF date extraction from uploaded photos""" test_date = datetime(2024, 1, 1, 12, 0, 0) image_file = self.create_test_image_with_exif(test_date) photo = Photo.objects.create( image=image_file, uploaded_by=self.user, content_type=self.content_type, object_id=self.park.pk ) if photo.date_taken: self.assertEqual( photo.date_taken.strftime("%Y-%m-%d %H:%M:%S"), test_date.strftime("%Y-%m-%d %H:%M:%S") ) else: self.skipTest("EXIF data extraction not supported in test environment") def test_photo_without_exif(self): """Test photo upload without EXIF data""" image_file = self.create_test_image_with_exif() # No date provided photo = Photo.objects.create( image=image_file, uploaded_by=self.user, content_type=self.content_type, object_id=self.park.pk ) self.assertIsNone(photo.date_taken) def test_default_caption(self): """Test default caption generation""" photo = Photo.objects.create( image=SimpleUploadedFile( 'test.jpg', b'dummy image data', content_type='image/jpeg' ), uploaded_by=self.user, content_type=self.content_type, object_id=self.park.pk ) expected_prefix = f"Uploaded by {self.user.username} on" self.assertTrue(photo.caption.startswith(expected_prefix)) def test_primary_photo_toggle(self): """Test primary photo functionality""" # Create two photos photo1 = Photo.objects.create( image=SimpleUploadedFile( 'test1.jpg', b'dummy image data', content_type='image/jpeg' ), uploaded_by=self.user, content_type=self.content_type, object_id=self.park.pk, is_primary=True ) photo2 = Photo.objects.create( image=SimpleUploadedFile( 'test2.jpg', b'dummy image data', content_type='image/jpeg' ), uploaded_by=self.user, content_type=self.content_type, object_id=self.park.pk, is_primary=True ) # Refresh from database photo1.refresh_from_db() photo2.refresh_from_db() # Verify only photo2 is primary self.assertFalse(photo1.is_primary) self.assertTrue(photo2.is_primary) @override_settings(MEDIA_ROOT='test_media/') def test_photo_upload_path(self): """Test photo upload path generation""" photo = Photo.objects.create( image=SimpleUploadedFile( 'test.jpg', b'dummy image data', content_type='image/jpeg' ), uploaded_by=self.user, content_type=self.content_type, object_id=self.park.pk ) expected_path = f"park/{self.park.slug}/" self.assertTrue(photo.image.name.startswith(expected_path)) def test_date_taken_field(self): """Test date_taken field functionality""" test_date = timezone.now() photo = Photo.objects.create( image=SimpleUploadedFile( 'test.jpg', b'dummy image data', content_type='image/jpeg' ), uploaded_by=self.user, content_type=self.content_type, object_id=self.park.pk, date_taken=test_date ) self.assertEqual(photo.date_taken, test_date)