def test_long_detail_xml(self): factory = AppFactory(build_version='2.26') factory.new_basic_module('registration', 'patient registration') module = factory.app.get_module(0) case_details = module.case_details long = case_details.long long.display = 'long' long_column = long.get_column(0) long_column.format = 'distance' suite = factory.app.create_suite() template_xpath = './detail[@id="m0_case_long"]/field' self.assertXmlHasXpath(suite, template_xpath) self.assertXmlPartialEqual( """ <partial> <field> <header> <text> <locale id="m0.case_long.case_name_1.header"/> </text> </header> <template> <text> <xpath function="if(here() = '', '', if(case_name = '', '', concat(round(distance(case_name, here()) div 1000), ' km')))"/> </text> </template> </field> </partial> """, suite, template_xpath )
def test_that_grid_style_is_added(self): """ Confirms that style="grid" is added to the root menu """ factory = AppFactory(build_version='2.24') factory.app.use_grid_menus = True factory.new_basic_module('registration', 'patient registration') factory.app.get_module(0).put_in_root = True factory.new_basic_module('visit', 'patient visit') factory.app.get_module(1).put_in_root = True suite = factory.app.create_suite() root_xpath = './menu[@id="root"]' self.assertXmlHasXpath(suite, root_xpath) self.assertXmlPartialEqual( """ <partial> <menu id="root" style="grid"> <text><locale id="modules.m0"/></text> <command id="m0-f0"/> </menu> <menu id="root" style="grid"> <text><locale id="modules.m1"/></text> <command id="m1-f0"/> </menu> </partial> """, suite, root_xpath )
def test_form_display_condition(self): """ case_id should be renamed in a basic submodule form """ factory = AppFactory(domain=DOMAIN) m0, m0f0 = factory.new_advanced_module('parent', 'gold-fish') factory.form_requires_case(m0f0) # changing this case tag should result in the session var in the submodule entry being updated to match it m0f0.actions.load_update_cases[0].case_tag = 'load_goldfish_renamed' m1, m1f0 = factory.new_advanced_module('child', 'guppy', parent_module=m0) factory.form_requires_case(m1f0, 'gold-fish', update={'question1': '/data/question1'}) factory.form_requires_case(m1f0, 'guppy', parent_case_type='gold-fish') # making this case tag the same as the one in the parent module should mean that it will also get changed # to avoid conflicts m1f0.actions.load_update_cases[1].case_tag = 'load_goldfish_renamed' m1f0.form_filter = "#case/age > 33" XML = """ <partial> <menu id="m1" root="m0"> <text> <locale id="modules.m1"/> </text> <command id="m1-f0" relevant="instance('casedb')/casedb/case[@case_id=instance('commcaresession')/session/data/case_id_load_goldfish_renamed_guppy]/age > 33"/> </menu> </partial> """ self.assertXmlPartialEqual(XML, factory.app.create_suite(), "./menu[@id='m1']")
def test_use_grid_menus_is_false(self): """ Confirms that style="grid" is not added to any menus when use_grid_menus is False. """ factory = AppFactory(build_version='2.24') factory.app.use_grid_menus = False factory.new_basic_module('registration', 'patient') suite = factory.app.create_suite() style_xpath = './menu[@style="grid"]' self.assertXmlDoesNotHaveXpath(suite, style_xpath)
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)
def setUp(self): update_toggle_cache(MODULE_FILTER.slug, DOMAIN, True, NAMESPACE_DOMAIN) self.factory = AppFactory(domain=DOMAIN) self.module_0, _ = self.factory.new_basic_module('parent', 'gold-fish') self.module_1, _ = self.factory.new_module(self.child_module_class, 'child', 'guppy', parent_module=self.module_0) self.app = self.factory.app
def test_that_root_menu_added(self): """ Confirms that a menu is added with id="root" and style="grid" when the app normally wouldn't have a menu with id="root". """ factory = AppFactory(build_version='2.24') factory.app.use_grid_menus = True factory.new_basic_module('registration', 'patient') suite = factory.app.create_suite() root_xpath = './menu[@id="root"]' self.assertXmlHasXpath(suite, root_xpath) self.assertXmlPartialEqual( '<partial><menu id="root" style="grid"><text/></menu></partial>', suite, root_xpath )
def test_case_list_lookup_display_results(self): factory = AppFactory(build_version='2.11') module, form = factory.new_basic_module('follow_up', 'case') case_list = module.case_details.short case_list.lookup_enabled = True case_list.lookup_action = "callout.commcarehq.org.dummycallout.LAUNCH" case_list.lookup_name = 'Scan fingerprint' case_list.lookup_extras = [ {'key': 'deviceId', 'value': '123'}, {'key': 'apiKey', 'value': '0000'}, {'key': 'packageName', 'value': 'foo'}, ] case_list.lookup_responses = [ {'key': 'fake'} ] case_list.lookup_display_results = True case_list.lookup_field_header['en'] = 'Accuracy' case_list.lookup_field_template = '@case_id' expected = """ <partial> <lookup name="Scan fingerprint" action="callout.commcarehq.org.dummycallout.LAUNCH"> <extra key="deviceId" value="123"/> <extra key="apiKey" value="0000"/> <extra key="packageName" value="foo"/> <response key="fake"/> <field> <header> <text> <locale id="case_lists.m0.callout.header"/> </text> </header> <template> <text> <xpath function="@case_id"/> </text> </template> </field> </lookup> </partial> """ self.assertXmlPartialEqual( expected, factory.app.create_suite(), "./detail[@id='m0_case_short']/lookup" )
def class_setup(cls): cls.domain = uuid.uuid4().hex cls.f1_xmlns = 'xmlns1' cls.f2_xmlns = 'xmlns2' app_factory = AppFactory(domain=cls.domain) module1, form1 = app_factory.new_basic_module('m1', '_casetype') module2, form2 = app_factory.new_basic_module('m2', '_casetype2') form1.xmlns = cls.f1_xmlns form2.xmlns = cls.f2_xmlns app_factory.app.save() cls.app = app_factory.app deleted_app_factory = AppFactory(domain=cls.domain) deleted_module1, deleted_form1 = deleted_app_factory.new_basic_module('del-m1', '_casetype3') cls.deleted_xmlns = 'xmlns3' deleted_form1.xmlns = cls.deleted_xmlns deleted_app_factory.app.doc_type = 'Application-Deleted' # make sure the ID comes after the primary app deleted_app_factory.app._id = '{}z'.format(cls.app.id) deleted_app_factory.app.save() cls.deleted_app = deleted_app_factory.app cls.xmlnses = [cls.f1_xmlns, cls.f2_xmlns, cls.deleted_xmlns] update_reports_analytics_indexes()
def test_short_detail_xml(self): factory = AppFactory(build_version='2.26') factory.new_basic_module('registration', 'patient registration') module = factory.app.get_module(0) case_details = module.case_details short = case_details.short short.display = 'short' short_column = short.get_column(0) short_column.format = 'distance' suite = factory.app.create_suite() template_xpath = './detail[@id="m0_case_short"]/field' self.assertXmlHasXpath(suite, template_xpath) self.assertXmlPartialEqual( """ <partial> <field> <header> <text> <locale id="m0.case_short.case_name_1.header"/> </text> </header> <template> <text> <xpath function="if(here() = '', '', if(case_name = '', '', concat(round(distance(case_name, here()) div 1000), ' km')))"/> </text> </template> <sort direction="ascending" order="1" type="double"> <text> <xpath function="round(distance(case_name, here()))"/> </text> </sort> </field> </partial> """, suite, template_xpath )
def test_parent_preload(self): """ Test parent case is correctly set in preloads when first form of parent module updates a case """ factory = AppFactory(build_version='2.9') upd_goldfish_mod, upd_goldfish_form = factory.new_basic_module('upd_goldfish', 'gold-fish') factory.form_requires_case(upd_goldfish_form) guppy_mod, guppy_form = factory.new_basic_module( 'upd_guppy', 'guppy', parent_module=upd_goldfish_mod, ) guppy_form.source = self.get_xml('original_form', override_path=('data',)) factory.form_requires_case( guppy_form, 'guppy', parent_case_type='gold-fish', preload={'/data/question1': 'parent/question1'}) self.assertXmlEqual(self.get_xml('child-module-preload-parent-ref'), guppy_form.render_xform())
def setUp(self): self.factory = AppFactory(build_version="2.26") self.factory.new_basic_module("registration", "patient registration") module = self.factory.app.get_module(0) self.case_details = module.case_details
class CaseDetailDistance(SimpleTestCase, TestXmlMixin): def setUp(self): self.factory = AppFactory(build_version="2.26") self.factory.new_basic_module("registration", "patient registration") module = self.factory.app.get_module(0) self.case_details = module.case_details def test_short_detail_xml(self): short = self.case_details.short short.display = "short" short_column = short.get_column(0) short_column.format = "distance" suite = self.factory.app.create_suite() template_xpath = './detail[@id="m0_case_short"]/field' self.assertXmlHasXpath(suite, template_xpath) self.assertXmlPartialEqual( """ <partial> <field> <header> <text> <locale id="m0.case_short.case_name_1.header"/> </text> </header> <template> <text> <xpath function="if(here() = '', '', if(case_name = '', '', concat(round(distance(case_name, here()) div 1000), ' km')))"/> </text> </template> <sort direction="ascending" order="1" type="double"> <text> <xpath function="round(distance(case_name, here()))"/> </text> </sort> </field> </partial> """, suite, template_xpath, ) def test_short_detail_xml_with_sort(self): short = self.case_details.short short.display = "short" short_column = short.get_column(0) short.sort_elements.append(SortElement(field=short_column.field, type="distance", direction="descending")) suite = self.factory.app.create_suite() template_xpath = './detail[@id="m0_case_short"]/field' self.assertXmlHasXpath(suite, template_xpath) self.assertXmlPartialEqual( """ <partial> <field> <header> <text> <locale id="m0.case_short.case_name_1.header"/> </text> </header> <template> <text> <xpath function="case_name"/> </text> </template> <sort direction="descending" order="1" type="double"> <text> <xpath function="round(distance(case_name, here()))"/> </text> </sort> </field> </partial> """, suite, template_xpath, ) def test_short_detail_xml_sort_only(self): short = self.case_details.short short.display = "short" short.sort_elements.append(SortElement(field="gps", type="distance", direction="descending")) suite = self.factory.app.create_suite() template_xpath = './detail[@id="m0_case_short"]/field' self.assertXmlHasXpath(suite, template_xpath) self.assertXmlPartialEqual( """ <partial> <field> <header> <text> <locale id="m0.case_short.case_name_1.header"/> </text> </header> <template> <text> <xpath function="case_name"/> </text> </template> </field> <field> <header width="0"> <text/> </header> <template width="0"> <text> <xpath function="gps"/> </text> </template> <sort direction="descending" order="1" type="double"> <text> <xpath function="round(distance(gps, here()))"/> </text> </sort> </field> </partial> """, suite, template_xpath, ) def test_long_detail_xml(self): long = self.case_details.long long.display = "long" long_column = long.get_column(0) long_column.format = "distance" suite = self.factory.app.create_suite() template_xpath = './detail[@id="m0_case_long"]/field' self.assertXmlHasXpath(suite, template_xpath) self.assertXmlPartialEqual( """ <partial> <field> <header> <text> <locale id="m0.case_long.case_name_1.header"/> </text> </header> <template> <text> <xpath function="if(here() = '', '', if(case_name = '', '', concat(round(distance(case_name, here()) div 1000), ' km')))"/> </text> </template> </field> </partial> """, suite, template_xpath, )
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) 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] expected = """ <partial> <menu id="m1"> <text> <locale id="modules.m1"/> </text> </menu> </partial> """ self.assertXmlPartialEqual( expected, self.factory.app.create_suite(), "./menu[@id='m1']" ) 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 test_form_rename_session_vars(self): """ The session vars in the entries for the submodule should match the parent and avoid naming conflicts. """ factory = AppFactory(build_version='2.9') reg_goldfish_mod, reg_goldfish_form = factory.new_basic_module('reg_goldfish', 'gold-fish') factory.form_opens_case(reg_goldfish_form) reg_guppy_mod, reg_guppy_form = factory.new_advanced_module('reg_guppy', 'guppy') factory.form_requires_case(reg_guppy_form, 'gold-fish') factory.form_opens_case(reg_guppy_form, 'guppy', is_subcase=True) upd_goldfish_mod, upd_goldfish_form = factory.new_advanced_module( 'upd_goldfish', 'gold-fish', ) factory.form_requires_case(upd_goldfish_form) # changing this case tag should result in the session var in the submodule entry being updated to match it upd_goldfish_form.actions.load_update_cases[0].case_tag = 'load_goldfish_renamed' upd_guppy_mod, upd_guppy_form = factory.new_advanced_module( 'upd_guppy', 'guppy', parent_module=upd_goldfish_mod, ) upd_guppy_form.source = self.get_xml('original_form', override_path=('data',)) factory.form_requires_case(upd_guppy_form, 'gold-fish', update={'question1': '/data/question1'}) factory.form_requires_case( upd_guppy_form, 'guppy', parent_case_type='gold-fish', update={'question1': '/data/question1'} ) # making this case tag the same as the one in the parent module should mean that it will also get changed # to avoid conflicts upd_guppy_form.actions.load_update_cases[1].case_tag = 'load_goldfish_renamed' self.assertXmlEqual(self.get_xml('child-module-rename-session-vars'), upd_guppy_form.render_xform())
class ModuleAsChildTestBase(TestXmlMixin): file_path = ('data', 'suite') child_module_class = None def setUp(self): update_toggle_cache(MODULE_FILTER.slug, DOMAIN, True, NAMESPACE_DOMAIN) self.factory = AppFactory(domain=DOMAIN) self.module_0, _ = self.factory.new_basic_module('parent', 'gold-fish') self.module_1, _ = self.factory.new_module(self.child_module_class, 'child', 'guppy', parent_module=self.module_0) self.app = self.factory.app def tearDown(self): clear_toggle_cache(MODULE_FILTER.slug, DOMAIN, NAMESPACE_DOMAIN) def test_basic_workflow(self): # make module_1 as submenu to module_0 XML = """ <partial> <menu id="m0"> <text> <locale id="modules.m0"/> </text> <command id="m0-f0"/> </menu> <menu root="m0" id="m1"> <text> <locale id="modules.m1"/> </text> <command id="m1-f0"/> </menu> </partial> """ self.assertXmlPartialEqual(XML, self.app.create_suite(), "./menu") def test_workflow_with_put_in_root(self): # make module_1 as submenu to module_0 self.module_1.put_in_root = True XML = """ <partial> <menu id="m0"> <text> <locale id="modules.m0"/> </text> <command id="m0-f0"/> </menu> <menu id="m0"> <text> <locale id="modules.m1"/> </text> <command id="m1-f0"/> </menu> </partial> """ self.assertXmlPartialEqual(XML, self.app.create_suite(), "./menu") def test_deleted_parent(self): self.module_1.root_module_id = "unknownmodule" cycle_error = { 'type': 'unknown root', } errors = self.app.validate_app() self.assertIn(cycle_error, errors) def test_circular_relation(self): self.module_0.root_module_id = self.module_1.unique_id cycle_error = { 'type': 'root cycle', } errors = self.app.validate_app() self.assertIn(cycle_error, errors)