Skip to content

Commit

Permalink
merge
Browse files Browse the repository at this point in the history
  • Loading branch information
rachidatecs committed Dec 21, 2024
2 parents 8326bbb + 1b16d6d commit f2bd0ad
Show file tree
Hide file tree
Showing 2 changed files with 226 additions and 6 deletions.
230 changes: 225 additions & 5 deletions src/registrar/tests/test_views_portfolio.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
from registrar.models.user_portfolio_permission import UserPortfolioPermission
from registrar.models.utility.portfolio_helper import UserPortfolioPermissionChoices, UserPortfolioRoleChoices
from registrar.tests.test_views import TestWithUser
from registrar.utility.email import EmailSendingError
from registrar.utility.email_invitations import send_portfolio_invitation_email
from registrar.utility.errors import MissingEmailError
from .common import MockSESClient, completed_domain_request, create_test_user, create_user
from waffle.testutils import override_flag
from django.contrib.sessions.middleware import SessionMiddleware
Expand Down Expand Up @@ -2531,7 +2534,7 @@ def setUpClass(cls):
],
)

cls.new_member_email = "new_user@example.com"
cls.new_member_email = "davekenn4242@gmail.com"

AllowedEmail.objects.get_or_create(email=cls.new_member_email)

Expand Down Expand Up @@ -2567,9 +2570,10 @@ def test_member_invite_for_new_users(self):
session_id = self.client.session.session_key
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)

mock_client = MagicMock()
mock_client_class = MagicMock()
mock_client = mock_client_class.return_value

with boto3_mocking.clients.handler_for("sesv2", mock_client):
with boto3_mocking.clients.handler_for("sesv2", mock_client_class):
# Simulate submission of member invite for new user
final_response = self.client.post(
reverse("new-member"),
Expand All @@ -2590,10 +2594,219 @@ def test_member_invite_for_new_users(self):
self.assertIsNotNone(portfolio_invite)
self.assertEqual(portfolio_invite.email, self.new_member_email)

# Check that an email was sent
self.assertTrue(mock_client.send_email.called)

@boto3_mocking.patching
@less_console_noise_decorator
@override_flag("organization_feature", active=True)
@override_flag("organization_members", active=True)
def test_member_invite_for_new_users_initial_ajax_call_passes(self):
"""Tests the member invitation flow for new users."""
self.client.force_login(self.user)

# Simulate a session to ensure continuity
session_id = self.client.session.session_key
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)

mock_client_class = MagicMock()
mock_client = mock_client_class.return_value

with boto3_mocking.clients.handler_for("sesv2", mock_client_class):
# Simulate submission of member invite for new user
final_response = self.client.post(
reverse("new-member"),
{
"role": UserPortfolioRoleChoices.ORGANIZATION_MEMBER.value,
"domain_request_permission_member": UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS.value,
"email": self.new_member_email,
},
HTTP_X_REQUESTED_WITH="XMLHttpRequest",
)

# Ensure the prep ajax submission is successful
self.assertEqual(final_response.status_code, 200)

# Check that the response is a JSON response with is_valid
json_response = final_response.json()
self.assertIn("is_valid", json_response)
self.assertTrue(json_response["is_valid"])

# assert that portfolio invitation is not created
self.assertFalse(
PortfolioInvitation.objects.filter(email=self.new_member_email, portfolio=self.portfolio).exists(),
"Portfolio invitation should not be created when an Exception occurs."
)

# Check that an email was not sent
self.assertFalse(mock_client.send_email.called)

@less_console_noise_decorator
@override_flag("organization_feature", active=True)
@override_flag("organization_members", active=True)
def test_member_invite_for_previously_invited_member(self):
@patch("registrar.views.portfolios.send_portfolio_invitation_email")
def test_member_invite_for_previously_invited_member_initial_ajax_call_fails(self, mock_send_email):
"""Tests the initial ajax call in the member invitation flow for existing portfolio member."""
self.client.force_login(self.user)

# Simulate a session to ensure continuity
session_id = self.client.session.session_key
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)

invite_count_before = PortfolioInvitation.objects.count()

# Simulate submission of member invite for user who has already been invited
response = self.client.post(
reverse("new-member"),
{
"role": UserPortfolioRoleChoices.ORGANIZATION_MEMBER.value,
"domain_request_permission_member": UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS.value,
"email": self.invited_member_email,
},
HTTP_X_REQUESTED_WITH="XMLHttpRequest",
)
self.assertEqual(response.status_code, 200)

# Check that the response is a JSON response with is_valid == False
json_response = response.json()
self.assertIn("is_valid", json_response)
self.assertFalse(json_response["is_valid"])

# Validate Database has not changed
invite_count_after = PortfolioInvitation.objects.count()
self.assertEqual(invite_count_after, invite_count_before)

# assert that send_portfolio_invitation_email is not called
mock_send_email.assert_not_called()

@less_console_noise_decorator
@override_flag("organization_feature", active=True)
@override_flag("organization_members", active=True)
@patch("registrar.views.portfolios.send_portfolio_invitation_email")
def test_submit_new_member_raises_email_sending_error(self, mock_send_email):
"""Test when adding a new member and email_send method raises EmailSendingError."""
mock_send_email.side_effect = EmailSendingError("Failed to send email.")

self.client.force_login(self.user)

# Simulate a session to ensure continuity
session_id = self.client.session.session_key
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)

form_data = {
"role": UserPortfolioRoleChoices.ORGANIZATION_MEMBER.value,
"domain_request_permission_member": UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS.value,
"email": self.new_member_email,
}

# Act
with patch("django.contrib.messages.warning") as mock_warning:
response = self.client.post(reverse("new-member"), data=form_data)

# Assert
# assert that the send_portfolio_invitation_email called
mock_send_email.assert_called_once_with(
email=self.new_member_email, requestor=self.user, portfolio=self.portfolio
)
# assert that response is a redirect to reverse("members")
self.assertRedirects(response, reverse("members"))
# assert that messages contains message, "Could not send email invitation"
mock_warning.assert_called_once_with(
response.wsgi_request, "Could not send email invitation."
)
# assert that portfolio invitation is not created
self.assertFalse(
PortfolioInvitation.objects.filter(email=self.new_member_email, portfolio=self.portfolio).exists(),
"Portfolio invitation should not be created when an EmailSendingError occurs."
)

@less_console_noise_decorator
@override_flag("organization_feature", active=True)
@override_flag("organization_members", active=True)
@patch("registrar.views.portfolios.send_portfolio_invitation_email")
def test_submit_new_member_raises_missing_email_error(self, mock_send_email):
"""Test when adding a new member and email_send method raises MissingEmailError."""
mock_send_email.side_effect = MissingEmailError(self.user.username)

self.client.force_login(self.user)

# Simulate a session to ensure continuity
session_id = self.client.session.session_key
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)

form_data = {
"role": UserPortfolioRoleChoices.ORGANIZATION_MEMBER.value,
"domain_request_permission_member": UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS.value,
"email": self.new_member_email,
}

# Act
with patch("django.contrib.messages.error") as mock_error:
response = self.client.post(reverse("new-member"), data=form_data)

# Assert
# assert that the send_portfolio_invitation_email called
mock_send_email.assert_called_once_with(
email=self.new_member_email, requestor=self.user, portfolio=self.portfolio
)
# assert that response is a redirect to reverse("members")
self.assertRedirects(response, reverse("members"))
# assert that messages contains message, "Could not send email invitation"
mock_error.assert_called_once_with(
response.wsgi_request, "Can't send invitation email. No email is associated with the account for 'test_user'."
)
# assert that portfolio invitation is not created
self.assertFalse(
PortfolioInvitation.objects.filter(email=self.new_member_email, portfolio=self.portfolio).exists(),
"Portfolio invitation should not be created when a MissingEmailError occurs."
)

@less_console_noise_decorator
@override_flag("organization_feature", active=True)
@override_flag("organization_members", active=True)
@patch("registrar.views.portfolios.send_portfolio_invitation_email")
def test_submit_new_member_raises_exception(self, mock_send_email):
"""Test when adding a new member and email_send method raises Exception."""
mock_send_email.side_effect = Exception("Generic exception")

self.client.force_login(self.user)

# Simulate a session to ensure continuity
session_id = self.client.session.session_key
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)

form_data = {
"role": UserPortfolioRoleChoices.ORGANIZATION_MEMBER.value,
"domain_request_permission_member": UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS.value,
"email": self.new_member_email,
}

# Act
with patch("django.contrib.messages.warning") as mock_warning:
response = self.client.post(reverse("new-member"), data=form_data)

# Assert
# assert that the send_portfolio_invitation_email called
mock_send_email.assert_called_once_with(
email=self.new_member_email, requestor=self.user, portfolio=self.portfolio
)
# assert that response is a redirect to reverse("members")
self.assertRedirects(response, reverse("members"))
# assert that messages contains message, "Could not send email invitation"
mock_warning.assert_called_once_with(
response.wsgi_request, "Could not send email invitation."
)
# assert that portfolio invitation is not created
self.assertFalse(
PortfolioInvitation.objects.filter(email=self.new_member_email, portfolio=self.portfolio).exists(),
"Portfolio invitation should not be created when an Exception occurs."
)

@less_console_noise_decorator
@override_flag("organization_feature", active=True)
@override_flag("organization_members", active=True)
@patch("registrar.views.portfolios.send_portfolio_invitation_email")
def test_member_invite_for_previously_invited_member(self, mock_send_email):
"""Tests the member invitation flow for existing portfolio member."""
self.client.force_login(self.user)

Expand Down Expand Up @@ -2621,10 +2834,14 @@ def test_member_invite_for_previously_invited_member(self):
invite_count_after = PortfolioInvitation.objects.count()
self.assertEqual(invite_count_after, invite_count_before)

# assert that send_portfolio_invitation_email is not called
mock_send_email.assert_not_called()

@less_console_noise_decorator
@override_flag("organization_feature", active=True)
@override_flag("organization_members", active=True)
def test_member_invite_for_existing_member(self):
@patch("registrar.views.portfolios.send_portfolio_invitation_email")
def test_member_invite_for_existing_member(self, mock_send_email):
"""Tests the member invitation flow for existing portfolio member."""
self.client.force_login(self.user)

Expand Down Expand Up @@ -2652,6 +2869,9 @@ def test_member_invite_for_existing_member(self):
invite_count_after = PortfolioInvitation.objects.count()
self.assertEqual(invite_count_after, invite_count_before)

# assert that send_portfolio_invitation_email is not called
mock_send_email.assert_not_called()


class TestEditPortfolioMemberView(WebTest):
"""Tests for the edit member page on portfolios"""
Expand Down
2 changes: 1 addition & 1 deletion src/registrar/views/portfolios.py
Original file line number Diff line number Diff line change
Expand Up @@ -594,5 +594,5 @@ def _handle_exceptions(self, exception, portfolio, email):
exc_info=True,
)
else:
logger.warning("Could not send email invitation (Other Exception)", portfolio, exc_info=True)
logger.warning("Could not send email invitation (Other Exception)", exc_info=True)
messages.warning(self.request, "Could not send email invitation.")

0 comments on commit f2bd0ad

Please sign in to comment.