Skip to content

Commit

Permalink
test: [AXM-1249] add tests and fix existing tests
Browse files Browse the repository at this point in the history
  • Loading branch information
kyrylo-kh committed Dec 20, 2024
1 parent 6afcdc7 commit 5c1c6fe
Show file tree
Hide file tree
Showing 6 changed files with 215 additions and 16 deletions.
5 changes: 2 additions & 3 deletions credentials/apps/badges/issuers.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
)
from credentials.apps.badges.credly.api_client import CredlyAPIClient
from credentials.apps.badges.credly.data import CredlyBadgeData
from credentials.apps.badges.credly.exceptions import CredlyAPIError
from credentials.apps.badges.exceptions import BadgeProviderError
from credentials.apps.badges.models import (
BadgeTemplate,
Expand Down Expand Up @@ -246,7 +245,7 @@ def issue_accredible_badge(self, *, user_credential):
)

try:
accredible_api = AccredibleAPIClient(group.api_config)
accredible_api = AccredibleAPIClient(group.api_config.id)
response = accredible_api.issue_badge(accredible_badge_data)
except BadgeProviderError:
user_credential.state = "error"
Expand All @@ -263,7 +262,7 @@ def revoke_accredible_badge(self, credential_id, user_credential):
"""

credential = self.get_credential(credential_id)
accredible_api_client = AccredibleAPIClient(credential.api_config)
accredible_api_client = AccredibleAPIClient(credential.api_config.id)
revoke_badge_data = AccredibleExpireBadgeData(
credential=AccredibleExpiredCredential(expired_on=datetime.now().strftime("%Y-%m-%d %H:%M:%S %z"))
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ def setUp(self):
recipient=AccredibleRecipient(name="Test name", email="test_name@test.com"),
group_id=123,
name="Test Badge",
description="Test Badge Description",
issued_on="2021-01-01 00:00:00 +0000",
complete=True,
)
Expand Down
10 changes: 5 additions & 5 deletions credentials/apps/badges/tests/test_admin_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
DataRuleExtensionsMixin,
ParentMixin,
)
from credentials.apps.badges.credly.exceptions import CredlyAPIError
from credentials.apps.badges.exceptions import BadgeProviderError
from credentials.apps.badges.models import BadgeRequirement, BadgeTemplate


Expand Down Expand Up @@ -132,7 +132,7 @@ def test_clean_with_invalid_organization(self):
) as mock_get_orgs:
mock_get_orgs.return_value = {"test_uuid": "test_org"}

with self.assertRaises(forms.ValidationError) as cm:
with self.assertRaises(BadgeProviderError) as cm:
form.clean()

self.assertIn("You specified an invalid authorization token.", str(cm.exception))
Expand Down Expand Up @@ -170,13 +170,13 @@ def test_ensure_organization_exists(self):
def test_ensure_organization_exists_with_error(self):
form = CredlyOrganizationAdminForm()
api_client = MagicMock()
api_client.fetch_organization.side_effect = CredlyAPIError("API Error")
api_client.fetch_organization.side_effect = BadgeProviderError("API Error")

with self.assertRaises(forms.ValidationError) as cm:
with self.assertRaises(BadgeProviderError) as cm:
form.ensure_organization_exists(api_client)

api_client.fetch_organization.assert_called_once()
self.assertEqual(str(cm.exception), "['API Error']")
self.assertEqual(str(cm.exception), "API Error")


class TestParentMixin(ParentMixin):
Expand Down
163 changes: 156 additions & 7 deletions credentials/apps/badges/tests/test_issuers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,18 @@
from django.contrib.contenttypes.models import ContentType
from django.test import TestCase

from credentials.apps.badges.exceptions import BadgeProviderError
from credentials.apps.badges.accredible.api_client import AccredibleAPIClient
from credentials.apps.badges.credly.api_client import CredlyAPIClient
from credentials.apps.badges.credly.exceptions import CredlyAPIError
from credentials.apps.badges.issuers import CredlyBadgeTemplateIssuer
from credentials.apps.badges.models import CredlyBadge, CredlyBadgeTemplate, CredlyOrganization
from credentials.apps.badges.issuers import CredlyBadgeTemplateIssuer, AccredibleBadgeTemplateIssuer
from credentials.apps.badges.models import (
CredlyBadge,
CredlyBadgeTemplate,
CredlyOrganization,
AccredibleAPIConfig,
AccredibleBadge,
AccredibleGroup,
)
from credentials.apps.credentials.constants import UserCredentialStatus


Expand Down Expand Up @@ -126,10 +134,10 @@ def test_issue_credly_badge_with_error(self):
# Mock the CredlyAPIClient and its issue_badge method to raise CredlyAPIError
with mock.patch("credentials.apps.badges.credly.api_client.CredlyAPIClient") as mock_credly_api_client:
mock_issue_badge = mock_credly_api_client.return_value.issue_badge
mock_issue_badge.side_effect = CredlyAPIError
mock_issue_badge.side_effect = BadgeProviderError

# Call the issue_credly_badge method and expect CredlyAPIError to be raised
with self.assertRaises(CredlyAPIError):
with self.assertRaises(BadgeProviderError):
self.issuer().issue_credly_badge(user_credential=user_credential)

# Check if the user credential state is updated to "error"
Expand All @@ -154,7 +162,7 @@ def test_revoke_credly_badge_success(self, mock_revoke_badge):
user_credential.refresh_from_db()
self.assertEqual(user_credential.state, "revoked")

@patch.object(CredlyAPIClient, "revoke_badge", side_effect=CredlyAPIError("Revocation failed"))
@patch.object(CredlyAPIClient, "revoke_badge", side_effect=BadgeProviderError("Revocation failed"))
def test_revoke_credly_badge_failure(self, mock_revoke_badge): # pylint: disable=unused-argument
user_credential = self.issued_user_credential_type.objects.create(
username="test_user",
Expand All @@ -165,8 +173,149 @@ def test_revoke_credly_badge_failure(self, mock_revoke_badge): # pylint: disabl
external_uuid=self.fake.uuid4(),
)

with self.assertRaises(CredlyAPIError):
with self.assertRaises(BadgeProviderError):
self.issuer().revoke_credly_badge(self.badge_template.id, user_credential)

user_credential.refresh_from_db()
self.assertEqual(user_credential.state, "error")


class AccredibleBadgeTemplateIssuerTestCase(TestCase):
issued_credential_type = AccredibleGroup
issued_user_credential_type = AccredibleBadge
issuer = AccredibleBadgeTemplateIssuer

def setUp(self):
self.fake = faker.Faker()
self.accredible_api_config = AccredibleAPIConfig.objects.create(
api_key=self.fake.uuid4(), name=self.fake.word()
)
self.group = self.issued_credential_type.objects.create(
origin=self.issued_credential_type.ORIGIN,
site_id=1,
uuid=self.fake.uuid4(),
name=self.fake.word(),
state="active",
api_config=self.accredible_api_config,
)
User.objects.create_user(username="test_user", email="test_email@example.com", password="test_password")

def _perform_request(self, method, endpoint, data=None): # pylint: disable=unused-argument
return {"credential": {"id": 123}}

def test_create_user_credential_awarded(self):
with mock.patch("credentials.apps.badges.issuers.notify_badge_awarded") as mock_notify_badge_awarded:
with mock.patch.object(self.issuer, "issue_accredible_badge") as mock_issue_accredible_badge:
self.issuer().award(credential_id=self.group.id, username="test_user")

mock_notify_badge_awarded.assert_called_once()
mock_issue_accredible_badge.assert_called_once()

self.assertTrue(
self.issued_user_credential_type.objects.filter(
username="test_user",
credential_content_type=ContentType.objects.get_for_model(self.group),
credential_id=self.group.id,
).exists()
)

def test_create_user_credential_revoked(self):
self.issued_user_credential_type.objects.create(
username="test_user",
credential_content_type=ContentType.objects.get_for_model(self.group),
credential_id=self.group.id,
state=AccredibleBadge.STATES.accepted,
uuid=self.fake.uuid4(),
external_id=123,
)

with mock.patch("credentials.apps.badges.issuers.notify_badge_revoked") as mock_notify_badge_revoked:
with mock.patch.object(self.issuer, "revoke_accredible_badge") as mock_revoke_accredible_badge:
self.issuer().revoke(self.group.id, "test_user")

mock_revoke_accredible_badge.assert_called_once()
mock_notify_badge_revoked.assert_called_once()

self.assertTrue(
self.issued_user_credential_type.objects.filter(
username="test_user",
credential_content_type=ContentType.objects.get_for_model(self.group),
credential_id=self.group.id,
status=UserCredentialStatus.REVOKED,
).exists()
)

@patch.object(AccredibleAPIClient, "perform_request", _perform_request)
def test_issue_accredible_badge(self):
user_credential = self.issued_user_credential_type.objects.create(
username="test_user",
credential_content_type=ContentType.objects.get_for_model(self.group),
credential_id=self.group.id,
state=AccredibleBadge.STATES.accepted,
uuid=self.fake.uuid4(),
external_id=123,
)

self.issuer().issue_accredible_badge(user_credential=user_credential)

self.assertIsNotNone(user_credential.external_id)
self.assertEqual(user_credential.state, AccredibleBadge.STATES.accepted)

user_credential.refresh_from_db()
self.assertIsNotNone(user_credential.external_id)
self.assertEqual(user_credential.state, AccredibleBadge.STATES.accepted)

def test_issue_accredible_badge_with_error(self):
user_credential = self.issued_user_credential_type.objects.create(
username="test_user",
credential_content_type=ContentType.objects.get_for_model(self.group),
credential_id=self.group.id,
state=AccredibleBadge.STATES.accepted,
uuid=self.fake.uuid4(),
external_id=123,
)

with mock.patch("credentials.apps.badges.accredible.api_client.AccredibleAPIClient") as mock_accredible_api_client:
mock_issue_badge = mock_accredible_api_client.return_value.issue_badge
mock_issue_badge.side_effect = BadgeProviderError

with self.assertRaises(BadgeProviderError):
self.issuer().issue_accredible_badge(user_credential=user_credential)

user_credential.refresh_from_db()
self.assertEqual(user_credential.state, "error")

@patch.object(AccredibleAPIClient, "revoke_badge")
def test_revoke_accredible_badge_success(self, mock_revoke_badge):
user_credential = self.issued_user_credential_type.objects.create(
username="test_user",
credential_content_type=ContentType.objects.get_for_model(self.group),
credential_id=self.group.id,
state=AccredibleBadge.STATES.accepted,
uuid=self.fake.uuid4(),
external_id=123,
)

mock_revoke_badge.return_value = {"credential": {"id": 123}}

self.issuer().revoke_accredible_badge(self.group.id, user_credential)

user_credential.refresh_from_db()
self.assertEqual(user_credential.state, "expired")

@patch.object(AccredibleAPIClient, "revoke_badge", side_effect=BadgeProviderError("Revocation failed"))
def test_revoke_accredible_badge_failure(self, mock_revoke_badge): # pylint: disable=unused-argument
user_credential = self.issued_user_credential_type.objects.create(
username="test_user",
credential_content_type=ContentType.objects.get_for_model(self.group),
credential_id=self.group.id,
state=AccredibleBadge.STATES.accepted,
uuid=self.fake.uuid4(),
external_id=123,
)

with self.assertRaises(BadgeProviderError):
self.issuer().revoke_accredible_badge(self.group.id, user_credential)

user_credential.refresh_from_db()
self.assertEqual(user_credential.state, "error")
50 changes: 50 additions & 0 deletions credentials/apps/badges/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
PenaltyDataRule,
AccredibleGroup,
AccredibleAPIConfig,
AccredibleBadge,
)
from credentials.apps.core.models import User

Expand Down Expand Up @@ -772,3 +773,52 @@ def setUp(self):
def test_get_all_api_config_ids(self):
organization_ids = [id for id in AccredibleAPIConfig.get_all_api_config_ids()]
self.assertEqual(organization_ids, [self.api_config.id])


class AccredibleBadgeAsBadgeDataTestCase(TestCase):
def setUp(self):
self.user = User.objects.create_user(
username="test_user",
email="test@example.com",
full_name="Test User",
lms_user_id=1,
)
self.site = Site.objects.create(domain="test_domain", name="test_name")
self.credential = BadgeTemplate.objects.create(
uuid=uuid.uuid4(),
origin="test_origin",
name="test_template",
description="test_description",
icon="test_icon",
site=self.site,
)
self.badge = AccredibleBadge.objects.create(
username="test_user",
credential_content_type=ContentType.objects.get_for_model(self.credential),
credential_id=self.credential.id,
state=AccredibleBadge.STATES.created,
uuid=uuid.uuid4(),
)

def test_as_badge_data(self):
expected_badge_data = BadgeData(
uuid=str(self.badge.uuid),
user=UserData(
pii=UserPersonalData(
username=self.user.username,
email=self.user.email,
name=self.user.get_full_name(),
),
id=self.user.lms_user_id,
is_active=self.user.is_active,
),
template=BadgeTemplateData(
uuid=str(self.credential.uuid),
origin=self.credential.origin,
name=self.credential.name,
description=self.credential.description,
image_url=str(self.credential.icon),
),
)
actual_badge_data = self.badge.as_badge_data()
self.assertEqual(actual_badge_data, expected_badge_data)
2 changes: 2 additions & 0 deletions credentials/apps/badges/tests/test_signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ def test_progression_signal_emission_and_receiver_execution(self):
sender=self,
username="test_user",
badge_template_id=self.badge_template.id,
origin=self.badge_template.origin,
)

# UserCredential object
Expand All @@ -51,6 +52,7 @@ def test_regression_signal_emission_and_receiver_execution(self):
sender=self,
username="test_user",
badge_template_id=self.badge_template.id,
origin=self.badge_template.origin,
)

# UserCredential object
Expand Down

0 comments on commit 5c1c6fe

Please sign in to comment.