Repository: dotkom/onlineweb4

Issue:
Cannot save user profile with an empty zip code
## What kind of an issue is this?

- [x] Bug report

## What is the expected behaviour?

That you can save the form and receive guidance without having to input a ZIP code.

## What is the current behaviour?

If you don't have a ZIP code in the field the form doesn't validate and you get a runtime error, which doesn't tell the user why it didn't work.

## How do you reproduce this problem? 

Go to my profile, empty the ZIP code field and save.


Discussion:

Resolving patch:
diff --git a/apps/authentication/templatetags/gravatar_url_resolver.py b/apps/authentication/templatetags/gravatar_url_resolver.py
--- a/apps/authentication/templatetags/gravatar_url_resolver.py
+++ b/apps/authentication/templatetags/gravatar_url_resolver.py
@@ -12,7 +12,7 @@ def gravatar_url(context, user, size):
     prefix = "https://" if context['request'].is_secure() else "http://"
     default = "%s%s%s_%s.png" % (
         prefix,
-        context['request'].META['HTTP_HOST'],
+        context['request'].META.get('HTTP_HOST', 'localhost'),
         settings.DEFAULT_PROFILE_PICTURE_PREFIX,
         user.gender
     )
diff --git a/apps/profiles/forms.py b/apps/profiles/forms.py
--- a/apps/profiles/forms.py
+++ b/apps/profiles/forms.py
@@ -8,6 +8,8 @@
 from apps.authentication.models import OnlineUser, Position
 from apps.profiles.models import Privacy
 
+ZIP_CODE_VALIDATION_ERROR = "Postnummer må bestå av fire siffer."
+
 
 class ProfileForm(forms.ModelForm):
     class Meta(object):
@@ -33,17 +35,10 @@ class Meta(object):
             'compiled': forms.CheckboxInput(attrs={'id': 'compiled'}),
         }
 
-    def clean(self):
-        super(ProfileForm, self).clean()
-
-        cleaned_data = self.cleaned_data
-
-        # ZIP code digits only
-        zip_code = cleaned_data['zip_code']
-        if len(zip_code) != 0 and not re.match(r'\d{4}', zip_code):
-            self._errors['zip_code'] = self.error_class([_("Postnummer må bestå av fire siffer.")])
-
-        return cleaned_data
+    def clean_zip_code(self):
+        zip_code = self.cleaned_data['zip_code']
+        if zip_code and len(zip_code) != 0 and not re.match(r'\d{4}', zip_code):
+            self.add_error('zip_code', ZIP_CODE_VALIDATION_ERROR)
 
 
 class PrivacyForm(forms.ModelForm):


Test patch:
diff --git a/apps/profiles/tests.py b/apps/profiles/tests.py
--- a/apps/profiles/tests.py
+++ b/apps/profiles/tests.py
@@ -1,15 +1,10 @@
-"""
-This file demonstrates writing tests using the unittest module. These will pass
-when you run "manage.py test".
-
-Replace this with more appropriate tests for your application.
-"""
 from django.core.urlresolvers import reverse
 from django.test import TestCase
 from django_dynamic_fixture import G
 from rest_framework import status
 
 from apps.authentication.models import OnlineUser as User
+from apps.profiles.forms import ZIP_CODE_VALIDATION_ERROR, ProfileForm
 
 
 class ProfilesURLTestCase(TestCase):
@@ -22,3 +17,62 @@ def test_user_search(self):
         response = self.client.get(url)
 
         self.assertEqual(response.status_code, status.HTTP_200_OK)
+
+
+class ProfileViewEditTestCase(TestCase):
+    @classmethod
+    def setUpClass(cls):
+        super().setUpClass()
+        cls._url = reverse('profile_edit')
+        cls._user = G(User)
+
+    def setUp(self):
+        self.client.force_login(self._user)
+
+    def test_profile_retrieve(self):
+        response = self.client.get(self._url)
+
+        self.assertEqual(200, response.status_code)
+
+    def test_profile_save(self):
+        response = self.client.post(self._url)
+
+        self.assertEqual(200, response.status_code)
+
+    def test_profile_save_valid_zip(self):
+        data = {
+            'zip_code': 7030
+        }
+
+        response = self.client.post(self._url, data)
+
+        self.assertEqual(200, response.status_code)
+
+    def test_profile_save_invalid_zip(self):
+        data = {
+            'zip_code': 123
+        }
+
+        response = self.client.post(self._url, data)
+
+        self.assertFormError(response, 'user_profile_form', 'zip_code', ZIP_CODE_VALIDATION_ERROR)
+
+
+class ProfileEditFormTestCase(TestCase):
+    def test_profile_form_valid_zip(self):
+        data = {
+            'gender': 'male',
+            'zip_code': 7030
+        }
+        form = ProfileForm(data=data)
+
+        self.assertTrue(form.is_valid())
+
+    def test_profile_form_invalid_zip(self):
+        data = {
+            'gender': 'male',
+            'zip_code': 123
+        }
+        form = ProfileForm(data=data)
+
+        self.assertFalse(form.is_valid())