Skip to content

Commit

Permalink
Revert "block starting session while one session is 'started' status"
Browse files Browse the repository at this point in the history
This reverts commit c8a09ce.
  • Loading branch information
Matt Hughes committed Jan 22, 2019
1 parent 4b7b298 commit a19cc37
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 194 deletions.
203 changes: 77 additions & 126 deletions edx_proctoring/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1246,8 +1246,8 @@ def get_last_exam_completion_date(course_id, username):
def get_active_exams_for_user(user_id, course_id=None):
"""
This method will return a list of active exams for the user,
i.e. started_at != None and completed_at == None. There will only
be one.
i.e. started_at != None and completed_at == None. Theoretically there
could be more than one, but in practice it will be one active exam.
If course_id is set, then attempts only for an exam in that course_id
should be returned.
Expand Down Expand Up @@ -1610,12 +1610,7 @@ def _get_timed_exam_view(exam, context, exam_id, user_id, course_id):
if has_due_date_passed(exam['due_date']):
student_view_template = 'timed_exam/expired.html'
else:
is_other_exam, other_exam_url = _get_running_exam_info(user_id, exam_id)
if is_other_exam:
context.update({'exam_url': other_exam_url})
student_view_template = 'proctored_exam/other_exam_in_progress.html'
else:
student_view_template = 'timed_exam/entrance.html'
student_view_template = 'timed_exam/entrance.html'
elif attempt_status == ProctoredExamStudentAttemptStatus.started:
# when we're taking the exam we should not override the view
return None
Expand Down Expand Up @@ -1777,28 +1772,16 @@ def _get_practice_exam_view(exam, context, exam_id, user_id, course_id):

attempt_status = attempt['status'] if attempt else None

if attempt_status == ProctoredExamStudentAttemptStatus.started:
if not attempt_status:
student_view_template = 'practice_exam/entrance.html'
elif attempt_status == ProctoredExamStudentAttemptStatus.started:
# when we're taking the exam we should not override the view
return None
elif not attempt_status or attempt_status in [
ProctoredExamStudentAttemptStatus.created,
ProctoredExamStudentAttemptStatus.download_software_clicked,
ProctoredExamStudentAttemptStatus.ready_to_start,
]:
is_other_exam, other_exam_url = _get_running_exam_info(user_id, exam_id)
if is_other_exam:
context.update({'exam_url': other_exam_url})
student_view_template = 'proctored_exam/other_exam_in_progress.html'
elif not attempt_status:
student_view_template = 'practice_exam/entrance.html'
elif attempt_status in [
ProctoredExamStudentAttemptStatus.created,
ProctoredExamStudentAttemptStatus.download_software_clicked,
]:
student_view_template = 'proctored_exam/instructions.html'
else:
# note: then the status must be ready_to_start
student_view_template = 'proctored_exam/ready_to_start.html'
elif attempt_status in [ProctoredExamStudentAttemptStatus.created,
ProctoredExamStudentAttemptStatus.download_software_clicked]:
student_view_template = 'proctored_exam/instructions.html'
elif attempt_status == ProctoredExamStudentAttemptStatus.ready_to_start:
student_view_template = 'proctored_exam/ready_to_start.html'
elif attempt_status == ProctoredExamStudentAttemptStatus.error:
student_view_template = 'practice_exam/error.html'
elif attempt_status == ProctoredExamStudentAttemptStatus.submitted:
Expand Down Expand Up @@ -1842,90 +1825,79 @@ def _get_proctored_exam_view(exam, context, exam_id, user_id, course_id):
if attempt_status == ProctoredExamStudentAttemptStatus.declined:
return None

if attempt_status == ProctoredExamStudentAttemptStatus.started:
# when we're taking the exam we should not override the view
return None
elif not attempt_status or attempt_status in [
ProctoredExamStudentAttemptStatus.created,
ProctoredExamStudentAttemptStatus.download_software_clicked,
ProctoredExamStudentAttemptStatus.ready_to_start,
]:
is_other_exam, other_exam_url = _get_running_exam_info(user_id, exam_id)
if is_other_exam:
context.update({'exam_url': other_exam_url})
student_view_template = 'proctored_exam/other_exam_in_progress.html'
elif not attempt_status:
# student has not started an attempt
# so, show them:
# 1) If there are failed prerequisites then block user and say why
# 2) If there are pending prerequisites then block user and allow them to remediate them
# 3) If there are declined prerequisites, then we auto-decline proctoring since user
# explicitly declined their interest in credit
# 4) Otherwise - all prerequisites are satisfied - then give user
# option to take exam as proctored

# get information about prerequisites

credit_requirement_status = (
credit_state.get('credit_requirement_status')
if credit_state else []
)
if not attempt_status:
# student has not started an attempt
# so, show them:
# 1) If there are failed prerequisites then block user and say why
# 2) If there are pending prerequisites then block user and allow them to remediate them
# 3) If there are declined prerequisites, then we auto-decline proctoring since user
# explicitly declined their interest in credit
# 4) Otherwise - all prerequisites are satisfied - then give user
# option to take exam as proctored

# get information about prerequisites

credit_requirement_status = (
credit_state.get('credit_requirement_status')
if credit_state else []
)

prerequisite_status = _are_prerequirements_satisfied(
credit_requirement_status,
evaluate_for_requirement_name=exam['content_id'],
filter_out_namespaces=['grade']
)
prerequisite_status = _are_prerequirements_satisfied(
credit_requirement_status,
evaluate_for_requirement_name=exam['content_id'],
filter_out_namespaces=['grade']
)

# add any prerequisite information, if applicable
context.update({
'prerequisite_status': prerequisite_status
})
# add any prerequisite information, if applicable
context.update({
'prerequisite_status': prerequisite_status
})

# if exam due date has passed, then we can't take the exam
if has_due_date_passed(exam['due_date']):
student_view_template = 'proctored_exam/expired.html'
elif not prerequisite_status['are_prerequisites_satisifed']:
# do we have any declined prerequisites, if so, then we
# will auto-decline this proctored exam
if prerequisite_status['declined_prerequisites']:
# user hasn't a record of attempt, create one now
# so we can mark it as declined
_create_and_decline_attempt(exam_id, user_id)
return None

# if exam due date has passed, then we can't take the exam
if has_due_date_passed(exam['due_date']):
student_view_template = 'proctored_exam/expired.html'
elif not prerequisite_status['are_prerequisites_satisifed']:
# do we have any declined prerequisites, if so, then we
# will auto-decline this proctored exam
if prerequisite_status['declined_prerequisites']:
# user hasn't a record of attempt, create one now
# so we can mark it as declined
_create_and_decline_attempt(exam_id, user_id)
return None

# do we have failed prerequisites? That takes priority in terms of
# messaging
if prerequisite_status['failed_prerequisites']:
# Let's resolve the URLs to jump to this prequisite
prerequisite_status['failed_prerequisites'] = _resolve_prerequisite_links(
exam,
prerequisite_status['failed_prerequisites']
)
student_view_template = 'proctored_exam/failed-prerequisites.html'
else:
# Let's resolve the URLs to jump to this prequisite
prerequisite_status['pending_prerequisites'] = _resolve_prerequisite_links(
exam,
prerequisite_status['pending_prerequisites']
)
student_view_template = 'proctored_exam/pending-prerequisites.html'
# do we have failed prerequisites? That takes priority in terms of
# messaging
if prerequisite_status['failed_prerequisites']:
# Let's resolve the URLs to jump to this prequisite
prerequisite_status['failed_prerequisites'] = _resolve_prerequisite_links(
exam,
prerequisite_status['failed_prerequisites']
)
student_view_template = 'proctored_exam/failed-prerequisites.html'
else:
student_view_template = 'proctored_exam/entrance.html'
# emit an event that the user was presented with the option
# to start timed exam
emit_event(exam, 'option-presented')
elif context.get('verification_status') is not APPROVED_STATUS:
# Let's resolve the URLs to jump to this prequisite
prerequisite_status['pending_prerequisites'] = _resolve_prerequisite_links(
exam,
prerequisite_status['pending_prerequisites']
)
student_view_template = 'proctored_exam/pending-prerequisites.html'
else:
student_view_template = 'proctored_exam/entrance.html'
# emit an event that the user was presented with the option
# to start timed exam
emit_event(exam, 'option-presented')
elif attempt_status == ProctoredExamStudentAttemptStatus.started:
# when we're taking the exam we should not override the view
return None
elif attempt_status in [ProctoredExamStudentAttemptStatus.created,
ProctoredExamStudentAttemptStatus.download_software_clicked]:
if context.get('verification_status') is not APPROVED_STATUS:
# 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'
elif attempt_status in [
ProctoredExamStudentAttemptStatus.created,
ProctoredExamStudentAttemptStatus.download_software_clicked,
]:
student_view_template = 'proctored_exam/instructions.html'
else:
# note: then the status must be ready_to_start
student_view_template = 'proctored_exam/ready_to_start.html'
student_view_template = 'proctored_exam/instructions.html'
elif attempt_status == ProctoredExamStudentAttemptStatus.ready_to_start:
student_view_template = 'proctored_exam/ready_to_start.html'
elif attempt_status == ProctoredExamStudentAttemptStatus.error:
student_view_template = 'proctored_exam/error.html'
elif attempt_status == ProctoredExamStudentAttemptStatus.timed_out:
Expand Down Expand Up @@ -2033,27 +2005,6 @@ def get_student_view(user_id, course_id, content_id,
return None


def _get_running_exam_info(user_id, currently_visited_exam_id):
"""
Check whether there are any other currently active exams besides
that currently being viewed
"""
active_exam_attempts = get_active_exams_for_user(user_id)
if active_exam_attempts:
active_exam = active_exam_attempts[0]['exam']
is_other_exam_running = active_exam['id'] != currently_visited_exam_id
try:
# resolve the LMS url, note we can't assume we're running in
# a same process as the LMS
other_exam_url = reverse('jump_to', args=[active_exam['course_id'], active_exam['content_id']])
except NoReverseMatch:
log.exception("Can't find exam url for course %s", active_exam['course_id'])
other_exam_url = ''
else:
is_other_exam_running, other_exam_url = False, ''
return is_other_exam_running, other_exam_url


def get_exam_violation_report(course_id, include_practice_exams=False):
"""
Returns proctored exam attempts for the course id, including review details.
Expand Down

This file was deleted.

53 changes: 0 additions & 53 deletions edx_proctoring/tests/test_student_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ def setUp(self):
self.practice_exam_submitted_msg = 'You have submitted this practice proctored exam'
self.take_exam_without_proctoring_msg = 'Take this exam without proctoring'
self.ready_to_start_msg = 'Important'
self.complete_other_exam_first_msg = 'Complete in-progress exam'
self.footer_msg = 'About Proctored Exams'
self.timed_footer_msg = 'Can I request additional time to complete my exam?'

Expand Down Expand Up @@ -132,18 +131,6 @@ def render_practice_exam(self, context_overrides=None):
context_overrides=exam_context_overrides
)

def render_timed_exam(self):
"""
Renders a test timed exam
"""
exam_context_overrides = {
'is_proctored': False
}
return self._render_exam(
self.timed_exam_id,
context_overrides=exam_context_overrides
)

def test_get_student_view(self):
"""
Test for get_student_view prompting the user to take the exam
Expand Down Expand Up @@ -470,46 +457,6 @@ def test_declined_attempt(self):
rendered_response = self.render_proctored_exam()
self.assertIsNone(rendered_response)

def test_get_studentview_exam_in_progress(self):
"""
Assert that we get the right content when another exam was
started first
"""
self._create_started_exam_attempt()
self.content_id = self.content_id + '_new'
self.proctored_exam_id = self._create_proctored_exam()
unstarted_attempt = self._create_unstarted_exam_attempt()

unstarted_attempt.status = ProctoredExamStudentAttemptStatus.created
unstarted_attempt.save()

rendered_response = self.render_proctored_exam()
self.assertIn(self.complete_other_exam_first_msg, rendered_response)

def test_get_studentview_exam_in_progress_timed(self):
"""
Assert that we get the right content when another exam was
started first for timed and practice exams
"""
self._create_started_exam_attempt()

rendered_response = self.render_timed_exam()
self.assertIn(self.complete_other_exam_first_msg, rendered_response)

def test_get_studentview_exam_in_progress_practice(self):
"""
Assert that we get the right content when another exam was
started first for timed and practice exams
"""
self._create_started_exam_attempt()
unstarted_attempt = self._create_unstarted_exam_attempt(is_practice=True)

unstarted_attempt.status = ProctoredExamStudentAttemptStatus.created
unstarted_attempt.save()

rendered_response = self.render_practice_exam()
self.assertIn(self.complete_other_exam_first_msg, rendered_response)

def test_get_studentview_ready(self):
"""
Assert that we get the right content
Expand Down

0 comments on commit a19cc37

Please sign in to comment.