From 40cc30a98849863e5e981b86ec84facd996d121f Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Fri, 16 Feb 2024 11:17:51 -0500 Subject: [PATCH 01/13] django admin updates for domain and application lists --- src/registrar/admin.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/registrar/admin.py b/src/registrar/admin.py index c5f5be276..21f966da3 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -767,6 +767,12 @@ class DomainApplicationAdmin(ListHeaderAdmin): "requested_domain", "status", "organization_type", + "federal_agency", + "federal_type", + "organization_name", + "is_election_board", + "city", + "state_territory", "created_at", "submitter", "investigator", @@ -1038,6 +1044,12 @@ class DomainAdmin(ListHeaderAdmin): list_display = [ "name", "organization_type", + "federal_agency", + "federal_type", + "organization_name", + "is_election_board", + "city", + "state_territory", "state", "expiration_date", "created_at", @@ -1061,6 +1073,24 @@ class DomainAdmin(ListHeaderAdmin): organization_type.admin_order_field = "domain_info__organization_type" # type: ignore + def federal_agency(self, obj): + return obj.domain_info.federal_agency if obj.domain_info else None + + def federal_type(self, obj): + return obj.domain_info.federal_type if obj.domain_info else None + + def organization_name(self, obj): + return obj.domain_info.organization_name if obj.domain_info else None + + def is_election_board(self, obj): + return obj.domain_info.is_election_board if obj.domain_info else None + + def city(self, obj): + return obj.domain_info.city if obj.domain_info else None + + def state_territory(self, obj): + return obj.domain_info.state_territory if obj.domain_info else None + # Filters list_filter = ["domain_info__organization_type", "state"] From e138458105f5c2f20443c410d4951d88da65dd16 Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Fri, 16 Feb 2024 11:24:22 -0500 Subject: [PATCH 02/13] fixed sorting --- src/registrar/admin.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/registrar/admin.py b/src/registrar/admin.py index 21f966da3..2f1a63966 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -1075,21 +1075,27 @@ class DomainAdmin(ListHeaderAdmin): def federal_agency(self, obj): return obj.domain_info.federal_agency if obj.domain_info else None + federal_agency.admin_order_field = "domain_info__federal_agency" def federal_type(self, obj): return obj.domain_info.federal_type if obj.domain_info else None + federal_type.admin_order_field = "domain_info__federal_type" def organization_name(self, obj): return obj.domain_info.organization_name if obj.domain_info else None + organization_name.admin_order_field = "domain_info__organization_name" def is_election_board(self, obj): return obj.domain_info.is_election_board if obj.domain_info else None + is_election_board.admin_order_field = "domain_info__is_election_board" def city(self, obj): return obj.domain_info.city if obj.domain_info else None + city.admin_order_field = "domain_info__city" def state_territory(self, obj): return obj.domain_info.state_territory if obj.domain_info else None + state_territory.admin_order_field = "domain_info__state_territory" # Filters list_filter = ["domain_info__organization_type", "state"] From bd418c3dca32d26aa602a97539ec62b92a662da7 Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Fri, 16 Feb 2024 11:32:09 -0500 Subject: [PATCH 03/13] formatted for linting --- src/registrar/admin.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/registrar/admin.py b/src/registrar/admin.py index 2f1a63966..bac361c6a 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -1075,28 +1075,34 @@ class DomainAdmin(ListHeaderAdmin): def federal_agency(self, obj): return obj.domain_info.federal_agency if obj.domain_info else None - federal_agency.admin_order_field = "domain_info__federal_agency" + + federal_agency.admin_order_field = "domain_info__federal_agency" # type: ignore def federal_type(self, obj): return obj.domain_info.federal_type if obj.domain_info else None - federal_type.admin_order_field = "domain_info__federal_type" - + + federal_type.admin_order_field = "domain_info__federal_type" # type: ignore + def organization_name(self, obj): return obj.domain_info.organization_name if obj.domain_info else None - organization_name.admin_order_field = "domain_info__organization_name" + + organization_name.admin_order_field = "domain_info__organization_name" # type: ignore def is_election_board(self, obj): return obj.domain_info.is_election_board if obj.domain_info else None - is_election_board.admin_order_field = "domain_info__is_election_board" + + is_election_board.admin_order_field = "domain_info__is_election_board" # type: ignore def city(self, obj): return obj.domain_info.city if obj.domain_info else None - city.admin_order_field = "domain_info__city" - + + city.admin_order_field = "domain_info__city" # type: ignore + def state_territory(self, obj): return obj.domain_info.state_territory if obj.domain_info else None - state_territory.admin_order_field = "domain_info__state_territory" - + + state_territory.admin_order_field = "domain_info__state_territory" # type: ignore + # Filters list_filter = ["domain_info__organization_type", "state"] From 4a3a72cfdd38945acf5c899be6384fff2240c40c Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Fri, 16 Feb 2024 12:41:15 -0500 Subject: [PATCH 04/13] fixed tests and cleaned up noise in existing tests --- src/registrar/tests/test_admin.py | 1779 +++++++++++++++-------------- 1 file changed, 911 insertions(+), 868 deletions(-) diff --git a/src/registrar/tests/test_admin.py b/src/registrar/tests/test_admin.py index f90b18584..1b133a052 100644 --- a/src/registrar/tests/test_admin.py +++ b/src/registrar/tests/test_admin.py @@ -68,9 +68,9 @@ class TestDomainAdmin(MockEppLib): response = self.client.get("/admin/registrar/domain/") - # There are 3 template references to Federal (3) plus one reference in the table + # There are 4 template references to Federal (4) plus four references in the table # for our actual application - self.assertContains(response, "Federal", count=4) + self.assertContains(response, "Federal", count=8) # This may be a bit more robust self.assertContains(response, 'Federal', count=1) # Now let's make sure the long description does not exist @@ -270,40 +270,43 @@ class TestDomainApplicationAdminForm(TestCase): self.application = completed_application() def test_form_choices(self): - # Create a form instance with the test application - form = DomainApplicationAdminForm(instance=self.application) + with less_console_noise(): + # Create a form instance with the test application + form = DomainApplicationAdminForm(instance=self.application) - # Verify that the form choices match the available transitions for started - expected_choices = [("started", "Started"), ("submitted", "Submitted")] - self.assertEqual(form.fields["status"].widget.choices, expected_choices) + # Verify that the form choices match the available transitions for started + expected_choices = [("started", "Started"), ("submitted", "Submitted")] + self.assertEqual(form.fields["status"].widget.choices, expected_choices) def test_form_choices_when_no_instance(self): - # Create a form instance without an instance - form = DomainApplicationAdminForm() + with less_console_noise(): + # Create a form instance without an instance + form = DomainApplicationAdminForm() - # Verify that the form choices show all choices when no instance is provided; - # this is necessary to show all choices when creating a new domain - # application in django admin; - # note that FSM ensures that no domain application exists with invalid status, - # so don't need to test for invalid status - self.assertEqual( - form.fields["status"].widget.choices, - DomainApplication._meta.get_field("status").choices, - ) + # Verify that the form choices show all choices when no instance is provided; + # this is necessary to show all choices when creating a new domain + # application in django admin; + # note that FSM ensures that no domain application exists with invalid status, + # so don't need to test for invalid status + self.assertEqual( + form.fields["status"].widget.choices, + DomainApplication._meta.get_field("status").choices, + ) def test_form_choices_when_ineligible(self): - # Create a form instance with a domain application with ineligible status - ineligible_application = DomainApplication(status="ineligible") + with less_console_noise(): + # Create a form instance with a domain application with ineligible status + ineligible_application = DomainApplication(status="ineligible") - # Attempt to create a form with the ineligible application - # The form should not raise an error, but choices should be the - # full list of possible choices - form = DomainApplicationAdminForm(instance=ineligible_application) + # Attempt to create a form with the ineligible application + # The form should not raise an error, but choices should be the + # full list of possible choices + form = DomainApplicationAdminForm(instance=ineligible_application) - self.assertEqual( - form.fields["status"].widget.choices, - DomainApplication._meta.get_field("status").choices, - ) + self.assertEqual( + form.fields["status"].widget.choices, + DomainApplication._meta.get_field("status").choices, + ) @boto3_mocking.patching @@ -327,90 +330,94 @@ class TestDomainApplicationAdmin(MockEppLib): def test_domain_sortable(self): """Tests if the DomainApplication sorts by domain correctly""" - p = "adminpass" - self.client.login(username="superuser", password=p) + with less_console_noise(): + p = "adminpass" + self.client.login(username="superuser", password=p) - multiple_unalphabetical_domain_objects("application") + multiple_unalphabetical_domain_objects("application") - # Assert that our sort works correctly - self.test_helper.assert_table_sorted("1", ("requested_domain__name",)) + # Assert that our sort works correctly + self.test_helper.assert_table_sorted("1", ("requested_domain__name",)) - # Assert that sorting in reverse works correctly - self.test_helper.assert_table_sorted("-1", ("-requested_domain__name",)) + # Assert that sorting in reverse works correctly + self.test_helper.assert_table_sorted("-1", ("-requested_domain__name",)) def test_submitter_sortable(self): """Tests if the DomainApplication sorts by domain correctly""" - p = "adminpass" - self.client.login(username="superuser", password=p) + with less_console_noise(): + p = "adminpass" + self.client.login(username="superuser", password=p) - multiple_unalphabetical_domain_objects("application") + multiple_unalphabetical_domain_objects("application") - additional_application = generic_domain_object("application", "Xylophone") - new_user = User.objects.filter(username=additional_application.investigator.username).get() - new_user.first_name = "Xylophonic" - new_user.save() + additional_application = generic_domain_object("application", "Xylophone") + new_user = User.objects.filter(username=additional_application.investigator.username).get() + new_user.first_name = "Xylophonic" + new_user.save() - # Assert that our sort works correctly - self.test_helper.assert_table_sorted( - "5", - ( - "submitter__first_name", - "submitter__last_name", - ), - ) + # Assert that our sort works correctly + self.test_helper.assert_table_sorted( + "11", + ( + "submitter__first_name", + "submitter__last_name", + ), + ) - # Assert that sorting in reverse works correctly - self.test_helper.assert_table_sorted( - "-5", - ( - "-submitter__first_name", - "-submitter__last_name", - ), - ) + # Assert that sorting in reverse works correctly + self.test_helper.assert_table_sorted( + "-11", + ( + "-submitter__first_name", + "-submitter__last_name", + ), + ) def test_investigator_sortable(self): """Tests if the DomainApplication sorts by domain correctly""" - p = "adminpass" - self.client.login(username="superuser", password=p) + with less_console_noise(): + p = "adminpass" + self.client.login(username="superuser", password=p) - multiple_unalphabetical_domain_objects("application") - additional_application = generic_domain_object("application", "Xylophone") - new_user = User.objects.filter(username=additional_application.investigator.username).get() - new_user.first_name = "Xylophonic" - new_user.save() + multiple_unalphabetical_domain_objects("application") + additional_application = generic_domain_object("application", "Xylophone") + new_user = User.objects.filter(username=additional_application.investigator.username).get() + new_user.first_name = "Xylophonic" + new_user.save() - # Assert that our sort works correctly - self.test_helper.assert_table_sorted( - "6", - ( - "investigator__first_name", - "investigator__last_name", - ), - ) + # Assert that our sort works correctly + self.test_helper.assert_table_sorted( + "6", + ( + "investigator__first_name", + "investigator__last_name", + ), + ) - # Assert that sorting in reverse works correctly - self.test_helper.assert_table_sorted( - "-6", - ( - "-investigator__first_name", - "-investigator__last_name", - ), - ) + # Assert that sorting in reverse works correctly + self.test_helper.assert_table_sorted( + "-6", + ( + "-investigator__first_name", + "-investigator__last_name", + ), + ) def test_short_org_name_in_applications_list(self): """ Make sure the short name is displaying in admin on the list page """ - self.client.force_login(self.superuser) - completed_application() - response = self.client.get("/admin/registrar/domainapplication/") - # There are 3 template references to Federal (3) plus one reference in the table - # for our actual application - self.assertContains(response, "Federal", count=4) - # This may be a bit more robust - self.assertContains(response, 'Federal', count=1) - # Now let's make sure the long description does not exist - self.assertNotContains(response, "Federal: an agency of the U.S. government") + with less_console_noise(): + self.client.force_login(self.superuser) + completed_application() + response = self.client.get("/admin/registrar/domainapplication/") + # There are 4 template references to Federal (4) plus two references in the table + # for our actual application + self.assertContains(response, "Federal", count=6) + # This may be a bit more robust + self.assertContains(response, 'Federal', count=1) + # Now let's make sure the long description does not exist + self.assertNotContains(response, "Federal: an agency of the U.S. government") def transition_state_and_send_email(self, application, status): """Helper method for the email test cases.""" @@ -430,20 +437,21 @@ class TestDomainApplicationAdmin(MockEppLib): """Helper method for the email test cases. email_index is the index of the email in mock_client.""" - # Access the arguments passed to send_email - call_args = self.mock_client.EMAILS_SENT - kwargs = call_args[email_index]["kwargs"] + with less_console_noise(): + # Access the arguments passed to send_email + call_args = self.mock_client.EMAILS_SENT + kwargs = call_args[email_index]["kwargs"] - # Retrieve the email details from the arguments - from_email = kwargs.get("FromEmailAddress") - to_email = kwargs["Destination"]["ToAddresses"][0] - email_content = kwargs["Content"] - email_body = email_content["Simple"]["Body"]["Text"]["Data"] + # Retrieve the email details from the arguments + from_email = kwargs.get("FromEmailAddress") + to_email = kwargs["Destination"]["ToAddresses"][0] + email_content = kwargs["Content"] + email_body = email_content["Simple"]["Body"]["Text"]["Data"] - # Assert or perform other checks on the email details - self.assertEqual(from_email, settings.DEFAULT_FROM_EMAIL) - self.assertEqual(to_email, email_address) - self.assertIn(expected_string, email_body) + # Assert or perform other checks on the email details + self.assertEqual(from_email, settings.DEFAULT_FROM_EMAIL) + self.assertEqual(to_email, email_address) + self.assertIn(expected_string, email_body) def test_save_model_sends_submitted_email(self): """When transitioning to submitted from started or withdrawn on a domain request, @@ -452,297 +460,303 @@ class TestDomainApplicationAdmin(MockEppLib): When transitioning to submitted from dns needed or in review on a domain request, no email is sent out.""" - # Ensure there is no user with this email - EMAIL = "mayor@igorville.gov" - User.objects.filter(email=EMAIL).delete() + with less_console_noise(): + # 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() + # Create a sample application + application = completed_application() - # Test Submitted Status from started - self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.SUBMITTED) - self.assert_email_is_accurate("We received your .gov domain request.", 0, EMAIL) - self.assertEqual(len(self.mock_client.EMAILS_SENT), 1) + # Test Submitted Status from started + self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.SUBMITTED) + self.assert_email_is_accurate("We received your .gov domain request.", 0, EMAIL) + self.assertEqual(len(self.mock_client.EMAILS_SENT), 1) - # Test Withdrawn Status - self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.WITHDRAWN) - self.assert_email_is_accurate( - "Your .gov domain request has been withdrawn and will not be reviewed by our team.", 1, EMAIL - ) - self.assertEqual(len(self.mock_client.EMAILS_SENT), 2) + # Test Withdrawn Status + self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.WITHDRAWN) + self.assert_email_is_accurate( + "Your .gov domain request has been withdrawn and will not be reviewed by our team.", 1, EMAIL + ) + self.assertEqual(len(self.mock_client.EMAILS_SENT), 2) - # Test Submitted Status Again (from withdrawn) - self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.SUBMITTED) - self.assertEqual(len(self.mock_client.EMAILS_SENT), 3) + # Test Submitted Status Again (from withdrawn) + self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.SUBMITTED) + self.assertEqual(len(self.mock_client.EMAILS_SENT), 3) - # Move it to IN_REVIEW - self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.IN_REVIEW) - self.assertEqual(len(self.mock_client.EMAILS_SENT), 3) + # Move it to IN_REVIEW + self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.IN_REVIEW) + self.assertEqual(len(self.mock_client.EMAILS_SENT), 3) - # Test Submitted Status Again from in IN_REVIEW, no new email should be sent - self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.SUBMITTED) - self.assertEqual(len(self.mock_client.EMAILS_SENT), 3) + # Test Submitted Status Again from in IN_REVIEW, no new email should be sent + self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.SUBMITTED) + self.assertEqual(len(self.mock_client.EMAILS_SENT), 3) - # Move it to IN_REVIEW - self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.IN_REVIEW) - self.assertEqual(len(self.mock_client.EMAILS_SENT), 3) + # Move it to IN_REVIEW + self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.IN_REVIEW) + self.assertEqual(len(self.mock_client.EMAILS_SENT), 3) - # Move it to ACTION_NEEDED - self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.ACTION_NEEDED) - self.assertEqual(len(self.mock_client.EMAILS_SENT), 3) + # Move it to ACTION_NEEDED + self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.ACTION_NEEDED) + self.assertEqual(len(self.mock_client.EMAILS_SENT), 3) - # Test Submitted Status Again from in ACTION_NEEDED, no new email should be sent - self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.SUBMITTED) - self.assertEqual(len(self.mock_client.EMAILS_SENT), 3) + # Test Submitted Status Again from in ACTION_NEEDED, no new email should be sent + self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.SUBMITTED) + self.assertEqual(len(self.mock_client.EMAILS_SENT), 3) def test_save_model_sends_approved_email(self): """When transitioning to approved on a domain request, an email is sent out every time.""" - # Ensure there is no user with this email - EMAIL = "mayor@igorville.gov" - User.objects.filter(email=EMAIL).delete() + with less_console_noise(): + # 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) + # Create a sample application + application = completed_application(status=DomainApplication.ApplicationStatus.IN_REVIEW) - # Test Submitted Status - self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.APPROVED) - self.assert_email_is_accurate("Congratulations! Your .gov domain request has been approved.", 0, EMAIL) - self.assertEqual(len(self.mock_client.EMAILS_SENT), 1) + # Test Submitted Status + self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.APPROVED) + self.assert_email_is_accurate("Congratulations! Your .gov domain request has been approved.", 0, EMAIL) + self.assertEqual(len(self.mock_client.EMAILS_SENT), 1) - # Test Withdrawn Status - self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.REJECTED) - self.assert_email_is_accurate("Your .gov domain request has been rejected.", 1, EMAIL) - self.assertEqual(len(self.mock_client.EMAILS_SENT), 2) + # Test Withdrawn Status + self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.REJECTED) + self.assert_email_is_accurate("Your .gov domain request has been rejected.", 1, EMAIL) + self.assertEqual(len(self.mock_client.EMAILS_SENT), 2) - # Test Submitted Status Again (No new email should be sent) - self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.APPROVED) - self.assertEqual(len(self.mock_client.EMAILS_SENT), 3) + # Test Submitted Status Again (No new email should be sent) + self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.APPROVED) + self.assertEqual(len(self.mock_client.EMAILS_SENT), 3) def test_save_model_sends_rejected_email(self): """When transitioning to rejected on a domain request, an email is sent out every time.""" - # Ensure there is no user with this email - EMAIL = "mayor@igorville.gov" - User.objects.filter(email=EMAIL).delete() + with less_console_noise(): + # 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) + # Create a sample application + application = completed_application(status=DomainApplication.ApplicationStatus.IN_REVIEW) - # Test Submitted Status - self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.REJECTED) - self.assert_email_is_accurate("Your .gov domain request has been rejected.", 0, EMAIL) - self.assertEqual(len(self.mock_client.EMAILS_SENT), 1) + # Test Submitted Status + self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.REJECTED) + self.assert_email_is_accurate("Your .gov domain request has been rejected.", 0, EMAIL) + self.assertEqual(len(self.mock_client.EMAILS_SENT), 1) - # Test Withdrawn Status - 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) + # Test Withdrawn Status + 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) - # Test Submitted Status Again (No new email should be sent) - self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.REJECTED) - self.assertEqual(len(self.mock_client.EMAILS_SENT), 3) + # Test Submitted Status Again (No new email should be sent) + self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.REJECTED) + self.assertEqual(len(self.mock_client.EMAILS_SENT), 3) def test_save_model_sends_withdrawn_email(self): """When transitioning to withdrawn on a domain request, an email is sent out every time.""" - # Ensure there is no user with this email - EMAIL = "mayor@igorville.gov" - User.objects.filter(email=EMAIL).delete() + with less_console_noise(): + # 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) + # Create a sample application + application = completed_application(status=DomainApplication.ApplicationStatus.IN_REVIEW) - # Test Submitted Status - self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.WITHDRAWN) - self.assert_email_is_accurate( - "Your .gov domain request has been withdrawn and will not be reviewed by our team.", 0, EMAIL - ) - self.assertEqual(len(self.mock_client.EMAILS_SENT), 1) + # Test Submitted Status + self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.WITHDRAWN) + self.assert_email_is_accurate( + "Your .gov domain request has been withdrawn and will not be reviewed by our team.", 0, EMAIL + ) + self.assertEqual(len(self.mock_client.EMAILS_SENT), 1) - # Test Withdrawn Status - self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.SUBMITTED) - self.assert_email_is_accurate("We received your .gov domain request.", 1, EMAIL) - self.assertEqual(len(self.mock_client.EMAILS_SENT), 2) + # Test Withdrawn Status + self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.SUBMITTED) + self.assert_email_is_accurate("We received your .gov domain request.", 1, EMAIL) + self.assertEqual(len(self.mock_client.EMAILS_SENT), 2) - # Test Submitted Status Again (No new email should be sent) - self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.WITHDRAWN) - self.assertEqual(len(self.mock_client.EMAILS_SENT), 3) + # Test Submitted Status Again (No new email should be sent) + self.transition_state_and_send_email(application, DomainApplication.ApplicationStatus.WITHDRAWN) + self.assertEqual(len(self.mock_client.EMAILS_SENT), 3) def test_save_model_sets_approved_domain(self): - # make sure there is no user with this email - EMAIL = "mayor@igorville.gov" - User.objects.filter(email=EMAIL).delete() + with less_console_noise(): + # make sure 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) + # Create a sample application + application = completed_application(status=DomainApplication.ApplicationStatus.IN_REVIEW) - # Create a mock request - request = self.factory.post("/admin/registrar/domainapplication/{}/change/".format(application.pk)) + # Create a mock request + request = self.factory.post("/admin/registrar/domainapplication/{}/change/".format(application.pk)) - with boto3_mocking.clients.handler_for("sesv2", self.mock_client): - with less_console_noise(): + with boto3_mocking.clients.handler_for("sesv2", self.mock_client): # Modify the application's property application.status = DomainApplication.ApplicationStatus.APPROVED # Use the model admin's save_model method self.admin.save_model(request, application, form=None, change=True) - # Test that approved domain exists and equals requested domain - self.assertEqual(application.requested_domain.name, application.approved_domain.name) + # Test that approved domain exists and equals requested domain + self.assertEqual(application.requested_domain.name, application.approved_domain.name) def test_save_model_sets_restricted_status_on_user(self): - # make sure there is no user with this email - EMAIL = "mayor@igorville.gov" - User.objects.filter(email=EMAIL).delete() + with less_console_noise(): + # make sure 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) + # Create a sample application + application = completed_application(status=DomainApplication.ApplicationStatus.IN_REVIEW) - # Create a mock request - request = self.factory.post("/admin/registrar/domainapplication/{}/change/".format(application.pk)) + # Create a mock request + request = self.factory.post("/admin/registrar/domainapplication/{}/change/".format(application.pk)) - with boto3_mocking.clients.handler_for("sesv2", self.mock_client): - with less_console_noise(): + with boto3_mocking.clients.handler_for("sesv2", self.mock_client): # Modify the application's property application.status = DomainApplication.ApplicationStatus.INELIGIBLE # Use the model admin's save_model method self.admin.save_model(request, application, form=None, change=True) - # Test that approved domain exists and equals requested domain - self.assertEqual(application.creator.status, "restricted") + # Test that approved domain exists and equals requested domain + self.assertEqual(application.creator.status, "restricted") def test_readonly_when_restricted_creator(self): - application = completed_application(status=DomainApplication.ApplicationStatus.IN_REVIEW) - with boto3_mocking.clients.handler_for("sesv2", self.mock_client): - with less_console_noise(): + with less_console_noise(): + application = completed_application(status=DomainApplication.ApplicationStatus.IN_REVIEW) + with boto3_mocking.clients.handler_for("sesv2", self.mock_client): application.creator.status = User.RESTRICTED application.creator.save() - request = self.factory.get("/") - request.user = self.superuser - - readonly_fields = self.admin.get_readonly_fields(request, application) - - expected_fields = [ - "id", - "created_at", - "updated_at", - "status", - "creator", - "investigator", - "organization_type", - "federally_recognized_tribe", - "state_recognized_tribe", - "tribe_name", - "federal_agency", - "federal_type", - "is_election_board", - "organization_name", - "address_line1", - "address_line2", - "city", - "state_territory", - "zipcode", - "urbanization", - "about_your_organization", - "authorizing_official", - "approved_domain", - "requested_domain", - "submitter", - "purpose", - "no_other_contacts_rationale", - "anything_else", - "is_policy_acknowledged", - "submission_date", - "notes", - "current_websites", - "other_contacts", - "alternative_domains", - ] - - self.assertEqual(readonly_fields, expected_fields) - - def test_readonly_fields_for_analyst(self): - request = self.factory.get("/") # Use the correct method and path - request.user = self.staffuser - - readonly_fields = self.admin.get_readonly_fields(request) - - expected_fields = [ - "creator", - "about_your_organization", - "requested_domain", - "approved_domain", - "alternative_domains", - "purpose", - "submitter", - "no_other_contacts_rationale", - "anything_else", - "is_policy_acknowledged", - ] - - self.assertEqual(readonly_fields, expected_fields) - - def test_readonly_fields_for_superuser(self): - request = self.factory.get("/") # Use the correct method and path - request.user = self.superuser - - readonly_fields = self.admin.get_readonly_fields(request) - - expected_fields = [] - - self.assertEqual(readonly_fields, expected_fields) - - def test_saving_when_restricted_creator(self): - # Create an instance of the model - application = completed_application(status=DomainApplication.ApplicationStatus.IN_REVIEW) - with boto3_mocking.clients.handler_for("sesv2", self.mock_client): - with less_console_noise(): - application.creator.status = User.RESTRICTED - application.creator.save() - - # Create a request object with a superuser - request = self.factory.get("/") - request.user = self.superuser - - with patch("django.contrib.messages.error") as mock_error: - # Simulate saving the model - self.admin.save_model(request, application, None, False) - - # Assert that the error message was called with the correct argument - mock_error.assert_called_once_with( - request, - "This action is not permitted for applications with a restricted creator.", - ) - - # Assert that the status has not changed - self.assertEqual(application.status, DomainApplication.ApplicationStatus.IN_REVIEW) - - def test_change_view_with_restricted_creator(self): - # Create an instance of the model - application = completed_application(status=DomainApplication.ApplicationStatus.IN_REVIEW) - with boto3_mocking.clients.handler_for("sesv2", self.mock_client): - with less_console_noise(): - application.creator.status = User.RESTRICTED - application.creator.save() - - with patch("django.contrib.messages.warning") as mock_warning: - # Create a request object with a superuser - request = self.factory.get("/admin/your_app/domainapplication/{}/change/".format(application.pk)) + request = self.factory.get("/") request.user = self.superuser - self.admin.display_restricted_warning(request, application) + readonly_fields = self.admin.get_readonly_fields(request, application) - # Assert that the error message was called with the correct argument - mock_warning.assert_called_once_with( - request, - "Cannot edit an application with a restricted creator.", - ) + expected_fields = [ + "id", + "created_at", + "updated_at", + "status", + "creator", + "investigator", + "organization_type", + "federally_recognized_tribe", + "state_recognized_tribe", + "tribe_name", + "federal_agency", + "federal_type", + "is_election_board", + "organization_name", + "address_line1", + "address_line2", + "city", + "state_territory", + "zipcode", + "urbanization", + "about_your_organization", + "authorizing_official", + "approved_domain", + "requested_domain", + "submitter", + "purpose", + "no_other_contacts_rationale", + "anything_else", + "is_policy_acknowledged", + "submission_date", + "notes", + "current_websites", + "other_contacts", + "alternative_domains", + ] + + self.assertEqual(readonly_fields, expected_fields) + + def test_readonly_fields_for_analyst(self): + with less_console_noise(): + request = self.factory.get("/") # Use the correct method and path + request.user = self.staffuser + + readonly_fields = self.admin.get_readonly_fields(request) + + expected_fields = [ + "creator", + "about_your_organization", + "requested_domain", + "approved_domain", + "alternative_domains", + "purpose", + "submitter", + "no_other_contacts_rationale", + "anything_else", + "is_policy_acknowledged", + ] + + self.assertEqual(readonly_fields, expected_fields) + + def test_readonly_fields_for_superuser(self): + with less_console_noise(): + request = self.factory.get("/") # Use the correct method and path + request.user = self.superuser + + readonly_fields = self.admin.get_readonly_fields(request) + + expected_fields = [] + + self.assertEqual(readonly_fields, expected_fields) + + def test_saving_when_restricted_creator(self): + with less_console_noise(): + # Create an instance of the model + application = completed_application(status=DomainApplication.ApplicationStatus.IN_REVIEW) + with boto3_mocking.clients.handler_for("sesv2", self.mock_client): + application.creator.status = User.RESTRICTED + application.creator.save() + + # Create a request object with a superuser + request = self.factory.get("/") + request.user = self.superuser + + with patch("django.contrib.messages.error") as mock_error: + # Simulate saving the model + self.admin.save_model(request, application, None, False) + + # Assert that the error message was called with the correct argument + mock_error.assert_called_once_with( + request, + "This action is not permitted for applications with a restricted creator.", + ) + + # Assert that the status has not changed + self.assertEqual(application.status, DomainApplication.ApplicationStatus.IN_REVIEW) + + def test_change_view_with_restricted_creator(self): + with less_console_noise(): + # Create an instance of the model + application = completed_application(status=DomainApplication.ApplicationStatus.IN_REVIEW) + with boto3_mocking.clients.handler_for("sesv2", self.mock_client): + application.creator.status = User.RESTRICTED + application.creator.save() + + with patch("django.contrib.messages.warning") as mock_warning: + # Create a request object with a superuser + request = self.factory.get("/admin/your_app/domainapplication/{}/change/".format(application.pk)) + request.user = self.superuser + + self.admin.display_restricted_warning(request, application) + + # Assert that the error message was called with the correct argument + mock_warning.assert_called_once_with( + request, + "Cannot edit an application with a restricted creator.", + ) def trigger_saving_approved_to_another_state(self, domain_is_active, another_state): """Helper method that triggers domain request state changes from approved to another state, @@ -751,49 +765,50 @@ class TestDomainApplicationAdmin(MockEppLib): Used to test errors when saving a change with an active domain, also used to test side effects when saving a change goes through.""" - # Create an instance of the model - application = completed_application(status=DomainApplication.ApplicationStatus.APPROVED) - domain = Domain.objects.create(name=application.requested_domain.name) - domain_information = DomainInformation.objects.create(creator=self.superuser, domain=domain) - application.approved_domain = domain - application.save() + with less_console_noise(): + # Create an instance of the model + application = completed_application(status=DomainApplication.ApplicationStatus.APPROVED) + domain = Domain.objects.create(name=application.requested_domain.name) + domain_information = DomainInformation.objects.create(creator=self.superuser, domain=domain) + application.approved_domain = domain + application.save() - # Create a request object with a superuser - request = self.factory.post("/admin/registrar/domainapplication/{}/change/".format(application.pk)) - request.user = self.superuser + # Create a request object with a superuser + request = self.factory.post("/admin/registrar/domainapplication/{}/change/".format(application.pk)) + request.user = self.superuser - # Define a custom implementation for is_active - def custom_is_active(self): - return domain_is_active # Override to return True + # Define a custom implementation for is_active + def custom_is_active(self): + return domain_is_active # Override to return True - # Use ExitStack to combine patch contexts - with ExitStack() as stack: - # Patch Domain.is_active and django.contrib.messages.error simultaneously - stack.enter_context(patch.object(Domain, "is_active", custom_is_active)) - stack.enter_context(patch.object(messages, "error")) + # Use ExitStack to combine patch contexts + with ExitStack() as stack: + # Patch Domain.is_active and django.contrib.messages.error simultaneously + stack.enter_context(patch.object(Domain, "is_active", custom_is_active)) + stack.enter_context(patch.object(messages, "error")) - application.status = another_state - self.admin.save_model(request, application, None, True) + application.status = another_state + self.admin.save_model(request, application, None, True) - # Assert that the error message was called with the correct argument - if domain_is_active: - messages.error.assert_called_once_with( - request, - "This action is not permitted. The domain " + "is already active.", - ) - else: - # Assert that the error message was never called - messages.error.assert_not_called() + # Assert that the error message was called with the correct argument + if domain_is_active: + messages.error.assert_called_once_with( + request, + "This action is not permitted. The domain " + "is already active.", + ) + else: + # Assert that the error message was never called + messages.error.assert_not_called() - self.assertEqual(application.approved_domain, None) + self.assertEqual(application.approved_domain, None) - # Assert that Domain got Deleted - with self.assertRaises(Domain.DoesNotExist): - domain.refresh_from_db() + # Assert that Domain got Deleted + with self.assertRaises(Domain.DoesNotExist): + domain.refresh_from_db() - # Assert that DomainInformation got Deleted - with self.assertRaises(DomainInformation.DoesNotExist): - domain_information.refresh_from_db() + # Assert that DomainInformation got Deleted + with self.assertRaises(DomainInformation.DoesNotExist): + domain_information.refresh_from_db() def test_error_when_saving_approved_to_in_review_and_domain_is_active(self): self.trigger_saving_approved_to_another_state(True, DomainApplication.ApplicationStatus.IN_REVIEW) @@ -826,14 +841,15 @@ class TestDomainApplicationAdmin(MockEppLib): It retrieves the current list of filters from DomainApplicationAdmin and checks that it matches the expected list of filters. """ - request = self.factory.get("/") - request.user = self.superuser + with less_console_noise(): + request = self.factory.get("/") + request.user = self.superuser - # Grab the current list of table filters - readonly_fields = self.admin.get_list_filter(request) - expected_fields = ("status", "organization_type", DomainApplicationAdmin.InvestigatorFilter) + # Grab the current list of table filters + readonly_fields = self.admin.get_list_filter(request) + expected_fields = ("status", "organization_type", DomainApplicationAdmin.InvestigatorFilter) - self.assertEqual(readonly_fields, expected_fields) + self.assertEqual(readonly_fields, expected_fields) def test_table_sorted_alphabetically(self): """ @@ -845,23 +861,24 @@ class TestDomainApplicationAdmin(MockEppLib): that it matches the expected queryset, which is sorted alphabetically by the 'requested_domain__name' field. """ - # Creates a list of DomainApplications in scrambled order - multiple_unalphabetical_domain_objects("application") + with less_console_noise(): + # Creates a list of DomainApplications in scrambled order + multiple_unalphabetical_domain_objects("application") - request = self.factory.get("/") - request.user = self.superuser + request = self.factory.get("/") + request.user = self.superuser - # Get the expected list of alphabetically sorted DomainApplications - expected_order = DomainApplication.objects.order_by("requested_domain__name") + # Get the expected list of alphabetically sorted DomainApplications + expected_order = DomainApplication.objects.order_by("requested_domain__name") - # Get the returned queryset - queryset = self.admin.get_queryset(request) + # Get the returned queryset + queryset = self.admin.get_queryset(request) - # Check the order - self.assertEqual( - list(queryset), - list(expected_order), - ) + # Check the order + self.assertEqual( + list(queryset), + list(expected_order), + ) def test_displays_investigator_filter(self): """ @@ -877,37 +894,38 @@ class TestDomainApplicationAdmin(MockEppLib): the filter displays correctly, when the filter isn't filtering correctly. """ - # Create a mock DomainApplication object, with a fake investigator - application: DomainApplication = generic_domain_object("application", "SomeGuy") - investigator_user = User.objects.filter(username=application.investigator.username).get() - investigator_user.is_staff = True - investigator_user.save() + with less_console_noise(): + # Create a mock DomainApplication object, with a fake investigator + application: DomainApplication = generic_domain_object("application", "SomeGuy") + investigator_user = User.objects.filter(username=application.investigator.username).get() + investigator_user.is_staff = True + investigator_user.save() - p = "userpass" - self.client.login(username="staffuser", password=p) - response = self.client.get( - "/admin/registrar/domainapplication/", - { - "investigator__id__exact": investigator_user.id, - }, - follow=True, - ) - - # Then, test if the filter actually exists - self.assertIn("filters", response.context) - - # Assert the content of filters and search_query - filters = response.context["filters"] - - self.assertEqual( - filters, - [ + p = "userpass" + self.client.login(username="staffuser", password=p) + response = self.client.get( + "/admin/registrar/domainapplication/", { - "parameter_name": "investigator", - "parameter_value": "SomeGuy first_name:investigator SomeGuy last_name:investigator", + "investigator__id__exact": investigator_user.id, }, - ], - ) + follow=True, + ) + + # Then, test if the filter actually exists + self.assertIn("filters", response.context) + + # Assert the content of filters and search_query + filters = response.context["filters"] + + self.assertEqual( + filters, + [ + { + "parameter_name": "investigator", + "parameter_value": "SomeGuy first_name:investigator SomeGuy last_name:investigator", + }, + ], + ) def test_investigator_dropdown_displays_only_staff(self): """ @@ -920,68 +938,70 @@ class TestDomainApplicationAdmin(MockEppLib): It then retrieves the queryset for the 'investigator' dropdown from DomainApplicationAdmin and checks that it matches the expected queryset, which only includes staff users. """ - # Create a mock DomainApplication object, with a fake investigator - application: DomainApplication = generic_domain_object("application", "SomeGuy") - investigator_user = User.objects.filter(username=application.investigator.username).get() - investigator_user.is_staff = True - investigator_user.save() + with less_console_noise(): + # Create a mock DomainApplication object, with a fake investigator + application: DomainApplication = generic_domain_object("application", "SomeGuy") + investigator_user = User.objects.filter(username=application.investigator.username).get() + investigator_user.is_staff = True + investigator_user.save() - # Create a mock DomainApplication object, with a user that is not staff - application_2: DomainApplication = generic_domain_object("application", "SomeOtherGuy") - investigator_user_2 = User.objects.filter(username=application_2.investigator.username).get() - investigator_user_2.is_staff = False - investigator_user_2.save() + # Create a mock DomainApplication object, with a user that is not staff + application_2: DomainApplication = generic_domain_object("application", "SomeOtherGuy") + investigator_user_2 = User.objects.filter(username=application_2.investigator.username).get() + investigator_user_2.is_staff = False + investigator_user_2.save() - p = "userpass" - self.client.login(username="staffuser", password=p) + p = "userpass" + self.client.login(username="staffuser", password=p) - request = self.factory.post("/admin/registrar/domainapplication/{}/change/".format(application.pk)) + request = self.factory.post("/admin/registrar/domainapplication/{}/change/".format(application.pk)) - # Get the actual field from the model's meta information - investigator_field = DomainApplication._meta.get_field("investigator") + # Get the actual field from the model's meta information + investigator_field = DomainApplication._meta.get_field("investigator") - # We should only be displaying staff users, in alphabetical order - expected_dropdown = list(User.objects.filter(is_staff=True)) - current_dropdown = list(self.admin.formfield_for_foreignkey(investigator_field, request).queryset) + # We should only be displaying staff users, in alphabetical order + expected_dropdown = list(User.objects.filter(is_staff=True)) + current_dropdown = list(self.admin.formfield_for_foreignkey(investigator_field, request).queryset) - self.assertEqual(expected_dropdown, current_dropdown) + self.assertEqual(expected_dropdown, current_dropdown) - # Non staff users should not be in the list - self.assertNotIn(application_2, current_dropdown) + # Non staff users should not be in the list + self.assertNotIn(application_2, current_dropdown) def test_investigator_list_is_alphabetically_sorted(self): """ This test verifies that filter list for the 'investigator' is displayed alphabetically """ - # Create a mock DomainApplication object, with a fake investigator - application: DomainApplication = generic_domain_object("application", "SomeGuy") - investigator_user = User.objects.filter(username=application.investigator.username).get() - investigator_user.is_staff = True - investigator_user.save() + with less_console_noise(): + # Create a mock DomainApplication object, with a fake investigator + application: DomainApplication = generic_domain_object("application", "SomeGuy") + investigator_user = User.objects.filter(username=application.investigator.username).get() + investigator_user.is_staff = True + investigator_user.save() - application_2: DomainApplication = generic_domain_object("application", "AGuy") - investigator_user_2 = User.objects.filter(username=application_2.investigator.username).get() - investigator_user_2.first_name = "AGuy" - investigator_user_2.is_staff = True - investigator_user_2.save() + application_2: DomainApplication = generic_domain_object("application", "AGuy") + investigator_user_2 = User.objects.filter(username=application_2.investigator.username).get() + investigator_user_2.first_name = "AGuy" + investigator_user_2.is_staff = True + investigator_user_2.save() - application_3: DomainApplication = generic_domain_object("application", "FinalGuy") - investigator_user_3 = User.objects.filter(username=application_3.investigator.username).get() - investigator_user_3.first_name = "FinalGuy" - investigator_user_3.is_staff = True - investigator_user_3.save() + application_3: DomainApplication = generic_domain_object("application", "FinalGuy") + investigator_user_3 = User.objects.filter(username=application_3.investigator.username).get() + investigator_user_3.first_name = "FinalGuy" + investigator_user_3.is_staff = True + investigator_user_3.save() - p = "userpass" - self.client.login(username="staffuser", password=p) - request = RequestFactory().get("/") + p = "userpass" + self.client.login(username="staffuser", password=p) + request = RequestFactory().get("/") - expected_list = list(User.objects.filter(is_staff=True).order_by("first_name", "last_name", "email")) + expected_list = list(User.objects.filter(is_staff=True).order_by("first_name", "last_name", "email")) - # Get the actual sorted list of investigators from the lookups method - actual_list = [item for _, item in self.admin.InvestigatorFilter.lookups(self, request, self.admin)] + # Get the actual sorted list of investigators from the lookups method + actual_list = [item for _, item in self.admin.InvestigatorFilter.lookups(self, request, self.admin)] - self.assertEqual(expected_list, actual_list) + self.assertEqual(expected_list, actual_list) def tearDown(self): super().tearDown() @@ -1010,28 +1030,29 @@ class DomainInvitationAdminTest(TestCase): def test_get_filters(self): """Ensures that our filters are displaying correctly""" - # Have to get creative to get past linter - p = "adminpass" - self.client.login(username="superuser", password=p) + with less_console_noise(): + # Have to get creative to get past linter + p = "adminpass" + self.client.login(username="superuser", password=p) - response = self.client.get( - "/admin/registrar/domaininvitation/", - {}, - follow=True, - ) + response = self.client.get( + "/admin/registrar/domaininvitation/", + {}, + follow=True, + ) - # Assert that the filters are added - self.assertContains(response, "invited", count=2) - self.assertContains(response, "Invited", count=2) - self.assertContains(response, "retrieved", count=2) - self.assertContains(response, "Retrieved", count=2) + # Assert that the filters are added + self.assertContains(response, "invited", count=2) + self.assertContains(response, "Invited", count=2) + self.assertContains(response, "retrieved", count=2) + self.assertContains(response, "Retrieved", count=2) - # Check for the HTML context specificially - invited_html = 'Invited' - retrieved_html = 'Retrieved' + # Check for the HTML context specificially + invited_html = 'Invited' + retrieved_html = 'Retrieved' - self.assertContains(response, invited_html, count=1) - self.assertContains(response, retrieved_html, count=1) + self.assertContains(response, invited_html, count=1) + self.assertContains(response, retrieved_html, count=1) class TestDomainInformationAdmin(TestCase): @@ -1088,49 +1109,52 @@ class TestDomainInformationAdmin(TestCase): def test_readonly_fields_for_analyst(self): """Ensures that analysts have their permissions setup correctly""" - request = self.factory.get("/") - request.user = self.staffuser + with less_console_noise(): + request = self.factory.get("/") + request.user = self.staffuser - readonly_fields = self.admin.get_readonly_fields(request) + readonly_fields = self.admin.get_readonly_fields(request) - expected_fields = [ - "creator", - "type_of_work", - "more_organization_information", - "domain", - "domain_application", - "submitter", - "no_other_contacts_rationale", - "anything_else", - "is_policy_acknowledged", - ] + expected_fields = [ + "creator", + "type_of_work", + "more_organization_information", + "domain", + "domain_application", + "submitter", + "no_other_contacts_rationale", + "anything_else", + "is_policy_acknowledged", + ] - self.assertEqual(readonly_fields, expected_fields) + self.assertEqual(readonly_fields, expected_fields) def test_domain_sortable(self): """Tests if DomainInformation sorts by domain correctly""" - p = "adminpass" - self.client.login(username="superuser", password=p) + with less_console_noise(): + p = "adminpass" + self.client.login(username="superuser", password=p) - # Assert that our sort works correctly - self.test_helper.assert_table_sorted("1", ("domain__name",)) + # Assert that our sort works correctly + self.test_helper.assert_table_sorted("1", ("domain__name",)) - # Assert that sorting in reverse works correctly - self.test_helper.assert_table_sorted("-1", ("-domain__name",)) + # Assert that sorting in reverse works correctly + self.test_helper.assert_table_sorted("-1", ("-domain__name",)) def test_submitter_sortable(self): """Tests if DomainInformation sorts by submitter correctly""" - p = "adminpass" - self.client.login(username="superuser", password=p) + with less_console_noise(): + p = "adminpass" + self.client.login(username="superuser", password=p) - # Assert that our sort works correctly - self.test_helper.assert_table_sorted( - "4", - ("submitter__first_name", "submitter__last_name"), - ) + # Assert that our sort works correctly + self.test_helper.assert_table_sorted( + "4", + ("submitter__first_name", "submitter__last_name"), + ) - # Assert that sorting in reverse works correctly - self.test_helper.assert_table_sorted("-4", ("-submitter__first_name", "-submitter__last_name")) + # Assert that sorting in reverse works correctly + self.test_helper.assert_table_sorted("-4", ("-submitter__first_name", "-submitter__last_name")) class UserDomainRoleAdminTest(TestCase): @@ -1157,109 +1181,113 @@ class UserDomainRoleAdminTest(TestCase): def test_domain_sortable(self): """Tests if the UserDomainrole sorts by domain correctly""" - p = "adminpass" - self.client.login(username="superuser", password=p) + with less_console_noise(): + p = "adminpass" + self.client.login(username="superuser", password=p) - fake_user = User.objects.create( - username="dummyuser", first_name="Stewart", last_name="Jones", email="AntarcticPolarBears@example.com" - ) + fake_user = User.objects.create( + username="dummyuser", first_name="Stewart", last_name="Jones", email="AntarcticPolarBears@example.com" + ) - # Create a list of UserDomainRoles that are in random order - mocks_to_create = ["jkl.gov", "ghi.gov", "abc.gov", "def.gov"] - for name in mocks_to_create: - fake_domain = Domain.objects.create(name=name) - UserDomainRole.objects.create(user=fake_user, domain=fake_domain, role="manager") + # Create a list of UserDomainRoles that are in random order + mocks_to_create = ["jkl.gov", "ghi.gov", "abc.gov", "def.gov"] + for name in mocks_to_create: + fake_domain = Domain.objects.create(name=name) + UserDomainRole.objects.create(user=fake_user, domain=fake_domain, role="manager") - # Assert that our sort works correctly - self.test_helper.assert_table_sorted("2", ("domain__name",)) + # Assert that our sort works correctly + self.test_helper.assert_table_sorted("2", ("domain__name",)) - # Assert that sorting in reverse works correctly - self.test_helper.assert_table_sorted("-2", ("-domain__name",)) + # Assert that sorting in reverse works correctly + self.test_helper.assert_table_sorted("-2", ("-domain__name",)) def test_user_sortable(self): """Tests if the UserDomainrole sorts by user correctly""" - p = "adminpass" - self.client.login(username="superuser", password=p) + with less_console_noise(): + p = "adminpass" + self.client.login(username="superuser", password=p) - mock_data_generator = AuditedAdminMockData() + mock_data_generator = AuditedAdminMockData() - fake_domain = Domain.objects.create(name="igorville.gov") - # Create a list of UserDomainRoles that are in random order - mocks_to_create = ["jkl", "ghi", "abc", "def"] - for name in mocks_to_create: - # Creates a fake "User" object - fake_user = mock_data_generator.dummy_user(name, "user") - UserDomainRole.objects.create(user=fake_user, domain=fake_domain, role="manager") + fake_domain = Domain.objects.create(name="igorville.gov") + # Create a list of UserDomainRoles that are in random order + mocks_to_create = ["jkl", "ghi", "abc", "def"] + for name in mocks_to_create: + # Creates a fake "User" object + fake_user = mock_data_generator.dummy_user(name, "user") + UserDomainRole.objects.create(user=fake_user, domain=fake_domain, role="manager") - # Assert that our sort works correctly - self.test_helper.assert_table_sorted("1", ("user__first_name", "user__last_name")) + # Assert that our sort works correctly + self.test_helper.assert_table_sorted("1", ("user__first_name", "user__last_name")) - # Assert that sorting in reverse works correctly - self.test_helper.assert_table_sorted("-1", ("-user__first_name", "-user__last_name")) + # Assert that sorting in reverse works correctly + self.test_helper.assert_table_sorted("-1", ("-user__first_name", "-user__last_name")) def test_email_not_in_search(self): """Tests the search bar in Django Admin for UserDomainRoleAdmin. Should return no results for an invalid email.""" - # Have to get creative to get past linter - p = "adminpass" - self.client.login(username="superuser", password=p) + with less_console_noise(): + # Have to get creative to get past linter + p = "adminpass" + self.client.login(username="superuser", password=p) - fake_user = User.objects.create( - username="dummyuser", first_name="Stewart", last_name="Jones", email="AntarcticPolarBears@example.com" - ) - fake_domain = Domain.objects.create(name="test123") - UserDomainRole.objects.create(user=fake_user, domain=fake_domain, role="manager") - # Make the request using the Client class - # which handles CSRF - # Follow=True handles the redirect - response = self.client.get( - "/admin/registrar/userdomainrole/", - { - "q": "testmail@igorville.com", - }, - follow=True, - ) + fake_user = User.objects.create( + username="dummyuser", first_name="Stewart", last_name="Jones", email="AntarcticPolarBears@example.com" + ) + fake_domain = Domain.objects.create(name="test123") + UserDomainRole.objects.create(user=fake_user, domain=fake_domain, role="manager") + # Make the request using the Client class + # which handles CSRF + # Follow=True handles the redirect + response = self.client.get( + "/admin/registrar/userdomainrole/", + { + "q": "testmail@igorville.com", + }, + follow=True, + ) - # Assert that the query is added to the extra_context - self.assertIn("search_query", response.context) - # Assert the content of filters and search_query - search_query = response.context["search_query"] - self.assertEqual(search_query, "testmail@igorville.com") + # Assert that the query is added to the extra_context + self.assertIn("search_query", response.context) + # Assert the content of filters and search_query + search_query = response.context["search_query"] + self.assertEqual(search_query, "testmail@igorville.com") - # We only need to check for the end of the HTML string - self.assertNotContains(response, "Stewart Jones AntarcticPolarBears@example.com") + # We only need to check for the end of the HTML string + self.assertNotContains(response, "Stewart Jones AntarcticPolarBears@example.com") def test_email_in_search(self): """Tests the search bar in Django Admin for UserDomainRoleAdmin. Should return results for an valid email.""" - # Have to get creative to get past linter - p = "adminpass" - self.client.login(username="superuser", password=p) + with less_console_noise(): + # Have to get creative to get past linter + p = "adminpass" + self.client.login(username="superuser", password=p) - fake_user = User.objects.create( - username="dummyuser", first_name="Joe", last_name="Jones", email="AntarcticPolarBears@example.com" - ) - fake_domain = Domain.objects.create(name="fake") - UserDomainRole.objects.create(user=fake_user, domain=fake_domain, role="manager") - # Make the request using the Client class - # which handles CSRF - # Follow=True handles the redirect - response = self.client.get( - "/admin/registrar/userdomainrole/", - { - "q": "AntarcticPolarBears@example.com", - }, - follow=True, - ) + fake_user = User.objects.create( + username="dummyuser", first_name="Joe", last_name="Jones", email="AntarcticPolarBears@example.com" + ) + fake_domain = Domain.objects.create(name="fake") + UserDomainRole.objects.create(user=fake_user, domain=fake_domain, role="manager") + # Make the request using the Client class + # which handles CSRF + # Follow=True handles the redirect + response = self.client.get( + "/admin/registrar/userdomainrole/", + { + "q": "AntarcticPolarBears@example.com", + }, + follow=True, + ) - # Assert that the query is added to the extra_context - self.assertIn("search_query", response.context) + # Assert that the query is added to the extra_context + self.assertIn("search_query", response.context) - search_query = response.context["search_query"] - self.assertEqual(search_query, "AntarcticPolarBears@example.com") + search_query = response.context["search_query"] + self.assertEqual(search_query, "AntarcticPolarBears@example.com") - # We only need to check for the end of the HTML string - self.assertContains(response, "Joe Jones AntarcticPolarBears@example.com", count=1) + # We only need to check for the end of the HTML string + self.assertContains(response, "Joe Jones AntarcticPolarBears@example.com", count=1) class ListHeaderAdminTest(TestCase): @@ -1341,39 +1369,42 @@ class MyUserAdminTest(TestCase): self.admin = MyUserAdmin(model=get_user_model(), admin_site=admin_site) def test_list_display_without_username(self): - request = self.client.request().wsgi_request - request.user = create_user() + with less_console_noise(): + request = self.client.request().wsgi_request + request.user = create_user() - list_display = self.admin.get_list_display(request) - expected_list_display = [ - "email", - "first_name", - "last_name", - "group", - "status", - ] + list_display = self.admin.get_list_display(request) + expected_list_display = [ + "email", + "first_name", + "last_name", + "group", + "status", + ] - self.assertEqual(list_display, expected_list_display) - self.assertNotIn("username", list_display) + self.assertEqual(list_display, expected_list_display) + self.assertNotIn("username", list_display) def test_get_fieldsets_superuser(self): - request = self.client.request().wsgi_request - request.user = create_superuser() - fieldsets = self.admin.get_fieldsets(request) - expected_fieldsets = super(MyUserAdmin, self.admin).get_fieldsets(request) - self.assertEqual(fieldsets, expected_fieldsets) + with less_console_noise(): + request = self.client.request().wsgi_request + request.user = create_superuser() + fieldsets = self.admin.get_fieldsets(request) + expected_fieldsets = super(MyUserAdmin, self.admin).get_fieldsets(request) + self.assertEqual(fieldsets, expected_fieldsets) def test_get_fieldsets_cisa_analyst(self): - request = self.client.request().wsgi_request - request.user = create_user() - fieldsets = self.admin.get_fieldsets(request) - expected_fieldsets = ( - (None, {"fields": ("password", "status")}), - ("Personal Info", {"fields": ("first_name", "last_name", "email")}), - ("Permissions", {"fields": ("is_active", "groups")}), - ("Important dates", {"fields": ("last_login", "date_joined")}), - ) - self.assertEqual(fieldsets, expected_fieldsets) + with less_console_noise(): + request = self.client.request().wsgi_request + request.user = create_user() + fieldsets = self.admin.get_fieldsets(request) + expected_fieldsets = ( + (None, {"fields": ("password", "status")}), + ("Personal Info", {"fields": ("first_name", "last_name", "email")}), + ("Permissions", {"fields": ("is_active", "groups")}), + ("Important dates", {"fields": ("last_login", "date_joined")}), + ) + self.assertEqual(fieldsets, expected_fieldsets) def tearDown(self): User.objects.all().delete() @@ -1386,172 +1417,176 @@ class AuditedAdminTest(TestCase): self.client = Client(HTTP_HOST="localhost:8080") def order_by_desired_field_helper(self, obj_to_sort: AuditedAdmin, request, field_name, *obj_names): - formatted_sort_fields = [] - for obj in obj_names: - formatted_sort_fields.append("{}__{}".format(field_name, obj)) + with less_console_noise(): + formatted_sort_fields = [] + for obj in obj_names: + formatted_sort_fields.append("{}__{}".format(field_name, obj)) - ordered_list = list( - obj_to_sort.get_queryset(request).order_by(*formatted_sort_fields).values_list(*formatted_sort_fields) - ) + ordered_list = list( + obj_to_sort.get_queryset(request).order_by(*formatted_sort_fields).values_list(*formatted_sort_fields) + ) - return ordered_list + return ordered_list def test_alphabetically_sorted_fk_fields_domain_application(self): - tested_fields = [ - DomainApplication.authorizing_official.field, - DomainApplication.submitter.field, - DomainApplication.investigator.field, - DomainApplication.creator.field, - DomainApplication.requested_domain.field, - ] + with less_console_noise(): + tested_fields = [ + DomainApplication.authorizing_official.field, + DomainApplication.submitter.field, + DomainApplication.investigator.field, + DomainApplication.creator.field, + DomainApplication.requested_domain.field, + ] - # Creates multiple domain applications - review status does not matter - applications = multiple_unalphabetical_domain_objects("application") + # Creates multiple domain applications - review status does not matter + applications = multiple_unalphabetical_domain_objects("application") - # Create a mock request - request = self.factory.post("/admin/registrar/domainapplication/{}/change/".format(applications[0].pk)) + # Create a mock request + request = self.factory.post("/admin/registrar/domainapplication/{}/change/".format(applications[0].pk)) - model_admin = AuditedAdmin(DomainApplication, self.site) + model_admin = AuditedAdmin(DomainApplication, self.site) - sorted_fields = [] - # Typically we wouldn't want two nested for fields, - # but both fields are of a fixed length. - # For test case purposes, this should be performant. - for field in tested_fields: - isNamefield: bool = field == DomainApplication.requested_domain.field - if isNamefield: - sorted_fields = ["name"] - else: - sorted_fields = ["first_name", "last_name"] - # We want both of these to be lists, as it is richer test wise. - - desired_order = self.order_by_desired_field_helper(model_admin, request, field.name, *sorted_fields) - current_sort_order = list(model_admin.formfield_for_foreignkey(field, request).queryset) - - # Conforms to the same object structure as desired_order - current_sort_order_coerced_type = [] - - # This is necessary as .queryset and get_queryset - # return lists of different types/structures. - # We need to parse this data and coerce them into the same type. - for contact in current_sort_order: - if not isNamefield: - first = contact.first_name - last = contact.last_name + sorted_fields = [] + # Typically we wouldn't want two nested for fields, + # but both fields are of a fixed length. + # For test case purposes, this should be performant. + for field in tested_fields: + isNamefield: bool = field == DomainApplication.requested_domain.field + if isNamefield: + sorted_fields = ["name"] else: + sorted_fields = ["first_name", "last_name"] + # We want both of these to be lists, as it is richer test wise. + + desired_order = self.order_by_desired_field_helper(model_admin, request, field.name, *sorted_fields) + current_sort_order = list(model_admin.formfield_for_foreignkey(field, request).queryset) + + # Conforms to the same object structure as desired_order + current_sort_order_coerced_type = [] + + # This is necessary as .queryset and get_queryset + # return lists of different types/structures. + # We need to parse this data and coerce them into the same type. + for contact in current_sort_order: + if not isNamefield: + first = contact.first_name + last = contact.last_name + else: + first = contact.name + last = None + + name_tuple = self.coerced_fk_field_helper(first, last, field.name, ":") + if name_tuple is not None: + current_sort_order_coerced_type.append(name_tuple) + + self.assertEqual( + desired_order, + current_sort_order_coerced_type, + "{} is not ordered alphabetically".format(field.name), + ) + + def test_alphabetically_sorted_fk_fields_domain_information(self): + with less_console_noise(): + tested_fields = [ + DomainInformation.authorizing_official.field, + DomainInformation.submitter.field, + # DomainInformation.creator.field, + (DomainInformation.domain.field, ["name"]), + (DomainInformation.domain_application.field, ["requested_domain__name"]), + ] + # Creates multiple domain applications - review status does not matter + applications = multiple_unalphabetical_domain_objects("information") + + # Create a mock request + request = self.factory.post("/admin/registrar/domaininformation/{}/change/".format(applications[0].pk)) + + model_admin = AuditedAdmin(DomainInformation, self.site) + + sorted_fields = [] + # Typically we wouldn't want two nested for fields, + # but both fields are of a fixed length. + # For test case purposes, this should be performant. + for field in tested_fields: + isOtherOrderfield: bool = isinstance(field, tuple) + field_obj = None + if isOtherOrderfield: + sorted_fields = field[1] + field_obj = field[0] + else: + sorted_fields = ["first_name", "last_name"] + field_obj = field + # We want both of these to be lists, as it is richer test wise. + desired_order = self.order_by_desired_field_helper(model_admin, request, field_obj.name, *sorted_fields) + current_sort_order = list(model_admin.formfield_for_foreignkey(field_obj, request).queryset) + + # Conforms to the same object structure as desired_order + current_sort_order_coerced_type = [] + + # This is necessary as .queryset and get_queryset + # return lists of different types/structures. + # We need to parse this data and coerce them into the same type. + for obj in current_sort_order: + last = None + if not isOtherOrderfield: + first = obj.first_name + last = obj.last_name + elif field_obj == DomainInformation.domain.field: + first = obj.name + elif field_obj == DomainInformation.domain_application.field: + first = obj.requested_domain.name + + name_tuple = self.coerced_fk_field_helper(first, last, field_obj.name, ":") + if name_tuple is not None: + current_sort_order_coerced_type.append(name_tuple) + + self.assertEqual( + desired_order, + current_sort_order_coerced_type, + "{} is not ordered alphabetically".format(field_obj.name), + ) + + def test_alphabetically_sorted_fk_fields_domain_invitation(self): + with less_console_noise(): + tested_fields = [DomainInvitation.domain.field] + + # Creates multiple domain applications - review status does not matter + applications = multiple_unalphabetical_domain_objects("invitation") + + # Create a mock request + request = self.factory.post("/admin/registrar/domaininvitation/{}/change/".format(applications[0].pk)) + + model_admin = AuditedAdmin(DomainInvitation, self.site) + + sorted_fields = [] + # Typically we wouldn't want two nested for fields, + # but both fields are of a fixed length. + # For test case purposes, this should be performant. + for field in tested_fields: + sorted_fields = ["name"] + # We want both of these to be lists, as it is richer test wise. + + desired_order = self.order_by_desired_field_helper(model_admin, request, field.name, *sorted_fields) + current_sort_order = list(model_admin.formfield_for_foreignkey(field, request).queryset) + + # Conforms to the same object structure as desired_order + current_sort_order_coerced_type = [] + + # This is necessary as .queryset and get_queryset + # return lists of different types/structures. + # We need to parse this data and coerce them into the same type. + for contact in current_sort_order: first = contact.name last = None - name_tuple = self.coerced_fk_field_helper(first, last, field.name, ":") - if name_tuple is not None: - current_sort_order_coerced_type.append(name_tuple) + name_tuple = self.coerced_fk_field_helper(first, last, field.name, ":") + if name_tuple is not None: + current_sort_order_coerced_type.append(name_tuple) - self.assertEqual( - desired_order, - current_sort_order_coerced_type, - "{} is not ordered alphabetically".format(field.name), - ) - - def test_alphabetically_sorted_fk_fields_domain_information(self): - tested_fields = [ - DomainInformation.authorizing_official.field, - DomainInformation.submitter.field, - # DomainInformation.creator.field, - (DomainInformation.domain.field, ["name"]), - (DomainInformation.domain_application.field, ["requested_domain__name"]), - ] - # Creates multiple domain applications - review status does not matter - applications = multiple_unalphabetical_domain_objects("information") - - # Create a mock request - request = self.factory.post("/admin/registrar/domaininformation/{}/change/".format(applications[0].pk)) - - model_admin = AuditedAdmin(DomainInformation, self.site) - - sorted_fields = [] - # Typically we wouldn't want two nested for fields, - # but both fields are of a fixed length. - # For test case purposes, this should be performant. - for field in tested_fields: - isOtherOrderfield: bool = isinstance(field, tuple) - field_obj = None - if isOtherOrderfield: - sorted_fields = field[1] - field_obj = field[0] - else: - sorted_fields = ["first_name", "last_name"] - field_obj = field - # We want both of these to be lists, as it is richer test wise. - desired_order = self.order_by_desired_field_helper(model_admin, request, field_obj.name, *sorted_fields) - current_sort_order = list(model_admin.formfield_for_foreignkey(field_obj, request).queryset) - - # Conforms to the same object structure as desired_order - current_sort_order_coerced_type = [] - - # This is necessary as .queryset and get_queryset - # return lists of different types/structures. - # We need to parse this data and coerce them into the same type. - for obj in current_sort_order: - last = None - if not isOtherOrderfield: - first = obj.first_name - last = obj.last_name - elif field_obj == DomainInformation.domain.field: - first = obj.name - elif field_obj == DomainInformation.domain_application.field: - first = obj.requested_domain.name - - name_tuple = self.coerced_fk_field_helper(first, last, field_obj.name, ":") - if name_tuple is not None: - current_sort_order_coerced_type.append(name_tuple) - - self.assertEqual( - desired_order, - current_sort_order_coerced_type, - "{} is not ordered alphabetically".format(field_obj.name), - ) - - def test_alphabetically_sorted_fk_fields_domain_invitation(self): - tested_fields = [DomainInvitation.domain.field] - - # Creates multiple domain applications - review status does not matter - applications = multiple_unalphabetical_domain_objects("invitation") - - # Create a mock request - request = self.factory.post("/admin/registrar/domaininvitation/{}/change/".format(applications[0].pk)) - - model_admin = AuditedAdmin(DomainInvitation, self.site) - - sorted_fields = [] - # Typically we wouldn't want two nested for fields, - # but both fields are of a fixed length. - # For test case purposes, this should be performant. - for field in tested_fields: - sorted_fields = ["name"] - # We want both of these to be lists, as it is richer test wise. - - desired_order = self.order_by_desired_field_helper(model_admin, request, field.name, *sorted_fields) - current_sort_order = list(model_admin.formfield_for_foreignkey(field, request).queryset) - - # Conforms to the same object structure as desired_order - current_sort_order_coerced_type = [] - - # This is necessary as .queryset and get_queryset - # return lists of different types/structures. - # We need to parse this data and coerce them into the same type. - for contact in current_sort_order: - first = contact.name - last = None - - name_tuple = self.coerced_fk_field_helper(first, last, field.name, ":") - if name_tuple is not None: - current_sort_order_coerced_type.append(name_tuple) - - self.assertEqual( - desired_order, - current_sort_order_coerced_type, - "{} is not ordered alphabetically".format(field.name), - ) + self.assertEqual( + desired_order, + current_sort_order_coerced_type, + "{} is not ordered alphabetically".format(field.name), + ) def coerced_fk_field_helper(self, first_name, last_name, field_name, queryset_shorthand): """Handles edge cases for test cases""" @@ -1585,93 +1620,98 @@ class DomainSessionVariableTest(TestCase): def test_session_vars_set_correctly(self): """Checks if session variables are being set correctly""" - p = "adminpass" - self.client.login(username="superuser", password=p) + with less_console_noise(): + p = "adminpass" + self.client.login(username="superuser", password=p) - dummy_domain_information = generic_domain_object("information", "session") - request = self.get_factory_post_edit_domain(dummy_domain_information.domain.pk) - self.populate_session_values(request, dummy_domain_information.domain) - self.assertEqual(request.session["analyst_action"], "edit") - self.assertEqual( - request.session["analyst_action_location"], - dummy_domain_information.domain.pk, - ) + dummy_domain_information = generic_domain_object("information", "session") + request = self.get_factory_post_edit_domain(dummy_domain_information.domain.pk) + self.populate_session_values(request, dummy_domain_information.domain) + self.assertEqual(request.session["analyst_action"], "edit") + self.assertEqual( + request.session["analyst_action_location"], + dummy_domain_information.domain.pk, + ) def test_session_vars_set_correctly_hardcoded_domain(self): """Checks if session variables are being set correctly""" - p = "adminpass" - self.client.login(username="superuser", password=p) + with less_console_noise(): + p = "adminpass" + self.client.login(username="superuser", password=p) - dummy_domain_information: Domain = generic_domain_object("information", "session") - dummy_domain_information.domain.pk = 1 + dummy_domain_information: Domain = generic_domain_object("information", "session") + dummy_domain_information.domain.pk = 1 - request = self.get_factory_post_edit_domain(dummy_domain_information.domain.pk) - self.populate_session_values(request, dummy_domain_information.domain) - self.assertEqual(request.session["analyst_action"], "edit") - self.assertEqual(request.session["analyst_action_location"], 1) + request = self.get_factory_post_edit_domain(dummy_domain_information.domain.pk) + self.populate_session_values(request, dummy_domain_information.domain) + self.assertEqual(request.session["analyst_action"], "edit") + self.assertEqual(request.session["analyst_action_location"], 1) def test_session_variables_reset_correctly(self): """Checks if incorrect session variables get overridden""" - p = "adminpass" - self.client.login(username="superuser", password=p) + with less_console_noise(): + p = "adminpass" + self.client.login(username="superuser", password=p) - dummy_domain_information = generic_domain_object("information", "session") - request = self.get_factory_post_edit_domain(dummy_domain_information.domain.pk) + dummy_domain_information = generic_domain_object("information", "session") + request = self.get_factory_post_edit_domain(dummy_domain_information.domain.pk) - self.populate_session_values(request, dummy_domain_information.domain, preload_bad_data=True) + self.populate_session_values(request, dummy_domain_information.domain, preload_bad_data=True) - self.assertEqual(request.session["analyst_action"], "edit") - self.assertEqual( - request.session["analyst_action_location"], - dummy_domain_information.domain.pk, - ) + self.assertEqual(request.session["analyst_action"], "edit") + self.assertEqual( + request.session["analyst_action_location"], + dummy_domain_information.domain.pk, + ) def test_session_variables_retain_information(self): """Checks to see if session variables retain old information""" - p = "adminpass" - self.client.login(username="superuser", password=p) + with less_console_noise(): + p = "adminpass" + self.client.login(username="superuser", password=p) - dummy_domain_information_list = multiple_unalphabetical_domain_objects("information") - for item in dummy_domain_information_list: - request = self.get_factory_post_edit_domain(item.domain.pk) - self.populate_session_values(request, item.domain) + dummy_domain_information_list = multiple_unalphabetical_domain_objects("information") + for item in dummy_domain_information_list: + request = self.get_factory_post_edit_domain(item.domain.pk) + self.populate_session_values(request, item.domain) - self.assertEqual(request.session["analyst_action"], "edit") - self.assertEqual(request.session["analyst_action_location"], item.domain.pk) + self.assertEqual(request.session["analyst_action"], "edit") + self.assertEqual(request.session["analyst_action_location"], item.domain.pk) def test_session_variables_concurrent_requests(self): """Simulates two requests at once""" - p = "adminpass" - self.client.login(username="superuser", password=p) + with less_console_noise(): + p = "adminpass" + self.client.login(username="superuser", password=p) - info_first = generic_domain_object("information", "session") - info_second = generic_domain_object("information", "session2") + info_first = generic_domain_object("information", "session") + info_second = generic_domain_object("information", "session2") - request_first = self.get_factory_post_edit_domain(info_first.domain.pk) - request_second = self.get_factory_post_edit_domain(info_second.domain.pk) + request_first = self.get_factory_post_edit_domain(info_first.domain.pk) + request_second = self.get_factory_post_edit_domain(info_second.domain.pk) - self.populate_session_values(request_first, info_first.domain, True) - self.populate_session_values(request_second, info_second.domain, True) + self.populate_session_values(request_first, info_first.domain, True) + self.populate_session_values(request_second, info_second.domain, True) - # Check if anything got nulled out - self.assertNotEqual(request_first.session["analyst_action"], None) - self.assertNotEqual(request_second.session["analyst_action"], None) - self.assertNotEqual(request_first.session["analyst_action_location"], None) - self.assertNotEqual(request_second.session["analyst_action_location"], None) + # Check if anything got nulled out + self.assertNotEqual(request_first.session["analyst_action"], None) + self.assertNotEqual(request_second.session["analyst_action"], None) + self.assertNotEqual(request_first.session["analyst_action_location"], None) + self.assertNotEqual(request_second.session["analyst_action_location"], None) - # Check if they are both the same action 'type' - self.assertEqual(request_first.session["analyst_action"], "edit") - self.assertEqual(request_second.session["analyst_action"], "edit") + # Check if they are both the same action 'type' + self.assertEqual(request_first.session["analyst_action"], "edit") + self.assertEqual(request_second.session["analyst_action"], "edit") - # Check their locations, and ensure they aren't the same across both - self.assertNotEqual( - request_first.session["analyst_action_location"], - request_second.session["analyst_action_location"], - ) + # Check their locations, and ensure they aren't the same across both + self.assertNotEqual( + request_first.session["analyst_action_location"], + request_second.session["analyst_action_location"], + ) def populate_session_values(self, request, domain_object, preload_bad_data=False): """Boilerplate for creating mock sessions""" @@ -1704,63 +1744,65 @@ class ContactAdminTest(TestCase): self.staffuser = create_user() def test_readonly_when_restricted_staffuser(self): - request = self.factory.get("/") - request.user = self.staffuser + with less_console_noise(): + request = self.factory.get("/") + request.user = self.staffuser - readonly_fields = self.admin.get_readonly_fields(request) + readonly_fields = self.admin.get_readonly_fields(request) - expected_fields = [ - "user", - ] + expected_fields = [ + "user", + ] - self.assertEqual(readonly_fields, expected_fields) + self.assertEqual(readonly_fields, expected_fields) def test_readonly_when_restricted_superuser(self): - request = self.factory.get("/") - request.user = self.superuser + with less_console_noise(): + request = self.factory.get("/") + request.user = self.superuser - readonly_fields = self.admin.get_readonly_fields(request) + readonly_fields = self.admin.get_readonly_fields(request) - expected_fields = [] + expected_fields = [] - self.assertEqual(readonly_fields, expected_fields) + self.assertEqual(readonly_fields, expected_fields) def test_change_view_for_joined_contact_five_or_less(self): """Create a contact, join it to 4 domain requests. The 5th join will be a user. Assert that the warning on the contact form lists 5 joins.""" + with less_console_noise(): + self.client.force_login(self.superuser) - self.client.force_login(self.superuser) + # Create an instance of the model + contact, _ = Contact.objects.get_or_create(user=self.staffuser) - # Create an instance of the model - contact, _ = Contact.objects.get_or_create(user=self.staffuser) + # join it to 4 domain requests. The 5th join will be a user. + application1 = completed_application(submitter=contact, name="city1.gov") + application2 = completed_application(submitter=contact, name="city2.gov") + application3 = completed_application(submitter=contact, name="city3.gov") + application4 = completed_application(submitter=contact, name="city4.gov") - # join it to 4 domain requests. The 5th join will be a user. - application1 = completed_application(submitter=contact, name="city1.gov") - application2 = completed_application(submitter=contact, name="city2.gov") - application3 = completed_application(submitter=contact, name="city3.gov") - application4 = completed_application(submitter=contact, name="city4.gov") + with patch("django.contrib.messages.warning") as mock_warning: + # Use the test client to simulate the request + response = self.client.get(reverse("admin:registrar_contact_change", args=[contact.pk])) - with patch("django.contrib.messages.warning") as mock_warning: - # Use the test client to simulate the request - response = self.client.get(reverse("admin:registrar_contact_change", args=[contact.pk])) - - # Assert that the error message was called with the correct argument - # Note: The 5th join will be a user. - mock_warning.assert_called_once_with( - response.wsgi_request, - "", - ) + # Assert that the error message was called with the correct argument + # Note: The 5th join will be a user. + mock_warning.assert_called_once_with( + response.wsgi_request, + "", + ) def test_change_view_for_joined_contact_five_or_more(self): """Create a contact, join it to 5 domain requests. The 6th join will be a user. @@ -1810,20 +1852,21 @@ class VerifiedByStaffAdminTestCase(TestCase): self.factory = RequestFactory() def test_save_model_sets_user_field(self): - self.client.force_login(self.superuser) + with less_console_noise(): + self.client.force_login(self.superuser) - # Create an instance of the admin class - admin_instance = VerifiedByStaffAdmin(model=VerifiedByStaff, admin_site=None) + # Create an instance of the admin class + admin_instance = VerifiedByStaffAdmin(model=VerifiedByStaff, admin_site=None) - # Create a VerifiedByStaff instance - vip_instance = VerifiedByStaff(email="test@example.com", notes="Test Notes") + # Create a VerifiedByStaff instance + vip_instance = VerifiedByStaff(email="test@example.com", notes="Test Notes") - # Create a request object - request = self.factory.post("/admin/yourapp/VerifiedByStaff/add/") - request.user = self.superuser + # Create a request object + request = self.factory.post("/admin/yourapp/VerifiedByStaff/add/") + request.user = self.superuser - # Call the save_model method - admin_instance.save_model(request, vip_instance, None, None) + # Call the save_model method + admin_instance.save_model(request, vip_instance, None, None) - # Check that the user field is set to the request.user - self.assertEqual(vip_instance.requestor, self.superuser) + # Check that the user field is set to the request.user + self.assertEqual(vip_instance.requestor, self.superuser) From a23c095139db5afa60503a4189038cf01a55ea06 Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Fri, 16 Feb 2024 16:09:13 -0500 Subject: [PATCH 05/13] updates to election office --- src/registrar/admin.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/registrar/admin.py b/src/registrar/admin.py index bac361c6a..d5a0f6bde 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -767,10 +767,10 @@ class DomainApplicationAdmin(ListHeaderAdmin): "requested_domain", "status", "organization_type", - "federal_agency", "federal_type", + "federal_agency", "organization_name", - "is_election_board", + "custom_election_board", "city", "state_territory", "created_at", @@ -784,6 +784,12 @@ class DomainApplicationAdmin(ListHeaderAdmin): ("investigator", ["first_name", "last_name"]), ] + def custom_election_board(self, obj): + return obj.is_election_board + + custom_election_board.admin_order_field = "is_election_board" # type: ignore + custom_election_board.short_description = "Election office" # type: ignore + # Filters list_filter = ("status", "organization_type", InvestigatorFilter) @@ -1044,8 +1050,8 @@ class DomainAdmin(ListHeaderAdmin): list_display = [ "name", "organization_type", - "federal_agency", "federal_type", + "federal_agency", "organization_name", "is_election_board", "city", @@ -1089,9 +1095,10 @@ class DomainAdmin(ListHeaderAdmin): organization_name.admin_order_field = "domain_info__organization_name" # type: ignore def is_election_board(self, obj): - return obj.domain_info.is_election_board if obj.domain_info else None + return obj.domain_info.is_election_board if obj.domain_info else False is_election_board.admin_order_field = "domain_info__is_election_board" # type: ignore + is_election_board.short_description = "Election office" # type: ignore def city(self, obj): return obj.domain_info.city if obj.domain_info else None From 9b86a154d0ab79766d94669e0269f90a7ec42b5e Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Thu, 22 Feb 2024 20:46:56 -0500 Subject: [PATCH 06/13] made filters for election office and federal branch, and set the default value for election office to false --- src/registrar/admin.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/registrar/admin.py b/src/registrar/admin.py index d5a0f6bde..4880d174c 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -785,13 +785,13 @@ class DomainApplicationAdmin(ListHeaderAdmin): ] def custom_election_board(self, obj): - return obj.is_election_board + return obj.is_election_board if obj.is_election_board else False custom_election_board.admin_order_field = "is_election_board" # type: ignore custom_election_board.short_description = "Election office" # type: ignore # Filters - list_filter = ("status", "organization_type", InvestigatorFilter) + list_filter = ("status", "organization_type", "is_election_board", "federal_type", InvestigatorFilter) # Search search_fields = [ @@ -1111,7 +1111,7 @@ class DomainAdmin(ListHeaderAdmin): state_territory.admin_order_field = "domain_info__state_territory" # type: ignore # Filters - list_filter = ["domain_info__organization_type", "state"] + list_filter = ["domain_info__organization_type", "state", "domain_info__is_election_board", "domain_info__federal_type"] search_fields = ["name"] search_help_text = "Search by domain name." From 262acee1cd39d916e34248954ce4f143dd488b87 Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Mon, 26 Feb 2024 14:03:06 -0500 Subject: [PATCH 07/13] updated filters and results list header --- src/registrar/admin.py | 55 ++++++++++++++++--- .../templates/admin/change_list.html | 10 +++- src/registrar/tests/test_admin.py | 8 ++- 3 files changed, 63 insertions(+), 10 deletions(-) diff --git a/src/registrar/admin.py b/src/registrar/admin.py index 4880d174c..ddfce2c7a 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -1,5 +1,6 @@ import logging from django import forms +from django.db.models import Q from django.db.models.functions import Concat from django.http import HttpResponse from django.shortcuts import redirect @@ -22,6 +23,7 @@ from auditlog.admin import LogEntryAdmin # type: ignore from django_fsm import TransitionNotAllowed # type: ignore from django.utils.safestring import mark_safe from django.utils.html import escape +from django.utils.translation import gettext_lazy as _ logger = logging.getLogger(__name__) @@ -762,6 +764,24 @@ class DomainApplicationAdmin(ListHeaderAdmin): else: return queryset.filter(investigator__id__exact=self.value()) + class ElectionOfficeFilter(admin.SimpleListFilter): + """Define a custom filter for is_election_board""" + + title = _("election office") + parameter_name = "is_election_board" + + def lookups(self, request, model_admin): + return ( + ("1", _("Yes")), + ("0", _("No")), + ) + + def queryset(self, request, queryset): + if self.value() == "1": + return queryset.filter(is_election_board=True) + if self.value() == "0": + return queryset.filter(Q(is_election_board=False) | Q(is_election_board=None)) + # Columns list_display = [ "requested_domain", @@ -785,13 +805,13 @@ class DomainApplicationAdmin(ListHeaderAdmin): ] def custom_election_board(self, obj): - return obj.is_election_board if obj.is_election_board else False + return "Yes" if obj.is_election_board else "No" custom_election_board.admin_order_field = "is_election_board" # type: ignore custom_election_board.short_description = "Election office" # type: ignore # Filters - list_filter = ("status", "organization_type", "is_election_board", "federal_type", InvestigatorFilter) + list_filter = ("status", "organization_type", "federal_type", ElectionOfficeFilter, InvestigatorFilter) # Search search_fields = [ @@ -1044,6 +1064,25 @@ class DomainInformationInline(admin.StackedInline): class DomainAdmin(ListHeaderAdmin): """Custom domain admin class to add extra buttons.""" + class ElectionOfficeFilter(admin.SimpleListFilter): + """Define a custom filter for is_election_board""" + + title = _("election office") + parameter_name = "is_election_board" + + def lookups(self, request, model_admin): + return ( + ("1", _("Yes")), + ("0", _("No")), + ) + + def queryset(self, request, queryset): + logger.debug(self.value()) + if self.value() == "1": + return queryset.filter(domain_info__is_election_board=True) + if self.value() == "0": + return queryset.filter(Q(domain_info__is_election_board=False) | Q(domain_info__is_election_board=None)) + inlines = [DomainInformationInline] # Columns @@ -1053,7 +1092,7 @@ class DomainAdmin(ListHeaderAdmin): "federal_type", "federal_agency", "organization_name", - "is_election_board", + "custom_election_board", "city", "state_territory", "state", @@ -1094,11 +1133,11 @@ class DomainAdmin(ListHeaderAdmin): organization_name.admin_order_field = "domain_info__organization_name" # type: ignore - def is_election_board(self, obj): - return obj.domain_info.is_election_board if obj.domain_info else False + def custom_election_board(self, obj): + return "Yes" if obj.domain_info.is_election_board else "No" - is_election_board.admin_order_field = "domain_info__is_election_board" # type: ignore - is_election_board.short_description = "Election office" # type: ignore + custom_election_board.admin_order_field = "domain_info__is_election_board" # type: ignore + custom_election_board.short_description = "Election office" # type: ignore def city(self, obj): return obj.domain_info.city if obj.domain_info else None @@ -1111,7 +1150,7 @@ class DomainAdmin(ListHeaderAdmin): state_territory.admin_order_field = "domain_info__state_territory" # type: ignore # Filters - list_filter = ["domain_info__organization_type", "state", "domain_info__is_election_board", "domain_info__federal_type"] + list_filter = ["domain_info__organization_type", "state", "domain_info__federal_type", ElectionOfficeFilter] search_fields = ["name"] search_help_text = "Search by domain name." diff --git a/src/registrar/templates/admin/change_list.html b/src/registrar/templates/admin/change_list.html index 4a58a4b7e..479b7b1ff 100644 --- a/src/registrar/templates/admin/change_list.html +++ b/src/registrar/templates/admin/change_list.html @@ -15,7 +15,15 @@ {% if filters %} filtered by {% for filter_param in filters %} - {{ filter_param.parameter_name }} = {{ filter_param.parameter_value }} + {% if filter_param.parameter_name == 'is_election_board' %} + {%if filter_param.parameter_value == '0' %} + election office = No + {% else %} + election office = Yes + {% endif %} + {% else %} + {{ filter_param.parameter_name }} = {{ filter_param.parameter_value }} + {% endif %} {% if not forloop.last %}, {% endif %} {% endfor %} {% endif %} diff --git a/src/registrar/tests/test_admin.py b/src/registrar/tests/test_admin.py index 1b133a052..9a46c58aa 100644 --- a/src/registrar/tests/test_admin.py +++ b/src/registrar/tests/test_admin.py @@ -847,7 +847,13 @@ class TestDomainApplicationAdmin(MockEppLib): # Grab the current list of table filters readonly_fields = self.admin.get_list_filter(request) - expected_fields = ("status", "organization_type", DomainApplicationAdmin.InvestigatorFilter) + expected_fields = ( + "status", + "organization_type", + "federal_type", + DomainApplicationAdmin.ElectionOfficeFilter, + DomainApplicationAdmin.InvestigatorFilter, + ) self.assertEqual(readonly_fields, expected_fields) From 9f7db1630c7d981da65adc5bc5cbe552afdc53b9 Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Mon, 26 Feb 2024 14:38:29 -0500 Subject: [PATCH 08/13] fixed case where domain_info is None --- src/registrar/admin.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/registrar/admin.py b/src/registrar/admin.py index ddfce2c7a..1e6ff0b21 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -1134,7 +1134,10 @@ class DomainAdmin(ListHeaderAdmin): organization_name.admin_order_field = "domain_info__organization_name" # type: ignore def custom_election_board(self, obj): - return "Yes" if obj.domain_info.is_election_board else "No" + domain_info = getattr(obj, 'domain_info', None) + if domain_info: + return "Yes" if domain_info.is_election_board else "No" + return "No" custom_election_board.admin_order_field = "domain_info__is_election_board" # type: ignore custom_election_board.short_description = "Election office" # type: ignore From 45b8ca358acb6d675bc15cdbb95a6079361d54a8 Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Mon, 26 Feb 2024 15:14:20 -0500 Subject: [PATCH 09/13] updated merge --- src/registrar/admin.py | 1 + src/registrar/tests/test_admin.py | 14 +++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/registrar/admin.py b/src/registrar/admin.py index 151305580..808433100 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -24,6 +24,7 @@ from auditlog.admin import LogEntryAdmin # type: ignore from django_fsm import TransitionNotAllowed # type: ignore from django.utils.safestring import mark_safe from django.utils.html import escape +from django.utils.translation import gettext_lazy as _ logger = logging.getLogger(__name__) diff --git a/src/registrar/tests/test_admin.py b/src/registrar/tests/test_admin.py index c1f357554..17e8c171f 100644 --- a/src/registrar/tests/test_admin.py +++ b/src/registrar/tests/test_admin.py @@ -1186,13 +1186,13 @@ class TestDomainApplicationAdmin(MockEppLib): self.client.login(username="staffuser", password=p) request = RequestFactory().get("/") - # These names have metadata embedded in them. :investigator implicitly tests if - # these are actually from the attribute "investigator". - expected_list = [ - "AGuy AGuy last_name:investigator", - "FinalGuy FinalGuy last_name:investigator", - "SomeGuy first_name:investigator SomeGuy last_name:investigator", - ] + # These names have metadata embedded in them. :investigator implicitly tests if + # these are actually from the attribute "investigator". + expected_list = [ + "AGuy AGuy last_name:investigator", + "FinalGuy FinalGuy last_name:investigator", + "SomeGuy first_name:investigator SomeGuy last_name:investigator", + ] # Get the actual sorted list of investigators from the lookups method actual_list = [item for _, item in self.admin.InvestigatorFilter.lookups(self, request, self.admin)] From ce7304d6ac81bf3c34b7d2ea6e375f25600a972c Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Mon, 26 Feb 2024 15:26:26 -0500 Subject: [PATCH 10/13] fixed linting --- src/registrar/admin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/registrar/admin.py b/src/registrar/admin.py index 808433100..ec07c5f36 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -1225,9 +1225,9 @@ class DomainAdmin(ListHeaderAdmin): organization_name.admin_order_field = "domain_info__organization_name" # type: ignore def custom_election_board(self, obj): - domain_info = getattr(obj, 'domain_info', None) + domain_info = getattr(obj, "domain_info", None) if domain_info: - return "Yes" if domain_info.is_election_board else "No" + return "Yes" if domain_info.is_election_board else "No" return "No" custom_election_board.admin_order_field = "domain_info__is_election_board" # type: ignore From 3e193b05b039985c3fdbecc43cb8dfce3a5f71c8 Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Mon, 26 Feb 2024 18:31:28 -0500 Subject: [PATCH 11/13] moved state to the last filter on domains list in admin --- src/registrar/admin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/registrar/admin.py b/src/registrar/admin.py index ec07c5f36..a6ea1f09f 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -1244,7 +1244,7 @@ class DomainAdmin(ListHeaderAdmin): state_territory.admin_order_field = "domain_info__state_territory" # type: ignore # Filters - list_filter = ["domain_info__organization_type", "state", "domain_info__federal_type", ElectionOfficeFilter] + list_filter = ["domain_info__organization_type", "domain_info__federal_type", ElectionOfficeFilter, "state"] search_fields = ["name"] search_help_text = "Search by domain name." From 06c30c2b73642e659d4cf18389f69cc40686e833 Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Mon, 26 Feb 2024 18:52:34 -0500 Subject: [PATCH 12/13] removed logging noise --- src/registrar/tests/test_models_domain.py | 164 +++++++++++----------- 1 file changed, 84 insertions(+), 80 deletions(-) diff --git a/src/registrar/tests/test_models_domain.py b/src/registrar/tests/test_models_domain.py index 647d0ff47..3caa1f632 100644 --- a/src/registrar/tests/test_models_domain.py +++ b/src/registrar/tests/test_models_domain.py @@ -321,21 +321,21 @@ class TestDomainCreation(MockEppLib): Then a Domain exists in the database with the same `name` But a domain object does not exist in the registry """ - draft_domain, _ = DraftDomain.objects.get_or_create(name="igorville.gov") - user, _ = User.objects.get_or_create() - application = DomainApplication.objects.create(creator=user, requested_domain=draft_domain) + with less_console_noise(): + draft_domain, _ = DraftDomain.objects.get_or_create(name="igorville.gov") + user, _ = User.objects.get_or_create() + application = DomainApplication.objects.create(creator=user, requested_domain=draft_domain) - mock_client = MockSESClient() - with boto3_mocking.clients.handler_for("sesv2", mock_client): - with less_console_noise(): + mock_client = MockSESClient() + with boto3_mocking.clients.handler_for("sesv2", mock_client): # skip using the submit method application.status = DomainApplication.ApplicationStatus.SUBMITTED # transition to approve state application.approve() - # should have information present for this domain - domain = Domain.objects.get(name="igorville.gov") - self.assertTrue(domain) - self.mockedSendFunction.assert_not_called() + # should have information present for this domain + domain = Domain.objects.get(name="igorville.gov") + self.assertTrue(domain) + self.mockedSendFunction.assert_not_called() def test_accessing_domain_properties_creates_domain_in_registry(self): """ @@ -346,33 +346,34 @@ class TestDomainCreation(MockEppLib): And `domain.state` is set to `UNKNOWN` And `domain.is_active()` returns False """ - domain = Domain.objects.create(name="beef-tongue.gov") - # trigger getter - _ = domain.statuses + with less_console_noise(): + domain = Domain.objects.create(name="beef-tongue.gov") + # trigger getter + _ = domain.statuses - # contacts = PublicContact.objects.filter(domain=domain, - # type=PublicContact.ContactTypeChoices.REGISTRANT).get() + # contacts = PublicContact.objects.filter(domain=domain, + # type=PublicContact.ContactTypeChoices.REGISTRANT).get() - # Called in _fetch_cache - self.mockedSendFunction.assert_has_calls( - [ - # TODO: due to complexity of the test, will return to it in - # a future ticket - # call( - # commands.CreateDomain(name="beef-tongue.gov", - # id=contact.registry_id, auth_info=None), - # cleaned=True, - # ), - call( - commands.InfoDomain(name="beef-tongue.gov", auth_info=None), - cleaned=True, - ), - ], - any_order=False, # Ensure calls are in the specified order - ) + # Called in _fetch_cache + self.mockedSendFunction.assert_has_calls( + [ + # TODO: due to complexity of the test, will return to it in + # a future ticket + # call( + # commands.CreateDomain(name="beef-tongue.gov", + # id=contact.registry_id, auth_info=None), + # cleaned=True, + # ), + call( + commands.InfoDomain(name="beef-tongue.gov", auth_info=None), + cleaned=True, + ), + ], + any_order=False, # Ensure calls are in the specified order + ) - self.assertEqual(domain.state, Domain.State.UNKNOWN) - self.assertEqual(domain.is_active(), False) + self.assertEqual(domain.state, Domain.State.UNKNOWN) + self.assertEqual(domain.is_active(), False) @skip("assertion broken with mock addition") def test_empty_domain_creation(self): @@ -382,7 +383,8 @@ class TestDomainCreation(MockEppLib): def test_minimal_creation(self): """Can create with just a name.""" - Domain.objects.create(name="igorville.gov") + with less_console_noise(): + Domain.objects.create(name="igorville.gov") @skip("assertion broken with mock addition") def test_duplicate_creation(self): @@ -503,24 +505,24 @@ class TestDomainAvailable(MockEppLib): return MagicMock( res_data=[responses.check.CheckDomainResultData(name="available.gov", avail=True, reason=None)], ) + with less_console_noise(): + patcher = patch("registrar.models.domain.registry.send") + mocked_send = patcher.start() + mocked_send.side_effect = side_effect - patcher = patch("registrar.models.domain.registry.send") - mocked_send = patcher.start() - mocked_send.side_effect = side_effect - - available = Domain.available("available.gov") - mocked_send.assert_has_calls( - [ - call( - commands.CheckDomain( - ["available.gov"], - ), - cleaned=True, - ) - ] - ) - self.assertTrue(available) - patcher.stop() + available = Domain.available("available.gov") + mocked_send.assert_has_calls( + [ + call( + commands.CheckDomain( + ["available.gov"], + ), + cleaned=True, + ) + ] + ) + self.assertTrue(available) + patcher.stop() def test_domain_unavailable(self): """ @@ -536,24 +538,24 @@ class TestDomainAvailable(MockEppLib): return MagicMock( res_data=[responses.check.CheckDomainResultData(name="unavailable.gov", avail=False, reason="In Use")], ) + with less_console_noise(): + patcher = patch("registrar.models.domain.registry.send") + mocked_send = patcher.start() + mocked_send.side_effect = side_effect - patcher = patch("registrar.models.domain.registry.send") - mocked_send = patcher.start() - mocked_send.side_effect = side_effect - - available = Domain.available("unavailable.gov") - mocked_send.assert_has_calls( - [ - call( - commands.CheckDomain( - ["unavailable.gov"], - ), - cleaned=True, - ) - ] - ) - self.assertFalse(available) - patcher.stop() + available = Domain.available("unavailable.gov") + mocked_send.assert_has_calls( + [ + call( + commands.CheckDomain( + ["unavailable.gov"], + ), + cleaned=True, + ) + ] + ) + self.assertFalse(available) + patcher.stop() def test_domain_available_with_invalid_error(self): """ @@ -562,8 +564,9 @@ class TestDomainAvailable(MockEppLib): Validate InvalidDomainError is raised """ - with self.assertRaises(errors.InvalidDomainError): - Domain.available("invalid-string") + with less_console_noise(): + with self.assertRaises(errors.InvalidDomainError): + Domain.available("invalid-string") def test_domain_available_with_empty_string(self): """ @@ -572,8 +575,9 @@ class TestDomainAvailable(MockEppLib): Validate InvalidDomainError is raised """ - with self.assertRaises(errors.InvalidDomainError): - Domain.available("") + with less_console_noise(): + with self.assertRaises(errors.InvalidDomainError): + Domain.available("") def test_domain_available_unsuccessful(self): """ @@ -584,14 +588,14 @@ class TestDomainAvailable(MockEppLib): def side_effect(_request, cleaned): raise RegistryError(code=ErrorCode.COMMAND_SYNTAX_ERROR) + with less_console_noise(): + patcher = patch("registrar.models.domain.registry.send") + mocked_send = patcher.start() + mocked_send.side_effect = side_effect - patcher = patch("registrar.models.domain.registry.send") - mocked_send = patcher.start() - mocked_send.side_effect = side_effect - - with self.assertRaises(RegistryError): - Domain.available("raises-error.gov") - patcher.stop() + with self.assertRaises(RegistryError): + Domain.available("raises-error.gov") + patcher.stop() class TestRegistrantContacts(MockEppLib): From bd71317da32852d12072aefd005fd6a358f1da7e Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Mon, 26 Feb 2024 19:32:35 -0500 Subject: [PATCH 13/13] lint and fixing merge problems --- src/registrar/admin.py | 9 ++- src/registrar/tests/test_admin.py | 81 ----------------------- src/registrar/tests/test_models_domain.py | 3 + 3 files changed, 11 insertions(+), 82 deletions(-) diff --git a/src/registrar/admin.py b/src/registrar/admin.py index ed0a671c7..86234431d 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -902,7 +902,14 @@ class DomainApplicationAdmin(ListHeaderAdmin): custom_election_board.short_description = "Election office" # type: ignore # Filters - list_filter = ("status", "organization_type", "federal_type", ElectionOfficeFilter, "rejection_reason", InvestigatorFilter) + list_filter = ( + "status", + "organization_type", + "federal_type", + ElectionOfficeFilter, + "rejection_reason", + InvestigatorFilter, + ) # Search search_fields = [ diff --git a/src/registrar/tests/test_admin.py b/src/registrar/tests/test_admin.py index d97631ab8..d76f12f35 100644 --- a/src/registrar/tests/test_admin.py +++ b/src/registrar/tests/test_admin.py @@ -1223,87 +1223,6 @@ class TestDomainApplicationAdmin(MockEppLib): # Assert that the status has not changed self.assertEqual(application.status, DomainApplication.ApplicationStatus.IN_REVIEW) - def test_change_view_with_restricted_creator(self): - with less_console_noise(): - # Create an instance of the model - application = completed_application(status=DomainApplication.ApplicationStatus.IN_REVIEW) - with boto3_mocking.clients.handler_for("sesv2", self.mock_client): - application.creator.status = User.RESTRICTED - application.creator.save() - - with patch("django.contrib.messages.warning") as mock_warning: - # Create a request object with a superuser - request = self.factory.get("/admin/your_app/domainapplication/{}/change/".format(application.pk)) - request.user = self.superuser - - self.admin.display_restricted_warning(request, application) - - # Assert that the error message was called with the correct argument - mock_warning.assert_called_once_with( - request, - "Cannot edit an application with a restricted creator.", - ) - - self.assertEqual(readonly_fields, expected_fields) - - def test_readonly_fields_for_analyst(self): - with less_console_noise(): - request = self.factory.get("/") # Use the correct method and path - request.user = self.staffuser - - readonly_fields = self.admin.get_readonly_fields(request) - - expected_fields = [ - "creator", - "about_your_organization", - "requested_domain", - "approved_domain", - "alternative_domains", - "purpose", - "submitter", - "no_other_contacts_rationale", - "anything_else", - "is_policy_acknowledged", - ] - - self.assertEqual(readonly_fields, expected_fields) - - def test_readonly_fields_for_superuser(self): - with less_console_noise(): - request = self.factory.get("/") # Use the correct method and path - request.user = self.superuser - - readonly_fields = self.admin.get_readonly_fields(request) - - expected_fields = [] - - self.assertEqual(readonly_fields, expected_fields) - - def test_saving_when_restricted_creator(self): - with less_console_noise(): - # Create an instance of the model - application = completed_application(status=DomainApplication.ApplicationStatus.IN_REVIEW) - with boto3_mocking.clients.handler_for("sesv2", self.mock_client): - application.creator.status = User.RESTRICTED - application.creator.save() - - # Create a request object with a superuser - request = self.factory.get("/") - request.user = self.superuser - - with patch("django.contrib.messages.error") as mock_error: - # Simulate saving the model - self.admin.save_model(request, application, None, False) - - # Assert that the error message was called with the correct argument - mock_error.assert_called_once_with( - request, - "This action is not permitted for applications with a restricted creator.", - ) - - # Assert that the status has not changed - self.assertEqual(application.status, DomainApplication.ApplicationStatus.IN_REVIEW) - def test_change_view_with_restricted_creator(self): with less_console_noise(): # Create an instance of the model diff --git a/src/registrar/tests/test_models_domain.py b/src/registrar/tests/test_models_domain.py index 3caa1f632..d99eaa25c 100644 --- a/src/registrar/tests/test_models_domain.py +++ b/src/registrar/tests/test_models_domain.py @@ -505,6 +505,7 @@ class TestDomainAvailable(MockEppLib): return MagicMock( res_data=[responses.check.CheckDomainResultData(name="available.gov", avail=True, reason=None)], ) + with less_console_noise(): patcher = patch("registrar.models.domain.registry.send") mocked_send = patcher.start() @@ -538,6 +539,7 @@ class TestDomainAvailable(MockEppLib): return MagicMock( res_data=[responses.check.CheckDomainResultData(name="unavailable.gov", avail=False, reason="In Use")], ) + with less_console_noise(): patcher = patch("registrar.models.domain.registry.send") mocked_send = patcher.start() @@ -588,6 +590,7 @@ class TestDomainAvailable(MockEppLib): def side_effect(_request, cleaned): raise RegistryError(code=ErrorCode.COMMAND_SYNTAX_ERROR) + with less_console_noise(): patcher = patch("registrar.models.domain.registry.send") mocked_send = patcher.start()