blob: b3b0507b5fb8f074f0d5b970e704d7ddd9e741d1 [file] [log] [blame]
# Copyright 2013 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 datetime
from google.appengine.ext import blobstore
from google.appengine.ext import ndb
from django.utils import html
from melange.models import address as address_model
from melange.models import education as education_model
from melange.models import profile as profile_model
from melange.models import signature as signature_model
from melange.models import user as user_model
from melange.views import profile as profile_view
from seeder import document as document_seeder
from seeder import profile as profile_seeder
from seeder import user as user_seeder
from soc.logic import validate
from soc.views import base
from summerofcode.templates import tabs
from tests import profile_utils
from tests import test_utils
from tests import timeline_utils
from tests.utils import project_utils
TEST_BIRTH_DATE = datetime.date(1993, 1, 1)
TEST_EMAIL = 'test@example.com'
TEST_FIRST_NAME = 'Test First'
TEST_GENDER = profile_view._GENDER_FEMALE_ID
TEST_LAST_NAME = 'Test Last'
TEST_PHONE = '1234567890'
TEST_PROGRAM_KNOWLEDGE = u'Test program knowledge'
TEST_PUBLIC_NAME = 'Test Public Name'
TEST_RESIDENTIAL_STREET = 'Test Street'
TEST_RESIDENTIAL_STREET_EXTRA = 'Test Street Extra'
TEST_RESIDENTIAL_CITY = 'Test City'
TEST_RESIDENTIAL_PROVINCE = 'CA'
TEST_RESIDENTIAL_POSTAL_CODE = '90000'
TEST_RESIDENTIAL_COUNTRY = 'United States'
TEST_SHIPPING_NAME = 'Test Shipping Name'
TEST_SHIPPING_STREET = 'Test Shipping Street'
TEST_SHIPPING_STREET_EXTRA = 'Test Shipping Street Extra.'
TEST_SHIPPING_CITY = 'Test Shipping City'
TEST_SHIPPING_PROVINCE = 'DC'
TEST_SHIPPING_POSTAL_CODE = '20000'
TEST_SHIPPING_COUNTRY = 'United States'
TEST_TEE_SIZE = profile_view._TEE_SIZE_M_ID
TEST_TEE_STYLE = profile_view._TEE_STYLE_FEMALE_ID
TEST_USER_ID = 'test_user_id'
TEST_SCHOOL_COUNTRY = 'United States'
TEST_SCHOOL_NAME = 'Melange University'
TEST_SCHOOL_WEB_PAGE = u'http://www.test.school.com/'
TEST_MAJOR = 'Computer Science'
TEST_DEGREE = profile_view._DEGREE_MASTERS_ID
TEST_EXPECTED_GRADUATION = 2015
TEST_ENROLLMENT_FORM = blobstore.BlobKey('unused')
TEST_TAX_FORM = blobstore.BlobKey('unused')
OTHER_TEST_SHIPPING_NAME = 'Other Shipping Name'
OTHER_TEST_SHIPPING_STREET = 'Other Shipping Street'
OTHER_TEST_SHIPPING_STREET_EXTRA = 'Other Shipping Street Extra'
OTHER_TEST_SHIPPING_CITY = 'Other Shipping City'
OTHER_TEST_SHIPPING_PROVINCE = 'AL'
OTHER_TEST_SHIPPING_POSTAL_CODE = '35005'
OTHER_TEST_SHIPPING_COUNTRY = 'United States'
OTHER_TEST_SCHOOL_COUNTRY = 'United States'
OTHER_TEST_SCHOOL_NAME = 'Other School'
OTHER_TEST_MAJOR = 'Economics'
OTHER_TEST_DEGREE = profile_view._DEGREE_PHD_ID
OTHER_TEST_EXPECTED_GRADUATION = 2016
OTHER_TEST_SCHOOL_WEB_PAGE = u'http://www.other.school.web.page.com/'
def _getProfileRegisterAsOrgMemberUrl(program_key):
"""Returns URL to Register As Organization Member page.
Args:
program_key: Program key.
Returns:
A string containing the URL to Register As Organization Member page.
"""
return '/gsoc/profile/register/org_member/%s' % program_key.name()
def _getProfileRegisterAsStudentUrl(program_key, is_json=False):
"""Returns URL to Register As Student page.
Args:
program_key: Program key.
is_json: A bool telling whether it is JSON data request.
Returns:
A string containing the URL to Register As Student page.
"""
return '/gsoc/profile/register/student/%s%s' % (
program_key.name(), '?fmt=json' if is_json else '')
def _getEditProfileUrl(program_key, is_json=False, is_validated=False):
"""Returns URL to Edit Profile page.
Args:
program_key: Program key.
is_json: A bool telling whether it is JSON data request.
is_validated: A bool telling whether the URL indicates data validation.
Returns:
A string containing the URL to Edit Profile page.
"""
url = '/gsoc/profile/edit/%s' % program_key.name()
if is_json or is_validated:
url += '?'
if is_json:
url += 'fmt=json'
if is_validated:
url += 'validated=true'
return url
def _getShowProfileUrl(program_key, is_validated=False):
"""Returns URL to Show Profile page.
Args:
program_key: Program key.
is_validated: A bool telling whether the URL indicates data validation.
Returns:
A string containing the URL to Show Profile page.
"""
url = '/gsoc/profile/show/%s' % program_key.name()
if is_validated:
url += '?validated=true'
return url
def _getAdminProfileUrl(profile_key):
"""Returns URL to Admin Profile page.
Args:
profile_key: Profile key.
Returns:
A string containing the URL to Admin Profile page.
"""
return '/gsoc/profile/admin/%s' % profile_key.id()
class ProfileOrgMemberCreatePageTest(test_utils.GSoCDjangoTestCase):
"""Unit tests for ProfileOrgMemberCreatePage class."""
def setUp(self):
"""See unittest.TestCase.setUp for specification."""
self.init()
def testPageLoads(self):
"""Tests that page loads properly."""
response = self.get(_getProfileRegisterAsOrgMemberUrl(self.program.key()))
self.assertResponseOK(response)
def testProfileCreatedWhenNoUserExists(self):
"""Tests that profile entity is created correctly."""
# check that page loads properly
response = self.get(_getProfileRegisterAsOrgMemberUrl(self.program.key()))
self.assertResponseOK(response)
# check that username is present in the form
form = response.context['forms'][0]
self.assertIn('user_id', form.fields)
postdata = {
'user_id': TEST_USER_ID,
'public_name': TEST_PUBLIC_NAME,
'first_name': TEST_FIRST_NAME,
'last_name': TEST_LAST_NAME,
'email': TEST_EMAIL,
'phone': TEST_PHONE,
'residential_street': TEST_RESIDENTIAL_STREET,
'residential_city': TEST_RESIDENTIAL_CITY,
'residential_province': TEST_RESIDENTIAL_PROVINCE,
'residential_country': TEST_RESIDENTIAL_COUNTRY,
'residential_postal_code': TEST_RESIDENTIAL_POSTAL_CODE,
'birth_date': TEST_BIRTH_DATE.strftime('%Y-%m-%d'),
'tee_style': TEST_TEE_STYLE,
'tee_size': TEST_TEE_SIZE,
'gender': TEST_GENDER,
'program_knowledge': TEST_PROGRAM_KNOWLEDGE,
'terms_of_service': True,
}
response = self.post(
_getProfileRegisterAsOrgMemberUrl(self.program.key()),
postdata=postdata)
self.assertResponseRedirect(
response, url=_getShowProfileUrl(self.program.key(), is_validated=True))
# check that user entity has been created
user_key = ndb.Key(user_model.User._get_kind(), TEST_USER_ID)
user = user_key.get()
self.assertIsNotNone(user)
# check that profile entity has been created
profile_key = ndb.Key(
user_model.User._get_kind(), TEST_USER_ID,
profile_model.Profile._get_kind(),
'%s/%s' % (self.program.key().name(), TEST_USER_ID))
profile = profile_key.get()
self.assertIsNotNone(profile)
# check that Terms Of Service is signed and a signature is created
self.assertIn(
ndb.Key.from_old_key(self.program.mentor_agreement.key()),
profile.accepted_tos)
signature = signature_model.Signature.query(
signature_model.Signature.profile == profile_key,
signature_model.Signature.document ==
ndb.Key.from_old_key(self.program.mentor_agreement.key())).get()
self.assertIsNotNone(signature)
def testProfileCreatedWhenUserExists(self):
"""Tests that a profile is created for a person with user entity."""
# seed user entity
user = user_seeder.seedUser(TEST_USER_ID)
profile_utils.loginNDB(user)
# check that page loads properly
response = self.get(_getProfileRegisterAsOrgMemberUrl(self.program.key()))
self.assertResponseOK(response)
# check that username is not present in the form
form = response.context['forms'][0]
self.assertNotIn('username', form.fields)
# check POST request
postdata = {
'public_name': TEST_PUBLIC_NAME,
'first_name': TEST_FIRST_NAME,
'last_name': TEST_LAST_NAME,
'email': TEST_EMAIL,
'phone': TEST_PHONE,
'residential_street': TEST_RESIDENTIAL_STREET,
'residential_city': TEST_RESIDENTIAL_CITY,
'residential_province': TEST_RESIDENTIAL_PROVINCE,
'residential_country': TEST_RESIDENTIAL_COUNTRY,
'residential_postal_code': TEST_RESIDENTIAL_POSTAL_CODE,
'birth_date': TEST_BIRTH_DATE.strftime('%Y-%m-%d'),
'tee_style': TEST_TEE_STYLE,
'tee_size': TEST_TEE_SIZE,
'gender': TEST_GENDER,
'program_knowledge': TEST_PROGRAM_KNOWLEDGE,
'terms_of_service': True,
}
response = self.post(
_getProfileRegisterAsOrgMemberUrl(self.program.key()),
postdata=postdata)
self.assertResponseRedirect(
response, url=_getShowProfileUrl(self.program.key(), is_validated=True))
# check that profile entity has been created for the existing user
profile = profile_model.Profile.query(ancestor=user.key).get()
self.assertIsNotNone(profile)
self.assertEqual(
profile.key.id(), '%s/%s' % (self.program.key().name(), user.key.id()))
# check that Terms Of Service is signed and a signature is created
self.assertIn(
ndb.Key.from_old_key(self.program.mentor_agreement.key()),
profile.accepted_tos)
signature = signature_model.Signature.query(
signature_model.Signature.profile == profile.key,
signature_model.Signature.document ==
ndb.Key.from_old_key(self.program.mentor_agreement.key())).get()
self.assertIsNotNone(signature)
def testSanitization(self):
"""Tests that possible malicious content is sanitized properly."""
self.timeline_helper.orgsAnnounced()
xss_payload = '><img src=http://www.google.com/images/srpr/logo4w.png>'
postdata = {
'user_id': xss_payload,
'public_name': xss_payload,
'first_name': xss_payload,
'last_name': xss_payload,
'email': xss_payload,
'phone': xss_payload,
'residential_street': xss_payload,
'residential_city': xss_payload,
'residential_province': xss_payload,
'residential_country': xss_payload,
'residential_postal_code': xss_payload,
'birth_date': xss_payload,
'tee_style': xss_payload,
'tee_size': xss_payload,
'gender': xss_payload,
'program_knowledge': xss_payload,
}
response = self.post(
_getProfileRegisterAsOrgMemberUrl(self.program.key()),
postdata=postdata)
self.assertNotIn(xss_payload, response.content)
self.assertIn(html.escape(xss_payload), response.content)
class ProfileRegisterAsStudentPageTest(test_utils.GSoCDjangoTestCase):
"""Unit tests for ProfileRegisterAsStudentPage class."""
def setUp(self):
"""See unittest.TestCase.setUp for specification."""
self.init()
# student registration is now
self.program.timeline.student_signup_start = timeline_utils.past()
self.program.timeline.student_signup_end = timeline_utils.future()
self.program.timeline.put()
def testPageLoads(self):
"""Tests that page loads properly."""
response = self.get(_getProfileRegisterAsStudentUrl(self.program.key()))
self.assertResponseOK(response)
def testJsonLoads(self):
"""Tests that JSON data loads properly."""
response = self.get(
_getProfileRegisterAsStudentUrl(self.program.key(), is_json=True))
self.assertNotIn(base.JSON_ERROR_VALUE, response.content)
def testStudentProfileCreated(self):
"""Tests that profile entity is created correctly."""
postdata = {
'user_id': TEST_USER_ID,
'public_name': TEST_PUBLIC_NAME,
'first_name': TEST_FIRST_NAME,
'last_name': TEST_LAST_NAME,
'email': TEST_EMAIL,
'phone': TEST_PHONE,
'residential_street': TEST_RESIDENTIAL_STREET,
'residential_street_extra': TEST_RESIDENTIAL_STREET_EXTRA,
'residential_city': TEST_RESIDENTIAL_CITY,
'residential_province': TEST_RESIDENTIAL_PROVINCE,
'residential_country': TEST_RESIDENTIAL_COUNTRY,
'residential_postal_code': TEST_RESIDENTIAL_POSTAL_CODE,
'birth_date': TEST_BIRTH_DATE.strftime('%Y-%m-%d'),
'tee_style': TEST_TEE_STYLE,
'tee_size': TEST_TEE_SIZE,
'gender': TEST_GENDER,
'program_knowledge': TEST_PROGRAM_KNOWLEDGE,
'school_country': TEST_SCHOOL_COUNTRY,
'school_name': TEST_SCHOOL_NAME,
'school_web_page': TEST_SCHOOL_WEB_PAGE,
'major': TEST_MAJOR,
'degree': TEST_DEGREE,
'expected_graduation': TEST_EXPECTED_GRADUATION,
'terms_of_service': True,
}
response = self.post(
_getProfileRegisterAsStudentUrl(self.program.key()),
postdata=postdata)
self.assertResponseRedirect(
response, url=_getShowProfileUrl(self.program.key(), is_validated=True))
# check that user entity has been created
user_key = ndb.Key(user_model.User._get_kind(), TEST_USER_ID)
user = user_key.get()
self.assertIsNotNone(user)
# check that profile entity has been created
profile_key = ndb.Key(
user_model.User._get_kind(), TEST_USER_ID,
profile_model.Profile._get_kind(),
'%s/%s' % (self.program.key().name(), TEST_USER_ID))
profile = profile_key.get()
self.assertIsNotNone(profile)
# check that the created profile is a student
self.assertIsNotNone(profile.student_data)
self.assertTrue(profile.is_student)
# check student data properties
self.assertEqual(
profile.student_data.education.school_country, TEST_SCHOOL_COUNTRY)
self.assertEqual(
profile.student_data.education.school_id, TEST_SCHOOL_NAME)
self.assertEqual(
profile.student_data.education.web_page, TEST_SCHOOL_WEB_PAGE)
self.assertEqual(profile.student_data.education.major, TEST_MAJOR)
self.assertEqual(
profile.student_data.education.expected_graduation,
TEST_EXPECTED_GRADUATION)
self.assertEqual(
profile.student_data.education.degree, education_model.Degree.MASTERS)
self.assertEqual(profile.student_data.number_of_proposals, 0)
self.assertEqual(profile.student_data.number_of_projects, 0)
self.assertEqual(profile.student_data.number_of_passed_evaluations, 0)
self.assertEqual(profile.student_data.number_of_failed_evaluations, 0)
self.assertListEqual(profile.student_data.project_for_orgs, [])
self.assertIsNone(profile.student_data.tax_form)
self.assertIsNone(profile.student_data.enrollment_form)
# check that Terms Of Service is signed and a signature is created
self.assertIn(
ndb.Key.from_old_key(self.program.student_agreement.key()),
profile.accepted_tos)
signature = signature_model.Signature.query(
signature_model.Signature.profile == profile_key,
signature_model.Signature.document ==
ndb.Key.from_old_key(self.program.student_agreement.key())).get()
self.assertIsNotNone(signature)
VALID_POSTDATA = {
'public_name': TEST_PUBLIC_NAME,
'first_name': TEST_FIRST_NAME,
'last_name': TEST_LAST_NAME,
'email': TEST_EMAIL,
'phone': TEST_PHONE,
'residential_street': TEST_RESIDENTIAL_STREET,
'residential_street_extra': TEST_RESIDENTIAL_STREET_EXTRA,
'residential_city': TEST_RESIDENTIAL_CITY,
'residential_province': TEST_RESIDENTIAL_PROVINCE,
'residential_country': TEST_RESIDENTIAL_COUNTRY,
'residential_postal_code': TEST_RESIDENTIAL_POSTAL_CODE,
'shipping_name': TEST_SHIPPING_NAME,
'shipping_street': TEST_SHIPPING_STREET,
'shipping_city': TEST_SHIPPING_CITY,
'shipping_province': TEST_SHIPPING_PROVINCE,
'shipping_country': TEST_SHIPPING_COUNTRY,
'shipping_postal_code': TEST_SHIPPING_POSTAL_CODE,
'is_shipping_address_different': True,
'birth_date': TEST_BIRTH_DATE.strftime('%Y-%m-%d'),
'tee_style': TEST_TEE_STYLE,
'tee_size': TEST_TEE_SIZE,
'gender': TEST_GENDER,
'program_knowledge': TEST_PROGRAM_KNOWLEDGE,
}
class ProfileEditPageTest(test_utils.GSoCDjangoTestCase):
"""Unit tests for ProfileEditPage class."""
def setUp(self):
"""See unittest.TestCase.setUp for specification."""
self.init()
shipping_address = address_model.Address(
name=TEST_SHIPPING_NAME, street=TEST_SHIPPING_STREET,
street_extra=TEST_SHIPPING_STREET_EXTRA, city=TEST_SHIPPING_CITY,
province=TEST_SHIPPING_PROVINCE, country=TEST_SHIPPING_COUNTRY,
postal_code=TEST_SHIPPING_POSTAL_CODE)
# seed an organization member profile
self.profile = profile_seeder.seedProfile(
self.program.key(), shipping_address=shipping_address,
accepted_tos=
[ndb.Key.from_old_key(self.program.mentor_agreement.key())])
# seed a student profile
student_data = profile_seeder.seedStudentData(
enrollment_form=TEST_ENROLLMENT_FORM, tax_form=TEST_TAX_FORM)
self.student = profile_seeder.seedProfile(
self.program.key(), shipping_address=shipping_address,
student_data=student_data, accepted_tos=
[ndb.Key.from_old_key(self.program.student_agreement.key())])
def testPageLoads(self):
"""Tests that page loads properly."""
# check that the page loads for an organization member
profile_utils.loginNDB(self.profile.key.parent().get())
response = self.get(_getEditProfileUrl(self.program.key()))
self.assertResponseOK(response)
# check that the page loads for a student
profile_utils.loginNDB(self.student.key.parent().get())
response = self.get(_getEditProfileUrl(self.program.key()))
self.assertResponseOK(response)
def testJsonLoads(self):
"""Tests that JSON data loads properly."""
profile_utils.loginNDB(self.profile.key.parent().get())
response = self.get(_getEditProfileUrl(self.program.key(), is_json=True))
self.assertNotIn(base.JSON_ERROR_VALUE, response.content)
def testOrgMemberProfileUpdated(self):
"""Tests that organization member profile is updated properly."""
profile_utils.loginNDB(self.profile.key.parent().get())
postdata = {
'public_name': TEST_PUBLIC_NAME,
'first_name': TEST_FIRST_NAME,
'last_name': TEST_LAST_NAME,
'email': TEST_EMAIL,
'phone': TEST_PHONE,
'residential_street': TEST_RESIDENTIAL_STREET,
'residential_street_extra': TEST_RESIDENTIAL_STREET_EXTRA,
'residential_city': TEST_RESIDENTIAL_CITY,
'residential_province': TEST_RESIDENTIAL_PROVINCE,
'residential_country': TEST_RESIDENTIAL_COUNTRY,
'residential_postal_code': TEST_RESIDENTIAL_POSTAL_CODE,
'is_shipping_address_different': True,
'shipping_name': OTHER_TEST_SHIPPING_NAME,
'shipping_street': OTHER_TEST_SHIPPING_STREET,
'shipping_street_extra': OTHER_TEST_SHIPPING_STREET_EXTRA,
'shipping_city': OTHER_TEST_SHIPPING_CITY,
'shipping_province': OTHER_TEST_SHIPPING_PROVINCE,
'shipping_country': OTHER_TEST_SHIPPING_COUNTRY,
'shipping_postal_code': OTHER_TEST_SHIPPING_POSTAL_CODE,
'birth_date': TEST_BIRTH_DATE.strftime('%Y-%m-%d'),
'tee_style': TEST_TEE_STYLE,
'tee_size': TEST_TEE_SIZE,
'gender': TEST_GENDER,
'program_knowledge': TEST_PROGRAM_KNOWLEDGE,
}
response = self.post(
_getEditProfileUrl(self.program.key()), postdata=postdata)
self.assertResponseRedirect(
response, url=_getShowProfileUrl(self.program.key(), is_validated=True))
# check profile properties
profile = self.profile.key.get()
self.assertEqual(profile.public_name, TEST_PUBLIC_NAME)
self.assertEqual(profile.contact.email, TEST_EMAIL)
self.assertEqual(profile.first_name, TEST_FIRST_NAME)
self.assertEqual(profile.last_name, TEST_LAST_NAME)
self.assertEqual(profile.contact.phone, TEST_PHONE)
# check residential address properties
self.assertEqual(
profile.residential_address.street, TEST_RESIDENTIAL_STREET)
self.assertEqual(
profile.residential_address.street_extra, TEST_RESIDENTIAL_STREET_EXTRA)
self.assertEqual(
profile.residential_address.city, TEST_RESIDENTIAL_CITY)
self.assertEqual(
profile.residential_address.province, TEST_RESIDENTIAL_PROVINCE)
self.assertEqual(
profile.residential_address.country, TEST_RESIDENTIAL_COUNTRY)
self.assertEqual(
profile.residential_address.postal_code, TEST_RESIDENTIAL_POSTAL_CODE)
# check shipping address properties
self.assertEqual(
profile.shipping_address.name, OTHER_TEST_SHIPPING_NAME)
self.assertEqual(
profile.shipping_address.street, OTHER_TEST_SHIPPING_STREET)
self.assertEqual(
profile.shipping_address.street_extra, OTHER_TEST_SHIPPING_STREET_EXTRA)
self.assertEqual(
profile.shipping_address.city, OTHER_TEST_SHIPPING_CITY)
self.assertEqual(
profile.shipping_address.province, OTHER_TEST_SHIPPING_PROVINCE)
self.assertEqual(
profile.shipping_address.country, OTHER_TEST_SHIPPING_COUNTRY)
self.assertEqual(
profile.shipping_address.postal_code, OTHER_TEST_SHIPPING_POSTAL_CODE)
self.assertEqual(profile.birth_date, TEST_BIRTH_DATE)
# : TODO(daniel): handle program_knowledge
# self.assertEqual(profile.program_knowledge, TEST_PROGRAM_KNOWLEDGE)
self.assertEqual(profile.tee_style, profile_model.TeeStyle.FEMALE)
self.assertEqual(profile.tee_size, profile_model.TeeSize.M)
# check profile is not a student
self.assertFalse(profile.is_student)
self.assertIsNone(profile.student_data)
def testStudentProfileUpdated(self):
"""Tests that a student profile is updated properly."""
profile_utils.loginNDB(self.student.key.parent().get())
postdata = VALID_POSTDATA.copy()
postdata.update({
'school_country': OTHER_TEST_SCHOOL_COUNTRY,
'school_name': OTHER_TEST_SCHOOL_NAME,
'school_web_page': OTHER_TEST_SCHOOL_WEB_PAGE,
'major': OTHER_TEST_MAJOR,
'degree': OTHER_TEST_DEGREE,
'expected_graduation': OTHER_TEST_EXPECTED_GRADUATION,
})
response = self.post(
_getEditProfileUrl(self.program.key()), postdata=postdata)
self.assertResponseRedirect(
response, url=_getShowProfileUrl(self.program.key(), is_validated=True))
student = self.student.key.get()
# check student data properties are updated
self.assertEqual(
student.student_data.education.school_country,
OTHER_TEST_SCHOOL_COUNTRY)
self.assertEqual(
student.student_data.education.school_id,
OTHER_TEST_SCHOOL_NAME)
self.assertEqual(
student.student_data.education.web_page,
OTHER_TEST_SCHOOL_WEB_PAGE)
self.assertEqual(
student.student_data.education.major,
OTHER_TEST_MAJOR)
self.assertEqual(
student.student_data.education.degree,
education_model.Degree.PHD)
self.assertIsNone(student.student_data.education.grade)
self.assertEqual(
student.student_data.education.expected_graduation,
OTHER_TEST_EXPECTED_GRADUATION)
# check that other student data properties are not changed
self.assertEqual(student.student_data.enrollment_form, TEST_ENROLLMENT_FORM)
self.assertEqual(student.student_data.tax_form, TEST_TAX_FORM)
def testTermsOfServiceChanges(self):
"""Tests that new Terms of Service must be accepted."""
profile_utils.loginNDB(self.profile.key.parent().get())
# create new Terms Of Service document
self.program.mentor_agreement = document_seeder.seedDocument(
self.program, prefix=self.program.prefix)
self.program.put()
# check that data error is returned if ToS is not signed
response = self.post(
_getEditProfileUrl(self.program.key()), postdata=VALID_POSTDATA)
self.assertTrue(response.context['error'])
# check that it is OK when ToS is accepted
postdata = VALID_POSTDATA.copy()
postdata['terms_of_service'] = True
response = self.post(
_getEditProfileUrl(self.program.key()), postdata=postdata)
self.assertResponseRedirect(
response, url=_getShowProfileUrl(self.program.key(), is_validated=True))
profile = self.profile.key.get()
# check that new Terms Of Service is signed and a signature is created
self.assertIn(
ndb.Key.from_old_key(self.program.mentor_agreement.key()),
profile.accepted_tos)
signature = signature_model.Signature.query(
signature_model.Signature.profile == profile.key,
signature_model.Signature.document ==
ndb.Key.from_old_key(self.program.mentor_agreement.key())).get()
self.assertIsNotNone(signature)
def testClearShippingAddress(self):
"""Tests that shipping address is cleared properly."""
profile_utils.loginNDB(self.profile.key.parent().get())
postdata = {
'public_name': TEST_PUBLIC_NAME,
'first_name': TEST_FIRST_NAME,
'last_name': TEST_LAST_NAME,
'email': TEST_EMAIL,
'phone': TEST_PHONE,
'residential_street': TEST_RESIDENTIAL_STREET,
'residential_city': TEST_RESIDENTIAL_CITY,
'residential_province': TEST_RESIDENTIAL_PROVINCE,
'residential_country': TEST_RESIDENTIAL_COUNTRY,
'residential_postal_code': TEST_RESIDENTIAL_POSTAL_CODE,
'is_shipping_address_different': False,
'birth_date': TEST_BIRTH_DATE.strftime('%Y-%m-%d'),
'tee_style': TEST_TEE_STYLE,
'tee_size': TEST_TEE_SIZE,
'gender': TEST_GENDER,
'program_knowledge': TEST_PROGRAM_KNOWLEDGE,
}
response = self.post(
_getEditProfileUrl(self.program.key()), postdata=postdata)
self.assertResponseRedirect(
response, url=_getShowProfileUrl(self.program.key(), is_validated=True))
# check that shipping address is cleared
profile = self.profile.key.get()
self.assertIsNone(profile.shipping_address)
def testIsShippingAddressDifferent(self):
"""Tests whether is_shipping_address_different is set correctly."""
profile_utils.loginNDB(self.profile.key.parent().get())
# different shipping address is used
response = self.get(_getEditProfileUrl(self.program.key()))
form = response.context['forms'][0]
self.assertTrue(form.data['is_shipping_address_different'])
# no shipping address is used
self.profile.shipping_address = None
self.profile.put()
response = self.get(_getEditProfileUrl(self.program.key()))
form = response.context['forms'][0]
self.assertFalse(form.data['is_shipping_address_different'])
def testInvalidData(self):
"""Tests that profile is not updated if data is not valid."""
profile_utils.loginNDB(self.profile.key.parent().get())
# check that data is really valid
response = self.post(
_getEditProfileUrl(self.program.key()), postdata=VALID_POSTDATA)
self.assertResponseRedirect(
response, url=_getShowProfileUrl(self.program.key(), is_validated=True))
# the birth date is not eligible (the user is too young to be an org member)
days = (365 * validate.ORGANIZATION_MEMBER_MIN_AGE) / 2
self.program.student_min_age_as_of = (
TEST_BIRTH_DATE + datetime.timedelta(days=days))
self.program.put()
postdata = VALID_POSTDATA.copy()
response = self.post(
_getEditProfileUrl(self.program.key()), postdata=postdata)
self.assertTrue(response.context['error'])
# residential address fields have invalid characters
fields = [
'residential_street', 'residential_street_extra', 'residential_city',
'residential_province', 'residential_country',
'residential_postal_code', 'first_name', 'last_name']
for field in fields:
postdata = VALID_POSTDATA.copy()
postdata[field] = '!N^al!D'
response = self.post(
_getEditProfileUrl(self.program.key()), postdata=postdata)
self.assertTrue(response.context['error'])
# shipping address fields have invalid characters
fields = [
'shipping_street', 'shipping_street_extra', 'shipping_city',
'shipping_province', 'shipping_country', 'shipping_postal_code',
'shipping_name']
for field in fields:
postdata = VALID_POSTDATA.copy()
postdata[field] = '!N^al!D'
response = self.post(
_getEditProfileUrl(self.program.key()), postdata=postdata)
self.assertTrue(response.context['error'])
def testGradeNotSet(self):
"""Tests that grade of a student profile is not updated.
Grade is a property of education model and a field in the generalized
profile form which are irrelevant for Summer Of Code programs. This test
case ensures that the property is not saved in the datastore even if
it is submitted in the POST data.
"""
profile_utils.loginNDB(self.student.key.parent().get())
# grade is present in the POST data
postdata = VALID_POSTDATA.copy()
postdata.update({
'school_country': OTHER_TEST_SCHOOL_COUNTRY,
'school_name': OTHER_TEST_SCHOOL_NAME,
'school_web_page': OTHER_TEST_SCHOOL_WEB_PAGE,
'major': OTHER_TEST_MAJOR,
'degree': OTHER_TEST_DEGREE,
'expected_graduation': OTHER_TEST_EXPECTED_GRADUATION,
'grade': '5'
})
response = self.post(
_getEditProfileUrl(self.program.key()), postdata=postdata)
self.assertResponseRedirect(
response, url=_getShowProfileUrl(self.program.key(), is_validated=True))
# check that the grade is not set
student = self.student.key.get()
self.assertIsNone(student.student_data.education.grade)
_TEST_FORM_FILE = 'test_file_name.pdf'
class ProfileShowPageTest(test_utils.GSoCDjangoTestCase):
"""Unit tests for ProfileShowPage class."""
def setUp(self):
"""See unittest.TestCase.setUp for specification."""
self.init()
def testPageLoads(self):
"""Tests that page loads properly."""
user = user_seeder.seedUser()
profile_utils.loginNDB(user)
profile_seeder.seedProfile(self.program.key(), user=user)
response = self.get(_getShowProfileUrl(self.program.key()))
self.assertResponseOK(response)
def testProfileTabs(self):
"""Tests that correct profile related tabs are present in context."""
self.timeline_helper.orgsAnnounced()
user = user_seeder.seedUser()
profile_utils.loginNDB(user)
profile_seeder.seedProfile(self.program.key(), user=user)
response = self.get(_getShowProfileUrl(self.program.key()))
# check that tabs are present in context
self.assertIn('tabs', response.context)
# check that tab to "Edit Profile" page is the selected one
self.assertEqual(response.context['tabs'].selected_tab_id,
tabs.VIEW_PROFILE_TAB_ID)
def testEnrollmentForm(self):
"""Tests that context for enrollment form is set properly."""
user = user_seeder.seedUser()
profile_utils.loginNDB(user)
# seed a student without a form
student = profile_seeder.seedStudent(self.program, user=user)
# during the program it is possible to submit a form
self.timeline_helper.studentSignup()
response = self.get(_getShowProfileUrl(self.program.key()))
forms_fields = dict(response.context['profile_template']._groups[-1].fields)
self.assertTrue(profile_view.ENROLLMENT_FORM_LABEL in forms_fields)
enrollment_form_field = forms_fields[profile_view.ENROLLMENT_FORM_LABEL]
self.assertIn(profile_view._NO_FORM_SUBMITTED, enrollment_form_field)
self.assertIn('Upload', enrollment_form_field)
# after the program it is not possible to submit a form
self.timeline_helper.offSeason()
response = self.get(_getShowProfileUrl(self.program.key()))
forms_fields = dict(response.context['profile_template']._groups[-1].fields)
self.assertTrue(profile_view.ENROLLMENT_FORM_LABEL in forms_fields)
enrollment_form_field = forms_fields[profile_view.ENROLLMENT_FORM_LABEL]
self.assertIn(profile_view._NO_FORM_SUBMITTED, enrollment_form_field)
self.assertNotIn('Upload', enrollment_form_field)
# now a form is submitted
student.student_data.enrollment_form = self.createBlob(_TEST_FORM_FILE)
student.put()
# during the program it is possible to download or re-upload a form
self.timeline_helper.studentSignup()
response = self.get(_getShowProfileUrl(self.program.key()))
forms_fields = dict(response.context['profile_template']._groups[-1].fields)
self.assertTrue(profile_view.ENROLLMENT_FORM_LABEL in forms_fields)
enrollment_form_field = forms_fields[profile_view.ENROLLMENT_FORM_LABEL]
self.assertIn(_TEST_FORM_FILE, enrollment_form_field)
self.assertIn('Download', enrollment_form_field)
self.assertIn('Re-upload', enrollment_form_field)
# after the program it is only possible to download a form
self.timeline_helper.offSeason()
response = self.get(_getShowProfileUrl(self.program.key()))
forms_fields = dict(response.context['profile_template']._groups[-1].fields)
self.assertTrue(profile_view.ENROLLMENT_FORM_LABEL in forms_fields)
enrollment_form_field = forms_fields[profile_view.ENROLLMENT_FORM_LABEL]
self.assertIn(_TEST_FORM_FILE, enrollment_form_field)
self.assertIn('Download', enrollment_form_field)
self.assertNotIn('Re-upload', enrollment_form_field)
def testTaxForm(self):
"""Tests that context for tax form is set properly."""
user = user_seeder.seedUser()
profile_utils.loginNDB(user)
# seed a student without a form
student = profile_seeder.seedStudent(self.program, user=user)
# no form is required during the sign-up
self.timeline_helper.studentSignup()
response = self.get(_getShowProfileUrl(self.program.key()))
forms_fields = dict(response.context['profile_template']._groups[-1].fields)
self.assertTrue(profile_view.TAX_FORM_LABEL in forms_fields)
tax_form_field = forms_fields[profile_view.TAX_FORM_LABEL]
self.assertIn(profile_view._NO_FORM_REQUIRED, tax_form_field)
# no form is required for a student with no projects
self.timeline_helper.formSubmission()
response = self.get(_getShowProfileUrl(self.program.key()))
forms_fields = dict(response.context['profile_template']._groups[-1].fields)
self.assertTrue(profile_view.TAX_FORM_LABEL in forms_fields)
tax_form_field = forms_fields[profile_view.TAX_FORM_LABEL]
self.assertIn(profile_view._NO_FORM_REQUIRED, tax_form_field)
# seed a project for the student so a form is required
project_utils.seedNDBProject(student, self.program.key())
response = self.get(_getShowProfileUrl(self.program.key()))
forms_fields = dict(response.context['profile_template']._groups[-1].fields)
self.assertTrue(profile_view.TAX_FORM_LABEL in forms_fields)
tax_form_field = forms_fields[profile_view.TAX_FORM_LABEL]
self.assertIn(profile_view._NO_FORM_SUBMITTED, tax_form_field)
self.assertIn('Upload', tax_form_field)
# it is not possible to submit a form after the program
self.timeline_helper.offSeason()
response = self.get(_getShowProfileUrl(self.program.key()))
forms_fields = dict(response.context['profile_template']._groups[-1].fields)
self.assertTrue(profile_view.TAX_FORM_LABEL in forms_fields)
tax_form_field = forms_fields[profile_view.TAX_FORM_LABEL]
self.assertIn(profile_view._NO_FORM_SUBMITTED, tax_form_field)
self.assertNotIn('Upload', tax_form_field)
# now a form is submitted
student.student_data.tax_form = self.createBlob(_TEST_FORM_FILE)
student.put()
# during the program it is possible to download or re-upload a form
self.timeline_helper.formSubmission()
response = self.get(_getShowProfileUrl(self.program.key()))
forms_fields = dict(response.context['profile_template']._groups[-1].fields)
self.assertTrue(profile_view.TAX_FORM_LABEL in forms_fields)
tax_form_field = forms_fields[profile_view.TAX_FORM_LABEL]
self.assertIn(_TEST_FORM_FILE, tax_form_field)
self.assertIn('Re-upload', tax_form_field)
self.assertIn('Download', tax_form_field)
# after the program it is only possible to download a form
self.timeline_helper.offSeason()
response = self.get(_getShowProfileUrl(self.program.key()))
forms_fields = dict(response.context['profile_template']._groups[-1].fields)
self.assertTrue(profile_view.TAX_FORM_LABEL in forms_fields)
tax_form_field = forms_fields[profile_view.TAX_FORM_LABEL]
self.assertIn(_TEST_FORM_FILE, tax_form_field)
self.assertNotIn('Re-upload', tax_form_field)
self.assertIn('Download', tax_form_field)
class ProfileAdminPageTest(test_utils.GSoCDjangoTestCase):
"""Unit tests for ProfileAdminPage class."""
def setUp(self):
"""See unittest.TestCase.setUp for specification."""
self.init()
def testPageLoads(self):
"""Tests that page loads properly."""
user = user_seeder.seedUser(host_for=[self.program])
profile_utils.loginNDB(user)
profile_seeder.seedProfile(self.program.key(), user=user)
# seed a profile to show
profile = profile_seeder.seedProfile(self.program.key())
response = self.get(_getAdminProfileUrl(profile.key))
self.assertResponseOK(response)