blob: e6b71804a65672266e35c165159af1faecc06100 [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.
"""Tests for profile logic."""
import datetime
import mock
import unittest
from google.appengine.ext import ndb
from melange.logic import profile as profile_logic
from melange.models import address as address_model
from melange.models import organization as org_model
from melange.models import profile as ndb_profile_model
from melange.models import user as user_model
from melange.utils import rich_bool
from melange.utils import time as time_utils
from seeder import education as education_seeder
from seeder import profile as profile_seeder
from seeder import program as program_seeder
from seeder import site as site_seeder
from seeder import sponsor as sponsor_seeder
from seeder import user as user_seeder
from soc.models import program as program_model
from soc.modules.seeder.logic.seeder import logic as seeder_logic
from tests import org_utils
from tests import test_utils
from tests import timeline_utils
class CanResignAsOrgAdminForOrgTest(unittest.TestCase):
"""Unit tests for canResignAsOrgAdminForOrg function."""
def setUp(self):
"""See unittest.TestCase.setUp for specification."""
# seed a new program
self.program = program_seeder.seedProgram()
# seed a couple of organizations
self.organization_one = org_utils.seedOrganization(self.program.key())
self.organization_two = org_utils.seedOrganization(self.program.key())
# seed a new org admin for organization one
self.org_admin = profile_seeder.seedProfile(
self.program.key(), admin_for=[self.organization_one.key])
def testOnlyOrgAdmin(self):
"""Tests that the only org admin cannot resign."""
can_resign = profile_logic.canResignAsOrgAdminForOrg(
self.org_admin, self.organization_one.key)
self.assertFalse(can_resign)
self.assertEqual(can_resign.extra, profile_logic.ONLY_ORG_ADMIN)
def testMoreOrgAdmins(self):
"""Tests that org admin can resign if there is another one."""
# seed another org admin
profile_seeder.seedProfile(
self.program.key(), admin_for=[self.organization_one.key])
# now the org admin can resign, as there is another admin
can_resign = profile_logic.canResignAsOrgAdminForOrg(
self.org_admin, self.organization_one.key)
self.assertTrue(can_resign)
def testNotOrgAdminForOrg(self):
"""Tests that error is raised if the profile is not an org admin."""
with self.assertRaises(ValueError):
profile_logic.canResignAsOrgAdminForOrg(
self.org_admin, self.organization_two.key)
class IsMentorRoleEligibleForOrgTest(unittest.TestCase):
"""Unit tests for isMentorRoleEligibleForOrg function."""
def setUp(self):
"""See unittest.TestCase.setUp for specification."""
program = program_seeder.seedProgram()
# seed an organization
self.org = org_utils.seedOrganization(program.key())
# seed a profile
self.profile = profile_seeder.seedProfile(program.key())
def testForUserWithNoRole(self):
"""Tests that user with no role is eligible."""
result = profile_logic.isMentorRoleEligibleForOrg(
self.profile, self.org.key)
self.assertTrue(result)
@mock.patch.object(
profile_logic, 'canResignAsOrgAdminForOrg', return_value=rich_bool.FALSE)
def testForOrgAdminThatCannotResign(self, mock_func):
"""Tests that org admin that cannot resign is not eligible."""
self.profile.mentor_for = [self.org.key]
self.profile.admin_for = [self.org.key]
result = profile_logic.isMentorRoleEligibleForOrg(
self.profile, self.org.key)
self.assertFalse(result)
@mock.patch.object(
profile_logic, 'canResignAsOrgAdminForOrg', return_value=rich_bool.TRUE)
def testForOrgAdminThatCanResign(self, mock_func):
"""Tests that org admin that can resign is eligible."""
self.profile.mentor_for = [self.org.key]
self.profile.admin_for = [self.org.key]
result = profile_logic.isMentorRoleEligibleForOrg(
self.profile, self.org.key)
self.assertTrue(result)
_NUMBER_OF_MENTORS = 3
class QueryAllMentorsForProgramTest(unittest.TestCase):
"""Unit test for queryAllMentorsForProgram function."""
def setUp(self):
"""See unittest.TestCase.setUp for specification."""
# seed two programs for the same sponsor
sponsor = sponsor_seeder.seedSponsor()
self.program_one = program_seeder.seedProgram(sponsor_key=sponsor.key())
program_two = program_seeder.seedProgram(sponsor_key=sponsor.key())
org_one = org_utils.seedOrganization(self.program_one.key())
org_two = org_utils.seedOrganization(program_two.key())
self.mentor_keys = set()
# seed a few mentors for both programs
for _ in range(_NUMBER_OF_MENTORS):
self.mentor_keys.add(profile_seeder.seedProfile(
self.program_one.key(), mentor_for=[org_one.key]).key)
profile_seeder.seedProfile(program_two.key(), mentor_for=[org_two.key])
def testAllMentorsForProgramFetched(self):
"""Tests that the returned query fetches all mentors for the program."""
query = profile_logic.queryAllMentorsForProgram(self.program_one.key())
result = query.fetch(1000)
self.assertEqual(self.mentor_keys, set(mentor.key for mentor in result))
_NUMBER_OF_MENTORS = 3
class QueryAllMentorsForOrgTest(unittest.TestCase):
"""Unit tests for queryAllMentorsForOrg function."""
def setUp(self):
"""See unittest.TestCase.setUp for specification."""
self.program = program_seeder.seedProgram()
self.org_one = org_utils.seedOrganization(self.program.key())
self.org_two = org_utils.seedOrganization(self.program.key())
self.org_three = org_utils.seedOrganization(self.program.key())
self.org_one_mentor_keys = set()
self.org_two_mentor_keys = set()
self.org_three_mentor_keys = set()
for _ in range(_NUMBER_OF_MENTORS):
self.org_one_mentor_keys.add(
profile_seeder.seedProfile(
self.program.key(), mentor_for=[self.org_one.key]).key)
self.org_two_mentor_keys.add(
profile_seeder.seedProfile(
self.program.key(), mentor_for=[self.org_two.key]).key)
def testAllMentorsForOrgFetched(self):
"""Tests that the returned query fetches mentors for the organization."""
# check mentors returned for organization one
query = profile_logic.queryAllMentorsForOrg(self.org_one.key)
actual_keys = query.fetch(1000, keys_only=True)
self.assertSetEqual(set(actual_keys), self.org_one_mentor_keys)
# check mentors returned for organization two
query = profile_logic.queryAllMentorsForOrg(self.org_two.key)
actual_keys = query.fetch(1000, keys_only=True)
self.assertSetEqual(set(actual_keys), self.org_two_mentor_keys)
# check mentors returned for organization three
query = profile_logic.queryAllMentorsForOrg(self.org_three.key)
actual_keys = query.fetch(1000, keys_only=True)
self.assertSetEqual(set(actual_keys), self.org_three_mentor_keys)
def testMentorsForMultipleOrgsFetched(self):
"""Tests that mentors are fetched for more than one organization."""
# seed a few mentors for the third organization
for _ in range(_NUMBER_OF_MENTORS):
self.org_three_mentor_keys.add(
profile_seeder.seedProfile(
self.program.key(), mentor_for=[self.org_three.key]).key)
# check mentors returned for organization one and two
query = profile_logic.queryAllMentorsForOrg(
self.org_one.key, self.org_two.key)
actual_keys = query.fetch(1000, keys_only=True)
self.assertSetEqual(
set(actual_keys), self.org_one_mentor_keys | self.org_two_mentor_keys)
_NUMBER_OF_STUDENTS = 3
class QueryAllStudentsForProgramTest(unittest.TestCase):
"""Unit test for queryAllStudentsForProgram function."""
def setUp(self):
"""See unittest.TestCase.setUp for specification."""
# seed two programs for the same sponsor
sponsor = sponsor_seeder.seedSponsor()
self.program_one = program_seeder.seedProgram(sponsor_key=sponsor.key())
program_two = program_seeder.seedProgram(sponsor_key=sponsor.key())
# seed mentors for both programs
org = org_utils.seedOrganization(self.program_one.key())
profile_seeder.seedProfile(self.program_one.key(), mentor_for=[org.key])
profile_seeder.seedProfile(program_two.key(), mentor_for=[org.key])
self.student_keys = set()
# seed a few students for both programs
for _ in range(_NUMBER_OF_STUDENTS):
self.student_keys.add(profile_seeder.seedStudent(self.program_one).key)
profile_seeder.seedProfile(program_two.key())
def testAllStudentsForProgramFetched(self):
"""Tests that the returned query fetches all students for the program."""
query = profile_logic.queryAllStudentsForProgram(self.program_one.key())
result = query.fetch(1000)
self.assertEqual(self.student_keys, set(student.key for student in result))
class GetOrgAdminsTest(unittest.TestCase):
"""Unit tests for getOrgAdmins function."""
def setUp(self):
"""See unittest.TestCase.setUp for specification."""
# seed a new program
self.program = program_seeder.seedProgram()
# seed a couple of organizations
self.organization_one = org_utils.seedOrganization(self.program.key())
self.organization_two = org_utils.seedOrganization(self.program.key())
def testNoOrgAdmin(self):
"""Tests that the empty list is returned if no org admin exists."""
org_admins = profile_logic.getOrgAdmins(self.organization_one)
self.assertListEqual(org_admins, [])
def testOneOrgAdmin(self):
"""Tests that a list of size one is returned if one org admin exists."""
# seed a new org admin for organization one
org_admin = profile_seeder.seedProfile(
self.program.key(), admin_for=[self.organization_one.key])
# the org admin should be returned
results = profile_logic.getOrgAdmins(self.organization_one)
self.assertSetEqual(
set(result.key for result in results), set([org_admin.key]))
# keys_only set to True should return only the key
org_admin_keys = profile_logic.getOrgAdmins(
self.organization_one, keys_only=True)
self.assertSetEqual(set(org_admin_keys), set([org_admin.key]))
# there is still no org admin for organization two
org_admins = profile_logic.getOrgAdmins(self.organization_two)
self.assertListEqual(org_admins, [])
def testManyOrgAdmins(self):
"""Tests that all org admins are returned if many exist."""
# seed a few org admins for organization one
org_admin_keys = set()
for _ in range(5):
org_admin_keys.add(profile_seeder.seedProfile(
self.program.key(), admin_for=[self.organization_one.key]).key)
# all org admins should be returned
results = profile_logic.getOrgAdmins(self.organization_one)
self.assertSetEqual(
set([result.key for result in results]), org_admin_keys),
# all org admins keys should be returned if keys_only set
results = profile_logic.getOrgAdmins(
self.organization_one, keys_only=True)
self.assertSetEqual(set(results), org_admin_keys),
def testNotActiveOrgAdmin(self):
# seed non-active org admin for organization one
profile_seeder.seedProfile(
self.program.key(), admin_for=[self.organization_one.key],
status=ndb_profile_model.Status.BANNED)
# not active org admin not returned
org_admins = profile_logic.getOrgAdmins(self.organization_one)
self.assertListEqual(org_admins, [])
# keys_only set to True does not return any keys
org_admin_keys = profile_logic.getOrgAdmins(
self.organization_one, keys_only=True)
self.assertListEqual(org_admin_keys, [])
def testExtraAttrs(self):
# seed male org admin for organization one
org_admin = profile_seeder.seedProfile(
self.program.key(), admin_for=[self.organization_one.key],
gender=ndb_profile_model.Gender.MALE)
# seed female org admin for organization one
profile_seeder.seedProfile(
self.program.key(), admin_for=[self.organization_one.key],
gender=ndb_profile_model.Gender.FEMALE)
# retrieve only org admins with extra attrs
extra_attrs = {
ndb_profile_model.Profile.gender: [ndb_profile_model.Gender.MALE]
}
results = profile_logic.getOrgAdmins(self.organization_one,
extra_attrs=extra_attrs)
# only the male org admin should be returned
self.assertSetEqual(
set([result.key for result in results]), set([org_admin.key]))
def testRejectedOrganization(self):
"""Tests that admins for a rejected organization are returned correctly."""
self.organization_one.status = org_model.Status.REJECTED
# seed some organization admins
admin_keys = set()
for _ in range(5):
admin_keys.add(profile_seeder.seedProfile(
self.program.key(), rejected_for=[self.organization_one.key]).key)
# fetch actual entities
results = profile_logic.getOrgAdmins(self.organization_one)
# check that all org admins are returned
self.assertSetEqual(
set([result.key for result in results]), admin_keys)
# fetch only keys
results = profile_logic.getOrgAdmins(self.organization_one, keys_only=True)
# check that all keys are returned
self.assertSetEqual(set(results), admin_keys)
class AssignNoRoleForOrgTest(unittest.TestCase):
"""Unit tests for assignNoRoleForOrg function."""
def setUp(self):
"""See unittest.TestCase.setUp for specification."""
# seed a program
self.program = program_seeder.seedProgram()
# seed an organization
self.org = org_utils.seedOrganization(self.program.key())
# seed a profile
self.profile = profile_seeder.seedProfile(self.program.key())
def testForRoleForOneOrg(self):
"""Tests that the user does not have roles for organization anymore."""
self.profile.mentor_for = [self.org.key]
self.profile.admin_for = [self.org.key]
self.profile.put()
profile_logic.assignNoRoleForOrg(self.profile, self.org.key)
self.assertFalse(self.profile.is_mentor)
self.assertListEqual(self.profile.mentor_for, [])
self.assertFalse(self.profile.is_admin)
self.assertListEqual(self.profile.admin_for, [])
def testForRoleForManyOrgs(self):
"""Tests that the user still have roles for other organizations."""
# seed another organization
other_org = org_utils.seedOrganization(self.program.key())
self.profile.mentor_for = [self.org.key, other_org.key]
self.profile.org_admin_for = [self.org.key]
self.profile.put()
profile_logic.assignNoRoleForOrg(self.profile, self.org.key)
self.assertTrue(self.profile.is_mentor)
self.assertListEqual(self.profile.mentor_for, [other_org.key])
self.assertFalse(self.profile.is_admin)
self.assertListEqual(self.profile.admin_for, [])
class AssignMentorRoleForOrgTest(test_utils.DjangoTestCase):
"""Unit tests for assignMentorRoleForOrg function."""
def setUp(self):
"""See unittest.TestCase.setUp for specification."""
self.init()
# seed a program
self.program = program_seeder.seedProgram()
# seed an organization
self.org = org_utils.seedOrganization(self.program.key())
# seed a profile
self.profile = profile_seeder.seedProfile(self.program.key())
def testForUserWithNoRole(self):
"""Tests that a user with no role is promoted to a mentor role."""
profile_logic.assignMentorRoleForOrg(self.profile, self.org.key)
self.assertTrue(self.profile.is_mentor)
self.assertListEqual(self.profile.mentor_for, [self.org.key])
self.assertFalse(self.profile.is_admin)
self.assertListEqual(self.profile.admin_for, [])
def testForUserWithOrgAdminRole(self):
"""Tests that a user with org admin role is lowered to a mentor role."""
self.profile.mentor_for = [self.org.key]
self.profile.admin_for = [self.org.key]
self.profile.put()
profile_logic.assignMentorRoleForOrg(self.profile, self.org.key)
self.assertTrue(self.profile.is_mentor)
self.assertListEqual(self.profile.mentor_for, [self.org.key])
self.assertFalse(self.profile.is_admin)
self.assertListEqual(self.profile.admin_for, [])
def testForOrgAdminForAnotherOrg(self):
"""Tests that a user is still org admin for another organization."""
# seed another organization
other_org = org_utils.seedOrganization(self.program.key())
self.profile.mentor_for = [other_org.key]
self.profile.admin_for = [other_org.key]
self.profile.put()
profile_logic.assignMentorRoleForOrg(self.profile, self.org.key)
self.assertTrue(self.profile.is_mentor)
self.assertIn(self.org.key, self.profile.mentor_for)
self.assertIn(other_org.key, self.profile.mentor_for)
self.assertTrue(self.profile.is_admin)
self.assertListEqual(self.profile.admin_for, [other_org.key])
def testOrgMemberWelcomeEmailSent(self):
"""Tests that welcome email is sent if needed."""
program_messages = program_seeder.seedProgramMessages(
program_key=self.program.key())
site = site_seeder.seedSite()
profile_logic.assignMentorRoleForOrg(
self.profile, self.org.key, send_org_member_welcome_email=True,
program=self.program, program_messages=program_messages, site=site)
self.assertIn(
ndb_profile_model.MessageType.ORG_MEMBER_WELCOME_MSG,
self.profile.sent_messages)
self.assertEmailSent(to=self.profile.contact.email)
class AssignOrgAdminRoleForOrgTest(test_utils.DjangoTestCase):
"""Unit tests for assignOrgAdminRoleForOrg function."""
def setUp(self):
"""See unittest.TestCase.setUp for specification."""
self.init()
# seed a program
self.program = program_seeder.seedProgram()
# seed an organization
self.org = org_utils.seedOrganization(self.program.key())
# seed a profile
self.profile = profile_seeder.seedProfile(self.program.key())
def testForUserWithNoRole(self):
"""Tests that a user with no role is promoted to an org admin role."""
profile_logic.assignOrgAdminRoleForOrg(self.profile, self.org.key)
self.assertTrue(self.profile.is_mentor)
self.assertListEqual(self.profile.mentor_for, [self.org.key])
self.assertTrue(self.profile.is_admin)
self.assertListEqual(self.profile.admin_for, [self.org.key])
def testForUserWithMentorRole(self):
"""Tests that a user with mentor role is promoted to an org admin role."""
self.profile.mentor_for = [self.org.key]
self.profile.put()
profile_logic.assignOrgAdminRoleForOrg(self.profile, self.org.key)
self.assertTrue(self.profile.is_mentor)
self.assertListEqual(self.profile.mentor_for, [self.org.key])
self.assertTrue(self.profile.is_admin)
self.assertListEqual(self.profile.admin_for, [self.org.key])
def testForMentorForAnotherOrg(self):
"""Tests that a user is still only a mentor for another organization."""
# seed another organization
other_org = org_utils.seedOrganization(self.program.key())
self.profile.mentor_for = [other_org.key]
self.profile.put()
profile_logic.assignOrgAdminRoleForOrg(self.profile, self.org.key)
self.assertTrue(self.profile.is_mentor)
self.assertIn(self.org.key, self.profile.mentor_for)
self.assertIn(other_org.key, self.profile.mentor_for)
self.assertTrue(self.profile.is_admin)
self.assertListEqual(self.profile.admin_for, [self.org.key])
def testOrgMemberWelcomeEmailSent(self):
"""Tests that welcome email is sent if needed."""
program_messages = program_seeder.seedProgramMessages(
program_key=self.program.key())
site = site_seeder.seedSite()
profile_logic.assignOrgAdminRoleForOrg(
self.profile, self.org.key, send_org_member_welcome_email=True,
program=self.program, program_messages=program_messages, site=site)
self.assertIn(
ndb_profile_model.MessageType.ORG_MEMBER_WELCOME_MSG,
self.profile.sent_messages)
self.assertEmailSent(to=self.profile.contact.email)
class GetProfileForUsernameTest(unittest.TestCase):
"""Unit tests for getProfileForUsername function."""
def setUp(self):
"""See unittest.TestCase.setUp for specification."""
# seed a program
self.program_key = seeder_logic.seed(program_model.Program).key()
# seed a user
self.user = user_seeder.seedUser(user_id='test')
# seed a profile
self.profile = profile_seeder.seedProfile(
self.program_key, user=self.user)
def testForNoProfile(self):
"""Tests that no entity is returned when a user does not have a profile."""
profile = profile_logic.getProfileForUsername('other', self.program_key)
self.assertIsNone(profile)
def testForOtherProgram(self):
"""Tests that no entity is returned for a different program."""
other_program = seeder_logic.seed(program_model.Program)
profile = profile_logic.getProfileForUsername('other', other_program.key())
self.assertIsNone(profile)
def testForExistingProfile(self):
"""Tests that profile is returned if exists."""
profile = profile_logic.getProfileForUsername('test', self.program_key)
self.assertEqual(profile.key, self.profile.key)
TEST_SPONSOR_ID = 'sponsor_id'
TEST_PROGRAM_ID = 'program_id'
TEST_PROFILE_ID = 'profile_id'
class GetProfileKeyTest(unittest.TestCase):
"""Unit tests for getProfileKey function."""
def testProfileKey(self):
"""Tests that constructed profile key is correct."""
key = profile_logic.getProfileKey(
TEST_SPONSOR_ID, TEST_PROGRAM_ID, TEST_PROFILE_ID)
self.assertEqual(
key.id(),
'%s/%s/%s' % (TEST_SPONSOR_ID, TEST_PROGRAM_ID, TEST_PROFILE_ID))
self.assertEqual(key.kind(), ndb_profile_model.Profile._get_kind())
self.assertEqual(key.parent().id(), TEST_PROFILE_ID)
self.assertEqual(key.parent().kind(), user_model.User._get_kind())
TEST_FIRST_NAME = 'First'
TEST_LAST_NAME = 'Last'
TEST_PUBLIC_NAME = 'Public Name'
TEST_PHOTO_URL = 'http://www.test.photo.url.com'
TEST_BIRTH_DATE = datetime.date(1990, 1, 1)
TEST_STREET = 'Test street'
TEST_CITY = 'Test city'
TEST_COUNTRY = 'United States'
TEST_PROVINCE = 'California'
TEST_POSTAL_CODE = '90000'
TEST_RESIDENTIAL_ADDRESS = address_model.Address(
street=TEST_STREET, city=TEST_CITY, country=TEST_COUNTRY,
province=TEST_PROVINCE, postal_code=TEST_POSTAL_CODE)
TEST_PROFILE_PROPERTIES = {
'first_name': TEST_FIRST_NAME,
'last_name': TEST_LAST_NAME,
'public_name': TEST_PUBLIC_NAME,
'photo_url': TEST_PHOTO_URL,
'birth_date': TEST_BIRTH_DATE,
'residential_address': TEST_RESIDENTIAL_ADDRESS,
}
TEST_STUDENT_DATA = {'education': education_seeder.seedEducation()}
class CreateProfileTest(unittest.TestCase):
"""Unit tests for createProfile function."""
def setUp(self):
"""See unittest.TestCase.setUp for specification."""
self.user = user_seeder.seedUser()
self.program = program_seeder.seedProgram()
def testProfileCreated(self):
"""Tests that profile entity is created."""
result = profile_logic.createProfile(
self.user.key, self.program.key(), TEST_PROFILE_PROPERTIES,
self.program.timeline)
# check that profile is returned
self.assertTrue(result)
# check that profile is persisted
profile = result.extra.key.get()
self.assertIsNotNone(profile)
# check properties
self.assertEqual(
profile.key.id(),
'%s/%s' % (self.program.key().name(), self.user.key.id()))
self.assertEqual(profile.program.to_old_key(), self.program.key())
self.assertEqual(profile.first_name, TEST_FIRST_NAME)
self.assertEqual(profile.last_name, TEST_LAST_NAME)
self.assertEqual(profile.photo_url, TEST_PHOTO_URL)
self.assertEqual(profile.birth_date, TEST_BIRTH_DATE)
self.assertEquals(
time_utils.getAge(TEST_BIRTH_DATE, datetime.date.today()), profile.age)
self.assertEqual(profile.residential_address.street, TEST_STREET)
self.assertEqual(profile.residential_address.city, TEST_CITY)
self.assertEqual(profile.residential_address.country, TEST_COUNTRY)
self.assertEqual(profile.residential_address.province, TEST_PROVINCE)
self.assertEqual(profile.residential_address.postal_code, TEST_POSTAL_CODE)
def testBirthDateNotStoredWithAgeOnly(self):
"""Tests that profile entity is created with persist_age_only parameter."""
result = profile_logic.createProfile(
self.user.key, self.program.key(), TEST_PROFILE_PROPERTIES,
self.program.timeline, persist_age_only=True)
# check that birth date is not stored
profile = result.extra.key.get()
self.assertIsNone(profile.birth_date)
self.assertEquals(
time_utils.getAge(TEST_BIRTH_DATE, datetime.date.today()), profile.age)
def testBirthDateTakesPrecedenceOverAge(self):
"""Tests that correct age is computed based on the birth date."""
# supply age that does not correspond to the birth date
properties = TEST_PROFILE_PROPERTIES.copy()
properties['age'] = (
time_utils.getAge(TEST_BIRTH_DATE, datetime.date.today()) + 99)
result = profile_logic.createProfile(
self.user.key, self.program.key(), TEST_PROFILE_PROPERTIES,
self.program.timeline, persist_age_only=False)
# check that birth date and age are correct
profile = result.extra.key.get()
self.assertEqual(profile.birth_date, TEST_BIRTH_DATE)
self.assertEqual(
time_utils.getAge(TEST_BIRTH_DATE, datetime.date.today()), profile.age)
@mock.patch.object(
profile_logic, 'isOrgMemberToStudentConversionEligible',
return_value=rich_bool.FALSE)
def testProfileExistsAndConversionNotEligible(self, mock_func):
"""Tests that second profile is not created for same user and program."""
# seed a profile
profile_seeder.seedProfile(self.program.key(), user=self.user)
result = profile_logic.createProfile(
self.user.key, self.program.key(), TEST_PROFILE_PROPERTIES,
self.program.timeline)
self.assertFalse(result)
self.assertEqual(result.extra, profile_logic.PROFILE_EXISTS)
@mock.patch.object(
profile_logic, 'isOrgMemberToStudentConversionEligible',
return_value=rich_bool.TRUE)
def testProfileExistsAndConversionEligible(self, mock_func):
"""Tests that a student profile is created when conversion is eligible."""
# seed an organization member profile
profile = profile_seeder.seedProfile(self.program.key(), user=self.user)
# check for organization member to organization member conversion
result = profile_logic.createProfile(
self.user.key, self.program.key(), TEST_PROFILE_PROPERTIES,
self.program.timeline)
self.assertFalse(result)
# check for organization member to student conversion
profile_properties = TEST_PROFILE_PROPERTIES.copy()
profile_properties['student_data'] = TEST_STUDENT_DATA
result = profile_logic.createProfile(
self.user.key, self.program.key(), profile_properties,
self.program.timeline)
self.assertTrue(result)
# check that the newly created profile has the same key
self.assertEqual(profile.key, result.extra.key)
# check that the newly created profile is a student
self.assertTrue(result.extra.is_student)
OTHER_TEST_FIRST_NAME = 'Other First'
OTHER_TEST_LAST_NAME = 'Other Last'
OTHER_TEST_PUBLIC_NAME = 'Other Public Name'
OTHER_TEST_PHOTO_URL = 'http://www.other.test.photo.url.com'
OTHER_TEST_BIRTH_DATE = datetime.date(1991, 1, 1)
OTHER_TEST_STREET = 'Test other street'
OTHER_TEST_CITY = 'Test city'
OTHER_TEST_COUNTRY = 'United States'
OTHER_TEST_PROVINCE = 'Alaska'
OTHER_TEST_POSTAL_CODE = '99503'
OTHER_TEST_RESIDENTIAL_ADDRESS = address_model.Address(
street=OTHER_TEST_STREET, city=OTHER_TEST_CITY, country=OTHER_TEST_COUNTRY,
province=OTHER_TEST_PROVINCE, postal_code=OTHER_TEST_POSTAL_CODE)
OTHER_TEST_PROFILE_PROPERTIES = {
'first_name': OTHER_TEST_FIRST_NAME,
'last_name': OTHER_TEST_LAST_NAME,
'public_name': OTHER_TEST_PUBLIC_NAME,
'photo_url': OTHER_TEST_PHOTO_URL,
'birth_date': OTHER_TEST_BIRTH_DATE,
'residential_address': OTHER_TEST_RESIDENTIAL_ADDRESS,
}
class EditProfileTest(unittest.TestCase):
"""Unit tests for editProfile function."""
def setUp(self):
"""See unittest.TestCase.setUp for specification."""
self.user = user_seeder.seedUser()
self.program = program_seeder.seedProgram()
self.profile_key = ndb.Key(
user_model.User._get_kind(), self.user.key.id(),
ndb_profile_model.Profile._get_kind(),
'%s/%s' % (self.program.key().name(), self.user.key.id()))
def testProfileDoesNotExist(self):
"""Tests that error is raised when a profile does not exist."""
result = profile_logic.editProfile(
self.profile_key, TEST_PROFILE_PROPERTIES)
self.assertFalse(result)
self.assertEqual(
result.extra,
profile_logic.PROFILE_DOES_NOT_EXIST % self.profile_key.id())
def testProfileUpdated(self):
"""Tests that profile properties are updated properly."""
# seed a profile
profile = profile_seeder.seedProfile(self.program.key(), user=self.user)
result = profile_logic.editProfile(
profile.key, OTHER_TEST_PROFILE_PROPERTIES)
self.assertTrue(result)
# check that updated profile is persisted
profile = result.extra.key.get()
self.assertIsNotNone(profile)
# check properties
self.assertEqual(
profile.key.id(),
'%s/%s' % (self.program.key().name(), self.user.key.id()))
self.assertEqual(profile.program.to_old_key(), self.program.key())
self.assertEqual(profile.first_name, OTHER_TEST_FIRST_NAME)
self.assertEqual(profile.last_name, OTHER_TEST_LAST_NAME)
self.assertEqual(profile.photo_url, OTHER_TEST_PHOTO_URL)
self.assertEqual(profile.birth_date, OTHER_TEST_BIRTH_DATE)
self.assertEqual(profile.residential_address.street, OTHER_TEST_STREET)
self.assertEqual(profile.residential_address.city, OTHER_TEST_CITY)
self.assertEqual(profile.residential_address.country, OTHER_TEST_COUNTRY)
self.assertEqual(profile.residential_address.province, OTHER_TEST_PROVINCE)
self.assertEqual(
profile.residential_address.postal_code, OTHER_TEST_POSTAL_CODE)
# NOTE: Please do not make this number less than five because five is the limit
# of entity groups per XG transaction. The test below should make sure that
# number of recipients is not constrained by this limit.
_NUMBER_OF_ORG_MEMBERS = 6
class DispatchOrgMemberWelcomeEmailTest(test_utils.DjangoTestCase):
"""Unit tests for dispatchOrgMemberWelcomeEmail function."""
def setUp(self):
self.init()
def testOrgMemberWelcomeEmailSent(self):
"""Tests that welcome email is sent properly."""
program = program_seeder.seedProgram()
program_messages = program_seeder.seedProgramMessages(
program_key=program.key())
profiles = [
profile_seeder.seedProfile(program.key())
for _ in range(_NUMBER_OF_ORG_MEMBERS)]
@ndb.transactional
def txn():
profile_logic.dispatchOrgMemberWelcomeEmail(
profiles, program, program_messages)
txn()
for profile in profiles:
self.assertEmailSent(
to=profile.contact.email,
subject=profile_logic._DEF_ORG_MEMBER_WELCOME_MAIL_SUBJECT)
TEST_NOTIFICATION_SETTINGS_PROPERTIES = {
'org_connections': True,
'user_connections': False,
'org_new_proposals': False,
'org_update_proposals': False,
'org_proposal_comments': False,
'task_updates': True,
}
class CreatetNotificationSettingsTest(unittest.TestCase):
"""Unit tests for createtNotificationSettings function."""
def testNotificationSettingsCreated(self):
"""Tests that notification settings is created properly if data is valid."""
notification_settings = profile_logic.createtNotificationSettings(
TEST_NOTIFICATION_SETTINGS_PROPERTIES)
# check properties
self.assertEqual(
notification_settings.to_dict(), TEST_NOTIFICATION_SETTINGS_PROPERTIES)
class EnrollmentFormSubmittedTest(test_utils.SoCTestCase):
"""Unit tests for enrollmentFormSubmitted function."""
def setUp(self):
"""See unittest.TestCase.setUp for specification."""
self.init()
self.program = program_seeder.seedProgram()
def testEnrollmentFormSubmitted(self):
"""Tests that True is returned when enrollment form is submitted."""
student_data_properties = {'enrollment_form': self.createBlob('unused')}
profile = profile_seeder.seedStudent(
self.program, student_data_properties=student_data_properties)
self.assertTrue(profile_logic.enrollmentFormSubmitted(profile))
def testEnrollmentFormNotSubmitted(self):
"""Tests that False is returned when enrollment form is not submitted."""
profile = profile_seeder.seedStudent(self.program)
self.assertFalse(profile_logic.enrollmentFormSubmitted(profile))
class RequestProfileDeletionTest(unittest.TestCase):
"""Unit tests for requestProfileDeletion function."""
@mock.patch('google.appengine.api.mail.send_mail')
def testEmailSent(self, mock_func):
"""Tests that email is sent to application administrators."""
program = program_seeder.seedProgram()
user = user_seeder.seedUser(host_for=[program])
profile = profile_seeder.seedProfile(program.key(), user=user)
profile_logic.requestProfileDeletion(profile)
# checks that the function to send an email to application
# administrators has been invoked
self.assertTrue(mock_func.called)
def testProfileStatusUpdated(self):
"""Tests that status of the profile is updated correctly."""
program = program_seeder.seedProgram()
user = user_seeder.seedUser(host_for=[program])
profile = profile_seeder.seedProfile(program.key(), user=user)
profile_logic.requestProfileDeletion(profile)
profile = profile.key.get()
self.assertEqual(
ndb_profile_model.Status.DELETION_REQUESTED, profile.status)
class IsOrgMemberToStudentConversionEligibleTest(unittest.TestCase):
"""Unit tests for isOrgMemberToStudentConversionEligible function."""
def setUp(self):
"""See unittest.TestCase.setUp for specification."""
self.program = program_seeder.seedProgram()
self.timeline = self.program.timeline
self.timeline_helper = timeline_utils.TimelineHelper(self.timeline, None)
def testConversionEligible(self):
"""Tests if role conversion is eligible."""
self.timeline_helper.studentSignup()
profile = profile_seeder.seedProfile(self.program.key())
result = profile_logic.isOrgMemberToStudentConversionEligible(
profile, self.timeline)
self.assertTrue(result)
def testHasRole(self):
"""Tests that conversion is not eligible if the user has actual role."""
self.timeline_helper.studentSignup()
org = org_utils.seedOrganization(self.program.key())
profile = profile_seeder.seedProfile(
self.program.key(), mentor_for=[org.key])
result = profile_logic.isOrgMemberToStudentConversionEligible(
profile, self.timeline)
self.assertFalse(result)
self.assertEqual(
profile_logic.OrgMemberToStudentConversionError.has_role, result.extra)
def testIsStudent(self):
"""Tests that conversion is not eligible if the user is a student."""
self.timeline_helper.studentSignup()
profile = profile_seeder.seedStudent(self.program)
result = profile_logic.isOrgMemberToStudentConversionEligible(
profile, self.timeline)
self.assertFalse(result)
self.assertEqual(
profile_logic.OrgMemberToStudentConversionError.is_student,
result.extra)
def testBeforeStudentSignup(self):
"""Tests that conversion is not eligible before student signup."""
self.timeline_helper.orgsAnnounced()
profile = profile_seeder.seedProfile(self.program.key())
result = profile_logic.isOrgMemberToStudentConversionEligible(
profile, self.timeline)
self.assertFalse(result)
self.assertEqual(
profile_logic.OrgMemberToStudentConversionError.before_student_signup,
result.extra)
def testAfterStudentSignup(self):
"""Tests that conversion is not eligible after student signup."""
self.timeline_helper.studentSignup()
self.timeline.student_signup_end = timeline_utils.past()
profile = profile_seeder.seedProfile(self.program.key())
result = profile_logic.isOrgMemberToStudentConversionEligible(
profile, self.timeline)
self.assertFalse(result)
self.assertEqual(
profile_logic.OrgMemberToStudentConversionError.after_student_signup,
result.extra)