fixed conflicts

This commit is contained in:
asaki222 2025-01-10 11:02:13 -05:00
commit 185c0222d3
No known key found for this signature in database
GPG key ID: C51913A3A09FDC03
14 changed files with 394 additions and 60 deletions

View file

@ -1434,6 +1434,20 @@ class DomainInvitationAdmin(ListHeaderAdmin):
# Get the filtered values # Get the filtered values
return super().changelist_view(request, extra_context=extra_context) return super().changelist_view(request, extra_context=extra_context)
def save_model(self, request, obj, form, change):
"""
Override the save_model method.
On creation of a new domain invitation, attempt to retrieve the invitation,
which will be successful if a single User exists for that email; otherwise, will
just continue to create the invitation.
"""
if not change and User.objects.filter(email=obj.email).count() == 1:
# Domain Invitation creation for an existing User
obj.retrieve()
# Call the parent save method to save the object
super().save_model(request, obj, form, change)
class PortfolioInvitationAdmin(ListHeaderAdmin): class PortfolioInvitationAdmin(ListHeaderAdmin):
"""Custom portfolio invitation admin class.""" """Custom portfolio invitation admin class."""

View file

@ -351,6 +351,40 @@ div#content > h2 {
} }
} }
.module {
.margin-left-0 {
margin-left: 0;
}
.margin-top-0 {
margin-top: 0;
}
.padding-left-0 {
padding-left: 0;
}
}
.admin-list-inline {
li {
float: left;
padding-top: 0;
margin-right: 4px;
}
li:not(:last-child)::after {
content: ",";
}
}
.form-row {
.margin-y-0 {
margin-top: 0;
margin-bottom: 0;
}
.padding-y-0 {
padding-top: 0;
padding-bottom: 0;
}
}
// Fixes a display issue where the list was entirely white, or had too much whitespace // Fixes a display issue where the list was entirely white, or had too much whitespace
.select2-dropdown { .select2-dropdown {
display: inline-grid !important; display: inline-grid !important;

View file

@ -1575,7 +1575,7 @@ class Domain(TimeStampedModel, DomainHelper):
logger.info("Changing to DNS_NEEDED state") logger.info("Changing to DNS_NEEDED state")
logger.info("able to transition to DNS_NEEDED state") logger.info("able to transition to DNS_NEEDED state")
def get_state_help_text(self) -> str: def get_state_help_text(self, request=None) -> str:
"""Returns a str containing additional information about a given state. """Returns a str containing additional information about a given state.
Returns custom content for when the domain itself is expired.""" Returns custom content for when the domain itself is expired."""
@ -1585,6 +1585,8 @@ class Domain(TimeStampedModel, DomainHelper):
help_text = ( help_text = (
"This domain has expired, but it is still online. " "To renew this domain, contact help@get.gov." "This domain has expired, but it is still online. " "To renew this domain, contact help@get.gov."
) )
elif flag_is_active(request, "domain_renewal") and self.is_expiring():
help_text = "This domain will expire soon. Contact one of the listed domain managers to renew the domain."
else: else:
help_text = Domain.State.get_help_text(self.state) help_text = Domain.State.get_help_text(self.state)

View file

@ -109,22 +109,38 @@ This is using a custom implementation fieldset.html (see admin/fieldset.html)
This ONLY applies to analysts. For superusers, its business as usual. This ONLY applies to analysts. For superusers, its business as usual.
{% endcomment %} {% endcomment %}
<div class="readonly"> <div class="readonly">
{% with total_websites=field.contents|split:", " %} {% with total_websites=field.contents|split:", " %}
{% for website in total_websites %} {% if total_websites|length == 1 %}
<a href="{{ website }}" target="_blank" class="padding-top-1 current-website__{{forloop.counter}}">{{ website }}</a>{% if not forloop.last %}, {% endif %} <p class="margin-y-0 padding-y-0">
{# Acts as a <br> #} <a href="{{ total_websites.0 }}" target="_blank">
{% if total_websites|length < 5 %} {{ total_websites.0 }}
<div class="display-block margin-top-1"></div> </a>
</p>
{% elif total_websites|length > 1 %}
<ul class="margin-top-0 margin-left-0 padding-left-0{% if total_websites|length > 5 %} admin-list-inline{% endif %}">
{% for website in total_websites %}
{% comment %}White space matters: do NOT reformat the following line{% endcomment %}
<li><a href="{{ website }}" target="_blank">{{ website }}</a></li>
{% endfor %}
</ul>
{% endif %} {% endif %}
{% endfor %} {% endwith %}
{% endwith %}
</div> </div>
{% elif field.field.name == "alternative_domains" %} {% elif field.field.name == "alternative_domains" %}
<div class="readonly"> <div class="readonly">
{% with current_path=request.get_full_path %} {% with current_path=request.get_full_path %}
{% for alt_domain in original_object.alternative_domains.all %} {% if original_object.alternative_domains.all|length == 1 %}
<a href="{% url 'admin:registrar_website_change' alt_domain.id %}?{{ 'return_path='|add:current_path }}">{{ alt_domain }}</a>{% if not forloop.last %}, {% endif %} <p class="margin-y-0 padding-y-0">
{% endfor %} <a href="{% url 'admin:registrar_website_change' original_object.alternative_domains.all.0.id %}?{{ 'return_path='|add:current_path }}" target="_blank">{{ original_object.alternative_domains.all.0 }}</a>
</p>
{% elif original_object.alternative_domains.all|length > 1 %}
<ul class="margin-top-0 margin-left-0 padding-left-0 admin-list-inline">
{% for alt_domain in original_object.alternative_domains.all %}
{% comment %}White space matters: do NOT reformat the following line{% endcomment %}
<li><a href="{% url 'admin:registrar_website_change' alt_domain.id %}?{{ 'return_path='|add:current_path }}" target="_blank">{{alt_domain}}</a></li>
{% endfor %}
</ul>
{% endif %}
{% endwith %} {% endwith %}
</div> </div>
{% elif field.field.name == "domain_managers" or field.field.name == "invited_domain_managers" %} {% elif field.field.name == "domain_managers" or field.field.name == "invited_domain_managers" %}

View file

@ -49,11 +49,11 @@
</span> </span>
{% if domain.get_state_help_text %} {% if domain.get_state_help_text %}
<div class="padding-top-1 text-primary-darker"> <div class="padding-top-1 text-primary-darker">
{% if has_domain_renewal_flag and domain.is_expiring and is_domain_manager %} {% if has_domain_renewal_flag and domain.is_expired and is_domain_manager %}
This domain has expired, but it is still online. This domain has expired, but it is still online.
{% url 'domain-renewal' pk=domain.id as url %} {% url 'domain-renewal' pk=domain.id as url %}
<a href="{{ url }}">Renew to maintain access.</a> <a href="{{ url }}">Renew to maintain access.</a>
{% elif has_domain_renewal_flag and domain.is_expired and is_domain_manager %} {% elif has_domain_renewal_flag and domain.is_expiring and is_domain_manager %}
This domain will expire soon. This domain will expire soon.
{% url 'domain-renewal' pk=domain.id as url %} {% url 'domain-renewal' pk=domain.id as url %}
<a href="{{ url }}">Renew to maintain access.</a> <a href="{{ url }}">Renew to maintain access.</a>

View file

@ -51,8 +51,6 @@
{% url 'user-profile' as url %} {% url 'user-profile' as url %}
{% include "includes/summary_item.html" with title='Your Contact Information' value=request.user edit_link=url editable=is_editable contact='true' %} {% include "includes/summary_item.html" with title='Your Contact Information' value=request.user edit_link=url editable=is_editable contact='true' %}
{% if analyst_action != 'edit' or analyst_action_location != domain.pk %} {% if analyst_action != 'edit' or analyst_action_location != domain.pk %}
{% if is_portfolio_user and not is_domain_manager %} {% if is_portfolio_user and not is_domain_manager %}
<div class="usa-alert usa-alert--info usa-alert--slim"> <div class="usa-alert usa-alert--info usa-alert--slim">
@ -67,10 +65,11 @@
{% url 'domain-security-email' pk=domain.id as url %} {% url 'domain-security-email' pk=domain.id as url %}
{% if security_email is not None and security_email not in hidden_security_emails%} {% if security_email is not None and security_email not in hidden_security_emails%}
{% include "includes/summary_item.html" with title='Security email' value=security_email custom_text_for_value_none='We strongly recommend that you provide a security email. This email will allow the public to report observed or suspected security issues on your domain.' edit_link=url editable=is_editable %} {% include "includes/summary_item.html" with title='Security email' value=security_email custom_text_for_value_none='We strongly recommend that you provide a security email. This email will allow the public to report observed or suspected security issues on your domain.' edit_link=url editable=is_editable %}
{% else %} {% else %}
{% include "includes/summary_item.html" with title='Security email' value='None provided' custom_text_for_value_none='We strongly recommend that you provide a security email. This email will allow the public to report observed or suspected security issues on your domain.' edit_link=url editable=is_editable %} {% include "includes/summary_item.html" with title='Security email' value='None provided' custom_text_for_value_none='We strongly recommend that you provide a security email. This email will allow the public to report observed or suspected security issues on your domain.' edit_link=url editable=is_editable %}
{% endif %} {% endif %}
{% url 'domain-users' pk=domain.id as url %} {% url 'domain-users' pk=domain.id as url %}
{% if portfolio %} {% if portfolio %}
{% include "includes/summary_item.html" with title='Domain managers' domain_permissions=True value=domain edit_link=url editable=is_editable %} {% include "includes/summary_item.html" with title='Domain managers' domain_permissions=True value=domain edit_link=url editable=is_editable %}
@ -78,7 +77,6 @@
{% include "includes/summary_item.html" with title='Domain managers' list=True users=True value=domain.permissions.all edit_link=url editable=is_editable %} {% include "includes/summary_item.html" with title='Domain managers' list=True users=True value=domain.permissions.all edit_link=url editable=is_editable %}
{% endif %} {% endif %}
<div class="border-top-1px border-primary-dark padding-top-1 margin-top-3 margin-bottom-2"> <div class="border-top-1px border-primary-dark padding-top-1 margin-top-3 margin-bottom-2">
<fieldset class="usa-fieldset"> <fieldset class="usa-fieldset">
@ -103,7 +101,9 @@
class="usa-checkbox__input" class="usa-checkbox__input"
id="renewal-checkbox" id="renewal-checkbox"
type="checkbox" type="checkbox"
name="{{ form.is_policy_acknowledged.name }}"> name="{{ form.is_policy_acknowledged.name }}"
{% if form.is_policy_acknowledged.value %}checked{% endif %}
>
<label class="usa-checkbox__label" for="renewal-checkbox"> <label class="usa-checkbox__label" for="renewal-checkbox">
I read and agree to the I read and agree to the
<a href="https://get.gov/domains/requirements/" class="usa-link"> <a href="https://get.gov/domains/requirements/" class="usa-link">

View file

@ -172,7 +172,7 @@
>Deleted</label >Deleted</label
> >
</div> </div>
{% if has_domain_renewal_flag and num_expiring_domains > 0 %} {% if has_domain_renewal_flag %}
<div class="usa-checkbox"> <div class="usa-checkbox">
<input <input
class="usa-checkbox__input" class="usa-checkbox__input"

View file

@ -127,17 +127,15 @@
</ul> </ul>
{% endif %} {% endif %}
{% else %} {% else %}
<p class="margin-top-0 margin-bottom-0">
{% if custom_text_for_value_none %} {% if custom_text_for_value_none %}
<p class="text-base-dark">{{ custom_text_for_value_none }}</p> <p class="margin-top-0 text-base-dark">{{ custom_text_for_value_none }}</p>
{% endif %} {% endif %}
{% if value %} {% if value %}
{{ value }} {{ value }}
{% endif %} {% endif %}
{% if not value and not custom_text_for_value_none %} {% if not value %}
None None
{% endif %} {% endif %}
</p>
{% endif %} {% endif %}
</div> </div>

View file

@ -13,6 +13,7 @@ from django.contrib.auth import get_user_model, login
from django.utils.timezone import make_aware from django.utils.timezone import make_aware
from datetime import date, datetime, timedelta from datetime import date, datetime, timedelta
from django.utils import timezone from django.utils import timezone
from django.utils.html import strip_spaces_between_tags
from registrar.models import ( from registrar.models import (
Contact, Contact,
@ -107,6 +108,11 @@ def get_time_aware_date(date=datetime(2023, 11, 1)):
return timezone.make_aware(date) return timezone.make_aware(date)
def normalize_html(html):
"""Normalize HTML by removing newlines and extra spaces."""
return strip_spaces_between_tags(" ".join(html.split()))
class GenericTestHelper(TestCase): class GenericTestHelper(TestCase):
"""A helper class that contains various helper functions for TestCases""" """A helper class that contains various helper functions for TestCases"""
@ -1017,8 +1023,9 @@ def create_ready_domain():
# TODO in 1793: Remove the federal agency/updated federal agency fields # TODO in 1793: Remove the federal agency/updated federal agency fields
def completed_domain_request( # noqa def completed_domain_request( # noqa
has_other_contacts=True, has_other_contacts=True,
has_current_website=True, # pass empty [] if you want current_websites or alternative_domains set to None
has_alternative_gov_domain=True, current_websites=["city.com"],
alternative_domains=["city1.gov"],
has_about_your_organization=True, has_about_your_organization=True,
has_anything_else=True, has_anything_else=True,
has_cisa_representative=True, has_cisa_representative=True,
@ -1050,8 +1057,6 @@ def completed_domain_request( # noqa
phone="(555) 555 5555", phone="(555) 555 5555",
) )
domain, _ = DraftDomain.objects.get_or_create(name=name) domain, _ = DraftDomain.objects.get_or_create(name=name)
alt, _ = Website.objects.get_or_create(website="city1.gov")
current, _ = Website.objects.get_or_create(website="city.com")
other, _ = Contact.objects.get_or_create( other, _ = Contact.objects.get_or_create(
first_name="Testy", first_name="Testy",
last_name="Tester", last_name="Tester",
@ -1118,10 +1123,14 @@ def completed_domain_request( # noqa
if has_other_contacts: if has_other_contacts:
domain_request.other_contacts.add(other) domain_request.other_contacts.add(other)
if has_current_website: if len(current_websites) > 0:
domain_request.current_websites.add(current) for website in current_websites:
if has_alternative_gov_domain: current, _ = Website.objects.get_or_create(website=website)
domain_request.alternative_domains.add(alt) domain_request.current_websites.add(current)
if len(alternative_domains) > 0:
for alternative_domain in alternative_domains:
alt, _ = Website.objects.get_or_create(website=alternative_domain)
domain_request.alternative_domains.add(alt)
if has_cisa_representative: if has_cisa_representative:
domain_request.cisa_representative_first_name = "CISA-first-name" domain_request.cisa_representative_first_name = "CISA-first-name"
domain_request.cisa_representative_last_name = "CISA-last-name" domain_request.cisa_representative_last_name = "CISA-last-name"

View file

@ -131,13 +131,11 @@ class TestDomainInvitationAdmin(TestCase):
tests have available superuser, client, and admin tests have available superuser, client, and admin
""" """
@classmethod
def setUpClass(cls):
cls.factory = RequestFactory()
cls.admin = ListHeaderAdmin(model=DomainInvitationAdmin, admin_site=AdminSite())
cls.superuser = create_superuser()
def setUp(self): def setUp(self):
self.factory = RequestFactory()
self.admin = ListHeaderAdmin(model=DomainInvitationAdmin, admin_site=AdminSite())
self.superuser = create_superuser()
self.domain = Domain.objects.create(name="example.com")
"""Create a client object""" """Create a client object"""
self.client = Client(HTTP_HOST="localhost:8080") self.client = Client(HTTP_HOST="localhost:8080")
@ -145,9 +143,6 @@ class TestDomainInvitationAdmin(TestCase):
"""Delete all DomainInvitation objects""" """Delete all DomainInvitation objects"""
DomainInvitation.objects.all().delete() DomainInvitation.objects.all().delete()
Contact.objects.all().delete() Contact.objects.all().delete()
@classmethod
def tearDownClass(self):
User.objects.all().delete() User.objects.all().delete()
@less_console_noise_decorator @less_console_noise_decorator
@ -168,6 +163,7 @@ class TestDomainInvitationAdmin(TestCase):
) )
self.assertContains(response, "Show more") self.assertContains(response, "Show more")
@less_console_noise_decorator
def test_get_filters(self): def test_get_filters(self):
"""Ensures that our filters are displaying correctly""" """Ensures that our filters are displaying correctly"""
with less_console_noise(): with less_console_noise():
@ -192,6 +188,59 @@ class TestDomainInvitationAdmin(TestCase):
self.assertContains(response, invited_html, count=1) self.assertContains(response, invited_html, count=1)
self.assertContains(response, retrieved_html, count=1) self.assertContains(response, retrieved_html, count=1)
@less_console_noise_decorator
def test_save_model_user_exists(self):
"""Test saving a domain invitation when the user exists.
Should attempt to retrieve the domain invitation."""
# Create a user with the same email
User.objects.create_user(email="test@example.com", username="username")
# Create a domain invitation instance
invitation = DomainInvitation(email="test@example.com", domain=self.domain)
admin_instance = DomainInvitationAdmin(DomainInvitation, admin_site=None)
# Create a request object
request = self.factory.post("/admin/registrar/DomainInvitation/add/")
request.user = self.superuser
# Patch the retrieve method
with patch.object(DomainInvitation, "retrieve") as mock_retrieve:
admin_instance.save_model(request, invitation, form=None, change=False)
# Assert retrieve was called
mock_retrieve.assert_called_once()
# Assert the invitation was saved
self.assertEqual(DomainInvitation.objects.count(), 1)
self.assertEqual(DomainInvitation.objects.first().email, "test@example.com")
@less_console_noise_decorator
def test_save_model_user_does_not_exist(self):
"""Test saving a domain invitation when the user does not exist.
Should not attempt to retrieve the domain invitation."""
# Create a domain invitation instance
invitation = DomainInvitation(email="nonexistent@example.com", domain=self.domain)
admin_instance = DomainInvitationAdmin(DomainInvitation, admin_site=None)
# Create a request object
request = self.factory.post("/admin/registrar/DomainInvitation/add/")
request.user = self.superuser
# Patch the retrieve method to ensure it is not called
with patch.object(DomainInvitation, "retrieve") as mock_retrieve:
admin_instance.save_model(request, invitation, form=None, change=False)
# Assert retrieve was not called
mock_retrieve.assert_not_called()
# Assert the invitation was saved
self.assertEqual(DomainInvitation.objects.count(), 1)
self.assertEqual(DomainInvitation.objects.first().email, "nonexistent@example.com")
class TestUserPortfolioPermissionAdmin(TestCase): class TestUserPortfolioPermissionAdmin(TestCase):
"""Tests for the PortfolioInivtationAdmin class""" """Tests for the PortfolioInivtationAdmin class"""

View file

@ -40,6 +40,7 @@ from .common import (
multiple_unalphabetical_domain_objects, multiple_unalphabetical_domain_objects,
MockEppLib, MockEppLib,
GenericTestHelper, GenericTestHelper,
normalize_html,
) )
from unittest.mock import ANY, patch from unittest.mock import ANY, patch
@ -1530,8 +1531,9 @@ class TestDomainRequestAdmin(MockEppLib):
self.assertContains(response, expected_url) self.assertContains(response, expected_url)
@less_console_noise_decorator @less_console_noise_decorator
def test_other_websites_has_readonly_link(self): def test_other_websites_has_one_readonly_link(self):
"""Tests if the readonly other_websites field has links""" """Tests if the readonly other_websites field has links.
Test markup for one website."""
# Create a fake domain request # Create a fake domain request
domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.IN_REVIEW) domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.IN_REVIEW)
@ -1547,8 +1549,224 @@ class TestDomainRequestAdmin(MockEppLib):
self.assertContains(response, domain_request.requested_domain.name) self.assertContains(response, domain_request.requested_domain.name)
# Check that the page contains the link we expect. # Check that the page contains the link we expect.
expected_url = '<a href="city.com" target="_blank" class="padding-top-1 current-website__1">city.com</a>' expected_markup = """
self.assertContains(response, expected_url) <p class="margin-y-0 padding-y-0">
<a href="city.com" target="_blank">
city.com
</a>
</p>
"""
normalized_expected = normalize_html(expected_markup)
normalized_response = normalize_html(response.content.decode("utf-8"))
index = normalized_response.find(normalized_expected)
# Assert that the expected markup is found in the response
if index == -1:
self.fail(
f"Expected markup not found in the response.\n\n"
f"Expected:\n{normalized_expected}\n\n"
f"Start index of mismatch: {index}\n\n"
f"Consider checking the surrounding response for context."
)
@less_console_noise_decorator
def test_other_websites_has_few_readonly_links(self):
"""Tests if the readonly other_websites field has links.
Test markup for 5 or less websites."""
# Create a domain request with 4 current websites
domain_request = completed_domain_request(
status=DomainRequest.DomainRequestStatus.IN_REVIEW,
current_websites=["city.gov", "city2.gov", "city3.gov", "city4.gov"],
)
self.client.force_login(self.staffuser)
response = self.client.get(
"/admin/registrar/domainrequest/{}/change/".format(domain_request.pk),
follow=True,
)
# Make sure the page loaded, and that we're on the right page
self.assertEqual(response.status_code, 200)
self.assertContains(response, domain_request.requested_domain.name)
# Check that the page contains the link we expect.
expected_markup = """
<ul class="margin-top-0 margin-left-0 padding-left-0">
<li><a href="city.gov" target="_blank">city.gov</a></li>
<li><a href="city2.gov" target="_blank">city2.gov</a></li>
<li><a href="city3.gov" target="_blank">city3.gov</a></li>
<li><a href="city4.gov" target="_blank">city4.gov</a></li>
</ul>
"""
normalized_expected = normalize_html(expected_markup)
normalized_response = normalize_html(response.content.decode("utf-8"))
index = normalized_response.find(normalized_expected)
# Assert that the expected markup is found in the response
if index == -1:
self.fail(
f"Expected markup not found in the response.\n\n"
f"Expected:\n{normalized_expected}\n\n"
f"Start index of mismatch: {index}\n\n"
f"Consider checking the surrounding response for context."
)
@less_console_noise_decorator
def test_other_websites_has_lots_readonly_links(self):
"""Tests if the readonly other_websites field has links.
Test markup for 6 or more websites."""
# Create a domain requests with 6 current websites
domain_request = completed_domain_request(
status=DomainRequest.DomainRequestStatus.IN_REVIEW,
current_websites=["city.gov", "city2.gov", "city3.gov", "city4.gov", "city5.gov", "city6.gov"],
)
self.client.force_login(self.staffuser)
response = self.client.get(
"/admin/registrar/domainrequest/{}/change/".format(domain_request.pk),
follow=True,
)
# Make sure the page loaded, and that we're on the right page
self.assertEqual(response.status_code, 200)
self.assertContains(response, domain_request.requested_domain.name)
# Check that the page contains the link we expect.
expected_markup = """
<ul class="margin-top-0 margin-left-0 padding-left-0 admin-list-inline">
<li><a href="city.gov" target="_blank">city.gov</a></li>
<li><a href="city2.gov" target="_blank">city2.gov</a></li>
<li><a href="city3.gov" target="_blank">city3.gov</a></li>
<li><a href="city4.gov" target="_blank">city4.gov</a></li>
<li><a href="city5.gov" target="_blank">city5.gov</a></li>
<li><a href="city6.gov" target="_blank">city6.gov</a></li>
</ul>
"""
normalized_expected = normalize_html(expected_markup)
normalized_response = normalize_html(response.content.decode("utf-8"))
index = normalized_response.find(normalized_expected)
# Assert that the expected markup is found in the response
if index == -1:
self.fail(
f"Expected markup not found in the response.\n\n"
f"Expected:\n{normalized_expected}\n\n"
f"Start index of mismatch: {index}\n\n"
f"Consider checking the surrounding response for context."
)
@less_console_noise_decorator
def test_alternative_domains_has_one_readonly_link(self):
"""Tests if the readonly alternative_domains field has links.
Test markup for one website."""
# Create a fake domain request
domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.IN_REVIEW)
self.client.force_login(self.staffuser)
response = self.client.get(
"/admin/registrar/domainrequest/{}/change/".format(domain_request.pk),
follow=True,
)
# Make sure the page loaded, and that we're on the right page
self.assertEqual(response.status_code, 200)
self.assertContains(response, domain_request.requested_domain.name)
# Check that the page contains the link we expect.
website = Website.objects.filter(website="city1.gov").first()
base_url = "/admin/registrar/website"
return_path = f"/admin/registrar/domainrequest/{domain_request.pk}/change/"
expected_markup = f"""
<p class="margin-y-0 padding-y-0">
<a href="{base_url}/{website.pk}/change/?return_path={return_path}" target="_blank">city1.gov</a>
</p>
"""
normalized_expected = normalize_html(expected_markup)
normalized_response = normalize_html(response.content.decode("utf-8"))
index = normalized_response.find(normalized_expected)
# Assert that the expected markup is found in the response
if index == -1:
self.fail(
f"Expected markup not found in the response.\n\n"
f"Expected:\n{normalized_expected}\n\n"
f"Start index of mismatch: {index}\n\n"
f"Consider checking the surrounding response for context."
)
@less_console_noise_decorator
def test_alternative_domains_has_lots_readonly_link(self):
"""Tests if the readonly other_websites field has links.
Test markup for 6 or more websites."""
# Create a domain request with 6 alternative domains
domain_request = completed_domain_request(
status=DomainRequest.DomainRequestStatus.IN_REVIEW,
alternative_domains=[
"altcity1.gov",
"altcity2.gov",
"altcity3.gov",
"altcity4.gov",
"altcity5.gov",
"altcity6.gov",
],
)
self.client.force_login(self.staffuser)
response = self.client.get(
"/admin/registrar/domainrequest/{}/change/".format(domain_request.pk),
follow=True,
)
# Make sure the page loaded, and that we're on the right page
self.assertEqual(response.status_code, 200)
self.assertContains(response, domain_request.requested_domain.name)
# Check that the page contains the link we expect.
website1 = Website.objects.filter(website="altcity1.gov").first()
website2 = Website.objects.filter(website="altcity2.gov").first()
website3 = Website.objects.filter(website="altcity3.gov").first()
website4 = Website.objects.filter(website="altcity4.gov").first()
website5 = Website.objects.filter(website="altcity5.gov").first()
website6 = Website.objects.filter(website="altcity6.gov").first()
base_url = "/admin/registrar/website"
return_path = f"/admin/registrar/domainrequest/{domain_request.pk}/change/"
attr = 'target="_blank"'
expected_markup = f"""
<ul class="margin-top-0 margin-left-0 padding-left-0 admin-list-inline">
<li><a href="{base_url}/{website1.pk}/change/?return_path={return_path}" {attr}>altcity1.gov</a></li>
<li><a href="{base_url}/{website2.pk}/change/?return_path={return_path}" {attr}>altcity2.gov</a></li>
<li><a href="{base_url}/{website3.pk}/change/?return_path={return_path}" {attr}>altcity3.gov</a></li>
<li><a href="{base_url}/{website4.pk}/change/?return_path={return_path}" {attr}>altcity4.gov</a></li>
<li><a href="{base_url}/{website5.pk}/change/?return_path={return_path}" {attr}>altcity5.gov</a></li>
<li><a href="{base_url}/{website6.pk}/change/?return_path={return_path}" {attr}>altcity6.gov</a></li>
</ul>
"""
normalized_expected = normalize_html(expected_markup)
normalized_response = normalize_html(response.content.decode("utf-8"))
index = normalized_response.find(normalized_expected)
# Assert that the expected markup is found in the response
if index == -1:
self.fail(
f"Expected markup not found in the response.\n\n"
f"Expected:\n{normalized_expected}\n\n"
f"Start index of mismatch: {index}\n\n"
f"Consider checking the surrounding response for context."
)
@less_console_noise_decorator @less_console_noise_decorator
def test_contact_fields_have_detail_table(self): def test_contact_fields_have_detail_table(self):

View file

@ -150,7 +150,7 @@ class TestEmails(TestCase):
def test_submission_confirmation_no_current_website_spacing(self): def test_submission_confirmation_no_current_website_spacing(self):
"""Test line spacing without current_website.""" """Test line spacing without current_website."""
domain_request = completed_domain_request( domain_request = completed_domain_request(
has_current_website=False, user=User.objects.create(username="test", email="testy@town.com") current_websites=[], user=User.objects.create(username="test", email="testy@town.com")
) )
with boto3_mocking.clients.handler_for("sesv2", self.mock_client_class): with boto3_mocking.clients.handler_for("sesv2", self.mock_client_class):
domain_request.submit() domain_request.submit()
@ -164,9 +164,7 @@ class TestEmails(TestCase):
@less_console_noise_decorator @less_console_noise_decorator
def test_submission_confirmation_current_website_spacing(self): def test_submission_confirmation_current_website_spacing(self):
"""Test line spacing with current_website.""" """Test line spacing with current_website."""
domain_request = completed_domain_request( domain_request = completed_domain_request(user=User.objects.create(username="test", email="testy@town.com"))
has_current_website=True, user=User.objects.create(username="test", email="testy@town.com")
)
with boto3_mocking.clients.handler_for("sesv2", self.mock_client_class): with boto3_mocking.clients.handler_for("sesv2", self.mock_client_class):
domain_request.submit() domain_request.submit()
_, kwargs = self.mock_client.send_email.call_args _, kwargs = self.mock_client.send_email.call_args
@ -218,9 +216,7 @@ class TestEmails(TestCase):
@less_console_noise_decorator @less_console_noise_decorator
def test_submission_confirmation_alternative_govdomain_spacing(self): def test_submission_confirmation_alternative_govdomain_spacing(self):
"""Test line spacing with alternative .gov domain.""" """Test line spacing with alternative .gov domain."""
domain_request = completed_domain_request( domain_request = completed_domain_request(user=User.objects.create(username="test", email="testy@town.com"))
has_alternative_gov_domain=True, user=User.objects.create(username="test", email="testy@town.com")
)
with boto3_mocking.clients.handler_for("sesv2", self.mock_client_class): with boto3_mocking.clients.handler_for("sesv2", self.mock_client_class):
domain_request.submit() domain_request.submit()
_, kwargs = self.mock_client.send_email.call_args _, kwargs = self.mock_client.send_email.call_args
@ -234,7 +230,7 @@ class TestEmails(TestCase):
def test_submission_confirmation_no_alternative_govdomain_spacing(self): def test_submission_confirmation_no_alternative_govdomain_spacing(self):
"""Test line spacing without alternative .gov domain.""" """Test line spacing without alternative .gov domain."""
domain_request = completed_domain_request( domain_request = completed_domain_request(
has_alternative_gov_domain=False, user=User.objects.create(username="test", email="testy@town.com") alternative_domains=[], user=User.objects.create(username="test", email="testy@town.com")
) )
with boto3_mocking.clients.handler_for("sesv2", self.mock_client_class): with boto3_mocking.clients.handler_for("sesv2", self.mock_client_class):
domain_request.submit() domain_request.submit()

View file

@ -606,10 +606,10 @@ class TestDomainDetailDomainRenewal(TestDomainOverview):
# Start on the Renewal page for the domain # Start on the Renewal page for the domain
renewal_page = self.app.get(reverse("domain-renewal", kwargs={"pk": self.domain_with_ip.id})) renewal_page = self.app.get(reverse("domain-renewal", kwargs={"pk": self.domain_with_ip.id}))
# Verify we see "Your Contact Information" on the renewal form # Verify we see "Your contact information" on the renewal form
self.assertContains(renewal_page, "Your Contact Information") self.assertContains(renewal_page, "Your contact information")
# Verify that the "Edit" button for Your Contact is there and links to correct URL # Verify that the "Edit" button for Your contact is there and links to correct URL
edit_button_url = reverse("user-profile") edit_button_url = reverse("user-profile")
self.assertContains(renewal_page, f'href="{edit_button_url}"') self.assertContains(renewal_page, f'href="{edit_button_url}"')
@ -2816,7 +2816,6 @@ class TestDomainRenewal(TestWithUser):
UserDomainRole.objects.filter(user=self.user, domain=self.domain_with_expiring_soon_date).delete() UserDomainRole.objects.filter(user=self.user, domain=self.domain_with_expiring_soon_date).delete()
self.client.force_login(self.user) self.client.force_login(self.user)
domains_page = self.client.get("/") domains_page = self.client.get("/")
self.assertNotContains(domains_page, "Expiring soon")
self.assertNotContains(domains_page, "will expire soon") self.assertNotContains(domains_page, "will expire soon")
@less_console_noise_decorator @less_console_noise_decorator
@ -2854,5 +2853,4 @@ class TestDomainRenewal(TestWithUser):
UserDomainRole.objects.filter(user=self.user, domain=self.domain_with_expiring_soon_date).delete() UserDomainRole.objects.filter(user=self.user, domain=self.domain_with_expiring_soon_date).delete()
self.client.force_login(self.user) self.client.force_login(self.user)
domains_page = self.client.get("/") domains_page = self.client.get("/")
self.assertNotContains(domains_page, "Expiring soon")
self.assertNotContains(domains_page, "will expire soon") self.assertNotContains(domains_page, "will expire soon")

View file

@ -315,7 +315,7 @@ class DomainRenewalView(DomainView):
"""Domain detail overview page.""" """Domain detail overview page."""
template_name = "domain_renewal.html" template_name = "domain_renewal.html"
def can_access_domain_via_portfolio(self, pk): def can_access_domain_via_portfolio(self, pk):
"""Most views should not allow permission to portfolio users. """Most views should not allow permission to portfolio users.
If particular views allow permissions, they will need to override If particular views allow permissions, they will need to override