blob: f30c01782d9ec4abd4a95eb1213381b5c75ab4ae [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 organization application view."""
import cloudstorage
import mock
import unittest
from django.core.files import uploadedfile
from django import forms as django_forms
from django import http
from google.appengine.api import images
from google.appengine.ext import ndb
from melange.logic import organization as org_logic
from melange.models import connection as connection_model
from melange.models import contact as contact_model
from melange.models import organization as org_model
from melange.models import survey as survey_model
from melange.views import organization as org_view
from seeder import profile as profile_seeder
from seeder import user as user_seeder
from soc.models import licenses
from soc.modules.gsoc.views.helper import request_data
from soc.views import forms
from summerofcode.templates import tabs
from summerofcode.views import org_app as org_app_view
from tests import org_utils
from tests import profile_utils
from tests import test_utils
TEST_ORG_ID = 'test_org_id'
TEST_ORG_NAME = u'Test Org Name'
TEST_BLOG = 'http://www.test.blog.com/'
TEST_DESCRIPTION = u'Test Organization Description'
TEST_TAGS = u'tag one,tag_two,tag 3'
TEST_SINGLE_TAG = u'tag_two'
TEST_LICENSE = licenses.LICENSES[0]
TEST_FACEBOOK = u'http://www.test.facebook.com/'
TEST_FEED_URL = u'http://www.test.feed.com/'
TEST_GOOGLE_PLUS = u'http://www.test.google.plus.com/'
TEST_IDEAS_PAGE = 'http://www.test.ideas.com/'
TEST_IRC_CHANNEL = 'irc://irc.freenode.net/test'
TEST_MAILING_LIST = 'mailinglist@example.com'
TEST_TWITTER = u'http://www.test.twitter.com/'
TEST_WEB_PAGE = u'http://www.web.page.com/'
TEST_IS_VETERAN = True
TEST_ELIGIBLE_COUNTRY = True
TEST_LOGO_IMAGE_PATH = 'tests/images/melange_logo.png'
TEST_LOGO_IMAGE_INVALID_SIZE_PATH = 'tests/images/melange_logo_invalid_size.png'
NUMBER_OF_ACCEPTED_ORGS = 4
def _getOrgLogoEditUrl(org):
"""Returns URL to Edit Organization Logo page.
Args:
org: Organization entity.
Returns:
A string containing the URL to Edit Organization Logo page.
"""
return '/gsoc/org/logo/edit/%s' % org.key.id()
def _getOrgPreferencesEditUrl(org):
"""Returns URL to Edit Organization Preferences page.
Args:
org: Organization entity.
Returns:
A string containing the URL to Edit Organization Preferences page.
"""
return '/gsoc/org/preferences/edit/%s' % org.key.id()
def _getOrgProfileCreateUrl(program):
"""Returns URL to Create Organization Profile page.
Args:
program: Program entity.
Returns:
A string containing the URL to Create Organization Profile page.
"""
return '/gsoc/org/profile/create/%s' % program.key().name()
def _getOrgProfileEditUrl(org):
"""Returns URL to Edit Organization Profile page.
Args:
org: Organization entity.
Returns:
A string containing the URL to Edit Organization Profile page.
"""
return '/gsoc/org/profile/edit/%s' % org.key.id()
def _getOrgApplicationSubmitUrl(org):
"""Returns URL to Submit Organization Application page.
Args:
org: Organization entity.
Returns:
A string containing the URL to Submit Organization Application page.
"""
return '/gsoc/org/application/submit/%s' % org.key.id()
def _getOrgAppShowUrl(org):
"""Returns URL to Organization Application Show page.
Args:
org: Organization entity.
Returns:
A string containing the URL to Organization Application Show page.
"""
return '/gsoc/org/application/show2/%s' % org.key.id()
def _getOrgSurveyResponseShowUrl(org):
"""Returns URL to Organization Survey Response Show page.
Args:
org: Organization entity.
Returns:
A string containing the URL to Organization Survey Response Show page.
"""
return '/gsoc/org/survey_response/show/%s' % org.key.id()
def _getPublicOrgListUrl(program):
"""Returns URL to Public Organization List page.
Args:
program: Program entity.
Returns:
A string containing the URL to Public Organization List page.
"""
return '/gsoc/org/list/public/%s' % program.key().name()
def _getOrgApplicationListPageListUrl(program):
"""Returns URL to Organization Application List page.
Args:
program: Program entity.
Returns:
A string containing the URL to Organization Application List page.
"""
return '/gsoc/org/application/list/%s' % program.key().name()
VALID_POSTDATA = {
'org_id': TEST_ORG_ID,
'name': TEST_ORG_NAME,
'blog': TEST_BLOG,
'description': TEST_DESCRIPTION,
'facebook': TEST_FACEBOOK,
'feed_url': TEST_FEED_URL,
'google_plus': TEST_GOOGLE_PLUS,
'license': TEST_LICENSE,
'ideas_page': TEST_IDEAS_PAGE,
'irc_channel': TEST_IRC_CHANNEL,
'mailing_list': TEST_MAILING_LIST,
'tags': TEST_TAGS,
'twitter': TEST_TWITTER,
'web_page': TEST_WEB_PAGE,
'eligible_country': True
}
# Proposal content which contains dangerous HTML that needs validation
RAW_HTML_DESCRIPTION = """
This is description of organization.
<form method="POST" action="http://www.example.com/"></form>
<p style="background-image: url(www.example.com/some_image.png);">
Another part of the description. Embedded in a paragraph with suspicious style.
</p>
"""
SANITIZED_HTML_DESCRIPTION = """
This is description of organization.
&lt;form method="POST" action="http://www.example.com/"&gt;&lt;/form&gt;
<p style="">
Another part of the description. Embedded in a paragraph with suspicious style.
</p>
""".strip()
class OrgProfileCreatePageTest(test_utils.GSoCDjangoTestCase):
"""Unit tests for OrgProfileCreatePage 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(_getOrgProfileCreateUrl(self.program))
self.assertResponseOK(response)
def testOrgProfileCreated(self):
"""Tests that organization entity is created properly."""
user = user_seeder.seedUser()
profile_utils.loginNDB(user)
profile = profile_seeder.seedProfile(
self.program.key(), user=user, admin_for=[self.org.key])
postdata = {
'org_id': TEST_ORG_ID,
'name': TEST_ORG_NAME,
'blog': TEST_BLOG,
'description': TEST_DESCRIPTION,
'facebook': TEST_FACEBOOK,
'feed_url': TEST_FEED_URL,
'google_plus': TEST_GOOGLE_PLUS,
'license': TEST_LICENSE,
'ideas_page': TEST_IDEAS_PAGE,
'irc_channel': TEST_IRC_CHANNEL,
'mailing_list': TEST_MAILING_LIST,
'tags': TEST_TAGS,
'twitter': TEST_TWITTER,
'web_page': TEST_WEB_PAGE,
'is_veteran': TEST_IS_VETERAN,
'eligible_country': TEST_ELIGIBLE_COUNTRY,
}
response = self.post(
_getOrgProfileCreateUrl(self.program), postdata=postdata)
# check that organization entity has been created
org = ndb.Key(
org_model.Organization._get_kind(),
'%s/%s' % (self.program.key().name(), TEST_ORG_ID)).get()
self.assertIsNotNone(org)
self.assertEqual(org.contact.blog, TEST_BLOG)
self.assertEqual(org.contact.facebook, TEST_FACEBOOK)
self.assertEqual(org.contact.feed_url, TEST_FEED_URL)
self.assertEqual(org.contact.google_plus, TEST_GOOGLE_PLUS)
self.assertEqual(org.contact.irc_channel, TEST_IRC_CHANNEL)
self.assertEqual(org.contact.mailing_list, TEST_MAILING_LIST)
self.assertEqual(org.contact.twitter, TEST_TWITTER)
self.assertEqual(org.contact.web_page, TEST_WEB_PAGE)
self.assertEqual(org.description, TEST_DESCRIPTION)
self.assertEqual(org.ideas_page, TEST_IDEAS_PAGE)
self.assertEqual(org.license, TEST_LICENSE)
self.assertEqual(org.name, TEST_ORG_NAME)
self.assertEqual(org.org_id, TEST_ORG_ID)
self.assertEqual(org.tags, TEST_TAGS.split(','))
self.assertTrue(org.is_veteran)
# check that the client is redirected to update page
self.assertResponseRedirect(response, url=_getOrgApplicationSubmitUrl(org))
# check that a connection with the current user has been started
profile = profile.key.get()
self.assertIn(org.key, profile.admin_for)
connection = connection_model.Connection.query(
connection_model.Connection.organization == org.key,
ancestor=profile.key).get()
self.assertIsNotNone(connection)
self.assertEqual(connection.org_role, connection_model.ORG_ADMIN_ROLE)
self.assertEqual(connection.user_role, connection_model.ROLE)
self.assertFalse(connection.init_by_user)
self.assertTrue(connection.seen_by_org)
self.assertTrue(connection.seen_by_user)
def testInvalidData(self):
"""Tests that organization is not created if data is not valid."""
user = user_seeder.seedUser()
profile_utils.loginNDB(user)
profile_seeder.seedProfile(
self.program.key(), user=user, admin_for=[self.org.key])
# the organization is not from the eligible countries
postdata = VALID_POSTDATA.copy()
postdata['eligible_country'] = False
response = self.post(
_getOrgProfileCreateUrl(self.program), postdata=postdata)
self.assertTrue(response.context['error'])
# the organization with the same org_id already exists
org_utils.seedSOCOrganization(self.program.key(), org_id='duplicate')
postdata = VALID_POSTDATA.copy()
postdata['org_id'] = 'duplicate'
response = self.post(
_getOrgProfileCreateUrl(self.program), postdata=postdata)
self.assertResponseBadRequest(response)
def testDescriptionSanitized(self):
"""Tests that submitted description is sanitized properly."""
user = user_seeder.seedUser()
profile_utils.loginNDB(user)
profile_seeder.seedProfile(
self.program.key(), user=user, admin_for=[self.org.key])
postdata = VALID_POSTDATA.copy()
postdata['description'] = RAW_HTML_DESCRIPTION
response = self.post(
_getOrgProfileCreateUrl(self.program), postdata=postdata)
# check that the description is sanitized
org = ndb.Key(
org_model.Organization._get_kind(),
'%s/%s' % (self.program.key().name(), TEST_ORG_ID)).get()
self.assertEqual(SANITIZED_HTML_DESCRIPTION, org.description)
OTHER_TEST_BLOG = 'http://www.other.test.blog.com/'
OTHER_TEST_DESCRIPTION = u'Other Organization Description'
OTHER_TEST_FACEBOOK = u'http://www.other.test.facebook.com/'
OTHER_TEST_NAME = 'Other Org Name'
OTHER_TEST_FEED_URL = u'http://www.other.test.feed.com/'
OTHER_TEST_GOOGLE_PLUS = 'http://www.other.test.google.plus.com/'
OTHER_TEST_IDEAS_PAGE = 'http://www.other.ideas.page.com/'
OTHER_TEST_IRC_CHANNEL = 'irc://irc.freenode.net/other'
OTHER_TEST_LICENSE = licenses.LICENSES[-1]
OTHER_TEST_MAILING_LIST = 'othermailinglist@example.com'
OTHER_TEST_TWITTER = u'http://www.other.test.twitter.com/'
OTHER_TEST_TAGS = u'other tag one,other_tag_two,other tag 3'
OTHER_TEST_WEB_PAGE = u'http://www.other.web.page.com/'
OTHER_TEST_IS_VETERAN = False
OTHER_TEST_LOGO_IMAGE_PATH = 'tests/images/melange_logo_2.png'
class OrgProfileEditPageTest(test_utils.GSoCDjangoTestCase):
"""Unit tests for OrgProfileEditPage class."""
def setUp(self):
"""See unittest.TestCase.setUp for specification."""
self.init()
contact = contact_model.Contact(mailing_list=TEST_MAILING_LIST)
self.org = org_utils.seedSOCOrganization(
self.program.key(), org_id=TEST_ORG_ID, name=TEST_ORG_NAME,
ideas_page=TEST_IDEAS_PAGE, tags=TEST_TAGS.split(','),
contact=contact, is_veteran=not OTHER_TEST_IS_VETERAN)
self.app_response = survey_model.SurveyResponse(parent=self.org.key)
self.app_response.put()
def testPageLoads(self):
"""Tests that page loads properly."""
user = user_seeder.seedUser()
profile_utils.loginNDB(user)
profile_seeder.seedProfile(
self.program.key(), user=user, admin_for=[self.org.key])
response = self.get(_getOrgProfileEditUrl(self.org))
self.assertResponseOK(response)
def testOrgProfileUpdated(self):
"""Tests that organization entity is updated correctly."""
user = user_seeder.seedUser()
profile_utils.loginNDB(user)
profile_seeder.seedProfile(
self.program.key(), user=user, admin_for=[self.org.key])
# check that mutable properties are updated
postdata = {
'blog': OTHER_TEST_BLOG,
'description': OTHER_TEST_DESCRIPTION,
'facebook': OTHER_TEST_FACEBOOK,
'feed_url': OTHER_TEST_FEED_URL,
'google_plus': OTHER_TEST_GOOGLE_PLUS,
'ideas_page': OTHER_TEST_IDEAS_PAGE,
'irc_channel': OTHER_TEST_IRC_CHANNEL,
'license': OTHER_TEST_LICENSE,
'mailing_list': OTHER_TEST_MAILING_LIST,
'name': OTHER_TEST_NAME,
'tags': OTHER_TEST_TAGS,
'twitter': OTHER_TEST_TWITTER,
'web_page': OTHER_TEST_WEB_PAGE,
'is_veteran': OTHER_TEST_IS_VETERAN,
}
response = self.post(_getOrgProfileEditUrl(self.org), postdata=postdata)
self.assertResponseRedirect(response, url=_getOrgProfileEditUrl(self.org))
# check that organization entity has been updated
org = ndb.Key(
org_model.Organization._get_kind(),
'%s/%s' % (self.program.key().name(), TEST_ORG_ID)).get()
self.assertEqual(org.contact.blog, OTHER_TEST_BLOG)
self.assertEqual(org.contact.mailing_list, OTHER_TEST_MAILING_LIST)
self.assertEqual(org.description, OTHER_TEST_DESCRIPTION)
self.assertEqual(org.contact.facebook, OTHER_TEST_FACEBOOK)
self.assertEqual(org.contact.google_plus, OTHER_TEST_GOOGLE_PLUS)
self.assertEqual(org.ideas_page, OTHER_TEST_IDEAS_PAGE)
self.assertEqual(org.contact.irc_channel, OTHER_TEST_IRC_CHANNEL)
self.assertEqual(org.license, OTHER_TEST_LICENSE)
self.assertEqual(org.name, OTHER_TEST_NAME)
self.assertEqual(org.tags, OTHER_TEST_TAGS.split(','))
self.assertEqual(org.contact.twitter, OTHER_TEST_TWITTER)
self.assertEqual(org.contact.web_page, OTHER_TEST_WEB_PAGE)
# check that organization ID is not updated even if it is in POST data
postdata = {
'blog': OTHER_TEST_BLOG,
'description': OTHER_TEST_DESCRIPTION,
'facebook': OTHER_TEST_FACEBOOK,
'feed_url': OTHER_TEST_FEED_URL,
'google_plus': OTHER_TEST_GOOGLE_PLUS,
'ideas_page': OTHER_TEST_IDEAS_PAGE,
'license': OTHER_TEST_LICENSE,
'org_id': 'other_org_id',
'name': TEST_ORG_NAME,
'twitter': OTHER_TEST_TWITTER,
'web_page': OTHER_TEST_WEB_PAGE,
}
response = self.post(_getOrgProfileEditUrl(self.org), postdata=postdata)
self.assertResponseRedirect(response, url=_getOrgProfileEditUrl(self.org))
# check that organization entity has been updated
org = ndb.Key(
org_model.Organization._get_kind(),
'%s/%s' % (self.program.key().name(), TEST_ORG_ID)).get()
self.assertEqual(org.org_id, TEST_ORG_ID)
def testOrgsTabs(self):
"""Tests that correct organization related tabs are present in context."""
user = user_seeder.seedUser()
profile_utils.loginNDB(user)
profile_seeder.seedProfile(
self.program.key(), user=user, admin_for=[self.org.key])
response = self.get(_getOrgProfileEditUrl(self.org))
# 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.ORG_PROFILE_TAB_ID)
def testDescriptionSanitized(self):
"""Tests that submitted description is sanitized properly."""
user = user_seeder.seedUser()
profile_utils.loginNDB(user)
profile_seeder.seedProfile(
self.program.key(), user=user, admin_for=[self.org.key])
postdata = VALID_POSTDATA.copy()
postdata['description'] = RAW_HTML_DESCRIPTION
response = self.post(_getOrgProfileEditUrl(self.org), postdata=postdata)
# check that the description is sanitized
org = self.org.key.get()
self.assertEqual(SANITIZED_HTML_DESCRIPTION, org.description)
class OrgApplicationSubmitPageTest(test_utils.GSoCDjangoTestCase):
"""Unit tests for OrgApplicationSubmitPage class."""
def setUp(self):
"""See unittest.TestCase.setUp for specification."""
self.init()
self.org = org_utils.seedSOCOrganization(self.program.key())
def testPageLoads(self):
"""Tests that page loads properly."""
user = user_seeder.seedUser()
profile_utils.loginNDB(user)
profile_seeder.seedProfile(
self.program.key(), user=user, admin_for=[self.org.key])
response = self.get(_getOrgApplicationSubmitUrl(self.org))
self.assertResponseOK(response)
def testApplicationCreated(self):
"""Tests that organization application is created properly."""
user = user_seeder.seedUser()
profile_utils.loginNDB(user)
profile_seeder.seedProfile(
self.program.key(), user=user, admin_for=[self.org.key])
# TODO(daniel): submit actual responses in POST data
response = self.post(_getOrgApplicationSubmitUrl(self.org))
self.assertResponseRedirect(response)
# check that application has been created
application = survey_model.SurveyResponse.query(ancestor=self.org.key).get()
self.assertIsNotNone(application)
def testOrgsTabs(self):
"""Tests that correct organization related tabs are present in context."""
user = user_seeder.seedUser()
profile_utils.loginNDB(user)
profile_seeder.seedProfile(
self.program.key(), user=user, admin_for=[self.org.key])
response = self.get(_getOrgApplicationSubmitUrl(self.org))
# 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.ORG_APP_RESPONSE_TAB_ID)
class OrgAppShowPageTest(test_utils.GSoCDjangoTestCase):
"""Unit tests for OrgAppShowPage class."""
def setUp(self):
"""See unittest.TestCase.setUp for specification."""
self.init()
self.org = org_utils.seedSOCOrganization(
self.program.key(), name=TEST_ORG_NAME)
self.app_response = survey_model.SurveyResponse(parent=self.org.key)
self.app_response.put()
def testPageLoads(self):
"""Tests that page loads properly."""
user = user_seeder.seedUser(host_for=[self.program])
profile_utils.loginNDB(user)
response = self.get(_getOrgAppShowUrl(self.org))
self.assertResponseOK(response)
def testPostMethodNotAllowed(self):
"""Tests that POST method is not permitted."""
user = user_seeder.seedUser(host_for=[self.program])
profile_utils.loginNDB(user)
response = self.post(_getOrgAppShowUrl(self.org))
self.assertResponseMethodNotAllowed(response)
class SurveyResponseShowPageTest(test_utils.GSoCDjangoTestCase):
"""Unit tests for SurveyResponseShowPage class."""
def setUp(self):
"""See unittest.TestCase.setUp for specification."""
self.init()
self.org = org_utils.seedSOCOrganization(
self.program.key(), name=TEST_ORG_NAME)
self.app_response = survey_model.SurveyResponse(parent=self.org.key)
self.app_response.put()
def testPageLoads(self):
"""Tests that page loads properly."""
user = user_seeder.seedUser()
profile_utils.loginNDB(user)
profile_seeder.seedProfile(
self.program.key(), user=user, admin_for=[self.org.key])
response = self.get(_getOrgSurveyResponseShowUrl(self.org))
self.assertResponseOK(response)
def testPostMethodNotAllowed(self):
"""Tests that POST method is not permitted."""
user = user_seeder.seedUser()
profile_utils.loginNDB(user)
profile_seeder.seedProfile(
self.program.key(), user=user, admin_for=[self.org.key])
response = self.post(_getOrgSurveyResponseShowUrl(self.org))
self.assertResponseMethodNotAllowed(response)
class PublicOrganizationListPageTest(test_utils.GSoCDjangoTestCase):
"""Unit tests for PublicOrganizationListPage class."""
def setUp(self):
"""See unittest.TestCase.setUp for specification."""
self.init()
def testPageLoads(self):
"""Tests that page loads properly."""
response = self.get(_getPublicOrgListUrl(self.program))
self.assertResponseOK(response)
def testOrgListWithTagFiltration(self):
"""Tests that filtered list of organizations is visible."""
# seed some organizations with accepted status and some tags
for _ in range(NUMBER_OF_ACCEPTED_ORGS):
org = org_utils.seedSOCOrganization(self.program.key(),
tags=OTHER_TEST_TAGS.split(','), status=org_model.Status.ACCEPTED)
# seed an organization with test tag
other_org = org_utils.seedSOCOrganization(self.program.key(),
tags=TEST_TAGS.split(','), status=org_model.Status.ACCEPTED)
# check that only orgs which have single test tag in their tags are listed
data = self.getListData(_getPublicOrgListUrl(self.program), 0)
dataWithTag = self.getListData(
_getPublicOrgListUrl(self.program), 0, tag=TEST_SINGLE_TAG)
self.assertNotEqual(len(dataWithTag), len(data))
class OrgApplicationListPageTest(test_utils.GSoCDjangoTestCase):
"""Unit tests for OrgApplicationListPage 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)
response = self.get(_getOrgApplicationListPageListUrl(self.program))
self.assertResponseOK(response)
class _MockView(object):
"""Simple request handler to be used as a callback for other handlers."""
def get(self, data, access, mutator):
"""See base.RequestHandler.get for specification."""
pass
_NUMBER_OF_ORG_ADMINS = 2
class ApplyOrgAdmissionDecisionHandlerTest(test_utils.GSoCDjangoTestCase):
"""Unit tests for ApplyOrgAdmissionDecisionHandler class."""
def setUp(self):
"""See unittest.TestCase.setUp for specification."""
self.init()
self.pre_accepted_org = org_utils.seedOrganization(
self.program.key(), status=org_model.Status.PRE_ACCEPTED)
org_utils.seedApplication(self.pre_accepted_org.key, self.org_app.key())
self.pre_rejected_org = org_utils.seedOrganization(
self.program.key(), status=org_model.Status.PRE_REJECTED)
org_utils.seedApplication(self.pre_rejected_org.key, self.org_app.key())
self.accepted_org = org_utils.seedOrganization(
self.program.key(), status=org_model.Status.ACCEPTED)
org_utils.seedApplication(self.accepted_org.key, self.org_app.key())
self.rejected_org = org_utils.seedOrganization(
self.program.key(), status=org_model.Status.REJECTED)
org_utils.seedApplication(self.rejected_org.key, self.org_app.key())
self.applying_org = org_utils.seedOrganization(
self.program.key(), status=org_model.Status.APPLYING)
org_utils.seedApplication(self.applying_org.key, self.org_app.key())
def testOrganizationStatusIsUpdated(self):
"""Tests that organization admission decisions are applied correctly."""
kwargs = {
'sponsor': self.sponsor.key().name(),
'program': self.program.program_id,
}
request = http.HttpRequest()
data = request_data.RequestData(request, None, kwargs)
handler = org_view.ApplyOrgAdmissionDecisionHandler(
_MockView(), url='unused-url')
handler.handle(data, None, None)
self.executeMapReduceJobs()
# check that status have been changed for pre_accepted and pre_rejected orgs
self.assertEqual(
self.pre_accepted_org.key.get().status, org_model.Status.ACCEPTED)
self.assertEqual(
self.pre_rejected_org.key.get().status, org_model.Status.REJECTED)
# check that status for other orgs have not changed
self.assertEqual(
self.accepted_org.key.get().status, org_model.Status.ACCEPTED)
self.assertEqual(
self.rejected_org.key.get().status, org_model.Status.REJECTED)
self.assertEqual(
self.applying_org.key.get().status, org_model.Status.APPLYING)
def testEmailIsSent(self):
"""Tests that acceptance and rejection emails are sent."""
# seed a couple of organization administrators for both organizations
addresses_for_accept_email = []
addresses_for_reject_email = []
for _ in range(_NUMBER_OF_ORG_ADMINS):
profile = profile_seeder.seedProfile(
self.program.key(), admin_for=[self.pre_accepted_org.key])
addresses_for_accept_email.append(profile.contact.email)
profile = profile_seeder.seedProfile(
self.program.key(), admin_for=[self.pre_rejected_org.key])
addresses_for_reject_email.append(profile.contact.email)
# finalize decision and execute all MapReduce jobs
kwargs = {
'sponsor': self.sponsor.key().name(),
'program': self.program.program_id,
}
request = http.HttpRequest()
data = request_data.RequestData(request, None, kwargs)
handler = org_view.ApplyOrgAdmissionDecisionHandler(
_MockView(), url='unused-url')
handler.handle(data, None, None)
self.executeMapReduceJobs()
# check that emails have been sent
for email_address in addresses_for_accept_email:
self.assertEmailSent(bcc=email_address)
for email_address in addresses_for_reject_email:
self.assertEmailSent(bcc=email_address)
class OrgLogoEditPageTest(test_utils.GSoCDjangoTestCase):
"""Unit tests for OrgLogoEditPage class."""
def setUp(self):
"""See unittest.TestCase.testUp for specification."""
self.init()
self.org = org_utils.seedSOCOrganization(
self.program.key(), name=TEST_ORG_NAME)
def testPageLoads(self):
"""Tests that page loads properly."""
user = user_seeder.seedUser()
profile_utils.loginNDB(user)
profile_seeder.seedProfile(
self.program.key(), user=user, admin_for=[self.org.key])
response = self.get(_getOrgLogoEditUrl(self.org))
self.assertResponseOK(response)
def testOrgLogoImageSet(self):
"""Tests that organization logo image is set properly."""
user = user_seeder.seedUser()
profile_utils.loginNDB(user)
profile_seeder.seedProfile(
self.program.key(), user=user, admin_for=[self.org.key])
# set logo image
with open(TEST_LOGO_IMAGE_PATH, 'rb') as logo_image_file:
postdata = {'logo_image': logo_image_file}
response = self.post(
_getOrgLogoEditUrl(self.org), postdata=postdata)
self.assertResponseRedirect(response, url=_getOrgLogoEditUrl(self.org))
logo_image_file.seek(0)
expected_size = len(logo_image_file.read())
# check that logo image is set
org = self.org.key.get()
self.assertIsNotNone(org.logo_path)
# check that the content is saved and that it has a proper size
with cloudstorage.open(org.logo_path) as logo_object:
self.assertEqual(expected_size, len(logo_object.read()))
def testOrgLogoImageUpdated(self):
"""Tests that organization logo image is updated properly."""
user = user_seeder.seedUser()
profile_utils.loginNDB(user)
profile_seeder.seedProfile(
self.program.key(), user=user, admin_for=[self.org.key])
# set an existing logo file
with open(TEST_LOGO_IMAGE_PATH, 'r') as logo_image_file:
uploaded_file = uploadedfile.UploadedFile(logo_image_file)
org_logic.setOrgLogo(self.org.key, uploaded_file)
org = self.org.key.get()
old_path = org.logo_path
# update logo image
with open(OTHER_TEST_LOGO_IMAGE_PATH, 'r') as logo_image_file:
postdata = {'logo_image': logo_image_file}
response = self.post(
_getOrgLogoEditUrl(self.org), postdata=postdata)
self.assertResponseRedirect(response, url=_getOrgLogoEditUrl(self.org))
# check that logo image is set and updated
org = self.org.key.get()
self.assertIsNotNone(org.logo_path)
self.assertNotEqual(old_path, org.logo_path)
# check that the old file is not stored anymore
with self.assertRaises(cloudstorage.NotFoundError):
cloudstorage.open(old_path)
@mock.patch.object(
org_logic, 'setOrgLogo', side_effect=images.TransformationError)
def testErrorWhileLogoIsSet(self, mock_func):
"""Tests that errors are handled properly."""
user = user_seeder.seedUser()
profile_utils.loginNDB(user)
profile_seeder.seedProfile(
self.program.key(), user=user, admin_for=[self.org.key])
# update logo image
with open(OTHER_TEST_LOGO_IMAGE_PATH, 'r') as logo_image_file:
postdata = {'logo_image': logo_image_file}
response = self.post(
_getOrgLogoEditUrl(self.org), postdata=postdata)
self.assertResponseBadRequest(response)
def testInvalidData(self):
"""Tests that organization logo is not set if the image is not valid."""
user = user_seeder.seedUser()
profile_utils.loginNDB(user)
profile_seeder.seedProfile(
self.program.key(), user=user, admin_for=[self.org.key])
# uploaded image has invalid size
with open(TEST_LOGO_IMAGE_INVALID_SIZE_PATH, 'rb') as logo_image_file:
postdata = {'logo_image': logo_image_file}
response = self.post(
_getOrgLogoEditUrl(self.org), postdata=postdata)
self.assertTrue(response.context['error'])
self.assertIn(
forms.ImageField.default_error_messages['invalid_dimensions'] % (
200, 200, # these are dimensions of the invalid image
org_view.LOGO_IMAGE_WIDTH, org_view.LOGO_IMAGE_HEIGHT),
response.context['forms'][0].errors['logo_image'])
TEST_MAX_SCORE = 7
TEST_SLOT_REQUEST_MIN = 3
TEST_SLOT_REQUEST_MAX = 10
TEST_CONTRIB_TEMPLATE = u'Test Application Template'
TEST_SCORING_ENABLED = False
TEST_ACCEPTED_STUDENTS_MESSAGE = u'Test Accepted Students Message'
TEST_REJECTED_STUDENTS_MESSAGE = u'Test Rejected Students Message'
TEST_EXTRA_FIELDS = ['one field', 'second field', 'third field']
class OrgPreferencesEditPageTest(test_utils.GSoCDjangoTestCase):
"""Unit tests for OrgPreferencesEditPage class."""
def setUp(self):
"""See unittest.TestCase.testUp for specification."""
self.init()
self.org = org_utils.seedSOCOrganization(
self.program.key(), name=TEST_ORG_NAME,
status=org_model.Status.ACCEPTED)
def testPageLoads(self):
"""Tests that page loads properly."""
user = user_seeder.seedUser()
profile_utils.loginNDB(user)
profile_seeder.seedProfile(
self.program.key(), user=user, admin_for=[self.org.key])
response = self.get(_getOrgPreferencesEditUrl(self.org))
self.assertResponseOK(response)
def testOrgPreferencesUpdated(self):
"""Tests that organization entity is updated correctly."""
user = user_seeder.seedUser()
profile_utils.loginNDB(user)
profile_seeder.seedProfile(
self.program.key(), user=user, admin_for=[self.org.key])
postdata = {
'slot_request_min': unicode(TEST_SLOT_REQUEST_MIN),
'slot_request_max': unicode(TEST_SLOT_REQUEST_MAX),
'max_score': unicode(TEST_MAX_SCORE),
'contrib_template': TEST_CONTRIB_TEMPLATE,
'scoring_enabled': TEST_SCORING_ENABLED,
'accepted_students_message': TEST_ACCEPTED_STUDENTS_MESSAGE,
'rejected_students_message': TEST_REJECTED_STUDENTS_MESSAGE,
'extra_fields': '\n'.join(TEST_EXTRA_FIELDS),
}
response = self.post(_getOrgPreferencesEditUrl(self.org), postdata=postdata)
self.assertResponseRedirect(
response, url=_getOrgPreferencesEditUrl(self.org))
org = self.org.key.get()
self.assertEqual(org.max_score, TEST_MAX_SCORE)
self.assertEqual(org.slot_request_min, TEST_SLOT_REQUEST_MIN)
self.assertEqual(org.slot_request_max, TEST_SLOT_REQUEST_MAX)
self.assertEqual(org.contrib_template, TEST_CONTRIB_TEMPLATE)
self.assertEqual(org.scoring_enabled, TEST_SCORING_ENABLED)
self.assertEqual(org.extra_fields, TEST_EXTRA_FIELDS)
org_messages = org_model.OrganizationMessages.query(
ancestor=org.key).get()
self.assertEqual(
org_messages.accepted_students_message, TEST_ACCEPTED_STUDENTS_MESSAGE)
self.assertEqual(
org_messages.rejected_students_message, TEST_REJECTED_STUDENTS_MESSAGE)
def testOrgsTabs(self):
"""Tests that correct organization related tabs are present in context."""
user = user_seeder.seedUser()
profile_utils.loginNDB(user)
profile_seeder.seedProfile(
self.program.key(), user=user, admin_for=[self.org.key])
response = self.get(_getOrgPreferencesEditUrl(self.org))
# 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.ORG_PREFERENCES_TAB_ID)
_TEST_EXTRA_FIELDS = ['field one', 'field two, with comma', 'field - three']
class CleanExtraFieldsTest(unittest.TestCase):
"""Unit tests for cleanExtraFields function."""
def testListReturned(self):
"""Tests that a list of extra fields is returned."""
extra_fields = org_app_view.cleanExtraFields('\n'.join(_TEST_EXTRA_FIELDS))
self.assertLessEqual(extra_fields, _TEST_EXTRA_FIELDS)
def testInputTooLong(self):
"""Tests that too long input is not allowed."""
with self.assertRaises(django_forms.ValidationError):
org_app_view.cleanExtraFields(
'a' * org_app_view.EXTRA_FIELD_MAX_LENGTH * 2)