Skip to content

Commit

Permalink
FS-4927 - Add intermediary pages 'Select a Fund' and 'Select an Appli…
Browse files Browse the repository at this point in the history
…cation' before 'Build application'
  • Loading branch information
wjrm500 committed Jan 3, 2025
1 parent 35f8906 commit 03779f7
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 2 deletions.
42 changes: 41 additions & 1 deletion app/blueprints/application/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
update_section,
)
from app.db.queries.clone import clone_single_form
from app.db.queries.fund import get_fund_by_id
from app.db.queries.fund import get_all_funds, get_fund_by_id
from app.db.queries.round import get_round_by_id
from app.export_config.generate_all_questions import print_html
from app.export_config.generate_assessment_config import (
Expand All @@ -54,6 +54,46 @@
)


@application_bp.route("/sections/select-fund", methods=["GET", "POST"])
def select_fund():
"""
Intermediary page to select a Fund before building an Application.
"""
if request.method == "POST":
fund_id = request.form.get("fund_id")
if not fund_id:
raise ValueError("Fund ID is required to manage an application")
return redirect(url_for("application_bp.select_application", fund_id=fund_id))
fund_dropdown_items = [{"value": "", "text": "Select a fund"}]
for fund in get_all_funds():
fund_dropdown_items.append(
{"value": str(fund.fund_id), "text": fund.short_name + " - " + fund.title_json["en"]}
)
return render_template("select_fund.html", fund_dropdown_items=fund_dropdown_items)


@application_bp.route("/sections/select-application", methods=["GET", "POST"])
def select_application():
"""
Intermediary page to select an Application before managing its tasklist.
"""
if request.method == "POST":
round_id = request.form.get("round_id")
if not round_id:
raise ValueError("Round ID is required to manage an application")
return redirect(url_for("application_bp.build_application", round_id=round_id))
fund_id = request.args.get("fund_id")
if not fund_id:
raise ValueError("Fund ID is required to manage an application")
round_dropdown_items = [{"value": "", "text": "Select an application"}]
fund = get_fund_by_id(fund_id)
for round_ in fund.rounds:
round_dropdown_items.append(
{"value": str(round_.round_id), "text": round_.short_name + " - " + round_.title_json["en"]}
)
return render_template("select_application.html", fund=fund, round_dropdown_items=round_dropdown_items)


@application_bp.route("/<round_id>/sections")
def build_application(round_id):
"""
Expand Down
2 changes: 1 addition & 1 deletion app/blueprints/index/templates/dashboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ <h2 class="govuk-heading-s">Fund Configuration (PoC)</h2>
<a class="govuk-link" href="{{ url_for("round_bp.select_fund") }}">Create a Round</a>
</li>
<li class="govuk-body">
<a class="govuk-link" href="{{ url_for("fund_bp.view_fund") }}">Manage Application Configuration</a>
<a class="govuk-link" href="{{ url_for("application_bp.select_fund") }}">Manage Application Configuration</a>
</li>
<li class="govuk-body">
<a class="govuk-link" href="{{ url_for("template_bp.view_templates") }}">Manage Templates</a>
Expand Down
45 changes: 45 additions & 0 deletions app/templates/select_application.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{% extends "base.html" %}
{% from "govuk_frontend_jinja/components/button/macro.html" import govukButton %}
{% from "govuk_frontend_jinja/components/select/macro.html" import govukSelect %}

{% block content %}
<div class="govuk-grid-row">
<div class="govuk-grid-column-full">
<span class="govuk-caption-m">{{ fund.short_name + " - " + fund.title_json["en"] }}</span>
<h1 class="govuk-heading-l">Select an application</h1>
<p class="govuk-body">Select the application you want to manage or create a new one</p>

<form method="POST">
{{ govukSelect({
"id": "round_id",
"name": "round_id",
"items": round_dropdown_items,
"label": "",
"attributes": {
"required": "required"
},
"classes": "govuk-!-width-one-half",
"formGroup": {
"classes": "govuk-!-margin-bottom-3"
}
}) }}

<p class="govuk-body govuk-!-margin-top-1 govuk-!-margin-bottom-6">
<a href="{{ url_for('round_bp.create_round', fund_id=fund.fund_id) }}" class="govuk-link">Add a new application</a>
</p>

<div class="govuk-button-group">
{{ govukButton({
"text": "Continue",
"type": "submit"
}) }}
{{ govukButton({
"text": "Cancel",
"href": url_for("index_bp.dashboard"),
"classes": "govuk-button--secondary"
}) }}
</div>
</form>
</div>
</div>
{% endblock content %}
67 changes: 67 additions & 0 deletions tests/blueprints/application/test_routes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import pytest
from flask import url_for


@pytest.mark.usefixtures("set_auth_cookie", "patch_validate_token_rs256_internal_user")
def test_select_fund(flask_test_client, seed_dynamic_data):
"""
Test the /rounds/sections/select-fund route to ensure:
1) A user cannot proceed without selecting a fund,
2) A valid fund selection redirects to the select_application page.
"""
# Attempt to submit without a fund selected
with pytest.raises(ValueError, match="Fund ID is required to manage an application"):
flask_test_client.post(
"/rounds/sections/select-fund",
data={"fund_id": ""},
follow_redirects=True,
)

# Submit with a valid fund
test_fund = seed_dynamic_data["funds"][0]
response = flask_test_client.post(
"/rounds/sections/select-fund", data={"fund_id": str(test_fund.fund_id)}, follow_redirects=False
)
assert response.status_code == 302

# Confirm redirect to the application_bp.select_application route
expected_location = url_for("application_bp.select_application", fund_id=test_fund.fund_id)
assert response.location == expected_location


@pytest.mark.usefixtures("set_auth_cookie", "patch_validate_token_rs256_internal_user")
def test_select_application(flask_test_client, seed_dynamic_data):
"""
Test the /rounds/sections/select-application route to ensure:
1) A user cannot proceed without selecting an application,
2) A valid application selection redirects to the build_application page.
"""
# Attempt to see the page without a fund ID
with pytest.raises(ValueError, match="Fund ID is required to manage an application"):
flask_test_client.get("/rounds/sections/select-application", follow_redirects=True)

# Attempt to see the page with an invalid fund ID
invalid_fund_id = "123e4567-e89b-12d3-a456-426614174000"
with pytest.raises(ValueError, match=f"Fund with id {invalid_fund_id} not found"):
flask_test_client.get(f"/rounds/sections/select-application?fund_id={invalid_fund_id}", follow_redirects=True)

# Attempt to submit without a round selected
with pytest.raises(ValueError, match="Round ID is required to manage an application"):
flask_test_client.post(
"/rounds/sections/select-application",
data={"round_id": ""},
follow_redirects=True,
)

# Submit with a valid round
test_round = seed_dynamic_data["rounds"][0]
response = flask_test_client.post(
f"/rounds/sections/select-application?fund_id={test_round.fund_id}",
data={"round_id": str(test_round.round_id)},
follow_redirects=False,
)
assert response.status_code == 302

# Confirm redirect to application_bp.build_application
expected_location = url_for("application_bp.build_application", round_id=test_round.round_id)
assert response.location == expected_location

0 comments on commit 03779f7

Please sign in to comment.