Files
edx-platform/lms/djangoapps/verify_student/tests/test_utils.py
2021-03-02 16:45:01 +05:00

168 lines
6.5 KiB
Python

"""
Tests for verify_student utility functions.
"""
import unittest
from datetime import timedelta
from unittest import mock
from unittest.mock import patch
import ddt
from django.conf import settings
from django.utils import timezone
from pytest import mark
from common.djangoapps.student.tests.factories import UserFactory
from lms.djangoapps.verify_student.models import ManualVerification, SoftwareSecurePhotoVerification, SSOVerification
from lms.djangoapps.verify_student.utils import (
most_recent_verification,
submit_request_to_ss,
verification_for_datetime
)
FAKE_SETTINGS = {
"DAYS_GOOD_FOR": 10,
}
@ddt.ddt
@patch.dict(settings.VERIFY_STUDENT, FAKE_SETTINGS)
@mark.django_db
class TestVerifyStudentUtils(unittest.TestCase):
"""
Tests for utility functions in verify_student.
"""
def test_verification_for_datetime(self):
user = UserFactory.create()
now = timezone.now()
# No attempts in the query set, so should return None
query = SoftwareSecurePhotoVerification.objects.filter(user=user)
result = verification_for_datetime(now, query)
assert result is None
# Should also return None if no deadline specified
query = SoftwareSecurePhotoVerification.objects.filter(user=user)
result = verification_for_datetime(None, query)
assert result is None
# Make an attempt
attempt = SoftwareSecurePhotoVerification.objects.create(user=user)
# Before the created date, should get no results
before = attempt.created_at - timedelta(seconds=1)
query = SoftwareSecurePhotoVerification.objects.filter(user=user)
result = verification_for_datetime(before, query)
assert result is None
# Immediately after the created date, should get the attempt
after_created = attempt.created_at + timedelta(seconds=1)
query = SoftwareSecurePhotoVerification.objects.filter(user=user)
result = verification_for_datetime(after_created, query)
assert result == attempt
# If no deadline specified, should return first available
query = SoftwareSecurePhotoVerification.objects.filter(user=user)
result = verification_for_datetime(None, query)
assert result == attempt
# Immediately before the expiration date, should get the attempt
expiration = attempt.expiration_datetime + timedelta(days=settings.VERIFY_STUDENT["DAYS_GOOD_FOR"])
before_expiration = expiration - timedelta(seconds=1)
query = SoftwareSecurePhotoVerification.objects.filter(user=user)
result = verification_for_datetime(before_expiration, query)
assert result == attempt
# Immediately after the expiration date, should not get the attempt
attempt.expiration_date = now - timedelta(seconds=1)
attempt.save()
after = now + timedelta(days=1)
query = SoftwareSecurePhotoVerification.objects.filter(user=user)
result = verification_for_datetime(after, query)
assert result is None
# Create a second attempt in the same window
second_attempt = SoftwareSecurePhotoVerification.objects.create(user=user)
# Now we should get the newer attempt
deadline = second_attempt.created_at + timedelta(days=1)
query = SoftwareSecurePhotoVerification.objects.filter(user=user)
result = verification_for_datetime(deadline, query)
assert result == second_attempt
@ddt.data(
(False, False, False, None, None),
(True, False, False, None, 'photo'),
(False, True, False, None, 'sso'),
(False, False, True, None, 'manual'),
(True, True, True, 'photo', 'sso'),
(True, True, True, 'sso', 'photo'),
(True, True, True, 'manual', 'photo')
)
@ddt.unpack
def test_most_recent_verification(
self,
create_photo_verification,
create_sso_verification,
create_manual_verification,
first_verification,
expected_verification):
user = UserFactory.create()
photo_verification = None
sso_verification = None
manual_verification = None
if not first_verification:
if create_photo_verification:
photo_verification = SoftwareSecurePhotoVerification.objects.create(user=user)
if create_sso_verification:
sso_verification = SSOVerification.objects.create(user=user)
if create_manual_verification:
manual_verification = ManualVerification.objects.create(user=user)
elif first_verification == 'photo':
photo_verification = SoftwareSecurePhotoVerification.objects.create(user=user)
sso_verification = SSOVerification.objects.create(user=user)
elif first_verification == 'sso':
sso_verification = SSOVerification.objects.create(user=user)
photo_verification = SoftwareSecurePhotoVerification.objects.create(user=user)
else:
manual_verification = ManualVerification.objects.create(user=user)
photo_verification = SoftwareSecurePhotoVerification.objects.create(user=user)
most_recent = most_recent_verification(
SoftwareSecurePhotoVerification.objects.all(),
SSOVerification.objects.all(),
ManualVerification.objects.all(),
'created_at'
)
if not expected_verification:
assert most_recent is None
elif expected_verification == 'photo':
assert most_recent == photo_verification
elif expected_verification == 'sso':
assert most_recent == sso_verification
else:
assert most_recent == manual_verification
@mock.patch('lms.djangoapps.verify_student.utils.log')
@mock.patch(
'lms.djangoapps.verify_student.tasks.send_request_to_ss_for_user.delay', mock.Mock(side_effect=Exception('error')) # lint-amnesty, pylint: disable=line-too-long
)
def test_submit_request_to_ss(self, mock_log):
"""Tests that we log appropriate information when celery task creation fails."""
user = UserFactory.create()
attempt = SoftwareSecurePhotoVerification.objects.create(user=user)
attempt.mark_ready()
submit_request_to_ss(user_verification=attempt, copy_id_photo_from=None)
mock_log.error.assert_called_with(
"Software Secure submit request %r failed, result: %s",
user.username,
'error'
)
assert attempt.status, SoftwareSecurePhotoVerification.STATUS.must_retry