Merge branch 'devel' into tools

This commit is contained in:
Oliver Falk
2018-07-03 07:15:01 +02:00
6 changed files with 217 additions and 76 deletions

View File

@@ -87,11 +87,11 @@ BOOTSTRAP4 = {
} }
if not 'test' in sys.argv and not 'collectstatic' in sys.argv: if not 'test' in sys.argv and not 'collectstatic' in sys.argv:
ANYMAIL = { ANYMAIL = { # pragma: no cover
'MAILGUN_API_KEY': os.environ['IVATAR_MAILGUN_API_KEY'], 'MAILGUN_API_KEY': os.environ['IVATAR_MAILGUN_API_KEY'],
'MAILGUN_SENDER_DOMAIN': os.environ['IVATAR_MAILGUN_SENDER_DOMAIN'], 'MAILGUN_SENDER_DOMAIN': os.environ['IVATAR_MAILGUN_SENDER_DOMAIN'],
} }
EMAIL_BACKEND = 'anymail.backends.mailgun.EmailBackend' EMAIL_BACKEND = 'anymail.backends.mailgun.EmailBackend' # pragma: no cover
DEFAULT_FROM_EMAIL = 'ivatar@linux-kernel.at' DEFAULT_FROM_EMAIL = 'ivatar@linux-kernel.at'
try: try:
@@ -99,13 +99,13 @@ try:
except Exception: # pragma: no cover except Exception: # pragma: no cover
DATABASES = [] # pragma: no cover DATABASES = [] # pragma: no cover
if not 'default' in DATABASES: if not 'default' in DATABASES:
DATABASES['default'] = { DATABASES['default'] = { # pragma: no cover
'ENGINE': 'django.db.backends.sqlite3', 'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
} }
if 'MYSQL_DATABASE' in os.environ: if 'MYSQL_DATABASE' in os.environ:
DATABASES['default'] = { DATABASES['default'] = { # pragma: no cover
'ENGINE': 'django.db.backends.mysql', 'ENGINE': 'django.db.backends.mysql',
'NAME': os.environ['MYSQL_DATABASE'], 'NAME': os.environ['MYSQL_DATABASE'],
'USER': os.environ['MYSQL_USER'], 'USER': os.environ['MYSQL_USER'],

View File

@@ -3,8 +3,7 @@ Default: useful variables for the base page templates.
''' '''
from ipware import get_client_ip from ipware import get_client_ip
from ivatar.settings import IVATAR_VERSION, SITE_NAME from ivatar.settings import IVATAR_VERSION, SITE_NAME, MAX_PHOTO_SIZE
def basepage(request): def basepage(request):
''' '''
@@ -20,4 +19,5 @@ def basepage(request):
context['ivatar_version'] = IVATAR_VERSION context['ivatar_version'] = IVATAR_VERSION
context['site_name'] = SITE_NAME context['site_name'] = SITE_NAME
context['site_url'] = request.build_absolute_uri('/')[:-1] context['site_url'] = request.build_absolute_uri('/')[:-1]
context['max_file_size'] = MAX_PHOTO_SIZE
return context return context

View File

@@ -0,0 +1,39 @@
# Generated by Django 2.0.6 on 2018-06-27 06:24
from django.db import migrations, models
import django.db.models.deletion
def add_sha256(apps, schema_editor):
'''
Make sure all ConfirmedEmail have digest_sha256 set
in order to alter the model so sha256 may not be NULL
'''
ConfirmedEmail = apps.get_model('ivataraccount', 'ConfirmedEmail')
for mail in ConfirmedEmail.objects.filter(digest_sha256=None):
mail.save() # pragma: no cover
class Migration(migrations.Migration):
dependencies = [
('ivataraccount', '0006_auto_20180626_1445'),
]
operations = [
migrations.RunPython(add_sha256),
migrations.AlterField(
model_name='confirmedemail',
name='digest_sha256',
field=models.CharField(max_length=64),
),
migrations.AlterField(
model_name='confirmedemail',
name='photo',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='emails', to='ivataraccount.Photo'),
),
migrations.AlterField(
model_name='confirmedopenid',
name='photo',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='openids', to='ivataraccount.Photo'),
),
]

View File

@@ -171,7 +171,7 @@ class Photo(BaseAccountModel):
email.save() email.save()
if openid: if openid:
# Explicitely asked # Explicitly asked
openid.photo = self openid.photo = self
openid.save() openid.save()
@@ -257,10 +257,10 @@ class ConfirmedEmail(BaseAccountModel):
related_name='emails', related_name='emails',
blank=True, blank=True,
null=True, null=True,
on_delete=models.deletion.CASCADE, on_delete=models.deletion.SET_NULL,
) )
digest = models.CharField(max_length=32) digest = models.CharField(max_length=32)
digest_sha256 = models.CharField(max_length=64, null=True) digest_sha256 = models.CharField(max_length=64)
objects = ConfirmedEmailManager() objects = ConfirmedEmailManager()
class Meta: # pylint: disable=too-few-public-methods class Meta: # pylint: disable=too-few-public-methods
@@ -336,7 +336,7 @@ class ConfirmedOpenId(BaseAccountModel):
related_name='openids', related_name='openids',
blank=True, blank=True,
null=True, null=True,
on_delete=models.deletion.CASCADE, on_delete=models.deletion.SET_NULL,
) )
digest = models.CharField(max_length=64) digest = models.CharField(max_length=64)

View File

@@ -1,26 +1,37 @@
from django.test import TestCase '''
from django.test import Client Test our views in ivatar.ivataraccount.views and ivatar.views
from django.urls import reverse '''
# pylint: disable=too-many-lines
from libravatar import libravatar_url
from urllib.parse import urlsplit from urllib.parse import urlsplit
from io import BytesIO
import io import io
import os import os
import django import django
from django.test import TestCase
from django.test import Client
from django.urls import reverse
from django.contrib.auth.models import User
from django.contrib.auth import authenticate
from libravatar import libravatar_url
from PIL import Image
os.environ['DJANGO_SETTINGS_MODULE'] = 'ivatar.settings' os.environ['DJANGO_SETTINGS_MODULE'] = 'ivatar.settings'
django.setup() django.setup()
from ivatar import settings # noqa # pylint: disable=wrong-import-position
from ivatar.ivataraccount.forms import MAX_NUM_UNCONFIRMED_EMAILS_DEFAULT # noqa from ivatar import settings
from ivatar.ivataraccount.forms import MAX_NUM_UNCONFIRMED_EMAILS_DEFAULT
from django.contrib.auth.models import User # noqa from ivatar.ivataraccount.models import Photo, ConfirmedOpenId
from django.contrib.auth import authenticate # noqa from ivatar.utils import random_string
from ivatar.utils import random_string # noqa # pylint: enable=wrong-import-position
from ivatar.ivataraccount.models import Photo, ConfirmedOpenId # noqa
class Tester(TestCase): class Tester(TestCase): # pylint: disable=too-many-public-methods
'''
Main test class
'''
client = Client() client = Client()
user = None user = None
username = random_string() username = random_string()
@@ -170,7 +181,7 @@ class Tester(TestCase):
self.user.confirmedemail_set.count(), 1, self.user.confirmedemail_set.count(), 1,
'there must not be more or less than ONE (1) confirmed address!') 'there must not be more or less than ONE (1) confirmed address!')
def test_confirm_email_w_invalid_auth_key(self): def test_confirm_email_w_invalid_auth_key(self): # pylint: disable=invalid-name
''' '''
Test confirmation with invalid auth key Test confirmation with invalid auth key
''' '''
@@ -193,7 +204,7 @@ class Tester(TestCase):
'Verification key incorrect', 'Verification key incorrect',
'Confirm w/o verification key does not produce error message?') 'Confirm w/o verification key does not produce error message?')
def test_confirm_email_w_inexisting_auth_key(self): def test_confirm_email_w_inexisting_auth_key(self): # pylint: disable=invalid-name
''' '''
Test confirmation with inexisting auth key Test confirmation with inexisting auth key
''' '''
@@ -246,7 +257,7 @@ class Tester(TestCase):
'Address removed', 'Address removed',
'Removing confirmed mail does not work?') 'Removing confirmed mail does not work?')
def test_remove_not_existing_confirmed_email(self): def test_remove_not_existing_confirmed_email(self): # pylint: disable=invalid-name
''' '''
Try removing confirmed mail that doesn't exist Try removing confirmed mail that doesn't exist
''' '''
@@ -310,7 +321,8 @@ class Tester(TestCase):
url = reverse( url = reverse(
'import_photo', 'import_photo',
args=[self.user.confirmedemail_set.first().id]) args=[self.user.confirmedemail_set.first().id])
response = self.client.post(url, { response = self.client.post(
url, {
'photo_Gravatar': 1, 'photo_Gravatar': 1,
}, },
follow=True follow=True
@@ -340,7 +352,7 @@ class Tester(TestCase):
self.assertEqual(response.status_code, 200, 'cannot fetch photo?') self.assertEqual(response.status_code, 200, 'cannot fetch photo?')
# Probably not the best way to access the content type # Probably not the best way to access the content type
self.assertEqual( self.assertEqual(
response._headers['content-type'][1], response['Content-Type'],
'image/jpg', 'image/jpg',
'Content type wrong!?') 'Content type wrong!?')
@@ -428,10 +440,13 @@ class Tester(TestCase):
}, },
follow=True follow=True
) )
self.assertFormError(response, 'form', 'email', self.assertFormError(
response,
'form',
'email',
'Address already added, currently unconfirmed') 'Address already added, currently unconfirmed')
def test_add_already_confirmed_email(self): def test_add_already_confirmed_email(self): # pylint: disable=invalid-name
''' '''
Request adding mail address that is already confirmed (by someone) Request adding mail address that is already confirmed (by someone)
''' '''
@@ -445,10 +460,13 @@ class Tester(TestCase):
}, },
follow=True, follow=True,
) )
self.assertFormError(response, 'form', 'email', self.assertFormError(
response,
'form',
'email',
'Address already confirmed (by someone else)') 'Address already confirmed (by someone else)')
def test_remove_unconfirmed_non_existing_email(self): def test_remove_unconfirmed_non_existing_email(self): # pylint: disable=invalid-name
''' '''
Remove unconfirmed email that doesn't exist Remove unconfirmed email that doesn't exist
''' '''
@@ -464,15 +482,19 @@ class Tester(TestCase):
'Address does not exist', 'Removing address that does not\ 'Address does not exist', 'Removing address that does not\
exist, should return error message!') exist, should return error message!')
def test_upload_image(self, test_only_one=True): def test_upload_image(self, test_only_one=True): # pylint: disable=inconsistent-return-statements
''' '''
Test uploading image Test uploading image
''' '''
self.login() self.login()
url = reverse('upload_photo') url = reverse('upload_photo')
# rb => Read binary # rb => Read binary
with open(os.path.join( with open(
settings.STATIC_ROOT, 'img', 'deadbeef.png'), 'rb') as photo: os.path.join(
settings.STATIC_ROOT,
'img',
'deadbeef.png'),
'rb') as photo:
response = self.client.post(url, { response = self.client.post(url, {
'photo': photo, 'photo': photo,
'not_porn': True, 'not_porn': True,
@@ -542,15 +564,19 @@ class Tester(TestCase):
'Invalid Format', 'Invalid Format',
'Invalid img data should return error message!') 'Invalid img data should return error message!')
def test_upload_invalid_image_format(self): def test_upload_invalid_image_format(self): # pylint: disable=invalid-name
''' '''
Test if invalid format is correctly detected Test if invalid format is correctly detected
''' '''
self.login() self.login()
url = reverse('upload_photo') url = reverse('upload_photo')
# rb => Read binary # rb => Read binary
with open(os.path.join( with open(
settings.STATIC_ROOT, 'img', 'mm.svg'), 'rb') as photo: os.path.join(
settings.STATIC_ROOT,
'img',
'mm.svg'),
'rb') as photo:
response = self.client.post(url, { response = self.client.post(url, {
'photo': photo, 'photo': photo,
'not_porn': True, 'not_porn': True,
@@ -568,10 +594,12 @@ class Tester(TestCase):
self.login() self.login()
url = reverse('upload_photo') url = reverse('upload_photo')
# rb => Read binary # rb => Read binary
with open(os.path.join( with open(
os.path.join(
settings.STATIC_ROOT, settings.STATIC_ROOT,
'img', 'img',
'broken.gif'), 'rb') as photo: 'broken.gif'),
'rb') as photo:
response = self.client.post(url, { response = self.client.post(url, {
'photo': photo, 'photo': photo,
'not_porn': True, 'not_porn': True,
@@ -585,17 +613,19 @@ class Tester(TestCase):
self.user.photo_set.first().format, 'gif', self.user.photo_set.first().format, 'gif',
'Format must be gif, since we uploaded a GIF!') 'Format must be gif, since we uploaded a GIF!')
def test_upload_unsupported_tif_image(self): def test_upload_unsupported_tif_image(self): # pylint: disable=invalid-name
''' '''
Test if unsupported format is correctly detected Test if unsupported format is correctly detected
''' '''
self.login() self.login()
url = reverse('upload_photo') url = reverse('upload_photo')
# rb => Read binary # rb => Read binary
with open(os.path.join( with open(
os.path.join(
settings.STATIC_ROOT, settings.STATIC_ROOT,
'img', 'img',
'hackergotchi_test.tif'), 'rb') as photo: 'hackergotchi_test.tif'),
'rb') as photo:
response = self.client.post(url, { response = self.client.post(url, {
'photo': photo, 'photo': photo,
'not_porn': True, 'not_porn': True,
@@ -606,13 +636,19 @@ class Tester(TestCase):
'Invalid Format', 'Invalid Format',
'Invalid img data should return error message!') 'Invalid img data should return error message!')
def test_automatic_photo_assign_to_confirmed_mail(self): def test_automatic_photo_assign_to_confirmed_mail(self): # pylint: disable=invalid-name
'''
Test if automatic assignment of photo works
'''
self.test_upload_image() self.test_upload_image()
self.test_confirm_email() self.test_confirm_email()
confirmed = self.user.confirmedemail_set.first() confirmed = self.user.confirmedemail_set.first()
self.assertEqual(confirmed.photo, self.user.photo_set.first()) self.assertEqual(confirmed.photo, self.user.photo_set.first())
def test_assign_photo_to_email(self): def test_assign_photo_to_email(self):
'''
Test assigning photo to mail address
'''
self.test_confirm_email() self.test_confirm_email()
self.test_upload_image() self.test_upload_image()
self.assertIsNone(self.user.confirmedemail_set.first().photo) self.assertIsNone(self.user.confirmedemail_set.first().photo)
@@ -632,7 +668,10 @@ class Tester(TestCase):
self.user.confirmedemail_set.first().photo, self.user.confirmedemail_set.first().photo,
self.user.photo_set.first()) self.user.photo_set.first())
def test_assign_photo_to_email_wo_photo_for_testing_template(self): def test_assign_photo_to_email_wo_photo_for_testing_template(self): # pylint: disable=invalid-name
'''
Test assign photo template
'''
self.test_confirm_email() self.test_confirm_email()
url = reverse( url = reverse(
'assign_photo_email', 'assign_photo_email',
@@ -641,7 +680,10 @@ class Tester(TestCase):
response = self.client.get(url) response = self.client.get(url)
self.assertEqual(response.status_code, 200, 'cannot fetch page?') self.assertEqual(response.status_code, 200, 'cannot fetch page?')
def test_assign_invalid_photo_id_to_email(self): def test_assign_invalid_photo_id_to_email(self): # pylint: disable=invalid-name
'''
Test if assigning an invalid photo id returns the correct error message
'''
self.test_confirm_email() self.test_confirm_email()
self.test_upload_image() self.test_upload_image()
self.assertIsNone(self.user.confirmedemail_set.first().photo) self.assertIsNone(self.user.confirmedemail_set.first().photo)
@@ -659,7 +701,10 @@ class Tester(TestCase):
'Photo does not exist', 'Photo does not exist',
'Assign non existing photo, does not return error message?') 'Assign non existing photo, does not return error message?')
def test_post_to_assign_photo_without_photo_id(self): def test_post_to_assign_photo_without_photo_id(self): # pylint: disable=invalid-name
'''
Test if assigning photo without id returns the correct error message
'''
self.test_confirm_email() self.test_confirm_email()
self.test_upload_image() self.test_upload_image()
self.assertIsNone(self.user.confirmedemail_set.first().photo) self.assertIsNone(self.user.confirmedemail_set.first().photo)
@@ -675,7 +720,11 @@ class Tester(TestCase):
'Invalid request [photo_id] missing', 'Invalid request [photo_id] missing',
'Assign non existing photo, does not return error message?') 'Assign non existing photo, does not return error message?')
def test_assign_photo_to_inexisting_mail(self): def test_assign_photo_to_inexisting_mail(self): # pylint: disable=invalid-name
'''
Test if assigning photo to mail address that doesn't exist returns
the correct error message
'''
self.test_upload_image() self.test_upload_image()
url = reverse('assign_photo_email', args=[1234]) url = reverse('assign_photo_email', args=[1234])
response = self.client.post(url, { response = self.client.post(url, {
@@ -689,7 +738,11 @@ class Tester(TestCase):
'Invalid request', 'Invalid request',
'Assign non existing photo, does not return error message?') 'Assign non existing photo, does not return error message?')
def test_import_photo_with_inexisting_email(self): def test_import_photo_with_inexisting_email(self): # pylint: disable=invalid-name
'''
Test if import with inexisting mail address returns
the correct error message
'''
self.login() self.login()
url = reverse('import_photo', args=[1234]) url = reverse('import_photo', args=[1234])
response = self.client.post(url, {}, follow=True) response = self.client.post(url, {}, follow=True)
@@ -703,6 +756,10 @@ class Tester(TestCase):
does not return error message?') does not return error message?')
def test_import_nothing(self): def test_import_nothing(self):
'''
Test if importing nothing causes the correct
error message to be returned
'''
self.test_confirm_email() self.test_confirm_email()
url = reverse( url = reverse(
'import_photo', 'import_photo',
@@ -732,7 +789,6 @@ class Tester(TestCase):
response = self.client.post( response = self.client.post(
reverse('add_openid'), { reverse('add_openid'), {
# Whohu, static... :-[
'openid': self.openid, 'openid': self.openid,
}, },
) )
@@ -762,7 +818,6 @@ class Tester(TestCase):
response = self.client.post( response = self.client.post(
reverse('add_openid'), { reverse('add_openid'), {
# Whohu, static... :-[
'openid': self.openid, 'openid': self.openid,
}, },
) )
@@ -770,7 +825,6 @@ class Tester(TestCase):
response = self.client.post( response = self.client.post(
reverse('add_openid'), { reverse('add_openid'), {
# Whohu, static... :-[
'openid': self.openid, 'openid': self.openid,
}, },
follow=True, follow=True,
@@ -779,8 +833,11 @@ class Tester(TestCase):
self.user.unconfirmedopenid_set.count(), self.user.unconfirmedopenid_set.count(),
1, 'There must only be one unconfirmed ID!') 1, 'There must only be one unconfirmed ID!')
self.assertFormError(response, 'form', 'openid', self.assertFormError(
'OpenID already added, but not confirmed yet!') response,
'form',
'openid',
'OpenID already added, but not confirmed yet!')
# Manual confirm, since testing is _really_ hard! # Manual confirm, since testing is _really_ hard!
unconfirmed = self.user.unconfirmedopenid_set.first() unconfirmed = self.user.unconfirmedopenid_set.first()
@@ -794,16 +851,21 @@ class Tester(TestCase):
# Try adding it again - although already confirmed # Try adding it again - although already confirmed
response = self.client.post( response = self.client.post(
reverse('add_openid'), { reverse('add_openid'), {
# Whohu, static... :-[
'openid': self.openid, 'openid': self.openid,
}, },
follow=True, follow=True,
) )
self.assertFormError(response, 'form', 'openid', self.assertFormError(
'OpenID already added and confirmed!') response,
'form',
'openid',
'OpenID already added and confirmed!')
def test_assign_photo_to_openid(self): def test_assign_photo_to_openid(self):
'''
Test assignment of photo to openid
'''
self.test_add_openid() self.test_add_openid()
self.test_upload_image() self.test_upload_image()
self.assertIsNone(self.user.confirmedopenid_set.first().photo) self.assertIsNone(self.user.confirmedopenid_set.first().photo)
@@ -823,7 +885,10 @@ class Tester(TestCase):
self.user.confirmedopenid_set.first().photo, self.user.confirmedopenid_set.first().photo,
self.user.photo_set.first()) self.user.photo_set.first())
def test_assign_photo_to_openid_wo_photo_for_testing_template(self): def test_assign_photo_to_openid_wo_photo_for_testing_template(self): # pylint: disable=invalid-name
'''
Test openid/photo assignment template
'''
self.test_add_openid() self.test_add_openid()
url = reverse( url = reverse(
'assign_photo_openid', 'assign_photo_openid',
@@ -831,7 +896,11 @@ class Tester(TestCase):
response = self.client.get(url) response = self.client.get(url)
self.assertEqual(response.status_code, 200, 'cannot fetch page?') self.assertEqual(response.status_code, 200, 'cannot fetch page?')
def test_assign_invalid_photo_id_to_openid(self): def test_assign_invalid_photo_id_to_openid(self): # pylint: disable=invalid-name
'''
Test assigning invalid photo to openid returns
the correct error message
'''
self.test_add_openid() self.test_add_openid()
self.assertIsNone(self.user.confirmedopenid_set.first().photo) self.assertIsNone(self.user.confirmedopenid_set.first().photo)
url = reverse( url = reverse(
@@ -848,7 +917,11 @@ class Tester(TestCase):
'Photo does not exist', 'Photo does not exist',
'Assign non existing photo, does not return error message?') 'Assign non existing photo, does not return error message?')
def test_post_to_assign_photo_openid_without_photo_id(self): def test_post_to_assign_photo_openid_without_photo_id(self): # pylint: disable=invalid-name
'''
Test POST assign photo to openid without photo id
returns the correct error message
'''
self.test_add_openid() self.test_add_openid()
self.test_upload_image() self.test_upload_image()
self.assertIsNone(self.user.confirmedopenid_set.first().photo) self.assertIsNone(self.user.confirmedopenid_set.first().photo)
@@ -864,7 +937,11 @@ class Tester(TestCase):
'Invalid request [photo_id] missing', 'Invalid request [photo_id] missing',
'Assign non existing photo, does not return error message?') 'Assign non existing photo, does not return error message?')
def test_assign_photo_to_openid_inexisting_openid(self): def test_assign_photo_to_openid_inexisting_openid(self): # pylint: disable=invalid-name
'''
Test assigning photo to openid that doesn't exist
returns the correct error message.
'''
self.test_upload_image() self.test_upload_image()
url = reverse('assign_photo_openid', args=[1234]) url = reverse('assign_photo_openid', args=[1234])
response = self.client.post(url, { response = self.client.post(url, {
@@ -878,7 +955,7 @@ class Tester(TestCase):
'Invalid request', 'Invalid request',
'Assign non existing photo, does not return error message?') 'Assign non existing photo, does not return error message?')
def test_remove_confirmed_openid(self): def test_remove_confirmed_openid(self): # pylint: disable=invalid-name
''' '''
Remove confirmed openid Remove confirmed openid
''' '''
@@ -896,7 +973,7 @@ class Tester(TestCase):
'ID removed', 'ID removed',
'Removing confirmed openid does not work?') 'Removing confirmed openid does not work?')
def test_remove_not_existing_confirmed_openid(self): def test_remove_not_existing_confirmed_openid(self): # pylint: disable=invalid-name
''' '''
Try removing confirmed openid that doesn't exist Try removing confirmed openid that doesn't exist
''' '''
@@ -931,7 +1008,7 @@ class Tester(TestCase):
'ID removed', 'ID removed',
'Removing unconfirmed mail does not work?') 'Removing unconfirmed mail does not work?')
def test_remove_unconfirmed_inexisting_openid(self): def test_remove_unconfirmed_inexisting_openid(self): # pylint: disable=invalid-name
''' '''
Remove unconfirmed openid that doesn't exist Remove unconfirmed openid that doesn't exist
''' '''
@@ -983,14 +1060,16 @@ class Tester(TestCase):
self.user.photo_set.first(), self.user.photo_set.first(),
'set_photo did not work!?') 'set_photo did not work!?')
def test_avatar_url_mail(self): def test_avatar_url_mail(self, do_upload_and_confirm=True):
''' '''
Test fetching avatar via mail Test fetching avatar via mail
''' '''
self.test_upload_image() if do_upload_and_confirm:
self.test_confirm_email() self.test_upload_image()
urlobj = urlsplit(libravatar_url( self.test_confirm_email()
email=self.user.confirmedemail_set.first().email) urlobj = urlsplit(
libravatar_url(
email=self.user.confirmedemail_set.first().email)
) )
url = urlobj.path url = urlobj.path
response = self.client.get(url, follow=True) response = self.client.get(url, follow=True)
@@ -1008,8 +1087,9 @@ class Tester(TestCase):
Test fetching avatar via openid Test fetching avatar via openid
''' '''
self.test_assign_photo_to_openid() self.test_assign_photo_to_openid()
urlobj = urlsplit(libravatar_url( urlobj = urlsplit(
openid=self.user.confirmedopenid_set.first().openid) libravatar_url(
openid=self.user.confirmedopenid_set.first().openid)
) )
url = urlobj.path url = urlobj.path
response = self.client.get(url, follow=True) response = self.client.get(url, follow=True)
@@ -1022,14 +1102,15 @@ class Tester(TestCase):
self.user.photo_set.first().data, self.user.photo_set.first().data,
'Why is this not the same data?') 'Why is this not the same data?')
def test_avatar_url_inexisting_mail_digest(self): def test_avatar_url_inexisting_mail_digest(self): # pylint: disable=invalid-name
''' '''
Test fetching avatar via inexisting mail digest Test fetching avatar via inexisting mail digest
''' '''
self.test_upload_image() self.test_upload_image()
self.test_confirm_email() self.test_confirm_email()
urlobj = urlsplit(libravatar_url( urlobj = urlsplit(
email=self.user.confirmedemail_set.first().email) libravatar_url(
email=self.user.confirmedemail_set.first().email)
) )
# Simply delete it, then it digest is 'correct', but # Simply delete it, then it digest is 'correct', but
# the hash is no longer there # the hash is no longer there
@@ -1037,3 +1118,24 @@ class Tester(TestCase):
url = urlobj.path url = urlobj.path
self.assertRaises(Exception, lambda: self.assertRaises(Exception, lambda:
self.client.get(url, follow=True)) self.client.get(url, follow=True))
def test_crop_photo(self):
'''
Test cropping photo
'''
self.test_upload_image()
self.test_confirm_email()
url = reverse('crop_photo', args=[self.user.photo_set.first().pk])
response = self.client.post(url, {
'x': 10,
'y': 10,
'w': 20,
'h': 20,
}, follow=True)
self.assertEqual(
response.status_code,
200,
'unable to crop?')
self.test_avatar_url_mail(do_upload_and_confirm=False)
img = Image.open(BytesIO(self.user.photo_set.first().data))
self.assertEqual(img.size, (20, 20), 'cropped to 20x20, but resulting image isn\'t 20x20!?')

View File

@@ -22,7 +22,7 @@ class AvatarImageView(TemplateView):
# Fetch by digest from mail # Fetch by digest from mail
pass pass
elif len(kwargs['digest']) == 64: elif len(kwargs['digest']) == 64:
if model.objects.filter(digest=kwargs['digest']).count(): if ConfirmedOpenId.objects.filter(digest=kwargs['digest']).count(): # pylint: disable=no-member
# Fetch by digest from OpenID # Fetch by digest from OpenID
model = ConfirmedOpenId model = ConfirmedOpenId
else: # pragma: no cover else: # pragma: no cover