Skip to content

Commit

Permalink
domain manager tests and linted
Browse files Browse the repository at this point in the history
  • Loading branch information
dave-kennedy-ecs committed Dec 21, 2024
1 parent f2bd0ad commit d36e2e2
Show file tree
Hide file tree
Showing 5 changed files with 218 additions and 51 deletions.
1 change: 0 additions & 1 deletion src/registrar/tests/test_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -710,7 +710,6 @@ def test_save_exception_generic_error(self, mock_messages_error, mock_send_email
# self.assertContains(response, "Simulated error message", msg_prefix="Expected error message not found.")



class TestHostAdmin(TestCase):
"""Tests for the HostAdmin class as super user
Expand Down
35 changes: 22 additions & 13 deletions src/registrar/tests/test_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@
AboutYourOrganizationForm,
)
from registrar.forms.domain import ContactForm
from registrar.forms.portfolio import BasePortfolioMemberForm, PortfolioInvitedMemberForm, PortfolioMemberForm, PortfolioNewMemberForm
from registrar.forms.portfolio import (
PortfolioInvitedMemberForm,
PortfolioMemberForm,
PortfolioNewMemberForm,
)
from registrar.models.portfolio import Portfolio
from registrar.models.portfolio_invitation import PortfolioInvitation
from registrar.models.user import User
Expand Down Expand Up @@ -423,7 +427,9 @@ class TestBasePortfolioMemberForms(TestCase):
def setUp(self):
super().setUp()
self.user = create_user()
self.portfolio, _ = Portfolio.objects.get_or_create(creator_id=self.user.id, organization_name="Hotel California")
self.portfolio, _ = Portfolio.objects.get_or_create(
creator_id=self.user.id, organization_name="Hotel California"
)

def tearDown(self):
super().tearDown()
Expand All @@ -433,10 +439,10 @@ def tearDown(self):
User.objects.all().delete()

def _assert_form_is_valid(self, form_class, data, instance=None):
if instance != None:
if instance is not None:
form = form_class(data=data, instance=instance)
else:
print('no instance')
print("no instance")
form = form_class(data=data)
self.assertTrue(form.is_valid(), f"Form {form_class.__name__} failed validation with data: {data}")
return form
Expand Down Expand Up @@ -491,13 +497,15 @@ def test_required_field_for_member(self):

def test_clean_validates_required_fields_for_role(self):
"""Test that the `clean` method validates the correct fields for each role.
For PortfolioMemberForm and PortfolioInvitedMemberForm, we pass an object as the instance to the form.
For UserPortfolioPermissionChoices, we add a portfolio and an email to the POST data.
These things are handled in the views."""

user_portfolio_permission, _ = UserPortfolioPermission.objects.get_or_create(portfolio=self.portfolio, user=self.user)
user_portfolio_permission, _ = UserPortfolioPermission.objects.get_or_create(
portfolio=self.portfolio, user=self.user
)
portfolio_invitation, _ = PortfolioInvitation.objects.get_or_create(portfolio=self.portfolio, email="hi@ho")

data = {
Expand All @@ -519,7 +527,7 @@ def test_clean_validates_required_fields_for_role(self):

data = {
"email": "[email protected]",
"portfolio": self.portfolio.id,
"portfolio": self.portfolio.id,
"role": UserPortfolioRoleChoices.ORGANIZATION_ADMIN.value,
"domain_request_permission_admin": UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS.value,
"member_permission_admin": UserPortfolioPermissionChoices.EDIT_MEMBERS.value,
Expand All @@ -534,7 +542,9 @@ def test_clean_member_permission_edgecase(self):
"""Test that the clean method correctly handles the special "no_access" value for members.
We'll need to add a portfolio, which in the app is handled by the view post."""

user_portfolio_permission, _ = UserPortfolioPermission.objects.get_or_create(portfolio=self.portfolio, user=self.user)
user_portfolio_permission, _ = UserPortfolioPermission.objects.get_or_create(
portfolio=self.portfolio, user=self.user
)
portfolio_invitation, _ = PortfolioInvitation.objects.get_or_create(portfolio=self.portfolio, email="hi@ho")

data = {
Expand All @@ -550,15 +560,14 @@ def test_clean_member_permission_edgecase(self):
cleaned_data = form.cleaned_data
self.assertEqual(cleaned_data["domain_request_permission_member"], None)


def test_map_instance_to_initial_admin_role(self):
"""Test that instance data is correctly mapped to the initial form values for an admin role."""
user_portfolio_permission = UserPortfolioPermission(
roles=[UserPortfolioRoleChoices.ORGANIZATION_ADMIN],
additional_permissions=[UserPortfolioPermissionChoices.VIEW_MEMBERS],
)
portfolio_invitation, _ = PortfolioInvitation.objects.get_or_create(
portfolio=self.portfolio,
portfolio=self.portfolio,
email="hi@ho",
roles=[UserPortfolioRoleChoices.ORGANIZATION_ADMIN],
additional_permissions=[UserPortfolioPermissionChoices.VIEW_MEMBERS],
Expand All @@ -579,7 +588,7 @@ def test_map_instance_to_initial_member_role(self):
additional_permissions=[UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS],
)
portfolio_invitation, _ = PortfolioInvitation.objects.get_or_create(
portfolio=self.portfolio,
portfolio=self.portfolio,
email="hi@ho",
roles=[UserPortfolioRoleChoices.ORGANIZATION_MEMBER],
additional_permissions=[UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS],
Expand All @@ -595,7 +604,7 @@ def test_invalid_data_for_admin(self):
"""Test invalid form submission for an admin role with missing permissions."""
data = {
"email": "[email protected]",
"portfolio": self.portfolio.id,
"portfolio": self.portfolio.id,
"role": UserPortfolioRoleChoices.ORGANIZATION_ADMIN.value,
"domain_request_permission_admin": "", # Missing field
"member_permission_admin": "", # Missing field
Expand Down
151 changes: 149 additions & 2 deletions src/registrar/tests/test_views_domain.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
from django.conf import settings
from django.urls import reverse
from django.contrib.auth import get_user_model
from registrar.models.portfolio_invitation import PortfolioInvitation
from registrar.utility.email import EmailSendingError
from waffle.testutils import override_flag
from api.tests.common import less_console_noise_decorator
from registrar.models.utility.portfolio_helper import UserPortfolioPermissionChoices, UserPortfolioRoleChoices
Expand Down Expand Up @@ -454,6 +456,7 @@ def tearDownClass(cls):

def tearDown(self):
"""Ensure that the user has its original permissions"""
PortfolioInvitation.objects.all().delete()
super().tearDown()

@less_console_noise_decorator
Expand Down Expand Up @@ -486,7 +489,7 @@ def test_domain_user_add(self):
@less_console_noise_decorator
def test_domain_user_add_form(self):
"""Adding an existing user works."""
other_user, _ = get_user_model().objects.get_or_create(email="[email protected]")
get_user_model().objects.get_or_create(email="[email protected]")
add_page = self.app.get(reverse("domain-users-add", kwargs={"pk": self.domain.id}))
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]

Expand All @@ -509,6 +512,148 @@ def test_domain_user_add_form(self):
success_page = success_result.follow()
self.assertContains(success_page, "[email protected]")

@boto3_mocking.patching
@override_flag("organization_feature", active=True)
@less_console_noise_decorator
@patch("registrar.views.domain.send_portfolio_invitation_email")
@patch("registrar.views.domain.send_domain_invitation_email")
def test_domain_user_add_form_sends_portfolio_invitation(self, mock_send_domain_email, mock_send_portfolio_email):
"""Adding an existing user works and sends portfolio invitation when
user is not member of portfolio."""
get_user_model().objects.get_or_create(email="[email protected]")
add_page = self.app.get(reverse("domain-users-add", kwargs={"pk": self.domain.id}))
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]

add_page.form["email"] = "[email protected]"

self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)

success_result = add_page.form.submit()

self.assertEqual(success_result.status_code, 302)
self.assertEqual(
success_result["Location"],
reverse("domain-users", kwargs={"pk": self.domain.id}),
)

# Verify that the invitation emails were sent
mock_send_portfolio_email.assert_called_once_with(
email="[email protected]", requestor=self.user, portfolio=self.portfolio
)
mock_send_domain_email.assert_called_once()
call_args = mock_send_domain_email.call_args.kwargs
self.assertEqual(call_args["email"], "[email protected]")
self.assertEqual(call_args["requestor"], self.user)
self.assertEqual(call_args["domain"], self.domain)
self.assertIsNone(call_args.get("is_member_of_different_org"))

# Assert that the PortfolioInvitation is created
portfolio_invitation = PortfolioInvitation.objects.filter(
email="[email protected]", portfolio=self.portfolio
).first()
self.assertIsNotNone(portfolio_invitation, "Portfolio invitation should be created.")
self.assertEqual(portfolio_invitation.email, "[email protected]")
self.assertEqual(portfolio_invitation.portfolio, self.portfolio)

self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
success_page = success_result.follow()
self.assertContains(success_page, "[email protected]")

@boto3_mocking.patching
@override_flag("organization_feature", active=True)
@less_console_noise_decorator
@patch("registrar.views.domain.send_portfolio_invitation_email")
@patch("registrar.views.domain.send_domain_invitation_email")
def test_domain_user_add_form_doesnt_send_portfolio_invitation_if_already_member(
self, mock_send_domain_email, mock_send_portfolio_email
):
"""Adding an existing user works and sends portfolio invitation when
user is not member of portfolio."""
other_user, _ = get_user_model().objects.get_or_create(email="[email protected]")
UserPortfolioPermission.objects.get_or_create(
user=other_user, portfolio=self.portfolio, roles=[UserPortfolioRoleChoices.ORGANIZATION_ADMIN]
)
add_page = self.app.get(reverse("domain-users-add", kwargs={"pk": self.domain.id}))
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]

add_page.form["email"] = "[email protected]"

self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)

success_result = add_page.form.submit()

self.assertEqual(success_result.status_code, 302)
self.assertEqual(
success_result["Location"],
reverse("domain-users", kwargs={"pk": self.domain.id}),
)

# Verify that the invitation emails were sent
mock_send_portfolio_email.assert_not_called()
mock_send_domain_email.assert_called_once()
call_args = mock_send_domain_email.call_args.kwargs
self.assertEqual(call_args["email"], "[email protected]")
self.assertEqual(call_args["requestor"], self.user)
self.assertEqual(call_args["domain"], self.domain)
self.assertIsNone(call_args.get("is_member_of_different_org"))

# Assert that no PortfolioInvitation is created
portfolio_invitation_exists = PortfolioInvitation.objects.filter(
email="[email protected]", portfolio=self.portfolio
).exists()
self.assertFalse(
portfolio_invitation_exists, "Portfolio invitation should not be created when the user is already a member."
)

self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
success_page = success_result.follow()
self.assertContains(success_page, "[email protected]")

@boto3_mocking.patching
@override_flag("organization_feature", active=True)
@less_console_noise_decorator
@patch("registrar.views.domain.send_portfolio_invitation_email")
@patch("registrar.views.domain.send_domain_invitation_email")
def test_domain_user_add_form_sends_portfolio_invitation_raises_email_sending_error(
self, mock_send_domain_email, mock_send_portfolio_email
):
"""Adding an existing user works and attempts to send portfolio invitation when
user is not member of portfolio and send raises an error."""
mock_send_portfolio_email.side_effect = EmailSendingError("Failed to send email.")
get_user_model().objects.get_or_create(email="[email protected]")
add_page = self.app.get(reverse("domain-users-add", kwargs={"pk": self.domain.id}))
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]

add_page.form["email"] = "[email protected]"

self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)

success_result = add_page.form.submit()

self.assertEqual(success_result.status_code, 302)
self.assertEqual(
success_result["Location"],
reverse("domain-users", kwargs={"pk": self.domain.id}),
)

# Verify that the invitation emails were sent
mock_send_portfolio_email.assert_called_once_with(
email="[email protected]", requestor=self.user, portfolio=self.portfolio
)
mock_send_domain_email.assert_not_called()

# Assert that no PortfolioInvitation is created
portfolio_invitation_exists = PortfolioInvitation.objects.filter(
email="[email protected]", portfolio=self.portfolio
).exists()
self.assertFalse(
portfolio_invitation_exists, "Portfolio invitation should not be created when email fails to send."
)

self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
success_page = success_result.follow()
self.assertContains(success_page, "Could not send email invitation.")

@boto3_mocking.patching
@less_console_noise_decorator
def test_domain_invitation_created(self):
Expand Down Expand Up @@ -757,7 +902,9 @@ def test_domain_invitation_email_displays_error(self):
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
add_page.form.submit()

expected_message_content = f"Can't send invitation email. No email is associated with the account for 'test_user'."
expected_message_content = (
"Can't send invitation email. No email is associated with the account for 'test_user'."
)

# Assert that the error message was called with the correct argument
mock_error.assert_called_once_with(
Expand Down
Loading

0 comments on commit d36e2e2

Please sign in to comment.