def _make_app_with_shadow_forms(self): factory = AppFactory('upstream', "Upstream App", include_xmlns=True) module1, form1 = factory.new_advanced_module('M1', 'casetype') factory.new_form(module1) module2, form2 = factory.new_advanced_module('M2', 'casetype') factory.new_form(module2) self._make_shadow_form(factory, 'M3', form1) self._make_shadow_form(factory, 'M4', form2) factory.app.save() self.addCleanup(factory.app.delete) # the test form names are unique form_names = [f.name['en'] for f in factory.app.get_forms()] self.assertEqual(len(form_names), len(set(form_names))) return factory.app
def test_scheduler_module(self): factory = AppFactory() m1, m1f1 = factory.new_basic_module('open_case', 'house') factory.form_opens_case(m1f1) m2, m2f1 = factory.new_advanced_module('scheduler_module', 'house') m2f2 = factory.new_form(m2) factory.form_requires_case(m2f1, case_type='house', update={ 'foo': '/data/question1', 'bar': '/data/question2', }) factory.form_requires_case(m2f2, case_type='house', update={ 'bleep': '/data/question1', 'bloop': '/data/question2', }) self._add_scheduler_to_module(m2) self._add_scheduler_to_form(m2f1, m2, 'form1') self._add_scheduler_to_form(m2f2, m2, 'form2') self.assertCaseProperties(factory.app, 'house', [ 'foo', 'bar', 'bleep', 'bloop', # Scheduler properties: 'last_visit_date_form1', 'last_visit_number_form1', 'last_visit_date_form2', 'last_visit_number_form2', 'current_schedule_phase', ])
def test_scheduler_module(self): factory = AppFactory() m1, m1f1 = factory.new_basic_module('open_case', 'house') factory.form_opens_case(m1f1) m2, m2f1 = factory.new_advanced_module('scheduler_module', 'house') m2f2 = factory.new_form(m2) factory.form_requires_case(m2f1, case_type='house', update={ 'foo': '/data/question1', 'bar': '/data/question2', }) factory.form_requires_case(m2f2, case_type='house', update={ 'bleep': '/data/question1', 'bloop': '/data/question2', }) self._add_scheduler_to_module(m2) self._add_scheduler_to_form(m2f1, m2, 'form1') self._add_scheduler_to_form(m2f2, m2, 'form2') self.assertCaseProperties(factory.app, 'house', [ 'foo', 'bar', 'bleep', 'bloop', # Scheduler properties: 'last_visit_date_form1', 'last_visit_number_form1', 'last_visit_date_form2', 'last_visit_number_form2', 'current_schedule_phase', ])
def test_form_links_submodule(self): """ Test that when linking between two forms in a submodule we match up the session variables between the source and target form correctly :return: """ factory = AppFactory(build_version='2.9.0/latest') m0, m0f0 = factory.new_basic_module('child visit', 'child') factory.form_requires_case(m0f0) factory.form_opens_case(m0f0, 'visit', is_subcase=True) m1, m1f0 = factory.new_advanced_module('visit histroy', 'visit', parent_module=m0) factory.form_requires_case(m1f0, 'child') factory.form_requires_case(m1f0, 'visit', parent_case_type='child') m1f1 = factory.new_form(m1) factory.form_requires_case(m1f1, 'child') factory.form_requires_case(m1f1, 'visit', parent_case_type='child') m1f0.post_form_workflow = WORKFLOW_FORM m1f0.form_links = [ FormLink(xpath="true()", form_id=m1f1.unique_id), ] self.assertXmlPartialEqual(self.get_xml('form_link_submodule'), factory.app.create_suite(), "./entry")
def test_case_list_form_advanced_module_different_case_config(self, *args): case_tile_error = { 'type': "all forms in case list module must load the same cases", 'module': { 'id': 1, 'name': { 'en': 'update module' } }, 'form': { 'id': 1, 'name': { 'en': 'update form 1' } }, } factory = AppFactory(build_version='2.11.0') m0, m0f0 = factory.new_basic_module('register', 'person') factory.form_opens_case(m0f0) m1, m1f0 = factory.new_advanced_module('update', 'person', case_list_form=m0f0) factory.form_requires_case(m1f0, case_type='house') factory.form_requires_case(m1f0, parent_case_type='house') m1f1 = factory.new_form(m1) factory.form_requires_case( m1f1) # only loads a person case and not a house case errors = factory.app.validate_app() self._clean_unique_id(errors) self.assertIn(case_tile_error, errors)
def test_form_links_submodule(self): # Test that when linking between two forms in a submodule we match up the # session variables between the source and target form correctly factory = AppFactory(build_version='2.9.0/latest') m0, m0f0 = factory.new_basic_module('child visit', 'child') factory.form_requires_case(m0f0) factory.form_opens_case(m0f0, 'visit', is_subcase=True) m1, m1f0 = factory.new_advanced_module('visit histroy', 'visit', parent_module=m0) factory.form_requires_case(m1f0, 'child') factory.form_requires_case(m1f0, 'visit', parent_case_type='child') m1f1 = factory.new_form(m1) factory.form_requires_case(m1f1, 'child') factory.form_requires_case(m1f1, 'visit', parent_case_type='child') m1f0.post_form_workflow = WORKFLOW_FORM m1f0.form_links = [ FormLink(xpath="true()", form_id=m1f1.unique_id), ] self.assertXmlPartialEqual(self.get_xml('form_link_submodule'), factory.app.create_suite(), "./entry")
def setUp(self): factory = AppFactory(DOMAIN, "App with DR and child modules", build_version='2.53.0') m0, f0 = factory.new_basic_module("case list", "case") factory.form_requires_case(f0) m1, f1 = factory.new_basic_module("child case list", "case", parent_module=m0) m1.parent_select = ParentSelect(active=True, relationship="other", module_id=m0.get_or_create_unique_id()) f2 = factory.new_form(m1) factory.form_requires_case(f1) factory.form_requires_case(f2) m1.search_config = CaseSearch( properties=[CaseSearchProperty(name='name', label={'en': 'Name'})], data_registry="myregistry", data_registry_workflow=REGISTRY_WORKFLOW_LOAD_CASE, ) # link from f1 to f2 (both in the child module) f1.post_form_workflow = WORKFLOW_FORM f1.form_links = [FormLink(form_id=f2.get_unique_id())] factory.app._id = "123" # wrap to have assign_references called self.app = Application.wrap(factory.app.to_json())
def setUpClass(cls): super(UCRAggregationTest, cls).setUpClass() # cleanup any previous data cls._cleanup_data() # setup app factory = AppFactory(domain=cls.domain) # parent case module, incl opening child cases of main type m_parent, f_parent = factory.new_basic_module('Parent Module', cls.parent_case_type) factory.form_opens_case(f_parent, case_type=cls.parent_case_type) factory.form_opens_case(f_parent, case_type=cls.case_type, is_subcase=True) # main module m0, f0 = factory.new_basic_module('A Module', cls.case_type) f1 = factory.new_form(m0) f1.source = cls._get_xform() factory.form_requires_case(f1, case_type=cls.case_type, update={ cp[0]: '/data/{}'.format(cp[0]) for cp in cls.case_properties }) cls.followup_form = f1 cls.app = factory.app cls.app.save() # create form and case ucrs cls.form_data_source = get_form_data_source(cls.app, cls.followup_form) cls.case_data_source = get_case_data_source(cls.app, cls.case_type) cls.parent_case_data_source = get_case_data_source(cls.app, cls.parent_case_type) # create some data - first just create the case cls.parent_case_id = cls._create_parent_case(cls.parent_name) cls.case_id = cls._create_case(cls.parent_case_id) for fu_date in cls.fu_visit_dates: cls._submit_followup_form(cls.case_id, received_on=fu_date) # the closed case causes there to be some data with an end_column cls.closed_case_id = cls._create_closed_case() # populate the UCRs with the data we just created cls.form_adapter = get_indicator_adapter(cls.form_data_source) cls.case_adapter = get_indicator_adapter(cls.case_data_source) cls.parent_case_adapter = get_indicator_adapter(cls.parent_case_data_source) cls.form_adapter.rebuild_table() cls.case_adapter.rebuild_table() cls.parent_case_adapter.rebuild_table() _iteratively_build_table(cls.form_data_source) _iteratively_build_table(cls.case_data_source) _iteratively_build_table(cls.parent_case_data_source) # setup AggregateTableDefinition cls.monthly_aggregate_table_definition = cls._get_monthly_aggregate_table_definition() cls.weekly_aggregate_table_definition = cls._get_weekly_aggregate_table_definition() cls.basic_aggregate_table_definition = cls._get_basic_aggregate_table_definition() # and adapter cls.monthly_adapter = get_indicator_adapter(cls.monthly_aggregate_table_definition)
def setUpClass(cls): super(UCRAggregationTest, cls).setUpClass() # cleanup any previous data cls._cleanup_data() # setup app factory = AppFactory(domain=cls.domain) # parent case module, incl opening child cases of main type m_parent, f_parent = factory.new_basic_module('Parent Module', cls.parent_case_type) factory.form_opens_case(f_parent, case_type=cls.parent_case_type) factory.form_opens_case(f_parent, case_type=cls.case_type, is_subcase=True) # main module m0, f0 = factory.new_basic_module('A Module', cls.case_type) f1 = factory.new_form(m0) f1.source = cls._get_xform() factory.form_requires_case(f1, case_type=cls.case_type, update={ cp[0]: '/data/{}'.format(cp[0]) for cp in cls.case_properties }) cls.followup_form = f1 cls.app = factory.app cls.app.save() # create form and case ucrs cls.form_data_source = get_form_data_source(cls.app, cls.followup_form) cls.case_data_source = get_case_data_source(cls.app, cls.case_type) cls.parent_case_data_source = get_case_data_source(cls.app, cls.parent_case_type) # create some data - first just create the case cls.parent_case_id = cls._create_parent_case(cls.parent_name) cls.case_id = cls._create_case(cls.parent_case_id) for fu_date in cls.fu_visit_dates: cls._submit_followup_form(cls.case_id, received_on=fu_date) # the closed case causes there to be some data with an end_column cls.closed_case_id = cls._create_closed_case() # populate the UCRs with the data we just created cls.form_adapter = get_indicator_adapter(cls.form_data_source) cls.case_adapter = get_indicator_adapter(cls.case_data_source) cls.parent_case_adapter = get_indicator_adapter(cls.parent_case_data_source) cls.form_adapter.rebuild_table() cls.case_adapter.rebuild_table() cls.parent_case_adapter.rebuild_table() _iteratively_build_table(cls.form_data_source) _iteratively_build_table(cls.case_data_source) _iteratively_build_table(cls.parent_case_data_source) # setup AggregateTableDefinition cls.monthly_aggregate_table_definition = cls._get_monthly_aggregate_table_definition() cls.weekly_aggregate_table_definition = cls._get_weekly_aggregate_table_definition() cls.basic_aggregate_table_definition = cls._get_basic_aggregate_table_definition() # and adapter cls.monthly_adapter = get_indicator_adapter(cls.monthly_aggregate_table_definition)
def test_basic_apps(self): for class_ in (Module, AdvancedModule): factory = AppFactory() m1, m1f1 = factory.new_module(class_, 'open_case', 'house') factory.form_opens_case(m1f1) m1f2 = factory.new_form(m1) factory.form_requires_case(m1f2, case_type='house', update={ 'foo': '/data/question1', 'bar': '/data/question2', }) self.assertCaseProperties(factory.app, 'house', ['foo', 'bar'])
def test_basic_apps(self): for class_ in (Module, AdvancedModule): factory = AppFactory() m1, m1f1 = factory.new_module(class_, 'open_case', 'house') factory.form_opens_case(m1f1) m1f2 = factory.new_form(m1) factory.form_requires_case(m1f2, case_type='house', update={ 'foo': '/data/question1', 'bar': '/data/question2', }) self.assertCaseProperties(factory.app, 'house', ['foo', 'bar'])
def test_target_module_different_datums(self): """ * Registration * Register patient form * open case (patient), update user_case * Visits (case type = patient, case list form = 'Register patient') * Visit form * update case, open child case (visit), load from user_case * Record notes * update case, open child case (visit) * Update patient * update case """ factory = AppFactory(build_version='2.9') registration_module, registration_form = factory.new_basic_module('registration', 'patient') factory.form_opens_case(registration_form) factory.form_uses_usercase(registration_form, preload={'username': '******'}) visit_module, visit_form = factory.new_basic_module( 'visits', 'patient', case_list_form=registration_form ) factory.form_requires_case(visit_form) factory.form_opens_case(visit_form, 'visit', is_subcase=True) factory.form_uses_usercase(visit_form, preload={'username': '******'}) notes_form = factory.new_form(visit_module) factory.form_requires_case(notes_form) factory.form_opens_case(notes_form, 'visit', is_subcase=True) update_patient_form = factory.new_form(visit_module) factory.form_requires_case(update_patient_form) self.assertXmlPartialEqual( self.get_xml('target_module_different_datums'), factory.app.create_suite(), './entry')
def test_target_module_different_datums(self): """ * Registration * Register patient form * open case (patient), update user_case * Visits (case type = patient, case list form = 'Register patient') * Visit form * update case, open child case (visit), load from user_case * Record notes * update case, open child case (visit) * Update patient * update case """ factory = AppFactory(build_version='2.9') registration_module, registration_form = factory.new_basic_module( 'registration', 'patient') factory.form_opens_case(registration_form) factory.form_uses_usercase(registration_form, preload={'username': '******'}) visit_module, visit_form = factory.new_basic_module( 'visits', 'patient', case_list_form=registration_form) factory.form_requires_case(visit_form) factory.form_opens_case(visit_form, 'visit', is_subcase=True) factory.form_uses_usercase(visit_form, preload={'username': '******'}) notes_form = factory.new_form(visit_module) factory.form_requires_case(notes_form) factory.form_opens_case(notes_form, 'visit', is_subcase=True) update_patient_form = factory.new_form(visit_module) factory.form_requires_case(update_patient_form) self.assertXmlPartialEqual( self.get_xml('target_module_different_datums'), factory.app.create_suite(), './entry')
def test_form_links_other_child_module(self): # This test demonstrates current behavior that I believe to be flawed factory = AppFactory(build_version='2.9.0') m0, m0f0 = factory.new_basic_module('parent', 'mother') factory.form_opens_case(m0f0) m1, m1f0 = factory.new_basic_module('child', 'baby', parent_module=m0) factory.form_requires_case(m1f0) m0f1 = factory.new_form(m0) m0f1.post_form_workflow = WORKFLOW_FORM m0f1.form_links = [FormLink(xpath='true()', form_id=m1f0.unique_id)] m2, m2f0 = factory.new_basic_module('other_module', 'baby') m2f0.post_form_workflow = WORKFLOW_FORM m2f0.form_links = [FormLink(xpath='true()', form_id=m1f0.unique_id)] suite_xml = factory.app.create_suite() # m0f1 links to m1f0, a form in its child module. Here's the stack for that: expected = """ <partial> <stack> <create if="true()"> <command value="'m0'"/> <command value="'m1'"/> <datum id="case_id_new_mother_0" value="uuid()"/> <datum id="case_id" value="instance('commcaresession')/session/data/case_id"/> <command value="'m1-f0'"/> </create> </stack> </partial> """ self.assertXmlPartialEqual(expected, suite_xml, "./entry[2]/stack") # m2f0 links to m1f0, a form in a separate child module, here's the stack there expected = """ <partial> <stack> <create if="true()"> <command value="'m0'"/> <command value="'m1'"/> <datum id="case_id_new_mother_0" value="uuid()"/> <datum id="case_id" value="instance('commcaresession')/session/data/case_id"/> <command value="'m1-f0'"/> </create> </stack> </partial> """ self.assertXmlPartialEqual(expected, suite_xml, "./entry[4]/stack")
def test_with_case_management_multiple_links(self): factory = AppFactory(build_version='2.9.0/latest') m0, m0f0 = factory.new_basic_module('m0', 'frog') factory.form_opens_case(m0f0) m1, m1f0 = factory.new_basic_module('m1', 'frog') factory.form_requires_case(m1f0) m1f1 = factory.new_form(m1) factory.form_opens_case(m1f1) m0f0.post_form_workflow = WORKFLOW_FORM m0f0.form_links = [ FormLink(xpath="a = 1", form_id=m1f0.unique_id), FormLink(xpath="a = 2", form_id=m1f1.unique_id) ] self.assertXmlPartialEqual(self.get_xml('form_link_multiple'), factory.app.create_suite(), "./entry[1]")
def test_with_case_management_multiple_links(self): factory = AppFactory(build_version='2.9.0/latest') m0, m0f0 = factory.new_basic_module('m0', 'frog') factory.form_opens_case(m0f0) m1, m1f0 = factory.new_basic_module('m1', 'frog') factory.form_requires_case(m1f0) m1f1 = factory.new_form(m1) factory.form_opens_case(m1f1) m0f0.post_form_workflow = WORKFLOW_FORM m0f0.form_links = [ FormLink(xpath="a = 1", form_id=m1f0.unique_id), FormLink(xpath="a = 2", form_id=m1f1.unique_id) ] self.assertXmlPartialEqual(self.get_xml('form_link_multiple'), factory.app.create_suite(), "./entry[1]")
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
def test_case_list_form_advanced_module_different_case_config(self): case_tile_error = { 'type': "all forms in case list module must load the same cases", 'module': {'id': 1, 'name': {u'en': u'update module'}}, 'form': {'id': 1, 'name': {u'en': u'update form 1'}}, } factory = AppFactory(build_version='2.11') m0, m0f0 = factory.new_basic_module('register', 'person') factory.form_opens_case(m0f0) m1, m1f0 = factory.new_advanced_module('update', 'person', case_list_form=m0f0) factory.form_requires_case(m1f0, case_type='house') factory.form_requires_case(m1f0, parent_case_type='house') m1f1 = factory.new_form(m1) factory.form_requires_case(m1f1) # only loads a person case and not a house case errors = factory.app.validate_app() self.assertIn(case_tile_error, errors)
def _build_workflow_app(self, mode): factory = AppFactory(build_version="2.9.0/latest") 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_updates_case(m1f1) m2, m2f0 = factory.new_basic_module("m2", "patient") m2f1 = factory.new_form(m2) factory.form_updates_case(m2f0) factory.form_updates_case(m2f1) m3, m3f0 = factory.new_basic_module("m3", "child") m3f1 = factory.new_form(m3) factory.form_updates_case(m3f0, parent_case_type="patient") factory.form_updates_case(m3f1) m4, m4f0 = factory.new_advanced_module("m4", "patient") factory.form_updates_case(m4f0, case_type="patient") factory.form_updates_case(m4f0, case_type="patient") m4f1 = factory.new_form(m4) factory.form_updates_case(m4f1, case_type="patient") factory.form_updates_case(m4f1, case_type="patient") factory.form_updates_case(m4f1, case_type="patient") m4f2 = factory.new_form(m4) factory.form_updates_case(m4f2, case_type="patient") factory.form_updates_case(m4f2, case_type="patient") factory.advanced_form_autoloads(m4f2, AUTO_SELECT_RAW, "case_id") for module in factory.app.get_modules(): for form in module.get_forms(): form.post_form_workflow = mode return factory.app
def _build_workflow_app(self, mode): factory = AppFactory(build_version='2.9.0/latest') 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') for module in factory.app.get_modules(): for form in module.get_forms(): form.post_form_workflow = mode return factory.app
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."), )
def test(self, mock): add_build(version='2.7.0', build_number=20655) domain = 'form-versioning-test' # set up inital app factory = AppFactory(domain, 'Foo') m0, f0 = factory.new_basic_module("bar", "bar") f0.source = get_simple_form(xmlns='xmlns-0.0') f1 = factory.new_form(m0) f1.source = get_simple_form(xmlns='xmlns-1') app = factory.app app.build_spec = BuildSpec.from_string('2.7.0/latest') app.save() # make a build build1 = app.make_build() build1.save() # modify first form app.get_module(0).get_form(0).source = get_simple_form( xmlns='xmlns-0.1') app.save() # make second build build2 = app.make_build() build2.save() # modify first form app.get_module(0).get_form(0).source = get_simple_form( xmlns='xmlns-0.2') app.save() app.save() app.save() # make third build build3 = app.make_build() build3.save() self.assertEqual(self.get_form_versions(build1), [1, 1]) self.assertEqual(self.get_form_versions(build2), [2, 1]) self.assertEqual(self.get_form_versions(build3), [5, 1]) # revert to build2 app = app.make_reversion_to_copy(build2) app.save() # make reverted build build4 = app.make_build() build4.save() self.assertEqual(self.get_form_versions(build4), [6, 1]) # copy app xxx_app = import_app(app.export_json(dump_json=False), domain) # make build of copy xxx_build1 = xxx_app.make_build() xxx_build1.save() # modify first form of copy app xxx_app.get_module(0).get_form(0).source = get_simple_form( xmlns='xmlns-0.xxx.0') xxx_app.save() # make second build of copy xxx_build2 = xxx_app.make_build() xxx_build2.save() self.assertEqual(self.get_form_versions(xxx_build1), [1, 1]) self.assertEqual(self.get_form_versions(xxx_build2), [2, 1])
class SuiteResourceOverridesTest(TestCase, TestXmlMixin): file_path = ('data', 'suite') def setUp(self): super().setUp() self.factory = AppFactory(build_version='2.40.0') module, form = self.factory.new_basic_module('module0', 'noun') self.factory.new_form(module) self.factory.new_form(module) self.factory.app.save() def test_overrides(self): forms = list(self.factory.app.get_module(0).get_forms()) add_xform_resource_overrides(self.factory.app.domain, self.factory.app.origin_id, { forms[0].unique_id: '123', forms[1].unique_id: '456', }) expected = """ <partial> <xform> <resource descriptor="Form: (Module module0 module) - module0 form 0" id="{}" version="1"> <location authority="local">./modules-0/forms-0.xml</location> <location authority="remote">./modules-0/forms-0.xml</location> </resource> </xform> <xform> <resource descriptor="Form: (Module module0 module) - module0 form 1" id="{}" version="1"> <location authority="local">./modules-0/forms-1.xml</location> <location authority="remote">./modules-0/forms-1.xml</location> </resource> </xform> <xform> <resource descriptor="Form: (Module module0 module) - module0 form 2" id="{}" version="1"> <location authority="local">./modules-0/forms-2.xml</location> <location authority="remote">./modules-0/forms-2.xml</location> </resource> </xform> </partial> """.format('123', '456', forms[2].unique_id) self.assertXmlPartialEqual(expected, self.factory.app.create_suite(), "./xform") def test_duplicate_overrides_raises(self): forms = list(self.factory.app.get_module(0).get_forms()) add_xform_resource_overrides( self.factory.app.domain, self.factory.app.origin_id, { forms[0].unique_id: '123', forms[1].unique_id: '456', forms[2].unique_id: '456', }) with self.assertRaises(ResourceOverrideError): self.factory.app.create_suite() def test_copy_xform_resource_overrides(self): forms = list(self.factory.app.get_module(0).get_forms()) add_xform_resource_overrides(self.factory.app.domain, self.factory.app.origin_id, { forms[0].unique_id: '123', forms[1].unique_id: '456', }) copy_xform_resource_overrides(self.factory.app.domain, self.factory.app.origin_id, { forms[0].unique_id: '321', '123': '987', }) overrides = get_xform_resource_overrides(self.factory.app.domain, self.factory.app.origin_id) self.assertEqual({o.pre_id: o.post_id for o in overrides.values()}, { forms[0].unique_id: '123', forms[1].unique_id: '456', '321': '123', })
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]')
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]' )
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" )