Skip to content

Commit

Permalink
Improved test coverage
Browse files Browse the repository at this point in the history
Mildly refactored User model access to support alternate User models
  • Loading branch information
Dave St.Germain committed Feb 25, 2019
1 parent 89dda35 commit d04c737
Showing 5 changed files with 51 additions and 20 deletions.
10 changes: 6 additions & 4 deletions edx_proctoring/api.py
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@

from django.utils.translation import ugettext as _, ugettext_noop
from django.conf import settings
from django.contrib.auth.models import User
from django.contrib.auth import get_user_model
from django.template import loader
from django.urls import reverse, NoReverseMatch
from django.core.mail.message import EmailMessage
@@ -65,6 +65,8 @@

REJECTED_GRADE_OVERRIDE_EARNED = 0.0

USER_MODEL = get_user_model()


def create_exam(course_id, content_id, exam_name, time_limit_mins, due_date=None,
is_proctored=True, is_practice_exam=False, external_id=None, is_active=True, hide_after_due=False,
@@ -1078,7 +1080,7 @@ def create_proctoring_attempt_status_email(user_id, exam_attempt_obj, course_nam
if not exam_attempt_obj.taking_as_proctored or exam_attempt_obj.is_sample_attempt:
return None

user = User.objects.get(id=user_id)
user = USER_MODEL.objects.get(id=user_id)
course_info_url = ''
email_subject = (
_('Proctoring Results For {course_name} {exam_name}').format(
@@ -1558,7 +1560,7 @@ def get_attempt_status_summary(user_id, course_id, content_id):
# eligibility
if credit_service and not exam['is_practice_exam']:
credit_state = credit_service.get_credit_state(user_id, six.text_type(course_id), return_course_info=True)
user = User.objects.get(id=user_id)
user = USER_MODEL.objects.get(id=user_id)
if not user.has_perm('edx_proctoring.can_take_proctored_exam', exam):
return None

@@ -1852,7 +1854,7 @@ def _get_proctored_exam_view(exam, context, exam_id, user_id, course_id):
"""
student_view_template = None

user = User.objects.get(id=user_id)
user = USER_MODEL.objects.get(id=user_id)

if not user.has_perm('edx_proctoring.can_take_proctored_exam', exam):
return None
28 changes: 15 additions & 13 deletions edx_proctoring/models.py
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@
from __future__ import absolute_import
import six

from django.contrib.auth.models import User
from django.contrib.auth import get_user_model
from django.db import models
from django.db.models import Q
from django.db.models.base import ObjectDoesNotExist
@@ -24,6 +24,8 @@
)
from edx_proctoring.statuses import ProctoredExamStudentAttemptStatus, SoftwareSecureReviewStatus

USER_MODEL = get_user_model()


@six.python_2_unicode_compatible
class ProctoredExam(TimeStampedModel):
@@ -123,7 +125,7 @@ class ProctoredExamReviewPolicy(TimeStampedModel):
"""

# who set this ProctoredExamReviewPolicy
set_by_user = models.ForeignKey(User)
set_by_user = models.ForeignKey(USER_MODEL)

# for which exam?
proctored_exam = models.ForeignKey(ProctoredExam, db_index=True)
@@ -166,7 +168,7 @@ class ProctoredExamReviewPolicyHistory(TimeStampedModel):
original_id = models.IntegerField(db_index=True)

# who set this ProctoredExamReviewPolicy
set_by_user = models.ForeignKey(User)
set_by_user = models.ForeignKey(USER_MODEL)

# for which exam?
proctored_exam = models.ForeignKey(ProctoredExam, db_index=True)
@@ -287,7 +289,7 @@ class ProctoredExamStudentAttempt(TimeStampedModel):
"""
objects = ProctoredExamStudentAttemptManager()

user = models.ForeignKey(User, db_index=True)
user = models.ForeignKey(USER_MODEL, db_index=True)

proctored_exam = models.ForeignKey(ProctoredExam, db_index=True)

@@ -374,7 +376,7 @@ class ProctoredExamStudentAttemptHistory(TimeStampedModel):
but will record (for audit history) all entries that have been updated.
"""

user = models.ForeignKey(User, db_index=True)
user = models.ForeignKey(USER_MODEL, db_index=True)

# this is the PK of the original table, note this is not a FK
attempt_id = models.IntegerField(null=True)
@@ -497,7 +499,7 @@ class ProctoredExamStudentAllowance(TimeStampedModel):

objects = ProctoredExamStudentAllowanceManager()

user = models.ForeignKey(User)
user = models.ForeignKey(USER_MODEL)

proctored_exam = models.ForeignKey(ProctoredExam)

@@ -558,9 +560,9 @@ def add_allowance_for_user(cls, exam_id, user_info, key, value):
user_id = user_info
else:
# we got a string, so try to resolve it
users = User.objects.filter(username=user_info)
users = USER_MODEL.objects.filter(username=user_info)
if not users.exists():
users = User.objects.filter(email=user_info)
users = USER_MODEL.objects.filter(email=user_info)

if not users.exists():
err_msg = (
@@ -626,7 +628,7 @@ class ProctoredExamStudentAllowanceHistory(TimeStampedModel):
# what was the original id of the allowance
allowance_id = models.IntegerField()

user = models.ForeignKey(User)
user = models.ForeignKey(USER_MODEL)

proctored_exam = models.ForeignKey(ProctoredExam)

@@ -662,12 +664,12 @@ class ProctoredExamSoftwareSecureReview(TimeStampedModel):
video_url = models.TextField()

# user_id of person who did the review (can be None if submitted via server-to-server API)
reviewed_by = models.ForeignKey(User, null=True, related_name='+')
reviewed_by = models.ForeignKey(USER_MODEL, null=True, related_name='+')

# student username for the exam
# this is an optimization for the Django Admin pane (so we can search)
# this is null because it is being added after initial production ship
student = models.ForeignKey(User, null=True, related_name='+')
student = models.ForeignKey(USER_MODEL, null=True, related_name='+')

# exam_id for the review
# this is an optimization for the Django Admin pane (so we can search)
@@ -727,12 +729,12 @@ class ProctoredExamSoftwareSecureReviewHistory(TimeStampedModel):
video_url = models.TextField()

# user_id of person who did the review (can be None if submitted via server-to-server API)
reviewed_by = models.ForeignKey(User, null=True, related_name='+')
reviewed_by = models.ForeignKey(USER_MODEL, null=True, related_name='+')

# student username for the exam
# this is an optimization for the Django Admin pane (so we can search)
# this is null because it is being added after initial production ship
student = models.ForeignKey(User, null=True, related_name='+')
student = models.ForeignKey(USER_MODEL, null=True, related_name='+')

# exam_id for the review
# this is an optimization for the Django Admin pane (so we can search)
16 changes: 16 additions & 0 deletions edx_proctoring/tests/test_api.py
Original file line number Diff line number Diff line change
@@ -1618,6 +1618,22 @@ def test_practice_no_attempt(self):
)
self.assertIn(summary, [expected])

def test_status_summary_no_perm(self):
"""
The summary should be None for users who don't have permission
(For the tests, that means non-authenticated users)
"""
set_runtime_service('credit', MockCreditService(enrollment_mode='verified'))
exam_attempt = self._create_started_exam_attempt()
with patch('django.contrib.auth.models.User.is_authenticated', False):
summary = get_attempt_status_summary(
self.user.id,
exam_attempt.proctored_exam.course_id,
exam_attempt.proctored_exam.content_id
)

self.assertIsNone(summary)

def test_status_summary_bad(self):
"""
Make sure we get back a None when getting summary for content that does not
10 changes: 10 additions & 0 deletions edx_proctoring/tests/test_student_view.py
Original file line number Diff line number Diff line change
@@ -737,6 +737,16 @@ def test_get_studentview_submitted_status_with_duedate(self):
)
self.assertIsNotNone(rendered_response)

def test_get_no_perm_view(self):
"""
Test for get_student_view prompting when the student does not have permission
to view proctored exams, this should return None
(For edx-proctoring tests, only authenticated students have the permission)
"""
with patch('django.contrib.auth.models.User.is_authenticated', False):
rendered_response = self.render_proctored_exam()
self.assertIsNone(rendered_response)

def test_get_studentview_started_onboarding(self):
"""
Test fallthrough page case for onboarding exams
7 changes: 4 additions & 3 deletions edx_proctoring/views.py
Original file line number Diff line number Diff line change
@@ -11,7 +11,8 @@

from crum import get_current_request
from django.conf import settings
from django.contrib.auth.models import User
from django.contrib.auth import get_user_model
from django.core.exceptions import ObjectDoesNotExist
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.urls import reverse, NoReverseMatch
from django.shortcuts import redirect
@@ -858,8 +859,8 @@ def make_review(self, attempt, data, backend=None):
review.exam_id = attempt['proctored_exam']['id']

try:
review.reviewed_by = User.objects.get(email=data['reviewed_by'])
except (User.DoesNotExist, KeyError):
review.reviewed_by = get_user_model().objects.get(email=data['reviewed_by'])
except (ObjectDoesNotExist, KeyError):
review.reviewed_by = None

# If the reviewing user is a user in the system (user may be None for automated reviews) and does

0 comments on commit d04c737

Please sign in to comment.