mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-07-21 10:16:13 +02:00
Unit tests
This commit is contained in:
parent
b1cdb1b3e4
commit
4aa91ccc9c
4 changed files with 167 additions and 19 deletions
|
@ -60,15 +60,8 @@ for step, view in [
|
||||||
(Step.ADDITIONAL_DETAILS, views.AdditionalDetails),
|
(Step.ADDITIONAL_DETAILS, views.AdditionalDetails),
|
||||||
(Step.REQUIREMENTS, views.Requirements),
|
(Step.REQUIREMENTS, views.Requirements),
|
||||||
(Step.REVIEW, views.Review),
|
(Step.REVIEW, views.Review),
|
||||||
|
|
||||||
# Portfolio steps
|
# Portfolio steps
|
||||||
(PortfolioDomainRequestStep.REQUESTING_ENTITY, views.RequestingEntity),
|
(PortfolioDomainRequestStep.REQUESTING_ENTITY, views.RequestingEntity),
|
||||||
# (PortfolioDomainRequestStep.CURRENT_SITES, views.CurrentSites),
|
|
||||||
# (PortfolioDomainRequestStep.DOTGOV_DOMAIN, views.DotgovDomain),
|
|
||||||
# (PortfolioDomainRequestStep.PURPOSE, views.Purpose),
|
|
||||||
# (PortfolioDomainRequestStep.ADDITIONAL_DETAILS, views.AdditionalDetails),
|
|
||||||
# (PortfolioDomainRequestStep.REQUIREMENTS, views.Requirements),
|
|
||||||
# (PortfolioDomainRequestStep.REVIEW, views.Review),
|
|
||||||
]:
|
]:
|
||||||
domain_request_urls.append(path(f"{step}/", view.as_view(), name=step))
|
domain_request_urls.append(path(f"{step}/", view.as_view(), name=step))
|
||||||
|
|
||||||
|
|
|
@ -13,4 +13,4 @@
|
||||||
|
|
||||||
{% input_with_errors forms.0.organization_name %}
|
{% input_with_errors forms.0.organization_name %}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -2742,6 +2742,64 @@ class DomainRequestTests(TestWithUser, WebTest):
|
||||||
self.assertContains(review_page, "toggle-submit-domain-request")
|
self.assertContains(review_page, "toggle-submit-domain-request")
|
||||||
self.assertContains(review_page, "Your request form is incomplete")
|
self.assertContains(review_page, "Your request form is incomplete")
|
||||||
|
|
||||||
|
@override_flag("organization_feature", active=True)
|
||||||
|
@override_flag("organization_requests", active=True)
|
||||||
|
def test_portfolio_user_missing_edit_permissions(self):
|
||||||
|
"""Tests that a portfolio user without edit request permissions cannot edit or add new requests"""
|
||||||
|
portfolio, _ = Portfolio.objects.get_or_create(creator=self.user, organization_name="Test Portfolio")
|
||||||
|
portfolio_perm, _ = UserPortfolioPermission.objects.get_or_create(
|
||||||
|
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)
|
||||||
|
self.assertEqual(intro_page.status_code, 403)
|
||||||
|
|
||||||
|
# This user should also be forbidden from editing existing ones
|
||||||
|
domain_request = completed_domain_request(user=self.user)
|
||||||
|
edit_page = self.app.get(reverse("edit-domain-request", kwargs={"id": domain_request.pk}), expect_errors=True)
|
||||||
|
self.assertEqual(edit_page.status_code, 403)
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
portfolio_perm.delete()
|
||||||
|
portfolio.delete()
|
||||||
|
|
||||||
|
@override_flag("organization_feature", active=True)
|
||||||
|
@override_flag("organization_requests", active=True)
|
||||||
|
def test_portfolio_user_with_edit_permissions(self):
|
||||||
|
"""Tests that a portfolio user with edit request permissions can edit and add new requests"""
|
||||||
|
portfolio, _ = Portfolio.objects.get_or_create(creator=self.user, organization_name="Test Portfolio")
|
||||||
|
portfolio_perm, _ = UserPortfolioPermission.objects.get_or_create(
|
||||||
|
user=self.user, portfolio=portfolio, roles=[UserPortfolioRoleChoices.ORGANIZATION_ADMIN]
|
||||||
|
)
|
||||||
|
|
||||||
|
# This user should be allowed to create new domain requests
|
||||||
|
intro_page = self.app.get(reverse("domain-request:"))
|
||||||
|
self.assertEqual(intro_page.status_code, 200)
|
||||||
|
|
||||||
|
# This user should also be allowed to edit existing ones
|
||||||
|
domain_request = completed_domain_request(user=self.user)
|
||||||
|
edit_page = self.app.get(reverse("edit-domain-request", kwargs={"id": domain_request.pk}))
|
||||||
|
self.assertEqual(edit_page.status_code, 200)
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
portfolio_perm.delete()
|
||||||
|
portfolio.delete()
|
||||||
|
|
||||||
|
def test_non_creator_access(self):
|
||||||
|
"""Tests that a user cannot edit a domain request they didn't create"""
|
||||||
|
other_user = User.objects.create_user(username="other_user", password="password")
|
||||||
|
domain_request = completed_domain_request(user=other_user)
|
||||||
|
|
||||||
|
edit_page = self.app.get(reverse("edit-domain-request", kwargs={"id": domain_request.pk}), expect_errors=True)
|
||||||
|
self.assertEqual(edit_page.status_code, 403)
|
||||||
|
|
||||||
|
def test_creator_access(self):
|
||||||
|
"""Tests that a user can edit a domain request they created"""
|
||||||
|
domain_request = completed_domain_request(user=self.user)
|
||||||
|
|
||||||
|
edit_page = self.app.get(reverse("edit-domain-request", kwargs={"id": domain_request.pk}))
|
||||||
|
self.assertEqual(edit_page.status_code, 200)
|
||||||
|
|
||||||
|
|
||||||
class DomainRequestTestDifferentStatuses(TestWithUser, WebTest):
|
class DomainRequestTestDifferentStatuses(TestWithUser, WebTest):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
@ -2904,7 +2962,7 @@ class DomainRequestTestDifferentStatuses(TestWithUser, WebTest):
|
||||||
self.assertNotContains(home_page, "city.gov")
|
self.assertNotContains(home_page, "city.gov")
|
||||||
|
|
||||||
|
|
||||||
class TestWizardUnlockingSteps(TestWithUser, WebTest):
|
class TestDomainRequestWizard(TestWithUser, WebTest):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
self.app.set_user(self.user.username)
|
self.app.set_user(self.user.username)
|
||||||
|
@ -2928,7 +2986,10 @@ class TestWizardUnlockingSteps(TestWithUser, WebTest):
|
||||||
def test_unlocked_steps_full_domain_request(self):
|
def test_unlocked_steps_full_domain_request(self):
|
||||||
"""Test when all fields in the domain request are filled."""
|
"""Test when all fields in the domain request are filled."""
|
||||||
|
|
||||||
domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.STARTED, user=self.user)
|
domain_request = completed_domain_request(
|
||||||
|
status=DomainRequest.DomainRequestStatus.STARTED,
|
||||||
|
user=self.user
|
||||||
|
)
|
||||||
domain_request.anything_else = False
|
domain_request.anything_else = False
|
||||||
domain_request.has_anything_else_text = False
|
domain_request.has_anything_else_text = False
|
||||||
domain_request.save()
|
domain_request.save()
|
||||||
|
@ -3026,6 +3087,93 @@ class TestWizardUnlockingSteps(TestWithUser, WebTest):
|
||||||
else:
|
else:
|
||||||
self.fail(f"Expected a redirect, but got a different response: {response}")
|
self.fail(f"Expected a redirect, but got a different response: {response}")
|
||||||
|
|
||||||
|
@less_console_noise_decorator
|
||||||
|
@override_flag("organization_feature", active=True)
|
||||||
|
@override_flag("organization_requests", active=True)
|
||||||
|
def test_wizard_steps_portfolio(self):
|
||||||
|
"""
|
||||||
|
Tests the behavior of the domain request wizard for portfolios.
|
||||||
|
Ensures that:
|
||||||
|
- The user can access the organization page.
|
||||||
|
- The expected number of steps are locked/unlocked (implicit test for expected steps).
|
||||||
|
- The user lands on the "Requesting entity" page
|
||||||
|
- The user does not see the Domain and Domain requests buttons
|
||||||
|
"""
|
||||||
|
|
||||||
|
# This should unlock 4 steps by default.
|
||||||
|
# Purpose, .gov domain, current websites, and requirements for operating
|
||||||
|
domain_request = completed_domain_request(
|
||||||
|
status=DomainRequest.DomainRequestStatus.STARTED,
|
||||||
|
user=self.user,
|
||||||
|
)
|
||||||
|
|
||||||
|
federal_agency = FederalAgency.objects.get(agency="Non-Federal Agency")
|
||||||
|
# Add a portfolio
|
||||||
|
portfolio = Portfolio.objects.create(
|
||||||
|
creator=self.user,
|
||||||
|
organization_name="test portfolio",
|
||||||
|
federal_agency=federal_agency,
|
||||||
|
)
|
||||||
|
|
||||||
|
user_portfolio_permission = UserPortfolioPermission.objects.create(
|
||||||
|
user=self.user,
|
||||||
|
portfolio=portfolio,
|
||||||
|
roles=[UserPortfolioRoleChoices.ORGANIZATION_ADMIN],
|
||||||
|
)
|
||||||
|
|
||||||
|
response = self.app.get(f"/domain-request/{domain_request.id}/edit/")
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
# Assert that we're on the organization page
|
||||||
|
self.assertContains(detail_page, portfolio.organization_name)
|
||||||
|
print(f"what is the page? {detail_page}")
|
||||||
|
|
||||||
|
# We should only see one unlocked step
|
||||||
|
self.assertContains(detail_page, "#check_circle", count=4)
|
||||||
|
|
||||||
|
# One pages should still be locked (additional details)
|
||||||
|
self.assertContains(detail_page, "#lock", 1)
|
||||||
|
|
||||||
|
# The current option should be selected
|
||||||
|
self.assertContains(detail_page, "usa-current", count=1)
|
||||||
|
|
||||||
|
# We default to the requesting entity page
|
||||||
|
expected_url = reverse("domain-request:requesting_entity")
|
||||||
|
# This returns the entire url, thus "in"
|
||||||
|
self.assertIn(expected_url, detail_page.request.url)
|
||||||
|
|
||||||
|
# We shouldn't show the "domains" and "domain requests" buttons
|
||||||
|
# on this page.
|
||||||
|
self.assertNotContains(detail_page, "Domains")
|
||||||
|
self.assertNotContains(detail_page, "Domain requests")
|
||||||
|
else:
|
||||||
|
self.fail(f"Expected a redirect, but got a different response: {response}")
|
||||||
|
|
||||||
|
# Data cleanup
|
||||||
|
user_portfolio_permission.delete()
|
||||||
|
portfolio.delete()
|
||||||
|
federal_agency.delete()
|
||||||
|
domain_request.delete()
|
||||||
|
|
||||||
|
|
||||||
class TestPortfolioDomainRequestViewonly(TestWithUser, WebTest):
|
class TestPortfolioDomainRequestViewonly(TestWithUser, WebTest):
|
||||||
|
|
||||||
|
|
|
@ -136,8 +136,8 @@ class DomainRequestWizard(DomainRequestWizardPermissionView, TemplateView):
|
||||||
portfolio=portfolio,
|
portfolio=portfolio,
|
||||||
)
|
)
|
||||||
|
|
||||||
# TODO - is this needed?
|
# Question for reviewers: we should probably be doing this right?
|
||||||
if portfolio:
|
if portfolio and not self._domain_request.generic_org_type:
|
||||||
self._domain_request.generic_org_type = portfolio.organization_type
|
self._domain_request.generic_org_type = portfolio.organization_type
|
||||||
self._domain_request.save()
|
self._domain_request.save()
|
||||||
else:
|
else:
|
||||||
|
@ -505,17 +505,14 @@ class DomainRequestWizard(DomainRequestWizardPermissionView, TemplateView):
|
||||||
|
|
||||||
# which button did the user press?
|
# which button did the user press?
|
||||||
button: str = request.POST.get("submit_button", "")
|
button: str = request.POST.get("submit_button", "")
|
||||||
# If a user hits the new request url directly
|
|
||||||
if "new_request" not in request.session:
|
if "new_request" not in request.session:
|
||||||
request.session["new_request"] = True
|
request.session["new_request"] = True
|
||||||
|
|
||||||
# if user has acknowledged the intro message
|
# if user has acknowledged the intro message
|
||||||
if button == "intro_acknowledge":
|
if button == "intro_acknowledge":
|
||||||
if request.path_info == self.NEW_URL_NAME:
|
# Split into a function: C901 'DomainRequestWizard.post' is too complex (11)
|
||||||
|
self.handle_intro_acknowledge(request)
|
||||||
if self.request.session["new_request"] is True:
|
|
||||||
# This will trigger the domain_request getter into creating a new DomainRequest
|
|
||||||
del self.storage
|
|
||||||
return self.goto(self.steps.first)
|
|
||||||
|
|
||||||
# if accessing this class directly, redirect to the first step
|
# if accessing this class directly, redirect to the first step
|
||||||
if self.__class__ == DomainRequestWizard:
|
if self.__class__ == DomainRequestWizard:
|
||||||
|
@ -546,6 +543,14 @@ class DomainRequestWizard(DomainRequestWizardPermissionView, TemplateView):
|
||||||
# otherwise, proceed as normal
|
# otherwise, proceed as normal
|
||||||
return self.goto_next_step()
|
return self.goto_next_step()
|
||||||
|
|
||||||
|
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):
|
def save(self, forms: list):
|
||||||
"""
|
"""
|
||||||
Unpack the form responses onto the model object properties.
|
Unpack the form responses onto the model object properties.
|
||||||
|
@ -576,11 +581,13 @@ class PortfolioDomainRequestWizard(DomainRequestWizard):
|
||||||
self.steps = StepsHelper(self)
|
self.steps = StepsHelper(self)
|
||||||
self._domain_request = None # for caching
|
self._domain_request = None # for caching
|
||||||
|
|
||||||
|
|
||||||
# Portfolio pages
|
# Portfolio pages
|
||||||
class RequestingEntity(DomainRequestWizard):
|
class RequestingEntity(DomainRequestWizard):
|
||||||
template_name = "domain_request_requesting_entity.html"
|
template_name = "domain_request_requesting_entity.html"
|
||||||
forms = [forms.RequestingEntityForm]
|
forms = [forms.RequestingEntityForm]
|
||||||
|
|
||||||
|
|
||||||
# Non-portfolio pages
|
# Non-portfolio pages
|
||||||
class OrganizationType(DomainRequestWizard):
|
class OrganizationType(DomainRequestWizard):
|
||||||
template_name = "domain_request_org_type.html"
|
template_name = "domain_request_org_type.html"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue