Пример #1
0
    def test_empty_module_errors(self, *args):
        factory = AppFactory(build_version='2.24.0')
        app = factory.app
        m1 = factory.new_basic_module('register', 'case', with_form=False)
        factory.new_advanced_module('update', 'case', with_form=False)

        m2 = factory.new_basic_module('update', 'case', with_form=False)
        m2.case_list = CaseList(show=True, label={'en': "case_list"})

        factory.new_shadow_module('update', m1, with_form=False)
        errors = app.validate_app()

        standard_module_error = {
            'type': 'no forms or case list',
            'module': {
                'id': 0,
                'name': {
                    'en': 'register module'
                }
            },
        }
        advanced_module_error = {
            'type': 'no forms or case list',
            'module': {
                'id': 1,
                'name': {
                    'en': 'update module'
                }
            },
        }
        self._clean_unique_id(errors)
        self.assertEqual(len(errors), 2)
        self.assertIn(standard_module_error, errors)
        self.assertIn(advanced_module_error, errors)
Пример #2
0
    def _build_workflow_app(self, mode):
        factory = AppFactory(build_version='2.9.0')
        m0, m0f0 = factory.new_basic_module('m0', '')
        factory.new_form(m0)

        m1, m1f0 = factory.new_basic_module('m1', 'patient')
        m1f1 = factory.new_form(m1)
        factory.form_opens_case(m1f0)
        factory.form_requires_case(m1f1)

        m2, m2f0 = factory.new_basic_module('m2', 'patient')
        m2f1 = factory.new_form(m2)
        factory.form_requires_case(m2f0)
        factory.form_requires_case(m2f1)

        m3, m3f0 = factory.new_basic_module('m3', 'child')
        m3f1 = factory.new_form(m3)
        factory.form_requires_case(m3f0, parent_case_type='patient')
        factory.form_requires_case(m3f1)

        m4, m4f0 = factory.new_advanced_module('m4', 'patient')
        factory.form_requires_case(m4f0, case_type='patient')
        factory.form_requires_case(m4f0, case_type='patient')

        m4f1 = factory.new_form(m4)
        factory.form_requires_case(m4f1, case_type='patient')
        factory.form_requires_case(m4f1, case_type='patient')
        factory.form_requires_case(m4f1, case_type='patient')

        m4f2 = factory.new_form(m4)
        factory.form_requires_case(m4f2, case_type='patient')
        factory.form_requires_case(m4f2, case_type='patient')
        factory.advanced_form_autoloads(m4f2, AUTO_SELECT_RAW, 'case_id')

        m5, m5f0 = factory.new_basic_module('m5', 'patient', parent_module=m1)
        factory.form_requires_case(m5f0)

        m6 = factory.new_shadow_module('shadow_module', m1, with_form=False)
        factory.new_shadow_module('shadow_child',
                                  m5,
                                  with_form=False,
                                  parent_module=m6)

        for module in factory.app.get_modules():
            for form in module.get_forms():
                form.post_form_workflow = mode

        return factory.app
Пример #3
0
    def test_empty_module_errors(self):
        factory = AppFactory(build_version='2.24')
        app = factory.app
        m1 = factory.new_basic_module('register', 'case', with_form=False)
        factory.new_advanced_module('update', 'case', with_form=False)

        m2 = factory.new_basic_module('update', 'case', with_form=False)
        m2.case_list = CaseList(show=True, label={'en': "case_list"})

        factory.new_shadow_module('update', m1, with_form=False)
        errors = app.validate_app()

        standard_module_error = {
            'type': 'no forms or case list',
            'module': {'id': 0, 'name': {'en': u'register module'}},
        }
        advanced_module_error = {
            'type': 'no forms or case list',
            'module': {'id': 1, 'name': {'en': u'update module'}},
        }
        self.assertEqual(len(errors), 2)
        self.assertIn(standard_module_error, errors)
        self.assertIn(advanced_module_error, errors)
Пример #4
0
    def test_return_to_shadow_module(self, *args):
        factory = AppFactory(build_version='2.9.0')
        m0, m0f0 = factory.new_basic_module('enroll child', 'child')
        factory.form_requires_case(m0f0)
        m0f0.post_form_workflow = WORKFLOW_MODULE

        m1 = factory.new_shadow_module('shadow_module', m0, with_form=False)

        expected = """
        <partial>
            <stack>
              <create>
                <command value="'m1'"/>
              </create>
            </stack>
        </partial>
        """

        self.assertXmlPartialEqual(expected, factory.app.create_suite(),
                                   "./entry[2]/stack")
Пример #5
0
class HandleShadowChildModulesTest(TestCase):
    """Test how shadow child modules are created and deleted
    """
    def setUp(self):
        super().setUp()
        self.domain = "test-domain"

        self.factory = AppFactory(domain=self.domain)

        # m0
        self.basic_module, self.form0 = self.factory.new_basic_module(
            "basic_module", "parrot")
        form1 = self.factory.new_form(self.basic_module)

        # m1
        self.child_module, form2 = self.factory.new_basic_module(
            "child_module", "parrot", parent_module=self.basic_module)
        self.child_module.put_in_root = True
        self.form3 = self.factory.new_form(self.child_module)

        # m2
        self.shadow_module = self.factory.new_shadow_module("shadow_module",
                                                            self.basic_module,
                                                            with_form=False)
        self.shadow_module.excluded_form_ids = [
            self.form0.unique_id, self.form3.unique_id
        ]
        self.factory.app.save()

        self.app = self.factory.app

    def tearDown(self):
        delete_all_apps()
        super().tearDown()

    def test_creates_new_modules(self):

        handle_shadow_child_modules(
            self.app,
            self.app.get_module_by_unique_id(self.shadow_module.unique_id))

        app = Application.get(self.app.get_id)

        # A new shadow module should be created whose module source is the child
        self.assertEqual(len(app.modules), 4)
        self.assertEqual(app.modules[3].module_type, "shadow")
        self.assertEqual(app.modules[3].source_module_id,
                         self.child_module.unique_id)

        # excluded form ids should move from the parent to the child module,
        # retaining the pertinent parent ids
        self.assertItemsEqual(app.modules[3].excluded_form_ids,
                              [self.form3.unique_id])
        self.assertItemsEqual(
            app.get_module_by_unique_id(
                self.shadow_module.unique_id).excluded_form_ids,
            [self.form0.unique_id],
        )

        # Calling the command again should not make new modules
        shadow_child_module_id = app.modules[3].unique_id
        handle_shadow_child_modules(
            app, app.get_module_by_unique_id(self.shadow_module.unique_id))
        app = Application.get(app.get_id)
        self.assertEqual(len(app.modules), 4)
        self.assertEqual(app.modules[3].unique_id, shadow_child_module_id)

    def test_deletes_module_child_removed(self):
        # Create new module
        handle_shadow_child_modules(
            self.app,
            self.app.get_module_by_unique_id(self.shadow_module.unique_id))

        # Change child module's parent
        app = Application.get(self.app.get_id)
        app.modules[1].root_module_id = None
        app.save()

        # The new shadow module should be deleted, since it is no longer needed
        handle_shadow_child_modules(
            app, app.get_module_by_unique_id(self.shadow_module.unique_id))
        self.assertEqual(len(app.modules), 3)

    def test_deletes_module_source_changed(self):
        # Create new module
        handle_shadow_child_modules(
            self.app,
            self.app.get_module_by_unique_id(self.shadow_module.unique_id))

        # Change parent shadow module's source
        app = Application.get(self.app.get_id)
        new_module = Module.new_module("name", "en")
        app.add_module(new_module)
        app.get_module_by_unique_id(self.shadow_module.unique_id
                                    ).source_module_id = new_module.unique_id
        app.save()
        self.assertEqual(len(app.modules), 5)

        # Child shadow module should be removed
        handle_shadow_child_modules(
            app, app.get_module_by_unique_id(self.shadow_module.unique_id))
        self.assertEqual(len(app.modules), 4)

    def test_shadow_source_is_child(self):
        # If the source is a child, the parent of the shadow should be the same as the source
        shadow_child = self.factory.new_shadow_module("shadow_child_module",
                                                      self.child_module,
                                                      with_form=False)
        self.factory.app.save()

        handle_shadow_child_modules(
            self.app, self.app.get_module_by_unique_id(shadow_child.unique_id))

        app = Application.get(self.app.get_id)
        shadow_child = app.get_module_by_unique_id(shadow_child.unique_id)
        self.assertEqual(shadow_child.root_module_id,
                         self.child_module.root_module_id)

        # change the source
        shadow_child.source_module_id = self.basic_module.unique_id
        app.save()

        handle_shadow_child_modules(
            app, app.get_module_by_unique_id(shadow_child.unique_id))

        app = Application.get(self.app.get_id)
        shadow_child = app.get_module_by_unique_id(shadow_child.unique_id)
        self.assertIsNone(shadow_child.root_module_id)

    def test_all_shadow_module_properties_set(self):
        ignored_properties = [
            "module_type",
            "source_module_id",
            "doc_type",
            "_root_module_id",
            "forms",
            "excluded_form_ids",
            "shadow_module_version",
        ]
        required_properties = {
            prop
            for prop in vars(ShadowModule) if isinstance(
                vars(ShadowModule)[prop], jsonobject.base_properties.
                JsonProperty) and prop not in ignored_properties
        }
        copied_properties = {
            prop
            for prop, _ in SHADOW_MODULE_PROPERTIES_TO_COPY
        }

        self.assertItemsEqual(
            required_properties - copied_properties,
            [],
            (f"Please handle the new property you just added '{required_properties - copied_properties}' "
             "to ShadowModule in app_manager.views.utils.handle_child_shadow_modules, or add it "
             "to the ignored_propertieslist in this test."),
        )

    def test_all_base_module_properties_set(self):
        ignored_properties = [
            "doc_type", "root_module_id", "name", "case_type", "unique_id"
        ]
        required_properties = {
            prop
            for prop in vars(ModuleBase) if isinstance(
                vars(ModuleBase)[prop], jsonobject.base_properties.JsonProperty
            ) and prop not in ignored_properties
        }
        required_properties |= {
            prop
            for prop in vars(NavMenuItemMediaMixin) if isinstance(
                vars(NavMenuItemMediaMixin)[prop], jsonobject.base_properties.
                JsonProperty) and prop not in ignored_properties
        }

        copied_properties = {
            prop
            for prop, _ in MODULE_BASE_PROPERTIES_TO_COPY
        }

        self.assertItemsEqual(
            required_properties - copied_properties,
            [],
            (f"Please handle the new property you just added '{required_properties - copied_properties}' "
             "to ShadowModule in app_manager.views.utils.handle_child_shadow_modules, or add it "
             "to the ignored_propertieslist in this test."),
        )
Пример #6
0
class ShadowModuleFormSelectionSuiteTest(SimpleTestCase, TestXmlMixin):
    def setUp(self):
        self.factory = AppFactory()
        self.basic_module, self.form0 = self.factory.new_basic_module(
            'basic_module', 'parrot')
        self.form0.xmlns = 'http://openrosa.org/formdesigner/firstform'
        self.form1 = self.factory.new_form(self.basic_module)
        self.form1.xmlns = 'http://openrosa.org/formdesigner/secondform'
        self.shadow_module = self.factory.new_shadow_module('shadow_module',
                                                            self.basic_module,
                                                            with_form=False)
        self.child_module, self.form2 = self.factory.new_basic_module(
            'child_module', 'parrot', parent_module=self.basic_module)

    def test_all_forms_selected(self):
        expected = """
        <partial>
          <menu id="m1">
            <text>
              <locale id="modules.m1"/>
            </text>
            <command id="m1-f0"/>
            <command id="m1-f1"/>
          </menu>
        </partial>
        """
        self.assertXmlPartialEqual(expected, self.factory.app.create_suite(),
                                   "./menu[@id='m1']")

    def test_some_forms_selected(self):
        self.shadow_module.excluded_form_ids = [self.form0.unique_id]
        expected = """
        <partial>
          <menu id="m1">
            <text>
              <locale id="modules.m1"/>
            </text>
            <command id="m1-f1"/>
          </menu>
        </partial>
        """
        self.assertXmlPartialEqual(expected, self.factory.app.create_suite(),
                                   "./menu[@id='m1']")

    def test_no_forms_selected(self):
        self.shadow_module.excluded_form_ids = [
            self.form0.unique_id, self.form1.unique_id
        ]
        self.assertXmlDoesNotHaveXpath(self.factory.app.create_suite(),
                                       "./menu[@id='m1']")

    def test_no_child_forms_selected(self):
        self.shadow_module.excluded_form_ids = [self.form2.unique_id]
        self.assertXmlPartialEqual(
            '''
                <partial>
                  <menu id="m0">
                    <text>
                      <locale id="modules.m0"/>
                    </text>
                    <command id="m0-f0"/>
                    <command id="m0-f1"/>
                  </menu>
                  <menu id="m1">
                    <text>
                      <locale id="modules.m1"/>
                    </text>
                    <command id="m1-f0"/>
                    <command id="m1-f1"/>
                  </menu>
                  <menu id="m2" root="m0">
                    <text>
                      <locale id="modules.m2"/>
                    </text>
                    <command id="m2-f0"/>
                  </menu>
                </partial>
            ''', self.factory.app.create_suite(), "./menu")

        self.basic_module.put_in_root = True
        self.shadow_module.put_in_root = False
        self.child_module.put_in_root = False
        self.assertXmlPartialEqual(
            '''
                <partial>
                  <menu id="root">
                    <text>
                      <locale id="modules.m0"/>
                    </text>
                    <command id="m0-f0"/>
                    <command id="m0-f1"/>
                  </menu>
                  <menu id="m1">
                    <text>
                      <locale id="modules.m1"/>
                    </text>
                    <command id="m1-f0"/>
                    <command id="m1-f1"/>
                  </menu>
                  <menu id="m2" root="root">
                    <text>
                      <locale id="modules.m2"/>
                    </text>
                    <command id="m2-f0"/>
                  </menu>
                </partial>
            ''', self.factory.app.create_suite(), "./menu")

        self.basic_module.put_in_root = False
        self.shadow_module.put_in_root = True
        self.child_module.put_in_root = False
        self.assertXmlPartialEqual(
            '''
                <partial>
                  <menu id="m0">
                    <text>
                      <locale id="modules.m0"/>
                    </text>
                    <command id="m0-f0"/>
                    <command id="m0-f1"/>
                  </menu>
                  <menu id="root">
                    <text>
                      <locale id="modules.m1"/>
                    </text>
                    <command id="m1-f0"/>
                    <command id="m1-f1"/>
                  </menu>
                  <menu id="m2" root="m0">
                    <text>
                      <locale id="modules.m2"/>
                    </text>
                    <command id="m2-f0"/>
                  </menu>
                </partial>
            ''', self.factory.app.create_suite(), "./menu")

        self.basic_module.put_in_root = False
        self.shadow_module.put_in_root = False
        self.child_module.put_in_root = True
        self.assertXmlPartialEqual(
            '''
                <partial>
                  <menu id="m0">
                    <text>
                      <locale id="modules.m0"/>
                    </text>
                    <command id="m0-f0"/>
                    <command id="m0-f1"/>
                  </menu>
                  <menu id="m1">
                    <text>
                      <locale id="modules.m1"/>
                    </text>
                    <command id="m1-f0"/>
                    <command id="m1-f1"/>
                  </menu>
                  <menu id="m0">
                    <text>
                      <locale id="modules.m0"/>
                    </text>
                    <command id="m2-f0"/>
                  </menu>
                </partial>
            ''', self.factory.app.create_suite(), "./menu")

        self.basic_module.put_in_root = False
        self.shadow_module.put_in_root = True
        self.child_module.put_in_root = True
        self.assertXmlPartialEqual(
            '''
                <partial>
                  <menu id="m0">
                    <text>
                      <locale id="modules.m0"/>
                    </text>
                    <command id="m0-f0"/>
                    <command id="m0-f1"/>
                  </menu>
                  <menu id="root">
                    <text>
                      <locale id="modules.m1"/>
                    </text>
                    <command id="m1-f0"/>
                    <command id="m1-f1"/>
                  </menu>
                  <menu id="m0">
                    <text>
                      <locale id="modules.m0"/>
                    </text>
                    <command id="m2-f0"/>
                  </menu>
                </partial>
            ''', self.factory.app.create_suite(), "./menu")

        self.basic_module.put_in_root = True
        self.shadow_module.put_in_root = False
        self.child_module.put_in_root = True
        self.assertXmlPartialEqual(
            '''
                <partial>
                  <menu id="root">
                    <text>
                      <locale id="modules.m0"/>
                    </text>
                    <command id="m0-f0"/>
                    <command id="m0-f1"/>
                  </menu>
                  <menu id="m1">
                    <text>
                      <locale id="modules.m1"/>
                    </text>
                    <command id="m1-f0"/>
                    <command id="m1-f1"/>
                  </menu>
                  <menu id="root">
                    <text>
                      <locale id="modules.m2"/>
                    </text>
                    <command id="m2-f0"/>
                  </menu>
                </partial>
            ''', self.factory.app.create_suite(), "./menu")

        self.basic_module.put_in_root = True
        self.shadow_module.put_in_root = True
        self.child_module.put_in_root = False
        self.assertXmlPartialEqual(
            '''
                <partial>
                  <menu id="root">
                    <text>
                      <locale id="modules.m0"/>
                    </text>
                    <command id="m0-f0"/>
                    <command id="m0-f1"/>
                  </menu>
                  <menu id="root">
                    <text>
                      <locale id="modules.m1"/>
                    </text>
                    <command id="m1-f0"/>
                    <command id="m1-f1"/>
                  </menu>
                  <menu id="m2" root="root">
                    <text>
                      <locale id="modules.m2"/>
                    </text>
                    <command id="m2-f0"/>
                  </menu>
                </partial>
            ''', self.factory.app.create_suite(), "./menu")

        self.basic_module.put_in_root = True
        self.shadow_module.put_in_root = True
        self.child_module.put_in_root = True
        self.assertXmlPartialEqual(
            '''
                <partial>
                  <menu id="root">
                    <text>
                      <locale id="modules.m0"/>
                    </text>
                    <command id="m0-f0"/>
                    <command id="m0-f1"/>
                  </menu>
                  <menu id="root">
                    <text>
                      <locale id="modules.m1"/>
                    </text>
                    <command id="m1-f0"/>
                    <command id="m1-f1"/>
                  </menu>
                  <menu id="root">
                    <text>
                      <locale id="modules.m2"/>
                    </text>
                    <command id="m2-f0"/>
                  </menu>
                </partial>
            ''', self.factory.app.create_suite(), "./menu")

    def test_form_added(self):
        self.shadow_module.excluded_form_ids = [self.form0.unique_id]
        self.factory.new_form(self.basic_module)
        expected = """
        <partial>
          <menu id="m1">
            <text>
              <locale id="modules.m1"/>
            </text>
            <command id="m1-f1"/>
            <command id="m1-f2"/>
          </menu>
        </partial>
        """
        self.assertXmlPartialEqual(expected, self.factory.app.create_suite(),
                                   "./menu[@id='m1']")

    def test_form_removed(self):
        self.basic_module.forms.remove(self.form1)
        expected = """
        <partial>
          <menu id="m1">
            <text>
              <locale id="modules.m1"/>
            </text>
            <command id="m1-f0"/>
          </menu>
        </partial>
        """
        self.assertXmlPartialEqual(expected, self.factory.app.create_suite(),
                                   "./menu[@id='m1']")

    def test_forms_reordered(self):
        expected_before = """
        <partial>
          <form>http://openrosa.org/formdesigner/firstform</form>
          <form>http://openrosa.org/formdesigner/secondform</form>

          <form>http://openrosa.org/formdesigner/firstform</form>
          <form>http://openrosa.org/formdesigner/secondform</form>
        </partial>
        """
        self.assertXmlPartialEqual(expected_before,
                                   self.factory.app.create_suite(),
                                   "./entry/form")
        # Swap forms around
        self.basic_module.forms = [self.form1, self.form0]
        expected_after = """
        <partial>
          <form>http://openrosa.org/formdesigner/secondform</form>
          <form>http://openrosa.org/formdesigner/firstform</form>

          <form>http://openrosa.org/formdesigner/secondform</form>
          <form>http://openrosa.org/formdesigner/firstform</form>
        </partial>
        """
        self.assertXmlPartialEqual(expected_after,
                                   self.factory.app.create_suite(),
                                   "./entry/form")

    def _create_parent_selection_app(self):
        '''
           setUp creates an app with three modules: basic, shadow, and child, all using parrot cases.
           This app adds an additional module that uses child cases (baby_parrot) and uses it as the
           source for the shadow module. Tests verify that when the shadow module uses parent child
           selection, it fetches both parrot and baby_parrot datums, using the correct details.
        '''
        self.factory.form_requires_case(self.form0)
        self.child_case_module, self.form3 = self.factory.new_basic_module(
            'child_case_module', 'baby_parrot')
        self.factory.form_requires_case(self.form3, parent_case_type='parrot')
        self.shadow_module.source_module_id = self.child_case_module.unique_id
        self.shadow_module.parent_select.active = True

    def test_parent_selection_first(self):
        self._create_parent_selection_app()
        self.shadow_module.parent_select.module_id = self.basic_module.unique_id

        # Test the entry for the shadow module's single form
        expected_entry = """
            <partial>
              <entry>
                <command id="m1-f0">
                  <text>
                    <locale id="forms.m3f0"/>
                  </text>
                </command>
                <instance id="casedb" src="jr://instance/casedb"/>
                <instance id="commcaresession" src="jr://instance/session"/>
                <session>
                  <datum id="parent_id" nodeset="instance('casedb')/casedb/case[@case_type='parrot'][@status='open']"
                         value="./@case_id" detail-select="m0_case_short"/>
                  <datum id="case_id" nodeset="instance('casedb')/casedb/case[@case_type='baby_parrot'][@status='open'][index/parent=instance('commcaresession')/session/data/parent_id]"
                         value="./@case_id" detail-select="m1_case_short" detail-confirm="m1_case_long"/>
                </session>
              </entry>
            </partial>
        """
        self.assertXmlPartialEqual(expected_entry,
                                   self.factory.app.create_suite(),
                                   './entry[3]')

    def test_parent_selection_different_module_than_source(self):
        self._create_parent_selection_app()
        self.additional_basic_module, dummy = self.factory.new_basic_module(
            'additional_basic_module', 'parrot')
        self.child_case_module.parent_select.active = True
        self.child_case_module.parent_select.module_id = self.basic_module.unique_id
        self.shadow_module.parent_select.module_id = self.additional_basic_module.unique_id

        # Test the entry for the shadow module's single form
        expected_entry = """
            <partial>
              <entry>
                <command id="m1-f0">
                  <text>
                    <locale id="forms.m3f0"/>
                  </text>
                </command>
                <instance id="casedb" src="jr://instance/casedb"/>
                <instance id="commcaresession" src="jr://instance/session"/>
                <session>
                  <datum id="parent_id" nodeset="instance('casedb')/casedb/case[@case_type='parrot'][@status='open']"
                         value="./@case_id" detail-select="m4_case_short"/>
                  <datum id="case_id" nodeset="instance('casedb')/casedb/case[@case_type='baby_parrot'][@status='open'][index/parent=instance('commcaresession')/session/data/parent_id]"
                         value="./@case_id" detail-select="m1_case_short" detail-confirm="m1_case_long"/>
                </session>
              </entry>
            </partial>
        """
        self.assertXmlPartialEqual(expected_entry,
                                   self.factory.app.create_suite(),
                                   './entry[3]')
Пример #7
0
class ShadowModuleFormSelectionSuiteTest(SimpleTestCase, TestXmlMixin):

    def setUp(self):
        self.factory = AppFactory()
        self.basic_module, self.form0 = self.factory.new_basic_module('basic_module', 'parrot')
        self.form0.xmlns = 'http://openrosa.org/formdesigner/firstform'
        self.form1 = self.factory.new_form(self.basic_module)
        self.form1.xmlns = 'http://openrosa.org/formdesigner/secondform'
        self.shadow_module = self.factory.new_shadow_module('shadow_module', self.basic_module, with_form=False)
        self.child_module, self.form2 = self.factory.new_basic_module('child_module', 'parrot',
                                                                      parent_module=self.basic_module)

    def test_all_forms_selected(self):
        expected = """
        <partial>
          <menu id="m1">
            <text>
              <locale id="modules.m1"/>
            </text>
            <command id="m1-f0"/>
            <command id="m1-f1"/>
          </menu>
        </partial>
        """
        self.assertXmlPartialEqual(
            expected,
            self.factory.app.create_suite(),
            "./menu[@id='m1']"
        )

    def test_some_forms_selected(self):
        self.shadow_module.excluded_form_ids = [self.form0.unique_id]
        expected = """
        <partial>
          <menu id="m1">
            <text>
              <locale id="modules.m1"/>
            </text>
            <command id="m1-f1"/>
          </menu>
        </partial>
        """
        self.assertXmlPartialEqual(
            expected,
            self.factory.app.create_suite(),
            "./menu[@id='m1']"
        )

    def test_no_forms_selected(self):
        self.shadow_module.excluded_form_ids = [self.form0.unique_id, self.form1.unique_id]
        self.assertXmlDoesNotHaveXpath(self.factory.app.create_suite(), "./menu[@id='m1']")

    def test_no_child_forms_selected(self):
        self.shadow_module.excluded_form_ids = [self.form2.unique_id]
        self.assertXmlPartialEqual(
            '''
                <partial>
                  <menu id="m0">
                    <text>
                      <locale id="modules.m0"/>
                    </text>
                    <command id="m0-f0"/>
                    <command id="m0-f1"/>
                  </menu>
                  <menu id="m1">
                    <text>
                      <locale id="modules.m1"/>
                    </text>
                    <command id="m1-f0"/>
                    <command id="m1-f1"/>
                  </menu>
                  <menu id="m2" root="m0">
                    <text>
                      <locale id="modules.m2"/>
                    </text>
                    <command id="m2-f0"/>
                  </menu>
                </partial>
            ''',
            self.factory.app.create_suite(),
            "./menu"
        )

        self.basic_module.put_in_root = True
        self.shadow_module.put_in_root = False
        self.child_module.put_in_root = False
        self.assertXmlPartialEqual(
            '''
                <partial>
                  <menu id="root">
                    <text>
                      <locale id="modules.m0"/>
                    </text>
                    <command id="m0-f0"/>
                    <command id="m0-f1"/>
                  </menu>
                  <menu id="m1">
                    <text>
                      <locale id="modules.m1"/>
                    </text>
                    <command id="m1-f0"/>
                    <command id="m1-f1"/>
                  </menu>
                  <menu id="m2" root="root">
                    <text>
                      <locale id="modules.m2"/>
                    </text>
                    <command id="m2-f0"/>
                  </menu>
                </partial>
            ''',
            self.factory.app.create_suite(),
            "./menu"
        )

        self.basic_module.put_in_root = False
        self.shadow_module.put_in_root = True
        self.child_module.put_in_root = False
        self.assertXmlPartialEqual(
            '''
                <partial>
                  <menu id="m0">
                    <text>
                      <locale id="modules.m0"/>
                    </text>
                    <command id="m0-f0"/>
                    <command id="m0-f1"/>
                  </menu>
                  <menu id="root">
                    <text>
                      <locale id="modules.m1"/>
                    </text>
                    <command id="m1-f0"/>
                    <command id="m1-f1"/>
                  </menu>
                  <menu id="m2" root="m0">
                    <text>
                      <locale id="modules.m2"/>
                    </text>
                    <command id="m2-f0"/>
                  </menu>
                </partial>
            ''',
            self.factory.app.create_suite(),
            "./menu"
        )

        self.basic_module.put_in_root = False
        self.shadow_module.put_in_root = False
        self.child_module.put_in_root = True
        self.assertXmlPartialEqual(
            '''
                <partial>
                  <menu id="m0">
                    <text>
                      <locale id="modules.m0"/>
                    </text>
                    <command id="m0-f0"/>
                    <command id="m0-f1"/>
                  </menu>
                  <menu id="m1">
                    <text>
                      <locale id="modules.m1"/>
                    </text>
                    <command id="m1-f0"/>
                    <command id="m1-f1"/>
                  </menu>
                  <menu id="m0">
                    <text>
                      <locale id="modules.m0"/>
                    </text>
                    <command id="m2-f0"/>
                  </menu>
                </partial>
            ''',
            self.factory.app.create_suite(),
            "./menu"
        )

        self.basic_module.put_in_root = False
        self.shadow_module.put_in_root = True
        self.child_module.put_in_root = True
        self.assertXmlPartialEqual(
            '''
                <partial>
                  <menu id="m0">
                    <text>
                      <locale id="modules.m0"/>
                    </text>
                    <command id="m0-f0"/>
                    <command id="m0-f1"/>
                  </menu>
                  <menu id="root">
                    <text>
                      <locale id="modules.m1"/>
                    </text>
                    <command id="m1-f0"/>
                    <command id="m1-f1"/>
                  </menu>
                  <menu id="m0">
                    <text>
                      <locale id="modules.m0"/>
                    </text>
                    <command id="m2-f0"/>
                  </menu>
                </partial>
            ''',
            self.factory.app.create_suite(),
            "./menu"
        )

        self.basic_module.put_in_root = True
        self.shadow_module.put_in_root = False
        self.child_module.put_in_root = True
        self.assertXmlPartialEqual(
            '''
                <partial>
                  <menu id="root">
                    <text>
                      <locale id="modules.m0"/>
                    </text>
                    <command id="m0-f0"/>
                    <command id="m0-f1"/>
                  </menu>
                  <menu id="m1">
                    <text>
                      <locale id="modules.m1"/>
                    </text>
                    <command id="m1-f0"/>
                    <command id="m1-f1"/>
                  </menu>
                  <menu id="root">
                    <text>
                      <locale id="modules.m2"/>
                    </text>
                    <command id="m2-f0"/>
                  </menu>
                </partial>
            ''',
            self.factory.app.create_suite(),
            "./menu"
        )

        self.basic_module.put_in_root = True
        self.shadow_module.put_in_root = True
        self.child_module.put_in_root = False
        self.assertXmlPartialEqual(
            '''
                <partial>
                  <menu id="root">
                    <text>
                      <locale id="modules.m0"/>
                    </text>
                    <command id="m0-f0"/>
                    <command id="m0-f1"/>
                  </menu>
                  <menu id="root">
                    <text>
                      <locale id="modules.m1"/>
                    </text>
                    <command id="m1-f0"/>
                    <command id="m1-f1"/>
                  </menu>
                  <menu id="m2" root="root">
                    <text>
                      <locale id="modules.m2"/>
                    </text>
                    <command id="m2-f0"/>
                  </menu>
                </partial>
            ''',
            self.factory.app.create_suite(),
            "./menu"
        )

        self.basic_module.put_in_root = True
        self.shadow_module.put_in_root = True
        self.child_module.put_in_root = True
        self.assertXmlPartialEqual(
            '''
                <partial>
                  <menu id="root">
                    <text>
                      <locale id="modules.m0"/>
                    </text>
                    <command id="m0-f0"/>
                    <command id="m0-f1"/>
                  </menu>
                  <menu id="root">
                    <text>
                      <locale id="modules.m1"/>
                    </text>
                    <command id="m1-f0"/>
                    <command id="m1-f1"/>
                  </menu>
                  <menu id="root">
                    <text>
                      <locale id="modules.m2"/>
                    </text>
                    <command id="m2-f0"/>
                  </menu>
                </partial>
            ''',
            self.factory.app.create_suite(),
            "./menu"
        )


    def test_form_added(self):
        self.shadow_module.excluded_form_ids = [self.form0.unique_id]
        self.factory.new_form(self.basic_module)
        expected = """
        <partial>
          <menu id="m1">
            <text>
              <locale id="modules.m1"/>
            </text>
            <command id="m1-f1"/>
            <command id="m1-f2"/>
          </menu>
        </partial>
        """
        self.assertXmlPartialEqual(
            expected,
            self.factory.app.create_suite(),
            "./menu[@id='m1']"
        )

    def test_form_removed(self):
        self.basic_module.forms.remove(self.form1)
        expected = """
        <partial>
          <menu id="m1">
            <text>
              <locale id="modules.m1"/>
            </text>
            <command id="m1-f0"/>
          </menu>
        </partial>
        """
        self.assertXmlPartialEqual(
            expected,
            self.factory.app.create_suite(),
            "./menu[@id='m1']"
        )

    def test_forms_reordered(self):
        expected_before = """
        <partial>
          <form>http://openrosa.org/formdesigner/firstform</form>
          <form>http://openrosa.org/formdesigner/secondform</form>

          <form>http://openrosa.org/formdesigner/firstform</form>
          <form>http://openrosa.org/formdesigner/secondform</form>
        </partial>
        """
        self.assertXmlPartialEqual(
            expected_before,
            self.factory.app.create_suite(),
            "./entry/form"
        )
        # Swap forms around
        self.basic_module.forms = [self.form1, self.form0]
        expected_after = """
        <partial>
          <form>http://openrosa.org/formdesigner/secondform</form>
          <form>http://openrosa.org/formdesigner/firstform</form>

          <form>http://openrosa.org/formdesigner/secondform</form>
          <form>http://openrosa.org/formdesigner/firstform</form>
        </partial>
        """
        self.assertXmlPartialEqual(
            expected_after,
            self.factory.app.create_suite(),
            "./entry/form"
        )

    def _create_parent_selection_app(self):
        '''
           setUp creates an app with three modules: basic, shadow, and child, all using parrot cases.
           This app adds an additional module that uses child cases (baby_parrot) and uses it as the
           source for the shadow module. Tests verify that when the shadow module uses parent child
           selection, it fetches both parrot and baby_parrot datums, using the correct details.
        '''
        self.factory.form_requires_case(self.form0)
        self.child_case_module, self.form3 = self.factory.new_basic_module('child_case_module', 'baby_parrot')
        self.factory.form_requires_case(self.form3, parent_case_type='parrot')
        self.shadow_module.source_module_id = self.child_case_module.unique_id
        self.shadow_module.parent_select.active = True

    def test_parent_selection_first(self):
        self._create_parent_selection_app()
        self.shadow_module.parent_select.module_id = self.basic_module.unique_id

        # Test the entry for the shadow module's single form
        expected_entry = """
            <partial>
              <entry>
                <command id="m1-f0">
                  <text>
                    <locale id="forms.m3f0"/>
                  </text>
                </command>
                <instance id="casedb" src="jr://instance/casedb"/>
                <instance id="commcaresession" src="jr://instance/session"/>
                <session>
                  <datum id="parent_id" nodeset="instance('casedb')/casedb/case[@case_type='parrot'][@status='open']"
                         value="./@case_id" detail-select="m0_case_short"/>
                  <datum id="case_id" nodeset="instance('casedb')/casedb/case[@case_type='baby_parrot'][@status='open'][index/parent=instance('commcaresession')/session/data/parent_id]"
                         value="./@case_id" detail-select="m1_case_short" detail-confirm="m1_case_long"/>
                </session>
              </entry>
            </partial>
        """
        self.assertXmlPartialEqual(
            expected_entry,
            self.factory.app.create_suite(),
            './entry[3]'
        )

    def test_parent_selection_different_module_than_source(self):
        self._create_parent_selection_app()
        self.additional_basic_module, dummy = self.factory.new_basic_module('additional_basic_module', 'parrot')
        self.child_case_module.parent_select.active = True
        self.child_case_module.parent_select.module_id = self.basic_module.unique_id
        self.shadow_module.parent_select.module_id = self.additional_basic_module.unique_id

        # Test the entry for the shadow module's single form
        expected_entry = """
            <partial>
              <entry>
                <command id="m1-f0">
                  <text>
                    <locale id="forms.m3f0"/>
                  </text>
                </command>
                <instance id="casedb" src="jr://instance/casedb"/>
                <instance id="commcaresession" src="jr://instance/session"/>
                <session>
                  <datum id="parent_id" nodeset="instance('casedb')/casedb/case[@case_type='parrot'][@status='open']"
                         value="./@case_id" detail-select="m4_case_short"/>
                  <datum id="case_id" nodeset="instance('casedb')/casedb/case[@case_type='baby_parrot'][@status='open'][index/parent=instance('commcaresession')/session/data/parent_id]"
                         value="./@case_id" detail-select="m1_case_short" detail-confirm="m1_case_long"/>
                </session>
              </entry>
            </partial>
        """
        self.assertXmlPartialEqual(
            expected_entry,
            self.factory.app.create_suite(),
            './entry[3]'
        )
Пример #8
0
class ShadowModuleFormSelectionSuiteTest(SimpleTestCase, TestXmlMixin):

    def setUp(self):
        self.factory = AppFactory()
        self.basic_module, self.form0 = self.factory.new_basic_module('basic_module', 'parrot')
        self.form0.xmlns = 'http://openrosa.org/formdesigner/firstform'
        self.form1 = self.factory.new_form(self.basic_module)
        self.form1.xmlns = 'http://openrosa.org/formdesigner/secondform'
        self.shadow_module = self.factory.new_shadow_module('shadow_module', self.basic_module, with_form=False)
        self.child_module, self.form2 = self.factory.new_basic_module('child_module', 'parrot',
                                                                      parent_module=self.basic_module)

    def test_all_forms_selected(self):
        expected = """
        <partial>
          <menu id="m1">
            <text>
              <locale id="modules.m1"/>
            </text>
            <command id="m1-f0"/>
            <command id="m1-f1"/>
          </menu>
        </partial>
        """
        self.assertXmlPartialEqual(
            expected,
            self.factory.app.create_suite(),
            "./menu[@id='m1']"
        )

    def test_some_forms_selected(self):
        self.shadow_module.excluded_form_ids = [self.form0.unique_id]
        expected = """
        <partial>
          <menu id="m1">
            <text>
              <locale id="modules.m1"/>
            </text>
            <command id="m1-f1"/>
          </menu>
        </partial>
        """
        self.assertXmlPartialEqual(
            expected,
            self.factory.app.create_suite(),
            "./menu[@id='m1']"
        )

    def test_no_forms_selected(self):
        self.shadow_module.excluded_form_ids = [self.form0.unique_id, self.form1.unique_id]
        self.assertXmlDoesNotHaveXpath(self.factory.app.create_suite(), "./menu[@id='m1']")

    def test_no_child_forms_selected(self):
        self.shadow_module.excluded_form_ids = [self.form2.unique_id]
        self.assertXmlPartialEqual(
            '''
                <partial>
                  <menu id="m0">
                    <text>
                      <locale id="modules.m0"/>
                    </text>
                    <command id="m0-f0"/>
                    <command id="m0-f1"/>
                  </menu>
                  <menu id="m1">
                    <text>
                      <locale id="modules.m1"/>
                    </text>
                    <command id="m1-f0"/>
                    <command id="m1-f1"/>
                  </menu>
                  <menu id="m2" root="m0">
                    <text>
                      <locale id="modules.m2"/>
                    </text>
                    <command id="m2-f0"/>
                  </menu>
                </partial>
            ''',
            self.factory.app.create_suite(),
            "./menu"
        )

        self.basic_module.put_in_root = True
        self.shadow_module.put_in_root = False
        self.child_module.put_in_root = False
        self.assertXmlPartialEqual(
            '''
                <partial>
                  <menu id="root">
                    <text>
                      <locale id="modules.m0"/>
                    </text>
                    <command id="m0-f0"/>
                    <command id="m0-f1"/>
                  </menu>
                  <menu id="m1">
                    <text>
                      <locale id="modules.m1"/>
                    </text>
                    <command id="m1-f0"/>
                    <command id="m1-f1"/>
                  </menu>
                  <menu id="m2" root="root">
                    <text>
                      <locale id="modules.m2"/>
                    </text>
                    <command id="m2-f0"/>
                  </menu>
                </partial>
            ''',
            self.factory.app.create_suite(),
            "./menu"
        )

        self.basic_module.put_in_root = False
        self.shadow_module.put_in_root = True
        self.child_module.put_in_root = False
        self.assertXmlPartialEqual(
            '''
                <partial>
                  <menu id="m0">
                    <text>
                      <locale id="modules.m0"/>
                    </text>
                    <command id="m0-f0"/>
                    <command id="m0-f1"/>
                  </menu>
                  <menu id="root">
                    <text>
                      <locale id="modules.m1"/>
                    </text>
                    <command id="m1-f0"/>
                    <command id="m1-f1"/>
                  </menu>
                  <menu id="m2" root="m0">
                    <text>
                      <locale id="modules.m2"/>
                    </text>
                    <command id="m2-f0"/>
                  </menu>
                </partial>
            ''',
            self.factory.app.create_suite(),
            "./menu"
        )

        self.basic_module.put_in_root = False
        self.shadow_module.put_in_root = False
        self.child_module.put_in_root = True
        self.assertXmlPartialEqual(
            '''
                <partial>
                  <menu id="m0">
                    <text>
                      <locale id="modules.m0"/>
                    </text>
                    <command id="m0-f0"/>
                    <command id="m0-f1"/>
                  </menu>
                  <menu id="m1">
                    <text>
                      <locale id="modules.m1"/>
                    </text>
                    <command id="m1-f0"/>
                    <command id="m1-f1"/>
                  </menu>
                  <menu id="m0">
                    <text>
                      <locale id="modules.m2"/>
                    </text>
                    <command id="m2-f0"/>
                  </menu>
                </partial>
            ''',
            self.factory.app.create_suite(),
            "./menu"
        )

        self.basic_module.put_in_root = False
        self.shadow_module.put_in_root = True
        self.child_module.put_in_root = True
        self.assertXmlPartialEqual(
            '''
                <partial>
                  <menu id="m0">
                    <text>
                      <locale id="modules.m0"/>
                    </text>
                    <command id="m0-f0"/>
                    <command id="m0-f1"/>
                  </menu>
                  <menu id="root">
                    <text>
                      <locale id="modules.m1"/>
                    </text>
                    <command id="m1-f0"/>
                    <command id="m1-f1"/>
                  </menu>
                  <menu id="m0">
                    <text>
                      <locale id="modules.m2"/>
                    </text>
                    <command id="m2-f0"/>
                  </menu>
                </partial>
            ''',
            self.factory.app.create_suite(),
            "./menu"
        )

        self.basic_module.put_in_root = True
        self.shadow_module.put_in_root = False
        self.child_module.put_in_root = True
        self.assertXmlPartialEqual(
            '''
                <partial>
                  <menu id="root">
                    <text>
                      <locale id="modules.m0"/>
                    </text>
                    <command id="m0-f0"/>
                    <command id="m0-f1"/>
                  </menu>
                  <menu id="m1">
                    <text>
                      <locale id="modules.m1"/>
                    </text>
                    <command id="m1-f0"/>
                    <command id="m1-f1"/>
                  </menu>
                  <menu id="root">
                    <text>
                      <locale id="modules.m2"/>
                    </text>
                    <command id="m2-f0"/>
                  </menu>
                </partial>
            ''',
            self.factory.app.create_suite(),
            "./menu"
        )

        self.basic_module.put_in_root = True
        self.shadow_module.put_in_root = True
        self.child_module.put_in_root = False
        self.assertXmlPartialEqual(
            '''
                <partial>
                  <menu id="root">
                    <text>
                      <locale id="modules.m0"/>
                    </text>
                    <command id="m0-f0"/>
                    <command id="m0-f1"/>
                  </menu>
                  <menu id="root">
                    <text>
                      <locale id="modules.m1"/>
                    </text>
                    <command id="m1-f0"/>
                    <command id="m1-f1"/>
                  </menu>
                  <menu id="m2" root="root">
                    <text>
                      <locale id="modules.m2"/>
                    </text>
                    <command id="m2-f0"/>
                  </menu>
                </partial>
            ''',
            self.factory.app.create_suite(),
            "./menu"
        )

        self.basic_module.put_in_root = True
        self.shadow_module.put_in_root = True
        self.child_module.put_in_root = True
        self.assertXmlPartialEqual(
            '''
                <partial>
                  <menu id="root">
                    <text>
                      <locale id="modules.m0"/>
                    </text>
                    <command id="m0-f0"/>
                    <command id="m0-f1"/>
                  </menu>
                  <menu id="root">
                    <text>
                      <locale id="modules.m1"/>
                    </text>
                    <command id="m1-f0"/>
                    <command id="m1-f1"/>
                  </menu>
                  <menu id="root">
                    <text>
                      <locale id="modules.m2"/>
                    </text>
                    <command id="m2-f0"/>
                  </menu>
                </partial>
            ''',
            self.factory.app.create_suite(),
            "./menu"
        )


    def test_form_added(self):
        self.shadow_module.excluded_form_ids = [self.form0.unique_id]
        self.factory.new_form(self.basic_module)
        expected = """
        <partial>
          <menu id="m1">
            <text>
              <locale id="modules.m1"/>
            </text>
            <command id="m1-f1"/>
            <command id="m1-f2"/>
          </menu>
        </partial>
        """
        self.assertXmlPartialEqual(
            expected,
            self.factory.app.create_suite(),
            "./menu[@id='m1']"
        )

    def test_form_removed(self):
        self.basic_module.forms.remove(self.form1)
        expected = """
        <partial>
          <menu id="m1">
            <text>
              <locale id="modules.m1"/>
            </text>
            <command id="m1-f0"/>
          </menu>
        </partial>
        """
        self.assertXmlPartialEqual(
            expected,
            self.factory.app.create_suite(),
            "./menu[@id='m1']"
        )

    def test_forms_reordered(self):
        expected_before = """
        <partial>
          <form>http://openrosa.org/formdesigner/firstform</form>
          <form>http://openrosa.org/formdesigner/secondform</form>

          <form>http://openrosa.org/formdesigner/firstform</form>
          <form>http://openrosa.org/formdesigner/secondform</form>
        </partial>
        """
        self.assertXmlPartialEqual(
            expected_before,
            self.factory.app.create_suite(),
            "./entry/form"
        )
        # Swap forms around
        self.basic_module.forms = [self.form1, self.form0]
        expected_after = """
        <partial>
          <form>http://openrosa.org/formdesigner/secondform</form>
          <form>http://openrosa.org/formdesigner/firstform</form>

          <form>http://openrosa.org/formdesigner/secondform</form>
          <form>http://openrosa.org/formdesigner/firstform</form>
        </partial>
        """
        self.assertXmlPartialEqual(
            expected_after,
            self.factory.app.create_suite(),
            "./entry/form"
        )
Пример #9
0
class MultiSelectCaseListTests(SimpleTestCase, TestXmlMixin):
    file_path = ('data', 'suite', 'multi_select_case_list')

    def setUp(self):
        self.factory = AppFactory(domain="multiple-referrals")
        self.app_id = uuid4().hex
        self.factory.app._id = self.app_id
        self.module, self.form = self.factory.new_basic_module(
            'basic', 'person')
        self.factory.form_requires_case(self.form, 'person')
        self.form.xmlns = "some-xmlns"

        self.module.case_details.short.multi_select = True
        self.module.search_config = CaseSearch(
            search_label=CaseSearchLabel(label={'en': 'Search'}),
            properties=[
                CaseSearchProperty(name=field)
                for field in ['name', 'greatest_fear']
            ],
        )
        self.module.assign_references()

    def test_multi_select_case_list(self):
        suite = self.factory.app.create_suite()
        self.assertXmlPartialEqual(
            """
            <partial>
              <entry>
                <form>some-xmlns</form>
                <command id="m0-f0">
                  <text>
                    <locale id="forms.m0f0"/>
                  </text>
                </command>
                <instance id="casedb" src="jr://instance/casedb"/>
                <session>
                  <instance-datum id="selected_cases"
                                  nodeset="instance('casedb')/casedb/case[@case_type='person'][@status='open']"
                                  value="./@case_id"
                                  detail-select="m0_case_short"
                                  detail-confirm="m0_case_long"/>
                </session>
              </entry>
            </partial>
            """,
            suite,
            "./entry",
        )
        self.assertXmlPartialEqual(
            self.get_xml('basic_remote_request').decode('utf-8').format(
                app_id=self.factory.app._id),
            suite,
            "./remote-request",
        )

    def test_session_schema(self):
        # Session schema should not contain case
        self.assertEqual(
            get_session_schema(self.form), {
                'id': 'commcaresession',
                'name': 'Session',
                'path': '/session',
                'structure': {},
                'uri': 'jr://instance/session'
            })

    @flag_enabled('APP_BUILDER_SHADOW_MODULES')
    def test_shadow_modules(self):
        shadow_module = self.factory.new_shadow_module('shadow',
                                                       self.module,
                                                       with_form=False)
        self.assertTrue(shadow_module.is_multi_select())
        del self.factory.app.modules[shadow_module.id]

    @flag_enabled('USH_CASE_CLAIM_UPDATES')
    def test_multi_select_case_list_auto_launch(self):
        self.module.search_config.auto_launch = True
        suite = self.factory.app.create_suite()

        self.assertXmlPartialEqual(
            """
            <partial>
              <action auto_launch="true()" redo_last="false">
                <display>
                  <text>
                    <locale id="case_search.m0"/>
                  </text>
                </display>
                <stack>
                  <push>
                    <mark/>
                    <command value="'search_command.m0'"/>
                  </push>
                </stack>
              </action>
            </partial>
            """,
            suite,
            "./detail[@id='m0_case_short']/action",
        )

        self.assertXmlPartialEqual(
            """
            <partial>
              <action auto_launch="false()" redo_last="true">
                <display>
                  <text>
                    <locale id="case_search.m0.again"/>
                  </text>
                </display>
                <stack>
                  <push>
                    <mark/>
                    <command value="'search_command.m0'"/>
                  </push>
                </stack>
              </action>
            </partial>
            """,
            suite,
            "./detail[@id='m0_search_short']/action",
        )