Skip to content

Commit

Permalink
Support piping repeating supplementary data outside a repeat (#1318)
Browse files Browse the repository at this point in the history
  • Loading branch information
petechd authored Feb 28, 2024
1 parent 352e952 commit fd8ba61
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 26 deletions.
24 changes: 21 additions & 3 deletions app/data_models/supplementary_data_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,28 @@ def get_data(
it would be get_data(identifier="some_list", selectors=["identifier"], list_item_id=list_item_id-1)
"""
if self.is_data_repeating(identifier) and not list_item_id:
raise InvalidSupplementaryDataSelector(
f"Cannot reference items from `{identifier}` outside a repeat"
)
values = []
for _list_item_id in self.list_lookup.get(identifier, {}).values():
value = self._resolve_value(
identifier=identifier,
selectors=selectors,
list_item_id=_list_item_id,
)
if value is not None:
values.append(value)
return values

return self._resolve_value(
identifier=identifier, selectors=selectors, list_item_id=list_item_id
)

def _resolve_value(
self,
*,
identifier: str,
selectors: Iterable[str] | None,
list_item_id: str | None,
) -> dict | str | list | None:
value = self._data_map.get((identifier, list_item_id))
# for nested data, index with each selector, or return None if there is no data to index
for selector in selectors or []:
Expand Down
45 changes: 43 additions & 2 deletions schemas/test/en/test_supplementary_data.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,52 @@
"contents": [
{
"title": "You have successfully loaded Supplementary data",
"description": "Press continue to proceed to the introduction",
"description": {
"text": "List of products: {products}",
"placeholders": [
{
"placeholder": "products",
"transforms": [
{
"transform": "format_list",
"arguments": {
"list_to_format": {
"source": "supplementary_data",
"identifier": "products",
"selectors": ["name"]
}
}
}
]
}
]
},
"guidance": {
"contents": [
{
"description": "The purpose of this block, is to test that supplementary data loads successfully, separate to using the supplementary data"
"description": {
"text": "The purpose of this block, is to test that supplementary data loads successfully, separate to using the supplementary data. The surnames of the employees are: {surnames}.",
"placeholders": [
{
"placeholder": "surnames",
"transforms": [
{
"transform": "concatenate_list",
"arguments": {
"list_to_concatenate": [
{
"source": "supplementary_data",
"identifier": "employees",
"selectors": ["personal_details", "surname"]
}
],
"delimiter": ", "
}
}
]
}
]
}
}
]
}
Expand Down
21 changes: 21 additions & 0 deletions tests/app/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,17 @@ def supplementary_data_list_mappings():
}


@pytest.fixture
def supplementary_data_list_mappings_extra_item():
return {
"products": [
SupplementaryDataListMapping(identifier=89929001, list_item_id="item-1"),
SupplementaryDataListMapping(identifier="201630601", list_item_id="item-2"),
SupplementaryDataListMapping(identifier="103219277", list_item_id="item-3"),
],
}


@pytest.fixture
def supplementary_data_employee_list_mappings():
return {
Expand Down Expand Up @@ -417,6 +428,16 @@ def supplementary_data_store_with_data(
)


@pytest.fixture
def supplementary_data_store_with_data_extra_item(
supplementary_data, supplementary_data_list_mappings_extra_item
):
return SupplementaryDataStore(
supplementary_data=supplementary_data,
list_mappings=supplementary_data_list_mappings_extra_item,
)


@pytest.fixture
def supplementary_data_store_with_employees(
supplementary_data_with_employees,
Expand Down
54 changes: 34 additions & 20 deletions tests/app/questionnaire/test_value_source_resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -1131,6 +1131,21 @@ def test_supplementary_data_value_source_non_list_items(
{"identifier": "products", "selectors": ["value_sales", "answer_code"]},
"201630601",
),
(
None,
{"identifier": "products", "selectors": ["name"]},
["Articles and equipment for sports or outdoor games", "Other Minerals"],
),
(
None,
{"identifier": "products", "selectors": ["value_sales", "answer_code"]},
["89929001", "201630601"],
),
(
None,
{"identifier": "products", "selectors": ["non_existing_optional_key"]},
[],
),
],
)
def test_supplementary_data_value_source_list_items(
Expand Down Expand Up @@ -1165,53 +1180,52 @@ def test_supplementary_data_value_source_list_items(
)


def test_supplementary_data_invalid_selector_raises_exception(
supplementary_data_store_with_data,
def test_supplementary_data_value_source_list_items_value_missing_excluded(
supplementary_data_store_with_data_extra_item,
):
list_store = ListStore([{"name": "products", "items": get_list_items(3)}])
location = Location(
section_id="section",
block_id="block-id",
list_name="products",
list_item_id=None,
)
value_source_resolver = get_value_source_resolver(
data_stores=DataStores(
supplementary_data_store=supplementary_data_store_with_data
supplementary_data_store=supplementary_data_store_with_data_extra_item,
list_store=list_store,
),
location=location,
list_item_id=None,
)
with pytest.raises(InvalidSupplementaryDataSelector) as e:
value_source_resolver.resolve(
{
"source": "supplementary_data",
"identifier": "guidance",
"selectors": ["invalid"],
}
)

assert e.value.args[0] == "Cannot use the selector `invalid` on non-nested data"
assert value_source_resolver.resolve(
{
"source": "supplementary_data",
**{"identifier": "products", "selectors": ["name"]},
}
) == ["Articles and equipment for sports or outdoor games", "Other Minerals"]


def test_supplementary_data_list_item_outside_repeating_section_raises_exception(
def test_supplementary_data_invalid_selector_raises_exception(
supplementary_data_store_with_data,
):
list_store = ListStore([{"name": "products", "items": get_list_items(2)}])
location = Location(
section_id="section",
block_id="block-id",
)
value_source_resolver = get_value_source_resolver(
data_stores=DataStores(
supplementary_data_store=supplementary_data_store_with_data,
list_store=list_store,
supplementary_data_store=supplementary_data_store_with_data
),
location=location,
)
with pytest.raises(InvalidSupplementaryDataSelector) as e:
value_source_resolver.resolve(
{
"source": "supplementary_data",
"identifier": "products",
"selectors": ["name"],
"identifier": "guidance",
"selectors": ["invalid"],
}
)

assert e.value.args[0] == "Cannot reference items from `products` outside a repeat"
assert e.value.args[0] == "Cannot use the selector `invalid` on non-nested data"
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,13 @@ describe("Using supplementary data", () => {
responseId,
});
});
it("Given I launch a survey using supplementary data, When I am outside a repeating section, Then I am able to see the list of items relating to a given supplementary data list item on the page", async () => {
await expect(await $("#main-content #guidance-1").getText()).toContain("The surnames of the employees are: Potter, Kent.");
await expect(await $$("#main-content li")[0].getText()).toBe("Articles and equipment for sports or outdoor games");
await expect(await $$("#main-content li")[1].getText()).toBe("Kitchen Equipment");
});

it("Given I launch a survey using supplementary data, When I begin the introduction block, Then I see the supplementary data piped in", async () => {
it("Given I progress through the interstitial block, When I begin the introduction block, Then I see the supplementary data piped in", async () => {
await click(LoadedSuccessfullyBlockPage.submit());
await $(IntroductionBlockPage.acceptCookies()).click();
await expect(await $(IntroductionBlockPage.businessDetailsContent()).getText()).toContain("You are completing this survey for Tesco");
Expand Down

0 comments on commit fd8ba61

Please sign in to comment.