예제 #1
0
    def setUpClass(cls):
        super(TestBuildingCaseSchemaFromMultipleApplications, cls).setUpClass()
        cls.current_app = Application.wrap(cls.get_json('basic_case_application'))
        cls.other_current_app = Application.wrap(cls.get_json('basic_case_application'))
        cls.other_current_app._id = 'other-app-id'

        cls.first_build = Application.wrap(cls.get_json('basic_case_application'))
        cls.first_build._id = '123'
        cls.first_build.copy_of = cls.current_app.get_id
        cls.first_build.version = 3

        cls.other_build = Application.wrap(cls.get_json('basic_case_application'))
        cls.other_build._id = '456'
        cls.other_build.copy_of = cls.other_current_app._id
        cls.other_build.version = 4
        cls.other_build.has_submissions = True

        cls.apps = [
            cls.current_app,
            cls.other_current_app,
            cls.first_build,
            cls.other_build,
        ]
        with drop_connected_signals(app_post_save):
            for app in cls.apps:
                app.save()
예제 #2
0
    def setUpClass(cls):
        cls.current_app = Application.wrap(cls.get_json('basic_case_application'))

        cls.first_build = Application.wrap(cls.get_json('basic_case_application'))
        cls.first_build._id = '123'
        cls.first_build.copy_of = cls.current_app.get_id
        cls.first_build.version = 3

        cls.apps = [
            cls.current_app,
            cls.first_build,
        ]
        for app in cls.apps:
            app.save()
예제 #3
0
    def setUpClass(cls):
        cls.current_app = Application.wrap(cls.get_json('basic_case_application'))

        cls.first_build = Application.wrap(cls.get_json('basic_case_application'))
        cls.first_build._id = '123'
        cls.first_build.copy_of = cls.current_app.get_id
        cls.first_build.version = 3

        cls.apps = [
            cls.current_app,
            cls.first_build,
        ]
        with drop_connected_signals(app_post_save):
            for app in cls.apps:
                app.save()
    def test_app_icon_permissions(self):
        LOGO_HOME = u'hq_logo_android_home'
        LOGO_LOGIN = u'hq_logo_android_login'

        advanced_sub = Subscription.new_domain_subscription(
            self.account, self.domain.name, self.advanced_plan,
            web_user=self.admin_user.username
        )
        with open(os.path.join(os.path.dirname(__file__), 'data', 'app-commcare-icon-standard.json')) as f:
            standard_source = json.load(f)
        with open(os.path.join(os.path.dirname(__file__), 'data', 'app-commcare-icon-build.json')) as f:
            build_source = json.load(f)

        app_standard = Application.wrap(standard_source)
        app_standard.save()
        self.assertEqual(self.domain.name, app_standard.domain)

        app_build = Application.wrap(build_source)
        app_build.save()
        self.assertEqual(self.domain.name, app_build.domain)

        self.assertTrue(LOGO_HOME in app_standard.logo_refs.keys())
        self.assertTrue(LOGO_LOGIN in app_standard.logo_refs.keys())
        self.assertTrue(LOGO_HOME in app_build.logo_refs.keys())
        self.assertTrue(LOGO_LOGIN in app_build.logo_refs.keys())

        advanced_sub.cancel_subscription(web_user=self.admin_user.username)

        app_standard = Application.get(app_standard._id)
        app_build = Application.get(app_build._id)

        self.assertFalse(LOGO_HOME in app_standard.logo_refs.keys())
        self.assertFalse(LOGO_LOGIN in app_standard.logo_refs.keys())
        self.assertFalse(LOGO_HOME in app_build.logo_refs.keys())
        self.assertFalse(LOGO_LOGIN in app_build.logo_refs.keys())

        Subscription.new_domain_subscription(
            self.account, self.domain.name, self.advanced_plan,
            web_user=self.admin_user.username
        )

        app_standard = Application.get(app_standard._id)
        app_build = Application.get(app_build._id)

        self.assertTrue(LOGO_HOME in app_standard.logo_refs.keys())
        self.assertTrue(LOGO_LOGIN in app_standard.logo_refs.keys())
        self.assertTrue(LOGO_HOME in app_build.logo_refs.keys())
        self.assertTrue(LOGO_LOGIN in app_build.logo_refs.keys())
예제 #5
0
    def test_form_workflow_root(self):
        app = Application.wrap(self.get_json('suite-workflow'))
        for module in app.get_modules():
            for form in module.get_forms():
                form.post_form_workflow = WORKFLOW_ROOT

        self.assertXmlPartialEqual(self.get_xml('suite-workflow-root'), app.create_suite(), "./entry")
예제 #6
0
    def test_form_workflow_module_in_root(self):
        app = Application.wrap(self.get_json('suite-workflow'))
        for m in [1, 2]:
            module = app.get_module(m)
            module.put_in_root = True

        self.assertXmlPartialEqual(self.get_xml('suite-workflow-module-in-root'), app.create_suite(), "./entry")
예제 #7
0
    def test_build_from_saved_schema(self):
        app = self.current_app

        schema = CaseExportDataSchema.generate_schema_from_builds(
            app.domain,
            app._id,
            self.case_type,
        )

        self.assertEqual(schema.last_app_versions[app._id], app.version)
        # One for case, one for case history
        self.assertEqual(len(schema.group_schemas), 2)

        # After the first schema has been saved let's add a second app to process
        second_build = Application.wrap(self.get_json('basic_case_application'))
        second_build._id = '456'
        second_build.copy_of = app.get_id
        second_build.version = 6
        with drop_connected_signals(app_post_save):
            second_build.save()
        self.addCleanup(second_build.delete)

        new_schema = CaseExportDataSchema.generate_schema_from_builds(
            app.domain,
            app._id,
            self.case_type,
        )

        self.assertEqual(new_schema._id, schema._id)
        self.assertEqual(new_schema.last_app_versions[app._id], app.version)
        # One for case, one for case history
        self.assertEqual(len(new_schema.group_schemas), 2)
예제 #8
0
 def testBuildApp(self):
     # do it from a NOT-SAVED app;
     # regression test against case where contents gets lazy-put w/o saving
     app = Application.wrap(self._yesno_source)
     self.assertEqual(app['_id'], None)  # i.e. hasn't been saved
     copy = app.make_build()
     copy.save()
예제 #9
0
 def test_advanced_suite_auto_select_user(self):
     app = Application.wrap(self.get_json('suite-advanced'))
     app.get_module(1).get_form(0).actions.load_update_cases[0].auto_select = AutoSelectCase(
         mode=AUTO_SELECT_USER,
         value_key='case_id'
     )
     self.assertXmlEqual(self.get_xml('suite-advanced-autoselect-user'), app.create_suite())
예제 #10
0
 def test_advanced_suite_auto_select_with_filter(self):
     """
     Form filtering should be done using the last 'non-autoload' case being loaded.
     """
     app = Application.wrap(self.get_json('suite-advanced'))
     app.get_module(1).get_form(0).actions.load_update_cases.append(LoadUpdateAction(
         case_tag='autoload',
         auto_select=AutoSelectCase(
             mode=AUTO_SELECT_USER,
             value_key='case_id'
         )
     ))
     form = app.get_module(1).get_form(0)
     form.form_filter = "./edd = '123'"
     suite = app.create_suite()
     self.assertXmlPartialEqual(self.get_xml('suite-advanced-autoselect-with-filter'), suite, './entry[2]')
     menu = """
     <partial>
       <menu id="m1">
         <text>
           <locale id="modules.m1"/>
         </text>
         <command id="m1-f0" relevant="instance('casedb')/casedb/case[@case_id=instance('commcaresession')/session/data/case_id_case_clinic]/edd = '123'"/>
         <command id="m1-f1"/>
         <command id="m1-f2"/>
         <command id="m1-case-list"/>
       </menu>
     </partial>
     """
     self.assertXmlPartialEqual(menu, suite, "./menu[@id='m1']")
 def test_missing_itext(self):
     self.app = Application.wrap(self.get_json("app_no_itext"))
     self.assert_question_label('question1', 0, 0, "en", "/data/question1")
     try:
         self.do_upload("upload_no_change")
     except Exception as e:
         self.fail(e)
 def test_missing_itext(self):
     self.app = Application.wrap(self.get_json("app_no_itext"))
     self.assert_question_label('question1', 0, 0, "en", "/data/question1")
     try:
         self.upload_raw_excel_translations(self.upload_no_change_headers, self.upload_no_change_data)
     except Exception as e:
         self.fail(e)
예제 #13
0
 def test_advanced_suite_auto_select_raw(self):
     app = Application.wrap(self.get_json('suite-advanced'))
     app.get_module(1).get_form(0).actions.load_update_cases[0].auto_select = AutoSelectCase(
         mode=AUTO_SELECT_RAW,
         value_key='some xpath expression'
     )
     self.assertXmlEqual(self.get_xml('suite-advanced-autoselect-raw'), app.create_suite())
예제 #14
0
 def test_advanced_suite_case_list_filter(self):
     app = Application.wrap(self.get_json('suite-advanced'))
     clinic_module = app.get_module(0)
     clinic_module.case_details.short.filter = "(filter = 'danny')"
     clinic_module_id = clinic_module.unique_id
     app.get_module(1).get_form(0).actions.load_update_cases[0].details_module = clinic_module_id
     self.assertXmlEqual(self.get_xml('suite-advanced-filter'), app.create_suite())
예제 #15
0
    def test_form_workflow_module(self):
        app = Application.wrap(self.get_json('suite-workflow'))
        for module in app.get_modules():
            for form in module.get_forms():
                form.post_form_workflow = WORKFLOW_MODULE

        self.assertXmlEqual(self.get_xml('suite-workflow-module'), app.create_suite())
예제 #16
0
 def test_advanced_suite_auto_select_usercase(self):
     app = Application.wrap(self.get_json('suite-advanced'))
     app.get_module(1).get_form(0).actions.load_update_cases[0].auto_select = AutoSelectCase(
         mode=AUTO_SELECT_USERCASE
     )
     self.assertXmlPartialEqual(self.get_xml('suite-advanced-autoselect-usercase'), app.create_suite(),
                                './entry[2]')
예제 #17
0
    def test_subcase_errors(self):
        with open(os.path.join(os.path.dirname(__file__), "data", "subcase-details.json")) as f:
            source = json.load(f)

        app = Application.wrap(source)
        errors = app.validate_app()
        update_path_error = {
            "type": "path error",
            "path": "/data/parent_age",
            "form_type": "module_form",
            "module": {"name": {"en": "Parent"}, "id": 0},
            "form": {"id": 0, "name": {"en": "Register"}},
        }
        subcase_path_error = {
            "type": "path error",
            "path": "/data/child_age",
            "form_type": "module_form",
            "module": {"name": {"en": "Parent"}, "id": 0},
            "form": {"id": 0, "name": {"en": "Register"}},
        }
        self.assertIn(update_path_error, errors)
        self.assertIn(subcase_path_error, errors)

        form = app.get_module(0).get_form(0)
        errors = form.validate_for_build()
        self.assertIn(update_path_error, errors)
        self.assertIn(subcase_path_error, errors)
예제 #18
0
 def test_advanced_suite_details(self):
     app = Application.wrap(self.get_json('suite-advanced'))
     clinic_module_id = app.get_module(0).unique_id
     other_module_id = app.get_module(1).unique_id
     app.get_module(1).get_form(0).actions.load_update_cases[0].details_module = clinic_module_id
     app.get_module(1).get_form(1).actions.load_update_cases[0].details_module = other_module_id
     self.assertXmlEqual(self.get_xml('suite-advanced-details'), app.create_suite())
예제 #19
0
    def test(self):
        app = Application.wrap(self.get_json('question_schema_test_app'))
        app._id = '123'
        app.version = 1

        xmlns = 'http://openrosa.org/formdesigner/284D3F7C-9C10-48E6-97AC-C37927CBA89A'
        schema = FormQuestionSchema(xmlns=xmlns)

        schema.update_for_app(app)
        self.assertIn(app.get_id, schema.processed_apps)
        self.assertEqual(app.version, schema.last_processed_version)
        self.assertEqual(schema.question_schema['form.multi_root'].options, ['item1', 'item2', 'item3'])
        self.assertEqual(schema.question_schema['form.group1.multi_level1'].options, ['item1', 'item2'])
        self.assertEqual(schema.question_schema['form.group1.question6.multi_level_2'].options, ['item1', 'item2'])
        self.assertEqual(schema.question_schema['form.repeat_1.multi_level_1_repeat'].options, ['item1', 'item2'])
        self.assertEqual(schema.question_schema['form.repeat_1.multi_level_1_repeat'].repeat_context, 'form.repeat_1')

        updated_form_xml = self.get_xml('question_schema_update_form')
        app.get_form_by_xmlns(xmlns).source = updated_form_xml
        app.version = 2

        schema.update_for_app(app)
        self.assertEqual(1, len(schema.processed_apps))
        self.assertIn(app.get_id, schema.processed_apps)
        self.assertEqual(app.version, schema.last_processed_version)
        self.assertEqual(schema.question_schema['form.new_multi'].options, ['z_first', 'a_last'])
        self.assertEqual(schema.question_schema['form.group1.multi_level1'].options, ['item1', 'item2', '1_item'])
예제 #20
0
    def update_schema(self):
        key = [self.domain, self.app_id]
        all_apps = Application.get_db().view(
            'app_manager/saved_app',
            startkey=key + [self.last_processed_version],
            endkey=key + [{}],
            reduce=False,
            include_docs=False,
            skip=(1 if self.last_processed_version else 0)).all()

        all_seen_apps = self.apps_with_errors | self.processed_apps
        to_process = [
            app['id'] for app in all_apps if app['id'] not in all_seen_apps
        ]
        if self.app_id not in all_seen_apps:
            to_process.append(self.app_id)

        for app_doc in iter_docs(Application.get_db(), to_process):
            if app_doc['doc_type'] == 'RemoteApp':
                continue
            app = Application.wrap(app_doc)
            try:
                self.update_for_app(app)
            except AppManagerException:
                self.apps_with_errors.add(app.get_id)
                self.last_processed_version = app.version

        if to_process:
            self.save()
예제 #21
0
    def handle(self, *args, **options):
        path, build_slug = args

        app_slugs = []
        perfpath = os.path.join(path, '{}-performance.txt'.format(build_slug))
        if os.path.exists(perfpath):
            os.remove(perfpath)

        for name in os.listdir(os.path.join(path, 'src')):
            _JSON = '.json'
            if name.endswith(_JSON):
                app_slugs.append(name[:-len(_JSON)])

        for slug in app_slugs:
            print 'Fetching %s...' % slug
            source_path = os.path.join(path, 'src', '%s.json' % slug)
            with open(source_path) as f:
                j = json.load(f)
                if j['doc_type'] == 'Application':
                    app = Application.wrap(j)
                elif j['doc_type'] == 'RemoteApp':
                    app = RemoteApp.wrap(j)

            app.version = 1
            if not app.domain:
                app.domain = "test"
            build_path = os.path.join(path, build_slug, slug)
            print ' Creating files...'
            if options.get('track_perf'):
                with record_performance_stats(perfpath, slug):
                    files = app.create_all_files()
            else:
                files = app.create_all_files()

            self.write_files(files, build_path)
예제 #22
0
 def test_advanced_suite_auto_select_raw(self):
     app = Application.wrap(self.get_json("suite-advanced"))
     app.get_module(1).get_form(0).actions.load_update_cases[0].auto_select = AutoSelectCase(
         mode=AUTO_SELECT_RAW,
         value_key=("some xpath expression " "containing instance('casedb') " "and instance('commcaresession')"),
     )
     self.assertXmlPartialEqual(self.get_xml("suite-advanced-autoselect-raw"), app.create_suite(), "./entry[2]")
예제 #23
0
파일: new.py 프로젝트: bazuzi/commcare-hq
    def generate_schema_from_builds(domain, case_type):
        """Builds a schema from Application builds for a given identifier

        :param domain: The domain that the export belongs to
        :param unique_form_id: The unique identifier of the item being exported
        :returns: Returns a ExportDataSchema instance
        """
        app_build_ids = get_all_app_ids(domain)
        all_case_schema = CaseExportDataSchema()

        for app_doc in iter_docs(Application.get_db(), app_build_ids):
            app = Application.wrap(app_doc)
            case_property_mapping = get_case_properties(
                app,
                [case_type],
                include_parent_properties=False
            )
            case_schema = CaseExportDataSchema._generate_schema_from_case_property_mapping(
                case_property_mapping,
                app.version,
            )
            case_history_schema = CaseExportDataSchema._generate_schema_for_case_history(
                case_property_mapping,
                app.version,
            )

            all_case_schema = CaseExportDataSchema._merge_schemas(
                all_case_schema,
                case_schema,
                case_history_schema
            )

        return all_case_schema
예제 #24
0
    def setUpClass(cls):
        cls.project = Domain(name=cls.domain)
        cls.project.save()
        cls.first_saved_version = 2
        cls.apps = [
            # .wrap adds lots of stuff in, but is hard to call directly
            # this workaround seems to work
            Application.wrap(Application(domain=cls.domain, name="foo", version=1, modules=[Module()]).to_json()),
            RemoteApp.wrap(RemoteApp(domain=cls.domain, version=1, name="bar").to_json()),
        ]
        for app in cls.apps:
            app.save()

        cls.decoy_apps = [
            # this one is a build
            Application(
                domain=cls.domain, copy_of=cls.apps[0].get_id, version=cls.first_saved_version, has_submissions=True
            ),
            # this one is another build
            Application(domain=cls.domain, copy_of=cls.apps[0].get_id, version=12),
            # this one is another app
            Application(domain=cls.domain, copy_of="1234", version=12),
            # this one is in the wrong domain
            Application(domain="decoy-domain", version=5),
        ]
        for app in cls.decoy_apps:
            app.save()
예제 #25
0
    def test_subcase_errors(self):
        with open(os.path.join(os.path.dirname(__file__), 'data', 'subcase-details.json')) as f:
            source = json.load(f)

        app = Application.wrap(source)
        errors = app.validate_app()
        update_path_error = {
            'type': 'path error',
            'path': '/data/parent_age',
            'form_type': 'module_form',
            'module': {'name': {'en': "Parent"}, 'id': 0},
            'form': {'id': 0, 'name': {'en': "Register"}},
        }
        subcase_path_error = {
            'type': 'path error',
            'path': '/data/child_age',
            'form_type': 'module_form',
            'module': {'name': {'en': "Parent"}, 'id': 0},
            'form': {'id': 0, 'name': {'en': "Register"}},
        }
        self.assertIn(update_path_error, errors)
        self.assertIn(subcase_path_error, errors)

        form = app.get_module(0).get_form(0)
        errors = form.validate_for_build()
        self.assertIn(update_path_error, errors)
        self.assertIn(subcase_path_error, errors)
예제 #26
0
    def test_build_from_saved_schema(self):
        app = self.current_app

        schema = FormExportDataSchema.generate_schema_from_builds(
            app.domain,
            app._id,
            'my_sweet_xmlns'
        )

        self.assertEqual(len(schema.group_schemas), 1)
        self.assertEqual(schema.last_app_versions[app._id], self.first_build.version)

        # After the first schema has been saved let's add a second app to process
        second_build = Application.wrap(self.get_json('basic_application'))
        second_build._id = '456'
        second_build.copy_of = app.get_id
        second_build.version = 6
        second_build.has_submissions = True
        second_build.save()
        self.addCleanup(second_build.delete)

        new_schema = FormExportDataSchema.generate_schema_from_builds(
            app.domain,
            app._id,
            'my_sweet_xmlns'
        )

        self.assertEqual(new_schema._id, schema._id)
        self.assertEqual(new_schema.last_app_versions[app._id], second_build.version)
        self.assertEqual(len(new_schema.group_schemas), 1)
예제 #27
0
 def test_advanced_suite_auto_select_fixture(self):
     app = Application.wrap(self.get_json('suite-advanced'))
     app.get_module(1).get_form(0).actions.load_update_cases[0].auto_select = AutoSelectCase(
         mode=AUTO_SELECT_FIXTURE,
         value_source='table_tag',
         value_key='field_name'
     )
     self.assertXmlEqual(self.get_xml('suite-advanced-autoselect-fixture'), app.create_suite())
예제 #28
0
 def test_form_filter(self):
     """
     Ensure form filter gets added correctly and appropriate instances get added to the entry.
     """
     app = Application.wrap(self.get_json('suite-advanced'))
     form = app.get_module(1).get_form(1)
     form.form_filter = "./edd = '123'"
     self.assertXmlEqual(self.get_xml('form-filter'), app.create_suite())
 def test_simple_form_management(self):
     app = Application.wrap(self.get_json('simple_app.json'))
     self.assertEqual('userreports_test', app.domain)
     data_sources = get_form_data_sources(app)
     self.assertEqual(1, len(data_sources))
     data_source = data_sources['http://openrosa.org/formdesigner/AF6F83BA-09A9-4773-9177-AB51EA6CF802']
     for indicator in data_source.configured_indicators:
         self.assertIsNotNone(indicator)
    def test_app_icon_permissions(self):
        LOGO_HOME = 'hq_logo_android_home'
        LOGO_LOGIN = '******'

        advanced_sub = self._subscribe_to_advanced()

        with open(os.path.join(os.path.dirname(__file__), 'data', 'app-commcare-icon-standard.json')) as f:
            standard_source = json.load(f)
        with open(os.path.join(os.path.dirname(__file__), 'data', 'app-commcare-icon-build.json')) as f:
            build_source = json.load(f)

        app_standard = Application.wrap(standard_source)
        app_standard.save()
        self.assertEqual(self.project.name, app_standard.domain)

        app_build = Application.wrap(build_source)
        app_build.save()
        self.assertEqual(self.project.name, app_build.domain)

        self.assertTrue(LOGO_HOME in app_standard.logo_refs)
        self.assertTrue(LOGO_LOGIN in app_standard.logo_refs)
        self.assertTrue(LOGO_HOME in app_build.logo_refs)
        self.assertTrue(LOGO_LOGIN in app_build.logo_refs)

        community_sub = advanced_sub.change_plan(DefaultProductPlan.get_default_plan_version())

        app_standard = Application.get(app_standard._id)
        app_build = Application.get(app_build._id)

        self.assertFalse(LOGO_HOME in app_standard.logo_refs)
        self.assertFalse(LOGO_LOGIN in app_standard.logo_refs)
        self.assertFalse(LOGO_HOME in app_build.logo_refs)
        self.assertFalse(LOGO_LOGIN in app_build.logo_refs)

        community_sub.change_plan(
            DefaultProductPlan.get_default_plan_version(edition=SoftwarePlanEdition.ADVANCED)
        )

        app_standard = Application.get(app_standard._id)
        app_build = Application.get(app_build._id)

        self.assertTrue(LOGO_HOME in app_standard.logo_refs)
        self.assertTrue(LOGO_LOGIN in app_standard.logo_refs)
        self.assertTrue(LOGO_HOME in app_build.logo_refs)
        self.assertTrue(LOGO_LOGIN in app_build.logo_refs)
예제 #31
0
 def test_sort_cache_suite(self):
     app = Application.wrap(self.get_json('suite-advanced'))
     detail = app.modules[0].case_details.short
     detail.sort_elements.append(
         SortElement(
             field=detail.columns[0].field,
             type='index',
             direction='descending',
             blanks='first',
         )
     )
     self.assertXmlPartialEqual(
         self.get_xml('sort-cache'),
         app.create_suite(),
         "./detail[@id='m0_case_short']"
     )
 def test_advanced_suite_load_from_fixture(self):
     nodeset = "instance('item-list:table_tag')/calendar/year/month/day[@date > 735992 and @date < 736000]"
     app = Application.wrap(self.get_json('suite-advanced'))
     app.get_module(1).get_form(0).actions.load_update_cases.append(LoadUpdateAction(
         case_type="clinic",
         load_case_from_fixture=LoadCaseFromFixture(
             fixture_nodeset=nodeset,
             fixture_tag="selected_date",
             fixture_variable="date",
             case_property="adherence_event_date",
             auto_select=True,
         )
     ))
     suite = app.create_suite()
     self.assertXmlPartialEqual(self.get_xml('load_from_fixture_session'), suite, './entry[2]/session')
     self.assertXmlPartialEqual(self.get_xml('load_from_fixture_instance'), suite, './entry[2]/instance')
예제 #33
0
    def test_advanced_suite_case_list_filter(self, *args):
        app = Application.wrap(self.get_json('suite-advanced'))
        clinic_module = app.get_module(0)
        clinic_module.case_details.short.filter = "(filter = 'danny')"
        clinic_module_id = clinic_module.unique_id
        app.get_module(1).get_form(
            0).actions.load_update_cases[0].details_module = clinic_module_id

        req_module = app.get_module(2)
        req_module.case_details.short.filter = "filter = 'this'][other = 'that'"
        req_module_id = req_module.unique_id
        app.get_module(2).get_form(
            0).actions.load_update_cases[0].details_module = req_module_id

        self.assertXmlEqual(self.get_xml('suite-advanced-filter'),
                            app.create_suite())
예제 #34
0
 def test_duplicate_remote_request(self, *args):
     """
     Adding a second search config should not affect the initial one.
     """
     copy_app = Application.wrap(self.app.to_json())
     copy_app.modules.append(Module.wrap(copy_app.modules[0].to_json()))
     with patch(
             'corehq.util.view_utils.get_url_base') as get_url_base_patch:
         get_url_base_patch.return_value = 'https://www.example.com'
         suite = copy_app.create_suite()
     self.assertXmlPartialEqual(
         self.get_xml('remote_request').decode('utf-8').format(
             module_id="m0"), suite, "./remote-request[1]")
     self.assertXmlPartialEqual(
         self.get_xml('remote_request').decode('utf-8').format(
             module_id="m1"), suite, "./remote-request[2]")
예제 #35
0
    def setUp(self):
        self.is_usercase_in_use_patch = patch(
            'corehq.apps.app_manager.models.is_usercase_in_use')
        self.is_usercase_in_use_mock = self.is_usercase_in_use_patch.start()
        self.is_usercase_in_use_mock.return_value = True
        self.app = Application.wrap(self.get_json('suite-advanced'))

        self.module = self.app.get_module(1)
        self.module.has_schedule = True
        self.form_1 = self.module.get_form(0)
        self.form_2 = self.module.get_form(1)
        self.form_3 = self.module.get_form(2)

        self._add_form_abbreviations()
        self._add_form_schedules()
        self._add_form_detail_variable()
    def setUpClass(cls):
        cls.app = Application.wrap(cls.get_json("app"))
        # Todo, refactor this into BulkAppTranslationTestBase.upload_raw_excel_translations
        file = StringIO()
        export_raw(cls.excel_headers,
                   cls.excel_data,
                   file,
                   format=Format.XLS_2007)

        with tempfile.TemporaryFile(suffix='.xlsx') as f:
            f.write(file.getvalue())
            wb_reader = WorkbookJSONReader(f)
            cls.expected_workbook = [{
                'name': ws.title,
                'rows': list(ws)
            } for ws in wb_reader.worksheets]
예제 #37
0
def premature_auto_gps(build):
    app = Application.wrap(build)
    if app.build_version and app.build_version >= LooseVersion('2.14'):
        return

    for module in app.get_modules():
        for form in module.get_forms():
            try:
                built_source = app.fetch_attachment(
                    'files/modules-{}/forms-{}.xml'.format(module.id, form.id))
            except ResourceNotFound:
                continue
            if form.get_auto_gps_capture():
                return 'auto gps error'
            elif XForm(built_source).model_node.find("{orx}pollsensor"):
                return 'auto gps error'
예제 #38
0
    def test_unused_media_removed(self, mock):
        image_path = 'jr://file/commcare/image{}_{}.jpg'
        audio_path = 'jr://file/commcare/audio{}_{}.mp3'
        app = Application.wrap(self.get_json('app'))
        app.domain = self.domain
        app.save()

        for lang in ['en', 'hin']:
            for num in ['1', '2', '3', '4']:
                app.create_mapping(CommCareImage(_id=num), image_path.format(num, lang), save=False)
                app.create_mapping(CommCareAudio(_id=num), audio_path.format(num, lang), save=False)
        app.get_module(0).case_list.show = True
        app.get_module(0).case_list.set_icon('en', image_path.format('4', 'en'))
        app.get_module(0).case_list.set_audio('en', audio_path.format('4', 'en'))

        app.get_module(0).set_icon('en', image_path.format('1', 'en'))
        app.get_module(0).set_audio('en', audio_path.format('1', 'en'))

        app.get_module(0).case_list_form.form_id = app.get_module(0).get_form(0).unique_id
        app.get_module(0).case_list_form.set_icon('en', image_path.format('2', 'en'))
        app.get_module(0).case_list_form.set_audio('en', audio_path.format('2', 'en'))

        app.get_module(0).get_form(0).set_icon('en', image_path.format('3', 'en'))
        app.get_module(0).get_form(0).set_audio('en', audio_path.format('3', 'en'))

        app.save()

        should_contain_media = [image_path.format(num, 'en') for num in [1, 2, 3, 4]] + \
                               [audio_path.format(num, 'en') for num in [1, 2, 3, 4]]
        media_for_removal = [image_path.format(num, 'hin') for num in [1, 2, 3, 4]] + \
                            [audio_path.format(num, 'hin') for num in [1, 2, 3, 4]]
        self.assertTrue(app.get_module(0).uses_media())
        self.assertEqual(app.all_media_paths(), set(should_contain_media))
        self.assertEqual(set(app.multimedia_map.keys()), set(should_contain_media + media_for_removal))
        app.remove_unused_mappings()
        self.assertEqual(set(app.multimedia_map.keys()), set(should_contain_media))

        # test multimedia removed
        app.get_module(0).case_list.set_icon('en', '')
        app.get_module(0).case_list.set_audio('en', '')
        app.get_module(0).set_icon('en', '')
        app.get_module(0).set_audio('en', '')
        app.get_module(0).case_list_form.set_icon('en', '')
        app.get_module(0).case_list_form.set_audio('en', '')
        app.get_module(0).get_form(0).set_icon('en', '')
        app.get_module(0).get_form(0).set_audio('en', '')
        self.assertFalse(list(app.multimedia_map.keys()))
예제 #39
0
    def setUpClass(cls):
        cls.project = Domain(name=cls.domain)
        cls.project.save()

        cls.apps = [
            # .wrap adds lots of stuff in, but is hard to call directly
            # this workaround seems to work
            Application.wrap(
                Application(domain=cls.domain,
                            name='foo',
                            version=1,
                            modules=[Module()]).to_json()),
            RemoteApp.wrap(
                RemoteApp(domain=cls.domain, version=1, name='bar').to_json()),
        ]
        for app in cls.apps:
            app.save()
예제 #40
0
 def test_duplicate_remote_request(self, *args):
     """
     Adding a second search config should not affect the initial one.
     """
     copy_app = Application.wrap(self.app.to_json())
     copy_app.modules.append(Module.wrap(copy_app.modules[0].to_json()))
     suite = copy_app.create_suite()
     self.assertXmlPartialEqual(
         self.get_xml('remote_request').decode('utf-8').format(module_id="m0"),
         suite,
         "./remote-request[1]"
     )
     self.assertXmlPartialEqual(
         self.get_xml('remote_request').decode('utf-8').format(module_id="m1"),
         suite,
         "./remote-request[2]"
     )
예제 #41
0
    def test_case_list_media(self):
        app = Application.wrap(self.get_json('app'))
        app.get_module(0).case_list_form.form_id = app.get_module(0).get_form(
            0).unique_id

        image_path = 'jr://file/commcare/case_list_image.jpg'
        audo_path = 'jr://file/commcare/case_list_audo.mp3'
        app.get_module(0).case_list_form.set_icon('en', image_path)
        app.get_module(0).case_list_form.set_audio('en', audo_path)

        app.create_mapping(CommCareImage(_id='123'), image_path, save=False)
        app.create_mapping(CommCareAudio(_id='456'), audo_path, save=False)

        app.set_media_versions(previous_version=None)

        self.assertXmlEqual(self.get_xml('media_suite'),
                            app.create_media_suite())
예제 #42
0
    def test_build_from_saved_schema(self):
        app = self.current_app

        schema = CaseExportDataSchema.generate_schema_from_builds(
            app.domain,
            app._id,
            self.case_type,
        )

        self.assertEqual(schema.last_app_versions[app._id],
                         self.first_build.version)
        # One for case, one for case history
        self.assertEqual(len(schema.group_schemas), 2)
        self.assertEqual(len(schema.group_schemas[0].items), 2)
        self.assertEqual(len(schema.group_schemas[1].items),
                         len(KNOWN_CASE_PROPERTIES) + 2)

        # After the first schema has been saved let's add a second app to process
        second_build = Application.wrap(
            self.get_json('basic_case_application'))
        second_build._id = '456'
        second_build.copy_of = app.get_id
        second_build.version = 6
        second_build.has_submissions = True
        second_build.get_module(0).get_form(
            0).actions.update_case.update['name'] = ConditionalCaseUpdate(
                question_path='/data/question2')
        with drop_connected_signals(app_post_save):
            second_build.save()
        self.addCleanup(second_build.delete)

        new_schema = CaseExportDataSchema.generate_schema_from_builds(
            app.domain,
            app._id,
            self.case_type,
        )

        self.assertEqual(new_schema._id, schema._id)
        self.assertEqual(new_schema.last_app_versions[app._id],
                         second_build.version)
        # One for case, one for case history
        self.assertEqual(len(new_schema.group_schemas), 2)
        self.assertEqual(len(schema.group_schemas[0].items), 2)
        self.assertEqual(len(schema.group_schemas[1].items),
                         len(KNOWN_CASE_PROPERTIES) + 2)
예제 #43
0
    def migrate_app(self, app_doc):
        modules = [
            m for m in app_doc['modules']
            if m.get('module_type', '') == 'advanced'
        ]
        should_save = False
        for module in modules:
            forms = module['forms']
            for form in forms:
                load_actions = form.get('actions',
                                        {}).get('load_update_cases', [])
                for action in load_actions:
                    preload = action['preload']
                    if preload and list(preload.values())[0].startswith('/'):
                        action['preload'] = {v: k for k, v in preload.items()}
                        should_save = True

        return Application.wrap(app_doc) if should_save else None
예제 #44
0
    def testBuildApp(self, mock):
        # do it from a NOT-SAVED app;
        # regression test against case where contents gets lazy-put w/o saving
        app = Application.wrap(self._yesno_source)
        self.assertEqual(app['_id'], None)  # i.e. hasn't been saved
        app._id = uuid.uuid4().hex
        copy = app.make_build()
        copy.save()
        self._check_has_build_files(copy, self.min_paths)

        app_strings_files = self._app_strings_files(copy)
        self._check_has_build_files(copy, app_strings_files)
        for path in app_strings_files:
            lang = path.split("/")[1]
            data_path = os.path.join(os.path.dirname(__file__), 'data', 'yesno_{}_app_strings.txt'.format(lang))
            with open(data_path, encoding='utf-8') as f:
                self.assertEqual(f.read().strip(), copy.fetch_attachment(path).decode('utf-8').strip())

        self._check_legacy_odk_files(copy)
예제 #45
0
 def test_sort_calculation(self):
     app = Application.wrap(self.get_json('suite-advanced'))
     detail = app.modules[0].case_details.short
     detail.sort_elements.append(
         SortElement(field=detail.columns[0].field,
                     type='string',
                     direction='descending',
                     sort_calculation='random()'))
     sort_node = """
     <partial>
         <sort direction="descending" order="1" type="string">
           <text>
             <xpath function="random()"/>
           </text>
         </sort>
     </partial>
     """
     self.assertXmlPartialEqual(sort_node, app.create_suite(),
                                "./detail[@id='m0_case_short']/field/sort")
예제 #46
0
 def test_advanced_suite_load_case_from_fixture_with_report_fixture(self):
     app = Application.wrap(self.get_json('suite-advanced'))
     app.get_module(1).get_form(0).actions.load_update_cases.append(
         LoadUpdateAction(
             case_tag="",
             case_type="clinic",
             load_case_from_fixture=LoadCaseFromFixture(
                 fixture_nodeset=
                 "instance('commcare:reports')/reports/report[@id='some-report-guid']/rows/row",
                 fixture_tag="selected_row",
                 fixture_variable="index",
             )))
     suite = app.create_suite()
     self.assertXmlPartialEqual(
         self.get_xml('load_case_from_report_fixture_session'), suite,
         './entry[2]/session')
     self.assertXmlPartialEqual(
         self.get_xml('load_case_from_report_fixture_instance'), suite,
         './entry[2]/instance')
예제 #47
0
 def test_case_tile_configuration_errors(self):
     case_tile_error = {
         'type': "invalid tile configuration",
         'module': {
             'id': 0,
             'name': {
                 u'en': u'View'
             }
         },
         'reason':
         'A case property must be assigned to the "sex" tile field.'
     }
     with open(
             os.path.join(os.path.dirname(__file__), 'data',
                          'bad_case_tile_config.json')) as f:
         source = json.load(f)
         app = Application.wrap(source)
         errors = app.validate_app()
         self.assertIn(case_tile_error, errors)
예제 #48
0
 def test_sort_cache_search(self):
     app = Application.wrap(self.get_json('suite-advanced'))
     app.modules[0].search_config = CaseSearch(
         properties=[CaseSearchProperty(name='name', label={'en': 'Name'})],
     )
     detail = app.modules[0].case_details.short
     detail.sort_elements.append(
         SortElement(
             field=detail.columns[0].field,
             type='index',
             direction='descending',
             blanks='first',
         )
     )
     self.assertXmlPartialEqual(
         self.get_xml('sort-cache-search'),
         app.create_suite(),
         "./detail[@id='m0_search_short']"
     )
 def migrate_app(self, app_doc):
     app = Application.wrap(app_doc)
     metadata = app.get_case_metadata()
     for case_type in metadata.case_types:
         if case_type.has_errors:
             logger.error('app {} has issue'.format(app._id))
     for module in app.modules:
         for form in module.forms:
             if form.doc_type == 'AdvancedForm':
                 # advanced forms don't have the same actions
                 return None
             actions = form.actions
             if actions.case_preload:
                 for action in actions.case_preload.preload.values():
                     log_excessive_parents(app, action)
             if actions.update_case:
                 for action in actions.update_case.update:
                     log_excessive_parents(app, action)
     return None
예제 #50
0
    def test_form_media_with_app_profile(self, *args):
        # Test that media for languages not in the profile are removed from the media suite

        app = Application.wrap(self.get_json('app'))
        app.build_profiles = OrderedDict({
            'en': BuildProfile(langs=['en'], name='en-profile'),
            'hin': BuildProfile(langs=['hin'], name='hin-profile'),
            'all': BuildProfile(langs=['en', 'hin'], name='all-profile'),
        })
        app.langs = ['en', 'hin']

        image_path = 'jr://file/commcare/module0_en.png'
        audio_path = 'jr://file/commcare/module0_{}.mp3'
        app.get_module(0).set_icon('en', image_path)
        app.get_module(0).set_audio('en', audio_path.format('en'))
        app.get_module(0).set_audio('hin', audio_path.format('hin'))

        app.create_mapping(CommCareImage(_id='123'), image_path, save=False)
        app.create_mapping(CommCareAudio(_id='456'), audio_path.format('en'), save=False)
        app.create_mapping(CommCareAudio(_id='789'), audio_path.format('hin'), save=False)

        form_xml = self.get_xml('form_with_media_refs').decode('utf-8')
        form = app.get_module(0).new_form('form_with_media', 'en', attachment=form_xml)
        xform = form.wrapped_xform()
        for i, path in enumerate(reversed(sorted(xform.media_references(form="audio")))):
            app.create_mapping(CommCareAudio(_id='form_audio_{}'.format(i)), path, save=False)
        for i, path in enumerate(sorted(xform.media_references(form="image"))):
            app.create_mapping(CommCareImage(_id='form_image_{}'.format(i)), path, save=False)

        app.set_media_versions()
        app.remove_unused_mappings()

        # includes all media
        self._assertMediaSuiteResourcesEqual(self.get_xml('form_media_suite'), app.create_media_suite())

        # generate all suites at once to mimic create_build_files_for_all_app_profiles
        suites = {id: app.create_media_suite(build_profile_id=id) for id in app.build_profiles.keys()}

        # include all app media and only language-specific form media
        self._assertMediaSuiteResourcesEqual(self.get_xml('form_media_suite_en'), suites['en'])
        self._assertMediaSuiteResourcesEqual(self.get_xml('form_media_suite_hin'), suites['hin'])
        self._assertMediaSuiteResourcesEqual(self.get_xml('form_media_suite_all'), suites['all'])
예제 #51
0
    def testRevertToCopy(self, mock):
        old_name = 'old name'
        new_name = 'new name'
        app = Application.wrap(self._yesno_source)
        app.name = old_name
        app.save()

        copy = app.make_build()
        copy.save()

        self.assertEqual(copy.name, old_name)

        app.name = new_name
        app.save()
        app = Application.get(app.get_id)
        self.assertEqual(app.name, new_name)

        app = app.make_reversion_to_copy(copy)
        app.save()
        self.assertEqual(app.name, old_name)
예제 #52
0
    def test_media_suite_generator(self):
        app = Application.wrap(self.get_json('app_video_inline'))
        image_path = 'jr://file/commcare/image1.jpg'
        audio_path = 'jr://file/commcare/audio1.mp3'
        video_path = 'jr://file/commcare/video-inline/data/inline_video.mp4'
        app.create_mapping(CommCareImage(_id='123'), image_path, save=False)
        app.create_mapping(CommCareAudio(_id='456'), audio_path, save=False)
        app.create_mapping(CommCareVideo(_id='789'), video_path, save=False)
        app.get_module(0).case_list_form.set_icon('en', image_path)
        app.get_module(0).case_list_form.set_audio('en', audio_path)
        app.get_module(0).case_list_form.form_id = app.get_module(0).get_form(
            0).unique_id

        app.profile["properties"] = {'lazy-load-video-files': 'true'}
        self.assertXmlEqual(self.get_xml('media-suite-lazy-true'),
                            MediaSuiteGenerator(app).generate_suite())

        app.profile["properties"] = {'lazy-load-video-files': 'false'}
        self.assertXmlEqual(self.get_xml('media-suite-lazy-false'),
                            MediaSuiteGenerator(app).generate_suite())
예제 #53
0
    def test_only_default_properties(self, *args):
        self.module.search_config = CaseSearch(
            default_properties=[
                DefaultCaseSearchProperty(
                    property='ɨŧsȺŧɍȺᵽ',
                    defaultValue=(
                        "instance('casedb')/case"
                        "[@case_id='instance('commcaresession')/session/data/case_id']"
                        "/ɨŧsȺŧɍȺᵽ")
                ),
                DefaultCaseSearchProperty(
                    property='name',
                    defaultValue="instance('locations')/locations/location[@id=123]/@type",
                ),
            ],
        )

        # wrap to have assign_references called
        self.app = Application.wrap(self.app.to_json())
        suite = self.app.create_suite()
        self.assertXmlPartialEqual(self.get_xml('search_config_default_only'), suite, "./remote-request[1]")
예제 #54
0
    def test_update_image_id(self):
        """
        When an image is updated, change only version number, not resource id
        """
        app = Application.wrap(self.get_json('app'))
        image_path = 'jr://file/commcare/case_list_image.jpg'
        app.get_module(0).case_list_form.set_icon('en', image_path)

        app.version = 1
        app.create_mapping(CommCareImage(_id='123'), image_path, save=False)
        app.set_media_versions(previous_version=None)
        old_app = deepcopy(app)

        app.version = 2
        app.create_mapping(CommCareImage(_id='456'), image_path, save=False)
        app.set_media_versions(previous_version=old_app)

        old_image = old_app.multimedia_map[image_path]
        new_image = app.multimedia_map[image_path]
        self.assertEqual(old_image.unique_id, new_image.unique_id)
        self.assertNotEqual(old_image.version, new_image.version)
예제 #55
0
 def test_advanced_suite_arbitrary_datum(self, *args):
     app = Application.wrap(self.get_json('suite-advanced'))
     app.get_module(1).get_form(0).arbitrary_datums = [
         ArbitraryDatum(datum_id='extra_id1',
                        datum_function='extra_function1()'),
         ArbitraryDatum(datum_id='extra_id2',
                        datum_function='extra_function2()')
     ]
     suite = app.create_suite()
     self.assertXmlPartialEqual(
         """
         <partial>
             <session>
                 <datum detail-confirm="m1_case_long" detail-select="m1_case_short" id="case_id_case_clinic"
                        nodeset="instance('casedb')/casedb/case[@case_type='clinic'][@status='open']"
                        value="./@case_id"/>
                 <datum id="extra_id1" function="extra_function1()" />
                 <datum id="extra_id2" function="extra_function2()" />
             </session>
         </partial>
         """, suite, './entry[2]/session')
예제 #56
0
    def setUpClass(cls):
        cls.project = Domain(name=cls.domain)
        cls.project.save()

        app_doc = Application(domain=cls.domain,
                              name='foo',
                              langs=["en"],
                              version=1,
                              modules=[Module()]).to_json()
        app = Application.wrap(app_doc)  # app is v1

        app.save()  # app is v2
        cls.v2_build = app.make_build()
        cls.v2_build.is_released = True
        cls.v2_build.save()  # There is a starred build at v2

        app.save()  # app is v3
        app.make_build().save()  # There is a build at v3

        app.save()  # app is v4
        cls.app_id = app._id
예제 #57
0
    def test(self):
        app = Application.wrap(self.get_json('question_schema_test_app'))
        app._id = '123'
        app.version = 1

        xmlns = 'http://openrosa.org/formdesigner/284D3F7C-9C10-48E6-97AC-C37927CBA89A'
        schema = FormQuestionSchema(xmlns=xmlns)

        schema.update_for_app(app)
        self.assertIn(app.get_id, schema.processed_apps)
        self.assertEqual(app.version, schema.last_processed_version)
        self.assertEqual(schema.question_schema['form.multi_root'].options,
                         ['item1', 'item2', 'item3'])
        self.assertEqual(
            schema.question_schema['form.group1.multi_level1'].options,
            ['item1', 'item2'])
        self.assertEqual(
            schema.question_schema['form.group1.question6.multi_level_2'].
            options, ['item1', 'item2'])
        self.assertEqual(
            schema.question_schema['form.repeat_1.multi_level_1_repeat'].
            options, ['item1', 'item2'])
        self.assertEqual(
            schema.question_schema['form.repeat_1.multi_level_1_repeat'].
            repeat_context, 'form.repeat_1')

        updated_form_xml = self.get_xml('question_schema_update_form').decode(
            'utf-8')
        app.get_forms_by_xmlns(xmlns)[0].source = updated_form_xml
        app.version = 2

        schema.update_for_app(app)
        self.assertEqual(1, len(schema.processed_apps))
        self.assertIn(app.get_id, schema.processed_apps)
        self.assertEqual(app.version, schema.last_processed_version)
        self.assertEqual(schema.question_schema['form.new_multi'].options,
                         ['z_first', 'a_last'])
        self.assertEqual(
            schema.question_schema['form.group1.multi_level1'].options,
            ['item1', 'item2', '1_item'])
예제 #58
0
    def get(self, request, *args, **kwargs):
        app_id = get_app_id_from_hash(request.domain, kwargs.pop('app_hash'))

        if not app_id:
            raise Http404()

        app_doc = get_latest_released_app_doc(request.domain, app_id)

        if not app_doc:
            raise Http404()

        app = Application.wrap(app_doc)

        if not app.anonymous_cloudcare_enabled:
            raise Http404()

        return self.render_to_response({
            'app': app,
            'formplayer_url': settings.FORMPLAYER_URL,
            "maps_api_key": settings.GMAPS_API_KEY,
            "environment": WEB_APPS_ENVIRONMENT,
        })
예제 #59
0
    def setUpClass(cls):
        super(DBAccessorsTest, cls).setUpClass()
        cls.project = Domain(name=cls.domain)
        cls.project.save()
        cls.first_saved_version = 2
        cls.apps = [
            # .wrap adds lots of stuff in, but is hard to call directly
            # this workaround seems to work
            Application.wrap(
                Application(domain=cls.domain,
                            name='foo',
                            version=1,
                            modules=[Module()]).to_json()),
            RemoteApp.wrap(
                RemoteApp(domain=cls.domain, version=1, name='bar').to_json()),
        ]
        for app in cls.apps:
            app.save()

        cls.decoy_apps = [
            # this one is a build
            Application(
                domain=cls.domain,
                copy_of=cls.apps[0].get_id,
                version=cls.first_saved_version,
                has_submissions=True,
            ),
            # this one is another build
            Application(domain=cls.domain,
                        copy_of=cls.apps[0].get_id,
                        version=12),

            # this one is another app
            Application(domain=cls.domain, copy_of='1234', version=12),
            # this one is in the wrong domain
            Application(domain='decoy-domain', version=5)
        ]
        for app in cls.decoy_apps:
            app.save()
예제 #60
0
    def _test_format(self, detail_format, template_form):
        app = Application.wrap(self.get_json('app_audio_format'))
        details = app.get_module(0).case_details
        details.short.get_column(0).format = detail_format
        details.long.get_column(0).format = detail_format

        expected = """
        <partial>
          <template form="{0}">
            <text>
              <xpath function="picproperty"/>
            </text>
          </template>
          <template form="{0}">
            <text>
              <xpath function="picproperty"/>
            </text>
          </template>
        </partial>
        """.format(template_form)
        self.assertXmlPartialEqual(expected, app.create_suite(),
                                   "./detail/field/template")