Merge branch 'main' into jon/425

This commit is contained in:
Jon Roberts 2023-02-27 13:24:06 -07:00
commit e213c7388b
No known key found for this signature in database
GPG key ID: EED093582198B041
8 changed files with 62 additions and 15 deletions

View file

@ -35,6 +35,7 @@ for step, view in [
(Step.PURPOSE, views.Purpose), (Step.PURPOSE, views.Purpose),
(Step.YOUR_CONTACT, views.YourContact), (Step.YOUR_CONTACT, views.YourContact),
(Step.OTHER_CONTACTS, views.OtherContacts), (Step.OTHER_CONTACTS, views.OtherContacts),
(Step.NO_OTHER_CONTACTS, views.NoOtherContacts),
(Step.ANYTHING_ELSE, views.AnythingElse), (Step.ANYTHING_ELSE, views.AnythingElse),
(Step.REQUIREMENTS, views.Requirements), (Step.REQUIREMENTS, views.Requirements),
(Step.REVIEW, views.Review), (Step.REVIEW, views.Review),

View file

@ -662,11 +662,11 @@ OtherContactsFormSet = forms.formset_factory(
class NoOtherContactsForm(RegistrarForm): class NoOtherContactsForm(RegistrarForm):
no_other_contacts_rationale = forms.CharField( no_other_contacts_rationale = forms.CharField(
required=False, required=True,
# label has to end in a space to get the label_suffix to show # label has to end in a space to get the label_suffix to show
label=( label=(
"If you cant provide other contacts for your organization," "Please explain why there are no other employees from your organization"
" please explain why." " that we can contact."
), ),
widget=forms.Textarea(), widget=forms.Textarea(),
) )

View file

@ -538,6 +538,10 @@ class DomainApplication(TimeStampedModel):
DomainApplication.OrganizationChoices.INTERSTATE, DomainApplication.OrganizationChoices.INTERSTATE,
] ]
def show_no_other_contacts_rationale(self) -> bool:
"""Show this step if the other contacts are blank."""
return not self.other_contacts.exists()
def is_federal(self) -> Union[bool, None]: def is_federal(self) -> Union[bool, None]:
"""Is this application for a federal agency? """Is this application for a federal agency?

View file

@ -0,0 +1,6 @@
{% extends 'application_form.html' %}
{% load static field_helpers %}
{% block form_fields %}
{% input_with_errors forms.0.no_other_contacts_rationale %}
{% endblock %}

View file

@ -2,7 +2,7 @@
{% load static field_helpers %} {% load static field_helpers %}
{% block form_instructions %} {% block form_instructions %}
<p>Wed like to contact other employees with administrative or technical responsibilities in your organization. For example, they could be involved in managing your organization or its technical infrastructure. This information will help us assess your eligibility and understand the purpose of the .gov domain. These contacts should be in addition to you and your authorizing official. They should be employees of your organization.</p> <p>Wed like to contact other employees in your organization about your domain request. For example, they could be involved in managing your organization or its technical infrastructure. <strong>This information will help us assess your eligibility for a .gov domain.</strong> These contacts should be in addition to you and your authorizing official. They should be employees of your organization.</p>
<p>Well email these contacts to let them know that you made this request.</p> <p>Well email these contacts to let them know that you made this request.</p>
{% endblock %} {% endblock %}
@ -14,7 +14,7 @@
{% for form in forms.0.forms %} {% for form in forms.0.forms %}
<fieldset class="usa-fieldset"> <fieldset class="usa-fieldset">
<legend> <legend>
<h2>Administrative or technical contact {{ forloop.counter }}</h2> <h2>Organization contact {{ forloop.counter }}</h2>
</legend> </legend>
{% input_with_errors form.first_name %} {% input_with_errors form.first_name %}
@ -39,8 +39,4 @@
<use xlink:href="{%static 'img/sprite.svg'%}#add_circle"></use> <use xlink:href="{%static 'img/sprite.svg'%}#add_circle"></use>
</svg><span class="margin-left-05">Add another contact</span> </svg><span class="margin-left-05">Add another contact</span>
</button> </button>
<h2>No contacts</h2>
{% input_with_errors forms.1.no_other_contacts_rationale %}
{% endblock %} {% endblock %}

View file

@ -36,7 +36,9 @@
{% endif %} {% endif %}
{% if step == Step.AUTHORIZING_OFFICIAL %} {% if step == Step.AUTHORIZING_OFFICIAL %}
{% if application.authorizing_official %} {% if application.authorizing_official %}
<div class="margin-bottom-105">
{% include "includes/contact.html" with contact=application.authorizing_official %} {% include "includes/contact.html" with contact=application.authorizing_official %}
</div>
{% else %} {% else %}
Incomplete Incomplete
{% endif %} {% endif %}
@ -51,8 +53,10 @@
</ul> </ul>
{% endif %} {% endif %}
{% if step == Step.DOTGOV_DOMAIN %} {% if step == Step.DOTGOV_DOMAIN %}
<ul class="add-list-reset"> <ul class="add-list-reset margin-bottom-105">
<li>{{ application.requested_domain.name|default:"Incomplete" }}</li> <li>{{ application.requested_domain.name|default:"Incomplete" }}</li>
</ul>
<ul class="add-list-reset">
{% for site in application.alternative_domains.all %} {% for site in application.alternative_domains.all %}
<li>{{ site.website }}</li> <li>{{ site.website }}</li>
{% endfor %} {% endfor %}
@ -63,23 +67,30 @@
{% endif %} {% endif %}
{% if step == Step.YOUR_CONTACT %} {% if step == Step.YOUR_CONTACT %}
{% if application.submitter %} {% if application.submitter %}
<div class="margin-bottom-105">
{% include "includes/contact.html" with contact=application.submitter %} {% include "includes/contact.html" with contact=application.submitter %}
</div>
{% else %} {% else %}
Incomplete Incomplete
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if step == Step.OTHER_CONTACTS %} {% if step == Step.OTHER_CONTACTS %}
{% for other in application.other_contacts.all %} {% for other in application.other_contacts.all %}
<div class="margin-bottom-105">
{% include "includes/contact.html" with contact=other %} {% include "includes/contact.html" with contact=other %}
</div>
{% empty %} {% empty %}
None None
{% endfor %} {% endfor %}
{% endif %} {% endif %}
{% if step == Step.NO_OTHER_CONTACTS %}
{{ application.no_other_contacts_rationale|default:"Incomplete" }}
{% endif %}
{% if step == Step.ANYTHING_ELSE %} {% if step == Step.ANYTHING_ELSE %}
{{ application.anything_else|default:"No" }} {{ application.anything_else|default:"No" }}
{% endif %} {% endif %}
{% if step == Step.REQUIREMENTS %} {% if step == Step.REQUIREMENTS %}
{{ application.is_policy_acknowledged|yesno:"Agree,Do not agree,Do not agree" }} {{ application.is_policy_acknowledged|yesno:"I agree.,I do not agree.,I do not agree." }}
{% endif %} {% endif %}
</div> </div>
</div> </div>

View file

@ -124,7 +124,8 @@ class DomainApplicationTests(TestWithUser, WebTest):
this test work. this test work.
""" """
num_pages_tested = 0 num_pages_tested = 0
SKIPPED_PAGES = 3 # elections, type_of_work, tribal_government # elections, type_of_work, tribal_government, no_other_contacts
SKIPPED_PAGES = 4
num_pages = len(self.TITLES) - SKIPPED_PAGES num_pages = len(self.TITLES) - SKIPPED_PAGES
type_page = self.app.get(reverse("application:")).follow() type_page = self.app.get(reverse("application:")).follow()
@ -696,6 +697,24 @@ class DomainApplicationTests(TestWithUser, WebTest):
self.assertContains(contact_page, self.TITLES[Step.TYPE_OF_WORK]) self.assertContains(contact_page, self.TITLES[Step.TYPE_OF_WORK])
def test_application_no_other_contacts(self):
"""Applicants with no other contacts have to give a reason."""
contacts_page = self.app.get(reverse("application:other_contacts"))
# django-webtest does not handle cookie-based sessions well because it keeps
# resetting the session key on each new request, thus destroying the concept
# of a "session". We are going to do it manually, saving the session ID here
# and then setting the cookie on each request.
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
result = contacts_page.form.submit()
# follow first redirect
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
no_contacts_page = result.follow()
expected_url_slug = str(Step.NO_OTHER_CONTACTS)
actual_url_slug = no_contacts_page.request.path.split("/")[-2]
self.assertEqual(expected_url_slug, actual_url_slug)
def test_application_type_of_work_interstate(self): def test_application_type_of_work_interstate(self):
"""Special districts have to answer an additional question.""" """Special districts have to answer an additional question."""
type_page = self.app.get(reverse("application:")).follow() type_page = self.app.get(reverse("application:")).follow()

View file

@ -37,6 +37,7 @@ class Step(StrEnum):
PURPOSE = "purpose" PURPOSE = "purpose"
YOUR_CONTACT = "your_contact" YOUR_CONTACT = "your_contact"
OTHER_CONTACTS = "other_contacts" OTHER_CONTACTS = "other_contacts"
NO_OTHER_CONTACTS = "no_other_contacts"
ANYTHING_ELSE = "anything_else" ANYTHING_ELSE = "anything_else"
REQUIREMENTS = "requirements" REQUIREMENTS = "requirements"
REVIEW = "review" REVIEW = "review"
@ -81,6 +82,7 @@ class ApplicationWizard(LoginRequiredMixin, TemplateView):
Step.PURPOSE: _("Purpose of your domain"), Step.PURPOSE: _("Purpose of your domain"),
Step.YOUR_CONTACT: _("Your contact information"), Step.YOUR_CONTACT: _("Your contact information"),
Step.OTHER_CONTACTS: _("Other contacts for your organization"), Step.OTHER_CONTACTS: _("Other contacts for your organization"),
Step.NO_OTHER_CONTACTS: _("No other employees from your organization?"),
Step.ANYTHING_ELSE: _("Anything else we should know?"), Step.ANYTHING_ELSE: _("Anything else we should know?"),
Step.REQUIREMENTS: _( Step.REQUIREMENTS: _(
"Requirements for registration and operation of .gov domains" "Requirements for registration and operation of .gov domains"
@ -99,6 +101,9 @@ class ApplicationWizard(LoginRequiredMixin, TemplateView):
"show_organization_election", False "show_organization_election", False
), ),
Step.TYPE_OF_WORK: lambda w: w.from_model("show_type_of_work", False), Step.TYPE_OF_WORK: lambda w: w.from_model("show_type_of_work", False),
Step.NO_OTHER_CONTACTS: lambda w: w.from_model(
"show_no_other_contacts_rationale", False
),
} }
def __init__(self): def __init__(self):
@ -423,7 +428,12 @@ class YourContact(ApplicationWizard):
class OtherContacts(ApplicationWizard): class OtherContacts(ApplicationWizard):
template_name = "application_other_contacts.html" template_name = "application_other_contacts.html"
forms = [forms.OtherContactsFormSet, forms.NoOtherContactsForm] forms = [forms.OtherContactsFormSet]
class NoOtherContacts(ApplicationWizard):
template_name = "application_no_other_contacts.html"
forms = [forms.NoOtherContactsForm]
class AnythingElse(ApplicationWizard): class AnythingElse(ApplicationWizard):