blob: dbb7dee916672b8fd106fdc098eff8a63c1c911e [file] [log] [blame]
# Copyright 2014 the Melange authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Unit tests for user profile related views."""
import collections
import datetime
import httplib
import mock
import unittest
from google.appengine.ext import ndb
from django import forms as django_forms
from melange.request import exception
from melange.views import profile as profile_view
from seeder import profile as profile_seeder
from seeder import program as program_seeder
from seeder import sponsor as sponsor_seeder
from seeder import user as user_seeder
from soc.logic import validate
from soc.views.helper import request_data
from tests import org_utils
from tests import profile_utils
TEST_BIRTH_DATE = datetime.date(1993, 1, 1)
class CleanShippingAddressPartTest(unittest.TestCase):
"""Unit tests for _cleanShippingAddressPart function."""
def testShippingAddressIsNotDifferent(self):
"""Tests that only no value is accepted if address is not different."""
# Empty or None values are accepted even when a field is required.
result = profile_view._cleanShippingAddressPart(False, '', True)
self.assertEqual(result, '')
result = profile_view._cleanShippingAddressPart(False, None, True)
self.assertIsNone(result)
# Empty or None values are accepted when a field is not required.
result = profile_view._cleanShippingAddressPart(False, '', False)
self.assertEqual(result, '')
result = profile_view._cleanShippingAddressPart(False, None, False)
self.assertIsNone(result)
# Actual values are not accepted no matter if a field is required or not
with self.assertRaises(django_forms.ValidationError):
profile_view._cleanShippingAddressPart(False, 'a value', True)
with self.assertRaises(django_forms.ValidationError):
profile_view._cleanShippingAddressPart(False, 'a value', False)
def testShippingAddressIsDifferent(self):
"""Tests that values are cleaned and returned if address is different."""
# Empty or None values are accepted for non-required fields
result = profile_view._cleanShippingAddressPart(True, '', False)
self.assertEqual(result, '')
result = profile_view._cleanShippingAddressPart(True, None, False)
self.assertIsNone(result)
# Empty or None values are not accepted for required fields
with self.assertRaises(django_forms.ValidationError):
profile_view._cleanShippingAddressPart(True, '', True)
with self.assertRaises(django_forms.ValidationError):
profile_view._cleanShippingAddressPart(True, None, True)
# Actual values is returned upon clearing
result = profile_view._cleanShippingAddressPart(True, 'a value', False)
self.assertEqual(result, 'a value')
def testInvalidAddressCharacters(self):
"""Tests that invalid characters are not accepted."""
# Empty or None values are not accepted for required fields
with self.assertRaises(django_forms.ValidationError):
profile_view._cleanShippingAddressPart(True, '!N^al!D', True)
class CleanBirthDateTest(unittest.TestCase):
"""Unit tests for cleanBirthDate function."""
@mock.patch.object(
validate, 'isAgeSufficientForStudent', return_value=True)
@mock.patch.object(
validate, 'isAgeSufficientForOrgMember', return_value=False)
def testForStudentEligibleBirthDate(self, mock_func1, mock_func2):
"""Tests that an eligible birth date for student is cleaned properly."""
program = program_seeder.seedGSoCProgram()
result = profile_view.cleanBirthDate(TEST_BIRTH_DATE, program, True)
self.assertEqual(result, TEST_BIRTH_DATE)
@mock.patch.object(
validate, 'isAgeSufficientForStudent', return_value=False)
@mock.patch.object(
validate, 'isAgeSufficientForOrgMember', return_value=True)
def testForStudentIneligibleBirthDate(self, mock_func1, mock_func2):
"""Tests that an error is raised for an ineligible student birth date."""
program = program_seeder.seedProgram()
with self.assertRaises(django_forms.ValidationError):
profile_view.cleanBirthDate(TEST_BIRTH_DATE, program, True)
@mock.patch.object(
validate, 'isAgeSufficientForStudent', return_value=False)
@mock.patch.object(
validate, 'isAgeSufficientForOrgMember', return_value=True)
def testForOrgMemeberEligibleBirthDate(self, mock_func1, mock_func2):
"""Tests that an eligible birth date for org member is cleaned properly."""
program = program_seeder.seedProgram()
result = profile_view.cleanBirthDate(TEST_BIRTH_DATE, program, False)
self.assertEqual(result, TEST_BIRTH_DATE)
@mock.patch.object(
validate, 'isAgeSufficientForStudent', return_value=True)
@mock.patch.object(
validate, 'isAgeSufficientForOrgMember', return_value=False)
def testForOrgMemberIneligibleBirthDate(self, mock_func1, mock_func2):
"""Tests that an error is raised for an ineligible org member birth date."""
program = program_seeder.seedProgram()
with self.assertRaises(django_forms.ValidationError):
profile_view.cleanBirthDate(TEST_BIRTH_DATE, program, False)
TEST_TOS_KEY = ndb.Key('Document', 'tos_key')
TEST_TOS_COUNT = 4
class AdaptAcceptedTosForDatastoreTest(unittest.TestCase):
"""Unit tests for _adaptAcceptedTosForDatastore function."""
def setUp(self):
"""See unittest.TestCase.setUp for specification."""
self.form_data = {'terms_of_service': TEST_TOS_KEY}
# current list of ToS contains some other keys
self.current_tos = [
(ndb.Key('Document', 'tos_key_%s' % i) for i in range(TEST_TOS_COUNT))]
def testForNonExistingKey(self):
"""Tests that a non existing ToS key lands in the list."""
# check form data without current ToS
accepted_tos = profile_view._adaptAcceptedTosForDatastore(self.form_data)
self.assertListEqual([TEST_TOS_KEY], accepted_tos)
# check form data with current ToS
accepted_tos = profile_view._adaptAcceptedTosForDatastore(
self.form_data, current_tos=self.current_tos)
self.assertSetEqual(
set(self.current_tos + [TEST_TOS_KEY]), set(accepted_tos))
def testForExistingKey(self):
"""Tests that the existing ToS key is not repeated."""
# check that the key is not repeated if current ToS has already that key
accepted_tos = profile_view._adaptAcceptedTosForDatastore(
self.form_data, current_tos=[TEST_TOS_KEY])
self.assertListEqual([TEST_TOS_KEY], accepted_tos)
# check that they key is not repeated even if the current ToS has more keys
self.current_tos.insert(len(self.current_tos) / 2, TEST_TOS_KEY)
accepted_tos = profile_view._adaptAcceptedTosForDatastore(
self.form_data, current_tos=self.current_tos)
counter = collections.Counter(accepted_tos)
self.assertEquals(1, counter[TEST_TOS_KEY])
class AgeNotSetAccessCheckerTest(unittest.TestCase):
"""Unit tests for AgeNotSetAccessChecker class."""
def setUp(self):
"""See unittest.setUp for specification."""
sponsor = sponsor_seeder.seedSponsor()
self.program = program_seeder.seedProgram(sponsor_key=sponsor.key())
kwargs = {
'sponsor': sponsor.key().name(),
'program': self.program.link_id,
}
self.data = request_data.RequestData(None, None, kwargs)
def testProfileWithBirthDateOrAgeAccessDenied(self):
"""Tests that access is denied for a profile with age or birth date."""
# seed a profile with both birth date and age
user = user_seeder.seedUser()
profile_utils.loginNDB(user)
profile = profile_seeder.seedProfile(self.program.key(), user=user)
access_checker = profile_view.AgeNotSetAccessChecker()
with self.assertRaises(exception.UserError) as context:
access_checker.checkAccess(self.data, None)
self.assertEqual(context.exception.status, httplib.FORBIDDEN)
# profile has no age
profile.age = None
profile.put()
with self.assertRaises(exception.UserError) as context:
access_checker.checkAccess(self.data, None)
self.assertEqual(context.exception.status, httplib.FORBIDDEN)
# profile has no birth date
profile.age = 17
profile.birth_date = None
profile.put()
with self.assertRaises(exception.UserError) as context:
access_checker.checkAccess(self.data, None)
self.assertEqual(context.exception.status, httplib.FORBIDDEN)
def testProfileWithoutBirthDateOrAgeAccessGranted(self):
"""Tests that access is granted to a profile without birth date and age."""
# seed a profile without birth date or age
user = user_seeder.seedUser()
profile_utils.loginNDB(user)
profile = profile_seeder.seedProfile(self.program.key(), user=user)
profile.age = None
profile.birth_date = None
profile.put()
access_checker = profile_view.AgeNotSetAccessChecker()
access_checker.checkAccess(self.data, None)
class IsEligibleToRegisterAsStudentTest(unittest.TestCase):
"""Unit tests for IsEligibleToRegisterAsStudent class."""
class HasNoRoleAccessCheckerTest(unittest.TestCase):
"""Unit tests for HasNoRoleAccessChecker class."""
def setUp(self):
"""See unittest.TestCase.setUp for specification."""
self.sponsor = sponsor_seeder.seedSponsor()
self.program = program_seeder.seedProgram(sponsor_key=self.sponsor.key())
kwargs = {
'sponsor': self.sponsor.key().name(),
'program': self.program.program_id
}
self.data = request_data.RequestData(None, None, kwargs)
def testUserWithNoProfileAccessGranted(self):
"""Tests that access is granted for a user with no profile."""
user = user_seeder.seedUser()
profile_utils.loginNDB(user)
access_checker = profile_view.IsEligibleToRegisterAsStudent()
access_checker.checkAccess(self.data, None)
def testUserWithProfileWithNoRoleAccessGranted(self):
"""Tests that access is granted for a user with a profile with no role."""
user = user_seeder.seedUser()
profile_utils.loginNDB(user)
profile_seeder.seedProfile(self.program.key(), user=user)
access_checker = profile_view.IsEligibleToRegisterAsStudent()
access_checker.checkAccess(self.data, None)
def testUserWithProfileWithRoleAccessDenied(self):
"""Tests that access is denied for a user with a profile with a role."""
org = org_utils.seedOrganization(self.program.key())
user = user_seeder.seedUser()
profile_utils.loginNDB(user)
profile_seeder.seedProfile(
self.program.key(), user=user, mentor_for=[org.key])
access_checker = profile_view.IsEligibleToRegisterAsStudent()
with self.assertRaises(exception.UserError) as context:
access_checker.checkAccess(self.data, None)
self.assertEqual(context.exception.status, httplib.FORBIDDEN)
def testUserWithStudentProfileAccessDenied(self):
"""Tests that access is denied for a user with student profile."""
user = user_seeder.seedUser()
profile_utils.loginNDB(user)
profile_seeder.seedStudent(self.program, user=user)
access_checker = profile_view.IsEligibleToRegisterAsStudent()
with self.assertRaises(exception.UserError) as context:
access_checker.checkAccess(self.data, None)
self.assertEqual(context.exception.status, httplib.FORBIDDEN)