mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-05-22 04:19:26 +02:00
Merge pull request #1729 from cisagov/rjm/1624-1472-unlock-application-pages
Issues 1624 1472: Unlock application pages (RJM sandbox)
This commit is contained in:
commit
72ee511238
4 changed files with 197 additions and 5 deletions
|
@ -8,10 +8,12 @@
|
|||
<li class="usa-sidenav__item sidenav__step--locked">
|
||||
<span>
|
||||
{% if not this_step == steps.current %}
|
||||
<svg class="usa-icon text-green" aria-hidden="true" focsuable="false" role="img" width="24" height="24">
|
||||
<title id="checked-step__{{forloop.counter}}">Checked mark</title>
|
||||
<use xlink:href="{%static 'img/sprite.svg'%}#check_circle"></use>
|
||||
</svg>
|
||||
{% if this_step != "review" %}
|
||||
<svg class="usa-icon text-green" aria-hidden="true" focsuable="false" role="img" width="24" height="24">
|
||||
<title id="checked-step__{{forloop.counter}}">Checked mark</title>
|
||||
<use xlink:href="{%static 'img/sprite.svg'%}#check_circle"></use>
|
||||
</svg>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<a href="{% namespaced_url 'application' this_step %}"
|
||||
{% if this_step == steps.current %}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from unittest import skip
|
||||
from unittest.mock import Mock
|
||||
|
||||
from django.conf import settings
|
||||
from django.urls import reverse
|
||||
|
@ -9,6 +10,7 @@ import boto3_mocking # type: ignore
|
|||
|
||||
from registrar.models import (
|
||||
DomainApplication,
|
||||
DraftDomain,
|
||||
Domain,
|
||||
DomainInformation,
|
||||
Contact,
|
||||
|
@ -2197,3 +2199,131 @@ class DomainApplicationTestDifferentStatuses(TestWithUser, WebTest):
|
|||
# domain object, so we do not expect to see 'city.gov'
|
||||
# in either the Domains or Requests tables.
|
||||
self.assertNotContains(home_page, "city.gov")
|
||||
|
||||
|
||||
class TestWizardUnlockingSteps(TestWithUser, WebTest):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.app.set_user(self.user.username)
|
||||
self.wizard = ApplicationWizard()
|
||||
# Mock the request object, its user, and session attributes appropriately
|
||||
self.wizard.request = Mock(user=self.user, session={})
|
||||
|
||||
def tearDown(self):
|
||||
super().tearDown()
|
||||
|
||||
def test_unlocked_steps_empty_application(self):
|
||||
"""Test when all fields in the application are empty."""
|
||||
unlocked_steps = self.wizard.db_check_for_unlocking_steps()
|
||||
expected_dict = []
|
||||
self.assertEqual(unlocked_steps, expected_dict)
|
||||
|
||||
def test_unlocked_steps_full_application(self):
|
||||
"""Test when all fields in the application are filled."""
|
||||
|
||||
completed_application(status=DomainApplication.ApplicationStatus.STARTED, user=self.user)
|
||||
# Make a request to the home page
|
||||
home_page = self.app.get("/")
|
||||
# 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)
|
||||
|
||||
# Assert that the response contains "city.gov"
|
||||
self.assertContains(home_page, "city.gov")
|
||||
|
||||
# Click the "Edit" link
|
||||
response = home_page.click("Edit", index=0)
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
# Check if the response is a redirect
|
||||
if response.status_code == 302:
|
||||
# Follow the redirect manually
|
||||
try:
|
||||
detail_page = response.follow()
|
||||
|
||||
self.wizard.get_context_data()
|
||||
except Exception as err:
|
||||
# Handle any potential errors while following the redirect
|
||||
self.fail(f"Error following the redirect {err}")
|
||||
|
||||
# Now 'detail_page' contains the response after following the redirect
|
||||
self.assertEqual(detail_page.status_code, 200)
|
||||
|
||||
# 10 unlocked steps, one active step, the review step will have link_usa but not check_circle
|
||||
self.assertContains(detail_page, "#check_circle", count=10)
|
||||
# Type of organization
|
||||
self.assertContains(detail_page, "usa-current", count=1)
|
||||
self.assertContains(detail_page, "link_usa-checked", count=11)
|
||||
|
||||
else:
|
||||
self.fail(f"Expected a redirect, but got a different response: {response}")
|
||||
|
||||
def test_unlocked_steps_partial_application(self):
|
||||
"""Test when some fields in the application are filled."""
|
||||
|
||||
# Create the site and contacts to delete (orphaned)
|
||||
contact = Contact.objects.create(
|
||||
first_name="Henry",
|
||||
last_name="Mcfakerson",
|
||||
)
|
||||
# Create two non-orphaned contacts
|
||||
contact_2 = Contact.objects.create(
|
||||
first_name="Saturn",
|
||||
last_name="Mars",
|
||||
)
|
||||
|
||||
# Attach a user object to a contact (should not be deleted)
|
||||
contact_user, _ = Contact.objects.get_or_create(user=self.user)
|
||||
|
||||
site = DraftDomain.objects.create(name="igorville.gov")
|
||||
application = DomainApplication.objects.create(
|
||||
creator=self.user,
|
||||
requested_domain=site,
|
||||
status=DomainApplication.ApplicationStatus.WITHDRAWN,
|
||||
authorizing_official=contact,
|
||||
submitter=contact_user,
|
||||
)
|
||||
application.other_contacts.set([contact_2])
|
||||
|
||||
# Make a request to the home page
|
||||
home_page = self.app.get("/")
|
||||
# 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)
|
||||
|
||||
# Assert that the response contains "city.gov"
|
||||
self.assertContains(home_page, "igorville.gov")
|
||||
|
||||
# Click the "Edit" link
|
||||
response = home_page.click("Edit", index=0)
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
# Check if the response is a redirect
|
||||
if response.status_code == 302:
|
||||
# Follow the redirect manually
|
||||
try:
|
||||
detail_page = response.follow()
|
||||
|
||||
self.wizard.get_context_data()
|
||||
except Exception as err:
|
||||
# Handle any potential errors while following the redirect
|
||||
self.fail(f"Error following the redirect {err}")
|
||||
|
||||
# Now 'detail_page' contains the response after following the redirect
|
||||
self.assertEqual(detail_page.status_code, 200)
|
||||
|
||||
# 5 unlocked steps (ao, domain, submitter, other contacts, and current sites
|
||||
# which unlocks if domain exists), one active step, the review step is locked
|
||||
self.assertContains(detail_page, "#check_circle", count=5)
|
||||
# Type of organization
|
||||
self.assertContains(detail_page, "usa-current", count=1)
|
||||
self.assertContains(detail_page, "link_usa-checked", count=5)
|
||||
|
||||
else:
|
||||
self.fail(f"Expected a redirect, but got a different response: {response}")
|
||||
|
|
|
@ -92,6 +92,12 @@ def parse_row(columns, domain_info: DomainInformation, security_emails_dict=None
|
|||
"Deleted": domain.deleted,
|
||||
}
|
||||
|
||||
# user_emails = [user.email for user in domain.permissions]
|
||||
|
||||
# Dynamically add user emails to the FIELDS dictionary
|
||||
# for i, user_email in enumerate(user_emails, start=1):
|
||||
# FIELDS[f"User{i} email"] = user_email
|
||||
|
||||
row = [FIELDS.get(column, "") for column in columns]
|
||||
return row
|
||||
|
||||
|
@ -127,6 +133,16 @@ def write_body(
|
|||
else:
|
||||
logger.warning("csv_export -> Domain was none for PublicContact")
|
||||
|
||||
# all_user_nums = 0
|
||||
# for domain_info in all_domain_infos:
|
||||
# user_num = len(domain_info.domain.permissions)
|
||||
# all_user_nums.append(user_num)
|
||||
|
||||
# if user_num > highest_user_nums:
|
||||
# highest_user_nums = user_num
|
||||
|
||||
# Build the header here passing to it highest_user_nums
|
||||
|
||||
# Reduce the memory overhead when performing the write operation
|
||||
paginator = Paginator(all_domain_infos, 1000)
|
||||
for page_num in paginator.page_range:
|
||||
|
|
|
@ -159,7 +159,11 @@ class ApplicationWizard(ApplicationWizardPermissionView, TemplateView):
|
|||
def storage(self):
|
||||
# marking session as modified on every access
|
||||
# so that updates to nested keys are always saved
|
||||
self.request.session.modified = True
|
||||
# Also - check that self.request.session has the attr
|
||||
# modified to account for test environments calling
|
||||
# view methods
|
||||
if hasattr(self.request.session, "modified"):
|
||||
self.request.session.modified = True
|
||||
return self.request.session.setdefault(self.prefix, {})
|
||||
|
||||
@storage.setter
|
||||
|
@ -211,6 +215,7 @@ class ApplicationWizard(ApplicationWizardPermissionView, TemplateView):
|
|||
if current_url == self.EDIT_URL_NAME and "id" in kwargs:
|
||||
del self.storage
|
||||
self.storage["application_id"] = kwargs["id"]
|
||||
self.storage["step_history"] = self.db_check_for_unlocking_steps()
|
||||
|
||||
# if accessing this class directly, redirect to the first step
|
||||
# in other words, if `ApplicationWizard` is called as view
|
||||
|
@ -269,6 +274,7 @@ class ApplicationWizard(ApplicationWizardPermissionView, TemplateView):
|
|||
and from the database if `use_db` is True (provided that record exists).
|
||||
An empty form will be provided if neither of those are true.
|
||||
"""
|
||||
|
||||
kwargs = {
|
||||
"files": files,
|
||||
"prefix": self.steps.current,
|
||||
|
@ -329,6 +335,43 @@ class ApplicationWizard(ApplicationWizardPermissionView, TemplateView):
|
|||
]
|
||||
return DomainApplication.objects.filter(creator=self.request.user, status__in=check_statuses)
|
||||
|
||||
def db_check_for_unlocking_steps(self):
|
||||
"""Helper for get_context_data
|
||||
|
||||
Queries the DB for an application and returns a list of unlocked steps."""
|
||||
history_dict = {
|
||||
"organization_type": self.application.organization_type is not None,
|
||||
"tribal_government": self.application.tribe_name is not None,
|
||||
"organization_federal": self.application.federal_type is not None,
|
||||
"organization_election": self.application.is_election_board is not None,
|
||||
"organization_contact": (
|
||||
self.application.federal_agency is not None
|
||||
or self.application.organization_name is not None
|
||||
or self.application.address_line1 is not None
|
||||
or self.application.city is not None
|
||||
or self.application.state_territory is not None
|
||||
or self.application.zipcode is not None
|
||||
or self.application.urbanization is not None
|
||||
),
|
||||
"about_your_organization": self.application.about_your_organization is not None,
|
||||
"authorizing_official": self.application.authorizing_official is not None,
|
||||
"current_sites": (
|
||||
self.application.current_websites.exists() or self.application.requested_domain is not None
|
||||
),
|
||||
"dotgov_domain": self.application.requested_domain is not None,
|
||||
"purpose": self.application.purpose is not None,
|
||||
"your_contact": self.application.submitter is not None,
|
||||
"other_contacts": (
|
||||
self.application.other_contacts.exists() or self.application.no_other_contacts_rationale is not None
|
||||
),
|
||||
"anything_else": (
|
||||
self.application.anything_else is not None or self.application.is_policy_acknowledged is not None
|
||||
),
|
||||
"requirements": self.application.is_policy_acknowledged is not None,
|
||||
"review": self.application.is_policy_acknowledged is not None,
|
||||
}
|
||||
return [key for key, value in history_dict.items() if value]
|
||||
|
||||
def get_context_data(self):
|
||||
"""Define context for access on all wizard pages."""
|
||||
# Build the submit button that we'll pass to the modal.
|
||||
|
@ -338,6 +381,7 @@ class ApplicationWizard(ApplicationWizardPermissionView, TemplateView):
|
|||
modal_heading = "You are about to submit a domain request for " + str(self.application.requested_domain)
|
||||
else:
|
||||
modal_heading = "You are about to submit an incomplete request"
|
||||
|
||||
return {
|
||||
"form_titles": self.TITLES,
|
||||
"steps": self.steps,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue