Commit 98c6bf37 by Chris Dodge

address some review feedback

parent c57c8095
......@@ -418,6 +418,15 @@ def update_attempt_status(exam_id, user_id, to_status):
Internal helper to handle state transitions of attempt status
"""
# In some configuration we may treat timeouts the same
# as the user saying he/she wises to submit the exam
alias_timeout = (
to_status == ProctoredExamStudentAttemptStatus.timed_out and
not settings.PROCTORING_SETTINGS.get('ALLOW_TIMED_OUT_STATE', False)
)
if alias_timeout:
to_status = ProctoredExamStudentAttemptStatus.ready_to_submit
exam_attempt_obj = ProctoredExamStudentAttempt.objects.get_exam_attempt(exam_id, user_id)
if exam_attempt_obj is None:
raise StudentExamAttemptDoesNotExistsException('Error. Trying to look up an exam that does not exist.')
......
......@@ -39,6 +39,7 @@ def start_exam_callback(request, attempt_code): # pylint: disable=unused-argume
IMPORTANT: This is an unauthenticated endpoint, so be VERY CAREFUL about extending
this endpoint
"""
attempt = get_exam_attempt_by_code(attempt_code)
if not attempt:
return HttpResponse(
......
......@@ -102,7 +102,6 @@ var edx = edx || {};
return this;
},
unloadMessage: function () {
return null;
return gettext("As you are currently taking a proctored exam,\n" +
"you should not be navigation away from the exam.\n" +
"This may be considered as a violation of the \n" +
......@@ -115,10 +114,8 @@ var edx = edx || {};
var url = self.model.url + '/' + self.model.get('attempt_id');
$.ajax(url).success(function(data) {
if (data.status === 'error') {
// Let the student know that his exam has failed due to an error.
// This alert may or may not bring the browser window back to the
// foreground (depending on browser as well as user settings)
alert(gettext('Your exam has failed'));
// The proctoring session is in error state
// refresh the page to
clearInterval(self.timerId); // stop the timer once the time finishes.
$(window).unbind('beforeunload', self.unloadMessage);
// refresh the page when the timer expired
......
......@@ -53,6 +53,17 @@
var exam_id = $(this).data('exam-id');
var attempt_proctored = $(this).data('attempt-proctored');
var start_immediately = $(this).data('start-immediately');
if (!attempt_proctored) {
var msg = gettext(
"Are you sure you want to take this exam without proctoring? " +
"This will make you no longer eligible to earn credit for this course."
)
if (!confirm(msg)) {
return;
}
}
if (typeof action_url === "undefined" ) {
return false;
}
......
......@@ -51,11 +51,22 @@
var _waiting_for_proctored_interval = null;
$('.proctored-decline-exam').click(
function(event) {
function(e) {
e.preventDefault();
e.stopPropagation();
var action_url = $(this).data('change-state-url');
var exam_id = $(this).data('exam-id');
var action = $(this).data('action')
var msg = gettext(
"Are you sure you want to take this exam without proctoring? " +
"This will make you no longer eligible to earn credit for this course."
)
if (!confirm(msg)) {
return;
}
// Update the state of the attempt
$.ajax({
url: action_url,
......
......@@ -839,6 +839,7 @@ class ProctoredExamApiTests(LoggedInTestCase):
)
self.assertIsNone(rendered_response)
@patch.dict('django.conf.settings.PROCTORING_SETTINGS', {'ALLOW_TIMED_OUT_STATE': True})
def test_get_studentview_timedout(self):
"""
Verifies that if we call get_studentview when the timer has expired
......@@ -959,6 +960,7 @@ class ProctoredExamApiTests(LoggedInTestCase):
)
self.assertIn(self.proctored_exam_completed_msg, rendered_response)
@patch.dict('django.conf.settings.PROCTORING_SETTINGS', {'ALLOW_TIMED_OUT_STATE': True})
def test_get_studentview_expired(self):
"""
Test for get_student_view proctored exam which has expired.
......@@ -1095,6 +1097,7 @@ class ProctoredExamApiTests(LoggedInTestCase):
(ProctoredExamStudentAttemptStatus.error, ProctoredExamStudentAttemptStatus.started),
)
@ddt.unpack
@patch.dict('django.conf.settings.PROCTORING_SETTINGS', {'ALLOW_TIMED_OUT_STATE': True})
def test_illegal_status_transition(self, from_status, to_status):
"""
Verify that we cannot reset backwards an attempt status
......@@ -1109,9 +1112,28 @@ class ProctoredExamApiTests(LoggedInTestCase):
)
with self.assertRaises(ProctoredExamIllegalStatusTransition):
print '*** from = {} to {}'.format(from_status, to_status)
update_attempt_status(
exam_attempt.proctored_exam_id,
self.user.id,
to_status
)
def test_alias_timed_out(self):
"""
Verified that timed_out will automatically state transition
to ready_to_submit
"""
exam_attempt = self._create_started_exam_attempt()
update_attempt_status(
exam_attempt.proctored_exam_id,
self.user.id,
ProctoredExamStudentAttemptStatus.timed_out
)
exam_attempt = get_exam_attempt_by_id(exam_attempt.id)
self.assertEqual(
exam_attempt['status'],
ProctoredExamStudentAttemptStatus.ready_to_submit
)
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