mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-08-03 08:22:18 +02:00
3056 lines
141 KiB
Python
3056 lines
141 KiB
Python
from unittest import skip
|
|
from unittest.mock import MagicMock, ANY, patch
|
|
|
|
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
|
|
from .common import MockEppLib, create_user # type: ignore
|
|
from django_webtest import WebTest # type: ignore
|
|
import boto3_mocking # type: ignore
|
|
|
|
from registrar.utility.errors import (
|
|
NameserverError,
|
|
NameserverErrorCodes,
|
|
SecurityEmailError,
|
|
SecurityEmailErrorCodes,
|
|
GenericError,
|
|
GenericErrorCodes,
|
|
DsDataError,
|
|
DsDataErrorCodes,
|
|
)
|
|
|
|
from registrar.models import (
|
|
DomainRequest,
|
|
Domain,
|
|
DomainInformation,
|
|
DomainInvitation,
|
|
AllowedEmail,
|
|
Contact,
|
|
PublicContact,
|
|
Host,
|
|
HostIP,
|
|
UserDomainRole,
|
|
User,
|
|
FederalAgency,
|
|
Portfolio,
|
|
Suborganization,
|
|
UserPortfolioPermission,
|
|
)
|
|
from datetime import date, datetime, timedelta
|
|
from django.utils import timezone
|
|
|
|
from .common import less_console_noise
|
|
from .test_views import TestWithUser
|
|
|
|
import logging
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class TestWithDomainPermissions(TestWithUser):
|
|
@less_console_noise_decorator
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.domain, _ = Domain.objects.get_or_create(name="igorville.gov")
|
|
self.domain_with_ip, _ = Domain.objects.get_or_create(name="nameserverwithip.gov")
|
|
self.domain_just_nameserver, _ = Domain.objects.get_or_create(name="justnameserver.com")
|
|
self.domain_no_information, _ = Domain.objects.get_or_create(name="noinformation.gov")
|
|
self.domain_on_hold, _ = Domain.objects.get_or_create(
|
|
name="on-hold.gov",
|
|
state=Domain.State.ON_HOLD,
|
|
expiration_date=timezone.make_aware(
|
|
datetime.combine(date.today() + timedelta(days=1), datetime.min.time())
|
|
),
|
|
)
|
|
self.domain_dns_needed, _ = Domain.objects.get_or_create(
|
|
name="dns-needed.gov",
|
|
state=Domain.State.DNS_NEEDED,
|
|
)
|
|
self.domain_deleted, _ = Domain.objects.get_or_create(
|
|
name="deleted.gov",
|
|
state=Domain.State.DELETED,
|
|
expiration_date=timezone.make_aware(
|
|
datetime.combine(date.today() + timedelta(days=1), datetime.min.time())
|
|
),
|
|
)
|
|
|
|
self.domain_dsdata, _ = Domain.objects.get_or_create(name="dnssec-dsdata.gov")
|
|
self.domain_multdsdata, _ = Domain.objects.get_or_create(name="dnssec-multdsdata.gov")
|
|
# We could simply use domain (igorville) but this will be more readable in tests
|
|
# that inherit this setUp
|
|
self.domain_dnssec_none, _ = Domain.objects.get_or_create(name="dnssec-none.gov")
|
|
|
|
self.domain_with_four_nameservers, _ = Domain.objects.get_or_create(name="fournameserversDomain.gov")
|
|
|
|
self.domain_information, _ = DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain)
|
|
|
|
DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain_dsdata)
|
|
DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain_multdsdata)
|
|
DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain_dnssec_none)
|
|
DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain_with_four_nameservers)
|
|
DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain_with_ip)
|
|
DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain_just_nameserver)
|
|
DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain_on_hold)
|
|
DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain_deleted)
|
|
DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain_dns_needed)
|
|
|
|
self.role, _ = UserDomainRole.objects.get_or_create(
|
|
user=self.user, domain=self.domain, role=UserDomainRole.Roles.MANAGER
|
|
)
|
|
|
|
UserDomainRole.objects.get_or_create(
|
|
user=self.user, domain=self.domain_dsdata, role=UserDomainRole.Roles.MANAGER
|
|
)
|
|
UserDomainRole.objects.get_or_create(
|
|
user=self.user, domain=self.domain_dns_needed, role=UserDomainRole.Roles.MANAGER
|
|
)
|
|
UserDomainRole.objects.get_or_create(
|
|
user=self.user,
|
|
domain=self.domain_multdsdata,
|
|
role=UserDomainRole.Roles.MANAGER,
|
|
)
|
|
UserDomainRole.objects.get_or_create(
|
|
user=self.user,
|
|
domain=self.domain_dnssec_none,
|
|
role=UserDomainRole.Roles.MANAGER,
|
|
)
|
|
UserDomainRole.objects.get_or_create(
|
|
user=self.user,
|
|
domain=self.domain_with_four_nameservers,
|
|
role=UserDomainRole.Roles.MANAGER,
|
|
)
|
|
UserDomainRole.objects.get_or_create(
|
|
user=self.user,
|
|
domain=self.domain_with_ip,
|
|
role=UserDomainRole.Roles.MANAGER,
|
|
)
|
|
UserDomainRole.objects.get_or_create(
|
|
user=self.user,
|
|
domain=self.domain_just_nameserver,
|
|
role=UserDomainRole.Roles.MANAGER,
|
|
)
|
|
UserDomainRole.objects.get_or_create(
|
|
user=self.user, domain=self.domain_on_hold, role=UserDomainRole.Roles.MANAGER
|
|
)
|
|
UserDomainRole.objects.get_or_create(
|
|
user=self.user, domain=self.domain_deleted, role=UserDomainRole.Roles.MANAGER
|
|
)
|
|
|
|
def tearDown(self):
|
|
try:
|
|
UserDomainRole.objects.all().delete()
|
|
DomainInvitation.objects.all().delete()
|
|
if hasattr(self.domain, "contacts"):
|
|
self.domain.contacts.all().delete()
|
|
DomainRequest.objects.all().delete()
|
|
DomainInformation.objects.all().delete()
|
|
PublicContact.objects.all().delete()
|
|
HostIP.objects.all().delete()
|
|
Host.objects.all().delete()
|
|
Domain.objects.all().delete()
|
|
UserDomainRole.objects.all().delete()
|
|
Suborganization.objects.all().delete()
|
|
Portfolio.objects.all().delete()
|
|
except ValueError: # pass if already deleted
|
|
pass
|
|
super().tearDown()
|
|
|
|
|
|
class TestDomainPermissions(TestWithDomainPermissions):
|
|
@less_console_noise_decorator
|
|
def test_not_logged_in(self):
|
|
"""Not logged in gets a redirect to Login."""
|
|
for view_name in [
|
|
"domain",
|
|
"domain-users",
|
|
"domain-users-add",
|
|
"domain-dns-nameservers",
|
|
"domain-org-name-address",
|
|
"domain-senior-official",
|
|
"domain-security-email",
|
|
]:
|
|
with self.subTest(view_name=view_name):
|
|
response = self.client.get(reverse(view_name, kwargs={"domain_pk": self.domain.id}))
|
|
self.assertEqual(response.status_code, 302)
|
|
|
|
@less_console_noise_decorator
|
|
def test_no_domain_role(self):
|
|
"""Logged in but no role gets 403 Forbidden."""
|
|
self.client.force_login(self.user)
|
|
self.role.delete() # user no longer has a role on this domain
|
|
|
|
for view_name in [
|
|
"domain",
|
|
"domain-users",
|
|
"domain-users-add",
|
|
"domain-dns-nameservers",
|
|
"domain-org-name-address",
|
|
"domain-senior-official",
|
|
"domain-security-email",
|
|
]:
|
|
with self.subTest(view_name=view_name):
|
|
response = self.client.get(reverse(view_name, kwargs={"domain_pk": self.domain.id}))
|
|
self.assertEqual(response.status_code, 403)
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_pages_blocked_for_on_hold_and_deleted(self):
|
|
"""Test that the domain pages are blocked for on hold and deleted domains"""
|
|
|
|
self.client.force_login(self.user)
|
|
for view_name in [
|
|
"domain-users",
|
|
"domain-users-add",
|
|
"domain-dns",
|
|
"domain-dns-nameservers",
|
|
"domain-dns-dnssec",
|
|
"domain-dns-dnssec-dsdata",
|
|
"domain-org-name-address",
|
|
"domain-senior-official",
|
|
"domain-security-email",
|
|
]:
|
|
for domain in [
|
|
self.domain_on_hold,
|
|
self.domain_deleted,
|
|
]:
|
|
with self.subTest(view_name=view_name, domain=domain):
|
|
response = self.client.get(reverse(view_name, kwargs={"domain_pk": domain.id}))
|
|
self.assertEqual(response.status_code, 403)
|
|
|
|
|
|
class TestDomainOverview(TestWithDomainPermissions, WebTest):
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.app.set_user(self.user.username)
|
|
self.client.force_login(self.user)
|
|
|
|
|
|
class TestDomainDetail(TestDomainOverview):
|
|
@skip("Assertion broke for no reason, why? Need to fix")
|
|
def test_domain_detail_link_works(self):
|
|
home_page = self.app.get("/")
|
|
logger.info(f"This is the value of home_page: {home_page}")
|
|
self.assertContains(home_page, "igorville.gov")
|
|
# click the "Edit" link
|
|
detail_page = home_page.click("Manage", index=0)
|
|
self.assertContains(detail_page, "igorville.gov")
|
|
self.assertContains(detail_page, "Status")
|
|
|
|
def test_unknown_domain_does_not_show_as_expired_on_detail_page(self):
|
|
"""An UNKNOWN domain should not exist on the detail_page anymore.
|
|
It shows as 'DNS needed'"""
|
|
# At the time of this test's writing, there are 6 UNKNOWN domains inherited
|
|
# from constructors. Let's reset.
|
|
with less_console_noise():
|
|
PublicContact.objects.all().delete()
|
|
Domain.objects.all().delete()
|
|
UserDomainRole.objects.all().delete()
|
|
|
|
self.domain, _ = Domain.objects.get_or_create(name="igorville.gov")
|
|
self.domain_information, _ = DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain)
|
|
self.role, _ = UserDomainRole.objects.get_or_create(
|
|
user=self.user, domain=self.domain, role=UserDomainRole.Roles.MANAGER
|
|
)
|
|
|
|
igorville = Domain.objects.get(name="igorville.gov")
|
|
self.assertEquals(igorville.state, Domain.State.UNKNOWN)
|
|
detail_page = self.app.get(f"/domain/{igorville.id}")
|
|
self.assertContains(detail_page, "Expired")
|
|
|
|
self.assertNotContains(detail_page, "DNS needed")
|
|
|
|
def test_domain_detail_blocked_for_ineligible_user(self):
|
|
"""We could easily duplicate this test for all domain management
|
|
views, but a single url test should be solid enough since all domain
|
|
management pages share the same permissions class"""
|
|
with less_console_noise():
|
|
self.user.status = User.RESTRICTED
|
|
self.user.save()
|
|
response = self.client.get(reverse("domain", kwargs={"domain_pk": self.domain.id}))
|
|
self.assertEqual(response.status_code, 403)
|
|
|
|
def test_domain_detail_allowed_for_on_hold(self):
|
|
"""Test that the domain overview page displays for on hold domain"""
|
|
with less_console_noise():
|
|
# View domain overview page
|
|
detail_page = self.client.get(reverse("domain", kwargs={"domain_pk": self.domain_on_hold.id}))
|
|
self.assertNotContains(detail_page, "Edit")
|
|
|
|
def test_domain_detail_see_just_nameserver(self):
|
|
with less_console_noise():
|
|
# View nameserver on Domain Overview page
|
|
detail_page = self.app.get(reverse("domain", kwargs={"domain_pk": self.domain_just_nameserver.id}))
|
|
|
|
self.assertContains(detail_page, "justnameserver.com")
|
|
self.assertContains(detail_page, "ns1.justnameserver.com")
|
|
self.assertContains(detail_page, "ns2.justnameserver.com")
|
|
|
|
def test_domain_detail_see_nameserver_and_ip(self):
|
|
with less_console_noise():
|
|
# View nameserver on Domain Overview page
|
|
detail_page = self.app.get(reverse("domain", kwargs={"domain_pk": self.domain_with_ip.id}))
|
|
|
|
self.assertContains(detail_page, "nameserverwithip.gov")
|
|
|
|
self.assertContains(detail_page, "ns1.nameserverwithip.gov")
|
|
self.assertContains(detail_page, "ns2.nameserverwithip.gov")
|
|
self.assertContains(detail_page, "ns3.nameserverwithip.gov")
|
|
# Splitting IP addresses bc there is odd whitespace and can't strip text
|
|
self.assertContains(detail_page, "(1.2.3.4,")
|
|
self.assertContains(detail_page, "2.3.4.5)")
|
|
|
|
def test_domain_detail_with_no_information_or_domain_request(self):
|
|
"""Test that domain management page returns 200 and displays error
|
|
when no domain information or domain request exist"""
|
|
with less_console_noise():
|
|
# have to use staff user for this test
|
|
staff_user = create_user()
|
|
# staff_user.save()
|
|
self.client.force_login(staff_user)
|
|
|
|
# need to set the analyst_action and analyst_action_location
|
|
# in the session to emulate user clicking Manage Domain
|
|
# in the admin interface
|
|
session = self.client.session
|
|
session["analyst_action"] = "foo"
|
|
session["analyst_action_location"] = self.domain_no_information.id
|
|
session.save()
|
|
|
|
detail_page = self.client.get(reverse("domain", kwargs={"domain_pk": self.domain_no_information.id}))
|
|
|
|
self.assertContains(detail_page, "noinformation.gov")
|
|
self.assertContains(detail_page, "Domain missing domain information")
|
|
|
|
def test_domain_detail_with_analyst_managing_domain(self):
|
|
"""Test that domain management page returns 200 and does not display
|
|
blue error message when an analyst is managing the domain"""
|
|
with less_console_noise():
|
|
staff_user = create_user()
|
|
self.client.force_login(staff_user)
|
|
|
|
# need to set the analyst_action and analyst_action_location
|
|
# in the session to emulate user clicking Manage Domain
|
|
# in the admin interface
|
|
session = self.client.session
|
|
session["analyst_action"] = "edit"
|
|
session["analyst_action_location"] = self.domain.id
|
|
session.save()
|
|
|
|
detail_page = self.client.get(reverse("domain", kwargs={"domain_pk": self.domain.id}))
|
|
|
|
self.assertNotContains(
|
|
detail_page, "If you need to make updates, contact one of the listed domain managers."
|
|
)
|
|
|
|
@less_console_noise_decorator
|
|
@override_flag("organization_feature", active=True)
|
|
def test_domain_readonly_on_detail_page(self):
|
|
"""Test that a domain, which is part of a portfolio, but for which the user is not a domain manager,
|
|
properly displays read only"""
|
|
|
|
portfolio, _ = Portfolio.objects.get_or_create(organization_name="Test org", creator=self.user)
|
|
# need to create a different user than self.user because the user needs permission assignments
|
|
user = get_user_model().objects.create(
|
|
first_name="Test",
|
|
last_name="User",
|
|
email="bogus@example.gov",
|
|
phone="8003111234",
|
|
title="test title",
|
|
)
|
|
domain, _ = Domain.objects.get_or_create(name="bogusdomain.gov")
|
|
DomainInformation.objects.get_or_create(creator=user, domain=domain, portfolio=portfolio)
|
|
|
|
UserPortfolioPermission.objects.get_or_create(
|
|
user=user,
|
|
portfolio=portfolio,
|
|
roles=[UserPortfolioRoleChoices.ORGANIZATION_MEMBER],
|
|
additional_permissions=[
|
|
UserPortfolioPermissionChoices.VIEW_ALL_DOMAINS,
|
|
],
|
|
)
|
|
user.refresh_from_db()
|
|
self.client.force_login(user)
|
|
detail_page = self.client.get(f"/domain/{domain.id}")
|
|
# Check that alert message displays properly
|
|
self.assertContains(
|
|
detail_page,
|
|
"You don't have access to manage "
|
|
+ domain.name
|
|
+ ". If you need to make updates, contact one of the listed domain managers.",
|
|
)
|
|
# Check that user does not have option to Edit domain
|
|
self.assertNotContains(detail_page, "Edit")
|
|
# Check that invited domain manager section not displayed when no invited domain managers
|
|
self.assertNotContains(detail_page, "Invited domain managers")
|
|
|
|
@less_console_noise_decorator
|
|
@override_flag("organization_feature", active=True)
|
|
def test_domain_readonly_on_detail_page_for_org_admin_not_manager(self):
|
|
"""Test that a domain, which is part of a portfolio, but for which the user is not a domain manager,
|
|
properly displays read only"""
|
|
|
|
portfolio, _ = Portfolio.objects.get_or_create(organization_name="Test org", creator=self.user)
|
|
# need to create a different user than self.user because the user needs permission assignments
|
|
user = get_user_model().objects.create(
|
|
first_name="Test",
|
|
last_name="User",
|
|
email="bogus@example.gov",
|
|
phone="8003111234",
|
|
title="test title",
|
|
)
|
|
domain, _ = Domain.objects.get_or_create(name="bogusdomain.gov")
|
|
DomainInformation.objects.get_or_create(creator=user, domain=domain, portfolio=portfolio)
|
|
|
|
UserPortfolioPermission.objects.get_or_create(
|
|
user=user, portfolio=portfolio, roles=[UserPortfolioRoleChoices.ORGANIZATION_ADMIN]
|
|
)
|
|
# add a domain invitation
|
|
DomainInvitation.objects.get_or_create(email="invited@example.com", domain=domain)
|
|
user.refresh_from_db()
|
|
self.client.force_login(user)
|
|
detail_page = self.client.get(f"/domain/{domain.id}")
|
|
# Check that alert message displays properly
|
|
self.assertContains(
|
|
detail_page,
|
|
"If you need to make updates, contact one of the listed domain managers.",
|
|
)
|
|
# Check that user does not have option to Edit domain
|
|
self.assertNotContains(detail_page, "Edit")
|
|
# Check that invited domain manager is displayed
|
|
self.assertContains(detail_page, "Invited domain managers")
|
|
self.assertContains(detail_page, "invited@example.com")
|
|
|
|
|
|
class TestDomainDetailDomainRenewal(TestDomainOverview):
|
|
def setUp(self):
|
|
super().setUp()
|
|
|
|
self.user = get_user_model().objects.create(
|
|
first_name="User",
|
|
last_name="Test",
|
|
email="bogus@example.gov",
|
|
phone="8003111234",
|
|
title="test title",
|
|
username="usertest",
|
|
)
|
|
|
|
self.domain_to_renew, _ = Domain.objects.get_or_create(
|
|
name="domainrenewal.gov",
|
|
)
|
|
|
|
self.domain_not_expiring, _ = Domain.objects.get_or_create(
|
|
name="domainnotexpiring.gov", expiration_date=timezone.now().date() + timedelta(days=65)
|
|
)
|
|
|
|
self.domain_no_domain_manager, _ = Domain.objects.get_or_create(name="domainnodomainmanager.gov")
|
|
|
|
UserDomainRole.objects.get_or_create(
|
|
user=self.user, domain=self.domain_to_renew, role=UserDomainRole.Roles.MANAGER
|
|
)
|
|
|
|
DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain_to_renew)
|
|
|
|
self.portfolio, _ = Portfolio.objects.get_or_create(organization_name="Test org", creator=self.user)
|
|
|
|
self.user.save()
|
|
|
|
def expiration_date_one_year_out(self):
|
|
todays_date = datetime.today()
|
|
new_expiration_date = todays_date.replace(year=todays_date.year + 1)
|
|
return new_expiration_date
|
|
|
|
def custom_is_expired_false(self):
|
|
return False
|
|
|
|
def custom_is_expired_true(self):
|
|
return True
|
|
|
|
def custom_is_expiring(self):
|
|
return True
|
|
|
|
def custom_renew_domain(self):
|
|
self.domain_with_ip.expiration_date = self.expiration_date_one_year_out()
|
|
self.domain_with_ip.save()
|
|
|
|
def test_expiring_domain_on_detail_page_as_domain_manager(self):
|
|
"""If a user is a domain manager and their domain is expiring soon,
|
|
user should be able to see the "Renew to maintain access" link domain overview detail box."""
|
|
self.client.force_login(self.user)
|
|
with patch.object(Domain, "is_expiring", self.custom_is_expiring), patch.object(
|
|
Domain, "is_expired", self.custom_is_expired_false
|
|
):
|
|
self.assertEquals(self.domain_to_renew.state, Domain.State.UNKNOWN)
|
|
detail_page = self.client.get(
|
|
reverse("domain", kwargs={"domain_pk": self.domain_to_renew.id}),
|
|
)
|
|
self.assertContains(detail_page, "Expiring soon")
|
|
|
|
self.assertContains(detail_page, "Renew to maintain access")
|
|
|
|
self.assertNotContains(detail_page, "DNS needed")
|
|
self.assertNotContains(detail_page, "Expired")
|
|
|
|
@override_flag("organization_feature", active=True)
|
|
def test_expiring_domain_on_detail_page_in_org_model_as_a_non_domain_manager(self):
|
|
"""In org model: If a user is NOT a domain manager and their domain is expiring soon,
|
|
user be notified to contact a domain manager in the domain overview detail box."""
|
|
portfolio, _ = Portfolio.objects.get_or_create(organization_name="Test org", creator=self.user)
|
|
non_dom_manage_user = get_user_model().objects.create(
|
|
first_name="Non Domain",
|
|
last_name="Manager",
|
|
email="verybogus@example.gov",
|
|
phone="8003111234",
|
|
title="test title again",
|
|
username="nondomain",
|
|
)
|
|
|
|
non_dom_manage_user.save()
|
|
UserPortfolioPermission.objects.get_or_create(
|
|
user=non_dom_manage_user,
|
|
portfolio=portfolio,
|
|
roles=[UserPortfolioRoleChoices.ORGANIZATION_MEMBER],
|
|
additional_permissions=[
|
|
UserPortfolioPermissionChoices.VIEW_ALL_DOMAINS,
|
|
],
|
|
)
|
|
domain_to_renew2, _ = Domain.objects.get_or_create(name="bogusdomain2.gov")
|
|
DomainInformation.objects.get_or_create(
|
|
creator=non_dom_manage_user, domain=domain_to_renew2, portfolio=self.portfolio
|
|
)
|
|
non_dom_manage_user.refresh_from_db()
|
|
self.client.force_login(non_dom_manage_user)
|
|
with patch.object(Domain, "is_expiring", self.custom_is_expiring), patch.object(
|
|
Domain, "is_expired", self.custom_is_expired_false
|
|
):
|
|
detail_page = self.client.get(
|
|
reverse("domain", kwargs={"domain_pk": domain_to_renew2.id}),
|
|
)
|
|
self.assertContains(detail_page, "Contact one of the listed domain managers to renew the domain.")
|
|
|
|
@override_flag("organization_feature", active=True)
|
|
def test_expiring_domain_on_detail_page_in_org_model_as_a_domain_manager(self):
|
|
"""Inorg model: If a user is a domain manager and their domain is expiring soon,
|
|
user should be able to see the "Renew to maintain access" link domain overview detail box."""
|
|
portfolio, _ = Portfolio.objects.get_or_create(organization_name="Test org2", creator=self.user)
|
|
|
|
domain_to_renew3, _ = Domain.objects.get_or_create(name="bogusdomain3.gov")
|
|
|
|
UserDomainRole.objects.get_or_create(user=self.user, domain=domain_to_renew3, role=UserDomainRole.Roles.MANAGER)
|
|
DomainInformation.objects.get_or_create(creator=self.user, domain=domain_to_renew3, portfolio=portfolio)
|
|
self.user.refresh_from_db()
|
|
self.client.force_login(self.user)
|
|
with patch.object(Domain, "is_expiring", self.custom_is_expiring), patch.object(
|
|
Domain, "is_expired", self.custom_is_expired_false
|
|
):
|
|
detail_page = self.client.get(
|
|
reverse("domain", kwargs={"domain_pk": domain_to_renew3.id}),
|
|
)
|
|
self.assertContains(detail_page, "Renew to maintain access")
|
|
|
|
def test_domain_renewal_form_and_sidebar_expiring(self):
|
|
"""If a user is a domain manager and their domain is expiring soon,
|
|
user should be able to see Renewal Form on the sidebar."""
|
|
self.client.force_login(self.user)
|
|
with patch.object(Domain, "is_expiring", self.custom_is_expiring), patch.object(
|
|
Domain, "is_expiring", self.custom_is_expiring
|
|
):
|
|
# Grab the detail page
|
|
detail_page = self.client.get(
|
|
reverse("domain", kwargs={"domain_pk": self.domain_to_renew.id}),
|
|
)
|
|
|
|
# Make sure we see the link as a domain manager
|
|
self.assertContains(detail_page, "Renew to maintain access")
|
|
|
|
# Make sure we can see Renewal form on the sidebar since it's expiring
|
|
self.assertContains(detail_page, "Renewal form")
|
|
|
|
# Grab link to the renewal page
|
|
renewal_form_url = reverse("domain-renewal", kwargs={"domain_pk": self.domain_to_renew.id})
|
|
self.assertContains(detail_page, f'href="{renewal_form_url}"')
|
|
|
|
# Simulate clicking the link
|
|
response = self.client.get(renewal_form_url)
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertContains(response, f"Renew {self.domain_to_renew.name}")
|
|
|
|
def test_domain_renewal_form_and_sidebar_expired(self):
|
|
"""If a user is a domain manager and their domain is expired,
|
|
user should be able to see Renewal Form on the sidebar."""
|
|
self.client.force_login(self.user)
|
|
|
|
with patch.object(Domain, "is_expired", self.custom_is_expired_true), patch.object(
|
|
Domain, "is_expired", self.custom_is_expired_true
|
|
):
|
|
# Grab the detail page
|
|
detail_page = self.client.get(
|
|
reverse("domain", kwargs={"domain_pk": self.domain_to_renew.id}),
|
|
)
|
|
|
|
# Make sure we see the link as a domain manager
|
|
self.assertContains(detail_page, "Renew to maintain access")
|
|
|
|
# Make sure we can see Renewal form on the sidebar since it's expired
|
|
self.assertContains(detail_page, "Renewal form")
|
|
|
|
# Grab link to the renewal page
|
|
renewal_form_url = reverse("domain-renewal", kwargs={"domain_pk": self.domain_to_renew.id})
|
|
self.assertContains(detail_page, f'href="{renewal_form_url}"')
|
|
|
|
# Simulate clicking the link
|
|
response = self.client.get(renewal_form_url)
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertContains(response, f"Renew {self.domain_to_renew.name}")
|
|
|
|
def test_domain_renewal_form_your_contact_info_edit(self):
|
|
"""Checking that if a user is a domain manager they can edit the
|
|
Your Profile portion of the Renewal Form."""
|
|
with less_console_noise():
|
|
# Start on the Renewal page for the domain
|
|
renewal_page = self.app.get(reverse("domain-renewal", kwargs={"domain_pk": self.domain_with_ip.id}))
|
|
|
|
# Verify we see "Your contact information" on the renewal form
|
|
self.assertContains(renewal_page, "Your contact information")
|
|
|
|
# Verify that the "Edit" button for Your contact is there and links to correct URL
|
|
edit_button_url = reverse("user-profile")
|
|
self.assertContains(renewal_page, f'href="{edit_button_url}"')
|
|
|
|
# Simulate clicking on edit button
|
|
edit_page = renewal_page.click(href=edit_button_url, index=1)
|
|
self.assertEqual(edit_page.status_code, 200)
|
|
self.assertContains(edit_page, "Review the details below and update any required information")
|
|
|
|
def test_domain_renewal_form_security_email_edit(self):
|
|
"""Checking that if a user is a domain manager they can edit the
|
|
Security Email portion of the Renewal Form."""
|
|
with less_console_noise():
|
|
# Start on the Renewal page for the domain
|
|
renewal_page = self.app.get(reverse("domain-renewal", kwargs={"domain_pk": self.domain_with_ip.id}))
|
|
|
|
# Verify we see "Security email" on the renewal form
|
|
self.assertContains(renewal_page, "Security email")
|
|
|
|
# Verify we see "strong recommend" blurb
|
|
self.assertContains(renewal_page, "We strongly recommend that you provide a security email.")
|
|
|
|
# Verify that the "Edit" button for Security email is there and links to correct URL
|
|
edit_button_url = reverse("domain-security-email", kwargs={"domain_pk": self.domain_with_ip.id})
|
|
self.assertContains(renewal_page, f'href="{edit_button_url}"')
|
|
|
|
# Simulate clicking on edit button
|
|
edit_page = renewal_page.click(href=edit_button_url, index=1)
|
|
self.assertEqual(edit_page.status_code, 200)
|
|
self.assertContains(edit_page, "A security contact should be capable of evaluating")
|
|
|
|
def test_domain_renewal_form_domain_manager_edit(self):
|
|
"""Checking that if a user is a domain manager they can edit the
|
|
Domain Manager portion of the Renewal Form."""
|
|
with less_console_noise():
|
|
# Start on the Renewal page for the domain
|
|
renewal_page = self.app.get(reverse("domain-renewal", kwargs={"domain_pk": self.domain_with_ip.id}))
|
|
|
|
# Verify we see "Domain managers" on the renewal form
|
|
self.assertContains(renewal_page, "Domain managers")
|
|
|
|
# Verify that the "Edit" button for Domain managers is there and links to correct URL
|
|
edit_button_url = reverse("domain-users", kwargs={"domain_pk": self.domain_with_ip.id})
|
|
self.assertContains(renewal_page, f'href="{edit_button_url}"')
|
|
|
|
# Simulate clicking on edit button
|
|
edit_page = renewal_page.click(href=edit_button_url, index=1)
|
|
self.assertEqual(edit_page.status_code, 200)
|
|
self.assertContains(edit_page, "Domain managers can update all information related to a domain")
|
|
|
|
def test_domain_renewal_form_not_expired_or_expiring(self):
|
|
"""Checking that if the user's domain is not expired or expiring that user should not be able
|
|
to access /renewal and that it should receive a 403."""
|
|
with less_console_noise():
|
|
# Start on the Renewal page for the domain
|
|
renewal_page = self.client.get(reverse("domain-renewal", kwargs={"domain_pk": self.domain_not_expiring.id}))
|
|
self.assertEqual(renewal_page.status_code, 403)
|
|
|
|
def test_domain_renewal_form_does_not_appear_if_not_domain_manager(self):
|
|
"""If user is not a domain manager and tries to access /renewal, user should receive a 403."""
|
|
with patch.object(Domain, "is_expired", self.custom_is_expired_true), patch.object(
|
|
Domain, "is_expired", self.custom_is_expired_true
|
|
):
|
|
renewal_page = self.client.get(
|
|
reverse("domain-renewal", kwargs={"domain_pk": self.domain_no_domain_manager.id})
|
|
)
|
|
self.assertEqual(renewal_page.status_code, 403)
|
|
|
|
def test_ack_checkbox_not_checked(self):
|
|
"""If user don't check the checkbox, user should receive an error message."""
|
|
# Grab the renewal URL
|
|
renewal_url = reverse("domain-renewal", kwargs={"domain_pk": self.domain_with_ip.id})
|
|
|
|
# Test that the checkbox is not checked
|
|
response = self.client.post(renewal_url, data={"submit_button": "next"})
|
|
|
|
error_message = "Check the box if you read and agree to the requirements for operating a .gov domain."
|
|
self.assertContains(response, error_message)
|
|
|
|
def test_ack_checkbox_checked(self):
|
|
"""If user check the checkbox and submits the form,
|
|
user should be redirected Domain Over page with an updated by 1 year expiration date"""
|
|
# Grab the renewal URL
|
|
with patch.object(Domain, "renew_domain", self.custom_renew_domain):
|
|
renewal_url = reverse("domain-renewal", kwargs={"domain_pk": self.domain_with_ip.id})
|
|
|
|
# Click the check, and submit
|
|
response = self.client.post(renewal_url, data={"is_policy_acknowledged": "on", "submit_button": "next"})
|
|
|
|
# Check that it redirects after a successfully submits
|
|
self.assertRedirects(response, reverse("domain", kwargs={"domain_pk": self.domain_with_ip.id}))
|
|
|
|
# Check for the updated expiration
|
|
formatted_new_expiration_date = self.expiration_date_one_year_out().strftime("%b. %-d, %Y")
|
|
redirect_response = self.client.get(
|
|
reverse("domain", kwargs={"domain_pk": self.domain_with_ip.id}), follow=True
|
|
)
|
|
self.assertContains(redirect_response, formatted_new_expiration_date)
|
|
|
|
|
|
class TestDomainManagers(TestDomainOverview):
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super().setUpClass()
|
|
allowed_emails = [
|
|
AllowedEmail(email=""),
|
|
AllowedEmail(email="testy@town.com"),
|
|
AllowedEmail(email="mayor@igorville.gov"),
|
|
AllowedEmail(email="testy2@town.com"),
|
|
]
|
|
AllowedEmail.objects.bulk_create(allowed_emails)
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
# Add portfolio in order to test portfolio view
|
|
self.portfolio = Portfolio.objects.create(creator=self.user, organization_name="Ice Cream")
|
|
# Add the portfolio to the domain_information object
|
|
self.domain_information.portfolio = self.portfolio
|
|
self.domain_information.save()
|
|
# Add portfolio perms to the user object
|
|
self.portfolio_permission, _ = UserPortfolioPermission.objects.get_or_create(
|
|
user=self.user, portfolio=self.portfolio, roles=[UserPortfolioRoleChoices.ORGANIZATION_ADMIN]
|
|
)
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
super().tearDownClass()
|
|
AllowedEmail.objects.all().delete()
|
|
|
|
def tearDown(self):
|
|
"""Ensure that the user has its original permissions"""
|
|
PortfolioInvitation.objects.all().delete()
|
|
UserPortfolioPermission.objects.all().delete()
|
|
UserDomainRole.objects.all().delete()
|
|
User.objects.exclude(id=self.user.id).delete()
|
|
super().tearDown()
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_managers(self):
|
|
response = self.client.get(reverse("domain-users", kwargs={"domain_pk": self.domain.id}))
|
|
self.assertContains(response, "Domain managers")
|
|
self.assertContains(response, "Add a domain manager")
|
|
# assert that the non-portfolio view contains Role column and doesn't contain Admin
|
|
self.assertContains(response, "Role</th>")
|
|
self.assertNotContains(response, "Admin")
|
|
self.assertContains(response, "This domain has one manager. Adding more can prevent issues.")
|
|
|
|
@less_console_noise_decorator
|
|
@override_flag("organization_feature", active=True)
|
|
def test_domain_managers_portfolio_view(self):
|
|
response = self.client.get(reverse("domain-users", kwargs={"domain_pk": self.domain.id}))
|
|
self.assertContains(response, "Domain managers")
|
|
self.assertContains(response, "Add a domain manager")
|
|
# assert that the portfolio view doesn't contain Role column and does contain Admin
|
|
self.assertNotContains(response, "Role</th>")
|
|
self.assertContains(response, "Admin")
|
|
self.assertContains(response, "This domain has one manager. Adding more can prevent issues.")
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_user_add(self):
|
|
response = self.client.get(reverse("domain-users-add", kwargs={"domain_pk": self.domain.id}))
|
|
self.assertContains(response, "Add a domain manager")
|
|
|
|
@less_console_noise_decorator
|
|
@patch("registrar.views.domain.send_domain_invitation_email")
|
|
def test_domain_user_add_form(self, mock_send_domain_email):
|
|
"""Adding an existing user works."""
|
|
get_user_model().objects.get_or_create(email="mayor@igorville.gov")
|
|
user = User.objects.filter(email="mayor@igorville.gov").first()
|
|
add_page = self.app.get(reverse("domain-users-add", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
|
|
add_page.form["email"] = "mayor@igorville.gov"
|
|
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
|
|
success_result = add_page.form.submit()
|
|
|
|
mock_send_domain_email.assert_called_once_with(
|
|
email="mayor@igorville.gov",
|
|
requestor=self.user,
|
|
domains=self.domain,
|
|
is_member_of_different_org=None,
|
|
requested_user=user,
|
|
)
|
|
|
|
self.assertEqual(success_result.status_code, 302)
|
|
self.assertEqual(
|
|
success_result["Location"],
|
|
reverse("domain-users", kwargs={"domain_pk": self.domain.id}),
|
|
)
|
|
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
success_page = success_result.follow()
|
|
self.assertContains(success_page, "mayor@igorville.gov")
|
|
|
|
@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="mayor@igorville.gov")
|
|
add_page = self.app.get(reverse("domain-users-add", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
|
|
add_page.form["email"] = "mayor@igorville.gov"
|
|
|
|
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={"domain_pk": self.domain.id}),
|
|
)
|
|
|
|
# Verify that the invitation emails were sent
|
|
mock_send_portfolio_email.assert_called_once_with(
|
|
email="mayor@igorville.gov",
|
|
requestor=self.user,
|
|
portfolio=self.portfolio,
|
|
is_admin_invitation=False,
|
|
)
|
|
mock_send_domain_email.assert_called_once()
|
|
call_args = mock_send_domain_email.call_args.kwargs
|
|
self.assertEqual(call_args["email"], "mayor@igorville.gov")
|
|
self.assertEqual(call_args["requestor"], self.user)
|
|
self.assertEqual(call_args["domains"], self.domain)
|
|
self.assertIsNone(call_args.get("is_member_of_different_org"))
|
|
|
|
# Assert that the PortfolioInvitation is created and retrieved
|
|
portfolio_invitation = PortfolioInvitation.objects.filter(
|
|
email="mayor@igorville.gov", portfolio=self.portfolio
|
|
).first()
|
|
self.assertIsNotNone(portfolio_invitation, "Portfolio invitation should be created.")
|
|
self.assertEqual(portfolio_invitation.email, "mayor@igorville.gov")
|
|
self.assertEqual(portfolio_invitation.portfolio, self.portfolio)
|
|
self.assertEqual(portfolio_invitation.status, PortfolioInvitation.PortfolioInvitationStatus.RETRIEVED)
|
|
|
|
# Assert that the UserPortfolioPermission is created
|
|
user_portfolio_permission = UserPortfolioPermission.objects.filter(
|
|
user=self.user, portfolio=self.portfolio
|
|
).first()
|
|
self.assertIsNotNone(user_portfolio_permission, "User portfolio permission should be created")
|
|
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
success_page = success_result.follow()
|
|
self.assertContains(success_page, "mayor@igorville.gov")
|
|
|
|
@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_to_new_email(
|
|
self, mock_send_domain_email, mock_send_portfolio_email
|
|
):
|
|
"""Adding an email not associated with a user works and sends portfolio invitation."""
|
|
add_page = self.app.get(reverse("domain-users-add", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
|
|
add_page.form["email"] = "notauser@igorville.gov"
|
|
|
|
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={"domain_pk": self.domain.id}),
|
|
)
|
|
|
|
# Verify that the invitation emails were sent
|
|
mock_send_portfolio_email.assert_called_once_with(
|
|
email="notauser@igorville.gov",
|
|
requestor=self.user,
|
|
portfolio=self.portfolio,
|
|
is_admin_invitation=False,
|
|
)
|
|
mock_send_domain_email.assert_called_once()
|
|
call_args = mock_send_domain_email.call_args.kwargs
|
|
self.assertEqual(call_args["email"], "notauser@igorville.gov")
|
|
self.assertEqual(call_args["requestor"], self.user)
|
|
self.assertEqual(call_args["domains"], self.domain)
|
|
self.assertIsNone(call_args.get("is_member_of_different_org"))
|
|
|
|
# Assert that the PortfolioInvitation is created
|
|
portfolio_invitation = PortfolioInvitation.objects.filter(
|
|
email="notauser@igorville.gov", portfolio=self.portfolio
|
|
).first()
|
|
self.assertIsNotNone(portfolio_invitation, "Portfolio invitation should be created.")
|
|
self.assertEqual(portfolio_invitation.email, "notauser@igorville.gov")
|
|
self.assertEqual(portfolio_invitation.portfolio, self.portfolio)
|
|
self.assertEqual(portfolio_invitation.status, PortfolioInvitation.PortfolioInvitationStatus.INVITED)
|
|
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
success_page = success_result.follow()
|
|
self.assertContains(success_page, "notauser@igorville.gov")
|
|
|
|
@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_fails_to_send_to_some_managers(
|
|
self, mock_send_domain_email, mock_send_portfolio_email
|
|
):
|
|
"""Adding an email not associated with a user works and sends portfolio invitation,
|
|
and when domain managers email(s) fail to send, assert proper warning displayed."""
|
|
add_page = self.app.get(reverse("domain-users-add", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
|
|
add_page.form["email"] = "notauser@igorville.gov"
|
|
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
|
|
mock_send_domain_email.return_value = False
|
|
|
|
success_result = add_page.form.submit()
|
|
|
|
self.assertEqual(success_result.status_code, 302)
|
|
self.assertEqual(
|
|
success_result["Location"],
|
|
reverse("domain-users", kwargs={"domain_pk": self.domain.id}),
|
|
)
|
|
|
|
# Verify that the invitation emails were sent
|
|
mock_send_portfolio_email.assert_called_once()
|
|
mock_send_domain_email.assert_called_once()
|
|
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
success_page = success_result.follow()
|
|
self.assertContains(success_page, "Could not send email confirmation to existing domain managers.")
|
|
|
|
@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="mayor@igorville.gov")
|
|
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={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
|
|
add_page.form["email"] = "mayor@igorville.gov"
|
|
|
|
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={"domain_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"], "mayor@igorville.gov")
|
|
self.assertEqual(call_args["requestor"], self.user)
|
|
self.assertEqual(call_args["domains"], 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="mayor@igorville.gov", 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, "mayor@igorville.gov")
|
|
|
|
@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="mayor@igorville.gov")
|
|
add_page = self.app.get(reverse("domain-users-add", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
|
|
add_page.form["email"] = "mayor@igorville.gov"
|
|
|
|
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={"domain_pk": self.domain.id}),
|
|
)
|
|
|
|
# Verify that the invitation emails were sent
|
|
mock_send_portfolio_email.assert_called_once_with(
|
|
email="mayor@igorville.gov",
|
|
requestor=self.user,
|
|
portfolio=self.portfolio,
|
|
is_admin_invitation=False,
|
|
)
|
|
mock_send_domain_email.assert_not_called()
|
|
|
|
# Assert that no PortfolioInvitation is created
|
|
portfolio_invitation_exists = PortfolioInvitation.objects.filter(
|
|
email="mayor@igorville.gov", 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, "Failed to send email.")
|
|
|
|
@boto3_mocking.patching
|
|
@less_console_noise_decorator
|
|
@patch("registrar.views.domain.send_templated_email")
|
|
def test_domain_remove_manager(self, mock_send_templated_email):
|
|
"""Removing a domain manager sends notification email to other domain managers."""
|
|
self.manager, _ = User.objects.get_or_create(email="mayor@igorville.com", first_name="Hello", last_name="World")
|
|
self.manager_domain_permission, _ = UserDomainRole.objects.get_or_create(user=self.manager, domain=self.domain)
|
|
self.client.post(
|
|
reverse("domain-user-delete", kwargs={"domain_pk": self.domain.id, "user_pk": self.manager.id})
|
|
)
|
|
|
|
# Verify that the notification emails were sent to domain manager
|
|
mock_send_templated_email.assert_called_once_with(
|
|
"emails/domain_manager_deleted_notification.txt",
|
|
"emails/domain_manager_deleted_notification_subject.txt",
|
|
to_address="info@example.com",
|
|
context=ANY,
|
|
)
|
|
|
|
@less_console_noise_decorator
|
|
@patch("registrar.views.domain.send_domain_invitation_email")
|
|
def test_domain_invitation_created(self, mock_send_domain_email):
|
|
"""Add user on a nonexistent email creates an invitation.
|
|
|
|
Adding a non-existent user sends an email as a side-effect, so mock
|
|
out send_domain_invitation_email here.
|
|
"""
|
|
# make sure there is no user with this email
|
|
email_address = "mayor@igorville.gov"
|
|
User.objects.filter(email=email_address).delete()
|
|
|
|
self.domain_information, _ = DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain)
|
|
|
|
add_page = self.app.get(reverse("domain-users-add", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
add_page.form["email"] = email_address
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
|
|
success_result = add_page.form.submit()
|
|
|
|
mock_send_domain_email.assert_called_once_with(
|
|
email="mayor@igorville.gov", requestor=self.user, domains=self.domain, is_member_of_different_org=None
|
|
)
|
|
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
success_page = success_result.follow()
|
|
|
|
self.assertContains(success_page, email_address)
|
|
self.assertContains(success_page, "Cancel") # link to cancel invitation
|
|
self.assertTrue(DomainInvitation.objects.filter(email=email_address).exists())
|
|
|
|
@less_console_noise_decorator
|
|
@patch("registrar.views.domain.send_domain_invitation_email")
|
|
def test_domain_invitation_created_for_caps_email(self, mock_send_domain_email):
|
|
"""Add user on a nonexistent email with CAPS creates an invitation to lowercase email.
|
|
|
|
Adding a non-existent user sends an email as a side-effect, so mock
|
|
out send_domain_invitation_email here.
|
|
"""
|
|
# make sure there is no user with this email
|
|
email_address = "mayor@igorville.gov"
|
|
caps_email_address = "MAYOR@igorville.gov"
|
|
User.objects.filter(email=email_address).delete()
|
|
|
|
self.domain_information, _ = DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain)
|
|
|
|
add_page = self.app.get(reverse("domain-users-add", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
add_page.form["email"] = caps_email_address
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
|
|
success_result = add_page.form.submit()
|
|
|
|
mock_send_domain_email.assert_called_once_with(
|
|
email="mayor@igorville.gov", requestor=self.user, domains=self.domain, is_member_of_different_org=None
|
|
)
|
|
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
success_page = success_result.follow()
|
|
|
|
self.assertContains(success_page, email_address)
|
|
self.assertContains(success_page, "Cancel") # link to cancel invitation
|
|
self.assertTrue(DomainInvitation.objects.filter(email=email_address).exists())
|
|
|
|
@boto3_mocking.patching
|
|
@less_console_noise_decorator
|
|
def test_domain_invitation_email_sent(self):
|
|
"""Inviting a non-existent user sends them an email."""
|
|
# make sure there is no user with this email
|
|
email_address = "mayor@igorville.gov"
|
|
allowed_email, _ = AllowedEmail.objects.get_or_create(email=email_address)
|
|
User.objects.filter(email=email_address).delete()
|
|
|
|
self.domain_information, _ = DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain)
|
|
|
|
mock_client = MagicMock()
|
|
mock_client_instance = mock_client.return_value
|
|
with boto3_mocking.clients.handler_for("sesv2", mock_client):
|
|
add_page = self.app.get(reverse("domain-users-add", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
add_page.form["email"] = email_address
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
add_page.form.submit()
|
|
|
|
# check the mock instance to see if `send_email` was called right
|
|
mock_client_instance.send_email.assert_called_once_with(
|
|
FromEmailAddress=settings.DEFAULT_FROM_EMAIL,
|
|
Destination={"ToAddresses": [email_address]},
|
|
Content=ANY,
|
|
)
|
|
allowed_email.delete()
|
|
|
|
@boto3_mocking.patching
|
|
@less_console_noise_decorator
|
|
def test_domain_invitation_email_has_email_as_requestor_non_existent(self):
|
|
"""Inviting a non existent user sends them an email, with email as the name."""
|
|
# make sure there is no user with this email
|
|
email_address = "mayor@igorville.gov"
|
|
User.objects.filter(email=email_address).delete()
|
|
|
|
self.domain_information, _ = DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain)
|
|
|
|
mock_client = MagicMock()
|
|
mock_client_instance = mock_client.return_value
|
|
|
|
with boto3_mocking.clients.handler_for("sesv2", mock_client):
|
|
add_page = self.app.get(reverse("domain-users-add", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
add_page.form["email"] = email_address
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
add_page.form.submit()
|
|
|
|
# check the mock instance to see if `send_email` was called right
|
|
mock_client_instance.send_email.assert_called_once_with(
|
|
FromEmailAddress=settings.DEFAULT_FROM_EMAIL,
|
|
Destination={"ToAddresses": [email_address]},
|
|
Content=ANY,
|
|
)
|
|
|
|
# Check the arguments passed to send_email method
|
|
_, kwargs = mock_client_instance.send_email.call_args
|
|
|
|
# Extract the email content, and check that the message is as we expect
|
|
email_content = kwargs["Content"]["Simple"]["Body"]["Text"]["Data"]
|
|
self.assertIn("info@example.com", email_content)
|
|
|
|
# Check that the requestors first/last name do not exist
|
|
self.assertNotIn("First", email_content)
|
|
self.assertNotIn("Last", email_content)
|
|
self.assertNotIn("First Last", email_content)
|
|
|
|
@boto3_mocking.patching
|
|
@less_console_noise_decorator
|
|
def test_domain_invitation_email_has_email_as_requestor(self):
|
|
"""Inviting a user sends them an email, with email as the name."""
|
|
# Create a fake user object
|
|
email_address = "mayor@igorville.gov"
|
|
User.objects.get_or_create(email=email_address, username="fakeuser@fakeymail.com")
|
|
|
|
self.domain_information, _ = DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain)
|
|
|
|
mock_client = MagicMock()
|
|
mock_client_instance = mock_client.return_value
|
|
|
|
with boto3_mocking.clients.handler_for("sesv2", mock_client):
|
|
add_page = self.app.get(reverse("domain-users-add", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
add_page.form["email"] = email_address
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
add_page.form.submit()
|
|
|
|
# check the mock instance to see if `send_email` was called right
|
|
mock_client_instance.send_email.assert_called_once_with(
|
|
FromEmailAddress=settings.DEFAULT_FROM_EMAIL,
|
|
Destination={"ToAddresses": [email_address]},
|
|
Content=ANY,
|
|
)
|
|
|
|
# Check the arguments passed to send_email method
|
|
_, kwargs = mock_client_instance.send_email.call_args
|
|
|
|
# Extract the email content, and check that the message is as we expect
|
|
email_content = kwargs["Content"]["Simple"]["Body"]["Text"]["Data"]
|
|
self.assertIn("info@example.com", email_content)
|
|
|
|
# Check that the requestors first/last name do not exist
|
|
self.assertNotIn("First", email_content)
|
|
self.assertNotIn("Last", email_content)
|
|
self.assertNotIn("First Last", email_content)
|
|
|
|
@boto3_mocking.patching
|
|
@less_console_noise_decorator
|
|
def test_domain_invitation_email_has_email_as_requestor_staff(self):
|
|
"""Inviting a user sends them an email, with email as the name."""
|
|
# Create a fake user object
|
|
email_address = "mayor@igorville.gov"
|
|
AllowedEmail.objects.get_or_create(email=email_address)
|
|
User.objects.get_or_create(email=email_address, username="fakeuser@fakeymail.com")
|
|
|
|
# Make sure the user is staff
|
|
self.user.is_staff = True
|
|
self.user.save()
|
|
|
|
self.domain_information, _ = DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain)
|
|
|
|
mock_client = MagicMock()
|
|
mock_client_instance = mock_client.return_value
|
|
|
|
with boto3_mocking.clients.handler_for("sesv2", mock_client):
|
|
add_page = self.app.get(reverse("domain-users-add", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
add_page.form["email"] = email_address
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
add_page.form.submit()
|
|
|
|
# check the mock instance to see if `send_email` was called right
|
|
mock_client_instance.send_email.assert_called_once_with(
|
|
FromEmailAddress=settings.DEFAULT_FROM_EMAIL,
|
|
Destination={"ToAddresses": [email_address]},
|
|
Content=ANY,
|
|
)
|
|
|
|
# Check the arguments passed to send_email method
|
|
_, kwargs = mock_client_instance.send_email.call_args
|
|
|
|
# Extract the email content, and check that the message is as we expect
|
|
email_content = kwargs["Content"]["Simple"]["Body"]["Text"]["Data"]
|
|
self.assertIn("help@get.gov", email_content)
|
|
|
|
# Check that the requestors first/last name do not exist
|
|
self.assertNotIn("First", email_content)
|
|
self.assertNotIn("Last", email_content)
|
|
self.assertNotIn("First Last", email_content)
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_invitation_email_validation_blocks_bad_email(self):
|
|
"""Inviting a bad email blocks at validation."""
|
|
email_address = "mayor"
|
|
self.domain_information, _ = DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain)
|
|
|
|
add_page = self.app.get(reverse("domain-users-add", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
add_page.form["email"] = email_address
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
response = add_page.form.submit()
|
|
|
|
self.assertContains(response, "Enter an email address in the required format, like name@example.com.")
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_invitation_email_displays_error(self):
|
|
"""When the requesting user has no email, an error is displayed"""
|
|
# make sure there is no user with this email
|
|
# Create a fake user object
|
|
email_address = "mayor@igorville.gov"
|
|
User.objects.get_or_create(email=email_address, username="fakeuser@fakeymail.com")
|
|
|
|
# Give the user who is sending the email an invalid email address
|
|
self.user.email = ""
|
|
self.user.is_staff = False
|
|
self.user.save()
|
|
|
|
self.domain_information, _ = DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain)
|
|
|
|
with patch("django.contrib.messages.error") as mock_error:
|
|
add_page = self.app.get(reverse("domain-users-add", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
add_page.form["email"] = email_address
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
add_page.form.submit()
|
|
|
|
expected_message_content = "Can't send invitation email. No email is associated with your user account."
|
|
|
|
# Assert that the error message was called with the correct argument
|
|
mock_error.assert_called_once_with(
|
|
ANY,
|
|
expected_message_content,
|
|
)
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_invitation_cancel(self):
|
|
"""Posting to the delete view deletes an invitation."""
|
|
email_address = "mayor@igorville.gov"
|
|
invitation, _ = DomainInvitation.objects.get_or_create(domain=self.domain, email=email_address)
|
|
self.client.post(reverse("invitation-cancel", kwargs={"domain_invitation_pk": invitation.id}))
|
|
invitation = DomainInvitation.objects.get(id=invitation.id)
|
|
self.assertEqual(invitation.status, DomainInvitation.DomainInvitationStatus.CANCELED)
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_invitation_cancel_retrieved_invitation(self):
|
|
"""Posting to the cancel view when invitation retrieved returns an error message"""
|
|
email_address = "mayor@igorville.gov"
|
|
invitation, _ = DomainInvitation.objects.get_or_create(
|
|
domain=self.domain, email=email_address, status=DomainInvitation.DomainInvitationStatus.RETRIEVED
|
|
)
|
|
response = self.client.post(
|
|
reverse("invitation-cancel", kwargs={"domain_invitation_pk": invitation.id}), follow=True
|
|
)
|
|
# Assert that an error message is displayed to the user
|
|
self.assertContains(response, f"Invitation to {email_address} has already been retrieved.")
|
|
# Assert that the Cancel link (form) is not displayed
|
|
self.assertNotContains(response, f"/invitation/{invitation.id}/cancel")
|
|
# Assert that the DomainInvitation is not deleted
|
|
self.assertTrue(DomainInvitation.objects.filter(id=invitation.id).exists())
|
|
DomainInvitation.objects.filter(email=email_address).delete()
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_invitation_cancel_no_permissions(self):
|
|
"""Posting to the cancel view as a different user should fail."""
|
|
email_address = "mayor@igorville.gov"
|
|
invitation, _ = DomainInvitation.objects.get_or_create(domain=self.domain, email=email_address)
|
|
|
|
other_user = create_user()
|
|
other_user.save()
|
|
self.client.force_login(other_user)
|
|
mock_client = MagicMock()
|
|
with boto3_mocking.clients.handler_for("sesv2", mock_client):
|
|
result = self.client.post(reverse("invitation-cancel", kwargs={"domain_invitation_pk": invitation.id}))
|
|
|
|
self.assertEqual(result.status_code, 403)
|
|
|
|
@boto3_mocking.patching
|
|
@less_console_noise_decorator
|
|
def test_domain_invitation_flow(self):
|
|
"""Send an invitation to a new user, log in and load the dashboard."""
|
|
email_address = "mayor@igorville.gov"
|
|
username = "mayor"
|
|
first_name = "First"
|
|
last_name = "Last"
|
|
title = "title"
|
|
phone = "8080102431"
|
|
title = "title"
|
|
User.objects.filter(email=email_address).delete()
|
|
|
|
add_page = self.app.get(reverse("domain-users-add", kwargs={"domain_pk": self.domain.id}))
|
|
|
|
self.domain_information, _ = DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain)
|
|
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
add_page.form["email"] = email_address
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
|
|
mock_client = MagicMock()
|
|
with boto3_mocking.clients.handler_for("sesv2", mock_client):
|
|
add_page.form.submit()
|
|
|
|
# user was invited, create them
|
|
new_user = User.objects.create(
|
|
username=username, email=email_address, first_name=first_name, last_name=last_name, title=title, phone=phone
|
|
)
|
|
# log them in to `self.app`
|
|
self.app.set_user(new_user.username)
|
|
# and manually call the on each login callback
|
|
new_user.on_each_login()
|
|
|
|
# Now load the home page and make sure our domain appears there
|
|
home_page = self.app.get(reverse("home"))
|
|
self.assertContains(home_page, self.domain.name)
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_user_role_delete(self):
|
|
"""Posting to the delete view deletes a user domain role."""
|
|
# add two managers to the domain so that one can be successfully deleted
|
|
email_address = "mayor@igorville.gov"
|
|
new_user = User.objects.create(email=email_address, username="mayor")
|
|
email_address_2 = "secondmayor@igorville.gov"
|
|
new_user_2 = User.objects.create(email=email_address_2, username="secondmayor")
|
|
user_domain_role = UserDomainRole.objects.create(
|
|
user=new_user, domain=self.domain, role=UserDomainRole.Roles.MANAGER
|
|
)
|
|
UserDomainRole.objects.create(user=new_user_2, domain=self.domain, role=UserDomainRole.Roles.MANAGER)
|
|
response = self.client.post(
|
|
reverse("domain-user-delete", kwargs={"domain_pk": self.domain.id, "user_pk": new_user.id}), follow=True
|
|
)
|
|
# Assert that a success message is displayed to the user
|
|
self.assertContains(response, f"Removed {email_address} as a manager for this domain.")
|
|
# Assert that the second user is displayed
|
|
self.assertContains(response, f"{email_address_2}")
|
|
# Assert that the UserDomainRole is deleted
|
|
self.assertFalse(UserDomainRole.objects.filter(id=user_domain_role.id).exists())
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_user_role_delete_only_manager(self):
|
|
"""Posting to the delete view attempts to delete a user domain role when there is only one manager."""
|
|
# self.user is the only domain manager, so attempt to delete it
|
|
response = self.client.post(
|
|
reverse("domain-user-delete", kwargs={"domain_pk": self.domain.id, "user_pk": self.user.id}), follow=True
|
|
)
|
|
# Assert that an error message is displayed to the user
|
|
self.assertContains(response, "Domains must have at least one domain manager.")
|
|
# Assert that the user is still displayed
|
|
self.assertContains(response, f"{self.user.email}")
|
|
# Assert that the UserDomainRole still exists
|
|
self.assertTrue(UserDomainRole.objects.filter(user=self.user, domain=self.domain).exists())
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_user_role_delete_self_delete(self):
|
|
"""Posting to the delete view attempts to delete a user domain role when there is only one manager."""
|
|
# add one manager, so there are two and the logged in user, self.user, can be deleted
|
|
email_address = "mayor@igorville.gov"
|
|
new_user = User.objects.create(email=email_address, username="mayor")
|
|
UserDomainRole.objects.create(user=new_user, domain=self.domain, role=UserDomainRole.Roles.MANAGER)
|
|
response = self.client.post(
|
|
reverse("domain-user-delete", kwargs={"domain_pk": self.domain.id, "user_pk": self.user.id}), follow=True
|
|
)
|
|
# Assert that a success message is displayed to the user
|
|
self.assertContains(response, f"You are no longer managing the domain {self.domain}.")
|
|
# Assert that the UserDomainRole no longer exists
|
|
self.assertFalse(UserDomainRole.objects.filter(user=self.user, domain=self.domain).exists())
|
|
|
|
|
|
class TestDomainNameservers(TestDomainOverview, MockEppLib):
|
|
@less_console_noise_decorator
|
|
def test_domain_nameservers(self):
|
|
"""Can load domain's nameservers page."""
|
|
page = self.client.get(reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}))
|
|
self.assertContains(page, "DNS name servers")
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_nameservers_form_submit_one_nameserver(self):
|
|
"""Nameserver form submitted with one nameserver throws error.
|
|
|
|
Uses self.app WebTest because we need to interact with forms.
|
|
"""
|
|
# initial nameservers page has one server with two ips
|
|
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
# attempt to submit the form with only one nameserver, should error
|
|
# regarding required fields
|
|
result = nameservers_page.form.submit()
|
|
# form submission was a post with an error, response should be a 200
|
|
# error text appears twice, once at the top of the page, once around
|
|
# the required field. form requires a minimum of 2 name servers
|
|
self.assertContains(
|
|
result,
|
|
"At least two name servers are required.",
|
|
count=2,
|
|
status_code=200,
|
|
)
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_nameservers_form_submit_subdomain_missing_ip(self):
|
|
"""Nameserver form catches missing ip error on subdomain.
|
|
|
|
Uses self.app WebTest because we need to interact with forms.
|
|
"""
|
|
# initial nameservers page has one server with two ips
|
|
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
# attempt to submit the form without two hosts, both subdomains,
|
|
# only one has ips
|
|
nameservers_page.form["form-1-server"] = "ns2.igorville.gov"
|
|
|
|
result = nameservers_page.form.submit()
|
|
# form submission was a post with an error, response should be a 200
|
|
# error text appears twice, once at the top of the page, once around
|
|
# the required field. subdomain missing an ip
|
|
self.assertContains(
|
|
result,
|
|
str(NameserverError(code=NameserverErrorCodes.MISSING_IP)),
|
|
count=2,
|
|
status_code=200,
|
|
)
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_nameservers_form_submit_missing_host(self):
|
|
"""Nameserver form catches error when host is missing.
|
|
|
|
Uses self.app WebTest because we need to interact with forms.
|
|
"""
|
|
# initial nameservers page has one server with two ips
|
|
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
# attempt to submit the form without two hosts, both subdomains,
|
|
# only one has ips
|
|
nameservers_page.form["form-1-ip"] = "127.0.0.1"
|
|
result = nameservers_page.form.submit()
|
|
# form submission was a post with an error, response should be a 200
|
|
# error text appears twice, once at the top of the page, once around
|
|
# the required field. nameserver has ip but missing host
|
|
self.assertContains(
|
|
result,
|
|
str(NameserverError(code=NameserverErrorCodes.MISSING_HOST)),
|
|
count=2,
|
|
status_code=200,
|
|
)
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_nameservers_form_submit_duplicate_host(self):
|
|
"""Nameserver form catches error when host is duplicated.
|
|
|
|
Uses self.app WebTest because we need to interact with forms.
|
|
"""
|
|
# initial nameservers page has one server with two ips
|
|
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
# attempt to submit the form with duplicate host names of fake.host.com
|
|
nameservers_page.form["form-0-ip"] = ""
|
|
nameservers_page.form["form-1-server"] = "fake.host.com"
|
|
result = nameservers_page.form.submit()
|
|
# form submission was a post with an error, response should be a 200
|
|
# error text appears twice, once at the top of the page, once around
|
|
# the required field. remove duplicate entry
|
|
self.assertContains(
|
|
result,
|
|
str(NameserverError(code=NameserverErrorCodes.DUPLICATE_HOST)),
|
|
count=2,
|
|
status_code=200,
|
|
)
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_nameservers_form_submit_whitespace(self):
|
|
"""Nameserver form removes whitespace from ip.
|
|
|
|
Uses self.app WebTest because we need to interact with forms.
|
|
"""
|
|
nameserver1 = "ns1.igorville.gov"
|
|
nameserver2 = "ns2.igorville.gov"
|
|
valid_ip = "1.1. 1.1"
|
|
valid_ip_2 = "2.2. 2.2"
|
|
# have to throw an error in order to test that the whitespace has been stripped from ip
|
|
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
# attempt to submit the form without one host and an ip with whitespace
|
|
nameservers_page.form["form-0-server"] = nameserver1
|
|
nameservers_page.form["form-0-ip"] = valid_ip
|
|
nameservers_page.form["form-1-ip"] = valid_ip_2
|
|
nameservers_page.form["form-1-server"] = nameserver2
|
|
result = nameservers_page.form.submit()
|
|
# form submission was a post with an ip address which has been stripped of whitespace,
|
|
# response should be a 302 to success page
|
|
self.assertEqual(result.status_code, 302)
|
|
self.assertEqual(
|
|
result["Location"],
|
|
reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}),
|
|
)
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
page = result.follow()
|
|
# in the event of a generic nameserver error from registry error, there will be a 302
|
|
# with an error message displayed, so need to follow 302 and test for success message
|
|
self.assertContains(page, "The name servers for this domain have been updated")
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_nameservers_form_submit_glue_record_not_allowed(self):
|
|
"""Nameserver form catches error when IP is present
|
|
but host not subdomain.
|
|
|
|
Uses self.app WebTest because we need to interact with forms.
|
|
"""
|
|
nameserver1 = "ns1.igorville.gov"
|
|
nameserver2 = "ns2.igorville.com"
|
|
valid_ip = "127.0.0.1"
|
|
# initial nameservers page has one server with two ips
|
|
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
# attempt to submit the form without two hosts, both subdomains,
|
|
# only one has ips
|
|
nameservers_page.form["form-0-server"] = nameserver1
|
|
nameservers_page.form["form-1-server"] = nameserver2
|
|
nameservers_page.form["form-1-ip"] = valid_ip
|
|
result = nameservers_page.form.submit()
|
|
# form submission was a post with an error, response should be a 200
|
|
# error text appears twice, once at the top of the page, once around
|
|
# the required field. nameserver has ip but missing host
|
|
self.assertContains(
|
|
result,
|
|
str(NameserverError(code=NameserverErrorCodes.GLUE_RECORD_NOT_ALLOWED)),
|
|
count=2,
|
|
status_code=200,
|
|
)
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_nameservers_form_submit_invalid_ip(self):
|
|
"""Nameserver form catches invalid IP on submission.
|
|
|
|
Uses self.app WebTest because we need to interact with forms.
|
|
"""
|
|
nameserver = "ns2.igorville.gov"
|
|
invalid_ip = "123"
|
|
# initial nameservers page has one server with two ips
|
|
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
# attempt to submit the form without two hosts, both subdomains,
|
|
# only one has ips
|
|
nameservers_page.form["form-1-server"] = nameserver
|
|
nameservers_page.form["form-1-ip"] = invalid_ip
|
|
result = nameservers_page.form.submit()
|
|
# form submission was a post with an error, response should be a 200
|
|
# error text appears twice, once at the top of the page, once around
|
|
# the required field. nameserver has ip but missing host
|
|
self.assertContains(
|
|
result,
|
|
str(NameserverError(code=NameserverErrorCodes.INVALID_IP, nameserver=nameserver)),
|
|
count=2,
|
|
status_code=200,
|
|
)
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_nameservers_form_submit_invalid_host(self):
|
|
"""Nameserver form catches invalid host on submission.
|
|
|
|
Uses self.app WebTest because we need to interact with forms.
|
|
"""
|
|
nameserver = "invalid-nameserver.gov"
|
|
valid_ip = "123.2.45.111"
|
|
# initial nameservers page has one server with two ips
|
|
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
# attempt to submit the form without two hosts, both subdomains,
|
|
# only one has ips
|
|
nameservers_page.form["form-1-server"] = nameserver
|
|
nameservers_page.form["form-1-ip"] = valid_ip
|
|
result = nameservers_page.form.submit()
|
|
# form submission was a post with an error, response should be a 200
|
|
# error text appears twice, once at the top of the page, once around
|
|
# the required field. nameserver has invalid host
|
|
self.assertContains(
|
|
result,
|
|
str(NameserverError(code=NameserverErrorCodes.INVALID_HOST, nameserver=nameserver)),
|
|
count=2,
|
|
status_code=200,
|
|
)
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_nameservers_form_submits_successfully(self):
|
|
"""Nameserver form submits successfully with valid input.
|
|
|
|
Uses self.app WebTest because we need to interact with forms.
|
|
"""
|
|
nameserver1 = "ns1.igorville.gov"
|
|
nameserver2 = "ns2.igorville.gov"
|
|
valid_ip = "127.0.0.1"
|
|
valid_ip_2 = "128.0.0.2"
|
|
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
nameservers_page.form["form-0-server"] = nameserver1
|
|
nameservers_page.form["form-0-ip"] = valid_ip
|
|
nameservers_page.form["form-1-server"] = nameserver2
|
|
nameservers_page.form["form-1-ip"] = valid_ip_2
|
|
result = nameservers_page.form.submit()
|
|
# form submission was a successful post, response should be a 302
|
|
self.assertEqual(result.status_code, 302)
|
|
self.assertEqual(
|
|
result["Location"],
|
|
reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}),
|
|
)
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
page = result.follow()
|
|
self.assertContains(page, "The name servers for this domain have been updated")
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_nameservers_can_blank_out_first_or_second_one_if_enough_entries(self):
|
|
"""Nameserver form submits successfully with 2 valid inputs, even if the first or
|
|
second entries are blanked out.
|
|
|
|
Uses self.app WebTest because we need to interact with forms.
|
|
"""
|
|
|
|
nameserver1 = ""
|
|
nameserver2 = "ns2.igorville.gov"
|
|
nameserver3 = "ns3.igorville.gov"
|
|
valid_ip = ""
|
|
valid_ip_2 = "128.0.0.2"
|
|
valid_ip_3 = "128.0.0.3"
|
|
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
nameservers_page.form["form-0-server"] = nameserver1
|
|
nameservers_page.form["form-0-ip"] = valid_ip
|
|
nameservers_page.form["form-1-server"] = nameserver2
|
|
nameservers_page.form["form-1-ip"] = valid_ip_2
|
|
nameservers_page.form["form-2-server"] = nameserver3
|
|
nameservers_page.form["form-2-ip"] = valid_ip_3
|
|
result = nameservers_page.form.submit()
|
|
|
|
# form submission was a successful post, response should be a 302
|
|
self.assertEqual(result.status_code, 302)
|
|
self.assertEqual(
|
|
result["Location"],
|
|
reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}),
|
|
)
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
nameservers_page = result.follow()
|
|
self.assertContains(nameservers_page, "The name servers for this domain have been updated")
|
|
|
|
nameserver1 = "ns1.igorville.gov"
|
|
nameserver2 = ""
|
|
nameserver3 = "ns3.igorville.gov"
|
|
valid_ip = "128.0.0.1"
|
|
valid_ip_2 = ""
|
|
valid_ip_3 = "128.0.0.3"
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
nameservers_page.form["form-0-server"] = nameserver1
|
|
nameservers_page.form["form-0-ip"] = valid_ip
|
|
nameservers_page.form["form-1-server"] = nameserver2
|
|
nameservers_page.form["form-1-ip"] = valid_ip_2
|
|
nameservers_page.form["form-2-server"] = nameserver3
|
|
nameservers_page.form["form-2-ip"] = valid_ip_3
|
|
result = nameservers_page.form.submit()
|
|
|
|
# form submission was a successful post, response should be a 302
|
|
self.assertEqual(result.status_code, 302)
|
|
self.assertEqual(
|
|
result["Location"],
|
|
reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}),
|
|
)
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
nameservers_page = result.follow()
|
|
self.assertContains(nameservers_page, "The name servers for this domain have been updated")
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_nameservers_can_blank_out_first_and_second_one_if_enough_entries(self):
|
|
"""Nameserver form submits successfully with 2 valid inputs, even if the first and
|
|
second entries are blanked out.
|
|
|
|
Uses self.app WebTest because we need to interact with forms.
|
|
"""
|
|
|
|
# We need to start with a domain with 4 nameservers otherwise the formset in the test environment
|
|
# will only have 3 forms
|
|
nameserver1 = ""
|
|
nameserver2 = ""
|
|
nameserver3 = "ns3.igorville.gov"
|
|
nameserver4 = "ns4.igorville.gov"
|
|
valid_ip = ""
|
|
valid_ip_2 = ""
|
|
valid_ip_3 = ""
|
|
valid_ip_4 = ""
|
|
nameservers_page = self.app.get(
|
|
reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain_with_four_nameservers.id})
|
|
)
|
|
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
|
|
# Minimal check to ensure the form is loaded correctly
|
|
self.assertEqual(nameservers_page.form["form-0-server"].value, "ns1.my-nameserver-1.com")
|
|
self.assertEqual(nameservers_page.form["form-3-server"].value, "ns1.explosive-chicken-nuggets.com")
|
|
|
|
nameservers_page.form["form-0-server"] = nameserver1
|
|
nameservers_page.form["form-0-ip"] = valid_ip
|
|
nameservers_page.form["form-1-server"] = nameserver2
|
|
nameservers_page.form["form-1-ip"] = valid_ip_2
|
|
nameservers_page.form["form-2-server"] = nameserver3
|
|
nameservers_page.form["form-2-ip"] = valid_ip_3
|
|
nameservers_page.form["form-3-server"] = nameserver4
|
|
nameservers_page.form["form-3-ip"] = valid_ip_4
|
|
result = nameservers_page.form.submit()
|
|
|
|
# form submission was a successful post, response should be a 302
|
|
self.assertEqual(result.status_code, 302)
|
|
self.assertEqual(
|
|
result["Location"],
|
|
reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain_with_four_nameservers.id}),
|
|
)
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
nameservers_page = result.follow()
|
|
self.assertContains(nameservers_page, "The name servers for this domain have been updated")
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_nameservers_form_invalid(self):
|
|
"""Nameserver form does not submit with invalid data.
|
|
|
|
Uses self.app WebTest because we need to interact with forms.
|
|
"""
|
|
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
# first two nameservers are required, so if we empty one out we should
|
|
# get a form error
|
|
nameservers_page.form["form-0-server"] = ""
|
|
result = nameservers_page.form.submit()
|
|
# form submission was a post with an error, response should be a 200
|
|
# error text appears four times, twice at the top of the page,
|
|
# once around each required field.
|
|
self.assertContains(
|
|
result,
|
|
"At least two name servers are required.",
|
|
count=4,
|
|
status_code=200,
|
|
)
|
|
|
|
|
|
class TestDomainSeniorOfficial(TestDomainOverview):
|
|
@less_console_noise_decorator
|
|
def test_domain_senior_official(self):
|
|
"""Can load domain's senior official page."""
|
|
page = self.client.get(reverse("domain-senior-official", kwargs={"domain_pk": self.domain.id}))
|
|
self.assertContains(page, "Senior official", count=4)
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_senior_official_content(self):
|
|
"""Senior official information appears on the page."""
|
|
self.domain_information.senior_official = Contact(first_name="Testy")
|
|
self.domain_information.senior_official.save()
|
|
self.domain_information.save()
|
|
page = self.app.get(reverse("domain-senior-official", kwargs={"domain_pk": self.domain.id}))
|
|
self.assertContains(page, "Testy")
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_edit_senior_official_in_place(self):
|
|
"""When editing a senior official for domain information and SO is not
|
|
joined to any other objects"""
|
|
self.domain_information.senior_official = Contact(
|
|
first_name="Testy", last_name="Tester", title="CIO", email="nobody@igorville.gov"
|
|
)
|
|
self.domain_information.senior_official.save()
|
|
self.domain_information.save()
|
|
so_page = self.app.get(reverse("domain-senior-official", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
so_form = so_page.forms[0]
|
|
self.assertEqual(so_form["first_name"].value, "Testy")
|
|
so_form["first_name"] = "Testy2"
|
|
# so_pk is the initial pk of the senior official. set it before update
|
|
# to be able to verify after update that the same contact object is in place
|
|
so_pk = self.domain_information.senior_official.id
|
|
so_form.submit()
|
|
|
|
# refresh domain information
|
|
self.domain_information.refresh_from_db()
|
|
self.assertEqual("Testy2", self.domain_information.senior_official.first_name)
|
|
self.assertEqual(so_pk, self.domain_information.senior_official.id)
|
|
|
|
@less_console_noise_decorator
|
|
def assert_all_form_fields_have_expected_values(self, form, test_cases, test_for_disabled=False):
|
|
"""
|
|
Asserts that each specified form field has the expected value and, optionally, checks if the field is disabled.
|
|
|
|
This method iterates over a list of tuples, where each
|
|
tuple contains a field name and the expected value for that field.
|
|
It uses subtests to isolate each assertion, allowing multiple field
|
|
checks within a single test method without stopping at the first failure.
|
|
|
|
Example usage:
|
|
test_cases = [
|
|
("first_name", "John"),
|
|
("last_name", "Doe"),
|
|
("email", "john.doe@example.com"),
|
|
]
|
|
self.assert_all_form_fields_have_expected_values(my_form, test_cases, test_for_disabled=True)
|
|
"""
|
|
for field_name, expected_value in test_cases:
|
|
with self.subTest(field_name=field_name, expected_value=expected_value):
|
|
# Test that each field has the value we expect
|
|
self.assertEqual(expected_value, form[field_name].value)
|
|
|
|
if test_for_disabled:
|
|
# Test for disabled on each field
|
|
self.assertTrue("disabled" in form[field_name].attrs)
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_cannot_edit_senior_official_when_federal(self):
|
|
"""Tests that no edit can occur when the underlying domain is federal"""
|
|
|
|
# Set the org type to federal
|
|
self.domain_information.generic_org_type = DomainInformation.OrganizationChoices.FEDERAL
|
|
self.domain_information.save()
|
|
|
|
# Add an SO
|
|
self.domain_information.senior_official = Contact(
|
|
first_name="Apple", last_name="Tester", title="CIO", email="nobody@igorville.gov"
|
|
)
|
|
self.domain_information.senior_official.save()
|
|
self.domain_information.save()
|
|
|
|
so_page = self.app.get(reverse("domain-senior-official", kwargs={"domain_pk": self.domain.id}))
|
|
self.assertContains(so_page, "Apple Tester")
|
|
self.assertContains(so_page, "CIO")
|
|
self.assertContains(so_page, "nobody@igorville.gov")
|
|
self.assertNotContains(so_page, "Save")
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_cannot_edit_senior_official_tribal(self):
|
|
"""Tests that no edit can occur when the underlying domain is tribal"""
|
|
|
|
# Set the org type to federal
|
|
self.domain_information.generic_org_type = DomainInformation.OrganizationChoices.TRIBAL
|
|
self.domain_information.save()
|
|
|
|
# Add an SO. We can do this at the model level, just not the form level.
|
|
self.domain_information.senior_official = Contact(
|
|
first_name="Apple", last_name="Tester", title="CIO", email="nobody@igorville.gov"
|
|
)
|
|
self.domain_information.senior_official.save()
|
|
self.domain_information.save()
|
|
|
|
so_page = self.app.get(reverse("domain-senior-official", kwargs={"domain_pk": self.domain.id}))
|
|
self.assertContains(so_page, "Apple Tester")
|
|
self.assertContains(so_page, "CIO")
|
|
self.assertContains(so_page, "nobody@igorville.gov")
|
|
self.assertNotContains(so_page, "Save")
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_edit_senior_official_creates_new(self):
|
|
"""When editing a senior official for domain information and SO IS
|
|
joined to another object"""
|
|
# set SO and Other Contact to the same Contact object
|
|
self.domain_information.senior_official = Contact(
|
|
first_name="Testy", last_name="Tester", title="CIO", email="nobody@igorville.gov"
|
|
)
|
|
self.domain_information.senior_official.save()
|
|
self.domain_information.save()
|
|
self.domain_information.other_contacts.add(self.domain_information.senior_official)
|
|
self.domain_information.save()
|
|
# load the Senior Official in the web form
|
|
so_page = self.app.get(reverse("domain-senior-official", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
so_form = so_page.forms[0]
|
|
# verify the first name is "Testy" and then change it to "Testy2"
|
|
self.assertEqual(so_form["first_name"].value, "Testy")
|
|
so_form["first_name"] = "Testy2"
|
|
# so_pk is the initial pk of the senior official. set it before update
|
|
# to be able to verify after update that the same contact object is in place
|
|
so_pk = self.domain_information.senior_official.id
|
|
so_form.submit()
|
|
|
|
# refresh domain information
|
|
self.domain_information.refresh_from_db()
|
|
# assert that SO information is updated, and that the SO is a new Contact
|
|
self.assertEqual("Testy2", self.domain_information.senior_official.first_name)
|
|
self.assertNotEqual(so_pk, self.domain_information.senior_official.id)
|
|
# assert that the Other Contact information is not updated and that the Other Contact
|
|
# is the original Contact object
|
|
other_contact = self.domain_information.other_contacts.all()[0]
|
|
self.assertEqual("Testy", other_contact.first_name)
|
|
self.assertEqual(so_pk, other_contact.id)
|
|
|
|
|
|
class TestDomainOrganization(TestDomainOverview):
|
|
@less_console_noise_decorator
|
|
def test_domain_org_name_address(self):
|
|
"""Can load domain's org name and mailing address page."""
|
|
page = self.client.get(reverse("domain-org-name-address", kwargs={"domain_pk": self.domain.id}))
|
|
# once on the sidebar, once in the page title, once as H1
|
|
self.assertContains(page, "/org-name-address")
|
|
self.assertContains(page, "Organization name and mailing address")
|
|
self.assertContains(page, "Organization</h1>")
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_org_name_address_content(self):
|
|
"""Org name and address information appears on the page."""
|
|
self.domain_information.organization_name = "Town of Igorville"
|
|
self.domain_information.save()
|
|
page = self.app.get(reverse("domain-org-name-address", kwargs={"domain_pk": self.domain.id}))
|
|
self.assertContains(page, "Town of Igorville")
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_org_name_address_form(self):
|
|
"""Submitting changes works on the org name address page."""
|
|
self.domain_information.organization_name = "Town of Igorville"
|
|
self.domain_information.save()
|
|
org_name_page = self.app.get(reverse("domain-org-name-address", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
|
|
org_name_page.form["organization_name"] = "Not igorville"
|
|
org_name_page.form["city"] = "Faketown"
|
|
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
success_result_page = org_name_page.form.submit()
|
|
self.assertEqual(success_result_page.status_code, 200)
|
|
|
|
self.assertContains(success_result_page, "Not igorville")
|
|
self.assertContains(success_result_page, "Faketown")
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_org_name_address_form_tribal(self):
|
|
"""
|
|
Submitting a change to organization_name is blocked for tribal domains
|
|
"""
|
|
# Set the current domain to a tribal organization with a preset value.
|
|
# Save first, so we can test if saving is unaffected (it should be).
|
|
tribal_org_type = DomainInformation.OrganizationChoices.TRIBAL
|
|
self.domain_information.generic_org_type = tribal_org_type
|
|
self.domain_information.save()
|
|
try:
|
|
# Add an org name
|
|
self.domain_information.organization_name = "Town of Igorville"
|
|
self.domain_information.save()
|
|
except ValueError as err:
|
|
self.fail(f"A ValueError was caught during the test: {err}")
|
|
|
|
self.assertEqual(self.domain_information.generic_org_type, tribal_org_type)
|
|
|
|
org_name_page = self.app.get(reverse("domain-org-name-address", kwargs={"domain_pk": self.domain.id}))
|
|
|
|
form = org_name_page.forms[0]
|
|
# Check the value of the input field
|
|
organization_name_input = form.fields["organization_name"][0]
|
|
self.assertEqual(organization_name_input.value, "Town of Igorville")
|
|
|
|
# Check if the input field is disabled
|
|
self.assertTrue("disabled" in organization_name_input.attrs)
|
|
self.assertEqual(organization_name_input.attrs.get("disabled"), "")
|
|
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
|
|
org_name_page.form["organization_name"] = "Not igorville"
|
|
org_name_page.form["city"] = "Faketown"
|
|
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
|
|
# Make the change. The org name should be unchanged, but city should be modifiable.
|
|
success_result_page = org_name_page.form.submit()
|
|
self.assertEqual(success_result_page.status_code, 200)
|
|
|
|
# Check for the old and new value
|
|
self.assertContains(success_result_page, "Town of Igorville")
|
|
self.assertNotContains(success_result_page, "Not igorville")
|
|
|
|
# Do another check on the form itself
|
|
form = success_result_page.forms[0]
|
|
# Check the value of the input field
|
|
organization_name_input = form.fields["organization_name"][0]
|
|
self.assertEqual(organization_name_input.value, "Town of Igorville")
|
|
|
|
# Check if the input field is disabled
|
|
self.assertTrue("disabled" in organization_name_input.attrs)
|
|
self.assertEqual(organization_name_input.attrs.get("disabled"), "")
|
|
|
|
# Check for the value we want to update
|
|
self.assertContains(success_result_page, "Faketown")
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_org_name_address_form_federal(self):
|
|
"""
|
|
Submitting a change to federal_agency is blocked for federal domains
|
|
"""
|
|
|
|
fed_org_type = DomainInformation.OrganizationChoices.FEDERAL
|
|
self.domain_information.generic_org_type = fed_org_type
|
|
self.domain_information.save()
|
|
try:
|
|
federal_agency, _ = FederalAgency.objects.get_or_create(agency="AMTRAK")
|
|
self.domain_information.federal_agency = federal_agency
|
|
self.domain_information.save()
|
|
except ValueError as err:
|
|
self.fail(f"A ValueError was caught during the test: {err}")
|
|
|
|
self.assertEqual(self.domain_information.generic_org_type, fed_org_type)
|
|
|
|
org_name_page = self.app.get(reverse("domain-org-name-address", kwargs={"domain_pk": self.domain.id}))
|
|
|
|
form = org_name_page.forms[0]
|
|
# Check the value of the input field
|
|
agency_input = form.fields["federal_agency"][0]
|
|
self.assertEqual(agency_input.value, str(federal_agency.id))
|
|
|
|
# Check if the input field is disabled
|
|
self.assertTrue("disabled" in agency_input.attrs)
|
|
self.assertEqual(agency_input.attrs.get("disabled"), "")
|
|
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
|
|
org_name_page.form["federal_agency"] = FederalAgency.objects.filter(agency="Department of State").get().id
|
|
org_name_page.form["city"] = "Faketown"
|
|
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
|
|
# Make the change. The agency should be unchanged, but city should be modifiable.
|
|
success_result_page = org_name_page.form.submit()
|
|
self.assertEqual(success_result_page.status_code, 200)
|
|
|
|
# Check that the agency has not changed
|
|
self.assertEqual(self.domain_information.federal_agency.agency, "AMTRAK")
|
|
|
|
# Do another check on the form itself
|
|
form = success_result_page.forms[0]
|
|
# Check the value of the input field
|
|
organization_name_input = form.fields["federal_agency"][0]
|
|
self.assertEqual(organization_name_input.value, str(federal_agency.id))
|
|
|
|
# Check if the input field is disabled
|
|
self.assertTrue("disabled" in organization_name_input.attrs)
|
|
self.assertEqual(organization_name_input.attrs.get("disabled"), "")
|
|
|
|
# Check for the value we want to update
|
|
self.assertContains(success_result_page, "Faketown")
|
|
|
|
@less_console_noise_decorator
|
|
def test_federal_agency_submit_blocked(self):
|
|
"""
|
|
Submitting a change to federal_agency is blocked for federal domains
|
|
"""
|
|
# Set the current domain to a tribal organization with a preset value.
|
|
# Save first, so we can test if saving is unaffected (it should be).
|
|
federal_org_type = DomainInformation.OrganizationChoices.FEDERAL
|
|
self.domain_information.generic_org_type = federal_org_type
|
|
self.domain_information.save()
|
|
|
|
federal_agency, _ = FederalAgency.objects.get_or_create(agency="AMTRAK")
|
|
old_federal_agency_value = federal_agency
|
|
try:
|
|
# Add a federal agency. Defined as a tuple since this list may change order.
|
|
self.domain_information.federal_agency = old_federal_agency_value
|
|
self.domain_information.save()
|
|
except ValueError as err:
|
|
self.fail(f"A ValueError was caught during the test: {err}")
|
|
|
|
self.assertEqual(self.domain_information.generic_org_type, federal_org_type)
|
|
|
|
new_value = ("Department of State", "Department of State")
|
|
self.client.post(
|
|
reverse("domain-org-name-address", kwargs={"domain_pk": self.domain.id}),
|
|
{
|
|
"federal_agency": new_value,
|
|
},
|
|
)
|
|
self.assertEqual(self.domain_information.federal_agency, old_federal_agency_value)
|
|
self.assertNotEqual(self.domain_information.federal_agency, new_value)
|
|
|
|
|
|
class TestDomainSuborganization(TestDomainOverview):
|
|
"""Tests the Suborganization page for portfolio users"""
|
|
|
|
@less_console_noise_decorator
|
|
@override_flag("organization_feature", active=True)
|
|
def test_edit_suborganization_field(self):
|
|
"""Ensure that org admins can edit the suborganization field"""
|
|
# Create a portfolio and two suborgs
|
|
portfolio = Portfolio.objects.create(creator=self.user, organization_name="Ice Cream")
|
|
suborg = Suborganization.objects.create(portfolio=portfolio, name="Vanilla")
|
|
suborg_2 = Suborganization.objects.create(portfolio=portfolio, name="Chocolate")
|
|
|
|
# Create an unrelated portfolio
|
|
unrelated_portfolio = Portfolio.objects.create(creator=self.user, organization_name="Fruit")
|
|
unrelated_suborg = Suborganization.objects.create(portfolio=unrelated_portfolio, name="Apple")
|
|
|
|
# Add the portfolio to the domain_information object
|
|
self.domain_information.portfolio = portfolio
|
|
self.domain_information.sub_organization = suborg
|
|
|
|
# Add a organization_name to test if the old value still displays
|
|
self.domain_information.organization_name = "Broccoli"
|
|
self.domain_information.save()
|
|
self.domain_information.refresh_from_db()
|
|
|
|
# Add portfolio perms to the user object
|
|
UserPortfolioPermission.objects.get_or_create(
|
|
user=self.user, portfolio=portfolio, roles=[UserPortfolioRoleChoices.ORGANIZATION_ADMIN]
|
|
)
|
|
|
|
self.assertEqual(self.domain_information.sub_organization, suborg)
|
|
|
|
# Navigate to the suborganization page
|
|
page = self.app.get(reverse("domain-suborganization", kwargs={"domain_pk": self.domain.id}))
|
|
|
|
# The page should contain the choices Vanilla and Chocolate
|
|
self.assertContains(page, "Vanilla")
|
|
self.assertContains(page, "Chocolate")
|
|
self.assertNotContains(page, unrelated_suborg.name)
|
|
|
|
# Assert that the right option is selected. This component uses data-default-value.
|
|
self.assertContains(page, f'data-default-value="{suborg.id}"')
|
|
|
|
# Try changing the suborg
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
page.form["sub_organization"] = suborg_2.id
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
page = page.form.submit().follow()
|
|
|
|
# The page should contain the choices Vanilla and Chocolate
|
|
self.assertContains(page, "Vanilla")
|
|
self.assertContains(page, "Chocolate")
|
|
self.assertNotContains(page, unrelated_suborg.name)
|
|
|
|
# Assert that the right option is selected
|
|
self.assertContains(page, f'data-default-value="{suborg_2.id}"')
|
|
|
|
self.domain_information.refresh_from_db()
|
|
self.assertEqual(self.domain_information.sub_organization, suborg_2)
|
|
|
|
@less_console_noise_decorator
|
|
@override_flag("organization_feature", active=True)
|
|
def test_view_suborganization_field(self):
|
|
"""Only org admins can edit the suborg field, ensure that others cannot"""
|
|
|
|
# Create a portfolio and two suborgs
|
|
portfolio = Portfolio.objects.create(creator=self.user, organization_name="Ice Cream")
|
|
suborg = Suborganization.objects.create(portfolio=portfolio, name="Vanilla")
|
|
Suborganization.objects.create(portfolio=portfolio, name="Chocolate")
|
|
|
|
# Create an unrelated portfolio
|
|
unrelated_portfolio = Portfolio.objects.create(creator=self.user, organization_name="Fruit")
|
|
unrelated_suborg = Suborganization.objects.create(portfolio=unrelated_portfolio, name="Apple")
|
|
|
|
# Add the portfolio to the domain_information object
|
|
self.domain_information.portfolio = portfolio
|
|
self.domain_information.sub_organization = suborg
|
|
|
|
# Add a organization_name to test if the old value still displays
|
|
self.domain_information.organization_name = "Broccoli"
|
|
self.domain_information.save()
|
|
self.domain_information.refresh_from_db()
|
|
|
|
# Add portfolio perms to the user object
|
|
portfolio_permission, _ = UserPortfolioPermission.objects.get_or_create(
|
|
user=self.user, portfolio=portfolio, roles=[UserPortfolioRoleChoices.ORGANIZATION_MEMBER]
|
|
)
|
|
|
|
self.assertEqual(self.domain_information.sub_organization, suborg)
|
|
|
|
# Navigate to the suborganization page
|
|
page = self.app.get(reverse("domain-suborganization", kwargs={"domain_pk": self.domain.id}))
|
|
|
|
# The page should display the readonly option
|
|
self.assertContains(page, "Vanilla")
|
|
|
|
# The page shouldn't contain these choices
|
|
self.assertNotContains(page, "Chocolate")
|
|
self.assertNotContains(page, unrelated_suborg.name)
|
|
self.assertNotContains(page, "Save")
|
|
|
|
self.assertContains(
|
|
page, "The suborganization for this domain can only be updated by a organization administrator."
|
|
)
|
|
|
|
@less_console_noise_decorator
|
|
@override_flag("organization_feature", active=True)
|
|
def test_has_suborganization_field_on_overview_with_flag(self):
|
|
"""Ensures that the suborganization field is visible
|
|
and displays correctly on the domain overview page"""
|
|
|
|
# Create a portfolio
|
|
portfolio = Portfolio.objects.create(creator=self.user, organization_name="Ice Cream")
|
|
suborg = Suborganization.objects.create(portfolio=portfolio, name="Vanilla")
|
|
|
|
# Add the portfolio to the domain_information object
|
|
self.domain_information.portfolio = portfolio
|
|
|
|
# Add a organization_name to test if the old value still displays
|
|
self.domain_information.organization_name = "Broccoli"
|
|
self.domain_information.save()
|
|
self.domain_information.refresh_from_db()
|
|
|
|
# Add portfolio perms to the user object
|
|
UserPortfolioPermission.objects.get_or_create(
|
|
user=self.user, portfolio=portfolio, roles=[UserPortfolioRoleChoices.ORGANIZATION_ADMIN]
|
|
)
|
|
self.user.refresh_from_db()
|
|
|
|
# Navigate to the domain overview page
|
|
page = self.app.get(reverse("domain", kwargs={"domain_pk": self.domain.id}))
|
|
|
|
# Test for the title change
|
|
self.assertContains(page, "Suborganization")
|
|
self.assertNotContains(page, "Organization")
|
|
|
|
# Test for the good value
|
|
self.assertContains(page, "Ice Cream")
|
|
|
|
# Test for the bad value
|
|
self.assertNotContains(page, "Broccoli")
|
|
|
|
# Cleanup
|
|
self.domain_information.delete()
|
|
suborg.delete()
|
|
portfolio.delete()
|
|
|
|
|
|
class TestDomainSecurityEmail(TestDomainOverview):
|
|
def test_domain_security_email_existing_security_contact(self):
|
|
"""Can load domain's security email page."""
|
|
with less_console_noise():
|
|
self.mockSendPatch = patch("registrar.models.domain.registry.send")
|
|
self.mockedSendFunction = self.mockSendPatch.start()
|
|
self.mockedSendFunction.side_effect = self.mockSend
|
|
|
|
domain_contact, _ = Domain.objects.get_or_create(name="freeman.gov")
|
|
# Add current user to this domain
|
|
_ = UserDomainRole(user=self.user, domain=domain_contact, role="admin").save()
|
|
page = self.client.get(reverse("domain-security-email", kwargs={"domain_pk": domain_contact.id}))
|
|
|
|
# Loads correctly
|
|
self.assertContains(page, "Security email")
|
|
self.assertContains(page, "security@mail.gov")
|
|
self.mockSendPatch.stop()
|
|
|
|
def test_domain_security_email_no_security_contact(self):
|
|
"""Loads a domain with no defined security email.
|
|
We should not show the default."""
|
|
with less_console_noise():
|
|
self.mockSendPatch = patch("registrar.models.domain.registry.send")
|
|
self.mockedSendFunction = self.mockSendPatch.start()
|
|
self.mockedSendFunction.side_effect = self.mockSend
|
|
|
|
page = self.client.get(reverse("domain-security-email", kwargs={"domain_pk": self.domain.id}))
|
|
|
|
# Loads correctly
|
|
self.assertContains(page, "Security email")
|
|
self.assertNotContains(page, "dotgov@cisa.dhs.gov")
|
|
self.mockSendPatch.stop()
|
|
|
|
def test_domain_security_email(self):
|
|
"""Can load domain's security email page."""
|
|
with less_console_noise():
|
|
page = self.client.get(reverse("domain-security-email", kwargs={"domain_pk": self.domain.id}))
|
|
self.assertContains(page, "Security email")
|
|
|
|
def test_domain_security_email_form(self):
|
|
"""Adding a security email works.
|
|
Uses self.app WebTest because we need to interact with forms.
|
|
"""
|
|
with less_console_noise():
|
|
security_email_page = self.app.get(reverse("domain-security-email", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
security_email_page.form["security_email"] = "mayor@igorville.gov"
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
mock_client = MagicMock()
|
|
with boto3_mocking.clients.handler_for("sesv2", mock_client):
|
|
with less_console_noise(): # swallow log warning message
|
|
result = security_email_page.form.submit()
|
|
self.assertEqual(result.status_code, 302)
|
|
self.assertEqual(
|
|
result["Location"],
|
|
reverse("domain-security-email", kwargs={"domain_pk": self.domain.id}),
|
|
)
|
|
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
success_page = result.follow()
|
|
self.assertContains(success_page, "The security email for this domain has been updated")
|
|
|
|
def test_domain_security_email_form_messages(self):
|
|
"""
|
|
Test against the success and error messages that are defined in the view
|
|
"""
|
|
with less_console_noise():
|
|
p = "adminpass"
|
|
self.client.login(username="superuser", password=p)
|
|
form_data_registry_error = {
|
|
"security_email": "test@failCreate.gov",
|
|
}
|
|
form_data_contact_error = {
|
|
"security_email": "test@contactError.gov",
|
|
}
|
|
form_data_success = {
|
|
"security_email": "test@something.gov",
|
|
}
|
|
test_cases = [
|
|
(
|
|
"RegistryError",
|
|
form_data_registry_error,
|
|
str(GenericError(code=GenericErrorCodes.CANNOT_CONTACT_REGISTRY)),
|
|
),
|
|
(
|
|
"ContactError",
|
|
form_data_contact_error,
|
|
str(SecurityEmailError(code=SecurityEmailErrorCodes.BAD_DATA)),
|
|
),
|
|
(
|
|
"RegistrySuccess",
|
|
form_data_success,
|
|
"The security email for this domain has been updated.",
|
|
),
|
|
# Add more test cases with different scenarios here
|
|
]
|
|
for test_name, data, expected_message in test_cases:
|
|
response = self.client.post(
|
|
reverse("domain-security-email", kwargs={"domain_pk": self.domain.id}),
|
|
data=data,
|
|
follow=True,
|
|
)
|
|
# Check the response status code, content, or any other relevant assertions
|
|
self.assertEqual(response.status_code, 200)
|
|
# Check if the expected message tag is set
|
|
if test_name == "RegistryError" or test_name == "ContactError":
|
|
message_tag = "error"
|
|
elif test_name == "RegistrySuccess":
|
|
message_tag = "success"
|
|
else:
|
|
# Handle other cases if needed
|
|
message_tag = "info" # Change to the appropriate default
|
|
# Check the message tag
|
|
messages = list(response.context["messages"])
|
|
self.assertEqual(len(messages), 1)
|
|
message = messages[0]
|
|
self.assertEqual(message.tags, message_tag)
|
|
self.assertEqual(message.message.strip(), expected_message.strip())
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_overview_blocked_for_ineligible_user(self):
|
|
"""We could easily duplicate this test for all domain management
|
|
views, but a single url test should be solid enough since all domain
|
|
management pages share the same permissions class"""
|
|
self.user.status = User.RESTRICTED
|
|
self.user.save()
|
|
response = self.client.get(reverse("domain", kwargs={"domain_pk": self.domain.id}))
|
|
self.assertEqual(response.status_code, 403)
|
|
|
|
|
|
class TestDomainDNSSEC(TestDomainOverview):
|
|
"""MockEPPLib is already inherited."""
|
|
|
|
@less_console_noise_decorator
|
|
def test_dnssec_page_refreshes_enable_button(self):
|
|
"""DNSSEC overview page loads when domain has no DNSSEC data
|
|
and shows a 'Enable DNSSEC' button."""
|
|
|
|
page = self.client.get(reverse("domain-dns-dnssec", kwargs={"domain_pk": self.domain.id}))
|
|
self.assertContains(page, "Enable DNSSEC")
|
|
|
|
@less_console_noise_decorator
|
|
def test_dnssec_page_loads_with_data_in_domain(self):
|
|
"""DNSSEC overview page loads when domain has DNSSEC data
|
|
and the template contains a button to disable DNSSEC."""
|
|
|
|
page = self.client.get(reverse("domain-dns-dnssec", kwargs={"domain_pk": self.domain_multdsdata.id}))
|
|
self.assertContains(page, "Disable DNSSEC")
|
|
|
|
# Prepare the data for the POST request
|
|
post_data = {
|
|
"disable_dnssec": "Disable DNSSEC",
|
|
}
|
|
updated_page = self.client.post(
|
|
reverse("domain-dns-dnssec", kwargs={"domain_pk": self.domain.id}),
|
|
post_data,
|
|
follow=True,
|
|
)
|
|
|
|
self.assertEqual(updated_page.status_code, 200)
|
|
|
|
self.assertContains(updated_page, "Enable DNSSEC")
|
|
|
|
@less_console_noise_decorator
|
|
def test_ds_form_loads_with_no_domain_data(self):
|
|
"""DNSSEC Add DS data page loads when there is no
|
|
domain DNSSEC data and shows a button to Add new record"""
|
|
|
|
page = self.client.get(reverse("domain-dns-dnssec-dsdata", kwargs={"domain_pk": self.domain_dnssec_none.id}))
|
|
self.assertContains(page, "You have no DS data added")
|
|
self.assertContains(page, "Add new record")
|
|
|
|
@less_console_noise_decorator
|
|
def test_ds_form_loads_with_ds_data(self):
|
|
"""DNSSEC Add DS data page loads when there is
|
|
domain DNSSEC DS data and shows the data"""
|
|
|
|
page = self.client.get(reverse("domain-dns-dnssec-dsdata", kwargs={"domain_pk": self.domain_dsdata.id}))
|
|
self.assertContains(page, "DS data record 1")
|
|
|
|
@less_console_noise_decorator
|
|
def test_ds_data_form_modal(self):
|
|
"""When user clicks on save, a modal pops up."""
|
|
add_data_page = self.app.get(reverse("domain-dns-dnssec-dsdata", kwargs={"domain_pk": self.domain_dsdata.id}))
|
|
# Assert that a hidden trigger for the modal does not exist.
|
|
# This hidden trigger will pop on the page when certain condition are met:
|
|
# 1) Initial form contained DS data, 2) All data is deleted and form is
|
|
# submitted.
|
|
self.assertNotContains(add_data_page, "Trigger Disable DNSSEC Modal")
|
|
# Simulate a delete all data
|
|
form_data = {}
|
|
response = self.client.post(
|
|
reverse("domain-dns-dnssec-dsdata", kwargs={"domain_pk": self.domain_dsdata.id}),
|
|
data=form_data,
|
|
)
|
|
self.assertEqual(response.status_code, 200) # Adjust status code as needed
|
|
# Now check to see whether the JS trigger for the modal is present on the page
|
|
self.assertContains(response, "Trigger Disable DNSSEC Modal")
|
|
|
|
@less_console_noise_decorator
|
|
def test_ds_data_form_submits(self):
|
|
"""DS data form submits successfully
|
|
|
|
Uses self.app WebTest because we need to interact with forms.
|
|
"""
|
|
add_data_page = self.app.get(reverse("domain-dns-dnssec-dsdata", kwargs={"domain_pk": self.domain_dsdata.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
result = add_data_page.forms[0].submit()
|
|
# form submission was a post, response should be a redirect
|
|
self.assertEqual(result.status_code, 302)
|
|
self.assertEqual(
|
|
result["Location"],
|
|
reverse("domain-dns-dnssec-dsdata", kwargs={"domain_pk": self.domain_dsdata.id}),
|
|
)
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
page = result.follow()
|
|
self.assertContains(page, "The DS data records for this domain have been updated.")
|
|
|
|
@less_console_noise_decorator
|
|
def test_ds_data_form_invalid(self):
|
|
"""DS data form errors with invalid data (missing required fields)
|
|
|
|
Uses self.app WebTest because we need to interact with forms.
|
|
"""
|
|
add_data_page = self.app.get(reverse("domain-dns-dnssec-dsdata", kwargs={"domain_pk": self.domain_dsdata.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
# all four form fields are required, so will test with each blank
|
|
add_data_page.forms[0]["form-0-key_tag"] = ""
|
|
add_data_page.forms[0]["form-0-algorithm"] = ""
|
|
add_data_page.forms[0]["form-0-digest_type"] = ""
|
|
add_data_page.forms[0]["form-0-digest"] = ""
|
|
result = add_data_page.forms[0].submit()
|
|
# form submission was a post with an error, response should be a 200
|
|
# error text appears twice, once at the top of the page, once around
|
|
# the field.
|
|
self.assertContains(result, "Key tag is required", count=2, status_code=200)
|
|
self.assertContains(result, "Algorithm is required", count=2, status_code=200)
|
|
self.assertContains(result, "Digest type is required", count=2, status_code=200)
|
|
self.assertContains(result, "Digest is required", count=2, status_code=200)
|
|
|
|
@less_console_noise_decorator
|
|
def test_ds_data_form_invalid_keytag(self):
|
|
"""DS data form errors with invalid data (key tag too large)
|
|
|
|
Uses self.app WebTest because we need to interact with forms.
|
|
"""
|
|
add_data_page = self.app.get(reverse("domain-dns-dnssec-dsdata", kwargs={"domain_pk": self.domain_dsdata.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
# first two nameservers are required, so if we empty one out we should
|
|
# get a form error
|
|
add_data_page.forms[0]["form-0-key_tag"] = "65536" # > 65535
|
|
add_data_page.forms[0]["form-0-algorithm"] = ""
|
|
add_data_page.forms[0]["form-0-digest_type"] = ""
|
|
add_data_page.forms[0]["form-0-digest"] = ""
|
|
result = add_data_page.forms[0].submit()
|
|
# form submission was a post with an error, response should be a 200
|
|
# error text appears twice, once at the top of the page, once around
|
|
# the field.
|
|
self.assertContains(
|
|
result, str(DsDataError(code=DsDataErrorCodes.INVALID_KEYTAG_SIZE)), count=2, status_code=200
|
|
)
|
|
|
|
@less_console_noise_decorator
|
|
def test_ds_data_form_invalid_digest_chars(self):
|
|
"""DS data form errors with invalid data (digest contains non hexadecimal chars)
|
|
|
|
Uses self.app WebTest because we need to interact with forms.
|
|
"""
|
|
add_data_page = self.app.get(reverse("domain-dns-dnssec-dsdata", kwargs={"domain_pk": self.domain_dsdata.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
# first two nameservers are required, so if we empty one out we should
|
|
# get a form error
|
|
add_data_page.forms[0]["form-0-key_tag"] = "1234"
|
|
add_data_page.forms[0]["form-0-algorithm"] = "3"
|
|
add_data_page.forms[0]["form-0-digest_type"] = "1"
|
|
add_data_page.forms[0]["form-0-digest"] = "GG1234"
|
|
result = add_data_page.forms[0].submit()
|
|
# form submission was a post with an error, response should be a 200
|
|
# error text appears twice, once at the top of the page, once around
|
|
# the field.
|
|
self.assertContains(
|
|
result, str(DsDataError(code=DsDataErrorCodes.INVALID_DIGEST_CHARS)), count=2, status_code=200
|
|
)
|
|
|
|
@less_console_noise_decorator
|
|
def test_ds_data_form_invalid_digest_sha1(self):
|
|
"""DS data form errors with invalid data (digest is invalid sha-1)
|
|
|
|
Uses self.app WebTest because we need to interact with forms.
|
|
"""
|
|
add_data_page = self.app.get(reverse("domain-dns-dnssec-dsdata", kwargs={"domain_pk": self.domain_dsdata.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
# first two nameservers are required, so if we empty one out we should
|
|
# get a form error
|
|
add_data_page.forms[0]["form-0-key_tag"] = "1234"
|
|
add_data_page.forms[0]["form-0-algorithm"] = "3"
|
|
add_data_page.forms[0]["form-0-digest_type"] = "1" # SHA-1
|
|
add_data_page.forms[0]["form-0-digest"] = "A123"
|
|
result = add_data_page.forms[0].submit()
|
|
# form submission was a post with an error, response should be a 200
|
|
# error text appears twice, once at the top of the page, once around
|
|
# the field.
|
|
self.assertContains(
|
|
result, str(DsDataError(code=DsDataErrorCodes.INVALID_DIGEST_SHA1)), count=2, status_code=200
|
|
)
|
|
|
|
@less_console_noise_decorator
|
|
def test_ds_data_form_invalid_digest_sha256(self):
|
|
"""DS data form errors with invalid data (digest is invalid sha-256)
|
|
|
|
Uses self.app WebTest because we need to interact with forms.
|
|
"""
|
|
add_data_page = self.app.get(reverse("domain-dns-dnssec-dsdata", kwargs={"domain_pk": self.domain_dsdata.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
# first two nameservers are required, so if we empty one out we should
|
|
# get a form error
|
|
add_data_page.forms[0]["form-0-key_tag"] = "1234"
|
|
add_data_page.forms[0]["form-0-algorithm"] = "3"
|
|
add_data_page.forms[0]["form-0-digest_type"] = "2" # SHA-256
|
|
add_data_page.forms[0]["form-0-digest"] = "GG1234"
|
|
result = add_data_page.forms[0].submit()
|
|
# form submission was a post with an error, response should be a 200
|
|
# error text appears twice, once at the top of the page, once around
|
|
# the field.
|
|
self.assertContains(
|
|
result, str(DsDataError(code=DsDataErrorCodes.INVALID_DIGEST_SHA256)), count=2, status_code=200
|
|
)
|
|
|
|
|
|
class TestDomainChangeNotifications(TestDomainOverview):
|
|
"""Test email notifications on updates to domain information"""
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super().setUpClass()
|
|
allowed_emails = [
|
|
AllowedEmail(email="info@example.com"),
|
|
AllowedEmail(email="doesnotexist@igorville.com"),
|
|
]
|
|
AllowedEmail.objects.bulk_create(allowed_emails)
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.mock_client_class = MagicMock()
|
|
self.mock_client = self.mock_client_class.return_value
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
super().tearDownClass()
|
|
AllowedEmail.objects.all().delete()
|
|
|
|
@boto3_mocking.patching
|
|
@less_console_noise_decorator
|
|
def test_notification_on_org_name_change(self):
|
|
"""Test that an email is sent when the organization name is changed."""
|
|
# We may end up sending emails on org name changes later, but it will be addressed
|
|
# in the portfolio itself, rather than the individual domain.
|
|
|
|
self.domain_information.organization_name = "Town of Igorville"
|
|
self.domain_information.address_line1 = "123 Main St"
|
|
self.domain_information.city = "Igorville"
|
|
self.domain_information.state_territory = "IL"
|
|
self.domain_information.zipcode = "62052"
|
|
self.domain_information.save()
|
|
|
|
org_name_page = self.app.get(reverse("domain-org-name-address", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
|
|
org_name_page.form["organization_name"] = "Not igorville"
|
|
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
with boto3_mocking.clients.handler_for("sesv2", self.mock_client_class):
|
|
org_name_page.form.submit()
|
|
|
|
# Check that an email was sent
|
|
self.assertTrue(self.mock_client.send_email.called)
|
|
|
|
# Check email content
|
|
# check the call sequence for the email
|
|
_, kwargs = self.mock_client.send_email.call_args
|
|
self.assertIn("Content", kwargs)
|
|
self.assertIn("Simple", kwargs["Content"])
|
|
self.assertIn("Subject", kwargs["Content"]["Simple"])
|
|
self.assertIn("Body", kwargs["Content"]["Simple"])
|
|
|
|
body = kwargs["Content"]["Simple"]["Body"]["Text"]["Data"]
|
|
|
|
self.assertIn("DOMAIN: igorville.gov", body)
|
|
self.assertIn("UPDATED BY: First Last info@example.com", body)
|
|
self.assertIn("INFORMATION UPDATED: Organization details", body)
|
|
|
|
@boto3_mocking.patching
|
|
@less_console_noise_decorator
|
|
def test_no_notification_on_org_name_change_with_portfolio(self):
|
|
"""Test that an email is not sent on org name change when the domain is in a portfolio"""
|
|
|
|
portfolio, _ = Portfolio.objects.get_or_create(organization_name="Test org", creator=self.user)
|
|
|
|
self.domain_information.organization_name = "Town of Igorville"
|
|
self.domain_information.address_line1 = "123 Main St"
|
|
self.domain_information.city = "Igorville"
|
|
self.domain_information.state_territory = "IL"
|
|
self.domain_information.zipcode = "62052"
|
|
self.domain_information.portfolio = portfolio
|
|
self.domain_information.save()
|
|
|
|
org_name_page = self.app.get(reverse("domain-org-name-address", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
|
|
org_name_page.form["organization_name"] = "Not igorville"
|
|
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
with boto3_mocking.clients.handler_for("sesv2", self.mock_client_class):
|
|
org_name_page.form.submit()
|
|
|
|
# Check that an email was not sent
|
|
self.assertFalse(self.mock_client.send_email.called)
|
|
|
|
@boto3_mocking.patching
|
|
@less_console_noise_decorator
|
|
def test_no_notification_on_change_by_analyst(self):
|
|
"""Test that an email is not sent on org name change when the domain is in a portfolio"""
|
|
|
|
portfolio, _ = Portfolio.objects.get_or_create(organization_name="Test org", creator=self.user)
|
|
|
|
self.domain_information.organization_name = "Town of Igorville"
|
|
self.domain_information.address_line1 = "123 Main St"
|
|
self.domain_information.city = "Igorville"
|
|
self.domain_information.state_territory = "IL"
|
|
self.domain_information.zipcode = "62052"
|
|
self.domain_information.portfolio = portfolio
|
|
self.domain_information.save()
|
|
|
|
org_name_page = self.app.get(reverse("domain-org-name-address", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
|
|
session = self.app.session
|
|
session["analyst_action"] = "foo"
|
|
session["analyst_action_location"] = self.domain.id
|
|
session.save()
|
|
|
|
org_name_page.form["organization_name"] = "Not igorville"
|
|
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
with boto3_mocking.clients.handler_for("sesv2", self.mock_client_class):
|
|
org_name_page.form.submit()
|
|
|
|
# Check that an email was not sent
|
|
self.assertFalse(self.mock_client.send_email.called)
|
|
|
|
@boto3_mocking.patching
|
|
@less_console_noise_decorator
|
|
def test_notification_on_security_email_change(self):
|
|
"""Test that an email is sent when the security email is changed."""
|
|
|
|
security_email_page = self.app.get(reverse("domain-security-email", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
|
|
security_email_page.form["security_email"] = "new_security@example.com"
|
|
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
with boto3_mocking.clients.handler_for("sesv2", self.mock_client_class):
|
|
security_email_page.form.submit()
|
|
|
|
self.assertTrue(self.mock_client.send_email.called)
|
|
|
|
_, kwargs = self.mock_client.send_email.call_args
|
|
body = kwargs["Content"]["Simple"]["Body"]["Text"]["Data"]
|
|
|
|
self.assertIn("DOMAIN: igorville.gov", body)
|
|
self.assertIn("UPDATED BY: First Last info@example.com", body)
|
|
self.assertIn("INFORMATION UPDATED: Security email", body)
|
|
|
|
@boto3_mocking.patching
|
|
@less_console_noise_decorator
|
|
def test_notification_on_dnssec_enable(self):
|
|
"""Test that an email is sent when DNSSEC is enabled."""
|
|
|
|
page = self.client.get(reverse("domain-dns-dnssec", kwargs={"domain_pk": self.domain_multdsdata.id}))
|
|
self.assertContains(page, "Disable DNSSEC")
|
|
|
|
# Prepare the data for the POST request
|
|
post_data = {
|
|
"disable_dnssec": "Disable DNSSEC",
|
|
}
|
|
|
|
with boto3_mocking.clients.handler_for("sesv2", self.mock_client_class):
|
|
updated_page = self.client.post(
|
|
reverse("domain-dns-dnssec", kwargs={"domain_pk": self.domain.id}),
|
|
post_data,
|
|
follow=True,
|
|
)
|
|
|
|
self.assertEqual(updated_page.status_code, 200)
|
|
|
|
self.assertContains(updated_page, "Enable DNSSEC")
|
|
|
|
self.assertTrue(self.mock_client.send_email.called)
|
|
|
|
_, kwargs = self.mock_client.send_email.call_args
|
|
body = kwargs["Content"]["Simple"]["Body"]["Text"]["Data"]
|
|
|
|
self.assertIn("DOMAIN: igorville.gov", body)
|
|
self.assertIn("UPDATED BY: First Last info@example.com", body)
|
|
self.assertIn("INFORMATION UPDATED: DNSSEC / DS Data", body)
|
|
|
|
@boto3_mocking.patching
|
|
@less_console_noise_decorator
|
|
def test_notification_on_ds_data_change(self):
|
|
"""Test that an email is sent when DS data is changed."""
|
|
|
|
ds_data_page = self.app.get(reverse("domain-dns-dnssec-dsdata", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
|
|
# Add DS data
|
|
ds_data_page.forms[0]["form-0-key_tag"] = "12345"
|
|
ds_data_page.forms[0]["form-0-algorithm"] = "13"
|
|
ds_data_page.forms[0]["form-0-digest_type"] = "2"
|
|
ds_data_page.forms[0]["form-0-digest"] = "1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF"
|
|
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
with boto3_mocking.clients.handler_for("sesv2", self.mock_client_class):
|
|
ds_data_page.forms[0].submit()
|
|
|
|
# check that the email was sent
|
|
self.assertTrue(self.mock_client.send_email.called)
|
|
|
|
# check some stuff about the email
|
|
_, kwargs = self.mock_client.send_email.call_args
|
|
body = kwargs["Content"]["Simple"]["Body"]["Text"]["Data"]
|
|
|
|
self.assertIn("DOMAIN: igorville.gov", body)
|
|
self.assertIn("UPDATED BY: First Last info@example.com", body)
|
|
self.assertIn("INFORMATION UPDATED: DNSSEC / DS Data", body)
|
|
|
|
@boto3_mocking.patching
|
|
@less_console_noise_decorator
|
|
def test_notification_on_senior_official_change(self):
|
|
"""Test that an email is sent when the senior official information is changed."""
|
|
|
|
self.domain_information.senior_official = Contact.objects.create(
|
|
first_name="Old", last_name="Official", title="Manager", email="old_official@example.com"
|
|
)
|
|
self.domain_information.save()
|
|
|
|
senior_official_page = self.app.get(reverse("domain-senior-official", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
|
|
senior_official_page.form["first_name"] = "New"
|
|
senior_official_page.form["last_name"] = "Official"
|
|
senior_official_page.form["title"] = "Director"
|
|
senior_official_page.form["email"] = "new_official@example.com"
|
|
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
with boto3_mocking.clients.handler_for("sesv2", self.mock_client_class):
|
|
senior_official_page.form.submit()
|
|
|
|
self.assertTrue(self.mock_client.send_email.called)
|
|
|
|
_, kwargs = self.mock_client.send_email.call_args
|
|
body = kwargs["Content"]["Simple"]["Body"]["Text"]["Data"]
|
|
|
|
self.assertIn("DOMAIN: igorville.gov", body)
|
|
self.assertIn("UPDATED BY: First Last info@example.com", body)
|
|
self.assertIn("INFORMATION UPDATED: Senior official", body)
|
|
|
|
@boto3_mocking.patching
|
|
@less_console_noise_decorator
|
|
def test_no_notification_on_senior_official_when_portfolio(self):
|
|
"""Test that an email is not sent when the senior official information is changed
|
|
and the domain is in a portfolio."""
|
|
|
|
self.domain_information.senior_official = Contact.objects.create(
|
|
first_name="Old", last_name="Official", title="Manager", email="old_official@example.com"
|
|
)
|
|
portfolio, _ = Portfolio.objects.get_or_create(
|
|
organization_name="portfolio",
|
|
creator=self.user,
|
|
)
|
|
self.domain_information.portfolio = portfolio
|
|
self.domain_information.save()
|
|
|
|
senior_official_page = self.app.get(reverse("domain-senior-official", kwargs={"domain_pk": self.domain.id}))
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
|
|
senior_official_page.form["first_name"] = "New"
|
|
senior_official_page.form["last_name"] = "Official"
|
|
senior_official_page.form["title"] = "Director"
|
|
senior_official_page.form["email"] = "new_official@example.com"
|
|
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
with boto3_mocking.clients.handler_for("sesv2", self.mock_client_class):
|
|
senior_official_page.form.submit()
|
|
|
|
self.assertFalse(self.mock_client.send_email.called)
|
|
|
|
@boto3_mocking.patching
|
|
@less_console_noise_decorator
|
|
def test_no_notification_when_dns_needed(self):
|
|
"""Test that an email is not sent when nameservers are changed while the state is DNS_NEEDED."""
|
|
|
|
nameservers_page = self.app.get(
|
|
reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain_dns_needed.id})
|
|
)
|
|
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
|
|
|
# add nameservers
|
|
nameservers_page.form["form-0-server"] = "ns1-new.dns-needed.gov"
|
|
nameservers_page.form["form-0-ip"] = "192.168.1.1"
|
|
nameservers_page.form["form-1-server"] = "ns2-new.dns-needed.gov"
|
|
nameservers_page.form["form-1-ip"] = "192.168.1.2"
|
|
|
|
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
|
with boto3_mocking.clients.handler_for("sesv2", self.mock_client_class):
|
|
nameservers_page.form.submit()
|
|
|
|
# Check that an email was not sent
|
|
self.assertFalse(self.mock_client.send_email.called)
|
|
|
|
|
|
class TestDomainRenewal(TestWithUser):
|
|
def setUp(self):
|
|
super().setUp()
|
|
today = datetime.now()
|
|
expiring_date = (today + timedelta(days=30)).strftime("%Y-%m-%d")
|
|
expiring_date_current = (today + timedelta(days=70)).strftime("%Y-%m-%d")
|
|
expired_date = (today - timedelta(days=30)).strftime("%Y-%m-%d")
|
|
|
|
self.domain_with_expiring_soon_date, _ = Domain.objects.get_or_create(
|
|
name="igorville.gov", expiration_date=expiring_date
|
|
)
|
|
self.domain_with_expired_date, _ = Domain.objects.get_or_create(
|
|
name="domainwithexpireddate.gov", expiration_date=expired_date
|
|
)
|
|
|
|
self.domain_with_current_date, _ = Domain.objects.get_or_create(
|
|
name="domainwithfarexpireddate.gov", expiration_date=expiring_date_current
|
|
)
|
|
|
|
UserDomainRole.objects.get_or_create(
|
|
user=self.user, domain=self.domain_with_current_date, role=UserDomainRole.Roles.MANAGER
|
|
)
|
|
|
|
UserDomainRole.objects.get_or_create(
|
|
user=self.user, domain=self.domain_with_expired_date, role=UserDomainRole.Roles.MANAGER
|
|
)
|
|
|
|
UserDomainRole.objects.get_or_create(
|
|
user=self.user, domain=self.domain_with_expiring_soon_date, role=UserDomainRole.Roles.MANAGER
|
|
)
|
|
|
|
def tearDown(self):
|
|
try:
|
|
UserDomainRole.objects.all().delete()
|
|
Domain.objects.all().delete()
|
|
except ValueError:
|
|
pass
|
|
super().tearDown()
|
|
|
|
@less_console_noise_decorator
|
|
def test_domain_with_single_domain(self):
|
|
self.client.force_login(self.user)
|
|
domains_page = self.client.get("/")
|
|
self.assertContains(domains_page, "One domain will expire soon")
|
|
self.assertContains(domains_page, "Expiring soon")
|
|
|
|
@less_console_noise_decorator
|
|
def test_with_mulitple_domains(self):
|
|
today = datetime.now()
|
|
expiring_date = (today + timedelta(days=30)).strftime("%Y-%m-%d")
|
|
self.domain_with_another_expiring, _ = Domain.objects.get_or_create(
|
|
name="domainwithanotherexpiringdate.gov", expiration_date=expiring_date
|
|
)
|
|
|
|
UserDomainRole.objects.get_or_create(
|
|
user=self.user, domain=self.domain_with_another_expiring, role=UserDomainRole.Roles.MANAGER
|
|
)
|
|
self.client.force_login(self.user)
|
|
domains_page = self.client.get("/")
|
|
self.assertContains(domains_page, "Multiple domains will expire soon")
|
|
self.assertContains(domains_page, "Expiring soon")
|
|
|
|
@less_console_noise_decorator
|
|
def test_with_no_expiring_domains(self):
|
|
UserDomainRole.objects.filter(user=self.user, domain=self.domain_with_expired_date).delete()
|
|
UserDomainRole.objects.filter(user=self.user, domain=self.domain_with_expiring_soon_date).delete()
|
|
self.client.force_login(self.user)
|
|
domains_page = self.client.get("/")
|
|
self.assertNotContains(domains_page, "will expire soon")
|
|
|
|
@less_console_noise_decorator
|
|
@override_flag("organization_feature", active=True)
|
|
def test_single_domain_w_org_feature_flag(self):
|
|
self.client.force_login(self.user)
|
|
domains_page = self.client.get("/")
|
|
self.assertContains(domains_page, "One domain will expire soon")
|
|
self.assertContains(domains_page, "Expiring soon")
|
|
|
|
@less_console_noise_decorator
|
|
@override_flag("organization_feature", active=True)
|
|
def test_with_mulitple_domains_w_org_feature_flag(self):
|
|
today = datetime.now()
|
|
expiring_date = (today + timedelta(days=31)).strftime("%Y-%m-%d")
|
|
self.domain_with_another_expiring_org_model, _ = Domain.objects.get_or_create(
|
|
name="domainwithanotherexpiringdate_orgmodel.gov", expiration_date=expiring_date
|
|
)
|
|
|
|
UserDomainRole.objects.get_or_create(
|
|
user=self.user, domain=self.domain_with_another_expiring_org_model, role=UserDomainRole.Roles.MANAGER
|
|
)
|
|
self.client.force_login(self.user)
|
|
domains_page = self.client.get("/")
|
|
self.assertContains(domains_page, "Multiple domains will expire soon")
|
|
self.assertContains(domains_page, "Expiring soon")
|
|
|
|
@less_console_noise_decorator
|
|
@override_flag("organization_feature", active=True)
|
|
def test_no_expiring_domains_w_org_feature_flag(self):
|
|
UserDomainRole.objects.filter(user=self.user, domain=self.domain_with_expired_date).delete()
|
|
UserDomainRole.objects.filter(user=self.user, domain=self.domain_with_expiring_soon_date).delete()
|
|
self.client.force_login(self.user)
|
|
domains_page = self.client.get("/")
|
|
self.assertNotContains(domains_page, "will expire soon")
|