From f4c6c084a6804c3fe6fa7ddcf3bb6a2e3985af42 Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Thu, 31 Oct 2024 13:54:27 -0600 Subject: [PATCH 01/31] kind of a solution Doesn't account for clicking the button after page refresh --- src/registrar/config/settings.py | 1 + src/registrar/registrar_middleware.py | 40 ++++++++++++++++++++++++++- src/registrar/views/domain_request.py | 17 +++++++----- src/registrar/views/index.py | 1 - src/registrar/views/portfolios.py | 2 -- src/registrar/views/utility/mixins.py | 2 +- 6 files changed, 51 insertions(+), 12 deletions(-) diff --git a/src/registrar/config/settings.py b/src/registrar/config/settings.py index da58eee86..f931dad5e 100644 --- a/src/registrar/config/settings.py +++ b/src/registrar/config/settings.py @@ -193,6 +193,7 @@ "waffle.middleware.WaffleMiddleware", "registrar.registrar_middleware.CheckUserProfileMiddleware", "registrar.registrar_middleware.CheckPortfolioMiddleware", + "registrar.registrar_middleware.NewRequestMiddleware" ] # application object used by Django's built-in servers (e.g. `runserver`) diff --git a/src/registrar/registrar_middleware.py b/src/registrar/registrar_middleware.py index 2ccea9321..d8340421a 100644 --- a/src/registrar/registrar_middleware.py +++ b/src/registrar/registrar_middleware.py @@ -8,7 +8,8 @@ from django.http import HttpResponseRedirect from registrar.models import User from waffle.decorators import flag_is_active - +from django.urls import resolve, Resolver404 +from registrar.config.urls import DOMAIN_REQUEST_NAMESPACE from registrar.models.utility.generic_helper import replace_url_queryparams logger = logging.getLogger(__name__) @@ -169,3 +170,40 @@ def set_portfolio_in_session(self, request): request.session["portfolio"] = request.user.get_first_portfolio() else: request.session["portfolio"] = request.user.get_first_portfolio() + + +class NewRequestMiddleware: + def __init__(self, get_response): + self.get_response = get_response + + def __call__(self, request): + response = self.get_response(request) + return response + + def process_view(self, request, view_func, view_args, view_kwargs): + if not request.user.is_authenticated: + return None + + if request.session.get("new_request") is None: + request.session["new_request"] = True + + resolved = resolve(request.path) + if request.session.get("new_request") is False: + try: + resolved = resolve(request.path) + # Check if we're in the domain-request namespace. + # If not, then a new request is not being made. + if resolved.namespace != DOMAIN_REQUEST_NAMESPACE: + request.session["new_request"] = True + # URL doesn't match any known pattern. + # This shouldn't happen (caught before this), but redundancy is good. + except Resolver404: + # If you somehow see this log, something must have went very, *very* wrong. + # All I can offer in consolidation is this ASCII cat to tend to these hard times: + # ⠀ /l、 + # (゚、 。 7 + # ⠀ l、゙ ~ヽ + #   じしf_, )ノ + logger.error("[CRITICAL] NewRequestMiddleware => Could not resolve the request path.") + + return None diff --git a/src/registrar/views/domain_request.py b/src/registrar/views/domain_request.py index 7bbe78775..d74897266 100644 --- a/src/registrar/views/domain_request.py +++ b/src/registrar/views/domain_request.py @@ -308,6 +308,13 @@ def get(self, request, *args, **kwargs): if current_url == self.EDIT_URL_NAME and "id" in kwargs: del self.storage self.storage["domain_request_id"] = kwargs["id"] + elif self.request.session.get("new_request") is True and current_url != self.NEW_URL_NAME and current_url != "": + print(f"what is the url: {current_url} vs type: {type(current_url)}") + # Add some popup here that indicates a new request was started... + logger.info(f"DomainRequestWizard => user {request.user} was redirected to home (because, etc...)") + del self.storage + return HttpResponseRedirect(reverse("home")) + # if accessing this class directly, redirect to either to an acknowledgement # page or to the first step in the processes (if an edit rather than a new request); @@ -493,10 +500,8 @@ def get_step_list(self) -> list: return request_step_list(self, self.get_step_enum()) def goto(self, step): - if step == "generic_org_type" or step == "portfolio_requesting_entity": - # We need to avoid creating a new domain request if the user - # clicks the back button - self.request.session["new_request"] = False + # We need to avoid creating a new domain request if the user clicks the back button + self.request.session["new_request"] = False self.steps.current = step return redirect(reverse(f"{self.URL_NAMESPACE}:{step}")) @@ -524,9 +529,6 @@ def post(self, request, *args, **kwargs) -> HttpResponse: # which button did the user press? button: str = request.POST.get("submit_button", "") - if "new_request" not in request.session: - request.session["new_request"] = True - # if user has acknowledged the intro message if button == "intro_acknowledge": # Split into a function: C901 'DomainRequestWizard.post' is too complex (11) @@ -564,6 +566,7 @@ def post(self, request, *args, **kwargs) -> HttpResponse: def handle_intro_acknowledge(self, request): """If we are starting a new request, clear storage and redirect to the first step""" + print(f"path info is: {request.path_info}") if request.path_info == self.NEW_URL_NAME: if self.request.session["new_request"] is True: del self.storage diff --git a/src/registrar/views/index.py b/src/registrar/views/index.py index 53900a4a7..7019c8db3 100644 --- a/src/registrar/views/index.py +++ b/src/registrar/views/index.py @@ -7,7 +7,6 @@ def index(request): if request and request.user and request.user.is_authenticated: # This controls the creation of a new domain request in the wizard - request.session["new_request"] = True context["user_domain_count"] = request.user.get_user_domain_ids(request).count() return render(request, "home.html", context) diff --git a/src/registrar/views/portfolios.py b/src/registrar/views/portfolios.py index 6fb976d5c..42158737a 100644 --- a/src/registrar/views/portfolios.py +++ b/src/registrar/views/portfolios.py @@ -46,8 +46,6 @@ class PortfolioDomainRequestsView(PortfolioDomainRequestsPermissionView, View): template_name = "portfolio_requests.html" def get(self, request): - if self.request.user.is_authenticated: - request.session["new_request"] = True return render(request, "portfolio_requests.html") diff --git a/src/registrar/views/utility/mixins.py b/src/registrar/views/utility/mixins.py index c1cf97d82..31913691c 100644 --- a/src/registrar/views/utility/mixins.py +++ b/src/registrar/views/utility/mixins.py @@ -401,7 +401,7 @@ def has_permission(self): id = self.kwargs.get("id") if hasattr(self, "kwargs") else None if not id: domain_request_wizard = self.request.session.get("wizard_domain_request") - if domain_request_wizard: + if domain_request_wizard and self.request.session.get("new_request") is False: id = domain_request_wizard.get("domain_request_id") # If no id is provided, we can assume that the user is starting a new request. From e19923f86fd30a263b945b869cf1eaa86a28a1e2 Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Thu, 31 Oct 2024 13:54:43 -0600 Subject: [PATCH 02/31] Revert "kind of a solution" This reverts commit f4c6c084a6804c3fe6fa7ddcf3bb6a2e3985af42. --- src/registrar/config/settings.py | 1 - src/registrar/registrar_middleware.py | 40 +-------------------------- src/registrar/views/domain_request.py | 17 +++++------- src/registrar/views/index.py | 1 + src/registrar/views/portfolios.py | 2 ++ src/registrar/views/utility/mixins.py | 2 +- 6 files changed, 12 insertions(+), 51 deletions(-) diff --git a/src/registrar/config/settings.py b/src/registrar/config/settings.py index f931dad5e..da58eee86 100644 --- a/src/registrar/config/settings.py +++ b/src/registrar/config/settings.py @@ -193,7 +193,6 @@ "waffle.middleware.WaffleMiddleware", "registrar.registrar_middleware.CheckUserProfileMiddleware", "registrar.registrar_middleware.CheckPortfolioMiddleware", - "registrar.registrar_middleware.NewRequestMiddleware" ] # application object used by Django's built-in servers (e.g. `runserver`) diff --git a/src/registrar/registrar_middleware.py b/src/registrar/registrar_middleware.py index d8340421a..2ccea9321 100644 --- a/src/registrar/registrar_middleware.py +++ b/src/registrar/registrar_middleware.py @@ -8,8 +8,7 @@ from django.http import HttpResponseRedirect from registrar.models import User from waffle.decorators import flag_is_active -from django.urls import resolve, Resolver404 -from registrar.config.urls import DOMAIN_REQUEST_NAMESPACE + from registrar.models.utility.generic_helper import replace_url_queryparams logger = logging.getLogger(__name__) @@ -170,40 +169,3 @@ def set_portfolio_in_session(self, request): request.session["portfolio"] = request.user.get_first_portfolio() else: request.session["portfolio"] = request.user.get_first_portfolio() - - -class NewRequestMiddleware: - def __init__(self, get_response): - self.get_response = get_response - - def __call__(self, request): - response = self.get_response(request) - return response - - def process_view(self, request, view_func, view_args, view_kwargs): - if not request.user.is_authenticated: - return None - - if request.session.get("new_request") is None: - request.session["new_request"] = True - - resolved = resolve(request.path) - if request.session.get("new_request") is False: - try: - resolved = resolve(request.path) - # Check if we're in the domain-request namespace. - # If not, then a new request is not being made. - if resolved.namespace != DOMAIN_REQUEST_NAMESPACE: - request.session["new_request"] = True - # URL doesn't match any known pattern. - # This shouldn't happen (caught before this), but redundancy is good. - except Resolver404: - # If you somehow see this log, something must have went very, *very* wrong. - # All I can offer in consolidation is this ASCII cat to tend to these hard times: - # ⠀ /l、 - # (゚、 。 7 - # ⠀ l、゙ ~ヽ - #   じしf_, )ノ - logger.error("[CRITICAL] NewRequestMiddleware => Could not resolve the request path.") - - return None diff --git a/src/registrar/views/domain_request.py b/src/registrar/views/domain_request.py index d74897266..7bbe78775 100644 --- a/src/registrar/views/domain_request.py +++ b/src/registrar/views/domain_request.py @@ -308,13 +308,6 @@ def get(self, request, *args, **kwargs): if current_url == self.EDIT_URL_NAME and "id" in kwargs: del self.storage self.storage["domain_request_id"] = kwargs["id"] - elif self.request.session.get("new_request") is True and current_url != self.NEW_URL_NAME and current_url != "": - print(f"what is the url: {current_url} vs type: {type(current_url)}") - # Add some popup here that indicates a new request was started... - logger.info(f"DomainRequestWizard => user {request.user} was redirected to home (because, etc...)") - del self.storage - return HttpResponseRedirect(reverse("home")) - # if accessing this class directly, redirect to either to an acknowledgement # page or to the first step in the processes (if an edit rather than a new request); @@ -500,8 +493,10 @@ def get_step_list(self) -> list: return request_step_list(self, self.get_step_enum()) def goto(self, step): - # We need to avoid creating a new domain request if the user clicks the back button - self.request.session["new_request"] = False + if step == "generic_org_type" or step == "portfolio_requesting_entity": + # We need to avoid creating a new domain request if the user + # clicks the back button + self.request.session["new_request"] = False self.steps.current = step return redirect(reverse(f"{self.URL_NAMESPACE}:{step}")) @@ -529,6 +524,9 @@ def post(self, request, *args, **kwargs) -> HttpResponse: # which button did the user press? button: str = request.POST.get("submit_button", "") + if "new_request" not in request.session: + request.session["new_request"] = True + # if user has acknowledged the intro message if button == "intro_acknowledge": # Split into a function: C901 'DomainRequestWizard.post' is too complex (11) @@ -566,7 +564,6 @@ def post(self, request, *args, **kwargs) -> HttpResponse: def handle_intro_acknowledge(self, request): """If we are starting a new request, clear storage and redirect to the first step""" - print(f"path info is: {request.path_info}") if request.path_info == self.NEW_URL_NAME: if self.request.session["new_request"] is True: del self.storage diff --git a/src/registrar/views/index.py b/src/registrar/views/index.py index 7019c8db3..53900a4a7 100644 --- a/src/registrar/views/index.py +++ b/src/registrar/views/index.py @@ -7,6 +7,7 @@ def index(request): if request and request.user and request.user.is_authenticated: # This controls the creation of a new domain request in the wizard + request.session["new_request"] = True context["user_domain_count"] = request.user.get_user_domain_ids(request).count() return render(request, "home.html", context) diff --git a/src/registrar/views/portfolios.py b/src/registrar/views/portfolios.py index 42158737a..6fb976d5c 100644 --- a/src/registrar/views/portfolios.py +++ b/src/registrar/views/portfolios.py @@ -46,6 +46,8 @@ class PortfolioDomainRequestsView(PortfolioDomainRequestsPermissionView, View): template_name = "portfolio_requests.html" def get(self, request): + if self.request.user.is_authenticated: + request.session["new_request"] = True return render(request, "portfolio_requests.html") diff --git a/src/registrar/views/utility/mixins.py b/src/registrar/views/utility/mixins.py index 31913691c..c1cf97d82 100644 --- a/src/registrar/views/utility/mixins.py +++ b/src/registrar/views/utility/mixins.py @@ -401,7 +401,7 @@ def has_permission(self): id = self.kwargs.get("id") if hasattr(self, "kwargs") else None if not id: domain_request_wizard = self.request.session.get("wizard_domain_request") - if domain_request_wizard and self.request.session.get("new_request") is False: + if domain_request_wizard: id = domain_request_wizard.get("domain_request_id") # If no id is provided, we can assume that the user is starting a new request. From aa930eb77c1742694c3506008d7936af403fcdca Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Thu, 31 Oct 2024 15:10:12 -0600 Subject: [PATCH 03/31] use id instead of session for domain requests --- src/registrar/config/urls.py | 9 +++-- src/registrar/registrar_middleware.py | 2 +- .../templates/domain_request_form.html | 2 +- .../templates/domain_request_intro.html | 2 +- .../templates/domain_request_sidebar.html | 2 +- src/registrar/templates/home.html | 7 +--- .../templates/includes/header_extended.html | 2 +- .../portfolio_request_review_steps.html | 2 +- .../includes/request_review_steps.html | 2 +- .../templates/portfolio_requests.html | 8 +--- src/registrar/tests/test_views.py | 4 +- src/registrar/tests/test_views_request.py | 38 +++++++++---------- src/registrar/views/domain_request.py | 20 ++++------ src/registrar/views/index.py | 1 - src/registrar/views/portfolios.py | 2 - src/registrar/views/user_profile.py | 2 +- 16 files changed, 46 insertions(+), 59 deletions(-) diff --git a/src/registrar/config/urls.py b/src/registrar/config/urls.py index f61e31e54..d1551c9da 100644 --- a/src/registrar/config/urls.py +++ b/src/registrar/config/urls.py @@ -39,10 +39,11 @@ from api.views import available, rdap, get_current_federal, get_current_full DOMAIN_REQUEST_NAMESPACE = views.DomainRequestWizard.URL_NAMESPACE -domain_request_urls = [ - path("", views.DomainRequestWizard.as_view(), name=""), +domain_request_start_and_finished_urls = [ + path("start/", views.DomainRequestWizard.as_view(), name="start"), path("finished/", views.Finished.as_view(), name="finished"), ] +domain_request_urls = [] # dynamically generate the other domain_request_urls for step, view in [ @@ -253,7 +254,9 @@ ), path("health", views.health, name="health"), path("openid/", include("djangooidc.urls")), - path("request/", include((domain_request_urls, DOMAIN_REQUEST_NAMESPACE))), + path("request/start/", views.DomainRequestWizard.as_view(), name="start"), + #path("request/", include((domain_request_start_and_finished_urls, DOMAIN_REQUEST_NAMESPACE))), + path("request//", include((domain_request_urls, DOMAIN_REQUEST_NAMESPACE))), path("api/v1/available/", available, name="available"), path("api/v1/rdap/", rdap, name="rdap"), path("api/v1/get-report/current-federal", get_current_federal, name="get-current-federal"), diff --git a/src/registrar/registrar_middleware.py b/src/registrar/registrar_middleware.py index 2ccea9321..bb6871803 100644 --- a/src/registrar/registrar_middleware.py +++ b/src/registrar/registrar_middleware.py @@ -100,7 +100,7 @@ def _handle_user_setup_not_finished(self, request, profile_page): # In some cases, we don't want to redirect to home. This handles that. # Can easily be generalized if need be, but for now lets keep this easy to read. - custom_redirect = "domain-request:" if request.path == "/request/" else None + custom_redirect = "domain-request:start" if request.path == "/request/" else None # Don't redirect on excluded pages (such as the setup page itself) if not any(request.path.startswith(page) for page in self._get_excluded_pages(profile_page)): diff --git a/src/registrar/templates/domain_request_form.html b/src/registrar/templates/domain_request_form.html index 9228e51db..fe1d816e6 100644 --- a/src/registrar/templates/domain_request_form.html +++ b/src/registrar/templates/domain_request_form.html @@ -11,7 +11,7 @@
{% if steps.prev %} - + Previous step diff --git a/src/registrar/templates/domain_request_intro.html b/src/registrar/templates/domain_request_intro.html index 6b5223991..dd5b7ec6e 100644 --- a/src/registrar/templates/domain_request_intro.html +++ b/src/registrar/templates/domain_request_intro.html @@ -21,7 +21,7 @@

Time to complete the form

If you have all the information you need, completing your domain request might take around 15 minutes.

How we’ll reach you

-

While reviewing your domain request, we may need to reach out with questions. We’ll also email you when we complete our review. If the contact information below is not correct, visit your profile to make updates.

+

While reviewing your domain request, we may need to reach out with questions. We’ll also email you when we complete our review. If the contact information below is not correct, visit your profile to make updates.

{% include "includes/profile_information.html" with user=user%} diff --git a/src/registrar/templates/domain_request_sidebar.html b/src/registrar/templates/domain_request_sidebar.html index f9ca5397d..efdfe391e 100644 --- a/src/registrar/templates/domain_request_sidebar.html +++ b/src/registrar/templates/domain_request_sidebar.html @@ -15,7 +15,7 @@ {% endif %} {% endif %} - Manage your domains - {% comment %} - IMPORTANT: - If this button is added on any other page, make sure to update the - relevant view to reset request.session["new_request"] = True - {% endcomment %}

- Start a new domain request diff --git a/src/registrar/templates/includes/header_extended.html b/src/registrar/templates/includes/header_extended.html index 23b7d1be3..b9846277a 100644 --- a/src/registrar/templates/includes/header_extended.html +++ b/src/registrar/templates/includes/header_extended.html @@ -72,7 +72,7 @@ >

  • - Start a new domain request
  • diff --git a/src/registrar/templates/includes/portfolio_request_review_steps.html b/src/registrar/templates/includes/portfolio_request_review_steps.html index 9d3c5bdeb..b8d86b420 100644 --- a/src/registrar/templates/includes/portfolio_request_review_steps.html +++ b/src/registrar/templates/includes/portfolio_request_review_steps.html @@ -4,7 +4,7 @@ {% for step in steps %}
    {% if is_editable %} - {% namespaced_url 'domain-request' step as domain_request_url %} + {% namespaced_url 'domain-request' step pk=domain_request_id as domain_request_url %} {% endif %} {% if step == Step.REQUESTING_ENTITY %} diff --git a/src/registrar/templates/includes/request_review_steps.html b/src/registrar/templates/includes/request_review_steps.html index db1743b34..e0f76b27e 100644 --- a/src/registrar/templates/includes/request_review_steps.html +++ b/src/registrar/templates/includes/request_review_steps.html @@ -4,7 +4,7 @@ {% for step in steps %}
    {% if is_editable %} - {% namespaced_url 'domain-request' step as domain_request_url %} + {% namespaced_url 'domain-request' step pk=domain_request_id as domain_request_url %} {% endif %} {% if step == Step.ORGANIZATION_TYPE %} diff --git a/src/registrar/templates/portfolio_requests.html b/src/registrar/templates/portfolio_requests.html index d21bbcc4e..0eea5f6bd 100644 --- a/src/registrar/templates/portfolio_requests.html +++ b/src/registrar/templates/portfolio_requests.html @@ -22,13 +22,9 @@

    Domain requests

    Domain requests can only be modified by the person who created the request.

    - {% comment %} - IMPORTANT: - If this button is added on any other page, make sure to update the - relevant view to reset request.session["new_request"] = True - {% endcomment %} +

    - Start a new domain request diff --git a/src/registrar/tests/test_views.py b/src/registrar/tests/test_views.py index 85ff5edd6..c1e859648 100644 --- a/src/registrar/tests/test_views.py +++ b/src/registrar/tests/test_views.py @@ -718,7 +718,7 @@ def test_new_user_goes_to_domain_request(self): self.app.set_user(incomplete_regular_user.username) with override_flag("", active=True): # This will redirect the user to the setup page - finish_setup_page = self.app.get(reverse("domain-request:")).follow() + finish_setup_page = self.app.get(reverse("domain-request:start")).follow() self._set_session_cookie() # Assert that we're on the right page @@ -927,7 +927,7 @@ def test_user_profile_main_nav(self): def test_user_profile_back_button_when_coming_from_domain_request(self): """tests user profile, and when they are redirected from the domain request page""" - response = self.client.get("/user-profile?redirect=domain-request:") + response = self.client.get("/user-profile?redirect=domain-request:start") self.assertContains(response, "Your profile") self.assertContains(response, "Go back to your domain request") self.assertNotContains(response, "Back to manage your domains") diff --git a/src/registrar/tests/test_views_request.py b/src/registrar/tests/test_views_request.py index 17e6bcbe6..9b676e850 100644 --- a/src/registrar/tests/test_views_request.py +++ b/src/registrar/tests/test_views_request.py @@ -54,7 +54,7 @@ def tearDown(self): @less_console_noise_decorator def test_domain_request_form_intro_acknowledgement(self): """Tests that user is presented with intro acknowledgement page""" - intro_page = self.app.get(reverse("domain-request:")) + intro_page = self.app.get(reverse("domain-request:start")) self.assertContains(intro_page, "You’re about to start your .gov domain request") @less_console_noise_decorator @@ -110,7 +110,7 @@ def test_domain_request_form_intro_is_skipped_when_edit_access(self): @less_console_noise_decorator def test_domain_request_form_empty_submit(self): """Tests empty submit on the first page after the acknowledgement page""" - intro_page = self.app.get(reverse("domain-request:")) + intro_page = self.app.get(reverse("domain-request:start")) # 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 @@ -141,7 +141,7 @@ def test_domain_request_multiple_domain_requests_exist(self): domain_request.save() # now, attempt to create another one - intro_page = self.app.get(reverse("domain-request:")) + intro_page = self.app.get(reverse("domain-request:start")) session_id = self.app.cookies[settings.SESSION_COOKIE_NAME] intro_form = intro_page.forms[0] self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id) @@ -167,7 +167,7 @@ def test_domain_request_into_acknowledgement_creates_new_request(self): session_id = self.app.cookies[settings.SESSION_COOKIE_NAME] self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id) - intro_page = self.app.get(reverse("domain-request:")) + intro_page = self.app.get(reverse("domain-request:start")) # Select the form intro_form = intro_page.forms[0] @@ -225,7 +225,7 @@ def test_domain_request_form_submission(self): SKIPPED_PAGES = 3 num_pages = len(self.TITLES) - SKIPPED_PAGES - intro_page = self.app.get(reverse("domain-request:")) + intro_page = self.app.get(reverse("domain-request:start")) # 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 @@ -549,7 +549,7 @@ def test_domain_request_form_submission_incomplete(self): num_pages_tested = 0 # skipping elections, type_of_work, tribal_government - intro_page = self.app.get(reverse("domain-request:")) + intro_page = self.app.get(reverse("domain-request:start")) # 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 @@ -873,7 +873,7 @@ def test_domain_request_form_started_allsteps(self): @less_console_noise_decorator def test_domain_request_form_conditional_federal(self): """Federal branch question is shown for federal organizations.""" - intro_page = self.app.get(reverse("domain-request:")) + intro_page = self.app.get(reverse("domain-request:start")) # 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 @@ -929,7 +929,7 @@ def test_domain_request_form_conditional_federal(self): @less_console_noise_decorator def test_domain_request_form_conditional_elections(self): """Election question is shown for other organizations.""" - intro_page = self.app.get(reverse("domain-request:")) + intro_page = self.app.get(reverse("domain-request:start")) # 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 @@ -984,7 +984,7 @@ def test_domain_request_form_conditional_elections(self): @less_console_noise_decorator def test_domain_request_form_section_skipping(self): """Can skip forward and back in sections""" - intro_page = self.app.get(reverse("domain-request:")) + intro_page = self.app.get(reverse("domain-request:start")) # 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 @@ -1029,7 +1029,7 @@ def test_domain_request_form_section_skipping(self): @less_console_noise_decorator def test_domain_request_form_nonfederal(self): """Non-federal organizations don't have to provide their federal agency.""" - intro_page = self.app.get(reverse("domain-request:")) + intro_page = self.app.get(reverse("domain-request:start")) # 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 @@ -1074,7 +1074,7 @@ def test_domain_request_form_nonfederal(self): @less_console_noise_decorator def test_domain_request_about_your_organization_special(self): """Special districts have to answer an additional question.""" - intro_page = self.app.get(reverse("domain-request:")) + intro_page = self.app.get(reverse("domain-request:start")) # 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 @@ -1104,7 +1104,7 @@ def test_domain_request_about_your_organization_special(self): def test_federal_agency_dropdown_excludes_expected_values(self): """The Federal Agency dropdown on a domain request form should not include options for gov Administration and Non-Federal Agency""" - intro_page = self.app.get(reverse("domain-request:")) + intro_page = self.app.get(reverse("domain-request:start")) # 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 @@ -2303,7 +2303,7 @@ def test_edit_creator_in_place(self): @less_console_noise_decorator def test_domain_request_about_your_organiztion_interstate(self): """Special districts have to answer an additional question.""" - intro_page = self.app.get(reverse("domain-request:")) + intro_page = self.app.get(reverse("domain-request:start")) # 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 @@ -2332,7 +2332,7 @@ def test_domain_request_about_your_organiztion_interstate(self): @less_console_noise_decorator def test_domain_request_tribal_government(self): """Tribal organizations have to answer an additional question.""" - intro_page = self.app.get(reverse("domain-request:")) + intro_page = self.app.get(reverse("domain-request:start")) # 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 @@ -2363,7 +2363,7 @@ def test_domain_request_tribal_government(self): @less_console_noise_decorator def test_domain_request_so_dynamic_text(self): - intro_page = self.app.get(reverse("domain-request:")) + intro_page = self.app.get(reverse("domain-request:start")) # 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 @@ -2447,7 +2447,7 @@ def test_domain_request_so_dynamic_text(self): @less_console_noise_decorator def test_domain_request_dotgov_domain_dynamic_text(self): - intro_page = self.app.get(reverse("domain-request:")) + intro_page = self.app.get(reverse("domain-request:start")) # 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 @@ -2712,7 +2712,7 @@ def test_long_org_name_in_domain_request(self): Make sure the long name is displaying in the domain request form, org step """ - intro_page = self.app.get(reverse("domain-request:")) + intro_page = self.app.get(reverse("domain-request:start")) # 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 @@ -2751,7 +2751,7 @@ def test_portfolio_user_missing_edit_permissions(self): user=self.user, portfolio=portfolio, roles=[UserPortfolioRoleChoices.ORGANIZATION_MEMBER] ) # This user should be forbidden from creating new domain requests - intro_page = self.app.get(reverse("domain-request:"), expect_errors=True) + intro_page = self.app.get(reverse("domain-request:start"), expect_errors=True) self.assertEqual(intro_page.status_code, 403) # This user should also be forbidden from editing existing ones @@ -2773,7 +2773,7 @@ def test_portfolio_user_with_edit_permissions(self): ) # This user should be allowed to create new domain requests - intro_page = self.app.get(reverse("domain-request:")) + intro_page = self.app.get(reverse("domain-request:start")) self.assertEqual(intro_page.status_code, 200) # This user should also be allowed to edit existing ones diff --git a/src/registrar/views/domain_request.py b/src/registrar/views/domain_request.py index 7bbe78775..70fefab11 100644 --- a/src/registrar/views/domain_request.py +++ b/src/registrar/views/domain_request.py @@ -53,7 +53,7 @@ class DomainRequestWizard(DomainRequestWizardPermissionView, TemplateView): URL_NAMESPACE = "domain-request" # name for accessing /domain-request//edit EDIT_URL_NAME = "edit-domain-request" - NEW_URL_NAME = "/request/" + NEW_URL_NAME = "/request/start/" # region: Titles # We need to pass our human-readable step titles as context to the templates. @@ -315,6 +315,7 @@ def get(self, request, *args, **kwargs): # send users "to the domain request wizard" without needing to know which view # is first in the list of steps. if self.__class__ == DomainRequestWizard: + print(F"what is this? {request.path_info}") if request.path_info == self.NEW_URL_NAME: # Clear context so the prop getter won't create a request here. # Creating a request will be handled in the post method for the @@ -485,6 +486,7 @@ def get_context_data(self): # Hides the requests and domains buttons in the navbar context_stuff["hide_requests"] = self.is_portfolio context_stuff["hide_domains"] = self.is_portfolio + context_stuff["domain_request_id"] = self.domain_request.id return context_stuff @@ -493,12 +495,12 @@ def get_step_list(self) -> list: return request_step_list(self, self.get_step_enum()) def goto(self, step): - if step == "generic_org_type" or step == "portfolio_requesting_entity": - # We need to avoid creating a new domain request if the user - # clicks the back button - self.request.session["new_request"] = False self.steps.current = step - return redirect(reverse(f"{self.URL_NAMESPACE}:{step}")) + self.domain_request + # Get or create the domain request + domain_request = self.domain_request + test = self.storage.get("domain_request_id") + return redirect(reverse(f"{self.URL_NAMESPACE}:{step}", kwargs={"pk": domain_request.pk})) def goto_next_step(self): """Redirects to the next step.""" @@ -524,9 +526,6 @@ def post(self, request, *args, **kwargs) -> HttpResponse: # which button did the user press? button: str = request.POST.get("submit_button", "") - if "new_request" not in request.session: - request.session["new_request"] = True - # if user has acknowledged the intro message if button == "intro_acknowledge": # Split into a function: C901 'DomainRequestWizard.post' is too complex (11) @@ -564,9 +563,6 @@ def post(self, request, *args, **kwargs) -> HttpResponse: def handle_intro_acknowledge(self, request): """If we are starting a new request, clear storage and redirect to the first step""" - if request.path_info == self.NEW_URL_NAME: - if self.request.session["new_request"] is True: - del self.storage return self.goto(self.steps.first) def save(self, forms: list): diff --git a/src/registrar/views/index.py b/src/registrar/views/index.py index 53900a4a7..7019c8db3 100644 --- a/src/registrar/views/index.py +++ b/src/registrar/views/index.py @@ -7,7 +7,6 @@ def index(request): if request and request.user and request.user.is_authenticated: # This controls the creation of a new domain request in the wizard - request.session["new_request"] = True context["user_domain_count"] = request.user.get_user_domain_ids(request).count() return render(request, "home.html", context) diff --git a/src/registrar/views/portfolios.py b/src/registrar/views/portfolios.py index 6fb976d5c..42158737a 100644 --- a/src/registrar/views/portfolios.py +++ b/src/registrar/views/portfolios.py @@ -46,8 +46,6 @@ class PortfolioDomainRequestsView(PortfolioDomainRequestsPermissionView, View): template_name = "portfolio_requests.html" def get(self, request): - if self.request.user.is_authenticated: - request.session["new_request"] = True return render(request, "portfolio_requests.html") diff --git a/src/registrar/views/user_profile.py b/src/registrar/views/user_profile.py index 4d3b44366..2012d12ab 100644 --- a/src/registrar/views/user_profile.py +++ b/src/registrar/views/user_profile.py @@ -53,7 +53,7 @@ def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # Set the profile_back_button_text based on the redirect parameter - if kwargs.get("redirect") == "domain-request:": + if kwargs.get("redirect") == "domain-request:start": context["profile_back_button_text"] = "Go back to your domain request" else: context["profile_back_button_text"] = "Go to manage your domains" From 37894e7ede4544b35fcdaa67e6364d598c85a9b1 Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Thu, 31 Oct 2024 15:20:50 -0600 Subject: [PATCH 04/31] fix session issue --- src/registrar/config/urls.py | 10 +++------- src/registrar/templates/domain_request_form.html | 2 +- src/registrar/templates/domain_request_sidebar.html | 2 +- .../includes/portfolio_request_review_steps.html | 2 +- .../templates/includes/request_review_steps.html | 2 +- src/registrar/views/domain_request.py | 8 +++----- 6 files changed, 10 insertions(+), 16 deletions(-) diff --git a/src/registrar/config/urls.py b/src/registrar/config/urls.py index d1551c9da..8ee89799f 100644 --- a/src/registrar/config/urls.py +++ b/src/registrar/config/urls.py @@ -39,13 +39,9 @@ from api.views import available, rdap, get_current_federal, get_current_full DOMAIN_REQUEST_NAMESPACE = views.DomainRequestWizard.URL_NAMESPACE -domain_request_start_and_finished_urls = [ - path("start/", views.DomainRequestWizard.as_view(), name="start"), - path("finished/", views.Finished.as_view(), name="finished"), -] -domain_request_urls = [] # dynamically generate the other domain_request_urls +domain_request_urls = [] for step, view in [ # add/remove steps here (Step.ORGANIZATION_TYPE, views.OrganizationType), @@ -255,8 +251,8 @@ path("health", views.health, name="health"), path("openid/", include("djangooidc.urls")), path("request/start/", views.DomainRequestWizard.as_view(), name="start"), - #path("request/", include((domain_request_start_and_finished_urls, DOMAIN_REQUEST_NAMESPACE))), - path("request//", include((domain_request_urls, DOMAIN_REQUEST_NAMESPACE))), + path("request/finished/", views.Finished.as_view(), name="finished"), + path("request//", include((domain_request_urls, DOMAIN_REQUEST_NAMESPACE))), path("api/v1/available/", available, name="available"), path("api/v1/rdap/", rdap, name="rdap"), path("api/v1/get-report/current-federal", get_current_federal, name="get-current-federal"), diff --git a/src/registrar/templates/domain_request_form.html b/src/registrar/templates/domain_request_form.html index fe1d816e6..49c61c524 100644 --- a/src/registrar/templates/domain_request_form.html +++ b/src/registrar/templates/domain_request_form.html @@ -11,7 +11,7 @@

    {% if steps.prev %} - + Previous step diff --git a/src/registrar/templates/domain_request_sidebar.html b/src/registrar/templates/domain_request_sidebar.html index efdfe391e..1af54bb24 100644 --- a/src/registrar/templates/domain_request_sidebar.html +++ b/src/registrar/templates/domain_request_sidebar.html @@ -15,7 +15,7 @@ {% endif %} {% endif %} - {% if is_editable %} - {% namespaced_url 'domain-request' step pk=domain_request_id as domain_request_url %} + {% namespaced_url 'domain-request' step id=domain_request_id as domain_request_url %} {% endif %} {% if step == Step.REQUESTING_ENTITY %} diff --git a/src/registrar/templates/includes/request_review_steps.html b/src/registrar/templates/includes/request_review_steps.html index e0f76b27e..73b71d536 100644 --- a/src/registrar/templates/includes/request_review_steps.html +++ b/src/registrar/templates/includes/request_review_steps.html @@ -4,7 +4,7 @@ {% for step in steps %}
    {% if is_editable %} - {% namespaced_url 'domain-request' step pk=domain_request_id as domain_request_url %} + {% namespaced_url 'domain-request' step id=domain_request_id as domain_request_url %} {% endif %} {% if step == Step.ORGANIZATION_TYPE %} diff --git a/src/registrar/views/domain_request.py b/src/registrar/views/domain_request.py index 70fefab11..6039a570e 100644 --- a/src/registrar/views/domain_request.py +++ b/src/registrar/views/domain_request.py @@ -308,6 +308,8 @@ def get(self, request, *args, **kwargs): if current_url == self.EDIT_URL_NAME and "id" in kwargs: del self.storage self.storage["domain_request_id"] = kwargs["id"] + elif "id" not in kwargs: + del self.storage # if accessing this class directly, redirect to either to an acknowledgement # page or to the first step in the processes (if an edit rather than a new request); @@ -496,11 +498,7 @@ def get_step_list(self) -> list: def goto(self, step): self.steps.current = step - self.domain_request - # Get or create the domain request - domain_request = self.domain_request - test = self.storage.get("domain_request_id") - return redirect(reverse(f"{self.URL_NAMESPACE}:{step}", kwargs={"pk": domain_request.pk})) + return redirect(reverse(f"{self.URL_NAMESPACE}:{step}", kwargs={"id": self.domain_request.id})) def goto_next_step(self): """Redirects to the next step.""" From 20a5774213afddf7780d5d3357022f16984b4d94 Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Thu, 31 Oct 2024 15:42:39 -0600 Subject: [PATCH 05/31] Update domain_request.py --- src/registrar/views/domain_request.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/registrar/views/domain_request.py b/src/registrar/views/domain_request.py index 6039a570e..57ca35628 100644 --- a/src/registrar/views/domain_request.py +++ b/src/registrar/views/domain_request.py @@ -158,6 +158,7 @@ def __init__(self): # Configure titles, wizard_conditions, unlocking_steps, and steps self.configure_step_options() self._domain_request = None # for caching + self.domain_request_id = None def configure_step_options(self): """Changes which steps are available to the user based on self.is_portfolio. @@ -182,7 +183,8 @@ def configure_step_options(self): def has_pk(self): """Does this wizard know about a DomainRequest database record?""" - return "domain_request_id" in self.storage + + return self.kwargs.get("id") is not None def get_step_enum(self): """Determines which step enum we should use for the wizard""" @@ -214,11 +216,10 @@ def domain_request(self) -> DomainRequest: raise ValueError("Invalid value for User") if self.has_pk(): - id = self.storage["domain_request_id"] try: self._domain_request = DomainRequest.objects.get( creator=creator, - pk=id, + pk=self.kwargs.get('id'), ) return self._domain_request except DomainRequest.DoesNotExist: @@ -239,7 +240,7 @@ def domain_request(self) -> DomainRequest: else: self._domain_request = DomainRequest.objects.create(creator=self.request.user) - self.storage["domain_request_id"] = self._domain_request.id + self.kwargs["id"] = self._domain_request.id return self._domain_request @property @@ -295,6 +296,7 @@ def from_model(self, attribute: str, default, *args, **kwargs): def get(self, request, *args, **kwargs): """This method handles GET requests.""" + self.kwargs = kwargs if not self.is_portfolio and self.request.user.is_org_user(request): self.is_portfolio = True # Configure titles, wizard_conditions, unlocking_steps, and steps @@ -307,9 +309,6 @@ def get(self, request, *args, **kwargs): # and remove any prior wizard data from their session if current_url == self.EDIT_URL_NAME and "id" in kwargs: del self.storage - self.storage["domain_request_id"] = kwargs["id"] - elif "id" not in kwargs: - del self.storage # if accessing this class directly, redirect to either to an acknowledgement # page or to the first step in the processes (if an edit rather than a new request); @@ -317,7 +316,6 @@ def get(self, request, *args, **kwargs): # send users "to the domain request wizard" without needing to know which view # is first in the list of steps. if self.__class__ == DomainRequestWizard: - print(F"what is this? {request.path_info}") if request.path_info == self.NEW_URL_NAME: # Clear context so the prop getter won't create a request here. # Creating a request will be handled in the post method for the From 18e25b0aca1120e70e5647db986a0a3ff5cbb761 Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Fri, 1 Nov 2024 13:25:24 -0600 Subject: [PATCH 06/31] cleanup urls a bit --- src/registrar/config/urls.py | 11 ++++++----- src/registrar/templates/home.html | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/registrar/config/urls.py b/src/registrar/config/urls.py index 06c722923..2d517a26e 100644 --- a/src/registrar/config/urls.py +++ b/src/registrar/config/urls.py @@ -41,7 +41,10 @@ DOMAIN_REQUEST_NAMESPACE = views.DomainRequestWizard.URL_NAMESPACE # dynamically generate the other domain_request_urls -domain_request_urls = [] +domain_request_urls = [ + path("start/", views.DomainRequestWizard.as_view(), name="start"), + path("finished/", views.Finished.as_view(), name="finished"), +] for step, view in [ # add/remove steps here (Step.ORGANIZATION_TYPE, views.OrganizationType), @@ -62,7 +65,7 @@ (PortfolioDomainRequestStep.REQUESTING_ENTITY, views.RequestingEntity), (PortfolioDomainRequestStep.ADDITIONAL_DETAILS, views.PortfolioAdditionalDetails), ]: - domain_request_urls.append(path(f"{step}/", view.as_view(), name=step)) + domain_request_urls.append(path(f"/{step}/", view.as_view(), name=step)) urlpatterns = [ @@ -255,9 +258,7 @@ ), path("health", views.health, name="health"), path("openid/", include("djangooidc.urls")), - path("request/start/", views.DomainRequestWizard.as_view(), name="start"), - path("request/finished/", views.Finished.as_view(), name="finished"), - path("request//", include((domain_request_urls, DOMAIN_REQUEST_NAMESPACE))), + path("request/", include((domain_request_urls, DOMAIN_REQUEST_NAMESPACE))), path("api/v1/available/", available, name="available"), path("api/v1/rdap/", rdap, name="rdap"), path("api/v1/get-report/current-federal", get_current_federal, name="get-current-federal"), diff --git a/src/registrar/templates/home.html b/src/registrar/templates/home.html index 0fa077daa..b00c57b5c 100644 --- a/src/registrar/templates/home.html +++ b/src/registrar/templates/home.html @@ -18,7 +18,7 @@

    Manage your domains

    - Start a new domain request From 4ae764bf0b43ee3ab9d169545dec845a65c48127 Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Fri, 1 Nov 2024 15:05:07 -0600 Subject: [PATCH 07/31] (draft) get a domain id per session --- src/registrar/assets/js/get-gov.js | 27 +++++++++++++++++++ .../templates/domain_request_form.html | 1 + 2 files changed, 28 insertions(+) diff --git a/src/registrar/assets/js/get-gov.js b/src/registrar/assets/js/get-gov.js index adcc21d2a..15d6b1712 100644 --- a/src/registrar/assets/js/get-gov.js +++ b/src/registrar/assets/js/get-gov.js @@ -2820,3 +2820,30 @@ document.addEventListener('DOMContentLoaded', function() { // Add event listener to the suborg dropdown to show/hide the suborg details section select.addEventListener("change", () => toggleSuborganization()); })(); + + +(function handleBackButtonStuff() { + function handleStuff() { + const domainRequestId = document.getElementById("wizard-domain-request-id")?.value; + if (domainRequestId) { + sessionStorage.setItem("domainRequestId", domainRequestId); + console.log("Domain request ID stored:", domainRequestId); + } + } + + // Handle back button navigation and initial page load + function handleStartPage(event) { + if (window.location.pathname === "/request/start/") { + if (event && !event.persisted) return; + const domainRequestId = sessionStorage.getItem("domainRequestId"); + console.log("Domain request ID retrieved:", domainRequestId); + } + } + + // Listen for back/forward navigation + window.addEventListener('pageshow', handleStartPage); + + // Handle initial page load + handleStuff(); + handleStartPage(); +})(); diff --git a/src/registrar/templates/domain_request_form.html b/src/registrar/templates/domain_request_form.html index 49c61c524..db99bdf10 100644 --- a/src/registrar/templates/domain_request_form.html +++ b/src/registrar/templates/domain_request_form.html @@ -10,6 +10,7 @@

    + {% if steps.prev %}
    - {% if steps.prev %} + {% if steps.current == steps.first %} + {% if portfolio %} + + Back to domain requests + + {% else %} + + Back to home + + {% endif %} + {% elif steps.prev %} Back to domain requests - + {% url 'domain-requests' as url_2 %} {% else %} - - Back to home - + {% url 'home' as url_2 %} {% endif %} + {% elif steps.prev %} Previous step - {% comment %} - TODO: uncomment in #2596 - {% else %} - {% if portfolio %} - {% url 'domain-requests' as url_2 %} - - {% endif %} {% endcomment %} {% endif %} {% block form_messages %} From 5fa622ada136bfa6202bb30c153faf33aaa0dda7 Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Thu, 7 Nov 2024 12:41:57 -0700 Subject: [PATCH 28/31] Unit test --- src/registrar/tests/test_views_request.py | 63 +++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/src/registrar/tests/test_views_request.py b/src/registrar/tests/test_views_request.py index e253d5ae6..13f7d12cc 100644 --- a/src/registrar/tests/test_views_request.py +++ b/src/registrar/tests/test_views_request.py @@ -2959,6 +2959,69 @@ def tearDown(self): DomainRequest.objects.all().delete() DomainInformation.objects.all().delete() + @less_console_noise_decorator + def test_breadcrumb_navigation(self): + """ + Tests the breadcrumb navigation behavior in domain request wizard. + Ensures that: + - Breadcrumb shows correct text based on portfolio flag + - Links point to correct destinations + - Back button appears on appropriate steps + - Back button is not present on first step + """ + # Create initial domain request + domain_request = completed_domain_request( + status=DomainRequest.DomainRequestStatus.STARTED, + user=self.user, + ) + + # Test without portfolio flag + start_page = self.app.get(f"/domain-request/{domain_request.id}/edit/").follow() + session_id = self.app.cookies[settings.SESSION_COOKIE_NAME] + self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id) + + # Check initial breadcrumb state. + # Ensure that the request name is shown if it exists, otherwise just show new domain request. + self.assertContains(start_page, '
      ') + self.assertContains(start_page, "city.gov") + self.assertContains(start_page, 'href="/"') + self.assertContains(start_page, "Manage your domains") + self.assertNotContains(start_page, "Previous step") + + # Move to next step + form = start_page.forms[0] + next_page = form.submit().follow() + self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id) + + # Verify that the back button appears + self.assertContains(next_page, "Previous step") + self.assertContains(next_page, "#arrow_back") + + # Test with portfolio flag + with override_flag("organization_feature", active=True), override_flag("organization_requests", active=True): + portfolio = Portfolio.objects.create( + creator=self.user, + organization_name="test portfolio", + ) + permission = UserPortfolioPermission.objects.create( + user=self.user, + portfolio=portfolio, + roles=[UserPortfolioRoleChoices.ORGANIZATION_ADMIN], + ) + + # Check portfolio-specific breadcrumb + portfolio_page = self.app.get(f"/domain-request/{domain_request.id}/edit/").follow() + self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id) + + self.assertContains(portfolio_page, "Domain requests") + + # Clean up portfolio + permission.delete() + portfolio.delete() + + # Clean up + domain_request.delete() + @less_console_noise_decorator def test_unlocked_steps_empty_domain_request(self): """Test when all fields in the domain request are empty.""" From 14f861b81edfe20b9c8c568289d0056dfc652686 Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Thu, 7 Nov 2024 12:44:14 -0700 Subject: [PATCH 29/31] Update test_views_request.py --- src/registrar/tests/test_views_request.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/registrar/tests/test_views_request.py b/src/registrar/tests/test_views_request.py index 13f7d12cc..a973e590f 100644 --- a/src/registrar/tests/test_views_request.py +++ b/src/registrar/tests/test_views_request.py @@ -3063,7 +3063,7 @@ def test_unlocked_steps_full_domain_request(self): # 10 unlocked steps, one active step, the review step will have link_usa but not check_circle self.assertContains(detail_page, "#check_circle", count=9) # Type of organization - self.assertContains(detail_page, "usa-current", count=1) + self.assertContains(detail_page, "usa-current", count=2) self.assertContains(detail_page, "link_usa-checked", count=10) else: @@ -3125,7 +3125,7 @@ def test_unlocked_steps_partial_domain_request(self): # which unlocks if domain exists), one active step, the review step is locked self.assertContains(detail_page, "#check_circle", count=4) # Type of organization - self.assertContains(detail_page, "usa-current", count=1) + self.assertContains(detail_page, "usa-current", count=2) self.assertContains(detail_page, "link_usa-checked", count=4) else: @@ -3199,7 +3199,7 @@ def test_wizard_steps_portfolio(self): self.assertContains(detail_page, "#lock", 1) # The current option should be selected - self.assertContains(detail_page, "usa-current", count=1) + self.assertContains(detail_page, "usa-current", count=2) # We default to the requesting entity page expected_url = reverse("domain-request:portfolio_requesting_entity", kwargs={"id": domain_request.id}) From f5cc5a63495412a9fcc6677d45e825636c85d161 Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Thu, 7 Nov 2024 12:56:10 -0700 Subject: [PATCH 30/31] Update test_views_request.py --- src/registrar/tests/test_views_request.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/registrar/tests/test_views_request.py b/src/registrar/tests/test_views_request.py index a973e590f..a73fac5a8 100644 --- a/src/registrar/tests/test_views_request.py +++ b/src/registrar/tests/test_views_request.py @@ -3209,7 +3209,7 @@ def test_wizard_steps_portfolio(self): # We shouldn't show the "domains" and "domain requests" buttons # on this page. self.assertNotContains(detail_page, "Domains") - self.assertNotContains(detail_page, "Domain requests") + self.assertNotContains(detail_page, "Domain requests") else: self.fail(f"Expected a redirect, but got a different response: {response}") From dd574bc6a9d8e16f9fd9d3f3df9e0e3dc974d151 Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Fri, 8 Nov 2024 09:57:41 -0700 Subject: [PATCH 31/31] PR suggestions --- src/registrar/views/domain_request.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/registrar/views/domain_request.py b/src/registrar/views/domain_request.py index cde9ff417..6519a5bbc 100644 --- a/src/registrar/views/domain_request.py +++ b/src/registrar/views/domain_request.py @@ -183,9 +183,7 @@ def configure_step_options(self): def has_pk(self): """Does this wizard know about a DomainRequest database record?""" - if self.kwargs.get("id") is not None: - return True - return False + return bool(self.kwargs.get("id") is not None) def get_step_enum(self): """Determines which step enum we should use for the wizard""" @@ -450,7 +448,7 @@ def get_context_data(self): if self.domain_request.requested_domain is not None: requested_domain_name = self.domain_request.requested_domain.name - context_stuff = {} + context = {} # Note: we will want to consolidate the non_org_steps_complete check into the same check that # org_steps_complete is using at some point. @@ -458,7 +456,7 @@ def get_context_data(self): org_steps_complete = len(self.db_check_for_unlocking_steps()) == len(self.steps) if (not self.is_portfolio and non_org_steps_complete) or (self.is_portfolio and org_steps_complete): modal_button = '" - context_stuff = { + context = { "not_form": False, "form_titles": self.titles, "steps": self.steps, @@ -475,7 +473,7 @@ def get_context_data(self): } else: # form is not complete modal_button = '' - context_stuff = { + context = { "not_form": True, "form_titles": self.titles, "steps": self.steps, @@ -491,11 +489,11 @@ def get_context_data(self): } # Hides the requests and domains buttons in the navbar - context_stuff["hide_requests"] = self.is_portfolio - context_stuff["hide_domains"] = self.is_portfolio - context_stuff["domain_request_id"] = self.domain_request.id + context["hide_requests"] = self.is_portfolio + context["hide_domains"] = self.is_portfolio + context["domain_request_id"] = self.domain_request.id - return context_stuff + return context def get_step_list(self) -> list: """Dynamically generated list of steps in the form wizard."""