Commit 66b468e7 by Chris Dodge

Declining a proctoring exam makes it open book and not eligibl for credit

parent ce90c0eb
......@@ -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