Admin unit tests

This commit is contained in:
Rachid Mrad 2024-02-16 17:14:44 -05:00
parent 856e25fcb9
commit a32b0c0373
No known key found for this signature in database
2 changed files with 144 additions and 20 deletions

View file

@ -19,7 +19,7 @@ Learn more about:
- What you can and cant do with .gov domains <https://get.gov/domains/requirements/> - What you can and cant do with .gov domains <https://get.gov/domains/requirements/>
If you have questions or comments, reply to this email. If you have questions or comments, reply to this email.
{% elif application.status == 'requestor' %} {% elif application.rejection_reason == 'requestor' %}
Your domain request was rejected because we dont believe youre eligible to request a Your domain request was rejected because we dont believe youre eligible to request a
.gov domain on behalf of {{ application.organization_name }}. You must be a government employee, or be .gov domain on behalf of {{ application.organization_name }}. You must be a government employee, or be
working on behalf of a government organization, to request a .gov domain. working on behalf of a government organization, to request a .gov domain.
@ -28,7 +28,7 @@ working on behalf of a government organization, to request a .gov domain.
DEMONSTRATE ELIGIBILITY DEMONSTRATE ELIGIBILITY
If you can provide more information that demonstrates your eligibility, or you want to If you can provide more information that demonstrates your eligibility, or you want to
discuss further, reply to this email. discuss further, reply to this email.
{% elif application.status == 'second_domain_reasoning' %} {% elif application.rejection_reason == 'second_domain_reasoning' %}
Your domain request was rejected because {{ application.organization_name }} has a .gov domain. Our Your domain request was rejected because {{ application.organization_name }} has a .gov domain. Our
practice is to approve one domain per online service per government organization. We practice is to approve one domain per online service per government organization. We
evaluate additional requests on a case-by-case basis. You did not provide sufficient evaluate additional requests on a case-by-case basis. You did not provide sufficient
@ -38,10 +38,10 @@ Read more about our practice of approving one domain per online service
<https://get.gov/domains/before/#one-domain-per-service>. <https://get.gov/domains/before/#one-domain-per-service>.
If you have questions or comments, reply to this email. If you have questions or comments, reply to this email.
{% elif application.status == 'contacts_or_organization_legitimacy' %} {% elif application.rejection_reason == 'contacts_or_organization_legitimacy' %}
Your domain request was rejected because we could not verify the organizational Your domain request was rejected because we could not verify the organizational
contacts you provided. If you have questions or comments, reply to this email. contacts you provided. If you have questions or comments, reply to this email.
{% elif application.status == 'organization_eligibility' %} {% elif application.rejection_reason == 'organization_eligibility' %}
Your domain request was rejected because we determined that {{ application.organization_name }} is not Your domain request was rejected because we determined that {{ application.organization_name }} is not
eligible for a .gov domain. .Gov domains are only available to official U.S.-based eligible for a .gov domain. .Gov domains are only available to official U.S.-based
government organizations. government organizations.
@ -53,7 +53,7 @@ This can include links to (or copies of) your authorizing legislation, your foun
charter or bylaws, or other similar documentation. Without this, we cant approve a charter or bylaws, or other similar documentation. Without this, we cant approve a
.gov domain for your organization. Learn more about eligibility for .gov domains .gov domain for your organization. Learn more about eligibility for .gov domains
<https://get.gov/domains/eligibility/>. <https://get.gov/domains/eligibility/>.
{% elif application.status == 'naming_requirements' %} {% elif application.rejection_reason == 'naming_requirements' %}
Your domain request was rejected because it does not meet our naming requirements. Your domain request was rejected because it does not meet our naming requirements.
Domains should uniquely identify a government organization and be clear to the Domains should uniquely identify a government organization and be clear to the
general public. Learn more about naming requirements for your type of organization general public. Learn more about naming requirements for your type of organization

View file

@ -412,7 +412,7 @@ class TestDomainApplicationAdmin(MockEppLib):
# Now let's make sure the long description does not exist # Now let's make sure the long description does not exist
self.assertNotContains(response, "Federal: an agency of the U.S. government") self.assertNotContains(response, "Federal: an agency of the U.S. government")
def transition_state_and_send_email(self, application, status): def transition_state_and_send_email(self, application, status, rejection_reason=None):
"""Helper method for the email test cases.""" """Helper method for the email test cases."""
with boto3_mocking.clients.handler_for("sesv2", self.mock_client): with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
@ -420,12 +420,15 @@ class TestDomainApplicationAdmin(MockEppLib):
# Create a mock request # Create a mock request
request = self.factory.post("/admin/registrar/domainapplication/{}/change/".format(application.pk)) request = self.factory.post("/admin/registrar/domainapplication/{}/change/".format(application.pk))
# Modify the application's property # Modify the application's properties
application.status = status application.status = status
application.rejection_reason = rejection_reason
# Use the model admin's save_model method # Use the model admin's save_model method
self.admin.save_model(request, application, form=None, change=True) self.admin.save_model(request, application, form=None, change=True)
logger.info(f'application.rejection_reason {application.rejection_reason}')
def assert_email_is_accurate(self, expected_string, email_index, email_address): def assert_email_is_accurate(self, expected_string, email_index, email_address):
"""Helper method for the email test cases. """Helper method for the email test cases.
email_index is the index of the email in mock_client.""" email_index is the index of the email in mock_client."""
@ -512,7 +515,7 @@ class TestDomainApplicationAdmin(MockEppLib):
self.assertEqual(len(self.mock_client.EMAILS_SENT), 1) self.assertEqual(len(self.mock_client.EMAILS_SENT), 1)
# Test Withdrawn Status # Test Withdrawn Status
self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.REJECTED) self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.REJECTED, DomainApplication.RejectionReasons.DOMAIN_PURPOSE)
self.assert_email_is_accurate("Your .gov domain request has been rejected.", 1, EMAIL) self.assert_email_is_accurate("Your .gov domain request has been rejected.", 1, EMAIL)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 2) self.assertEqual(len(self.mock_client.EMAILS_SENT), 2)
@ -520,9 +523,9 @@ class TestDomainApplicationAdmin(MockEppLib):
self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.APPROVED) self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.APPROVED)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 3) self.assertEqual(len(self.mock_client.EMAILS_SENT), 3)
def test_save_model_sends_rejected_email(self): def test_save_model_sends_rejected_email_domain_purpose(self):
"""When transitioning to rejected on a domain request, """When transitioning to rejected on a domain request, an email is sent
an email is sent out every time.""" explaining why when the reason is domain purpose."""
# Ensure there is no user with this email # Ensure there is no user with this email
EMAIL = "mayor@igorville.gov" EMAIL = "mayor@igorville.gov"
@ -531,19 +534,137 @@ class TestDomainApplicationAdmin(MockEppLib):
# Create a sample application # Create a sample application
application = completed_application(status=DomainApplication.ApplicationStatus.IN_REVIEW) application = completed_application(status=DomainApplication.ApplicationStatus.IN_REVIEW)
# Test Submitted Status # Reject for reason DOMAIN_PURPOSE and test email
self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.REJECTED) self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.REJECTED, DomainApplication.RejectionReasons.DOMAIN_PURPOSE)
self.assert_email_is_accurate("Your .gov domain request has been rejected.", 0, EMAIL) self.assert_email_is_accurate("Your domain request was rejected because the purpose you provided did not meet our \nrequirements.", 0, EMAIL)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 1) self.assertEqual(len(self.mock_client.EMAILS_SENT), 1)
# Test Withdrawn Status # Approve
self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.APPROVED) self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.APPROVED)
self.assert_email_is_accurate("Congratulations! Your .gov domain request has been approved.", 1, EMAIL) self.assert_email_is_accurate("Congratulations! Your .gov domain request has been approved.", 1, EMAIL)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 2) self.assertEqual(len(self.mock_client.EMAILS_SENT), 2)
# Test Submitted Status Again (No new email should be sent) def test_save_model_sends_rejected_email_requestor(self):
self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.REJECTED) """When transitioning to rejected on a domain request, an email is sent
self.assertEqual(len(self.mock_client.EMAILS_SENT), 3) explaining why when the reason is requestor."""
# Ensure there is no user with this email
EMAIL = "mayor@igorville.gov"
User.objects.filter(email=EMAIL).delete()
# Create a sample application
application = completed_application(status=DomainApplication.ApplicationStatus.IN_REVIEW)
# Reject for reason REQUESTOR and test email including dynamic organization name
self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.REJECTED, DomainApplication.RejectionReasons.REQUESTOR)
self.assert_email_is_accurate("Your domain request was rejected because we dont believe youre eligible to request a .gov domain on behalf of Testorg", 0, EMAIL)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 1)
# Approve
self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.APPROVED)
self.assert_email_is_accurate("Congratulations! Your .gov domain request has been approved.", 1, EMAIL)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 2)
def test_save_model_sends_rejected_email_requestor(self):
"""When transitioning to rejected on a domain request, an email is sent
explaining why when the reason is second domain."""
# Ensure there is no user with this email
EMAIL = "mayor@igorville.gov"
User.objects.filter(email=EMAIL).delete()
# Create a sample application
application = completed_application(status=DomainApplication.ApplicationStatus.IN_REVIEW)
# Reject for reason SECOND_DOMAIN_REASONING and test email including dynamic organization name
self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.REJECTED, DomainApplication.RejectionReasons.SECOND_DOMAIN_REASONING)
self.assert_email_is_accurate("Your domain request was rejected because Testorg has a .gov domain.", 0, EMAIL)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 1)
# Approve
self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.APPROVED)
self.assert_email_is_accurate("Congratulations! Your .gov domain request has been approved.", 1, EMAIL)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 2)
def test_save_model_sends_rejected_email_contacts_or_org_legitimacy(self):
"""When transitioning to rejected on a domain request, an email is sent
explaining why when the reason is contacts or org legitimacy."""
# Ensure there is no user with this email
EMAIL = "mayor@igorville.gov"
User.objects.filter(email=EMAIL).delete()
# Create a sample application
application = completed_application(status=DomainApplication.ApplicationStatus.IN_REVIEW)
# Reject for reason CONTACTS_OR_ORGANIZATION_LEGITIMACY and test email including dynamic organization name
self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.REJECTED, DomainApplication.RejectionReasons.CONTACTS_OR_ORGANIZATION_LEGITIMACY)
self.assert_email_is_accurate("Your domain request was rejected because we could not verify the organizational \ncontacts you provided. If you have questions or comments, reply to this email.", 0, EMAIL)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 1)
# Approve
self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.APPROVED)
self.assert_email_is_accurate("Congratulations! Your .gov domain request has been approved.", 1, EMAIL)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 2)
def test_save_model_sends_rejected_email_org_eligibility(self):
"""When transitioning to rejected on a domain request, an email is sent
explaining why when the reason is org eligibility."""
# Ensure there is no user with this email
EMAIL = "mayor@igorville.gov"
User.objects.filter(email=EMAIL).delete()
# Create a sample application
application = completed_application(status=DomainApplication.ApplicationStatus.IN_REVIEW)
# Reject for reason ORGANIZATION_ELIGIBILITY and test email including dynamic organization name
self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.REJECTED, DomainApplication.RejectionReasons.ORGANIZATION_ELIGIBILITY)
self.assert_email_is_accurate("Your domain request was rejected because we determined that Testorg is not \neligible for a .gov domain.", 0, EMAIL)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 1)
# Approve
self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.APPROVED)
self.assert_email_is_accurate("Congratulations! Your .gov domain request has been approved.", 1, EMAIL)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 2)
def test_save_model_sends_rejected_email_naming(self):
"""When transitioning to rejected on a domain request, an email is sent
explaining why when the reason is naming."""
# Ensure there is no user with this email
EMAIL = "mayor@igorville.gov"
User.objects.filter(email=EMAIL).delete()
# Create a sample application
application = completed_application(status=DomainApplication.ApplicationStatus.IN_REVIEW)
# Reject for reason NAMING_REQUIREMENTS and test email including dynamic organization name
self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.REJECTED, DomainApplication.RejectionReasons.NAMING_REQUIREMENTS)
self.assert_email_is_accurate("Your domain request was rejected because it does not meet our naming requirements.", 0, EMAIL)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 1)
# Approve
self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.APPROVED)
self.assert_email_is_accurate("Congratulations! Your .gov domain request has been approved.", 1, EMAIL)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 2)
def test_save_model_clear_rejected_reason(self):
"""When transitioning from rejected on a domain request,
the rejected_reason is cleared."""
# Create a sample application
application = completed_application(status=DomainApplication.ApplicationStatus.REJECTED)
application.rejected_reason = DomainApplication.RejectionReasons.DOMAIN_PURPOSE
application.save()
# Approve
with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
application.approve()
application.refresh_from_db()
self.assertEqual(application.rejected_reason, None)
def test_save_model_sends_withdrawn_email(self): def test_save_model_sends_withdrawn_email(self):
"""When transitioning to withdrawn on a domain request, """When transitioning to withdrawn on a domain request,
@ -633,6 +754,7 @@ class TestDomainApplicationAdmin(MockEppLib):
"created_at", "created_at",
"updated_at", "updated_at",
"status", "status",
"rejection_reason",
"creator", "creator",
"investigator", "investigator",
"organization_type", "organization_type",
@ -744,7 +866,7 @@ class TestDomainApplicationAdmin(MockEppLib):
"Cannot edit an application with a restricted creator.", "Cannot edit an application with a restricted creator.",
) )
def trigger_saving_approved_to_another_state(self, domain_is_active, another_state): def trigger_saving_approved_to_another_state(self, domain_is_active, another_state, rejection_reason=None):
"""Helper method that triggers domain request state changes from approved to another state, """Helper method that triggers domain request state changes from approved to another state,
with an associated domain that can be either active (READY) or not. with an associated domain that can be either active (READY) or not.
@ -773,6 +895,8 @@ class TestDomainApplicationAdmin(MockEppLib):
stack.enter_context(patch.object(messages, "error")) stack.enter_context(patch.object(messages, "error"))
application.status = another_state application.status = another_state
application.rejection_reason = rejection_reason
self.admin.save_model(request, application, None, True) self.admin.save_model(request, application, None, True)
# Assert that the error message was called with the correct argument # Assert that the error message was called with the correct argument
@ -814,7 +938,7 @@ class TestDomainApplicationAdmin(MockEppLib):
self.trigger_saving_approved_to_another_state(False, DomainApplication.ApplicationStatus.ACTION_NEEDED) self.trigger_saving_approved_to_another_state(False, DomainApplication.ApplicationStatus.ACTION_NEEDED)
def test_side_effects_when_saving_approved_to_rejected(self): def test_side_effects_when_saving_approved_to_rejected(self):
self.trigger_saving_approved_to_another_state(False, DomainApplication.ApplicationStatus.REJECTED) self.trigger_saving_approved_to_another_state(False, DomainApplication.ApplicationStatus.REJECTED, DomainApplication.RejectionReasons.CONTACTS_OR_ORGANIZATION_LEGITIMACY)
def test_side_effects_when_saving_approved_to_ineligible(self): def test_side_effects_when_saving_approved_to_ineligible(self):
self.trigger_saving_approved_to_another_state(False, DomainApplication.ApplicationStatus.INELIGIBLE) self.trigger_saving_approved_to_another_state(False, DomainApplication.ApplicationStatus.INELIGIBLE)