Skip to content

Commit

Permalink
Add IDV Status to VerifiedName (#215)
Browse files Browse the repository at this point in the history
* feat: Adding IDV Status to VerifiedName

* fix: Moved attempt status getter from Serialized to Model

* fix: Reverted Views unit tests

* fix: Updated tests

* chore: Added proper tests to model

* fix: Added catch to not found exception

* chore: Updated tests

* fix: Updated tests

* chore: Moved test variables to be more localized

* chore: Moved test variables to be more localized
  • Loading branch information
rijuma authored Sep 9, 2024
1 parent 70093bc commit bf0493f
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 4 deletions.
20 changes: 20 additions & 0 deletions edx_name_affirmation/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,16 @@
from simple_history.models import HistoricalRecords

from django.contrib.auth import get_user_model
from django.core.exceptions import ObjectDoesNotExist
from django.db import models

from edx_name_affirmation.statuses import VerifiedNameStatus

try:
from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification
except ImportError:
SoftwareSecurePhotoVerification = None

User = get_user_model()


Expand Down Expand Up @@ -45,6 +51,20 @@ class Meta:
db_table = 'nameaffirmation_verifiedname'
verbose_name = 'verified name'

@property
def verification_attempt_status(self):
"Returns the status associated with its SoftwareSecurePhotoVerification with verification_attempt_id if any."

if not self.verification_attempt_id or not SoftwareSecurePhotoVerification:
return None

try:
verification = SoftwareSecurePhotoVerification.objects.get(id=self.verification_attempt_id)
return verification.status

except ObjectDoesNotExist:
return None


class VerifiedNameConfig(ConfigurationModel):
"""
Expand Down
3 changes: 2 additions & 1 deletion edx_name_affirmation/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class VerifiedNameSerializer(serializers.ModelSerializer):
verified_name = serializers.CharField(required=True)
profile_name = serializers.CharField(required=True)
verification_attempt_id = serializers.IntegerField(required=False, allow_null=True)
verification_attempt_status = serializers.CharField(required=False, allow_null=True)
proctored_exam_attempt_id = serializers.IntegerField(required=False, allow_null=True)
status = serializers.CharField(required=False, allow_null=True)

Expand All @@ -30,7 +31,7 @@ class Meta:

fields = (
"id", "created", "username", "verified_name", "profile_name", "verification_attempt_id",
"proctored_exam_attempt_id", "status"
"verification_attempt_status", "proctored_exam_attempt_id", "status"
)

def validate_verified_name(self, verified_name):
Expand Down
44 changes: 41 additions & 3 deletions edx_name_affirmation/tests/test_models.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
"""
Tests for Name Affirmation models
"""
from unittest.mock import patch

from django.contrib.auth import get_user_model
from django.core.exceptions import ObjectDoesNotExist
from django.test import TestCase

from edx_name_affirmation.models import VerifiedName
Expand All @@ -16,6 +18,9 @@ class VerifiedNameModelTests(TestCase):
Test suite for the VerifiedName models
"""
def setUp(self):
self.idv_attempt_id = 34455
self.idv_attempt_status = 'submitted'
self.idv_attempt_id_notfound = 404
self.verified_name = 'Test Tester'
self.user = User.objects.create(username='modelTester', email='[email protected]')
self.verified_name = VerifiedName.objects.create(
Expand All @@ -29,11 +34,11 @@ def test_histories(self):
"""
Test the model history is recording records as expected
"""

verified_name_history = self.verified_name.history.all().order_by('history_date')
assert len(verified_name_history) == 1
idv_attempt_id = 34455
self.verified_name.status = VerifiedNameStatus.APPROVED
self.verified_name.verification_attempt_id = idv_attempt_id
self.verified_name.verification_attempt_id = self.idv_attempt_id
self.verified_name.save()
verified_name_history = self.verified_name.history.all().order_by('history_date')
assert len(verified_name_history) == 2
Expand All @@ -44,4 +49,37 @@ def test_histories(self):

second_history_record = verified_name_history[1]
assert second_history_record.status == VerifiedNameStatus.APPROVED
assert second_history_record.verification_attempt_id == idv_attempt_id
assert second_history_record.verification_attempt_id == self.idv_attempt_id

@patch('edx_name_affirmation.models.SoftwareSecurePhotoVerification')
def test_verification_status(self, sspv_mock):
"""
Test the model history is recording records as expected
"""

idv_attempt_id_notfound_status = None

sspv_mock.objects.get = self._mocked_model_get

self.verified_name.verification_attempt_id = self.idv_attempt_id_notfound
assert self.verified_name.verification_attempt_status is idv_attempt_id_notfound_status

self.verified_name.verification_attempt_id = self.idv_attempt_id
assert self.verified_name.verification_attempt_status is self.idv_attempt_status

# Helper methods

def _obj(self, dictionary):
"Helper method to turn a dict into an object. Used to mock below."

return type('obj', (object,), dictionary)

def _mocked_model_get(self, id): # pylint: disable=redefined-builtin
"Helper method to mock the behavior of SoftwareSecurePhotoVerification model. Used to mock below."
if id == self.idv_attempt_id_notfound:
raise ObjectDoesNotExist

if id == self.idv_attempt_id:
return self._obj({'status': self.idv_attempt_status})

return self._obj({'status': None})
22 changes: 22 additions & 0 deletions edx_name_affirmation/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
All tests for edx_name_affirmation views
"""
import json
from unittest.mock import PropertyMock, patch

import ddt

Expand Down Expand Up @@ -357,6 +358,7 @@ def _get_expected_data(
'verified_name': verified_name_obj.verified_name,
'profile_name': verified_name_obj.profile_name,
'verification_attempt_id': verified_name_obj.verification_attempt_id,
'verification_attempt_status': None,
'proctored_exam_attempt_id': verified_name_obj.proctored_exam_attempt_id,
'status': verified_name_obj.status,
'use_verified_name_for_certs': use_verified_name_for_certs,
Expand All @@ -379,6 +381,25 @@ def test_get(self):
data = json.loads(response.content.decode('utf-8'))
self.assertEqual(data, expected_response)

@patch('edx_name_affirmation.api.VerifiedName.verification_attempt_status', new_callable=PropertyMock)
def test_get_with_idv_status(self, verification_attempt_status_mock):
mocked_idv_status = 'approved'

verification_attempt_status_mock.return_value = mocked_idv_status
verified_name_history = self._create_verified_name_history(self.user)
expected_response = self._get_expected_response(self.user, verified_name_history)

# replacing the expected response results with the mocked status
for row in expected_response['results']:
row['verification_attempt_status'] = mocked_idv_status

response = self.client.get(reverse('edx_name_affirmation:verified_name_history'))

self.assertEqual(response.status_code, 200)
data = json.loads(response.content.decode('utf-8'))

self.assertEqual(data, expected_response)

def test_get_bools(self):
verified_name_history = self._create_verified_name_history(self.user)
expected_response = self._get_expected_response(
Expand Down Expand Up @@ -456,6 +477,7 @@ def _get_expected_response(
'verified_name': verified_name_obj.verified_name,
'profile_name': verified_name_obj.profile_name,
'verification_attempt_id': verified_name_obj.verification_attempt_id,
'verification_attempt_status': None,
'proctored_exam_attempt_id': verified_name_obj.proctored_exam_attempt_id,
'status': verified_name_obj.status
}
Expand Down

0 comments on commit bf0493f

Please sign in to comment.