Unrecognized tribal government more explanation

This commit is contained in:
Neil Martinsen-Burrell 2023-01-24 10:19:52 -06:00
parent 2c66b3728e
commit 2cd53dc4c8
No known key found for this signature in database
GPG key ID: 6A3C818CC10D0184
6 changed files with 148 additions and 6 deletions

View file

@ -25,6 +25,7 @@ for step, view in [
# add/remove steps here # add/remove steps here
(Step.ORGANIZATION_TYPE, views.OrganizationType), (Step.ORGANIZATION_TYPE, views.OrganizationType),
(Step.TRIBAL_GOVERNMENT, views.TribalGovernment), (Step.TRIBAL_GOVERNMENT, views.TribalGovernment),
(Step.TRIBAL_EXPLANATION, views.TribalExplanation),
(Step.ORGANIZATION_FEDERAL, views.OrganizationFederal), (Step.ORGANIZATION_FEDERAL, views.OrganizationFederal),
(Step.ORGANIZATION_ELECTION, views.OrganizationElection), (Step.ORGANIZATION_ELECTION, views.OrganizationElection),
(Step.ORGANIZATION_CONTACT, views.OrganizationContact), (Step.ORGANIZATION_CONTACT, views.OrganizationContact),

View file

@ -83,11 +83,26 @@ class TribalGovernmentForm(RegistrarForm):
error_messages={"required": "Enter the tribe you represent."}, error_messages={"required": "Enter the tribe you represent."},
) )
def clean(self):
"""Needs to be either state or federally recognized.""" class TribalExplanationForm(RegistrarForm):
if not (self.cleaned_data["federally_recognized_tribe"] or
self.cleaned_data["state_recognized_tribe"]): # this overloads `more_organization_information` by using the existing field
raise forms.ValidationError("Only tribes recognized by the U.S. federal government or by a U.S. state government are eligible for .gov domains.", code="invalid") # on the domain application object on a second form.
more_organization_information = forms.CharField(
# label has to end in a space to get the label_suffix to show
label=(
"Only tribes recognized by the U.S. federal government or by a"
" U.S. state government are eligible for .gov domains. Please tell"
" us more about your tribe and why you want a .gov domain. "
),
label_suffix=REQUIRED_SUFFIX,
widget=forms.Textarea(),
error_messages={
"required": (
"Please tell us more about your tribe and why you want a .gov domain."
)
},
)
class OrganizationFederalForm(RegistrarForm): class OrganizationFederalForm(RegistrarForm):

View file

@ -495,6 +495,17 @@ class DomainApplication(TimeStampedModel):
user_choice = self.organization_type user_choice = self.organization_type
return user_choice == DomainApplication.OrganizationChoices.TRIBAL return user_choice == DomainApplication.OrganizationChoices.TRIBAL
def show_tribal_explanation(self) -> bool:
"""Show this step if the tribe is not federally or state recognized."""
user_choice = self.organization_type
if (user_choice == DomainApplication.OrganizationChoices.TRIBAL):
# did answer tribal, check the recognition answers
if self.federally_recognized_tribe is not None and self.state_recognized_tribe is not None:
# have answered these questions
if not self.federally_recognized_tribe and not self.state_recognized_tribe:
return True
return False
def show_organization_election(self) -> bool: def show_organization_election(self) -> bool:
"""Show this step if the answer to the first question implies it. """Show this step if the answer to the first question implies it.

View file

@ -0,0 +1,45 @@
<!-- Test page -->
{% extends 'application_form.html' %}
{% block form_content %}
{% load widget_tweaks dynamic_question_tags field_helpers %}
{% include "includes/required_fields.html" %}
<form id="step__{{steps.current}}" class="usa-form usa-form--large" method="post" novalidate>
<div class="usa-form-group">
{% csrf_token %}
<div class="usa-character-count">
{% with field=forms.0.more_organization_information %}
{% if field.errors %}
<div class="usa-form-group usa-form-group--error">
{{ field|add_label_class:"usa-label usa-label--error" }}
{% for error in field.errors %}
<span class="usa-error-message" id="input-error-message" role="alert">
{{ error }}
</span>
{% endfor %}
{{ field|add_class:"usa-input--error usa-textarea usa-character-count__field"|attr:"aria-describedby:instructions"|attr:"maxlength=500"|attr:"aria-invalid:true" }}
</div>
{% else %}
{{ field|add_label_class:"usa-label" }}
{{ field|add_class:"usa-textarea usa-character-count__field"|attr:"aria-describedby:instructions"|attr:"maxlength=500" }}
{% endif %}
{% endwith %}
<span class="usa-character-count__message" id="with-hint-textarea-info with-hint-textarea-hint"> You c
an enter up to 500 characters </span>
</div>
</div>
{# don't use the super-block's buttons? {{ block.super }} #}
<div class="stepnav">
<button
type="submit"
class="usa-button"
>Submit your domain request</button>
</div>
</form>
{% endblock %}

View file

@ -120,7 +120,7 @@ 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 SKIPPED_PAGES = 4 # elections, type_of_work, tribal_government, tribal_explanation
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()
@ -742,6 +742,12 @@ class DomainApplicationTests(TestWithUser, WebTest):
def test_application_tribal_government(self): def test_application_tribal_government(self):
"""Tribal organizations have to answer an additional question.""" """Tribal organizations have to answer an additional question."""
type_page = self.app.get(reverse("application:")).follow()
# 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]
type_form = type_page.form type_form = type_page.form
type_form[ type_form[
"organization_type-organization_type" "organization_type-organization_type"
@ -757,6 +763,44 @@ class DomainApplicationTests(TestWithUser, WebTest):
# and the step is on the sidebar list. # and the step is on the sidebar list.
self.assertContains(tribal_government_page, self.TITLES[Step.TRIBAL_GOVERNMENT]) self.assertContains(tribal_government_page, self.TITLES[Step.TRIBAL_GOVERNMENT])
def test_application_tribal_explanation(self):
"""Unrecognized tribes have to answer an additional question."""
type_page = self.app.get(reverse("application:")).follow()
# 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]
type_form = type_page.form
type_form[
"organization_type-organization_type"
] = DomainApplication.OrganizationChoices.TRIBAL
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
type_result = type_page.form.submit()
# the tribal government page comes immediately afterwards
self.assertIn("/tribal_government", type_result.headers["Location"])
# follow first redirect
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
tribal_government_page = type_result.follow()
# Enter a tribe name but don't check either state or federal recognition
tribal_government_page.form["tribal_government-tribe_name"] = "Tribe name"
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
tribal_government_result = tribal_government_page.form.submit()
# should be a redirect to tribal_more_information
self.assertIn("/tribal_more_information", tribal_government_result.headers["Location"])
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
tribal_more_information_page = tribal_government_result.follow()
# put an explanation and submit
tribal_more_information_page.form["tribal_more_information-more_organization_information"] = "Some explanation"
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
result = tribal_more_information_page.form.submit()
# result should be a success
self.assertEqual(result.status_code, 200)
def test_application_ao_dynamic_text(self): def test_application_ao_dynamic_text(self):
type_page = self.app.get(reverse("application:")).follow() type_page = self.app.get(reverse("application:")).follow()
# django-webtest does not handle cookie-based sessions well because it keeps # django-webtest does not handle cookie-based sessions well because it keeps

View file

@ -25,6 +25,7 @@ class Step(StrEnum):
ORGANIZATION_TYPE = "organization_type" ORGANIZATION_TYPE = "organization_type"
TRIBAL_GOVERNMENT = "tribal_government" TRIBAL_GOVERNMENT = "tribal_government"
TRIBAL_EXPLANATION = "tribal_more_information"
ORGANIZATION_FEDERAL = "organization_federal" ORGANIZATION_FEDERAL = "organization_federal"
ORGANIZATION_ELECTION = "organization_election" ORGANIZATION_ELECTION = "organization_election"
ORGANIZATION_CONTACT = "organization_contact" ORGANIZATION_CONTACT = "organization_contact"
@ -70,6 +71,7 @@ class ApplicationWizard(LoginRequiredMixin, TemplateView):
TITLES = { TITLES = {
Step.ORGANIZATION_TYPE: _("Type of organization"), Step.ORGANIZATION_TYPE: _("Type of organization"),
Step.TRIBAL_GOVERNMENT: _("Tribal government"), Step.TRIBAL_GOVERNMENT: _("Tribal government"),
Step.TRIBAL_EXPLANATION: _("More Information - Tribal government"),
Step.ORGANIZATION_FEDERAL: _("Type of organization — Federal"), Step.ORGANIZATION_FEDERAL: _("Type of organization — Federal"),
Step.ORGANIZATION_ELECTION: _("Type of organization — Election board"), Step.ORGANIZATION_ELECTION: _("Type of organization — Election board"),
Step.ORGANIZATION_CONTACT: _("Organization name and mailing address"), Step.ORGANIZATION_CONTACT: _("Organization name and mailing address"),
@ -97,6 +99,9 @@ class ApplicationWizard(LoginRequiredMixin, TemplateView):
Step.TRIBAL_GOVERNMENT: lambda w: w.from_model( Step.TRIBAL_GOVERNMENT: lambda w: w.from_model(
"show_tribal_government", False "show_tribal_government", False
), ),
Step.TRIBAL_EXPLANATION: lambda w: w.from_model(
"show_tribal_explanation", False
),
Step.ORGANIZATION_ELECTION: lambda w: w.from_model( Step.ORGANIZATION_ELECTION: lambda w: w.from_model(
"show_organization_election", False "show_organization_election", False
), ),
@ -346,6 +351,27 @@ class TribalGovernment(ApplicationWizard):
forms = [forms.TribalGovernmentForm] forms = [forms.TribalGovernmentForm]
class TribalExplanation(ApplicationWizard):
template_name = "application_tribal_explanation.html"
forms = [forms.TribalExplanationForm]
def post(self, request, *args, **kwargs):
"""Custom submit method to skip directly to submit at this point."""
forms = self.get_forms(use_post=True)
if self.is_valid(forms):
# always save progress
self.save(forms)
else:
# unless there are errors
context = self.get_context_data()
context["forms"] = forms
return render(request, self.template_name, context)
# don't go to next step
# return self.goto_next_step()
return self.done()
class OrganizationFederal(ApplicationWizard): class OrganizationFederal(ApplicationWizard):
template_name = "application_org_federal.html" template_name = "application_org_federal.html"
forms = [forms.OrganizationFederalForm] forms = [forms.OrganizationFederalForm]