Merge pull request #8328 from edx/awais786/awais786/ECOM-1572-icrv-emails-format-new
ECOM-1572 implementing code to new branch.
This commit is contained in:
@@ -20,15 +20,17 @@ from django.core.urlresolvers import reverse
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.core import mail
|
||||
from django.test import TestCase
|
||||
from django.test.client import Client
|
||||
from django.test.client import Client, RequestFactory
|
||||
from django.test.utils import override_settings
|
||||
from django.utils import timezone
|
||||
|
||||
from opaque_keys.edx.locations import SlashSeparatedCourseKey
|
||||
from opaque_keys.edx.locator import CourseLocator
|
||||
from opaque_keys.edx.keys import UsageKey
|
||||
|
||||
from course_modes.models import CourseMode
|
||||
from course_modes.tests.factories import CourseModeFactory
|
||||
from courseware.url_helpers import get_redirect_url
|
||||
from commerce.tests import TEST_PAYMENT_DATA, TEST_API_URL, TEST_API_SIGNING_KEY
|
||||
from embargo.test_utils import restrict_course
|
||||
from microsite_configuration import microsite
|
||||
@@ -1891,6 +1893,7 @@ class TestEmailMessageWithCustomICRVBlock(ModuleStoreTestCase):
|
||||
self.course_key = SlashSeparatedCourseKey("Robot", "999", "Test_Course")
|
||||
self.course = CourseFactory.create(org='Robot', number='999', display_name='Test Course')
|
||||
self.due_date = datetime(2015, 6, 22, tzinfo=pytz.UTC)
|
||||
self.allowed_attempts = 1
|
||||
|
||||
# Create the course modes
|
||||
for mode in ('audit', 'honor', 'verified'):
|
||||
@@ -1906,7 +1909,7 @@ class TestEmailMessageWithCustomICRVBlock(ModuleStoreTestCase):
|
||||
parent=vertical,
|
||||
category='edx-reverification-block',
|
||||
display_name='Test Verification Block',
|
||||
metadata={'attempts': 3, 'due': self.due_date}
|
||||
metadata={'attempts': self.allowed_attempts, 'due': self.due_date}
|
||||
)
|
||||
|
||||
self.section_location = section.location
|
||||
@@ -1940,73 +1943,148 @@ class TestEmailMessageWithCustomICRVBlock(ModuleStoreTestCase):
|
||||
status='submitted'
|
||||
)
|
||||
self.attempt = SoftwareSecurePhotoVerification.objects.filter(user=self.user)
|
||||
location_id = VerificationStatus.get_location_id(self.attempt)
|
||||
usage_key = UsageKey.from_string(location_id)
|
||||
redirect_url = get_redirect_url(self.course_key, usage_key.replace(course_key=self.course_key))
|
||||
self.request = RequestFactory().get('/url')
|
||||
self.course_link = self.request.build_absolute_uri(redirect_url)
|
||||
|
||||
def test_approved_email_message(self):
|
||||
"""
|
||||
Test email message for approved photo verification.
|
||||
"""
|
||||
|
||||
subject, body = _compose_message_reverification_email(
|
||||
self.course.id, self.user.id, self.reverification_location, "approved", True
|
||||
self.course.id, self.user.id, self.reverification_location, "approved", self.request
|
||||
)
|
||||
|
||||
self.assertIn(
|
||||
"Your verification for course {course_name} and assessment {assessment} has been passed.".format(
|
||||
course_name=self.course.display_name_with_default,
|
||||
assessment=self.assessment
|
||||
"We have successfully verified your identity for the {assessment} "
|
||||
"assessment in the {course_name} course.".format(
|
||||
assessment=self.assessment,
|
||||
course_name=self.course.display_name_with_default
|
||||
),
|
||||
body
|
||||
)
|
||||
|
||||
self.check_courseware_link_exists(body)
|
||||
self.assertIn("Re-verification Status", subject)
|
||||
|
||||
def test_denied_email_message_with_valid_due_date_and_attempts_allowed(self):
|
||||
|
||||
__, body = _compose_message_reverification_email(
|
||||
self.course.id, self.user.id, self.reverification_location, "denied", True
|
||||
subject, body = _compose_message_reverification_email(
|
||||
self.course.id, self.user.id, self.reverification_location, "denied", self.request
|
||||
)
|
||||
|
||||
self.assertIn(
|
||||
"Your verification for course {course_name} and assessment {assessment} has failed.".format(
|
||||
"We could not verify your identity for the {assessment} assessment "
|
||||
"in the {course_name} course. You have used "
|
||||
"{used_attempts} out of {allowed_attempts} attempts to "
|
||||
"verify your identity.".format(
|
||||
course_name=self.course.display_name_with_default,
|
||||
assessment=self.assessment
|
||||
assessment=self.assessment,
|
||||
used_attempts=1,
|
||||
allowed_attempts=self.allowed_attempts + 1
|
||||
),
|
||||
body
|
||||
)
|
||||
|
||||
self.assertIn("Assessment closes on {due_date}".format(due_date=get_default_time_display(self.due_date)), body)
|
||||
self.assertIn("Click on link below to re-verify", body)
|
||||
self.assertIn(
|
||||
"https://{}{}".format(
|
||||
microsite.get_value('SITE_NAME', 'localhost'), self.re_verification_link
|
||||
"You must verify your identity before the assessment "
|
||||
"closes on {due_date}".format(
|
||||
due_date=get_default_time_display(self.due_date)
|
||||
),
|
||||
body
|
||||
)
|
||||
reverify_link = self.request.build_absolute_uri(self.re_verification_link)
|
||||
self.assertIn(
|
||||
"To try to verify your identity again, select the following link:",
|
||||
body
|
||||
)
|
||||
|
||||
self.assertIn(reverify_link, body)
|
||||
self.assertIn("Re-verification Status", subject)
|
||||
|
||||
def test_denied_email_message_with_due_date_and_no_attempts(self):
|
||||
""" Denied email message if due date is still open but user has no
|
||||
attempts available.
|
||||
"""
|
||||
|
||||
VerificationStatus.add_verification_status(
|
||||
checkpoint=self.check_point,
|
||||
user=self.user,
|
||||
status='submitted'
|
||||
)
|
||||
|
||||
__, body = _compose_message_reverification_email(
|
||||
self.course.id, self.user.id, self.reverification_location, "denied", self.request
|
||||
)
|
||||
|
||||
self.assertIn(
|
||||
"We could not verify your identity for the {assessment} assessment "
|
||||
"in the {course_name} course. You have used "
|
||||
"{used_attempts} out of {allowed_attempts} attempts to "
|
||||
"verify your identity, and verification is no longer "
|
||||
"possible".format(
|
||||
course_name=self.course.display_name_with_default,
|
||||
assessment=self.assessment,
|
||||
used_attempts=2,
|
||||
allowed_attempts=self.allowed_attempts + 1
|
||||
),
|
||||
body
|
||||
)
|
||||
|
||||
self.check_courseware_link_exists(body)
|
||||
|
||||
def test_denied_email_message_with_close_verification_dates(self):
|
||||
# Due date given and expired
|
||||
|
||||
return_value = datetime(2016, 1, 1, tzinfo=timezone.utc)
|
||||
with patch.object(timezone, 'now', return_value=return_value):
|
||||
__, body = _compose_message_reverification_email(
|
||||
self.course.id, self.user.id, self.reverification_location, "denied", True
|
||||
self.course.id, self.user.id, self.reverification_location, "denied", self.request
|
||||
)
|
||||
|
||||
self.assertIn(
|
||||
"Your verification for course {course_name} and assessment {assessment} has failed.".format(
|
||||
"We could not verify your identity for the {assessment} assessment "
|
||||
"in the {course_name} course. You have used "
|
||||
"{used_attempts} out of {allowed_attempts} attempts to "
|
||||
"verify your identity, and verification is no longer "
|
||||
"possible".format(
|
||||
course_name=self.course.display_name_with_default,
|
||||
assessment=self.assessment
|
||||
assessment=self.assessment,
|
||||
used_attempts=1,
|
||||
allowed_attempts=self.allowed_attempts + 1
|
||||
),
|
||||
body
|
||||
)
|
||||
|
||||
self.assertIn("Assessment date has passed and retake not allowed", body)
|
||||
|
||||
def test_check_num_queries(self):
|
||||
# Get the re-verification block to check the call made
|
||||
with check_mongo_calls(2):
|
||||
with check_mongo_calls(1):
|
||||
ver_block = modulestore().get_item(self.reverification.location)
|
||||
|
||||
# Expect that the verification block is fetched
|
||||
self.assertIsNotNone(ver_block)
|
||||
|
||||
def check_courseware_link_exists(self, body):
|
||||
"""Checking courseware url and signature information of EDX"""
|
||||
self.assertIn(
|
||||
"To go to the courseware, select the following link:",
|
||||
body
|
||||
)
|
||||
self.assertIn(
|
||||
"{course_link}".format(
|
||||
course_link=self.course_link
|
||||
),
|
||||
body
|
||||
)
|
||||
|
||||
self.assertIn("Thanks,", body)
|
||||
self.assertIn(
|
||||
"The {platform_name} team".format(
|
||||
platform_name=settings.PLATFORM_NAME
|
||||
),
|
||||
body
|
||||
)
|
||||
|
||||
|
||||
class TestEmailMessageWithDefaultICRVBlock(ModuleStoreTestCase):
|
||||
"""
|
||||
@@ -2059,6 +2137,7 @@ class TestEmailMessageWithDefaultICRVBlock(ModuleStoreTestCase):
|
||||
)
|
||||
self.check_point.add_verification_attempt(SoftwareSecurePhotoVerification.objects.create(user=self.user))
|
||||
self.attempt = SoftwareSecurePhotoVerification.objects.filter(user=self.user)
|
||||
self.request = RequestFactory().get('/url')
|
||||
|
||||
def test_denied_email_message_with_no_attempt_allowed(self):
|
||||
|
||||
@@ -2069,73 +2148,25 @@ class TestEmailMessageWithDefaultICRVBlock(ModuleStoreTestCase):
|
||||
)
|
||||
|
||||
__, body = _compose_message_reverification_email(
|
||||
self.course.id, self.user.id, self.reverification_location, "denied", True
|
||||
self.course.id, self.user.id, self.reverification_location, "denied", self.request
|
||||
)
|
||||
|
||||
self.assertIn(
|
||||
"Your verification for course {course_name} and assessment {assessment} has failed.".format(
|
||||
"We could not verify your identity for the {assessment} assessment "
|
||||
"in the {course_name} course. You have used "
|
||||
"{used_attempts} out of {allowed_attempts} attempts to "
|
||||
"verify your identity, and verification is no longer "
|
||||
"possible".format(
|
||||
course_name=self.course.display_name_with_default,
|
||||
assessment=self.assessment
|
||||
),
|
||||
body
|
||||
)
|
||||
|
||||
self.assertIn("You have reached your allowed attempts limit. No more retakes allowed.", body)
|
||||
|
||||
def test_due_date(self):
|
||||
self.reverification.due = datetime.now()
|
||||
self.reverification.save()
|
||||
|
||||
VerificationStatus.add_verification_status(
|
||||
checkpoint=self.check_point,
|
||||
user=self.user,
|
||||
status='submitted'
|
||||
)
|
||||
__, body = _compose_message_reverification_email(
|
||||
self.course.id, self.user.id, self.reverification_location, "denied", True
|
||||
)
|
||||
|
||||
self.assertIn(
|
||||
"Your verification for course {course_name} and assessment {assessment} has failed.".format(
|
||||
course_name=self.course.display_name_with_default,
|
||||
assessment=self.assessment
|
||||
),
|
||||
body
|
||||
)
|
||||
|
||||
self.assertIn("You have reached your allowed attempts limit. No more retakes allowed.", body)
|
||||
|
||||
def test_denied_email_message_with_no_due_date(self):
|
||||
|
||||
VerificationStatus.add_verification_status(
|
||||
checkpoint=self.check_point,
|
||||
user=self.user,
|
||||
status='error'
|
||||
)
|
||||
|
||||
__, body = _compose_message_reverification_email(
|
||||
self.course.id, self.user.id, self.reverification_location, "denied", True
|
||||
)
|
||||
|
||||
self.assertIn(
|
||||
"Your verification for course {course_name} and assessment {assessment} has failed.".format(
|
||||
course_name=self.course.display_name_with_default,
|
||||
assessment=self.assessment
|
||||
),
|
||||
body
|
||||
)
|
||||
|
||||
self.assertIn("Assessment is open and you have 1 attempt(s) remaining.", body)
|
||||
self.assertIn("Click on link below to re-verify", body)
|
||||
self.assertIn(
|
||||
"https://{}{}".format(
|
||||
microsite.get_value('SITE_NAME', 'localhost'), self.re_verification_link
|
||||
assessment=self.assessment,
|
||||
used_attempts=1,
|
||||
allowed_attempts=1
|
||||
),
|
||||
body
|
||||
)
|
||||
|
||||
def test_error_on_compose_email(self):
|
||||
resp = _compose_message_reverification_email(
|
||||
self.course.id, self.user.id, u'i4x://edX/DemoX/edx-reverification-block/invalid_location', "denied", True
|
||||
self.course.id, self.user.id, self.reverification_location, "denied", True
|
||||
)
|
||||
self.assertIsNone(resp)
|
||||
|
||||
@@ -858,7 +858,7 @@ def submit_photos_for_verification(request):
|
||||
|
||||
|
||||
def _compose_message_reverification_email(
|
||||
course_key, user_id, related_assessment_location, status, is_secure
|
||||
course_key, user_id, related_assessment_location, status, request
|
||||
): # pylint: disable=invalid-name
|
||||
"""
|
||||
Compose subject and message for photo reverification email.
|
||||
@@ -885,14 +885,13 @@ def _compose_message_reverification_email(
|
||||
context = {
|
||||
"status": status,
|
||||
"course_name": course.display_name_with_default,
|
||||
"assessment": reverification_block.related_assessment,
|
||||
"courseware_url": redirect_url
|
||||
"assessment": reverification_block.related_assessment
|
||||
}
|
||||
|
||||
# Allowed attempts is 1 if not set on verification block
|
||||
allowed_attempts = 1 if reverification_block.attempts == 0 else reverification_block.attempts
|
||||
user_attempts = VerificationStatus.get_user_attempts(user_id, course_key, related_assessment_location)
|
||||
left_attempts = allowed_attempts - user_attempts
|
||||
allowed_attempts = reverification_block.attempts + 1
|
||||
used_attempts = VerificationStatus.get_user_attempts(user_id, course_key, related_assessment_location)
|
||||
left_attempts = allowed_attempts - used_attempts
|
||||
is_attempt_allowed = left_attempts > 0
|
||||
verification_open = True
|
||||
if reverification_block.due:
|
||||
@@ -902,9 +901,11 @@ def _compose_message_reverification_email(
|
||||
context["is_attempt_allowed"] = is_attempt_allowed
|
||||
context["verification_open"] = verification_open
|
||||
context["due_date"] = get_default_time_display(reverification_block.due)
|
||||
context["is_secure"] = is_secure
|
||||
context["site"] = microsite.get_value('SITE_NAME', 'localhost')
|
||||
context['platform_name'] = microsite.get_value('platform_name', settings.PLATFORM_NAME),
|
||||
|
||||
context['platform_name'] = settings.PLATFORM_NAME
|
||||
context["used_attempts"] = used_attempts
|
||||
context["allowed_attempts"] = allowed_attempts
|
||||
context["support_link"] = microsite.get_value('email_from_address', settings.CONTACT_EMAIL)
|
||||
|
||||
re_verification_link = reverse(
|
||||
'verify_student_incourse_reverify',
|
||||
@@ -913,7 +914,10 @@ def _compose_message_reverification_email(
|
||||
related_assessment_location
|
||||
)
|
||||
)
|
||||
context["reverify_link"] = re_verification_link
|
||||
|
||||
context["course_link"] = request.build_absolute_uri(redirect_url)
|
||||
context["reverify_link"] = request.build_absolute_uri(re_verification_link)
|
||||
|
||||
message = render_to_string('emails/reverification_processed.txt', context)
|
||||
log.info(
|
||||
"Sending email to User_Id=%s. Attempts left for this user are %s. "
|
||||
@@ -1030,7 +1034,7 @@ def results_callback(request):
|
||||
related_assessment_location = checkpoints[0].checkpoint_location
|
||||
|
||||
subject, message = _compose_message_reverification_email(
|
||||
course_key, user_id, related_assessment_location, status, request.is_secure()
|
||||
course_key, user_id, related_assessment_location, status, request
|
||||
)
|
||||
|
||||
_send_email(user_id, subject, message)
|
||||
|
||||
@@ -1,43 +1,28 @@
|
||||
<%namespace file="../main.html" import="stanford_theme_enabled" />
|
||||
<%! from django.utils.translation import ugettext as _ %>
|
||||
% if status == "approved":
|
||||
${_("Your verification for course {course_name} and assessment {assessment} "
|
||||
"has been passed."
|
||||
).format(course_name=course_name, assessment=assessment)}
|
||||
${_("We have successfully verified your identity for the {assessment} assessment in the {course_name} course."
|
||||
).format(course_name=course_name, assessment=assessment)}
|
||||
|
||||
%else:
|
||||
${_("Your verification for course {course_name} and assessment {assessment} "
|
||||
"has failed."
|
||||
).format(course_name=course_name, assessment=assessment)}
|
||||
% elif is_attempt_allowed and verification_open: # if attempts are allowed and verification is still open.
|
||||
${_("We could not verify your identity for the {assessment} assessment in the {course_name} course. You have used {used_attempts} out of {allowed_attempts} attempts to verify your identity."
|
||||
).format(course_name=course_name, assessment=assessment, used_attempts=used_attempts, allowed_attempts=allowed_attempts)}
|
||||
%if due_date:
|
||||
${_("You must verify your identity before the assessment closes on {due_date}.").format(due_date=due_date)}
|
||||
%endif
|
||||
|
||||
% if not is_attempt_allowed:
|
||||
${_("You have reached your allowed attempts limit. No more retakes allowed.")}
|
||||
% elif not verification_open:
|
||||
${_("Assessment date has passed and retake not allowed.")}
|
||||
% else:
|
||||
% if due_date:
|
||||
${_("Assessment closes on {due_date}.".format(due_date=due_date))}
|
||||
% else:
|
||||
${_("Assessment is open and you have {left_attempts} attempt(s) remaining.".format(left_attempts=left_attempts))}
|
||||
% endif
|
||||
${_("To try to verify your identity again, select the following link:")}
|
||||
${reverify_link}
|
||||
|
||||
${_("Click on link below to re-verify:")}
|
||||
% if is_secure:
|
||||
https://${ site }${ reverify_link }
|
||||
% else:
|
||||
http://${ site }${ reverify_link }
|
||||
% endif
|
||||
% elif not is_attempt_allowed or not verification_open: # if attempts are not allowed or verification window is closed
|
||||
${_("We could not verify your identity for the {assessment} assessment in the {course_name} course. You have used {used_attempts} out of {allowed_attempts} attempts to verify your identity, and verification is no longer possible."
|
||||
).format(course_name=course_name, assessment=assessment, used_attempts=used_attempts, allowed_attempts=allowed_attempts)}
|
||||
%endif
|
||||
|
||||
% endif
|
||||
% endif
|
||||
${_("To go to the courseware, select the following link:")}
|
||||
${course_link}
|
||||
|
||||
${_("Click on link below to go to the courseware:")}
|
||||
% if is_secure:
|
||||
https://${ site }${ courseware_url }
|
||||
% else:
|
||||
http://${ site }${ courseware_url }
|
||||
% endif
|
||||
${_("If you have any questions, you can contact student support at {support_link}.").format(support_link=support_link)}
|
||||
|
||||
|
||||
|
||||
${_("The {platform_name} Team.").format(platform_name=platform_name)}
|
||||
${_("Thanks,")}
|
||||
${_("The {platform_name} team").format(platform_name=platform_name)}
|
||||
|
||||
Reference in New Issue
Block a user