Commit 6ef5eec6 by Andy Armstrong

Introduce id verification step for proctored exams

TNL-5083
parent f2c320fb
...@@ -1641,6 +1641,7 @@ def _get_proctored_exam_view(exam, context, exam_id, user_id, course_id): ...@@ -1641,6 +1641,7 @@ def _get_proctored_exam_view(exam, context, exam_id, user_id, course_id):
student_view_template = None student_view_template = None
credit_state = context.get('credit_state') 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 # see if only 'verified' track students should see this *except* if it is a practice exam
check_mode = ( check_mode = (
...@@ -1720,6 +1721,8 @@ def _get_proctored_exam_view(exam, context, exam_id, user_id, course_id): ...@@ -1720,6 +1721,8 @@ def _get_proctored_exam_view(exam, context, exam_id, user_id, course_id):
prerequisite_status['pending_prerequisites'] prerequisite_status['pending_prerequisites']
) )
student_view_template = 'proctored_exam/pending-prerequisites.html' student_view_template = 'proctored_exam/pending-prerequisites.html'
elif verification_status is not 'approved':
student_view_template = 'proctored_exam/id_verification.html'
else: else:
student_view_template = 'proctored_exam/entrance.html' student_view_template = 'proctored_exam/entrance.html'
# emit an event that the user was presented with the option # emit an event that the user was presented with the option
......
{% 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 @@ ...@@ -35,7 +35,9 @@
</p> </p>
<p> <p>
{% blocktrans %} {% 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 %} {% endblocktrans %}
</p> </p>
<p> <p>
......
...@@ -82,6 +82,8 @@ class ProctoredExamStudentViewTests(ProctoredExamTestCase): ...@@ -82,6 +82,8 @@ class ProctoredExamStudentViewTests(ProctoredExamTestCase):
'display_name': self.exam_name, 'display_name': self.exam_name,
'default_time_limit_mins': 90, 'default_time_limit_mins': 90,
'hide_after_due': False, 'hide_after_due': False,
'verification_status': 'approved',
'verification_url': '/reverify',
} }
) )
self.assertIn( self.assertIn(
...@@ -149,6 +151,42 @@ class ProctoredExamStudentViewTests(ProctoredExamTestCase): ...@@ -149,6 +151,42 @@ class ProctoredExamStudentViewTests(ProctoredExamTestCase):
self.assertIsNone(rendered_response) self.assertIsNone(rendered_response)
@ddt.data( @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 for their current status.
"""
exam = get_exam_by_id(self.proctored_exam_id)
rendered_response = get_student_view(
user_id=self.user_id,
course_id=exam['course_id'],
content_id=exam['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', 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', 'pending', 'The following prerequisites are in a <strong>pending</strong> state', True),
('reverification', 'failed', 'You did not satisfy the following prerequisites', True), ('reverification', 'failed', 'You did not satisfy the following prerequisites', True),
...@@ -196,6 +234,8 @@ class ProctoredExamStudentViewTests(ProctoredExamTestCase): ...@@ -196,6 +234,8 @@ class ProctoredExamStudentViewTests(ProctoredExamTestCase):
} }
] ]
}, },
'verification_status': 'approved',
'verification_url': '/reverify',
} }
) )
......
...@@ -414,6 +414,7 @@ class TestStudentProctoredExamAttempt(LoggedInTestCase): ...@@ -414,6 +414,7 @@ class TestStudentProctoredExamAttempt(LoggedInTestCase):
self.student_taking_exam = User() self.student_taking_exam = User()
self.student_taking_exam.save() self.student_taking_exam.save()
set_runtime_service('credit', MockCreditService())
set_runtime_service('instructor', MockInstructorService(is_user_course_staff=True)) set_runtime_service('instructor', MockInstructorService(is_user_course_staff=True))
def _create_exam_attempt(self): 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