mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-07-25 20:18:38 +02:00
fixed conflicts
This commit is contained in:
commit
185c0222d3
14 changed files with 394 additions and 60 deletions
|
@ -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."""
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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" %}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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"""
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue