Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions pyxform/question.py
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,11 @@ def build_xml(self, survey: "Survey"):
raise PyXFormError("""Invalid value for `self.bind["type"]`.""")

result = self._build_xml(survey=survey)
choices = None
if survey.choices:
choices = survey.choices.get(self.itemset, None)
if not choices:
choices = self.choices

# itemset are only supposed to be strings,
# check to prevent the rare dicts that show up
Expand All @@ -390,7 +395,7 @@ def build_xml(self, survey: "Survey"):

if file_extension in EXTERNAL_INSTANCE_EXTENSIONS:
pass
elif self.choices and self.choices.requires_itext:
elif choices and choices.requires_itext:
itemset = self.itemset
itemset_label_ref = "jr:itext(itextId)"
else:
Expand Down Expand Up @@ -448,13 +453,12 @@ def build_xml(self, survey: "Survey"):
nodeset=nodeset,
)
)
elif self.choices:
elif choices:
# Options processing specific to XLSForms using the "search()" function.
# The _choice_itext_ref is prepared by Survey._redirect_is_search_itext.
itemset = self.choices
if itemset.used_by_search:
for option in itemset.options:
if itemset.requires_itext:
if choices.used_by_search:
for option in choices.options:
if choices.requires_itext:
label_node = node("label", ref=option._choice_itext_ref)
elif self.label:
label, output_inserted = survey.insert_output_values(
Expand Down
14 changes: 9 additions & 5 deletions pyxform/survey.py
Original file line number Diff line number Diff line change
Expand Up @@ -783,12 +783,16 @@ def _redirect_is_search_itext(self, element: MultipleChoiceQuestion) -> bool:
)
raise PyXFormError(msg)

choices = None
if self.choices:
choices = self.choices.get(element.itemset, None)
if not choices:
choices = element.choices
element.itemset = ""
itemset = element.choices
if not itemset.used_by_search:
itemset.used_by_search = True
for i, opt in enumerate(itemset.options):
opt._choice_itext_ref = f"jr:itext('{itemset.name}-{i}')"
if not choices.used_by_search:
choices.used_by_search = True
for i, opt in enumerate(choices.options):
opt._choice_itext_ref = f"jr:itext('{choices.name}-{i}')"
return is_search

def _setup_translations(self):
Expand Down
67 changes: 67 additions & 0 deletions tests/test_randomize_itemsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
"""

from tests.pyxform_test_case import PyxformTestCase
from tests.xpath_helpers.choices import xpc
from tests.xpath_helpers.questions import xpq


class RandomizeItemsetsTest(PyxformTestCase):
Expand Down Expand Up @@ -203,3 +205,68 @@ def test_randomized_select_one_seed_without_randomize(self):
""",
error__contains=["Parameters must include randomize=true to use a seed."],
)

def test_randomized_select_one_translated(self):
"""Should find itemset label refers to itext func for randomized select1."""
md = """
| survey |
| | type | name | label::English (en) | parameters |
| | select_one c1 | q1 | Q1 en | randomize=True |
| choices |
| | list_name | name | label::English (en) |
| | c1 | a | A |
| | c1 | b | B |
"""
self.assertPyxformXform(
md=md,
xml__xpath_match=[
xpq.body_select1_itemset("q1"),
xpc.model_itext_choice_text_label_by_pos(
"English (en)",
"c1",
("A", "B"),
),
# Nodeset ref to choices instance wrapped in randomize().
"""
/h:html/h:body/x:select1[@ref='/test_name/q1']
/x:itemset[
@nodeset="randomize(instance('c1')/root/item)"
and child::x:label[@ref='jr:itext(itextId)']
and child::x:value[@ref='name']
]
""",
],
)

def test_randomized_select_one_translated_filtered(self):
"""Should find itemset label refers to itext func for randomized select1 + filter."""
md = """
| survey |
| | type | name | label::English (en) | parameters | choice_filter |
| | text | q0 | Question 0 | | |
| | select_one c1 | q1 | Question 1 | randomize=True | ${q0} = cf |
| choices | | | |
| | list_name | name | label::English (en) | cf |
| | c1 | a | A | 1 |
| | c1 | b | B | 2 |
"""
self.assertPyxformXform(
md=md,
xml__xpath_match=[
xpq.body_select1_itemset("q1"),
xpc.model_itext_choice_text_label_by_pos(
"English (en)",
"c1",
("A", "B"),
),
# Nodeset ref to choices instance + filter predicate wrapped in randomize().
"""
/h:html/h:body/x:select1[@ref='/test_name/q1']
/x:itemset[
@nodeset="randomize(instance('c1')/root/item[ /test_name/q0 = cf])"
and child::x:label[@ref='jr:itext(itextId)']
and child::x:value[@ref='name']
]
""",
],
)