Skip to content

Commit 8a80f28

Browse files
authored
Send notification to admins when new Savio project request is ready for processing (#738)
* Send admins email when a new project request has been approved and is ready for processing * Add unit, component Pytest tests for email to admins re: project ready for processing
1 parent 8745133 commit 8a80f28

9 files changed

Lines changed: 815 additions & 0 deletions

File tree

bootstrap/ansible/main.copyme

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@ email_admin_notification_recipients:
284284
created: []
285285
new_project_requests:
286286
agreement_uploaded: []
287+
approved: []
287288
created: []
288289
project_user_removal_requests:
289290
completed: []

coldfront/core/project/tests/pytest/__init__.py

Whitespace-only changes.

coldfront/core/project/tests/pytest/test_views/__init__.py

Whitespace-only changes.

coldfront/core/project/tests/pytest/test_views/test_new_project_views/__init__.py

Whitespace-only changes.
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
"""Unit tests for SavioProjectRequestMixin.conditionally_send_project_ready_for_processing_email()"""
2+
3+
import pytest
4+
from unittest.mock import Mock, patch
5+
from coldfront.core.project.views_.new_project_views.approval_views import (
6+
SavioProjectRequestMixin,
7+
)
8+
9+
10+
@pytest.mark.unit
11+
class TestConditionallySendProjectReadyForProcessingEmail:
12+
"""Unit tests for conditionally sending ready-for-processing
13+
email."""
14+
15+
SEND_EMAIL_PATH = (
16+
'coldfront.core.project.views_.new_project_views.approval_views.'
17+
'send_project_request_ready_for_processing_email'
18+
)
19+
20+
@pytest.fixture(autouse=True)
21+
def mock_computing_allowance(self):
22+
"""Patch ComputingAllowanceInterface to avoid DB access during
23+
mixin init."""
24+
with patch(
25+
'coldfront.core.project.views_.new_project_views.'
26+
'approval_views.ComputingAllowanceInterface'):
27+
yield
28+
29+
def _create_mixin(self):
30+
"""Create a mixin instance (relies on mock_computing_allowance
31+
fixture)."""
32+
mixin = SavioProjectRequestMixin()
33+
mixin.logger = Mock()
34+
return mixin
35+
36+
def test_sends_email_if_status_is_approved_processing(self):
37+
"""Test email is sent when status is 'Approved - Processing'."""
38+
# Setup
39+
mixin = self._create_mixin()
40+
mock_request_obj = Mock()
41+
mock_request_obj.status.name = 'Approved - Processing'
42+
mixin.request_obj = mock_request_obj
43+
44+
# Execute
45+
with patch(self.SEND_EMAIL_PATH) as mock_send:
46+
mixin.conditionally_send_project_ready_for_processing_email()
47+
48+
# Assert
49+
mock_send.assert_called_once_with(mock_request_obj)
50+
51+
def test_handles_email_send_exception_gracefully(self):
52+
"""Test that exceptions during email send are logged but not
53+
raised."""
54+
# Setup
55+
mixin = self._create_mixin()
56+
mock_request_obj = Mock()
57+
mock_request_obj.status.name = 'Approved - Processing'
58+
mixin.request_obj = mock_request_obj
59+
60+
# Execute
61+
with patch(self.SEND_EMAIL_PATH) as mock_send:
62+
mock_send.side_effect = Exception('Email service error')
63+
# Should not raise
64+
mixin.conditionally_send_project_ready_for_processing_email()
65+
66+
# Assert - exception was logged
67+
mixin.logger.error.assert_called_once()
68+
mixin.logger.exception.assert_called_once()
69+
70+
@pytest.mark.parametrize('status_name', [
71+
'Under Review',
72+
'Approved - Complete',
73+
'Approved - Scheduled',
74+
'Denied',
75+
])
76+
def test_does_not_send_email_for_non_processing_statuses(self, status_name):
77+
"""Test email is not sent for any status other than 'Approved -
78+
Processing'."""
79+
# Setup
80+
mixin = self._create_mixin()
81+
mock_request_obj = Mock()
82+
mock_request_obj.status.name = status_name
83+
mixin.request_obj = mock_request_obj
84+
85+
# Execute
86+
with patch(self.SEND_EMAIL_PATH) as mock_send:
87+
mixin.conditionally_send_project_ready_for_processing_email()
88+
89+
# Assert
90+
mock_send.assert_not_called()

0 commit comments

Comments
 (0)