Test skeleton

Not done, still needs to be fixed up. Getting some initial data in place
This commit is contained in:
zandercymatics 2024-11-19 09:54:52 -07:00
parent a2365831ca
commit c98a96e990
No known key found for this signature in database
GPG key ID: FF4636ABEC9682B7
3 changed files with 148 additions and 30 deletions

View file

@ -3,6 +3,7 @@ import logging
from contextlib import contextmanager from contextlib import contextmanager
import random import random
import boto3_mocking # type: ignore
from string import ascii_uppercase from string import ascii_uppercase
import uuid import uuid
from django.test import TestCase from django.test import TestCase
@ -29,6 +30,7 @@ from registrar.models import (
FederalAgency, FederalAgency,
UserPortfolioPermission, UserPortfolioPermission,
Portfolio, Portfolio,
PortfolioInvitation,
) )
from epplibwrapper import ( from epplibwrapper import (
commands, commands,
@ -39,6 +41,7 @@ from epplibwrapper import (
ErrorCode, ErrorCode,
responses, responses,
) )
from registrar.models.utility.portfolio_helper import UserPortfolioPermissionChoices, UserPortfolioRoleChoices
from registrar.models.user_domain_role import UserDomainRole from registrar.models.user_domain_role import UserDomainRole
from registrar.models.utility.contact_error import ContactError, ContactErrorCodes from registrar.models.utility.contact_error import ContactError, ContactErrorCodes
@ -196,6 +199,7 @@ class GenericTestHelper(TestCase):
self.assertEqual(expected_sort_order, returned_sort_order) self.assertEqual(expected_sort_order, returned_sort_order)
@classmethod
def _mock_user_request_for_factory(self, request): def _mock_user_request_for_factory(self, request):
"""Adds sessionmiddleware when using factory to associate session information""" """Adds sessionmiddleware when using factory to associate session information"""
middleware = SessionMiddleware(lambda req: req) middleware = SessionMiddleware(lambda req: req)
@ -529,8 +533,11 @@ class AuditedAdminMockData:
class MockDb(TestCase): class MockDb(TestCase):
@classmethod @classmethod
@boto3_mocking.patching
@less_console_noise_decorator @less_console_noise_decorator
def sharedSetUp(cls): def sharedSetUp(cls):
cls.mock_client_class = MagicMock()
cls.mock_client = cls.mock_client_class.return_value
username = "test_user" username = "test_user"
first_name = "First" first_name = "First"
last_name = "Last" last_name = "Last"
@ -540,6 +547,27 @@ class MockDb(TestCase):
cls.user = get_user_model().objects.create( cls.user = get_user_model().objects.create(
username=username, first_name=first_name, last_name=last_name, email=email, title=title, phone=phone username=username, first_name=first_name, last_name=last_name, email=email, title=title, phone=phone
) )
cls.meoward_user = get_user_model().objects.create(
username="meoward_username", first_name="first_meoward", last_name="last_meoward", email="meoward@rocks.com"
)
cls.lebowski_user = get_user_model().objects.create(
username="big_lebowski", first_name="big", last_name="lebowski", email="big_lebowski@dude.co"
)
cls.tired_user = get_user_model().objects.create(
username="ministry_of_bedtime", first_name="tired", last_name="sleepy", email="tired_sleepy@igorville.gov"
)
# Custom superuser and staff so that these do not conflict with what may be defined on what implements this.
cls.custom_superuser = create_superuser(
username="cold_superuser", first_name="cold", last_name="icy", email="icy_superuser@igorville.gov"
)
cls.custom_staffuser = create_user(
username="warm_staff", first_name="warm", last_name="cozy", email="cozy_staffuser@igorville.gov"
)
cls.federal_agency_1, _ = FederalAgency.objects.get_or_create(agency="World War I Centennial Commission")
cls.federal_agency_2, _ = FederalAgency.objects.get_or_create(agency="Armed Forces Retirement Home")
cls.portfolio_1, _ = Portfolio.objects.get_or_create(creator=cls.custom_superuser, federal_agency=cls.federal_agency_1)
current_date = get_time_aware_date(datetime(2024, 4, 2)) current_date = get_time_aware_date(datetime(2024, 4, 2))
# Create start and end dates using timedelta # Create start and end dates using timedelta
@ -547,9 +575,6 @@ class MockDb(TestCase):
cls.end_date = current_date + timedelta(days=2) cls.end_date = current_date + timedelta(days=2)
cls.start_date = current_date - timedelta(days=2) cls.start_date = current_date - timedelta(days=2)
cls.federal_agency_1, _ = FederalAgency.objects.get_or_create(agency="World War I Centennial Commission")
cls.federal_agency_2, _ = FederalAgency.objects.get_or_create(agency="Armed Forces Retirement Home")
cls.domain_1, _ = Domain.objects.get_or_create( cls.domain_1, _ = Domain.objects.get_or_create(
name="cdomain1.gov", state=Domain.State.READY, first_ready=get_time_aware_date(datetime(2024, 4, 2)) name="cdomain1.gov", state=Domain.State.READY, first_ready=get_time_aware_date(datetime(2024, 4, 2))
) )
@ -596,9 +621,11 @@ class MockDb(TestCase):
federal_agency=cls.federal_agency_1, federal_agency=cls.federal_agency_1,
federal_type="executive", federal_type="executive",
is_election_board=False, is_election_board=False,
portfolio=cls.portfolio_1,
) )
cls.domain_information_2, _ = DomainInformation.objects.get_or_create( cls.domain_information_2, _ = DomainInformation.objects.get_or_create(
creator=cls.user, domain=cls.domain_2, generic_org_type="interstate", is_election_board=True creator=cls.user, domain=cls.domain_2, generic_org_type="interstate", is_election_board=True,
portfolio=cls.portfolio_1,
) )
cls.domain_information_3, _ = DomainInformation.objects.get_or_create( cls.domain_information_3, _ = DomainInformation.objects.get_or_create(
creator=cls.user, creator=cls.user,
@ -671,14 +698,6 @@ class MockDb(TestCase):
is_election_board=False, is_election_board=False,
) )
cls.meoward_user = get_user_model().objects.create(
username="meoward_username", first_name="first_meoward", last_name="last_meoward", email="meoward@rocks.com"
)
cls.lebowski_user = get_user_model().objects.create(
username="big_lebowski", first_name="big", last_name="lebowski", email="big_lebowski@dude.co"
)
_, created = UserDomainRole.objects.get_or_create( _, created = UserDomainRole.objects.get_or_create(
user=cls.meoward_user, domain=cls.domain_1, role=UserDomainRole.Roles.MANAGER user=cls.meoward_user, domain=cls.domain_1, role=UserDomainRole.Roles.MANAGER
) )
@ -723,6 +742,49 @@ class MockDb(TestCase):
email="squeaker@rocks.com", domain=cls.domain_10, status=DomainInvitation.DomainInvitationStatus.INVITED email="squeaker@rocks.com", domain=cls.domain_10, status=DomainInvitation.DomainInvitationStatus.INVITED
) )
# Add portfolio invitations + retrieve
with boto3_mocking.clients.handler_for("sesv2", cls.mock_client_class):
portfolio_invitation_1, _ = PortfolioInvitation.objects.get_or_create(
email=cls.meoward_user.email,
portfolio=cls.portfolio_1,
roles=[UserPortfolioRoleChoices.ORGANIZATION_MEMBER],
additional_permissions=[UserPortfolioPermissionChoices.EDIT_MEMBERS]
)
portfolio_invitation_2, _ = PortfolioInvitation.objects.get_or_create(
email=cls.lebowski_user.email, portfolio=cls.portfolio_1,
roles=[UserPortfolioRoleChoices.ORGANIZATION_MEMBER],
additional_permissions=[UserPortfolioPermissionChoices.VIEW_MEMBERS]
)
portfolio_invitation_3, _ = PortfolioInvitation.objects.get_or_create(
email=cls.tired_user.email, portfolio=cls.portfolio_1,
roles=[UserPortfolioRoleChoices.ORGANIZATION_MEMBER],
additional_permissions=[UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS]
)
portfolio_invitation_4, _ = PortfolioInvitation.objects.get_or_create(
email=cls.custom_superuser.email, portfolio=cls.portfolio_1,
roles=[UserPortfolioRoleChoices.ORGANIZATION_ADMIN],
additional_permissions=[
UserPortfolioPermissionChoices.VIEW_MEMBERS,
UserPortfolioPermissionChoices.EDIT_MEMBERS,
UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS,
UserPortfolioPermissionChoices.EDIT_REQUESTS
]
)
portfolio_invitation_5, _ = PortfolioInvitation.objects.get_or_create(
email=cls.custom_staffuser.email, portfolio=cls.portfolio_1,
roles=[UserPortfolioRoleChoices.ORGANIZATION_ADMIN]
)
portfolio_invitation_1.retrieve()
portfolio_invitation_2.retrieve()
portfolio_invitation_3.retrieve()
portfolio_invitation_4.retrieve()
portfolio_invitation_5.retrieve()
with less_console_noise(): with less_console_noise():
cls.domain_request_1 = completed_domain_request( cls.domain_request_1 = completed_domain_request(
status=DomainRequest.DomainRequestStatus.STARTED, status=DomainRequest.DomainRequestStatus.STARTED,
@ -731,10 +793,12 @@ class MockDb(TestCase):
cls.domain_request_2 = completed_domain_request( cls.domain_request_2 = completed_domain_request(
status=DomainRequest.DomainRequestStatus.IN_REVIEW, status=DomainRequest.DomainRequestStatus.IN_REVIEW,
name="city2.gov", name="city2.gov",
portfolio=cls.portfolio_1,
) )
cls.domain_request_3 = completed_domain_request( cls.domain_request_3 = completed_domain_request(
status=DomainRequest.DomainRequestStatus.STARTED, status=DomainRequest.DomainRequestStatus.STARTED,
name="city3.gov", name="city3.gov",
portfolio=cls.portfolio_1,
) )
cls.domain_request_4 = completed_domain_request( cls.domain_request_4 = completed_domain_request(
status=DomainRequest.DomainRequestStatus.STARTED, status=DomainRequest.DomainRequestStatus.STARTED,
@ -749,6 +813,7 @@ class MockDb(TestCase):
cls.domain_request_6 = completed_domain_request( cls.domain_request_6 = completed_domain_request(
status=DomainRequest.DomainRequestStatus.STARTED, status=DomainRequest.DomainRequestStatus.STARTED,
name="city6.gov", name="city6.gov",
portfolio=cls.portfolio_1,
) )
cls.domain_request_3.submit() cls.domain_request_3.submit()
cls.domain_request_4.submit() cls.domain_request_4.submit()
@ -797,6 +862,7 @@ class MockDb(TestCase):
UserPortfolioPermission.objects.all().delete() UserPortfolioPermission.objects.all().delete()
User.objects.all().delete() User.objects.all().delete()
DomainInvitation.objects.all().delete() DomainInvitation.objects.all().delete()
PortfolioInvitation.objects.all().delete()
cls.federal_agency_1.delete() cls.federal_agency_1.delete()
cls.federal_agency_2.delete() cls.federal_agency_2.delete()
@ -837,17 +903,18 @@ def mock_user():
return mock_user return mock_user
def create_superuser(): def create_superuser(**kwargs):
"""Creates a analyst user with is_staff=True and the group full_access_group"""
User = get_user_model() User = get_user_model()
p = "adminpass" p = "adminpass"
user = User.objects.create_user( user = User.objects.create_user(
username="superuser", username=kwargs.get("username", "superuser"),
email="admin@example.com", email=kwargs.get("email", "admin@example.com"),
first_name="first", first_name=kwargs.get("first_name", "first"),
last_name="last", last_name=kwargs.get("last_name", "last"),
is_staff=True, is_staff=kwargs.get("is_staff", True),
password=p, password=kwargs.get("password", p),
phone="8003111234", phone=kwargs.get("phone", "8003111234"),
) )
# Retrieve the group or create it if it doesn't exist # Retrieve the group or create it if it doesn't exist
group, _ = UserGroup.objects.get_or_create(name="full_access_group") group, _ = UserGroup.objects.get_or_create(name="full_access_group")
@ -856,18 +923,19 @@ def create_superuser():
return user return user
def create_user(): def create_user(**kwargs):
"""Creates a analyst user with is_staff=True and the group cisa_analysts_group"""
User = get_user_model() User = get_user_model()
p = "userpass" p = "userpass"
user = User.objects.create_user( user = User.objects.create_user(
username="staffuser", username=kwargs.get("username", "staffuser"),
email="staff@example.com", email=kwargs.get("email", "staff@example.com"),
first_name="first", first_name=kwargs.get("first_name", "first"),
last_name="last", last_name=kwargs.get("last_name", "last"),
is_staff=True, is_staff=kwargs.get("is_staff", True),
title="title", title=kwargs.get("title", "title"),
password=p, password=kwargs.get("password", p),
phone="8003111234", phone=kwargs.get("phone", "8003111234"),
) )
# Retrieve the group or create it if it doesn't exist # Retrieve the group or create it if it doesn't exist
group, _ = UserGroup.objects.get_or_create(name="cisa_analysts_group") group, _ = UserGroup.objects.get_or_create(name="cisa_analysts_group")

View file

@ -22,6 +22,7 @@ from registrar.utility.csv_export import (
DomainRequestExport, DomainRequestExport,
DomainRequestGrowth, DomainRequestGrowth,
DomainRequestDataFull, DomainRequestDataFull,
MemberExport,
get_default_start_date, get_default_start_date,
get_default_end_date, get_default_end_date,
) )
@ -42,7 +43,9 @@ from .common import (
get_wsgi_request_object, get_wsgi_request_object,
less_console_noise, less_console_noise,
get_time_aware_date, get_time_aware_date,
GenericTestHelper,
) )
from .common import GenericTestHelper
from waffle.testutils import override_flag from waffle.testutils import override_flag
@ -794,6 +797,53 @@ class ExportDataTest(MockDbForIndividualTests, MockEppLib):
self.assertEqual(csv_content, expected_content) self.assertEqual(csv_content, expected_content)
class MemberExportTest(MockDbForIndividualTests, MockEppLib):
def setUp(self):
super().setUp()
self.factory = RequestFactory()
@override_flag("organization_feature", active=True)
@override_flag("organization_members", active=True)
@less_console_noise_decorator
def test_member_export(self):
"""Tests the member export report"""
# Create a request and add the user to the request
request = self.factory.get("/")
request.user = self.user
# Add portfolio to session
request = GenericTestHelper._mock_user_request_for_factory(request)
request.session["portfolio"] = self.portfolio_1
# Create a CSV file in memory
csv_file = StringIO()
# Call the export function
MemberExport.export_data_to_csv(csv_file, request=request)
# Reset the CSV file's position to the beginning
csv_file.seek(0)
# Read the content into a variable
csv_content = csv_file.read()
print("what is the csv content?")
print(csv_content)
expected_content = (
# Header
"Email,Organization admin,Invited by,Invitation date,Last active,Domain requests,"
"Member management,Domain management,Number of domains,Domains\n"
# Content
"meoward@rocks.com,False,Unknown,Unknown,Invited,None,Manager,False,0,\n"
"big_lebowski@dude.co,False,Unknown,Unknown,Invited,None,Viewer,False,0,\n"
"tired_sleepy@igorville.gov,False,Unknown,Unknown,Invited,Viewer,None,False,0,\n"
"icy_superuser@igorville.gov,True,Unknown,Unknown,Invited,Viewer Requester,Manager,False,0,\n"
"cozy_staffuser@igorville.gov,True,Unknown,Unknown,Invited,Viewer Requester,None,False,0,\n"
)
# Normalize line endings and remove commas,
# spaces and leading/trailing whitespace
csv_content = csv_content.replace(",,", "").replace(",", "").replace(" ", "").replace("\r\n", "\n").strip()
expected_content = expected_content.replace(",,", "").replace(",", "").replace(" ", "").strip()
self.assertEqual(csv_content, expected_content)
class HelperFunctions(MockDbForSharedTests): class HelperFunctions(MockDbForSharedTests):
"""This asserts that 1=1. Its limited usefulness lies in making sure the helper methods stay healthy.""" """This asserts that 1=1. Its limited usefulness lies in making sure the helper methods stay healthy."""

View file

@ -386,7 +386,7 @@ class PortfolioInvitationModelAnnotation(BaseModelAnnotation):
.order_by("action_time") .order_by("action_time")
.values("display_date")[:1] .values("display_date")[:1]
), ),
Value("Invalid date"), Value("Unknown"),
output_field=TextField(), output_field=TextField(),
) )