diff --git a/src/registrar/tests/common.py b/src/registrar/tests/common.py index a8ee22a03..def9793f3 100644 --- a/src/registrar/tests/common.py +++ b/src/registrar/tests/common.py @@ -191,7 +191,7 @@ def completed_application( return application -def multiple_completed_applications(has_other_contacts=True, +def multiple_completed_applications_for_alphabetical_test(has_other_contacts=True, has_current_website=True, has_alternative_gov_domain=True, has_type_of_work=True, @@ -202,11 +202,14 @@ def multiple_completed_applications(has_other_contacts=True, list_of_letters = list(ascii_uppercase) random.shuffle(list_of_letters) for x in list_of_letters: - if not user: - user = get_user_model().objects.create(username="username{}".format(x)) + user = get_user_model().objects.create( + first_name="{} First:cre".format(x), + last_name="{} Last:cre".format(x), + username="{} username:cre".format(x) + ) ao, _ = Contact.objects.get_or_create( - first_name="{} Testy".format(x), - last_name="{} Tester".format(x), + first_name="{} First:ao".format(x), + last_name="{} Last:ao".format(x), title="{} Chief Tester".format(x), email="testy@town.com", phone="(555) 555 5555", @@ -215,19 +218,24 @@ def multiple_completed_applications(has_other_contacts=True, alt, _ = Website.objects.get_or_create(website="cityalt{}.gov".format(x)) current, _ = Website.objects.get_or_create(website="city{}.com".format(x)) you, _ = Contact.objects.get_or_create( - first_name="{} Testy you".format(x), - last_name="{} Tester you".format(x), + first_name="{} First:you".format(x), + last_name="{} Last:you".format(x), title="{} Admin Tester".format(x), email="mayor@igorville.gov", phone="(555) 555 5556", ) other, _ = Contact.objects.get_or_create( - first_name="{} Testy".format(x), - last_name="{} Tester".format(x), + first_name="{} First:other".format(x), + last_name="{} Last:other".format(x), title="{} Another Tester".format(x), email="{}testy2@town.com".format(x), phone="(555) 555 5557", ) + inv, _ = User.objects.get_or_create( + first_name="{} First:inv".format(x), + last_name="{} Last:inv".format(x), + username="{} username:inv".format(x) + ) domain_application_kwargs = dict( organization_type="federal", federal_type="executive", @@ -243,6 +251,7 @@ def multiple_completed_applications(has_other_contacts=True, submitter=you, creator=user, status=status, + investigator=inv ) if has_type_of_work: domain_application_kwargs["type_of_work"] = "e-Government" @@ -260,5 +269,4 @@ def multiple_completed_applications(has_other_contacts=True, if has_alternative_gov_domain: application.alternative_domains.add(alt) applications.append(application) - return applications \ No newline at end of file diff --git a/src/registrar/tests/test_admin.py b/src/registrar/tests/test_admin.py index f9ab53863..f971ed6c0 100644 --- a/src/registrar/tests/test_admin.py +++ b/src/registrar/tests/test_admin.py @@ -3,7 +3,7 @@ from django.contrib.admin.sites import AdminSite from registrar.admin import DomainApplicationAdmin, ListHeaderAdmin, MyUserAdmin, AuditedAdmin from registrar.models import DomainApplication, DomainInformation, User from registrar.models.contact import Contact -from .common import completed_application, mock_user, create_superuser, create_user, multiple_completed_applications +from .common import completed_application, mock_user, create_superuser, create_user, multiple_completed_applications_for_alphabetical_test from django.contrib.auth import get_user_model from django.conf import settings @@ -375,33 +375,67 @@ class AuditedAdminTest(TestCase): self.site = AdminSite() self.factory = RequestFactory() self.client = Client(HTTP_HOST="localhost:8080") - self.superuser = create_superuser() - self.factory.post - def test_alphabetically_sorted_fk_fields(self): - mock_client = MagicMock() - - #tested_fields = [{"name": "submitter"}, {"name": "authorizing_official"}, {"name": "investigator"}, {"name": "creator"}, {"name": "user"}] + def test_alphabetically_sorted_fk_fields_domain_application(self): tested_fields = [DomainApplication.authorizing_official.field, DomainApplication.submitter.field, DomainApplication.investigator.field, DomainApplication.creator.field] - with boto3_mocking.clients.handler_for("sesv2", mock_client): - # Create a sample application - review status does not matter - applications = multiple_completed_applications(status=DomainApplication.IN_REVIEW) - # Create a mock request - request = self.factory.post( - "/admin/registrar/domainapplication/{}/change/".format(applications[0].pk) - ) - - model_admin = AuditedAdmin(DomainApplication, self.site) - - for field in tested_fields: - desired_order = model_admin.get_queryset(request).order_by("{}__first_name".format(field.name)) - current_sort_order = model_admin.formfield_for_foreignkey(field, request).queryset - self.assertEqual(desired_order, current_sort_order, "{} is not ordered alphabetically".format(field.name)) - + # Create a sample application - review status does not matter + applications = multiple_completed_applications_for_alphabetical_test(status=DomainApplication.IN_REVIEW) + # Create a mock request + request = self.factory.post( + "/admin/registrar/domainapplication/{}/change/".format(applications[0].pk) + ) + + model_admin = AuditedAdmin(DomainApplication, self.site) + + # Typically we wouldnt 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: + first_name_field = "{}__first_name".format(field.name) + last_name_field = "{}__last_name".format(field.name) + + desired_order = list(model_admin.get_queryset(request).order_by( + first_name_field, last_name_field).values_list(first_name_field, last_name_field)) + logger.debug(desired_order) + current_sort_order: Contact = list(model_admin.formfield_for_foreignkey(field, request).queryset) + 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_name = contact.first_name + last_name = contact.last_name + + match field.name: + case DomainApplication.authorizing_official.field.name: + name_tuple = self.coerced_fk_field_helper(first_name, last_name, 'ao', ':') + if name_tuple: + current_sort_order_coerced_type.append((first_name, last_name)) + case DomainApplication.submitter.field.name: + name_tuple = self.coerced_fk_field_helper(first_name, last_name, 'you', ':') + if name_tuple: + current_sort_order_coerced_type.append((first_name, last_name)) + case DomainApplication.investigator.field.name: + name_tuple = self.coerced_fk_field_helper(first_name, last_name, 'inv', ':') + if name_tuple: + current_sort_order_coerced_type.append((first_name, last_name)) + case DomainApplication.creator.field.name: + name_tuple = self.coerced_fk_field_helper(first_name, last_name, 'cre', ':') + if name_tuple: + current_sort_order_coerced_type.append((first_name, last_name)) + logger.debug("current: {}".format(current_sort_order_coerced_type)) + + self.assertEqual(desired_order, current_sort_order_coerced_type, "{} is not ordered alphabetically".format(field.name)) + + # I originally spent some time trying to fully generalize this to replace the match/arg fields, + # but I think for this specific use-case its not necessary since it'll only be used here + def coerced_fk_field_helper(self, first_name, last_name, field_name, queryset_shorthand): + if(first_name and first_name.split(queryset_shorthand)[1] == field_name): + return (first_name, last_name) + else: + return None + def tearDown(self): DomainInformation.objects.all().delete() DomainApplication.objects.all().delete() - User.objects.all().delete() - self.superuser.delete()