From 8638ee7dc9446e557b724d353519f136b64a69ee Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Thu, 14 Dec 2023 14:02:46 -0700 Subject: [PATCH] Better test cases, align with AC --- .../templates/emails/domain_invitation.txt | 2 +- src/registrar/tests/test_views.py | 149 +++++++++++++++--- src/registrar/views/domain.py | 25 +-- 3 files changed, 131 insertions(+), 45 deletions(-) diff --git a/src/registrar/templates/emails/domain_invitation.txt b/src/registrar/templates/emails/domain_invitation.txt index ed9c297f4..f0612a67f 100644 --- a/src/registrar/templates/emails/domain_invitation.txt +++ b/src/registrar/templates/emails/domain_invitation.txt @@ -1,7 +1,7 @@ {% autoescape off %}{# In a text file, we don't want to have HTML entities escaped #} Hi. -{{ full_name }} has added you as a manager on {{ domain.name }}. +{{ requester_email }} has added you as a manager on {{ domain.name }}. YOU NEED A LOGIN.GOV ACCOUNT You’ll need a Login.gov account to manage your .gov domain. Login.gov provides diff --git a/src/registrar/tests/test_views.py b/src/registrar/tests/test_views.py index d34f1e2a5..2e1d29296 100644 --- a/src/registrar/tests/test_views.py +++ b/src/registrar/tests/test_views.py @@ -1,5 +1,5 @@ from unittest import skip -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock, ANY, call, patch from django.conf import settings from django.test import Client, TestCase @@ -1416,35 +1416,136 @@ class TestDomainManagers(TestDomainOverview): self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id) add_page.form.submit() - expected_email_content = { - "Simple": { - "Subject": {"Data": "You’ve been added to a .gov domain"}, - "Body": { - "Text": { - "Data": "\nHi.\n\nFirst Last has added you as a manager on igorville.gov.\n\n" - "YOU NEED A LOGIN.GOV ACCOUNT\nYou’ll need a Login.gov account to manage your .gov domain. " - "Login.gov provides\na simple and secure process for signing into many government services with" - " one\naccount. If you don’t already have one, follow these steps to create your\nLogin.gov " - "account .\n\nDOMAIN MANAGEMENT\nAs a " - ".gov domain manager you can add or update information about your domain.\nYou’ll also serve as" - " a contact for your .gov domain. Please keep your contact\ninformation updated. " - "Learn more about domain management .\n\nSOMETHING WRONG?\nIf you’re" - "not affiliated with igorville.gov or think you received this\nmessage in error, contact the " - ".gov team .\n\n\nTHANK YOU\n\n.Gov helps the public identify" - " official, trusted information. " - "Thank you for\nusing a .gov domain.\n\n-------------------------------------------------------" - "---------\n\nThe .gov team\nContact us: \nVisit \n" - } - }, - } - } # check the mock instance to see if `send_email` was called right mock_client_instance.send_email.assert_called_once_with( FromEmailAddress=settings.DEFAULT_FROM_EMAIL, Destination={"ToAddresses": [email_address]}, - Content=expected_email_content, + Content=ANY, ) + @boto3_mocking.patching + def test_domain_invitation_email_has_email_as_requester_non_existent(self): + """Inviting a non existent user sends them an email, with email as the name.""" + # make sure there is no user with this email + email_address = "mayor@igorville.gov" + User.objects.filter(email=email_address).delete() + + self.domain_information, _ = DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain) + + mock_client = MagicMock() + mock_client_instance = mock_client.return_value + + with boto3_mocking.clients.handler_for("sesv2", mock_client): + add_page = self.app.get(reverse("domain-users-add", kwargs={"pk": self.domain.id})) + session_id = self.app.cookies[settings.SESSION_COOKIE_NAME] + add_page.form["email"] = email_address + self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id) + add_page.form.submit() + + # check the mock instance to see if `send_email` was called right + mock_client_instance.send_email.assert_called_once_with( + FromEmailAddress=settings.DEFAULT_FROM_EMAIL, + Destination={"ToAddresses": [email_address]}, + Content=ANY, + ) + + # Check the arguments passed to send_email method + _, kwargs = mock_client_instance.send_email.call_args + + # Extract the email content, and check that the message is as we expect + email_content = kwargs["Content"]["Simple"]["Body"]["Text"]["Data"] + self.assertIn("info@example.com", email_content) + + # Check that the requesters first/last name do not exist + self.assertNotIn("First", email_content) + self.assertNotIn("Last", email_content) + + @boto3_mocking.patching + def test_domain_invitation_email_has_email_as_requester(self): + """Inviting a user sends them an email, with email as the name.""" + # Create a fake user object + email_address = "mayor@igorville.gov" + User.objects.get_or_create(email=email_address, username="fakeuser@fakeymail.com") + + self.domain_information, _ = DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain) + + mock_client = MagicMock() + mock_client_instance = mock_client.return_value + + with boto3_mocking.clients.handler_for("sesv2", mock_client): + add_page = self.app.get(reverse("domain-users-add", kwargs={"pk": self.domain.id})) + session_id = self.app.cookies[settings.SESSION_COOKIE_NAME] + add_page.form["email"] = email_address + self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id) + add_page.form.submit() + + # check the mock instance to see if `send_email` was called right + mock_client_instance.send_email.assert_called_once_with( + FromEmailAddress=settings.DEFAULT_FROM_EMAIL, + Destination={"ToAddresses": [email_address]}, + Content=ANY, + ) + + # Check the arguments passed to send_email method + _, kwargs = mock_client_instance.send_email.call_args + + # Extract the email content, and check that the message is as we expect + email_content = kwargs["Content"]["Simple"]["Body"]["Text"]["Data"] + self.assertIn("info@example.com", email_content) + + # Check that the requesters first/last name do not exist + self.assertNotIn("First", email_content) + self.assertNotIn("Last", email_content) + + @boto3_mocking.patching + def test_domain_invitation_email_throws_exception_non_existent(self): + """Inviting a non existent user sends them an email, with email as the name.""" + # make sure there is no user with this email + email_address = "mayor@igorville.gov" + User.objects.filter(email=email_address).delete() + + # Give the user who is sending the email an invalid email address + requester = User.objects.filter(email="info@example.com").get() + requester.email = "" + requester.save() + + self.domain_information, _ = DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain) + + mock_client = MagicMock() + + with boto3_mocking.clients.handler_for("sesv2", mock_client): + with self.assertRaisesMessage(ValueError, "Can't send email. No email exists for the requester"): + add_page = self.app.get(reverse("domain-users-add", kwargs={"pk": self.domain.id})) + session_id = self.app.cookies[settings.SESSION_COOKIE_NAME] + add_page.form["email"] = email_address + self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id) + add_page.form.submit() + + @boto3_mocking.patching + def test_domain_invitation_email_throws_exception(self): + """Inviting a user sends them an email, with email as the name.""" + # make sure there is no user with this email + # Create a fake user object + email_address = "mayor@igorville.gov" + User.objects.get_or_create(email=email_address, username="fakeuser@fakeymail.com") + + # Give the user who is sending the email an invalid email address + requester = User.objects.filter(email="info@example.com").get() + requester.email = "" + requester.save() + + self.domain_information, _ = DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain) + + mock_client = MagicMock() + + with boto3_mocking.clients.handler_for("sesv2", mock_client): + with self.assertRaisesMessage(ValueError, "Can't send email. No email exists for the requester"): + add_page = self.app.get(reverse("domain-users-add", kwargs={"pk": self.domain.id})) + session_id = self.app.cookies[settings.SESSION_COOKIE_NAME] + add_page.form["email"] = email_address + self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id) + add_page.form.submit() + def test_domain_invitation_cancel(self): """Posting to the delete view deletes an invitation.""" email_address = "mayor@igorville.gov" diff --git a/src/registrar/views/domain.py b/src/registrar/views/domain.py index 632530e71..7c3f175d3 100644 --- a/src/registrar/views/domain.py +++ b/src/registrar/views/domain.py @@ -651,32 +651,17 @@ class DomainAddUserView(DomainFormBaseView): add_success: bool- default True indicates: adding a success message to the view if the email sending succeeds""" # created a new invitation in the database, so send an email - domainInfoResults = DomainInformation.objects.filter(domain=self.object) - domainInfo = domainInfoResults.first() - first: str = "" - last: str = "" - if requester is not None: - first = requester.first_name - last = requester.last_name - elif domainInfo is not None: - first = domainInfo.creator.first_name - last = domainInfo.creator.last_name - else: + if requester is None: # This edgecase would be unusual if encountered. We don't want to handle this here. Rather, we would # want to fix this upstream where it is happening. raise ValueError("Can't send email. The given DomainInformation object has no requestor or creator.") - # Attempt to grab the first and last names. As a last resort, just use the email. - if first and last: - full_name = f"{first} {last}" - elif requester.email is not None and requester.email.strip() != "": - full_name = requester.email - elif domainInfo.creator.email is not None and domainInfo.creator.email.strip() != "": - full_name = domainInfo.creator.email + if requester.email is not None and requester.email.strip() != "": + requester_email = requester.email else: # This edgecase would be unusual if encountered. We don't want to handle this here. Rather, we would # want to fix this upstream where it is happening. - raise ValueError("Can't send email. First and last names, as well as the email, are none.") + raise ValueError("Can't send email. No email exists for the requester.") try: send_templated_email( @@ -686,7 +671,7 @@ class DomainAddUserView(DomainFormBaseView): context={ "domain_url": self._domain_abs_url(), "domain": self.object, - "full_name": full_name, + "requester_email": requester_email, }, ) except EmailSendingError: