-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: failed notifications for assignments leave state as allocated
When the assignment email notification task fails, the corresponding assignment is now NOT moved to an errored state, but instead left in an allocated state. Furthermore, the admin-serializer for the assignment now indicates a "failed" _learner_ state, and an error reason related to the failed notification attempt. ENT-9037
- Loading branch information
1 parent
5a4bb19
commit d4b359b
Showing
5 changed files
with
158 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -39,6 +39,8 @@ | |
from enterprise_access.utils import get_automatic_expiration_date_and_reason | ||
from test_utils import APITestWithMocks | ||
|
||
TEST_CONTENT_KEY = 'course:test_content' | ||
TEST_ENTERPRISE_CUSTOMER_NAME = 'test-customer-name' | ||
TEST_ENTERPRISE_UUID = uuid4() | ||
TEST_EMAIL = '[email protected]' | ||
TEST_LMS_USER_ID = 2 | ||
|
@@ -215,13 +217,37 @@ def setUpTestData(cls): | |
assignment_configuration=cls.assignment_configuration, | ||
spend_limit=10000000, | ||
) | ||
cls.mock_enterprise_customer_data = { | ||
'uuid': TEST_ENTERPRISE_UUID, | ||
'slug': 'test-slug', | ||
'admin_users': [{ | ||
'email': '[email protected]', | ||
'lms_user_id': 1 | ||
}], | ||
'name': TEST_ENTERPRISE_CUSTOMER_NAME, | ||
} | ||
cls.mock_content_metadata = { | ||
'key': TEST_CONTENT_KEY, | ||
'normalized_metadata': { | ||
'start_date': '2020-01-01T12:00:00Z', | ||
'end_date': '2022-01-01 12:00:00Z', | ||
'enroll_by_date': '2021-01-01T12:00:00Z', | ||
'content_price': 123, | ||
}, | ||
'owners': [ | ||
{'name': 'Smart Folks', 'logo_image_url': 'http://pictures.yes'}, | ||
{'name': 'Good People', 'logo_image_url': 'http://pictures.nice'}, | ||
], | ||
'card_image_url': 'https://itsanimage.com', | ||
} | ||
|
||
def setUp(self): | ||
super().setUp() | ||
self.course_name = 'test-course-name' | ||
self.enterprise_customer_name = 'test-customer-name' | ||
self.enterprise_customer_name = TEST_ENTERPRISE_CUSTOMER_NAME | ||
self.assignment = LearnerContentAssignmentFactory( | ||
uuid=TEST_ASSIGNMENT_UUID, | ||
content_key=TEST_CONTENT_KEY, | ||
learner_email='TESTING THIS EMAIL', | ||
lms_user_id=TEST_LMS_USER_ID, | ||
assignment_configuration=self.assignment_configuration, | ||
|
@@ -386,36 +412,13 @@ def test_send_email_for_new_assignment( | |
""" | ||
Verify send_email_for_new_assignment hits braze client with expected args | ||
""" | ||
admin_email = '[email protected]' | ||
mock_lms_client.return_value.get_enterprise_customer_data.return_value = { | ||
'uuid': TEST_ENTERPRISE_UUID, | ||
'slug': 'test-slug', | ||
'admin_users': [{ | ||
'email': admin_email, | ||
'lms_user_id': 1 | ||
}], | ||
'name': self.enterprise_customer_name, | ||
} | ||
mock_lms_client.return_value.get_enterprise_customer_data.return_value = self.mock_enterprise_customer_data | ||
mock_recipient = { | ||
'external_user_id': 1 | ||
} | ||
mock_metadata = { | ||
'key': self.assignment.content_key, | ||
'normalized_metadata': { | ||
'start_date': '2020-01-01T12:00:00Z', | ||
'end_date': '2022-01-01 12:00:00Z', | ||
'enroll_by_date': '2021-01-01T12:00:00Z', | ||
'content_price': 123, | ||
}, | ||
'owners': [ | ||
{'name': 'Smart Folks', 'logo_image_url': 'http://pictures.yes'}, | ||
{'name': 'Good People', 'logo_image_url': 'http://pictures.nice'}, | ||
], | ||
'card_image_url': 'https://itsanimage.com', | ||
} | ||
mock_catalog_client.return_value.catalog_content_metadata.return_value = { | ||
'count': 1, | ||
'results': [mock_metadata] | ||
'results': [self.mock_content_metadata] | ||
} | ||
|
||
# Set the subsidy expiration time to tomorrow | ||
|
@@ -425,7 +428,8 @@ def test_send_email_for_new_assignment( | |
} | ||
mock_subsidy_client.retrieve_subsidy.return_value = mock_subsidy | ||
|
||
mock_admin_mailto = f'mailto:{admin_email}' | ||
admin_email = self.mock_enterprise_customer_data['admin_users'][0]['email'] | ||
mock_admin_mailto = f"mailto:{admin_email}" | ||
mock_braze_client.return_value.create_recipient.return_value = mock_recipient | ||
mock_braze_client.return_value.generate_mailto_link.return_value = mock_admin_mailto | ||
|
||
|
@@ -446,13 +450,62 @@ def test_send_email_for_new_assignment( | |
'enrollment_deadline': 'Jan 01, 2021', | ||
'start_date': 'Jan 01, 2020', | ||
'course_partner': 'Smart Folks and Good People', | ||
'course_card_image': 'https://itsanimage.com', | ||
'learner_portal_link': '{}/{}'.format(settings.ENTERPRISE_LEARNER_PORTAL_URL, 'test-slug'), | ||
'course_card_image': self.mock_content_metadata['card_image_url'], | ||
'learner_portal_link': '{}/{}'.format( | ||
settings.ENTERPRISE_LEARNER_PORTAL_URL, | ||
self.mock_enterprise_customer_data['slug'] | ||
), | ||
'action_required_by_timestamp': '2021-01-01T12:00:00Z' | ||
}, | ||
) | ||
assert mock_braze_client.return_value.send_campaign_message.call_count == 1 | ||
|
||
@mock.patch('enterprise_access.apps.subsidy_access_policy.models.SubsidyAccessPolicy.subsidy_client') | ||
@mock.patch('enterprise_access.apps.content_metadata.api.EnterpriseCatalogApiClient') | ||
@mock.patch('enterprise_access.apps.content_assignments.tasks.LmsApiClient') | ||
@mock.patch('enterprise_access.apps.content_assignments.tasks.BrazeApiClient') | ||
def test_send_email_for_new_assignment_failure( | ||
self, | ||
mock_braze_client, | ||
mock_lms_client, | ||
mock_catalog_client, | ||
mock_subsidy_client, | ||
): | ||
""" | ||
Verify send_email_for_new_assignment does not change the state of the | ||
assignment record on failure. | ||
""" | ||
mock_lms_client.return_value.get_enterprise_customer_data.return_value = self.mock_enterprise_customer_data | ||
mock_recipient = { | ||
'external_user_id': 1 | ||
} | ||
mock_catalog_client.return_value.catalog_content_metadata.return_value = { | ||
'count': 1, | ||
'results': [self.mock_content_metadata] | ||
} | ||
|
||
# Set the subsidy expiration time to tomorrow | ||
mock_subsidy = { | ||
'uuid': self.policy.subsidy_uuid, | ||
'expiration_datetime': (now() + timedelta(days=1)).strftime('%Y-%m-%d %H:%M:%SZ'), | ||
} | ||
mock_subsidy_client.retrieve_subsidy.return_value = mock_subsidy | ||
|
||
braze_client_instance = mock_braze_client.return_value | ||
braze_client_instance.send_campaign_message.side_effect = Exception('foo') | ||
|
||
admin_email = self.mock_enterprise_customer_data['admin_users'][0]['email'] | ||
mock_admin_mailto = f"mailto:{admin_email}" | ||
braze_client_instance.create_recipient.return_value = mock_recipient | ||
braze_client_instance.generate_mailto_link.return_value = mock_admin_mailto | ||
|
||
send_email_for_new_assignment.delay(self.assignment.uuid) | ||
self.assertEqual(self.assignment.state, LearnerContentAssignmentStateChoices.ALLOCATED) | ||
self.assertTrue(self.assignment.actions.filter( | ||
error_reason=AssignmentActionErrors.EMAIL_ERROR, | ||
action_type=AssignmentActions.NOTIFIED, | ||
).exists()) | ||
|
||
@mock.patch('enterprise_access.apps.subsidy_access_policy.models.SubsidyAccessPolicy.objects') | ||
@mock.patch('enterprise_access.apps.content_assignments.tasks.LmsApiClient') | ||
@mock.patch('enterprise_access.apps.content_assignments.tasks.BrazeApiClient') | ||
|