Repository: XLSForm/pyxform
Pull request #493 (2020-12-09 06:11:56)

Make value ref dynamic for selects from repeats
#472 added support for selects from repeats but it did not make the `value` ref dynamic so only fields with the name `name` could be used.

#### Why is this the best possible solution? Were any other approaches considered?
This matches the way the `label` ref is set and is simple to understand.

#### What are the regression risks?
One risk I thought of is that if `itemset_value_ref` is in the wrong place, some select cases could end up without a `ref` set.

#### Does this change require updates to documentation? If so, please file an issue [here](https://github.com/XLSForm/xlsform.github.io) and include the link below.
No.

#### Before submitting this PR, please make sure you have:
- [x] included test cases for core behavior and edge cases in `tests_v1`
- [x] run `nosetests` and verified all tests pass
- [x] run `black pyxform` to format code
- [x] verified that any code or assets from external sources are properly credited in comments


Patch:
diff --git a/pyxform/question.py b/pyxform/question.py
index 7d9ab56..56e9918 100644
--- a/pyxform/question.py
+++ b/pyxform/question.py
@@ -200,6 +200,7 @@ class MultipleChoiceQuestion(Question):
         # check to prevent the rare dicts that show up
         if self["itemset"] and isinstance(self["itemset"], basestring):
             choice_filter = self.get("choice_filter")
+            itemset_value_ref = "name"
             itemset, file_extension = os.path.splitext(self["itemset"])
             has_media = False
             is_previous_question = bool(re.match(r"^\${.*}$", self.get("itemset")))
@@ -226,6 +227,7 @@ class MultipleChoiceQuestion(Question):
                     .split("/")
                 )
                 nodeset = "/".join(path[:-1])
+                itemset_value_ref = path[-1]
                 itemset_label_ref = path[-1]
                 if choice_filter:
                     choice_filter = choice_filter.replace(
@@ -261,7 +263,7 @@ class MultipleChoiceQuestion(Question):
                     nodeset += ")"
 
             itemset_children = [
-                node("value", ref="name"),
+                node("value", ref=itemset_value_ref),
                 node("label", ref=itemset_label_ref),
             ]
             result.appendChild(node("itemset", *itemset_children, nodeset=nodeset))


Test patch:
diff --git a/pyxform/tests_v1/test_repeat.py b/pyxform/tests_v1/test_repeat.py
index dc100d1..81adb45 100644
--- a/pyxform/tests_v1/test_repeat.py
+++ b/pyxform/tests_v1/test_repeat.py
@@ -339,19 +339,36 @@ class TestRepeat(PyxformTestCase):
         |         | begin repeat       | rep        | Repeat         |
         |         | text               | name       | Enter name     |
         |         | end repeat         |            |                |
-        |         | select one fruits  | fruit      | Choose a fruit |
         |         | select one ${name} | choice     | Choose name    |
-        | choices |                    |            |                |
-        |         | list name          | name       | label          |
-        |         | fruits             | banana     | Banana         |
-        |         | fruits             | mango      | Mango          |
         """
         self.assertPyxformXform(
+            name="data",
             md=xlsform_md,
             xml__contains=[
-                "<itemset nodeset=\"/pyxform_autotestname/rep[./name != '']\">"
+                "<itemset nodeset=\"/data/rep[./name != '']\">",
+                '<value ref="name"/>',
+                '<label ref="name"/>',
+            ],
+        )
+
+    def test_choice_from_previous_repeat_answers_not_name(self):
+        """Select one choices from previous repeat answers."""
+        xlsform_md = """
+        | survey  |                      |            |                |
+        |         | type                 | name       | label          |
+        |         | begin repeat         | rep        | Repeat         |
+        |         | text                 | answer     | Enter name     |
+        |         | end repeat           |            |                |
+        |         | select one ${answer} | choice     | Choose name    |
+        """
+        self.assertPyxformXform(
+            name="data",
+            md=xlsform_md,
+            xml__contains=[
+                "<itemset nodeset=\"/data/rep[./answer != '']\">",
+                '<value ref="answer"/>',
+                '<label ref="answer"/>',
             ],
-            run_odk_validate=False,
         )
 
     def test_choice_from_previous_repeat_answers_with_choice_filter(self):