Commit 12625a92 by cewing

MIT: CCX. Increase test coverage

Implelement test coverage for utility code supporting enrollments in CCXs

bugfix: prevent UnboundNameError if user does not exist in database.
parent a2cb7fd2
from factory.django import DjangoModelFactory
from pocs.models import PersonalOnlineCourse
from pocs.models import PocMembership
from pocs.models import PocFutureMembership
class PocFactory(DjangoModelFactory):
FACTORY_FOR = PersonalOnlineCourse
display_name = "Test POC"
class PocMembershipFactory(DjangoModelFactory):
FACTORY_FOR = PocMembership
active = False
class PocFutureMembershipFactory(DjangoModelFactory):
FACTORY_FOR = PocFutureMembership
from pocs.models import (
PocMembership,
PocFutureMembership,
)
from pocs.tests.factories import (
PocFactory,
PocMembershipFactory,
PocFutureMembershipFactory,
)
from student.roles import CoursePocCoachRole
from student.tests.factories import (
AdminFactory,
UserFactory,
)
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory
class TestEmailEnrollmentState(ModuleStoreTestCase):
"""unit tests for the EmailEnrollmentState class
"""
def setUp(self):
"""
Set up tests
"""
course = CourseFactory.create()
coach = AdminFactory.create()
role = CoursePocCoachRole(course.id)
role.add_users(coach)
self.poc = PocFactory(course_id=course.id, coach=coach)
def create_user(self):
"""provide a legitimate django user for testing
"""
if getattr(self, 'user', None) is None:
self.user = UserFactory()
def register_user_in_poc(self):
"""create registration of self.user in self.poc
registration will be inactive
"""
self.create_user()
PocMembershipFactory(poc=self.poc, student=self.user)
def create_one(self, email=None):
"""Create a single EmailEnrollmentState object and return it
"""
from pocs.utils import EmailEnrollmentState
if email is None:
email = self.user.email
return EmailEnrollmentState(self.poc, email)
def test_enrollment_state_for_non_user(self):
"""verify behavior for non-user email address
"""
ee_state = self.create_one(email='nobody@nowhere.com')
for attr in ['user', 'member', 'full_name', 'in_poc']:
value = getattr(ee_state, attr, 'missing attribute')
self.assertFalse(value, "{}: {}".format(value, attr))
def test_enrollment_state_for_non_member_user(self):
"""verify behavior for email address of user who is not a poc memeber
"""
self.create_user()
ee_state = self.create_one()
self.assertTrue(ee_state.user)
self.assertFalse(ee_state.in_poc)
self.assertEqual(ee_state.member, self.user)
self.assertEqual(ee_state.full_name, self.user.profile.name)
def test_enrollment_state_for_member_user(self):
"""verify behavior for email address of user who is a poc member
"""
self.create_user()
self.register_user_in_poc()
ee_state = self.create_one()
for attr in ['user', 'in_poc']:
self.assertTrue(
getattr(ee_state, attr, False),
"attribute {} is missing or False".format(attr)
)
self.assertEqual(ee_state.member, self.user)
self.assertEqual(ee_state.full_name, self.user.profile.name)
def test_enrollment_state_to_dict(self):
"""verify dict representation of EmailEnrollmentState
"""
self.create_user()
self.register_user_in_poc()
ee_state = self.create_one()
ee_dict = ee_state.to_dict()
expected = {
'user': True,
'member': self.user,
'in_poc': True,
}
for expected_key, expected_value in expected.iteritems():
self.assertTrue(expected_key in ee_dict)
self.assertEqual(expected_value, ee_dict[expected_key])
def test_enrollment_state_repr(self):
self.create_user()
self.register_user_in_poc()
ee_state = self.create_one()
representation = repr(ee_state)
self.assertTrue('user=True' in representation)
self.assertTrue('in_poc=True' in representation)
member = 'member={}'.format(self.user)
self.assertTrue(member in representation)
# TODO: deal with changes in behavior for auto_enroll
class TestGetEmailParams(ModuleStoreTestCase):
"""tests for pocs.utils.get_email_params
"""
def setUp(self):
"""
Set up tests
"""
course = CourseFactory.create()
coach = AdminFactory.create()
role = CoursePocCoachRole(course.id)
role.add_users(coach)
self.poc = PocFactory(course_id=course.id, coach=coach)
self.all_keys = [
'site_name', 'course', 'course_url', 'registration_url',
'course_about_url', 'auto_enroll'
]
self.url_keys = [k for k in self.all_keys if 'url' in k]
self.course_keys = [k for k in self.url_keys if 'course' in k]
def call_FUT(self, auto_enroll=False, secure=False):
from pocs.utils import get_email_params
return get_email_params(self.poc, auto_enroll, secure)
def test_params_have_expected_keys(self):
params = self.call_FUT()
self.assertFalse(set(params.keys()) - set(self.all_keys))
def test_poc_id_in_params(self):
expected_course_id = self.poc.course_id.to_deprecated_string()
params = self.call_FUT()
self.assertEqual(params['course'], self.poc)
for url_key in self.url_keys:
self.assertTrue('http://' in params[url_key])
for url_key in self.course_keys:
self.assertTrue(expected_course_id in params[url_key])
def test_security_respected(self):
secure = self.call_FUT(secure=True)
for url_key in self.url_keys:
self.assertTrue('https://' in secure[url_key])
insecure = self.call_FUT(secure=False)
for url_key in self.url_keys:
self.assertTrue('http://' in insecure[url_key])
def test_auto_enroll_passed_correctly(self):
not_auto = self.call_FUT(auto_enroll=False)
self.assertFalse(not_auto['auto_enroll'])
auto = self.call_FUT(auto_enroll=True)
self.assertTrue(auto['auto_enroll'])
# TODO: deal with changes in behavior for auto_enroll
class TestEnrollEmail(ModuleStoreTestCase):
"""tests for the enroll_email function from pocs.utils
"""
def setUp(self):
course = CourseFactory.create()
coach = AdminFactory.create()
role = CoursePocCoachRole(course.id)
role.add_users(coach)
self.poc = PocFactory(course_id=course.id, coach=coach)
self.outbox = self.get_outbox()
def create_user(self):
"""provide a legitimate django user for testing
"""
if getattr(self, 'user', None) is None:
self.user = UserFactory()
def register_user_in_poc(self):
"""create registration of self.user in self.poc
registration will be inactive
"""
self.create_user()
PocMembershipFactory(poc=self.poc, student=self.user)
def get_outbox(self):
"""Return the django mail outbox"""
from django.core import mail
return mail.outbox
def check_membership(self, email=None, user=None, future=False):
"""Verify tjat an appropriate Poc Membership exists"""
if not email and not user:
self.fail(
"must provide user or email address to check Poc Membership"
)
if future and email:
membership = PocFutureMembership.objects.filter(
poc=self.poc, email=email
)
elif not future:
if not user:
user = self.user
membership = PocMembership.objects.filter(
poc=self.poc, student=user
)
self.assertTrue(membership.exists())
def check_enrollment_state(self, state, in_poc, member, user):
"""Verify an enrollment state object against provided arguments
state.in_poc will always be a boolean
state.user will always be a boolean
state.member will be a Django user object or None
"""
self.assertEqual(in_poc, state.in_poc)
self.assertEqual(member, state.member)
self.assertEqual(user, state.user)
def call_FUT(
self,
student_email=None,
auto_enroll=False,
email_students=False,
email_params=None
):
from pocs.utils import enroll_email
if student_email is None:
student_email = self.user.email
before, after = enroll_email(
self.poc, student_email, auto_enroll, email_students, email_params
)
return before, after
def test_enroll_non_user_sending_email(self):
"""enroll a non-user email and send an enrollment email to them
"""
# ensure no emails are in the outbox now
self.assertEqual(len(self.outbox), 0)
test_email = "nobody@nowhere.com"
before, after = self.call_FUT(
student_email=test_email, email_students=True
)
# there should be a future membership set for this email address now
self.check_membership(email=test_email, future=True)
for state in [before, after]:
self.check_enrollment_state(state, False, None, False)
# mail was sent and to the right person
self.assertEqual(len(self.outbox), 1)
msg = self.outbox[0]
self.assertTrue(test_email in msg.recipients())
def test_enroll_non_member_sending_email(self):
"""register a non-member and send an enrollment email to them
"""
self.create_user()
# ensure no emails are in the outbox now
self.assertEqual(len(self.outbox), 0)
before, after = self.call_FUT(email_students=True)
# there should be a membership set for this email address now
self.check_membership(email=self.user.email)
self.check_enrollment_state(before, False, self.user, True)
self.check_enrollment_state(after, True, self.user, True)
# mail was sent and to the right person
self.assertEqual(len(self.outbox), 1)
msg = self.outbox[0]
self.assertTrue(self.user.email in msg.recipients())
def test_enroll_member_sending_email(self):
"""register a member and send an enrollment email to them
"""
self.register_user_in_poc()
# ensure no emails are in the outbox now
self.assertEqual(len(self.outbox), 0)
before, after = self.call_FUT(email_students=True)
# there should be a membership set for this email address now
self.check_membership(email=self.user.email)
for state in [before, after]:
self.check_enrollment_state(state, True, self.user, True)
# mail was sent and to the right person
self.assertEqual(len(self.outbox), 1)
msg = self.outbox[0]
self.assertTrue(self.user.email in msg.recipients())
def test_enroll_non_user_no_email(self):
"""register a non-user via email address but send no email
"""
# ensure no emails are in the outbox now
self.assertEqual(len(self.outbox), 0)
test_email = "nobody@nowhere.com"
before, after = self.call_FUT(
student_email=test_email, email_students=False
)
# there should be a future membership set for this email address now
self.check_membership(email=test_email, future=True)
for state in [before, after]:
self.check_enrollment_state(state, False, None, False)
# ensure there are still no emails in the outbox now
self.assertEqual(len(self.outbox), 0)
def test_enroll_non_member_no_email(self):
"""register a non-member but send no email"""
self.create_user()
# ensure no emails are in the outbox now
self.assertEqual(len(self.outbox), 0)
before, after = self.call_FUT(email_students=False)
# there should be a membership set for this email address now
self.check_membership(email=self.user.email)
self.check_enrollment_state(before, False, self.user, True)
self.check_enrollment_state(after, True, self.user, True)
# ensure there are still no emails in the outbox now
self.assertEqual(len(self.outbox), 0)
def test_enroll_member_no_email(self):
"""enroll a member but send no email
"""
self.register_user_in_poc()
# ensure no emails are in the outbox now
self.assertEqual(len(self.outbox), 0)
before, after = self.call_FUT(email_students=False)
# there should be a membership set for this email address now
self.check_membership(email=self.user.email)
for state in [before, after]:
self.check_enrollment_state(state, True, self.user, True)
# ensure there are still no emails in the outbox now
self.assertEqual(len(self.outbox), 0)
# TODO: deal with changes in behavior for auto_enroll
class TestUnenrollEmail(ModuleStoreTestCase):
"""Tests for the unenroll_email function from pocs.utils"""
def setUp(self):
course = CourseFactory.create()
coach = AdminFactory.create()
role = CoursePocCoachRole(course.id)
role.add_users(coach)
self.poc = PocFactory(course_id=course.id, coach=coach)
self.outbox = self.get_outbox()
def tearDown(self):
for attr in ['user', 'email']:
if hasattr(self, attr):
delattr(self, attr)
def get_outbox(self):
"""Return the django mail outbox"""
from django.core import mail
return mail.outbox
def create_user(self):
"""provide a legitimate django user for testing
"""
if getattr(self, 'user', None) is None:
self.user = UserFactory()
def make_poc_membership(self):
"""create registration of self.user in self.poc
registration will be inactive
"""
self.create_user()
PocMembershipFactory.create(poc=self.poc, student=self.user)
def make_poc_future_membership(self):
"""create future registration for email in self.poc"""
self.email = "nobody@nowhere.com"
PocFutureMembershipFactory.create(
poc=self.poc, email=self.email
)
def check_enrollment_state(self, state, in_poc, member, user):
"""Verify an enrollment state object against provided arguments
state.in_poc will always be a boolean
state.user will always be a boolean
state.member will be a Django user object or None
"""
self.assertEqual(in_poc, state.in_poc)
self.assertEqual(member, state.member)
self.assertEqual(user, state.user)
def check_membership(self, future=False):
if future:
membership = PocFutureMembership.objects.filter(
poc=self.poc, email=self.email
)
else:
membership = PocMembership.objects.filter(
poc=self.poc, student=self.user
)
return membership.exists()
def call_FUT(self, email_students=False):
from pocs.utils import unenroll_email
email = hasattr(self, 'user') and self.user.email or self.email
return unenroll_email(self.poc, email, email_students=email_students)
def test_unenroll_future_member_with_email(self):
"""unenroll a future member and send an email
"""
self.make_poc_future_membership()
# assert that a membership exists and that no emails have been sent
self.assertTrue(self.check_membership(future=True))
self.assertEqual(len(self.outbox), 0)
# unenroll the student
before, after = self.call_FUT(email_students=True)
# assert that membership is now gone
self.assertFalse(self.check_membership(future=True))
# validate the before and after enrollment states
for state in [before, after]:
self.check_enrollment_state(state, False, None, False)
# check that mail was sent and to the right person
self.assertEqual(len(self.outbox), 1)
msg = self.outbox[0]
self.assertTrue(self.email in msg.recipients())
def test_unenroll_member_with_email(self):
"""unenroll a current member and send an email"""
self.make_poc_membership()
# assert that a membership exists and that no emails have been sent
self.assertTrue(self.check_membership())
self.assertEqual(len(self.outbox), 0)
# unenroll the student
before, after = self.call_FUT(email_students=True)
# assert that membership is now gone
self.assertFalse(self.check_membership())
# validate the before and after enrollment state
self.check_enrollment_state(after, False, self.user, True)
self.check_enrollment_state(before, True, self.user, True)
# check that mail was sent and to the right person
self.assertEqual(len(self.outbox), 1)
msg = self.outbox[0]
self.assertTrue(self.user.email in msg.recipients())
def test_unenroll_future_member_no_email(self):
"""unenroll a future member but send no email
"""
self.make_poc_future_membership()
# assert that a membership exists and that no emails have been sent
self.assertTrue(self.check_membership(future=True))
self.assertEqual(len(self.outbox), 0)
# unenroll the student
before, after = self.call_FUT()
# assert that membership is now gone
self.assertFalse(self.check_membership(future=True))
# validate the before and after enrollment states
for state in [before, after]:
self.check_enrollment_state(state, False, None, False)
# no email was sent to the student
self.assertEqual(len(self.outbox), 0)
def test_unenroll_member_no_email(self):
"""unenroll a current member but send no email
"""
self.make_poc_membership()
# assert that a membership exists and that no emails have been sent
self.assertTrue(self.check_membership())
self.assertEqual(len(self.outbox), 0)
# unenroll the student
before, after = self.call_FUT()
# assert that membership is now gone
self.assertFalse(self.check_membership())
# validate the before and after enrollment state
self.check_enrollment_state(after, False, self.user, True)
self.check_enrollment_state(before, True, self.user, True)
# no email was sent to the student
self.assertEqual(len(self.outbox), 0)
......@@ -8,12 +8,26 @@ from courseware.tests.helpers import LoginEnrollmentTestCase
from django.core.urlresolvers import reverse
from edxmako.shortcuts import render_to_response
from student.roles import CoursePocCoachRole
from student.tests.factories import AdminFactory
from student.tests.factories import (
AdminFactory,
CourseEnrollmentFactory,
)
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
from ..models import PersonalOnlineCourse
from xmodule.modulestore.tests.factories import (
CourseFactory,
ItemFactory,
)
from ..models import (
PersonalOnlineCourse,
PocMembership,
PocFutureMembership,
)
from ..overrides import get_override_for_poc
from .factories import (
PocFactory,
PocMembershipFactory,
PocFutureMembershipFactory,
)
def intercept_renderer(path, context):
......@@ -65,6 +79,14 @@ class TestCoachDashboard(ModuleStoreTestCase, LoginEnrollmentTestCase):
role = CoursePocCoachRole(self.course.id)
role.add_users(self.coach)
def make_poc(self):
poc = PocFactory(course_id=self.course.id, coach=self.coach)
return poc
def get_outbox(self):
from django.core import mail
return mail.outbox
def tearDown(self):
"""
Undo patches.
......@@ -158,6 +180,122 @@ class TestCoachDashboard(ModuleStoreTestCase, LoginEnrollmentTestCase):
course_start = get_override_for_poc(poc, self.course, 'start')
self.assertEqual(str(course_start)[:-9], u'2014-11-20 00:00')
def test_enroll_member_student(self):
self.make_coach()
poc = self.make_poc()
enrollment = CourseEnrollmentFactory(course_id=self.course.id)
student = enrollment.user
outbox = self.get_outbox()
self.assertEqual(len(outbox), 0)
url = reverse(
'poc_invite',
kwargs={'course_id': self.course.id.to_deprecated_string()}
)
data = {
'enrollment-button': 'Enroll',
'student-ids': u','.join([student.email, ]),
}
response = self.client.post(url, data=data, follow=True)
self.assertEqual(response.status_code, 200)
# we were redirected to our current location
self.assertEqual(len(response.redirect_chain), 1)
self.assertTrue(302 in response.redirect_chain[0])
self.assertEqual(len(outbox), 1)
self.assertTrue(student.email in outbox[0].recipients())
# a PocMembership exists for this student
self.assertTrue(
PocMembership.objects.filter(poc=poc, student=student).exists()
)
def test_unenroll_member_student(self):
self.make_coach()
poc = self.make_poc()
enrollment = CourseEnrollmentFactory(course_id=self.course.id)
student = enrollment.user
outbox = self.get_outbox()
self.assertEqual(len(outbox), 0)
# student is member of POC:
PocMembershipFactory(poc=poc, student=student)
url = reverse(
'poc_invite',
kwargs={'course_id': self.course.id.to_deprecated_string()}
)
data = {
'enrollment-button': 'Unenroll',
'student-ids': u','.join([student.email, ]),
}
response = self.client.post(url, data=data, follow=True)
self.assertEqual(response.status_code, 200)
# we were redirected to our current location
self.assertEqual(len(response.redirect_chain), 1)
self.assertTrue(302 in response.redirect_chain[0])
self.assertEqual(len(outbox), 1)
self.assertTrue(student.email in outbox[0].recipients())
# the membership for this student is gone
self.assertFalse(
PocMembership.objects.filter(poc=poc, student=student).exists()
)
def test_enroll_non_user_student(self):
test_email = "nobody@nowhere.com"
self.make_coach()
poc = self.make_poc()
outbox = self.get_outbox()
self.assertEqual(len(outbox), 0)
url = reverse(
'poc_invite',
kwargs={'course_id': self.course.id.to_deprecated_string()}
)
data = {
'enrollment-button': 'Enroll',
'student-ids': u','.join([test_email, ]),
}
response = self.client.post(url, data=data, follow=True)
self.assertEqual(response.status_code, 200)
# we were redirected to our current location
self.assertEqual(len(response.redirect_chain), 1)
self.assertTrue(302 in response.redirect_chain[0])
self.assertEqual(len(outbox), 1)
self.assertTrue(test_email in outbox[0].recipients())
self.assertTrue(
PocFutureMembership.objects.filter(
poc=poc, email=test_email
).exists()
)
def test_unenroll_non_user_student(self):
test_email = "nobody@nowhere.com"
self.make_coach()
poc = self.make_poc()
outbox = self.get_outbox()
PocFutureMembershipFactory(poc=poc, email=test_email)
self.assertEqual(len(outbox), 0)
url = reverse(
'poc_invite',
kwargs={'course_id': self.course.id.to_deprecated_string()}
)
data = {
'enrollment-button': 'Unenroll',
'student-ids': u','.join([test_email, ]),
}
response = self.client.post(url, data=data, follow=True)
self.assertEqual(response.status_code, 200)
# we were redirected to our current location
self.assertEqual(len(response.redirect_chain), 1)
self.assertTrue(302 in response.redirect_chain[0])
self.assertEqual(len(outbox), 1)
self.assertTrue(test_email in outbox[0].recipients())
self.assertFalse(
PocFutureMembership.objects.filter(
poc=poc, email=test_email
).exists()
)
def flatten(seq):
"""
......
......@@ -31,6 +31,7 @@ class EmailEnrollmentState(object):
in_poc = poc_member.exists()
full_name = user.profile.name
else:
user = None
in_poc = False
full_name = None
self.user = exists_user
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment