test_avatars.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. from path import Path
  2. from PIL import Image
  3. from django.contrib.auth import get_user_model
  4. from django.core.exceptions import ValidationError
  5. from django.test import TestCase
  6. from misago.conf import settings
  7. from ..avatars import dynamic, gallery, gravatar, store, uploaded
  8. from ..models import Avatar
  9. class AvatarsStoreTests(TestCase):
  10. def test_store(self):
  11. """store successfully stores and deletes avatar"""
  12. User = get_user_model()
  13. user = User.objects.create_user('Bob', 'bob@bob.com', 'pass123')
  14. test_image = Image.new("RGBA", (100, 100), 0)
  15. store.store_avatar(user, test_image)
  16. # reload user
  17. test_user = User.objects.get(pk=user.pk)
  18. # assert that avatars were stored in media
  19. avatars_dict = {}
  20. for size in settings.MISAGO_AVATARS_SIZES:
  21. avatar = user.avatar_set.get(size=size)
  22. self.assertTrue(avatar.image.url)
  23. self.assertEqual(avatar.url, avatar.image.url)
  24. avatars_dict[size] = avatar
  25. # asserts that user.avatars cache was set
  26. self.assertEqual(len(avatars_dict), len(settings.MISAGO_AVATARS_SIZES))
  27. self.assertEqual(len(user.avatars), len(settings.MISAGO_AVATARS_SIZES))
  28. self.assertEqual(len(user.avatars), len(avatars_dict))
  29. for avatar in user.avatars:
  30. self.assertIn(avatar['size'], settings.MISAGO_AVATARS_SIZES)
  31. self.assertEqual(avatar['url'], avatars_dict[avatar['size']].url)
  32. # another avatar change deleted old avatars
  33. store.store_avatar(user, test_image)
  34. for old_avatar in avatars_dict.values():
  35. avatar_path = Path(old_avatar.image.path)
  36. self.assertFalse(avatar_path.exists())
  37. self.assertFalse(avatar_path.isfile())
  38. with self.assertRaises(Avatar.DoesNotExist):
  39. Avatar.objects.get(pk=old_avatar.pk)
  40. # and updated user avatars again
  41. new_avatars_dict = {}
  42. for size in settings.MISAGO_AVATARS_SIZES:
  43. avatar = user.avatar_set.get(size=size)
  44. self.assertTrue(avatar.image.url)
  45. self.assertEqual(avatar.url, avatar.image.url)
  46. new_avatars_dict[size] = avatar
  47. self.assertTrue(avatars_dict != new_avatars_dict)
  48. # asserts that user.avatars cache was updated
  49. self.assertEqual(len(user.avatars), len(settings.MISAGO_AVATARS_SIZES))
  50. for avatar in user.avatars:
  51. self.assertIn(avatar['size'], settings.MISAGO_AVATARS_SIZES)
  52. self.assertEqual(avatar['url'], new_avatars_dict[avatar['size']].url)
  53. # delete avatar
  54. store.delete_avatar(user)
  55. for removed_avatar in new_avatars_dict.values():
  56. avatar_path = Path(removed_avatar.image.path)
  57. self.assertFalse(avatar_path.exists())
  58. self.assertFalse(avatar_path.isfile())
  59. with self.assertRaises(Avatar.DoesNotExist):
  60. Avatar.objects.get(pk=removed_avatar.pk)
  61. class AvatarSetterTests(TestCase):
  62. def setUp(self):
  63. User = get_user_model()
  64. self.user = User.objects.create_user(
  65. 'Bob', 'kontakt@rpiton.com', 'pass123')
  66. store.delete_avatar(self.user)
  67. def tearDown(self):
  68. store.delete_avatar(self.user)
  69. def assertNoAvatarIsSet(self):
  70. avatar_dir = store.get_existing_avatars_dir(self.user)
  71. for size in settings.MISAGO_AVATARS_SIZES:
  72. avatar = Path('%s/%s_%s.png' % (avatar_dir, self.user.pk, size))
  73. self.assertFalse(avatar.exists())
  74. def assertAvatarWasSet(self):
  75. avatar_dir = store.get_existing_avatars_dir(self.user)
  76. for size in settings.MISAGO_AVATARS_SIZES:
  77. avatar = Path('%s/%s_%s.png' % (avatar_dir, self.user.pk, size))
  78. self.assertTrue(avatar.exists())
  79. self.assertTrue(avatar.isfile())
  80. def test_dynamic_avatar(self):
  81. """dynamic avatar gets created"""
  82. self.assertNoAvatarIsSet()
  83. dynamic.set_avatar(self.user)
  84. self.assertAvatarWasSet()
  85. def test_random_gallery_avatar(self):
  86. """dynamic avatar gets created"""
  87. self.assertNoAvatarIsSet()
  88. gallery.set_random_avatar(self.user)
  89. self.assertAvatarWasSet()
  90. def test_selected_gallery_avatar(self):
  91. """dynamic avatar gets created"""
  92. self.assertNoAvatarIsSet()
  93. gallery.set_avatar(self.user, 'avatars/Nature/serval.jpg')
  94. self.assertAvatarWasSet()
  95. def test_gravatar(self):
  96. """dynamic avatar gets created"""
  97. self.assertNoAvatarIsSet()
  98. gravatar.set_avatar(self.user)
  99. self.assertAvatarWasSet()
  100. class MockAvatarFile(object):
  101. def __init__(self, size=None, name=None, mime=None):
  102. self.size = size
  103. self.name = name
  104. self.content_type = mime
  105. class UploadedAvatarTests(TestCase):
  106. def test_clean_crop(self):
  107. """crop validation and cleaning"""
  108. image = Image.new("RGBA", (200, 200), 0)
  109. with self.assertRaises(ValidationError):
  110. uploaded.clean_crop(image, "abc")
  111. with self.assertRaises(ValidationError):
  112. uploaded.clean_crop(image, {})
  113. with self.assertRaises(ValidationError):
  114. uploaded.clean_crop(image, {'offset': {'x': 'ugabuga'}})
  115. with self.assertRaises(ValidationError):
  116. uploaded.clean_crop(image, {
  117. 'offset': {
  118. 'x': 0,
  119. 'y': 0,
  120. },
  121. 'zoom': -2
  122. })
  123. with self.assertRaises(ValidationError):
  124. uploaded.clean_crop(image, {
  125. 'offset': {
  126. 'x': 0,
  127. 'y': 0,
  128. },
  129. 'zoom': 2
  130. })
  131. def test_uploaded_image_size_validation(self):
  132. """uploaded image size is validated"""
  133. image = MockAvatarFile(size=settings.avatar_upload_limit * 2024)
  134. with self.assertRaises(ValidationError):
  135. uploaded.validate_file_size(image)
  136. image = MockAvatarFile(size=settings.avatar_upload_limit * 1000)
  137. uploaded.validate_file_size(image)
  138. def test_uploaded_image_extension_validation(self):
  139. """uploaded image extension is validated"""
  140. for invalid_extension in ('.txt', '.zip', '.py', '.tiff'):
  141. with self.assertRaises(ValidationError):
  142. image = MockAvatarFile(name='test%s' % invalid_extension)
  143. uploaded.validate_extension(image)
  144. for valid_extension in uploaded.ALLOWED_EXTENSIONS:
  145. image = MockAvatarFile(name='test%s' % valid_extension)
  146. uploaded.validate_extension(image)
  147. def test_uploaded_image_mime_validation(self):
  148. """uploaded image mime type is validated"""
  149. image = MockAvatarFile(mime='fake/mime')
  150. with self.assertRaises(ValidationError):
  151. uploaded.validate_mime(image)
  152. for valid_mime in uploaded.ALLOWED_MIME_TYPES:
  153. image = MockAvatarFile(mime=valid_mime)
  154. uploaded.validate_mime(image)