Skip to content

Commit

Permalink
Fs 4631 generate form unit tests (#58)
Browse files Browse the repository at this point in the history
* fs-4631 WIP unit tests

* fs-4631 wip testing with conditions - will fail atm

* fs-4631 add build start page test

* fs-4631 WIP unit tests

* fs-4631 wip testing with conditions - will fail atm

* fs-4631 add build start page test

* fs-4631 tests passing

* fs-4631 WIP unit tests

* fs-4631 wip testing with conditions - will fail atm

* fs-4631 add build start page test

* fs-4631 tests passing

* fs-4631 removing unused test config

* fs-4631 update all_questions to use new conditions structure

* fs-4631 create list tests

* bau updating docker compose host names to remove conflict with dev container (#59)

* Bugfix/FS-4695 update page title (#61)

* update page title

* Update page headings

* update pageheading

* Add correct form runner external host variable for form preview (#63)

* fs-4631 WIP unit tests

* fs-4631 wip testing with conditions - will fail atm

* fs-4631 add build start page test

* fs-4631 tests passing

* fs-4631 removing unused test config

* fs-4631 update all_questions to use new conditions structure

* fs-4631 create list tests

* review comments - defining test objects in one place

---------

Co-authored-by: Narender Raju B <[email protected]>
  • Loading branch information
srh-sloan and NarenderRajuB authored Oct 2, 2024
1 parent 3f302af commit 17f6c19
Show file tree
Hide file tree
Showing 14 changed files with 2,363 additions and 464 deletions.
23 changes: 14 additions & 9 deletions app/all_questions/metadata_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -368,17 +368,22 @@ def build_components_from_page(
condition_name = next_config["condition"]
condition_config = next(fc for fc in form_conditions if fc["name"] == condition_name)
destination = index_of_printed_headers[next_config["path"]]["heading_number"]
condition_value = next(
text_with_coordinators = ""
for condition in [
cc for cc in condition_config["value"]["conditions"] if cc["field"]["name"] == c["name"]
)["value"]["value"]
condition_text = determine_display_value_for_condition(
condition_value,
list_name=c["list"] if "list" in c else None,
form_lists=form_lists,
lang=lang,
)
]:
condition_value = condition["value"]["value"]
condition_text = determine_display_value_for_condition(
condition_value,
list_name=c["list"] if "list" in c else None,
form_lists=form_lists,
lang=lang,
)
if condition.get("coordinator"):
text_with_coordinators += f" {condition.get('coordinator')} "
text_with_coordinators += f"'{condition_text}'"
text.append(
f"If '{condition_text}', go to <strong>{destination}</strong>"
f"If {text_with_coordinators}, go to <strong>{destination}</strong>"
if lang == "en"
else (f"Os '{condition_text}', ewch i <strong>{destination}</strong>")
)
Expand Down
34 changes: 24 additions & 10 deletions app/db/queries/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,6 @@ def get_form_for_component(component: Component) -> Form:
return form


def get_template_page_by_display_path(display_path: str) -> Page:
page = (
db.session.query(Page)
.where(Page.display_path == display_path)
.where(Page.is_template == True) # noqa:E712
.one_or_none()
)
return page


def get_form_by_id(form_id: str) -> Form:
form = db.session.query(Form).where(Form.form_id == form_id).one_or_none()
return form
Expand All @@ -62,6 +52,11 @@ def get_list_by_id(list_id: str) -> Lizt:
return lizt


def get_list_by_name(list_name: str) -> Lizt:
lizt = db.session.query(Lizt).filter_by(name=list_name).first()
return lizt


def _initiate_cloned_component(to_clone: Component, new_page_id=None, new_theme_id=None):
clone = Component(**to_clone.as_dict())

Expand Down Expand Up @@ -746,3 +741,22 @@ def move_form_up(section_id, form_index_to_move_up: int):

section.forms = swap_elements_in_list(section.forms, list_index_to_move_up, list_index_to_move_up - 1)
db.session.commit()


def insert_list(list_config: dict, do_commit: bool = True) -> Lizt:
new_list = Lizt(
is_template=True,
name=list_config.get("name"),
title=list_config.get("title"),
type=list_config.get("type"),
items=list_config.get("items"),
)
try:
db.session.add(new_list)
except Exception as e:
print(e)
raise e
if do_commit:
db.session.commit()
db.session.flush() # flush to get the list id
return new_list
90 changes: 34 additions & 56 deletions app/export_config/generate_form.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import copy
from dataclasses import asdict

from app.db.models import Component
from app.db.models import Form
from app.db.models import Page
from app.db.models.application_config import READ_ONLY_COMPONENTS
from app.db.models.application_config import ComponentType
from app.db.queries.application import get_list_by_id
from app.db.queries.application import get_template_page_by_display_path
from app.shared.data_classes import ConditionValue

BASIC_FORM_STRUCTURE = {
"startPage": None,
Expand Down Expand Up @@ -43,34 +44,26 @@ def build_conditions(component: Component) -> list:
"""
results = []
for condition in component.conditions:
condition_entry = {
"field": {
"name": component.runner_component_name,
"type": component.type.value,
"display": component.title,
},
"operator": condition["operator"],
"value": condition["value"],
}

# Add 'coordinator' only if it exists
if condition.get("coordinator"):
condition_entry["coordinator"] = condition.get("coordinator")

if condition["name"] in [c["name"] for c in results]:
# If this condition already exists, add it to the existing condition
existing_condition = next(c for c in results if c["name"] == condition["name"])
existing_condition["value"]["conditions"].append(condition_entry)
continue

result = {
"displayName": condition["display_name"],
"name": condition["name"],
"value": {
"name": condition["display_name"],
"conditions": [condition_entry],
},
"value": asdict(
ConditionValue(
name=condition["value"]["name"],
conditions=[],
)
),
}
for sc in condition["value"]["conditions"]:
sub_condition = {
"field": sc["field"],
"operator": sc["operator"],
"value": sc["value"],
}
# only add coordinator if it exists
if "coordinator" in sc and sc.get("coordinator") is not None:
sub_condition["coordinator"] = sc.get("coordinator", None)
result["value"]["conditions"].append(sub_condition)

results.append(result)

Expand Down Expand Up @@ -118,19 +111,12 @@ def build_component(component: Component) -> dict:
return built_component


def build_page(page: Page = None, page_display_path: str = None) -> dict:
def build_page(page: Page = None) -> dict:
"""
Builds the form runner JSON structure for the supplied page. If that page is None, retrieves a template
page with the display_path matching page_display_path.
This accounts for conditional logic where the destination target will be the display path of a template
page, but that page does not actually live in the main hierarchy as branching logic uses a fixed set of
conditions at this stage.
Builds the form runner JSON structure for the supplied page.
Then builds all the components on this page and adds them to the page json structure
"""
if not page:
page = get_template_page_by_display_path(page_display_path)
built_page = copy.deepcopy(BASIC_PAGE_STRUCTURE)
built_page.update(
{
Expand Down Expand Up @@ -173,26 +159,12 @@ def build_navigation(partial_form_json: dict, input_pages: list[Page]) -> dict:
for component in page.components:
if not component.conditions:
continue
form_json_conditions = build_conditions(component)
has_conditions = True
form_json_conditions = build_conditions(component)
partial_form_json["conditions"].extend(form_json_conditions)

for condition in component.conditions:
if condition["destination_page_path"] == "CONTINUE":
destination_path = f"/{next_path}"
else:
destination_path = f"/{condition['destination_page_path'].lstrip('/')}"
# TODO No longer needed since db schema change?
# If this points to a pre-built page flow, add that in now (it won't be in the input)
# if (
# destination_path not in [page["path"] for page in partial_form_json["pages"]]
# and not destination_path == "/summary"
# ):
# sub_page = build_page(page_display_path=destination_path[1:])
# if not sub_page.get("next", None):
# sub_page["next"] = [{"path": f"/{next_path}"}]

# partial_form_json["pages"].append(sub_page)
destination_path = f"/{condition['destination_page_path'].lstrip('/')}"

this_page_in_results["next"].append(
{
Expand Down Expand Up @@ -245,20 +217,26 @@ def build_start_page(content: str, form: Form) -> dict:
"title": form.name_in_apply_json["en"],
"path": f"/intro-{human_to_kebab_case(form.name_in_apply_json['en'])}",
"controller": "./pages/start.js",
"next": [{"path": f"/{form.pages[0].display_path}"}],
}
)
ask_about = "<p class='govuk-body'>We will ask you about:</p> <ul>"
for page in form.pages:
ask_about += f"<li>{page.name_in_apply_json['en']}</li>"
ask_about += "</ul>"
ask_about = None
if len(form.pages) > 0:
ask_about = '<p class="govuk-body">We will ask you about:</p> <ul>'
for page in form.pages:
ask_about += f"<li>{page.name_in_apply_json['en']}</li>"
ask_about += "</ul>"
start_page.update(
{
"next": [{"path": f"/{form.pages[0].display_path}"}],
}
)

start_page["components"].append(
{
"name": "start-page-content",
"options": {},
"type": "Html",
"content": f"<p class='govuk-body'>{content}</p>{ask_about}",
"content": f'<p class="govuk-body">{content or ""}</p>{ask_about or ""}',
"schema": {},
}
)
Expand Down
Loading

0 comments on commit 17f6c19

Please sign in to comment.