Commit f22b9b30 by chrisndodge

Merge pull request #55 from edx/cdodge/decline-proctoring

Cdodge/decline proctoring
parents ce90c0eb ebe66950
......@@ -633,8 +633,13 @@ def get_student_view(user_id, course_id, content_id,
return None
attempt = get_exam_attempt(exam_id, user_id)
has_started_exam = attempt and attempt.get('started_at')
# if user has declined the attempt, then we don't show the
# proctored exam
if attempt and attempt['status'] == ProctoredExamStudentAttemptStatus.declined:
return None
has_started_exam = attempt and attempt.get('started_at')
if has_started_exam:
if attempt.get('status') == 'error':
student_view_template = 'proctoring/seq_proctored_exam_error.html'
......
......@@ -788,6 +788,26 @@ class ProctoredExamApiTests(LoggedInTestCase):
)
self.assertIn(self.chose_proctored_exam_msg % self.exam_name, rendered_response)
def test_declined_attempt(self):
"""
Make sure that a declined attempt does not show proctoring
"""
attempt_obj = self._create_unstarted_exam_attempt()
attempt_obj.status = ProctoredExamStudentAttemptStatus.declined
attempt_obj.save()
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
}
)
self.assertIsNone(rendered_response)
def test_get_studentview_started_exam(self): # pylint: disable=invalid-name
"""
Test for get_student_view proctored exam which has started.
......
......@@ -29,7 +29,7 @@ from edx_proctoring.urls import urlpatterns
from edx_proctoring.backends.tests.test_review_payload import TEST_REVIEW_PAYLOAD
from edx_proctoring.backends.tests.test_software_secure import mock_response_content
from edx_proctoring.tests.test_services import MockCreditService
from edx_proctoring.runtime import set_runtime_service
from edx_proctoring.runtime import set_runtime_service, get_runtime_service
class ProctoredExamsApiTests(LoggedInTestCase):
......@@ -42,6 +42,7 @@ class ProctoredExamsApiTests(LoggedInTestCase):
Build out test harnessing
"""
super(ProctoredExamsApiTests, self).setUp()
set_runtime_service('credit', MockCreditService())
def test_no_anonymous_access(self):
"""
......@@ -950,6 +951,42 @@ class TestStudentProctoredExamAttempt(LoggedInTestCase):
)
self.assertEqual(response.status_code, 200)
def test_declined_attempt(self):
"""
Makes sure that a declined proctored attempt means that he/she fails credit requirement.
"""
# Create an exam.
proctored_exam = ProctoredExam.objects.create(
course_id='a/b/c',
content_id='test_content',
exam_name='Test Exam',
external_id='123aXqe3',
is_proctored=True,
time_limit_mins=90
)
attempt_data = {
'exam_id': proctored_exam.id,
'start_clock': False,
'attempt_proctored': False
}
# create a exam attempt
response = self.client.post(
reverse('edx_proctoring.proctored_exam.attempt.collection'),
attempt_data
)
self.assertEqual(response.status_code, 200)
# make sure we failed the requirement status
credit_service = get_runtime_service('credit')
credit_status = credit_service.get_credit_state(self.user.id, proctored_exam.course_id)
self.assertEqual(len(credit_status['credit_requirement_status']), 1)
self.assertEqual(
credit_status['credit_requirement_status'][0]['status'],
'failed'
)
def test_exam_callback(self):
"""
Start an exam (create an exam attempt)
......
......@@ -30,7 +30,8 @@ from edx_proctoring.api import (
get_all_exam_attempts,
remove_exam_attempt,
get_filtered_exam_attempts,
update_exam_attempt
update_exam_attempt,
update_attempt_status
)
from edx_proctoring.exceptions import (
ProctoredBaseException,
......@@ -40,6 +41,7 @@ from edx_proctoring.exceptions import (
StudentExamAttemptDoesNotExistsException,
)
from edx_proctoring.serializers import ProctoredExamSerializer
from edx_proctoring.models import ProctoredExamStudentAttemptStatus
from .utils import AuthenticatedAPIView
......@@ -528,7 +530,17 @@ class StudentProctoredExamAttemptCollection(AuthenticatedAPIView):
taking_as_proctored=attempt_proctored
)
if start_immediately:
exam = get_exam_by_id(exam_id)
# if use elected not to take as proctored exam, then
# use must take as open book, and loose credit eligibility
if exam['is_proctored'] and not attempt_proctored:
update_attempt_status(
exam_id,
request.user.id,
ProctoredExamStudentAttemptStatus.declined
)
elif start_immediately:
start_exam_attempt(exam_id, request.user.id)
return Response({'exam_attempt_id': exam_attempt_id})
......
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