def test_get_casedb_schema_with_deep_hierarchy(self): child = self.add_form("child") parent = self.add_form("parent") self.factory.form_opens_case(parent, case_type='child', is_subcase=True) grandparent = self.add_form("grandparent") self.factory.form_opens_case(grandparent, case_type='parent', is_subcase=True) greatgrandparent = self.add_form("greatgrandparent") self.factory.form_opens_case(greatgrandparent, case_type='grandparent', is_subcase=True) schema = util.get_casedb_schema(child) self.assertEqual( [s["name"] for s in schema["subsets"]], ["child", "parent (parent)", "grandparent (grandparent)"]) schema = util.get_casedb_schema(parent) self.assertEqual([s["name"] for s in schema["subsets"]], [ "parent", "parent (grandparent)", "grandparent (greatgrandparent)" ]) schema = util.get_casedb_schema(grandparent) self.assertEqual([s["name"] for s in schema["subsets"]], ["grandparent", "parent (greatgrandparent)"])
def test_get_case_sharing_hierarchy(self): with patch( 'corehq.apps.app_manager.util.get_case_sharing_apps_in_domain' ) as mock_sharing: mock_sharing.return_value = [self.factory.app, self.factory_2.app] self.factory.app.case_sharing = True self.factory_2.app.case_sharing = True self.add_form("referral") child = self.add_form("child") self.factory.form_opens_case(child, case_type='referral', is_subcase=True) pregnancy = self.add_form("pregnancy") self.factory.form_opens_case(pregnancy, case_type='referral', is_subcase=True) referral_2 = self.add_form_app_2('referral') schema = util.get_casedb_schema(referral_2) subsets = {s["id"]: s for s in schema["subsets"]} self.assertTrue( re.match( r'^parent \((pregnancy|child) or (pregnancy|child)\)$', subsets["parent"]["name"])) self.assertEqual(subsets["parent"]["structure"], {"case_name": { "description": "" }})
def get_form_data_schema(request, domain, form_unique_id): """Get data schema One of `app_id` or `form_unique_id` is required. `app_id` is ignored if `form_unique_id` is provided. :returns: A list of data source schema definitions. A data source schema definition is a dictionary. For details on the content of the dictionary, see https://github.com/dimagi/Vellum/blob/master/src/datasources.js """ data = [] try: form, app = Form.get_form(form_unique_id, and_app=True) except ResourceConflict: raise Http404() if app.domain != domain: raise Http404() try: data.append(get_session_schema(form)) if form.requires_case() or is_usercase_in_use(domain): data.append(get_casedb_schema(form)) except Exception: logger.exception("schema error") return HttpResponseBadRequest("schema error, see log for details") data.extend( sorted(item_lists_by_domain(domain), key=lambda x: x['name'].lower()) ) kw = {} if "pretty" in request.GET: kw["indent"] = 2 return HttpResponse(json.dumps(data, **kw))
def test_get_casedb_schema_with_deep_hierarchy(self): child = self.add_form("child") parent = self.add_form("parent") self.factory.form_opens_case(parent, case_type='child', is_subcase=True) grandparent = self.add_form("grandparent") self.factory.form_opens_case(grandparent, case_type='parent', is_subcase=True) greatgrandparent = self.add_form("greatgrandparent") self.factory.form_opens_case(greatgrandparent, case_type='grandparent', is_subcase=True) schema = util.get_casedb_schema(child) self.assertEqual([s["name"] for s in schema["subsets"]], ["child", "parent (parent)", "grandparent (grandparent)"]) schema = util.get_casedb_schema(parent) self.assertEqual([s["name"] for s in schema["subsets"]], ["parent", "parent (grandparent)", "grandparent (greatgrandparent)"]) schema = util.get_casedb_schema(grandparent) self.assertEqual([s["name"] for s in schema["subsets"]], ["grandparent", "parent (greatgrandparent)"])
def test_get_casedb_schema_with_related_case_types(self): family = self.add_form("family") village = self.add_form("village") self.factory.form_opens_case(village, case_type='family', is_subcase=True) schema = util.get_casedb_schema(family) subsets = {s["id"]: s for s in schema["subsets"]} self.assertEqual(subsets["parent"]["related"], None) self.assertDictEqual(subsets["case"]["related"], {"parent": "parent"})
def test_get_casedb_schema_with_parent_case_property_update(self): family = self.add_form("family", {"parent/has_well": "/data/village_has_well"}) village = self.add_form("village") self.factory.form_opens_case(village, case_type='family', is_subcase=True) schema = util.get_casedb_schema(family) subsets = {s["id"]: s for s in schema["subsets"]} self.assertDictEqual(subsets["case"]["related"], {"parent": "parent"}) self.assertEqual(subsets["case"]["structure"]["case_name"], {}) #self.assertEqual(subsets["parent"]["structure"]["has_well"], {}) TODO self.assertNotIn("parent/has_well", subsets["case"]["structure"])
def test_get_casedb_schema(self): module, form = self.factory.new_basic_module('village', 'village') self.factory.form_uses_usercase(form, update={ 'name': '/data/username', 'role': '/data/userrole', }) schema = util.get_casedb_schema(form) subsets = {s["id"]: s for s in schema["subsets"]} self.assertNotIn(util.USERCASE_TYPE, subsets, repr(subsets))
def test_get_casedb_schema_with_form(self): app = self.make_app() self.add_form(app, "village") schema = util.get_casedb_schema(app) self.assertEqual(len(schema["subsets"]), 1, schema["subsets"]) self.assert_has_kv_pairs(schema["subsets"][0], { 'id': 'village', 'key': '@case_type', 'structure': {'case_name': {}}, 'related': None, })
def test_get_casedb_schema_with_multiple_parent_case_types(self): referral = self.add_form("referral") child = self.add_form("child") self.factory.form_opens_case(child, case_type='referral', is_subcase=True) pregnancy = self.add_form("pregnancy") self.factory.form_opens_case(pregnancy, case_type='referral', is_subcase=True) schema = util.get_casedb_schema(referral) subsets = {s["id"]: s for s in schema["subsets"]} self.assertTrue(re.match(r'^parent \((pregnancy|child) or (pregnancy|child)\)$', subsets["parent"]["name"])) self.assertEqual(subsets["parent"]["structure"], {"case_name": {}})
def test_get_casedb_schema_with_related_case_types(self): app = self.make_app() self.add_form(app, "family") village = self.add_form(app, "village") village.actions.subcases.append( OpenSubCaseAction(case_type='family', reference_id='parent')) schema = util.get_casedb_schema(app) subsets = {s["id"]: s for s in schema["subsets"]} self.assertEqual(subsets["village"]["related"], None) self.assertDictEqual(subsets["family"]["related"], {"parent": "village"})
def test_get_casedb_schema_empty_app(self): app = self.make_app() schema = util.get_casedb_schema(app) self.assert_has_kv_pairs(schema, { "id": "casedb", "uri": "jr://instance/casedb", "name": "case", "path": "/casedb/case", "structure": {}, "subsets": [], })
def test_get_casedb_schema_form_without_cases(self): survey = self.add_form() schema = util.get_casedb_schema(survey) self.assert_has_kv_pairs(schema, { "id": "casedb", "uri": "jr://instance/casedb", "name": "case", "path": "/casedb/case", "structure": {}, "subsets": [], })
def test_get_casedb_schema_empty_app(self): app = self.make_app() schema = util.get_casedb_schema(app) self.assert_has_kv_pairs( schema, { "id": "casedb", "uri": "jr://instance/casedb", "name": "case", "path": "/casedb/case", "structure": {}, "subsets": [], })
def test_get_session_schema_for_child_module(self): # m0 - opens 'gold-fish' case. # m1 - has m0 as root-module, has parent-select, updates 'guppy' case self.module_0, _ = self.factory.new_basic_module('parent', 'gold-fish') self.module_1, _ = self.factory.new_basic_module( 'child', 'guppy', parent_module=self.module_0) # m0f0 registers gold-fish case and a child case ('guppy') m0f0 = self.module_0.get_form(0) self.factory.form_requires_case(m0f0, update={'name': 'goldilocks'}) self.factory.form_opens_case(m0f0, 'guppy', is_subcase=True) # m1f0 has parent-select, updates `guppy` case m1f0 = self.module_1.get_form(0) self.factory.form_requires_case(m1f0, parent_case_type='gold-fish') casedb_schema = util.get_casedb_schema(m1f0) session_schema = util.get_session_schema(m1f0) expected_session_schema_structure = { "case_id_guppy": { "reference": { "subset": "case", "source": "casedb", "key": "@case_id" } } } expected_casedb_schema_subsets = [{ "structure": { "case_name": {} }, "related": { "parent": "parent" }, "id": "case", "key": "@case_type", "name": "guppy" }, { "structure": { "name": {}, "case_name": {} }, "related": None, "id": "parent", "key": "@case_type", "name": "parent (gold-fish)" }] self.assertEqual(casedb_schema['subsets'], expected_casedb_schema_subsets) self.assertEqual(session_schema['structure'], expected_session_schema_structure)
def test_get_session_schema_for_child_module(self): # m0 - opens 'gold-fish' case. # m1 - has m0 as root-module, has parent-select, updates 'guppy' case self.module_0, _ = self.factory.new_basic_module('parent', 'gold-fish') self.module_1, _ = self.factory.new_basic_module('child', 'guppy', parent_module=self.module_0) # m0f0 registers gold-fish case and a child case ('guppy') m0f0 = self.module_0.get_form(0) self.factory.form_requires_case(m0f0, update={'name': 'goldilocks'}) self.factory.form_opens_case(m0f0, 'guppy', is_subcase=True) # m1f0 has parent-select, updates `guppy` case m1f0 = self.module_1.get_form(0) self.factory.form_requires_case(m1f0, parent_case_type='gold-fish') casedb_schema = util.get_casedb_schema(m1f0) session_schema = util.get_session_schema(m1f0) expected_session_schema_structure = { "case_id_guppy": { "reference": { "subset": "case", "source": "casedb", "key": "@case_id" } } } expected_casedb_schema_subsets = [ { "structure": { "case_name": {} }, "related": { "parent": "parent" }, "id": "case", "key": "@case_type", "name": "guppy" }, { "structure": { "name": {}, "case_name": {} }, "related": None, "id": "parent", "key": "@case_type", "name": "parent (gold-fish)" } ] self.assertEqual(casedb_schema['subsets'], expected_casedb_schema_subsets) self.assertEqual(session_schema['structure'], expected_session_schema_structure)
def test_get_casedb_schema_with_related_case_types(self): app = self.make_app() self.add_form(app, "family") village = self.add_form(app, "village") village.actions.subcases.append(OpenSubCaseAction( case_type='family', reference_id='parent' )) schema = util.get_casedb_schema(app) subsets = {s["id"]: s for s in schema["subsets"]} self.assertEqual(subsets["village"]["related"], None) self.assertDictEqual(subsets["family"]["related"], {"parent": "village"})
def test_get_casedb_schema_form_without_cases(self): survey = self.add_form() schema = util.get_casedb_schema(survey) self.assert_has_kv_pairs( schema, { "id": "casedb", "uri": "jr://instance/casedb", "name": "case", "path": "/casedb/case", "structure": {}, "subsets": [], })
def test_get_casedb_schema_with_form(self): village = self.add_form("village") schema = util.get_casedb_schema(village) self.assertEqual(len(schema["subsets"]), 1, schema["subsets"]) self.assert_has_kv_pairs( schema["subsets"][0], { 'id': 'case', 'name': 'village', 'structure': { 'case_name': {} }, 'related': None, })
def test_get_casedb_schema_with_form(self): app = self.make_app() self.add_form(app, "village") schema = util.get_casedb_schema(app) self.assertEqual(len(schema["subsets"]), 1, schema["subsets"]) self.assert_has_kv_pairs( schema["subsets"][0], { 'id': 'village', 'key': '@case_type', 'structure': { 'name': {} }, 'related': None, })
def test_get_casedb_schema_with_multiple_parent_case_types(self): referral = self.add_form("referral") child = self.add_form("child") self.factory.form_opens_case(child, case_type='referral', is_subcase=True) pregnancy = self.add_form("pregnancy") self.factory.form_opens_case(pregnancy, case_type='referral', is_subcase=True) schema = util.get_casedb_schema(referral) subsets = {s["id"]: s for s in schema["subsets"]} self.assertTrue( re.match(r'^parent \((pregnancy|child) or (pregnancy|child)\)$', subsets["parent"]["name"])) self.assertEqual(subsets["parent"]["structure"], {"case_name": {}})
def test_get_case_sharing_hierarchy(self): with patch('corehq.apps.app_manager.util.get_case_sharing_apps_in_domain') as mock_sharing: mock_sharing.return_value = [self.factory.app, self.factory_2.app] self.factory.app.case_sharing = True self.factory_2.app.case_sharing = True self.add_form("referral") child = self.add_form("child") self.factory.form_opens_case(child, case_type='referral', is_subcase=True) pregnancy = self.add_form("pregnancy") self.factory.form_opens_case(pregnancy, case_type='referral', is_subcase=True) referral_2 = self.add_form_app_2('referral') schema = util.get_casedb_schema(referral_2) subsets = {s["id"]: s for s in schema["subsets"]} self.assertTrue(re.match(r'^parent \((pregnancy|child) or (pregnancy|child)\)$', subsets["parent"]["name"])) self.assertEqual(subsets["parent"]["structure"], {"case_name": {}})
def test_get_casedb_schema_with_user_case(self): module, form = self.factory.new_basic_module('village', 'village') self.factory.form_uses_usercase(form, update={ 'name': '/data/username', 'role': '/data/userrole', }) with patch('corehq.apps.app_manager.util.is_usercase_in_use') as mock: mock.return_value = True schema = util.get_casedb_schema(form) subsets = {s["id"]: s for s in schema["subsets"]} self.assertDictEqual( subsets[util.USERCASE_TYPE], { "id": util.USERCASE_TYPE, "key": "@case_type", "name": "user", "structure": { "name": {}, "role": {}, }, })
def get_form_data_schema(request, domain, form_unique_id): """Get data schema One of `app_id` or `form_unique_id` is required. `app_id` is ignored if `form_unique_id` is provided. :returns: A list of data source schema definitions. A data source schema definition is a dictionary with the following format: ``` { "id": string (default instance id) "uri": string (instance src) "path": string (path of root nodeset, not including `instance(...)`) "name": string (human readable name) "structure": { element: { "name": string (optional human readable name) "structure": { nested-element: { ... } }, }, ref-element: { "reference": { "source": string (optional data source id, defaults to this data source) "subset": string (optional subset id) "key": string (referenced property) } }, @attribute: { }, ... }, "subsets": [ { "id": string (unique identifier for this subset) "key": string (unique identifier property name) "name": string (optional human readable name) "structure": { ... } "related": { string (relationship): string (related subset name), ... } }, ... ] } ``` A structure may contain nested structure elements. A nested element may contain one of "structure" (a concrete structure definition) or "reference" (a link to some other structure definition). Any structure item may have a human readable "name". """ data = [] try: form, app = Form.get_form(form_unique_id, and_app=True) except ResourceConflict: raise Http404() if app.domain != domain: raise Http404() try: data.append(get_session_schema(form)) if form and form.requires_case(): data.append(get_casedb_schema(form)) except Exception as e: return HttpResponseBadRequest(e) data.extend( sorted(item_lists_by_domain(domain), key=lambda x: x['name'].lower())) kw = {} if "pretty" in request.GET: kw["indent"] = 2 return HttpResponse(json.dumps(data, **kw))
def get_data_schema(request, domain, app_id=None, form_unique_id=None): """Get data schema One of `app_id` or `form_unique_id` is required. `app_id` is ignored if `form_unique_id` is provided. :returns: A list of data source schema definitions. A data source schema definition is a dictionary with the following format: ``` { "id": string (default instance id) "uri": string (instance src) "path": string (path of root nodeset, not including `instance(...)`) "name": string (human readable name) "structure": { element: { "name": string (optional human readable name) "structure": { nested-element: { ... } }, }, ref-element: { "reference": { "source": string (optional data source id, defaults to this data source) "subset": string (optional subset id) "key": string (referenced property) } }, @attribute: { }, ... }, "subsets": [ { "id": string (unique identifier for this subset) "key": string (unique identifier property name) "name": string (optional human readable name) "structure": { ... } "related": { string (relationship): string (related subset name), ... } }, ... ] } ``` A structure may contain nested structure elements. A nested element may contain one of "structure" (a concrete structure definition) or "reference" (a link to some other structure definition). Any structure item may have a human readable "name". """ data = [] if form_unique_id is None: app = get_app(domain, app_id) form = None else: try: form, app = Form.get_form(form_unique_id, and_app=True) except ResourceConflict: raise Http404() data.append(get_session_schema(form)) if app.domain != domain: raise Http404() data.append(get_casedb_schema(app)) # TODO use domain instead of app data.extend( sorted(item_lists_by_domain(domain), key=lambda x: x['name'].lower()) ) kw = {} if "pretty" in request.GET: kw["indent"] = 2 return HttpResponse(json.dumps(data, **kw))