diff --git a/src/registrar/admin.py b/src/registrar/admin.py
index 485a1b07d..ca51e8b72 100644
--- a/src/registrar/admin.py
+++ b/src/registrar/admin.py
@@ -1976,30 +1976,18 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
# If the status is not mapped properly, saving could cause
# weird issues down the line. Instead, we should block this.
- # NEEDS A UNIT TEST
should_proceed = False
- return (obj, should_proceed)
+ return should_proceed
- obj_is_not_approved = obj.status != models.DomainRequest.DomainRequestStatus.APPROVED
- if obj_is_not_approved and not obj.domain_is_not_active():
- # REDUNDANT CHECK / ERROR SCREEN AVOIDANCE:
- # This action (moving a request from approved to
- # another status) when the domain is already active (READY),
- # would still not go through even without this check as the rules are
- # duplicated in the model and the error is raised from the model.
- # This avoids an ugly Django error screen.
+ request_is_not_approved = obj.status != models.DomainRequest.DomainRequestStatus.APPROVED
+ if request_is_not_approved and not obj.domain_is_not_active():
+ # If an admin tried to set an approved domain request to
+ # another status and the related domain is already
+ # active, shortcut the action and throw a friendly
+ # error message. This action would still not go through
+ # shortcut or not as the rules are duplicated on the model,
+ # but the error would be an ugly Django error screen.
error_message = "This action is not permitted. The domain is already active."
- elif (
- original_obj.status != models.DomainRequest.DomainRequestStatus.APPROVED
- and obj.status == models.DomainRequest.DomainRequestStatus.APPROVED
- and original_obj.requested_domain is not None
- and Domain.objects.filter(name=original_obj.requested_domain.name).exists()
- ):
- # REDUNDANT CHECK:
- # This action (approving a request when the domain exists)
- # would still not go through even without this check as the rules are
- # duplicated in the model and the error is raised from the model.
- error_message = FSMDomainRequestError.get_error_message(FSMErrorCodes.APPROVE_DOMAIN_IN_USE)
elif obj.status == models.DomainRequest.DomainRequestStatus.REJECTED and not obj.rejection_reason:
# This condition should never be triggered.
# The opposite of this condition is acceptable (rejected -> other status and rejection_reason)
diff --git a/src/registrar/assets/js/get-gov-admin.js b/src/registrar/assets/js/get-gov-admin.js
index f44211c6d..73f3dded1 100644
--- a/src/registrar/assets/js/get-gov-admin.js
+++ b/src/registrar/assets/js/get-gov-admin.js
@@ -515,14 +515,10 @@ document.addEventListener('DOMContentLoaded', function() {
const formLabel = document.querySelector('label[for="id_action_needed_reason_email"]');
let lastSentEmailContent = document.getElementById("last-sent-email-content");
const initialDropdownValue = dropdown ? dropdown.value : null;
- let initialEmailValue;
- if (textarea)
- initialEmailValue = textarea.value
+ const initialEmailValue = textarea.value;
// We will use the const to control the modal
- let isEmailAlreadySentConst;
- if (lastSentEmailContent)
- isEmailAlreadySentConst = lastSentEmailContent.value.replace(/\s+/g, '') === textarea.value.replace(/\s+/g, '');
+ let isEmailAlreadySentConst = lastSentEmailContent.value.replace(/\s+/g, '') === textarea.value.replace(/\s+/g, '');
// We will use the function to control the label and help
function isEmailAlreadySent() {
return lastSentEmailContent.value.replace(/\s+/g, '') === textarea.value.replace(/\s+/g, '');
@@ -710,6 +706,18 @@ document.addEventListener('DOMContentLoaded', function() {
}
return '';
}
+ // Extract the submitter name, title, email, and phone number
+ const submitterDiv = document.querySelector('.form-row.field-submitter');
+ const submitterNameElement = document.getElementById('id_submitter');
+ // We have to account for different superuser and analyst markups
+ const submitterName = submitterNameElement
+ ? submitterNameElement.options[submitterNameElement.selectedIndex].text
+ : submitterDiv.querySelector('a').text;
+ const submitterTitle = extractTextById('contact_info_title', submitterDiv);
+ const submitterEmail = extractTextById('contact_info_email', submitterDiv);
+ const submitterPhone = extractTextById('contact_info_phone', submitterDiv);
+ let submitterInfo = `${submitterName}${submitterTitle}${submitterEmail}${submitterPhone}`;
+
//------ Senior Official
const seniorOfficialDiv = document.querySelector('.form-row.field-senior_official');
@@ -726,6 +734,7 @@ document.addEventListener('DOMContentLoaded', function() {
`Current Websites: ${existingWebsites.join(', ')}` +
`Rationale: ` +
`Alternative Domains: ${alternativeDomains.join(', ')}` +
+ `Submitter: ${submitterInfo}` +
`Senior Official: ${seniorOfficialInfo}` +
`Other Employees: ${otherContactsSummary}`;
diff --git a/src/registrar/assets/sass/_theme/_admin.scss b/src/registrar/assets/sass/_theme/_admin.scss
index b6bc0d296..5cea72c4c 100644
--- a/src/registrar/assets/sass/_theme/_admin.scss
+++ b/src/registrar/assets/sass/_theme/_admin.scss
@@ -385,7 +385,6 @@ a.button,
font-kerning: auto;
font-family: inherit;
font-weight: normal;
- text-decoration: none !important;
}
.button svg,
.button span,
@@ -393,9 +392,6 @@ a.button,
.usa-button--dja span {
vertical-align: middle;
}
-.usa-button--dja.usa-button--unstyled {
- color: var(--link-fg);
-}
.usa-button--dja:not(.usa-button--unstyled, .usa-button--outline, .usa-modal__close, .usa-button--secondary) {
background: var(--button-bg);
}
@@ -425,34 +421,11 @@ input[type=submit].button--dja-toolbar {
input[type=submit].button--dja-toolbar:focus, input[type=submit].button--dja-toolbar:hover {
border-color: var(--body-quiet-color);
}
-.admin-icon-group {
- position: relative;
- display: inline;
- align-items: center;
-
- input {
- // Allow for padding around the copy button
- padding-right: 35px !important;
- }
-
- button {
- width: max-content;
- }
-
- @media (max-width: 1000px) {
- button {
- display: block;
- }
- }
-
- span {
- padding-left: 0.05rem;
- }
-
-}
-.usa-button__small-text,
-.usa-button__small-text span {
- font-size: 13px;
+// Targets the DJA buttom with a nested icon
+button .usa-icon,
+.button .usa-icon,
+.button--clipboard .usa-icon {
+ vertical-align: middle;
}
.module--custom {
@@ -700,10 +673,71 @@ address.dja-address-contact-list {
}
}
+// Make the clipboard button "float" inside of the input box
+.admin-icon-group {
+ position: relative;
+ display: inline;
+ align-items: center;
+
+ input {
+ // Allow for padding around the copy button
+ padding-right: 35px !important;
+ // Match the height of other inputs
+ min-height: 2.25rem !important;
+ }
+
+ button {
+ line-height: 14px;
+ width: max-content;
+ font-size: unset;
+ text-decoration: none !important;
+ }
+
+ @media (max-width: 1000px) {
+ button {
+ display: block;
+ padding-top: 8px;
+ }
+ }
+
+ span {
+ padding-left: 0.1rem;
+ }
+
+}
+
+.admin-icon-group.admin-icon-group__clipboard-link {
+ position: relative;
+ display: inline;
+ align-items: center;
+
+
+ .usa-button--icon {
+ position: absolute;
+ right: auto;
+ left: 4px;
+ height: 100%;
+ top: -1px;
+ }
+ button {
+ font-size: unset !important;
+ display: inline-flex;
+ padding-top: 4px;
+ line-height: 14px;
+ width: max-content;
+ font-size: unset;
+ text-decoration: none !important;
+ }
+}
+
.no-outline-on-click:focus {
outline: none !important;
}
+.usa-button__small-text {
+ font-size: small;
+}
+
// Get rid of padding on all help texts
form .aligned p.help, form .aligned div.help {
padding-left: 0px !important;
@@ -853,9 +887,6 @@ div.dja__model-description{
padding-top: 0 !important;
}
-.padding-bottom-0 {
- padding-bottom: 0 !important;
-}
.flex-container {
@media screen and (min-width: 700px) and (max-width: 1150px) {
diff --git a/src/registrar/templates/admin/change_form_object_tools.html b/src/registrar/templates/admin/change_form_object_tools.html
index 66011a3c4..198140c19 100644
--- a/src/registrar/templates/admin/change_form_object_tools.html
+++ b/src/registrar/templates/admin/change_form_object_tools.html
@@ -20,11 +20,10 @@
{% if opts.model_name == 'domainrequest' %}
-
+
-
{% translate "Copy request summary" %}
diff --git a/src/registrar/templates/admin/input_with_clipboard.html b/src/registrar/templates/admin/input_with_clipboard.html
index d6a016fd5..5ad2b27f7 100644
--- a/src/registrar/templates/admin/input_with_clipboard.html
+++ b/src/registrar/templates/admin/input_with_clipboard.html
@@ -8,7 +8,7 @@ Template for an input field with a clipboard
{{ field }}
@@ -17,27 +17,23 @@ Template for an input field with a clipboard
>
-
- Copy
+ Copy
{% else %}
-
+
- {% if field.email is not None %}
-
+
-
-
-
-
- Copy
-
- {% endif %}
+
+
+ Copy
+
-{% endif %}
+{% endif %}
\ No newline at end of file
diff --git a/src/registrar/templates/django/admin/includes/contact_detail_list.html b/src/registrar/templates/django/admin/includes/contact_detail_list.html
index 84fb07f33..0a28a6532 100644
--- a/src/registrar/templates/django/admin/includes/contact_detail_list.html
+++ b/src/registrar/templates/django/admin/includes/contact_detail_list.html
@@ -26,7 +26,7 @@
{% if user.email %}
{{ user.email }}
{% include "admin/input_with_clipboard.html" with field=user invisible_input_field=True %}
-
+
{% else %}
None
{% endif %}
diff --git a/src/registrar/templates/django/admin/includes/detail_table_fieldset.html b/src/registrar/templates/django/admin/includes/detail_table_fieldset.html
index 2369f235b..6b755724e 100644
--- a/src/registrar/templates/django/admin/includes/detail_table_fieldset.html
+++ b/src/registrar/templates/django/admin/includes/detail_table_fieldset.html
@@ -254,7 +254,7 @@ This is using a custom implementation fieldset.html (see admin/fieldset.html)
- Other contact information
+ Other contact information
@@ -267,31 +267,18 @@ This is using a custom implementation fieldset.html (see admin/fieldset.html)
{{ contact.phone }}
- {% if contact.email %}
-
-
+
+
-
-
-
-
- Copy email
-
- {% endif %}
+
+
+ Copy email
+
{% endfor %}
diff --git a/src/registrar/tests/test_admin.py b/src/registrar/tests/test_admin.py
index 9c5e3b582..cdc3c97de 100644
--- a/src/registrar/tests/test_admin.py
+++ b/src/registrar/tests/test_admin.py
@@ -654,7 +654,7 @@ class TestDomainInformationAdmin(TestCase):
self.test_helper.assert_response_contains_distinct_values(response, expected_other_employees_fields)
# Test for the copy link
- self.assertContains(response, "copy-to-clipboard", count=3)
+ self.assertContains(response, "button--clipboard", count=3)
# cleanup this test
domain_info.delete()
diff --git a/src/registrar/tests/test_admin_domain.py b/src/registrar/tests/test_admin_domain.py
index f02b59a91..a9b94781f 100644
--- a/src/registrar/tests/test_admin_domain.py
+++ b/src/registrar/tests/test_admin_domain.py
@@ -535,7 +535,7 @@ class TestDomainAdminWithClient(TestCase):
self.assertContains(response, "Testy Tester")
# Test for the copy link
- self.assertContains(response, "copy-to-clipboard")
+ self.assertContains(response, "button--clipboard")
# cleanup from this test
domain.delete()
diff --git a/src/registrar/tests/test_admin_request.py b/src/registrar/tests/test_admin_request.py
index f19008ca1..a9b073472 100644
--- a/src/registrar/tests/test_admin_request.py
+++ b/src/registrar/tests/test_admin_request.py
@@ -1511,7 +1511,7 @@ class TestDomainRequestAdmin(MockEppLib):
self.test_helper.assert_response_contains_distinct_values(response, expected_other_employees_fields)
# Test for the copy link
- self.assertContains(response, "copy-to-clipboard", count=4)
+ self.assertContains(response, "button--clipboard", count=4)
# Test that Creator counts display properly
self.assertNotContains(response, "Approved domains")
@@ -1846,58 +1846,6 @@ class TestDomainRequestAdmin(MockEppLib):
def test_side_effects_when_saving_approved_to_ineligible(self):
self.trigger_saving_approved_to_another_state(False, DomainRequest.DomainRequestStatus.INELIGIBLE)
- @less_console_noise
- def test_error_when_saving_to_approved_and_domain_exists(self):
- """Redundant admin check on model transition not allowed."""
- Domain.objects.create(name="wabbitseason.gov")
-
- new_request = completed_domain_request(
- status=DomainRequest.DomainRequestStatus.SUBMITTED, name="wabbitseason.gov"
- )
-
- # Create a request object with a superuser
- request = self.factory.post("/admin/registrar/domainrequest/{}/change/".format(new_request.pk))
- request.user = self.superuser
-
- request.session = {}
-
- # Use ExitStack to combine patch contexts
- with ExitStack() as stack:
- # Patch django.contrib.messages.error
- stack.enter_context(patch.object(messages, "error"))
-
- new_request.status = DomainRequest.DomainRequestStatus.APPROVED
-
- self.admin.save_model(request, new_request, None, True)
-
- messages.error.assert_called_once_with(
- request,
- "Cannot approve. Requested domain is already in use.",
- )
-
- @less_console_noise
- def test_no_error_when_saving_to_approved_and_domain_exists(self):
- """The negative of the redundant admin check on model transition not allowed."""
- new_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.SUBMITTED)
-
- # Create a request object with a superuser
- request = self.factory.post("/admin/registrar/domainrequest/{}/change/".format(new_request.pk))
- request.user = self.superuser
-
- request.session = {}
-
- # Use ExitStack to combine patch contexts
- with ExitStack() as stack:
- # Patch Domain.is_active and django.contrib.messages.error simultaneously
- stack.enter_context(patch.object(messages, "error"))
-
- new_request.status = DomainRequest.DomainRequestStatus.APPROVED
-
- self.admin.save_model(request, new_request, None, True)
-
- # Assert that the error message was never called
- messages.error.assert_not_called()
-
def test_has_correct_filters(self):
"""
This test verifies that DomainRequestAdmin has the correct filters set up.
diff --git a/src/registrar/tests/test_models.py b/src/registrar/tests/test_models.py
index f1d25ece9..681d04c92 100644
--- a/src/registrar/tests/test_models.py
+++ b/src/registrar/tests/test_models.py
@@ -1,5 +1,7 @@
from django.forms import ValidationError
from django.test import TestCase
+from django.db.utils import IntegrityError
+from django.db import transaction
from unittest.mock import patch
from django.test import RequestFactory
@@ -18,18 +20,23 @@ from registrar.models import (
UserPortfolioPermission,
AllowedEmail,
)
+
import boto3_mocking
from registrar.models.portfolio import Portfolio
from registrar.models.portfolio_invitation import PortfolioInvitation
from registrar.models.transition_domain import TransitionDomain
from registrar.models.utility.portfolio_helper import UserPortfolioPermissionChoices, UserPortfolioRoleChoices
from registrar.models.verified_by_staff import VerifiedByStaff # type: ignore
+from registrar.utility.constants import BranchChoices
from .common import (
MockSESClient,
+ less_console_noise,
completed_domain_request,
+ set_domain_request_investigators,
create_test_user,
)
+from django_fsm import TransitionNotAllowed
from waffle.testutils import override_flag
from api.tests.common import less_console_noise_decorator
diff --git a/src/registrar/tests/test_models_requests.py b/src/registrar/tests/test_models_requests.py
deleted file mode 100644
index 9e86f5f9c..000000000
--- a/src/registrar/tests/test_models_requests.py
+++ /dev/null
@@ -1,1029 +0,0 @@
-from django.test import TestCase
-from django.db.utils import IntegrityError
-from django.db import transaction
-from unittest.mock import patch
-
-
-from registrar.models import (
- Contact,
- DomainRequest,
- DomainInformation,
- User,
- Website,
- Domain,
- DraftDomain,
- FederalAgency,
- AllowedEmail,
-)
-
-import boto3_mocking
-from registrar.utility.constants import BranchChoices
-from registrar.utility.errors import FSMDomainRequestError
-
-from .common import (
- MockSESClient,
- less_console_noise,
- completed_domain_request,
- set_domain_request_investigators,
-)
-from django_fsm import TransitionNotAllowed
-
-from api.tests.common import less_console_noise_decorator
-
-
-@boto3_mocking.patching
-class TestDomainRequest(TestCase):
- @less_console_noise_decorator
- def setUp(self):
-
- self.dummy_user, _ = Contact.objects.get_or_create(
- email="mayor@igorville.com", first_name="Hello", last_name="World"
- )
- self.dummy_user_2, _ = User.objects.get_or_create(
- username="intern@igorville.com", email="intern@igorville.com", first_name="Lava", last_name="World"
- )
- self.started_domain_request = completed_domain_request(
- status=DomainRequest.DomainRequestStatus.STARTED,
- name="started.gov",
- )
- self.submitted_domain_request = completed_domain_request(
- status=DomainRequest.DomainRequestStatus.SUBMITTED,
- name="submitted.gov",
- )
- self.in_review_domain_request = completed_domain_request(
- status=DomainRequest.DomainRequestStatus.IN_REVIEW,
- name="in-review.gov",
- )
- self.action_needed_domain_request = completed_domain_request(
- status=DomainRequest.DomainRequestStatus.ACTION_NEEDED,
- name="action-needed.gov",
- )
- self.approved_domain_request = completed_domain_request(
- status=DomainRequest.DomainRequestStatus.APPROVED,
- name="approved.gov",
- )
- self.withdrawn_domain_request = completed_domain_request(
- status=DomainRequest.DomainRequestStatus.WITHDRAWN,
- name="withdrawn.gov",
- )
- self.rejected_domain_request = completed_domain_request(
- status=DomainRequest.DomainRequestStatus.REJECTED,
- name="rejected.gov",
- )
- self.ineligible_domain_request = completed_domain_request(
- status=DomainRequest.DomainRequestStatus.INELIGIBLE,
- name="ineligible.gov",
- )
-
- # Store all domain request statuses in a variable for ease of use
- self.all_domain_requests = [
- self.started_domain_request,
- self.submitted_domain_request,
- self.in_review_domain_request,
- self.action_needed_domain_request,
- self.approved_domain_request,
- self.withdrawn_domain_request,
- self.rejected_domain_request,
- self.ineligible_domain_request,
- ]
-
- self.mock_client = MockSESClient()
-
- def tearDown(self):
- super().tearDown()
- DomainInformation.objects.all().delete()
- DomainRequest.objects.all().delete()
- DraftDomain.objects.all().delete()
- Domain.objects.all().delete()
- User.objects.all().delete()
- self.mock_client.EMAILS_SENT.clear()
-
- def assertNotRaises(self, exception_type):
- """Helper method for testing allowed transitions."""
- with less_console_noise():
- return self.assertRaises(Exception, None, exception_type)
-
- @less_console_noise_decorator
- def test_request_is_withdrawable(self):
- """Tests the is_withdrawable function"""
- domain_request_1 = completed_domain_request(
- status=DomainRequest.DomainRequestStatus.SUBMITTED,
- name="city2.gov",
- )
- domain_request_2 = completed_domain_request(
- status=DomainRequest.DomainRequestStatus.IN_REVIEW,
- name="city3.gov",
- )
- domain_request_3 = completed_domain_request(
- status=DomainRequest.DomainRequestStatus.ACTION_NEEDED,
- name="city4.gov",
- )
- domain_request_4 = completed_domain_request(
- status=DomainRequest.DomainRequestStatus.REJECTED,
- name="city5.gov",
- )
- self.assertTrue(domain_request_1.is_withdrawable())
- self.assertTrue(domain_request_2.is_withdrawable())
- self.assertTrue(domain_request_3.is_withdrawable())
- self.assertFalse(domain_request_4.is_withdrawable())
-
- @less_console_noise_decorator
- def test_request_is_awaiting_review(self):
- """Tests the is_awaiting_review function"""
- domain_request_1 = completed_domain_request(
- status=DomainRequest.DomainRequestStatus.SUBMITTED,
- name="city2.gov",
- )
- domain_request_2 = completed_domain_request(
- status=DomainRequest.DomainRequestStatus.IN_REVIEW,
- name="city3.gov",
- )
- domain_request_3 = completed_domain_request(
- status=DomainRequest.DomainRequestStatus.ACTION_NEEDED,
- name="city4.gov",
- )
- domain_request_4 = completed_domain_request(
- status=DomainRequest.DomainRequestStatus.REJECTED,
- name="city5.gov",
- )
- self.assertTrue(domain_request_1.is_awaiting_review())
- self.assertTrue(domain_request_2.is_awaiting_review())
- self.assertFalse(domain_request_3.is_awaiting_review())
- self.assertFalse(domain_request_4.is_awaiting_review())
-
- @less_console_noise_decorator
- def test_federal_agency_set_to_non_federal_on_approve(self):
- """Ensures that when the federal_agency field is 'none' when .approve() is called,
- the field is set to the 'Non-Federal Agency' record"""
- domain_request = completed_domain_request(
- status=DomainRequest.DomainRequestStatus.IN_REVIEW,
- name="city2.gov",
- federal_agency=None,
- )
-
- # Ensure that the federal agency is None
- self.assertEqual(domain_request.federal_agency, None)
-
- # Approve the request
- domain_request.approve()
- self.assertEqual(domain_request.status, DomainRequest.DomainRequestStatus.APPROVED)
-
- # After approval, it should be "Non-Federal agency"
- expected_federal_agency = FederalAgency.objects.filter(agency="Non-Federal Agency").first()
- self.assertEqual(domain_request.federal_agency, expected_federal_agency)
-
- def test_empty_create_fails(self):
- """Can't create a completely empty domain request."""
- with less_console_noise():
- with transaction.atomic():
- with self.assertRaisesRegex(IntegrityError, "creator"):
- DomainRequest.objects.create()
-
- @less_console_noise_decorator
- def test_minimal_create(self):
- """Can create with just a creator."""
- user, _ = User.objects.get_or_create(username="testy")
- domain_request = DomainRequest.objects.create(creator=user)
- self.assertEqual(domain_request.status, DomainRequest.DomainRequestStatus.STARTED)
-
- @less_console_noise_decorator
- def test_full_create(self):
- """Can create with all fields."""
- user, _ = User.objects.get_or_create(username="testy")
- contact = Contact.objects.create()
- com_website, _ = Website.objects.get_or_create(website="igorville.com")
- gov_website, _ = Website.objects.get_or_create(website="igorville.gov")
- domain, _ = DraftDomain.objects.get_or_create(name="igorville.gov")
- domain_request = DomainRequest.objects.create(
- creator=user,
- investigator=user,
- generic_org_type=DomainRequest.OrganizationChoices.FEDERAL,
- federal_type=BranchChoices.EXECUTIVE,
- is_election_board=False,
- organization_name="Test",
- address_line1="100 Main St.",
- address_line2="APT 1A",
- state_territory="CA",
- zipcode="12345-6789",
- senior_official=contact,
- requested_domain=domain,
- purpose="Igorville rules!",
- anything_else="All of Igorville loves the dotgov program.",
- is_policy_acknowledged=True,
- )
- domain_request.current_websites.add(com_website)
- domain_request.alternative_domains.add(gov_website)
- domain_request.other_contacts.add(contact)
- domain_request.save()
-
- @less_console_noise_decorator
- def test_domain_info(self):
- """Can create domain info with all fields."""
- user, _ = User.objects.get_or_create(username="testy")
- contact = Contact.objects.create()
- domain, _ = Domain.objects.get_or_create(name="igorville.gov")
- information = DomainInformation.objects.create(
- creator=user,
- generic_org_type=DomainInformation.OrganizationChoices.FEDERAL,
- federal_type=BranchChoices.EXECUTIVE,
- is_election_board=False,
- organization_name="Test",
- address_line1="100 Main St.",
- address_line2="APT 1A",
- state_territory="CA",
- zipcode="12345-6789",
- senior_official=contact,
- purpose="Igorville rules!",
- anything_else="All of Igorville loves the dotgov program.",
- is_policy_acknowledged=True,
- domain=domain,
- )
- information.other_contacts.add(contact)
- information.save()
- self.assertEqual(information.domain.id, domain.id)
- self.assertEqual(information.id, domain.domain_info.id)
-
- @less_console_noise_decorator
- def test_status_fsm_submit_fail(self):
- user, _ = User.objects.get_or_create(username="testy")
- domain_request = DomainRequest.objects.create(creator=user)
-
- with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
- with less_console_noise():
- with self.assertRaises(ValueError):
- # can't submit a domain request with a null domain name
- domain_request.submit()
-
- @less_console_noise_decorator
- def test_status_fsm_submit_succeed(self):
- user, _ = User.objects.get_or_create(username="testy")
- site = DraftDomain.objects.create(name="igorville.gov")
- domain_request = DomainRequest.objects.create(creator=user, requested_domain=site)
-
- # no email sent to creator so this emits a log warning
-
- with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
- with less_console_noise():
- domain_request.submit()
- self.assertEqual(domain_request.status, domain_request.DomainRequestStatus.SUBMITTED)
-
- @less_console_noise_decorator
- def check_email_sent(
- self, domain_request, msg, action, expected_count, expected_content=None, expected_email="mayor@igorville.com"
- ):
- """Check if an email was sent after performing an action."""
- email_allowed, _ = AllowedEmail.objects.get_or_create(email=expected_email)
- with self.subTest(msg=msg, action=action):
- with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
- # Perform the specified action
- action_method = getattr(domain_request, action)
- action_method()
-
- # Check if an email was sent
- sent_emails = [
- email
- for email in MockSESClient.EMAILS_SENT
- if expected_email in email["kwargs"]["Destination"]["ToAddresses"]
- ]
- self.assertEqual(len(sent_emails), expected_count)
-
- if expected_content:
- email_content = sent_emails[0]["kwargs"]["Content"]["Simple"]["Body"]["Text"]["Data"]
- self.assertIn(expected_content, email_content)
-
- email_allowed.delete()
-
- @less_console_noise_decorator
- def test_submit_from_started_sends_email_to_creator(self):
- """tests that we send an email to the creator"""
- msg = "Create a domain request and submit it and see if email was sent when the feature flag is on."
- domain_request = completed_domain_request(user=self.dummy_user_2)
- self.check_email_sent(
- domain_request, msg, "submit", 1, expected_content="Lava", expected_email="intern@igorville.com"
- )
-
- @less_console_noise_decorator
- def test_submit_from_withdrawn_sends_email(self):
- msg = "Create a withdrawn domain request and submit it and see if email was sent."
- user, _ = User.objects.get_or_create(username="testy")
- domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.WITHDRAWN, user=user)
- self.check_email_sent(domain_request, msg, "submit", 1, expected_content="Hi", expected_email=user.email)
-
- @less_console_noise_decorator
- def test_submit_from_action_needed_does_not_send_email(self):
- msg = "Create a domain request with ACTION_NEEDED status and submit it, check if email was not sent."
- domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.ACTION_NEEDED)
- self.check_email_sent(domain_request, msg, "submit", 0)
-
- @less_console_noise_decorator
- def test_submit_from_in_review_does_not_send_email(self):
- msg = "Create a withdrawn domain request and submit it and see if email was sent."
- domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.IN_REVIEW)
- self.check_email_sent(domain_request, msg, "submit", 0)
-
- @less_console_noise_decorator
- def test_approve_sends_email(self):
- msg = "Create a domain request and approve it and see if email was sent."
- user, _ = User.objects.get_or_create(username="testy")
- domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.IN_REVIEW, user=user)
- self.check_email_sent(domain_request, msg, "approve", 1, expected_content="approved", expected_email=user.email)
-
- @less_console_noise_decorator
- def test_withdraw_sends_email(self):
- msg = "Create a domain request and withdraw it and see if email was sent."
- user, _ = User.objects.get_or_create(username="testy")
- domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.IN_REVIEW, user=user)
- self.check_email_sent(
- domain_request, msg, "withdraw", 1, expected_content="withdrawn", expected_email=user.email
- )
-
- @less_console_noise_decorator
- def test_reject_sends_email(self):
- msg = "Create a domain request and reject it and see if email was sent."
- user, _ = User.objects.get_or_create(username="testy")
- domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.APPROVED, user=user)
- self.check_email_sent(domain_request, msg, "reject", 1, expected_content="Hi", expected_email=user.email)
-
- @less_console_noise_decorator
- def test_reject_with_prejudice_does_not_send_email(self):
- msg = "Create a domain request and reject it with prejudice and see if email was sent."
- domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.APPROVED)
- self.check_email_sent(domain_request, msg, "reject_with_prejudice", 0)
-
- @less_console_noise_decorator
- def assert_fsm_transition_raises_error(self, test_cases, method_to_run):
- """Given a list of test cases, check if each transition throws the intended error"""
- with boto3_mocking.clients.handler_for("sesv2", self.mock_client), less_console_noise():
- for domain_request, exception_type in test_cases:
- with self.subTest(domain_request=domain_request, exception_type=exception_type):
- with self.assertRaises(exception_type):
- # Retrieve the method by name from the domain_request object and call it
- method = getattr(domain_request, method_to_run)
- # Call the method
- method()
-
- @less_console_noise_decorator
- def assert_fsm_transition_does_not_raise_error(self, test_cases, method_to_run):
- """Given a list of test cases, ensure that none of them throw transition errors"""
- with boto3_mocking.clients.handler_for("sesv2", self.mock_client), less_console_noise():
- for domain_request, exception_type in test_cases:
- with self.subTest(domain_request=domain_request, exception_type=exception_type):
- try:
- # Retrieve the method by name from the DomainRequest object and call it
- method = getattr(domain_request, method_to_run)
- # Call the method
- method()
- except exception_type:
- self.fail(f"{exception_type} was raised, but it was not expected.")
-
- @less_console_noise_decorator
- def test_submit_transition_allowed_with_no_investigator(self):
- """
- Tests for attempting to transition without an investigator.
- For submit, this should be valid in all cases.
- """
-
- test_cases = [
- (self.started_domain_request, TransitionNotAllowed),
- (self.in_review_domain_request, TransitionNotAllowed),
- (self.action_needed_domain_request, TransitionNotAllowed),
- (self.withdrawn_domain_request, TransitionNotAllowed),
- ]
-
- # Set all investigators to none
- set_domain_request_investigators(self.all_domain_requests, None)
-
- self.assert_fsm_transition_does_not_raise_error(test_cases, "submit")
-
- @less_console_noise_decorator
- def test_submit_transition_allowed_with_investigator_not_staff(self):
- """
- Tests for attempting to transition with an investigator user that is not staff.
- For submit, this should be valid in all cases.
- """
-
- test_cases = [
- (self.in_review_domain_request, TransitionNotAllowed),
- (self.action_needed_domain_request, TransitionNotAllowed),
- ]
-
- # Set all investigators to a user with no staff privs
- user, _ = User.objects.get_or_create(username="pancakesyrup", is_staff=False)
- set_domain_request_investigators(self.all_domain_requests, user)
-
- self.assert_fsm_transition_does_not_raise_error(test_cases, "submit")
-
- @less_console_noise_decorator
- def test_submit_transition_allowed(self):
- """
- Test that calling submit from allowable statuses does raises TransitionNotAllowed.
- """
- test_cases = [
- (self.started_domain_request, TransitionNotAllowed),
- (self.in_review_domain_request, TransitionNotAllowed),
- (self.action_needed_domain_request, TransitionNotAllowed),
- (self.withdrawn_domain_request, TransitionNotAllowed),
- ]
-
- self.assert_fsm_transition_does_not_raise_error(test_cases, "submit")
-
- @less_console_noise_decorator
- def test_submit_transition_allowed_twice(self):
- """
- Test that rotating between submit and in_review doesn't throw an error
- """
- with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
- try:
- # Make a submission
- self.in_review_domain_request.submit()
-
- # Rerun the old method to get back to the original state
- self.in_review_domain_request.in_review()
-
- # Make another submission
- self.in_review_domain_request.submit()
- except TransitionNotAllowed:
- self.fail("TransitionNotAllowed was raised, but it was not expected.")
-
- self.assertEqual(self.in_review_domain_request.status, DomainRequest.DomainRequestStatus.SUBMITTED)
-
- @less_console_noise_decorator
- def test_submit_transition_not_allowed(self):
- """
- Test that calling submit against transition rules raises TransitionNotAllowed.
- """
- test_cases = [
- (self.submitted_domain_request, TransitionNotAllowed),
- (self.approved_domain_request, TransitionNotAllowed),
- (self.rejected_domain_request, TransitionNotAllowed),
- (self.ineligible_domain_request, TransitionNotAllowed),
- ]
-
- self.assert_fsm_transition_raises_error(test_cases, "submit")
-
- @less_console_noise_decorator
- def test_in_review_transition_allowed(self):
- """
- Test that calling in_review from allowable statuses does raises TransitionNotAllowed.
- """
- test_cases = [
- (self.submitted_domain_request, TransitionNotAllowed),
- (self.action_needed_domain_request, TransitionNotAllowed),
- (self.approved_domain_request, TransitionNotAllowed),
- (self.rejected_domain_request, TransitionNotAllowed),
- (self.ineligible_domain_request, TransitionNotAllowed),
- ]
-
- self.assert_fsm_transition_does_not_raise_error(test_cases, "in_review")
-
- @less_console_noise_decorator
- def test_in_review_transition_not_allowed_with_no_investigator(self):
- """
- Tests for attempting to transition without an investigator
- """
-
- test_cases = [
- (self.action_needed_domain_request, TransitionNotAllowed),
- (self.approved_domain_request, TransitionNotAllowed),
- (self.rejected_domain_request, TransitionNotAllowed),
- (self.ineligible_domain_request, TransitionNotAllowed),
- ]
-
- # Set all investigators to none
- set_domain_request_investigators(self.all_domain_requests, None)
-
- self.assert_fsm_transition_raises_error(test_cases, "in_review")
-
- @less_console_noise_decorator
- def test_in_review_transition_not_allowed_with_investigator_not_staff(self):
- """
- Tests for attempting to transition with an investigator that is not staff.
- This should throw an exception.
- """
-
- test_cases = [
- (self.action_needed_domain_request, TransitionNotAllowed),
- (self.approved_domain_request, TransitionNotAllowed),
- (self.rejected_domain_request, TransitionNotAllowed),
- (self.ineligible_domain_request, TransitionNotAllowed),
- ]
-
- # Set all investigators to a user with no staff privs
- user, _ = User.objects.get_or_create(username="pancakesyrup", is_staff=False)
- set_domain_request_investigators(self.all_domain_requests, user)
-
- self.assert_fsm_transition_raises_error(test_cases, "in_review")
-
- @less_console_noise_decorator
- def test_in_review_transition_not_allowed(self):
- """
- Test that calling in_review against transition rules raises TransitionNotAllowed.
- """
- test_cases = [
- (self.started_domain_request, TransitionNotAllowed),
- (self.in_review_domain_request, TransitionNotAllowed),
- (self.withdrawn_domain_request, TransitionNotAllowed),
- ]
-
- self.assert_fsm_transition_raises_error(test_cases, "in_review")
-
- @less_console_noise_decorator
- def test_action_needed_transition_allowed(self):
- """
- Test that calling action_needed from allowable statuses does raises TransitionNotAllowed.
- """
- test_cases = [
- (self.in_review_domain_request, TransitionNotAllowed),
- (self.approved_domain_request, TransitionNotAllowed),
- (self.rejected_domain_request, TransitionNotAllowed),
- (self.ineligible_domain_request, TransitionNotAllowed),
- ]
-
- self.assert_fsm_transition_does_not_raise_error(test_cases, "action_needed")
-
- @less_console_noise_decorator
- def test_action_needed_transition_not_allowed_with_no_investigator(self):
- """
- Tests for attempting to transition without an investigator
- """
-
- test_cases = [
- (self.in_review_domain_request, TransitionNotAllowed),
- (self.approved_domain_request, TransitionNotAllowed),
- (self.rejected_domain_request, TransitionNotAllowed),
- (self.ineligible_domain_request, TransitionNotAllowed),
- ]
-
- # Set all investigators to none
- set_domain_request_investigators(self.all_domain_requests, None)
-
- self.assert_fsm_transition_raises_error(test_cases, "action_needed")
-
- @less_console_noise_decorator
- def test_action_needed_transition_not_allowed_with_investigator_not_staff(self):
- """
- Tests for attempting to transition with an investigator that is not staff
- """
-
- test_cases = [
- (self.in_review_domain_request, TransitionNotAllowed),
- (self.approved_domain_request, TransitionNotAllowed),
- (self.rejected_domain_request, TransitionNotAllowed),
- (self.ineligible_domain_request, TransitionNotAllowed),
- ]
-
- # Set all investigators to a user with no staff privs
- user, _ = User.objects.get_or_create(username="pancakesyrup", is_staff=False)
- set_domain_request_investigators(self.all_domain_requests, user)
-
- self.assert_fsm_transition_raises_error(test_cases, "action_needed")
-
- @less_console_noise_decorator
- def test_action_needed_transition_not_allowed(self):
- """
- Test that calling action_needed against transition rules raises TransitionNotAllowed.
- """
- test_cases = [
- (self.started_domain_request, TransitionNotAllowed),
- (self.submitted_domain_request, TransitionNotAllowed),
- (self.action_needed_domain_request, TransitionNotAllowed),
- (self.withdrawn_domain_request, TransitionNotAllowed),
- ]
-
- self.assert_fsm_transition_raises_error(test_cases, "action_needed")
-
- @less_console_noise_decorator
- def test_approved_transition_allowed(self):
- """
- Test that calling action_needed from allowable statuses does raises TransitionNotAllowed.
- """
- test_cases = [
- (self.submitted_domain_request, TransitionNotAllowed),
- (self.in_review_domain_request, TransitionNotAllowed),
- (self.action_needed_domain_request, TransitionNotAllowed),
- (self.rejected_domain_request, TransitionNotAllowed),
- ]
-
- self.assert_fsm_transition_does_not_raise_error(test_cases, "approve")
-
- @less_console_noise_decorator
- def test_approved_transition_not_allowed_with_no_investigator(self):
- """
- Tests for attempting to transition without an investigator
- """
-
- test_cases = [
- (self.in_review_domain_request, TransitionNotAllowed),
- (self.action_needed_domain_request, TransitionNotAllowed),
- (self.rejected_domain_request, TransitionNotAllowed),
- ]
-
- # Set all investigators to none
- set_domain_request_investigators(self.all_domain_requests, None)
-
- self.assert_fsm_transition_raises_error(test_cases, "approve")
-
- @less_console_noise_decorator
- def test_approved_transition_not_allowed_with_investigator_not_staff(self):
- """
- Tests for attempting to transition with an investigator that is not staff
- """
-
- test_cases = [
- (self.in_review_domain_request, TransitionNotAllowed),
- (self.action_needed_domain_request, TransitionNotAllowed),
- (self.rejected_domain_request, TransitionNotAllowed),
- ]
-
- # Set all investigators to a user with no staff privs
- user, _ = User.objects.get_or_create(username="pancakesyrup", is_staff=False)
- set_domain_request_investigators(self.all_domain_requests, user)
-
- self.assert_fsm_transition_raises_error(test_cases, "approve")
-
- @less_console_noise_decorator
- def test_approved_skips_sending_email(self):
- """
- Test that calling .approve with send_email=False doesn't actually send
- an email
- """
-
- with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
- self.submitted_domain_request.approve(send_email=False)
-
- # Assert that no emails were sent
- self.assertEqual(len(self.mock_client.EMAILS_SENT), 0)
-
- @less_console_noise_decorator
- def test_approved_transition_not_allowed(self):
- """
- Test that calling approve against transition rules raises TransitionNotAllowed.
- """
- test_cases = [
- (self.started_domain_request, TransitionNotAllowed),
- (self.approved_domain_request, TransitionNotAllowed),
- (self.withdrawn_domain_request, TransitionNotAllowed),
- (self.ineligible_domain_request, TransitionNotAllowed),
- ]
- self.assert_fsm_transition_raises_error(test_cases, "approve")
-
- @less_console_noise_decorator
- def test_approved_transition_not_allowed_when_domain_already_approved(self):
- """
- Test that calling approve whith an already approved requested domain raises
- TransitionNotAllowed.
- """
- Domain.objects.all().create(name=self.submitted_domain_request.requested_domain.name)
- test_cases = [
- (self.submitted_domain_request, FSMDomainRequestError),
- ]
- self.assert_fsm_transition_raises_error(test_cases, "approve")
-
- @less_console_noise_decorator
- def test_withdraw_transition_allowed(self):
- """
- Test that calling action_needed from allowable statuses does raises TransitionNotAllowed.
- """
- test_cases = [
- (self.submitted_domain_request, TransitionNotAllowed),
- (self.in_review_domain_request, TransitionNotAllowed),
- (self.action_needed_domain_request, TransitionNotAllowed),
- ]
-
- self.assert_fsm_transition_does_not_raise_error(test_cases, "withdraw")
-
- @less_console_noise_decorator
- def test_withdraw_transition_allowed_with_no_investigator(self):
- """
- Tests for attempting to transition without an investigator.
- For withdraw, this should be valid in all cases.
- """
-
- test_cases = [
- (self.submitted_domain_request, TransitionNotAllowed),
- (self.in_review_domain_request, TransitionNotAllowed),
- (self.action_needed_domain_request, TransitionNotAllowed),
- ]
-
- # Set all investigators to none
- set_domain_request_investigators(self.all_domain_requests, None)
-
- self.assert_fsm_transition_does_not_raise_error(test_cases, "withdraw")
-
- @less_console_noise_decorator
- def test_withdraw_transition_allowed_with_investigator_not_staff(self):
- """
- Tests for attempting to transition when investigator is not staff.
- For withdraw, this should be valid in all cases.
- """
-
- test_cases = [
- (self.submitted_domain_request, TransitionNotAllowed),
- (self.in_review_domain_request, TransitionNotAllowed),
- (self.action_needed_domain_request, TransitionNotAllowed),
- ]
-
- # Set all investigators to a user with no staff privs
- user, _ = User.objects.get_or_create(username="pancakesyrup", is_staff=False)
- set_domain_request_investigators(self.all_domain_requests, user)
-
- self.assert_fsm_transition_does_not_raise_error(test_cases, "withdraw")
-
- @less_console_noise_decorator
- def test_withdraw_transition_not_allowed(self):
- """
- Test that calling action_needed against transition rules raises TransitionNotAllowed.
- """
- test_cases = [
- (self.started_domain_request, TransitionNotAllowed),
- (self.approved_domain_request, TransitionNotAllowed),
- (self.withdrawn_domain_request, TransitionNotAllowed),
- (self.rejected_domain_request, TransitionNotAllowed),
- (self.ineligible_domain_request, TransitionNotAllowed),
- ]
-
- self.assert_fsm_transition_raises_error(test_cases, "withdraw")
-
- @less_console_noise_decorator
- def test_reject_transition_allowed(self):
- """
- Test that calling action_needed from allowable statuses does raises TransitionNotAllowed.
- """
- test_cases = [
- (self.in_review_domain_request, TransitionNotAllowed),
- (self.action_needed_domain_request, TransitionNotAllowed),
- (self.approved_domain_request, TransitionNotAllowed),
- ]
-
- self.assert_fsm_transition_does_not_raise_error(test_cases, "reject")
-
- @less_console_noise_decorator
- def test_reject_transition_not_allowed_with_no_investigator(self):
- """
- Tests for attempting to transition without an investigator
- """
-
- test_cases = [
- (self.in_review_domain_request, TransitionNotAllowed),
- (self.action_needed_domain_request, TransitionNotAllowed),
- (self.approved_domain_request, TransitionNotAllowed),
- ]
-
- # Set all investigators to none
- set_domain_request_investigators(self.all_domain_requests, None)
-
- self.assert_fsm_transition_raises_error(test_cases, "reject")
-
- @less_console_noise_decorator
- def test_reject_transition_not_allowed_with_investigator_not_staff(self):
- """
- Tests for attempting to transition when investigator is not staff
- """
-
- test_cases = [
- (self.in_review_domain_request, TransitionNotAllowed),
- (self.action_needed_domain_request, TransitionNotAllowed),
- (self.approved_domain_request, TransitionNotAllowed),
- ]
-
- # Set all investigators to a user with no staff privs
- user, _ = User.objects.get_or_create(username="pancakesyrup", is_staff=False)
- set_domain_request_investigators(self.all_domain_requests, user)
-
- self.assert_fsm_transition_raises_error(test_cases, "reject")
-
- @less_console_noise_decorator
- def test_reject_transition_not_allowed(self):
- """
- Test that calling action_needed against transition rules raises TransitionNotAllowed.
- """
- test_cases = [
- (self.started_domain_request, TransitionNotAllowed),
- (self.submitted_domain_request, TransitionNotAllowed),
- (self.withdrawn_domain_request, TransitionNotAllowed),
- (self.rejected_domain_request, TransitionNotAllowed),
- (self.ineligible_domain_request, TransitionNotAllowed),
- ]
-
- self.assert_fsm_transition_raises_error(test_cases, "reject")
-
- @less_console_noise_decorator
- def test_reject_with_prejudice_transition_allowed(self):
- """
- Test that calling action_needed from allowable statuses does raises TransitionNotAllowed.
- """
- test_cases = [
- (self.in_review_domain_request, TransitionNotAllowed),
- (self.action_needed_domain_request, TransitionNotAllowed),
- (self.approved_domain_request, TransitionNotAllowed),
- (self.rejected_domain_request, TransitionNotAllowed),
- ]
-
- self.assert_fsm_transition_does_not_raise_error(test_cases, "reject_with_prejudice")
-
- @less_console_noise_decorator
- def test_reject_with_prejudice_transition_not_allowed_with_no_investigator(self):
- """
- Tests for attempting to transition without an investigator
- """
-
- test_cases = [
- (self.in_review_domain_request, TransitionNotAllowed),
- (self.action_needed_domain_request, TransitionNotAllowed),
- (self.approved_domain_request, TransitionNotAllowed),
- (self.rejected_domain_request, TransitionNotAllowed),
- ]
-
- # Set all investigators to none
- set_domain_request_investigators(self.all_domain_requests, None)
-
- self.assert_fsm_transition_raises_error(test_cases, "reject_with_prejudice")
-
- @less_console_noise_decorator
- def test_reject_with_prejudice_not_allowed_with_investigator_not_staff(self):
- """
- Tests for attempting to transition when investigator is not staff
- """
-
- test_cases = [
- (self.in_review_domain_request, TransitionNotAllowed),
- (self.action_needed_domain_request, TransitionNotAllowed),
- (self.approved_domain_request, TransitionNotAllowed),
- (self.rejected_domain_request, TransitionNotAllowed),
- ]
-
- # Set all investigators to a user with no staff privs
- user, _ = User.objects.get_or_create(username="pancakesyrup", is_staff=False)
- set_domain_request_investigators(self.all_domain_requests, user)
-
- self.assert_fsm_transition_raises_error(test_cases, "reject_with_prejudice")
-
- @less_console_noise_decorator
- def test_reject_with_prejudice_transition_not_allowed(self):
- """
- Test that calling action_needed against transition rules raises TransitionNotAllowed.
- """
- test_cases = [
- (self.started_domain_request, TransitionNotAllowed),
- (self.submitted_domain_request, TransitionNotAllowed),
- (self.withdrawn_domain_request, TransitionNotAllowed),
- (self.ineligible_domain_request, TransitionNotAllowed),
- ]
-
- self.assert_fsm_transition_raises_error(test_cases, "reject_with_prejudice")
-
- @less_console_noise_decorator
- def test_transition_not_allowed_approved_in_review_when_domain_is_active(self):
- """Create a domain request with status approved, create a matching domain that
- is active, and call in_review against transition rules"""
-
- domain = Domain.objects.create(name=self.approved_domain_request.requested_domain.name)
- self.approved_domain_request.approved_domain = domain
- self.approved_domain_request.save()
-
- # Define a custom implementation for is_active
- def custom_is_active(self):
- return True # Override to return True
-
- with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
- # Use patch to temporarily replace is_active with the custom implementation
- with patch.object(Domain, "is_active", custom_is_active):
- # Now, when you call is_active on Domain, it will return True
- with self.assertRaises(TransitionNotAllowed):
- self.approved_domain_request.in_review()
-
- @less_console_noise_decorator
- def test_transition_not_allowed_approved_action_needed_when_domain_is_active(self):
- """Create a domain request with status approved, create a matching domain that
- is active, and call action_needed against transition rules"""
-
- domain = Domain.objects.create(name=self.approved_domain_request.requested_domain.name)
- self.approved_domain_request.approved_domain = domain
- self.approved_domain_request.save()
-
- # Define a custom implementation for is_active
- def custom_is_active(self):
- return True # Override to return True
-
- with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
- # Use patch to temporarily replace is_active with the custom implementation
- with patch.object(Domain, "is_active", custom_is_active):
- # Now, when you call is_active on Domain, it will return True
- with self.assertRaises(TransitionNotAllowed):
- self.approved_domain_request.action_needed()
-
- @less_console_noise_decorator
- def test_transition_not_allowed_approved_rejected_when_domain_is_active(self):
- """Create a domain request with status approved, create a matching domain that
- is active, and call reject against transition rules"""
-
- domain = Domain.objects.create(name=self.approved_domain_request.requested_domain.name)
- self.approved_domain_request.approved_domain = domain
- self.approved_domain_request.save()
-
- # Define a custom implementation for is_active
- def custom_is_active(self):
- return True # Override to return True
-
- with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
- # Use patch to temporarily replace is_active with the custom implementation
- with patch.object(Domain, "is_active", custom_is_active):
- # Now, when you call is_active on Domain, it will return True
- with self.assertRaises(TransitionNotAllowed):
- self.approved_domain_request.reject()
-
- @less_console_noise_decorator
- def test_transition_not_allowed_approved_ineligible_when_domain_is_active(self):
- """Create a domain request with status approved, create a matching domain that
- is active, and call reject_with_prejudice against transition rules"""
-
- domain = Domain.objects.create(name=self.approved_domain_request.requested_domain.name)
- self.approved_domain_request.approved_domain = domain
- self.approved_domain_request.save()
-
- # Define a custom implementation for is_active
- def custom_is_active(self):
- return True # Override to return True
-
- with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
- # Use patch to temporarily replace is_active with the custom implementation
- with patch.object(Domain, "is_active", custom_is_active):
- # Now, when you call is_active on Domain, it will return True
- with self.assertRaises(TransitionNotAllowed):
- self.approved_domain_request.reject_with_prejudice()
-
- @less_console_noise_decorator
- def test_approve_from_rejected_clears_rejection_reason(self):
- """When transitioning from rejected to approved on a domain request,
- the rejection_reason is cleared."""
-
- # Create a sample domain request
- domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.REJECTED)
- domain_request.rejection_reason = DomainRequest.RejectionReasons.DOMAIN_PURPOSE
-
- # Approve
- with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
- domain_request.approve()
-
- self.assertEqual(domain_request.status, DomainRequest.DomainRequestStatus.APPROVED)
- self.assertEqual(domain_request.rejection_reason, None)
-
- @less_console_noise_decorator
- def test_in_review_from_rejected_clears_rejection_reason(self):
- """When transitioning from rejected to in_review on a domain request,
- the rejection_reason is cleared."""
-
- # Create a sample domain request
- domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.REJECTED)
- domain_request.domain_is_not_active = True
- domain_request.rejection_reason = DomainRequest.RejectionReasons.DOMAIN_PURPOSE
-
- # Approve
- with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
- domain_request.in_review()
-
- self.assertEqual(domain_request.status, DomainRequest.DomainRequestStatus.IN_REVIEW)
- self.assertEqual(domain_request.rejection_reason, None)
-
- @less_console_noise_decorator
- def test_action_needed_from_rejected_clears_rejection_reason(self):
- """When transitioning from rejected to action_needed on a domain request,
- the rejection_reason is cleared."""
-
- # Create a sample domain request
- domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.REJECTED)
- domain_request.domain_is_not_active = True
- domain_request.rejection_reason = DomainRequest.RejectionReasons.DOMAIN_PURPOSE
-
- # Approve
- with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
- domain_request.action_needed()
-
- self.assertEqual(domain_request.status, DomainRequest.DomainRequestStatus.ACTION_NEEDED)
- self.assertEqual(domain_request.rejection_reason, None)
-
- @less_console_noise_decorator
- def test_has_rationale_returns_true(self):
- """has_rationale() returns true when a domain request has no_other_contacts_rationale"""
- self.started_domain_request.no_other_contacts_rationale = "You talkin' to me?"
- self.started_domain_request.save()
- self.assertEquals(self.started_domain_request.has_rationale(), True)
-
- @less_console_noise_decorator
- def test_has_rationale_returns_false(self):
- """has_rationale() returns false when a domain request has no no_other_contacts_rationale"""
- self.assertEquals(self.started_domain_request.has_rationale(), False)
-
- @less_console_noise_decorator
- def test_has_other_contacts_returns_true(self):
- """has_other_contacts() returns true when a domain request has other_contacts"""
- # completed_domain_request has other contacts by default
- self.assertEquals(self.started_domain_request.has_other_contacts(), True)
-
- @less_console_noise_decorator
- def test_has_other_contacts_returns_false(self):
- """has_other_contacts() returns false when a domain request has no other_contacts"""
- domain_request = completed_domain_request(
- status=DomainRequest.DomainRequestStatus.STARTED, name="no-others.gov", has_other_contacts=False
- )
- self.assertEquals(domain_request.has_other_contacts(), False)
diff --git a/src/registrar/tests/test_views_request.py b/src/registrar/tests/test_views_request.py
index ff2e61939..8530859e2 100644
--- a/src/registrar/tests/test_views_request.py
+++ b/src/registrar/tests/test_views_request.py
@@ -82,6 +82,7 @@ class DomainRequestTests(TestWithUser, WebTest):
response = self.app.get(f"/domain-request/{domain_request.id}")
# Ensure that the date is still set to None
self.assertIsNone(domain_request.last_status_update)
+ print(response)
# We should still grab a date for this field in this event - but it should come from the audit log instead
self.assertContains(response, "Started on:")
self.assertContains(response, fixed_date.strftime("%B %-d, %Y"))