Commit bd5f6341 by Andy Armstrong Committed by GitHub

Merge pull request #309 from edx/andya/proctoring-verification-step-2

Introduce id verification step for proctored exams
parents 113ba496 a5681bc1
......@@ -1641,6 +1641,7 @@ def _get_proctored_exam_view(exam, context, exam_id, user_id, course_id):
student_view_template = None
credit_state = context.get('credit_state')
verification_status = context.get('verification_status')
# see if only 'verified' track students should see this *except* if it is a practice exam
check_mode = (
......@@ -1730,12 +1731,16 @@ def _get_proctored_exam_view(exam, context, exam_id, user_id, course_id):
return None
elif attempt_status in [ProctoredExamStudentAttemptStatus.created,
ProctoredExamStudentAttemptStatus.download_software_clicked]:
provider = get_backend_provider()
student_view_template = 'proctored_exam/instructions.html'
context.update({
'exam_code': attempt['attempt_code'],
'software_download_url': provider.get_software_download_url(),
})
if verification_status is not 'approved':
# if the user has not id verified yet, show them the page that requires them to do so
student_view_template = 'proctored_exam/id_verification.html'
else:
provider = get_backend_provider()
student_view_template = 'proctored_exam/instructions.html'
context.update({
'exam_code': attempt['attempt_code'],
'software_download_url': provider.get_software_download_url(),
})
elif attempt_status == ProctoredExamStudentAttemptStatus.ready_to_start:
student_view_template = 'proctored_exam/ready_to_start.html'
elif attempt_status == ProctoredExamStudentAttemptStatus.error:
......
{% load i18n %}
<div class="sequence proctored-exam instructions message-left-bar" data-exam-id="{{exam_id}}" data-exam-started-poll-url="{{exam_started_poll_url}}">
<div class="">
<h3>
{% blocktrans %}
Complete your verification before starting the proctored exam.
{% endblocktrans %}
</h3>
<p>
{% blocktrans %}
You must successfully complete identity verification before you can start the proctored exam.
{% endblocktrans %}
</p>
{% if verification_status == 'pending' %}
<p>
{% blocktrans %}
Your verification is pending. Results should be available 2-3 days after you
submit your verification.
{% endblocktrans %}
</p>
{% elif verification_status == 'must_reverify' %}
<p>
{% blocktrans %}
Your verification attempt failed. Please read our guidelines to make
sure you understand the requirements for successfully completing verification,
then try again.
{% endblocktrans %}
</p>
<div>
<a href="{{ reverify_url }}" class="reverify-url btn-pl-primary">
{% trans "Retry Verification" %}
</a>
</div>
{% elif verification_status == 'expired' %}
<p>
{% blocktrans %}
Your verification has expired. You must successfully complete a new identity verification
before you can start the proctored exam.
{% endblocktrans %}
</p>
<div>
<a href="{{ reverify_url }}" class="reverify-url btn-pl-primary">
{% trans "Continue to Verification" %}
</a>
</div>
{% else %}
<p>
{% blocktrans %}
Make sure you are on a computer with a webcam, and that you have valid photo identification
such as a driver's license or passport, before you continue.
{% endblocktrans %}
</p>
<div>
<a href="{{ reverify_url }}" class="reverify-url btn-pl-primary">
{% trans "Continue to Verification" %}
</a>
</div>
{% endif %}
</div>
</div>
{% include 'proctored_exam/footer.html' %}
......@@ -35,7 +35,9 @@
</p>
<p>
{% blocktrans %}
You will be asked to verify your identity before you begin the exam. Make sure you have valid photo identification, such as a driver's license or passport, before you continue.
You will be asked to verify your identity as part of the proctoring exam set up.
Make sure you are on a computer with a webcam, and that you have valid photo identification
such as a driver's license or passport, before you continue.
{% endblocktrans %}
</p>
<p>
......
......@@ -82,6 +82,8 @@ class ProctoredExamStudentViewTests(ProctoredExamTestCase):
'display_name': self.exam_name,
'default_time_limit_mins': 90,
'hide_after_due': False,
'verification_status': 'approved',
'verification_url': '/reverify',
}
)
self.assertIn(
......@@ -149,6 +151,42 @@ class ProctoredExamStudentViewTests(ProctoredExamTestCase):
self.assertIsNone(rendered_response)
@ddt.data(
(None, 'Make sure you are on a computer with a webcam, and that you have valid photo identification'),
('pending', 'Your verification is pending'),
('must_reverify', 'Your verification attempt failed'),
('expired', 'Your verification has expired'),
)
@ddt.unpack
def test_verification_status(self, verification_status, expected_message):
"""
This test asserts that the correct id verification message is shown
to the user when they choose to take a proctored exam.
"""
self._create_unstarted_exam_attempt()
rendered_response = get_student_view(
user_id=self.user_id,
course_id=self.course_id,
content_id=self.content_id,
context={
'is_proctored': True,
'display_name': self.exam_name,
'default_time_limit_mins': 90,
'is_practice_exam': False,
'credit_state': {
'enrollment_mode': 'verified',
'credit_requirement_status': [
]
},
'verification_status': verification_status,
'verification_url': '/reverify',
}
)
self.assertIn(expected_message, rendered_response)
@ddt.data(
('reverification', None, 'The following prerequisites are in a <strong>pending</strong> state', True),
('reverification', 'pending', 'The following prerequisites are in a <strong>pending</strong> state', True),
('reverification', 'failed', 'You did not satisfy the following prerequisites', True),
......@@ -196,6 +234,8 @@ class ProctoredExamStudentViewTests(ProctoredExamTestCase):
}
]
},
'verification_status': 'approved',
'verification_url': '/reverify',
}
)
......@@ -333,7 +373,9 @@ class ProctoredExamStudentViewTests(ProctoredExamTestCase):
context={
'is_proctored': True,
'display_name': self.exam_name,
'default_time_limit_mins': 90
'default_time_limit_mins': 90,
'verification_status': 'approved',
'verification_url': '/reverify',
}
)
self.assertIn(self.chose_proctored_exam_msg, rendered_response)
......@@ -354,7 +396,9 @@ class ProctoredExamStudentViewTests(ProctoredExamTestCase):
context={
'is_proctored': True,
'display_name': self.exam_name,
'default_time_limit_mins': 90
'default_time_limit_mins': 90,
'verification_status': 'approved',
'verification_url': '/reverify',
}
)
self.assertIn(self.chose_proctored_exam_msg, rendered_response)
......
......@@ -414,6 +414,7 @@ class TestStudentProctoredExamAttempt(LoggedInTestCase):
self.student_taking_exam = User()
self.student_taking_exam.save()
set_runtime_service('credit', MockCreditService())
set_runtime_service('instructor', MockInstructorService(is_user_course_staff=True))
def _create_exam_attempt(self):
......
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