Example #1
0
 def test_flat_sync_format(self, uses_locations):
     with flag_enabled('SYNC_ALL_LOCATIONS'):
         with flag_enabled('FLAT_LOCATION_FIXTURE'):
             self._assert_fixture_has_locations(
                 'expand_from_root_flat',
                 ['Massachusetts', 'Suffolk', 'Middlesex', 'Boston', 'Revere', 'Cambridge',
                  'Somerville', 'New York', 'New York City', 'Manhattan', 'Queens', 'Brooklyn'],
                 flat=True,
             )
Example #2
0
 def test_should_sync_flat_format_disabled_toggle(self):
     location_settings = LocationFixtureConfiguration.objects.create(
         domain='some-domain', sync_flat_fixture=False
     )
     self.addCleanup(location_settings.delete)
     with flag_enabled('FLAT_LOCATION_FIXTURE'):
         self.assertEqual(False, should_sync_flat_fixture('some-domain'))
Example #3
0
    def test_location_instances(self):
        self.form.form_filter = "instance('locations')/locations/"
        with flag_enabled('FLAT_LOCATION_FIXTURE'):
            self.assertXmlPartialEqual(
                u"""
                <partial>
                    <instance id='locations' src='jr://fixture/locations' />
                </partial>
                """,
                self.factory.app.create_suite(),
                "entry/instance")

        self.assertXmlPartialEqual(
            u"""
            <partial>
                <instance id='locations' src='jr://fixture/commtrack:locations' />
            </partial>
            """,
            self.factory.app.create_suite(),
            "entry/instance"
        )

        self.form.form_filter = "instance('commtrack:locations')/locations/"
        self.assertXmlPartialEqual(
            u"""
            <partial>
                <instance id='commtrack:locations' src='jr://fixture/commtrack:locations' />
            </partial>
            """,
            self.factory.app.create_suite(),
            "entry/instance"
        )
 def test_all_locations_flag_returns_all_locations(self):
     with flag_enabled('SYNC_ALL_LOCATIONS'):
         self._assert_fixture_matches_file(
             'expand_from_root',
             ['Massachusetts', 'Suffolk', 'Middlesex', 'Boston', 'Revere', 'Cambridge',
              'Somerville', 'New York', 'New York City', 'Manhattan', 'Queens', 'Brooklyn']
         )
Example #5
0
 def test_opened_on(self):
     case = self.factory.create_case()
     new_date = '2015-04-30T14:41:53.000000Z'
     with flag_enabled('BULK_UPLOAD_DATE_OPENED'):
         self.import_mock_file([
             ['case_id', 'date_opened'],
             [case.case_id, new_date]
         ])
     case = CaseAccessors(self.domain).get_case(case.case_id)
     self.assertEqual(case.opened_on, PhoneTime(parse_datetime(new_date)).done())
Example #6
0
    def test_use_default_media(self):
        self.module.use_default_image_for_all = True
        self.module.use_default_audio_for_all = True

        self.module.set_icon('en', self.image_path)
        self.module.set_audio('en', self.audio_path)
        self.module.set_icon('hin', 'jr://file/commcare/case_list_image_hin.jpg')
        self.module.set_audio('hin', 'jr://file/commcare/case_list_audio_hin.mp3')

        with flag_enabled('LANGUAGE_LINKED_MULTIMEDIA'):
            en_app_strings = commcare_translations.loads(self.app.create_app_strings('en'))
            hin_app_strings = commcare_translations.loads(self.app.create_app_strings('hin'))
        self.assertEqual(en_app_strings['modules.m0.icon'], hin_app_strings['modules.m0.icon'])
        self.assertEqual(en_app_strings['modules.m0.audio'], hin_app_strings['modules.m0.audio'])
Example #7
0
 def test_should_sync_hierarchical_format_disabled(self):
     domain = uuid.uuid4().hex
     project = Domain(name=domain)
     project.save()
     location_type = LocationType.objects.create(domain=domain, name='test-type')
     location_settings = LocationFixtureConfiguration.objects.create(
         domain=domain, sync_hierarchical_fixture=False
     )
     self.assertEqual(False, should_sync_hierarchical_fixture(project))
     with flag_enabled('FLAT_LOCATION_FIXTURE'):
         self.assertEqual(False, should_sync_hierarchical_fixture(project))
     self.addCleanup(project.delete)
     self.addCleanup(location_type.delete)
     self.addCleanup(location_settings.delete)
Example #8
0
    def _do_submit(self, xml_data, dict_attachments, sync_token=None, date=None):
        """
        RequestFactory submitter - simulates direct submission to server
        directly (no need to call process case after fact)
        """
        with flag_enabled('MM_CASE_PROPERTIES'):
            result = submit_form_locally(
                xml_data,
                TEST_DOMAIN_NAME,
                attachments=dict_attachments,
                last_sync_token=sync_token,
                received_on=date
            )
        attachments = result.xform.attachments
        self.assertEqual(set(dict_attachments.keys()),
                         set(attachments.keys()))
        self.assertEqual(result.case.case_id, TEST_CASE_ID)

        return result.response, result.xform, result.cases
Example #9
0
 def test_case_detail_tabs_with_nodesets(self):
     with flag_enabled('DISPLAY_CONDITION_ON_TABS'):
         self._test_generic_suite("app_case_detail_tabs_with_nodesets", 'suite-case-detail-tabs-with-nodesets')
Example #10
0
def test_contractor():
    user = CouchUser(username="******")
    with flag_enabled('IS_CONTRACTOR'):
        assert_true(is_superuser_or_contractor(user))
Example #11
0
class ImporterTest(TestCase):

    def setUp(self):
        super(ImporterTest, self).setUp()
        self.domain_obj = create_domain("importer-test")
        self.domain = self.domain_obj.name
        self.default_case_type = 'importer-test-casetype'

        self.couch_user = WebUser.create(None, "test", "foobar")
        self.couch_user.add_domain_membership(self.domain, is_admin=True)
        self.couch_user.save()

        self.accessor = CaseAccessors(self.domain)

        self.factory = CaseFactory(domain=self.domain, case_defaults={
            'case_type': self.default_case_type,
        })
        delete_all_cases()

    def tearDown(self):
        self.couch_user.delete()
        self.domain_obj.delete()
        super(ImporterTest, self).tearDown()

    def _config(self, col_names, search_column=None, case_type=None,
                search_field='case_id', create_new_cases=True):
        return ImporterConfig(
            couch_user_id=self.couch_user._id,
            case_type=case_type or self.default_case_type,
            excel_fields=col_names,
            case_fields=[''] * len(col_names),
            custom_fields=col_names,
            search_column=search_column or col_names[0],
            search_field=search_field,
            create_new_cases=create_new_cases,
        )

    @run_with_all_backends
    @patch('corehq.apps.case_importer.tasks.bulk_import_async.update_state')
    def testImportNone(self, update_state):
        res = bulk_import_async.delay(self._config(['anything']), self.domain, None)
        self.assertIsInstance(res.result, Ignore)
        update_state.assert_called_with(
            state=states.FAILURE,
            meta={'errors': 'Sorry, your session has expired. Please start over and try again.'})
        self.assertEqual(0, len(get_case_ids_in_domain(self.domain)))

    @run_with_all_backends
    def testImportBasic(self):
        config = self._config(['case_id', 'age', 'sex', 'location'])
        file = make_worksheet_wrapper(
            ['case_id', 'age', 'sex', 'location'],
            ['case_id-0', 'age-0', 'sex-0', 'location-0'],
            ['case_id-1', 'age-1', 'sex-1', 'location-1'],
            ['case_id-2', 'age-2', 'sex-2', 'location-2'],
            ['case_id-3', 'age-3', 'sex-3', 'location-3'],
            ['case_id-4', 'age-4', 'sex-4', 'location-4'],
        )
        res = do_import(file, config, self.domain)
        self.assertEqual(5, res['created_count'])
        self.assertEqual(0, res['match_count'])
        self.assertFalse(res['errors'])
        self.assertEqual(1, res['num_chunks'])
        case_ids = self.accessor.get_case_ids_in_domain()
        cases = list(self.accessor.get_cases(case_ids))
        self.assertEqual(5, len(cases))
        properties_seen = set()
        for case in cases:
            self.assertEqual(self.couch_user._id, case.user_id)
            self.assertEqual(self.couch_user._id, case.owner_id)
            self.assertEqual(self.default_case_type, case.type)
            for prop in ['age', 'sex', 'location']:
                self.assertTrue(prop in case.get_case_property(prop))
                self.assertFalse(case.get_case_property(prop) in properties_seen)
                properties_seen.add(case.get_case_property(prop))

    @run_with_all_backends
    def testImportNamedColumns(self):
        config = self._config(['case_id', 'age', 'sex', 'location'])
        file = make_worksheet_wrapper(
            ['case_id', 'age', 'sex', 'location'],
            ['case_id-0', 'age-0', 'sex-0', 'location-0'],
            ['case_id-1', 'age-1', 'sex-1', 'location-1'],
            ['case_id-2', 'age-2', 'sex-2', 'location-2'],
            ['case_id-3', 'age-3', 'sex-3', 'location-3'],
        )
        res = do_import(file, config, self.domain)

        self.assertEqual(4, res['created_count'])
        self.assertEqual(4, len(self.accessor.get_case_ids_in_domain()))

    @run_with_all_backends
    def testImportTrailingWhitespace(self):
        cols = ['case_id', 'age', 'sex\xa0', 'location']
        config = self._config(cols)
        file = make_worksheet_wrapper(
            ['case_id', 'age', 'sex\xa0', 'location'],
            ['case_id-0', 'age-0', 'sex\xa0-0', 'location-0'],
        )
        res = do_import(file, config, self.domain)

        self.assertEqual(1, res['created_count'])
        case_ids = self.accessor.get_case_ids_in_domain()
        self.assertEqual(1, len(case_ids))
        case = self.accessor.get_case(case_ids[0])
        self.assertTrue(bool(case.get_case_property('sex')))  # make sure the value also got properly set

    @run_with_all_backends
    def testCaseIdMatching(self):
        # bootstrap a stub case
        [case] = self.factory.create_or_update_case(CaseStructure(attrs={
            'create': True,
            'update': {'importer_test_prop': 'foo'},
        }))
        self.assertEqual(1, len(self.accessor.get_case_ids_in_domain()))

        config = self._config(['case_id', 'age', 'sex', 'location'])
        file = make_worksheet_wrapper(
            ['case_id', 'age', 'sex', 'location'],
            [case.case_id, 'age-0', 'sex-0', 'location-0'],
            [case.case_id, 'age-1', 'sex-1', 'location-1'],
            [case.case_id, 'age-2', 'sex-2', 'location-2'],
        )
        res = do_import(file, config, self.domain)
        self.assertEqual(0, res['created_count'])
        self.assertEqual(3, res['match_count'])
        self.assertFalse(res['errors'])

        # shouldn't create any more cases, just the one
        case_ids = self.accessor.get_case_ids_in_domain()
        self.assertEqual(1, len(case_ids))
        [case] = self.accessor.get_cases(case_ids)
        for prop in ['age', 'sex', 'location']:
            self.assertTrue(prop in case.get_case_property(prop))

        # shouldn't touch existing properties
        self.assertEqual('foo', case.get_case_property('importer_test_prop'))

    @run_with_all_backends
    def testCaseLookupTypeCheck(self):
        [case] = self.factory.create_or_update_case(CaseStructure(attrs={
            'create': True,
            'case_type': 'nonmatch-type',
        }))
        self.assertEqual(1, len(self.accessor.get_case_ids_in_domain()))
        config = self._config(['case_id', 'age', 'sex', 'location'])
        file = make_worksheet_wrapper(
            ['case_id', 'age', 'sex', 'location'],
            [case.case_id, 'age-0', 'sex-0', 'location-0'],
            [case.case_id, 'age-1', 'sex-1', 'location-1'],
            [case.case_id, 'age-2', 'sex-2', 'location-2'],
        )
        res = do_import(file, config, self.domain)
        # because the type is wrong these shouldn't match
        self.assertEqual(3, res['created_count'])
        self.assertEqual(0, res['match_count'])
        self.assertEqual(4, len(self.accessor.get_case_ids_in_domain()))

    @run_with_all_backends
    def testCaseLookupDomainCheck(self):
        self.factory.domain = 'wrong-domain'
        [case] = self.factory.create_or_update_case(CaseStructure(attrs={
            'create': True,
        }))
        self.assertEqual(0, len(self.accessor.get_case_ids_in_domain()))
        config = self._config(['case_id', 'age', 'sex', 'location'])
        file = make_worksheet_wrapper(
            ['case_id', 'age', 'sex', 'location'],
            [case.case_id, 'age-0', 'sex-0', 'location-0'],
            [case.case_id, 'age-1', 'sex-1', 'location-1'],
            [case.case_id, 'age-2', 'sex-2', 'location-2'],
        )
        res = do_import(file, config, self.domain)

        # because the domain is wrong these shouldn't match
        self.assertEqual(3, res['created_count'])
        self.assertEqual(0, res['match_count'])
        self.assertEqual(3, len(self.accessor.get_case_ids_in_domain()))

    @run_with_all_backends
    def testExternalIdMatching(self):
        # bootstrap a stub case
        external_id = 'importer-test-external-id'
        [case] = self.factory.create_or_update_case(CaseStructure(
            attrs={
                'create': True,
                'external_id': external_id,
            }
        ))
        self.assertEqual(1, len(self.accessor.get_case_ids_in_domain()))

        headers = ['external_id', 'age', 'sex', 'location']
        config = self._config(headers, search_field='external_id')
        file = make_worksheet_wrapper(
            ['external_id', 'age', 'sex', 'location'],
            ['importer-test-external-id', 'age-0', 'sex-0', 'location-0'],
            ['importer-test-external-id', 'age-1', 'sex-1', 'location-1'],
            ['importer-test-external-id', 'age-2', 'sex-2', 'location-2'],
        )
        res = do_import(file, config, self.domain)
        self.assertEqual(0, res['created_count'])
        self.assertEqual(3, res['match_count'])
        self.assertFalse(res['errors'])

        # shouldn't create any more cases, just the one
        self.assertEqual(1, len(self.accessor.get_case_ids_in_domain()))

    @run_with_all_backends
    def test_external_id_matching_on_create_with_custom_column_name(self):
        headers = ['id_column', 'age', 'sex', 'location']
        external_id = 'external-id-test'
        config = self._config(headers[1:], search_column='id_column', search_field='external_id')
        file = make_worksheet_wrapper(
            ['id_column', 'age', 'sex', 'location'],
            ['external-id-test', 'age-0', 'sex-0', 'location-0'],
            ['external-id-test', 'age-1', 'sex-1', 'location-1'],
        )

        res = do_import(file, config, self.domain)
        self.assertFalse(res['errors'])
        self.assertEqual(1, res['created_count'])
        self.assertEqual(1, res['match_count'])
        case_ids = self.accessor.get_case_ids_in_domain()
        self.assertEqual(1, len(case_ids))
        case = self.accessor.get_case(case_ids[0])
        self.assertEqual(external_id, case.external_id)

    def testNoCreateNew(self):
        config = self._config(['case_id', 'age', 'sex', 'location'], create_new_cases=False)
        file = make_worksheet_wrapper(
            ['case_id', 'age', 'sex', 'location'],
            ['case_id-0', 'age-0', 'sex-0', 'location-0'],
            ['case_id-1', 'age-1', 'sex-1', 'location-1'],
            ['case_id-2', 'age-2', 'sex-2', 'location-2'],
            ['case_id-3', 'age-3', 'sex-3', 'location-3'],
            ['case_id-4', 'age-4', 'sex-4', 'location-4'],
        )
        res = do_import(file, config, self.domain)

        # no matching and no create new set - should do nothing
        self.assertEqual(0, res['created_count'])
        self.assertEqual(0, res['match_count'])
        self.assertEqual(0, len(get_case_ids_in_domain(self.domain)))

    def testBlankRows(self):
        # don't create new cases for rows left blank
        config = self._config(['case_id', 'age', 'sex', 'location'], create_new_cases=True)
        file = make_worksheet_wrapper(
            ['case_id', 'age', 'sex', 'location'],
            [None, None, None, None],
            ['', '', '', ''],
        )
        res = do_import(file, config, self.domain)

        # no matching and no create new set - should do nothing
        self.assertEqual(0, res['created_count'])
        self.assertEqual(0, res['match_count'])
        self.assertEqual(0, len(get_case_ids_in_domain(self.domain)))

    @patch('corehq.apps.case_importer.do_import.CASEBLOCK_CHUNKSIZE', 2)
    def testBasicChunking(self):
        config = self._config(['case_id', 'age', 'sex', 'location'])
        file = make_worksheet_wrapper(
            ['case_id', 'age', 'sex', 'location'],
            ['case_id-0', 'age-0', 'sex-0', 'location-0'],
            ['case_id-1', 'age-1', 'sex-1', 'location-1'],
            ['case_id-2', 'age-2', 'sex-2', 'location-2'],
            ['case_id-3', 'age-3', 'sex-3', 'location-3'],
            ['case_id-4', 'age-4', 'sex-4', 'location-4'],
        )
        res = do_import(file, config, self.domain)
        # 5 cases in chunks of 2 = 3 chunks
        self.assertEqual(3, res['num_chunks'])
        self.assertEqual(5, res['created_count'])
        self.assertEqual(5, len(get_case_ids_in_domain(self.domain)))

    @run_with_all_backends
    def testExternalIdChunking(self):
        # bootstrap a stub case
        external_id = 'importer-test-external-id'

        headers = ['external_id', 'age', 'sex', 'location']
        config = self._config(headers, search_field='external_id')
        file = make_worksheet_wrapper(
            ['external_id', 'age', 'sex', 'location'],
            ['importer-test-external-id', 'age-0', 'sex-0', 'location-0'],
            ['importer-test-external-id', 'age-1', 'sex-1', 'location-1'],
            ['importer-test-external-id', 'age-2', 'sex-2', 'location-2'],
        )

        # the first one should create the case, and the remaining two should update it
        res = do_import(file, config, self.domain)
        self.assertEqual(1, res['created_count'])
        self.assertEqual(2, res['match_count'])
        self.assertFalse(res['errors'])
        self.assertEqual(2, res['num_chunks']) # the lookup causes an extra chunk

        # should just create the one case
        case_ids = self.accessor.get_case_ids_in_domain()
        self.assertEqual(1, len(case_ids))
        [case] = self.accessor.get_cases(case_ids)
        self.assertEqual(external_id, case.external_id)
        for prop in ['age', 'sex', 'location']:
            self.assertTrue(prop in case.get_case_property(prop))

    @run_with_all_backends
    def testParentCase(self):
        headers = ['parent_id', 'name', 'case_id']
        config = self._config(headers, create_new_cases=True, search_column='case_id')
        rows = 3
        [parent_case] = self.factory.create_or_update_case(CaseStructure(attrs={'create': True}))
        self.assertEqual(1, len(self.accessor.get_case_ids_in_domain()))

        file = make_worksheet_wrapper(
            ['parent_id', 'name', 'case_id'],
            [parent_case.case_id, 'name-0', 'case_id-0'],
            [parent_case.case_id, 'name-1', 'case_id-1'],
            [parent_case.case_id, 'name-2', 'case_id-2'],
        )
        file_missing = make_worksheet_wrapper(
            ['parent_id', 'name', 'case_id'],
            ['parent_id-0', 'name-0', 'case_id-0'],
            ['parent_id-1', 'name-1', 'case_id-1'],
            ['parent_id-2', 'name-2', 'case_id-2'],
        )

        # Should successfully match on `rows` cases
        res = do_import(file, config, self.domain)
        self.assertEqual(rows, res['created_count'])

        # Should be unable to find parent case on `rows` cases
        res = do_import(file_missing, config, self.domain)
        error_column_name = 'parent_id'
        self.assertEqual(rows,
                         len(res['errors'][exceptions.InvalidParentId.title][error_column_name]['rows']),
                         "All cases should have missing parent")

    def import_mock_file(self, rows):
        config = self._config(rows[0])
        xls_file = make_worksheet_wrapper(*rows)
        return do_import(xls_file, config, self.domain)

    @run_with_all_backends
    def testLocationOwner(self):
        # This is actually testing several different things, but I figure it's
        # worth it, as each of these tests takes a non-trivial amount of time.
        non_case_sharing = LocationType.objects.create(
            domain=self.domain, name='lt1', shares_cases=False
        )
        case_sharing = LocationType.objects.create(
            domain=self.domain, name='lt2', shares_cases=True
        )
        location = make_loc('loc-1', 'Loc 1', self.domain, case_sharing.code)
        make_loc('loc-2', 'Loc 2', self.domain, case_sharing.code)
        duplicate_loc = make_loc('loc-3', 'Loc 2', self.domain, case_sharing.code)
        improper_loc = make_loc('loc-4', 'Loc 4', self.domain, non_case_sharing.code)

        res = self.import_mock_file([
            ['case_id', 'name', 'owner_id', 'owner_name'],
            ['', 'location-owner-id', location.group_id, ''],
            ['', 'location-owner-code', '', location.site_code],
            ['', 'location-owner-name', '', location.name],
            ['', 'duplicate-location-name', '', duplicate_loc.name],
            ['', 'non-case-owning-name', '', improper_loc.name],
        ])
        case_ids = self.accessor.get_case_ids_in_domain()
        cases = {c.name: c for c in list(self.accessor.get_cases(case_ids))}

        self.assertEqual(cases['location-owner-id'].owner_id, location.group_id)
        self.assertEqual(cases['location-owner-code'].owner_id, location.group_id)
        self.assertEqual(cases['location-owner-name'].owner_id, location.group_id)

        error_message = exceptions.DuplicateLocationName.title
        error_column_name = None
        self.assertIn(error_message, res['errors'])
        self.assertEqual(res['errors'][error_message][error_column_name]['rows'], [5])

        error_message = exceptions.InvalidOwnerId.title
        self.assertIn(error_message, res['errors'])
        error_column_name = 'owner_id'
        self.assertEqual(res['errors'][error_message][error_column_name]['rows'], [6])

    @run_with_all_backends
    def test_opened_on(self):
        case = self.factory.create_case()
        new_date = '2015-04-30T14:41:53.000000Z'
        with flag_enabled('BULK_UPLOAD_DATE_OPENED'):
            self.import_mock_file([
                ['case_id', 'date_opened'],
                [case.case_id, new_date]
            ])
        case = CaseAccessors(self.domain).get_case(case.case_id)
        self.assertEqual(case.opened_on, PhoneTime(parse_datetime(new_date)).done())
Example #12
0
 def test_should_sync_flat_format_default_toggle(self):
     with flag_enabled('FLAT_LOCATION_FIXTURE'):
         self.assertEqual(True, should_sync_flat_fixture('some-domain'))
Example #13
0
 def test_wrong_password(self):
     wrong_credentials = self._get_basic_credentials(self.web_user.username, 'wrong_password')
     with flag_enabled('ODATA'):
         response = self._execute_query(wrong_credentials)
     self.assertEqual(response.status_code, 401)
Example #14
0
class ImporterTest(TestCase):
    def setUp(self):
        super(ImporterTest, self).setUp()
        self.domain_obj = create_domain("importer-test")
        self.domain = self.domain_obj.name
        self.default_case_type = 'importer-test-casetype'

        self.couch_user = WebUser.create(None, "test", "foobar", None, None)
        self.couch_user.add_domain_membership(self.domain, is_admin=True)
        self.couch_user.save()

        self.accessor = CaseAccessors(self.domain)

        self.factory = CaseFactory(domain=self.domain,
                                   case_defaults={
                                       'case_type': self.default_case_type,
                                   })
        delete_all_cases()

    def tearDown(self):
        self.couch_user.delete(deleted_by=None)
        self.domain_obj.delete()
        super(ImporterTest, self).tearDown()

    def _config(self,
                col_names,
                search_column=None,
                case_type=None,
                search_field='case_id',
                create_new_cases=True):
        return ImporterConfig(
            couch_user_id=self.couch_user._id,
            case_type=case_type or self.default_case_type,
            excel_fields=col_names,
            case_fields=[''] * len(col_names),
            custom_fields=col_names,
            search_column=search_column or col_names[0],
            search_field=search_field,
            create_new_cases=create_new_cases,
        )

    @run_with_all_backends
    @patch('corehq.apps.case_importer.tasks.bulk_import_async.update_state')
    def testImportFileMissing(self, update_state):
        # by using a made up upload_id, we ensure it's not referencing any real file
        case_upload = CaseUploadRecord(upload_id=str(uuid.uuid4()),
                                       task_id=str(uuid.uuid4()))
        case_upload.save()
        res = bulk_import_async.delay(self._config(['anything']), self.domain,
                                      case_upload.upload_id)
        self.assertIsInstance(res.result, Ignore)
        update_state.assert_called_with(
            state=states.FAILURE,
            meta=get_interned_exception(
                'Sorry, your session has expired. Please start over and try again.'
            ))
        self.assertEqual(0, len(get_case_ids_in_domain(self.domain)))

    @run_with_all_backends
    def testImportBasic(self):
        config = self._config(['case_id', 'age', 'sex', 'location'])
        file = make_worksheet_wrapper(
            ['case_id', 'age', 'sex', 'location'],
            ['case_id-0', 'age-0', 'sex-0', 'location-0'],
            ['case_id-1', 'age-1', 'sex-1', 'location-1'],
            ['case_id-2', 'age-2', 'sex-2', 'location-2'],
            ['case_id-3', 'age-3', 'sex-3', 'location-3'],
            ['case_id-4', 'age-4', 'sex-4', 'location-4'],
        )
        res = do_import(file, config, self.domain)
        self.assertEqual(5, res['created_count'])
        self.assertEqual(0, res['match_count'])
        self.assertFalse(res['errors'])
        self.assertEqual(1, res['num_chunks'])
        case_ids = self.accessor.get_case_ids_in_domain()
        cases = list(self.accessor.get_cases(case_ids))
        self.assertEqual(5, len(cases))
        properties_seen = set()
        for case in cases:
            self.assertEqual(self.couch_user._id, case.user_id)
            self.assertEqual(self.couch_user._id, case.owner_id)
            self.assertEqual(self.default_case_type, case.type)
            for prop in ['age', 'sex', 'location']:
                self.assertTrue(prop in case.get_case_property(prop))
                self.assertFalse(
                    case.get_case_property(prop) in properties_seen)
                properties_seen.add(case.get_case_property(prop))

    @run_with_all_backends
    def testCreateCasesWithDuplicateExternalIds(self):
        config = self._config(
            ['case_id', 'age', 'sex', 'location', 'external_id'])
        file = make_worksheet_wrapper(
            ['case_id', 'age', 'sex', 'location', 'external_id'],
            ['case_id-0', 'age-0', 'sex-0', 'location-0', 'external_id-0'],
            ['case_id-1', 'age-1', 'sex-1', 'location-1', 'external_id-0'],
            ['case_id-2', 'age-2', 'sex-2', 'location-2', 'external_id-1'],
        )
        res = do_import(file, config, self.domain)
        self.assertEqual(3, res['created_count'])
        self.assertEqual(0, res['match_count'])
        self.assertFalse(res['errors'])
        case_ids = self.accessor.get_case_ids_in_domain()
        self.assertItemsEqual(
            [case.external_id for case in self.accessor.get_cases(case_ids)],
            ['external_id-0', 'external_id-0', 'external_id-1'])

    @run_with_all_backends
    def testImportNamedColumns(self):
        config = self._config(['case_id', 'age', 'sex', 'location'])
        file = make_worksheet_wrapper(
            ['case_id', 'age', 'sex', 'location'],
            ['case_id-0', 'age-0', 'sex-0', 'location-0'],
            ['case_id-1', 'age-1', 'sex-1', 'location-1'],
            ['case_id-2', 'age-2', 'sex-2', 'location-2'],
            ['case_id-3', 'age-3', 'sex-3', 'location-3'],
        )
        res = do_import(file, config, self.domain)

        self.assertEqual(4, res['created_count'])
        self.assertEqual(4, len(self.accessor.get_case_ids_in_domain()))

    @run_with_all_backends
    def testImportTrailingWhitespace(self):
        cols = ['case_id', 'age', 'sex\xa0', 'location']
        config = self._config(cols)
        file = make_worksheet_wrapper(
            ['case_id', 'age', 'sex\xa0', 'location'],
            ['case_id-0', 'age-0', 'sex\xa0-0', 'location-0'],
        )
        res = do_import(file, config, self.domain)

        self.assertEqual(1, res['created_count'])
        case_ids = self.accessor.get_case_ids_in_domain()
        self.assertEqual(1, len(case_ids))
        case = self.accessor.get_case(case_ids[0])
        self.assertTrue(bool(case.get_case_property(
            'sex')))  # make sure the value also got properly set

    @run_with_all_backends
    def testCaseIdMatching(self):
        # bootstrap a stub case
        [case] = self.factory.create_or_update_case(
            CaseStructure(attrs={
                'create': True,
                'update': {
                    'importer_test_prop': 'foo'
                },
            }))
        self.assertEqual(1, len(self.accessor.get_case_ids_in_domain()))

        config = self._config(['case_id', 'age', 'sex', 'location'])
        file = make_worksheet_wrapper(
            ['case_id', 'age', 'sex', 'location'],
            [case.case_id, 'age-0', 'sex-0', 'location-0'],
            [case.case_id, 'age-1', 'sex-1', 'location-1'],
            [case.case_id, 'age-2', 'sex-2', 'location-2'],
        )
        res = do_import(file, config, self.domain)
        self.assertEqual(0, res['created_count'])
        self.assertEqual(3, res['match_count'])
        self.assertFalse(res['errors'])

        # shouldn't create any more cases, just the one
        case_ids = self.accessor.get_case_ids_in_domain()
        self.assertEqual(1, len(case_ids))
        [case] = self.accessor.get_cases(case_ids)
        for prop in ['age', 'sex', 'location']:
            self.assertTrue(prop in case.get_case_property(prop))

        # shouldn't touch existing properties
        self.assertEqual('foo', case.get_case_property('importer_test_prop'))

    @run_with_all_backends
    def testCaseLookupTypeCheck(self):
        [case] = self.factory.create_or_update_case(
            CaseStructure(attrs={
                'create': True,
                'case_type': 'nonmatch-type',
            }))
        self.assertEqual(1, len(self.accessor.get_case_ids_in_domain()))
        config = self._config(['case_id', 'age', 'sex', 'location'])
        file = make_worksheet_wrapper(
            ['case_id', 'age', 'sex', 'location'],
            [case.case_id, 'age-0', 'sex-0', 'location-0'],
            [case.case_id, 'age-1', 'sex-1', 'location-1'],
            [case.case_id, 'age-2', 'sex-2', 'location-2'],
        )
        res = do_import(file, config, self.domain)
        # because the type is wrong these shouldn't match
        self.assertEqual(3, res['created_count'])
        self.assertEqual(0, res['match_count'])
        self.assertEqual(4, len(self.accessor.get_case_ids_in_domain()))

    @run_with_all_backends
    def testCaseLookupDomainCheck(self):
        self.factory.domain = 'wrong-domain'
        [case] = self.factory.create_or_update_case(
            CaseStructure(attrs={
                'create': True,
            }))
        self.assertEqual(0, len(self.accessor.get_case_ids_in_domain()))
        config = self._config(['case_id', 'age', 'sex', 'location'])
        file = make_worksheet_wrapper(
            ['case_id', 'age', 'sex', 'location'],
            [case.case_id, 'age-0', 'sex-0', 'location-0'],
            [case.case_id, 'age-1', 'sex-1', 'location-1'],
            [case.case_id, 'age-2', 'sex-2', 'location-2'],
        )
        res = do_import(file, config, self.domain)

        # because the domain is wrong these shouldn't match
        self.assertEqual(3, res['created_count'])
        self.assertEqual(0, res['match_count'])
        self.assertEqual(3, len(self.accessor.get_case_ids_in_domain()))

    @run_with_all_backends
    def testExternalIdMatching(self):
        # bootstrap a stub case
        external_id = 'importer-test-external-id'
        [case] = self.factory.create_or_update_case(
            CaseStructure(attrs={
                'create': True,
                'external_id': external_id,
            }))
        self.assertEqual(1, len(self.accessor.get_case_ids_in_domain()))

        headers = ['external_id', 'age', 'sex', 'location']
        config = self._config(headers, search_field='external_id')
        file = make_worksheet_wrapper(
            ['external_id', 'age', 'sex', 'location'],
            ['importer-test-external-id', 'age-0', 'sex-0', 'location-0'],
            ['importer-test-external-id', 'age-1', 'sex-1', 'location-1'],
            ['importer-test-external-id', 'age-2', 'sex-2', 'location-2'],
        )
        res = do_import(file, config, self.domain)
        self.assertEqual(0, res['created_count'])
        self.assertEqual(3, res['match_count'])
        self.assertFalse(res['errors'])

        # shouldn't create any more cases, just the one
        self.assertEqual(1, len(self.accessor.get_case_ids_in_domain()))

    @run_with_all_backends
    def test_external_id_matching_on_create_with_custom_column_name(self):
        headers = ['id_column', 'age', 'sex', 'location']
        external_id = 'external-id-test'
        config = self._config(headers[1:],
                              search_column='id_column',
                              search_field='external_id')
        file = make_worksheet_wrapper(
            ['id_column', 'age', 'sex', 'location'],
            ['external-id-test', 'age-0', 'sex-0', 'location-0'],
            ['external-id-test', 'age-1', 'sex-1', 'location-1'],
        )

        res = do_import(file, config, self.domain)
        self.assertFalse(res['errors'])
        self.assertEqual(1, res['created_count'])
        self.assertEqual(1, res['match_count'])
        case_ids = self.accessor.get_case_ids_in_domain()
        self.assertEqual(1, len(case_ids))
        case = self.accessor.get_case(case_ids[0])
        self.assertEqual(external_id, case.external_id)

    def testNoCreateNew(self):
        config = self._config(['case_id', 'age', 'sex', 'location'],
                              create_new_cases=False)
        file = make_worksheet_wrapper(
            ['case_id', 'age', 'sex', 'location'],
            ['case_id-0', 'age-0', 'sex-0', 'location-0'],
            ['case_id-1', 'age-1', 'sex-1', 'location-1'],
            ['case_id-2', 'age-2', 'sex-2', 'location-2'],
            ['case_id-3', 'age-3', 'sex-3', 'location-3'],
            ['case_id-4', 'age-4', 'sex-4', 'location-4'],
        )
        res = do_import(file, config, self.domain)

        # no matching and no create new set - should do nothing
        self.assertEqual(0, res['created_count'])
        self.assertEqual(0, res['match_count'])
        self.assertEqual(0, len(get_case_ids_in_domain(self.domain)))

    def testBlankRows(self):
        # don't create new cases for rows left blank
        config = self._config(['case_id', 'age', 'sex', 'location'],
                              create_new_cases=True)
        file = make_worksheet_wrapper(
            ['case_id', 'age', 'sex', 'location'],
            [None, None, None, None],
            ['', '', '', ''],
        )
        res = do_import(file, config, self.domain)

        # no matching and no create new set - should do nothing
        self.assertEqual(0, res['created_count'])
        self.assertEqual(0, res['match_count'])
        self.assertEqual(0, len(get_case_ids_in_domain(self.domain)))

    @patch('corehq.apps.case_importer.do_import.CASEBLOCK_CHUNKSIZE', 2)
    def testBasicChunking(self):
        config = self._config(['case_id', 'age', 'sex', 'location'])
        file = make_worksheet_wrapper(
            ['case_id', 'age', 'sex', 'location'],
            ['case_id-0', 'age-0', 'sex-0', 'location-0'],
            ['case_id-1', 'age-1', 'sex-1', 'location-1'],
            ['case_id-2', 'age-2', 'sex-2', 'location-2'],
            ['case_id-3', 'age-3', 'sex-3', 'location-3'],
            ['case_id-4', 'age-4', 'sex-4', 'location-4'],
        )
        res = do_import(file, config, self.domain)
        # 5 cases in chunks of 2 = 3 chunks
        self.assertEqual(3, res['num_chunks'])
        self.assertEqual(5, res['created_count'])
        self.assertEqual(5, len(get_case_ids_in_domain(self.domain)))

    @run_with_all_backends
    def testExternalIdChunking(self):
        # bootstrap a stub case
        external_id = 'importer-test-external-id'

        headers = ['external_id', 'age', 'sex', 'location']
        config = self._config(headers, search_field='external_id')
        file = make_worksheet_wrapper(
            ['external_id', 'age', 'sex', 'location'],
            ['importer-test-external-id', 'age-0', 'sex-0', 'location-0'],
            ['importer-test-external-id', 'age-1', 'sex-1', 'location-1'],
            ['importer-test-external-id', 'age-2', 'sex-2', 'location-2'],
        )

        # the first one should create the case, and the remaining two should update it
        res = do_import(file, config, self.domain)
        self.assertEqual(1, res['created_count'])
        self.assertEqual(2, res['match_count'])
        self.assertFalse(res['errors'])
        self.assertEqual(2,
                         res['num_chunks'])  # the lookup causes an extra chunk

        # should just create the one case
        case_ids = self.accessor.get_case_ids_in_domain()
        self.assertEqual(1, len(case_ids))
        [case] = self.accessor.get_cases(case_ids)
        self.assertEqual(external_id, case.external_id)
        for prop in ['age', 'sex', 'location']:
            self.assertTrue(prop in case.get_case_property(prop))

    @run_with_all_backends
    def testParentCase(self):
        headers = ['parent_id', 'name', 'case_id']
        config = self._config(headers,
                              create_new_cases=True,
                              search_column='case_id')
        rows = 3
        [parent_case] = self.factory.create_or_update_case(
            CaseStructure(attrs={'create': True}))
        self.assertEqual(1, len(self.accessor.get_case_ids_in_domain()))

        file = make_worksheet_wrapper(
            ['parent_id', 'name', 'case_id'],
            [parent_case.case_id, 'name-0', 'case_id-0'],
            [parent_case.case_id, 'name-1', 'case_id-1'],
            [parent_case.case_id, 'name-2', 'case_id-2'],
        )

        # Should successfully match on `rows` cases
        res = do_import(file, config, self.domain)
        self.assertEqual(rows, res['created_count'])
        # Should create child cases
        self.assertEqual(
            len(self.accessor.get_reverse_indexed_cases([parent_case.case_id
                                                         ])), 3)
        self.assertEqual(
            self.accessor.get_extension_case_ids([parent_case.case_id]), [])

        file_missing = make_worksheet_wrapper(
            ['parent_id', 'name', 'case_id'],
            ['parent_id-0', 'name-0', 'case_id-0'],
            ['parent_id-1', 'name-1', 'case_id-1'],
            ['parent_id-2', 'name-2', 'case_id-2'],
        )

        # Should be unable to find parent case on `rows` cases
        res = do_import(file_missing, config, self.domain)
        error_column_name = 'parent_id'
        self.assertEqual(
            rows,
            len(res['errors'][exceptions.InvalidParentId.title]
                [error_column_name]['rows']),
            "All cases should have missing parent")

    @run_with_all_backends
    def testExtensionCase(self):
        headers = [
            'parent_id', 'name', 'case_id', 'parent_relationship_type',
            'parent_identifier'
        ]
        config = self._config(headers,
                              create_new_cases=True,
                              search_column='case_id')
        [parent_case] = self.factory.create_or_update_case(
            CaseStructure(attrs={'create': True}))
        self.assertEqual(1, len(self.accessor.get_case_ids_in_domain()))

        file = make_worksheet_wrapper(
            headers,
            [parent_case.case_id, 'name-0', 'case_id-0', 'extension', 'host'],
            [
                parent_case.case_id, 'name-1', 'case_id-1', 'extension',
                'mother'
            ],
            [parent_case.case_id, 'name-2', 'case_id-2', 'child', 'parent'],
        )

        # Should successfully match on `rows` cases
        res = do_import(file, config, self.domain)
        self.assertEqual(res['created_count'], 3)
        # Of the 3, 2 should be extension cases
        extension_case_ids = self.accessor.get_extension_case_ids(
            [parent_case.case_id])
        self.assertEqual(len(extension_case_ids), 2)
        extension_cases = self.accessor.get_cases(extension_case_ids)
        # Check that identifier is set correctly
        self.assertEqual({'host', 'mother'},
                         {c.indices[0].identifier
                          for c in extension_cases})

    # This test will only run on SQL backend because of a bug in couch backend
    # that overrides current domain with the 'domain' column value from excel
    @override_settings(TESTS_SHOULD_USE_SQL_BACKEND=True)
    @flag_enabled('DOMAIN_PERMISSIONS_MIRROR')
    def test_multiple_domain_case_import(self):
        mirror_domain1 = DomainPermissionsMirror(source=self.domain,
                                                 mirror='mirrordomain1')
        mirror_domain2 = DomainPermissionsMirror(source=self.domain,
                                                 mirror='mirrordomain2')
        mirror_domain1.save()
        mirror_domain2.save()
        headers_with_domain = ['case_id', 'name', 'artist', 'domain']
        config_1 = self._config(headers_with_domain,
                                create_new_cases=True,
                                search_column='case_id')
        case_with_domain_file = make_worksheet_wrapper(
            ['case_id', 'name', 'artist', 'domain'],
            ['', 'name-0', 'artist-0', self.domain],
            ['', 'name-1', 'artist-1', mirror_domain1.mirror],
            ['', 'name-2', 'artist-2', mirror_domain2.mirror],
            ['', 'name-3', 'artist-3', self.domain],
            ['', 'name-4', 'artist-4', self.domain],
            ['', 'name-5', 'artist-5', 'not-existing-domain'])
        res = do_import(case_with_domain_file, config_1, self.domain)
        self.assertEqual(5, res['created_count'])
        self.assertEqual(0, res['match_count'])
        self.assertEqual(1, res['failed_count'])

        # Asserting current domain
        cur_case_ids = self.accessor.get_case_ids_in_domain()
        cur_cases = list(self.accessor.get_cases(cur_case_ids))
        self.assertEqual(3, len(cur_cases))
        #Asserting current domain case property
        cases = {c.name: c for c in cur_cases}
        self.assertEqual(cases['name-0'].get_case_property('artist'),
                         'artist-0')

        # Asserting mirror domain 1
        md1_case_ids = CaseAccessors(
            mirror_domain1.mirror).get_case_ids_in_domain()
        md1_cases = list(self.accessor.get_cases(md1_case_ids))
        self.assertEqual(1, len(md1_cases))
        # Asserting mirror domain 1 case property
        md1_cases_pro = {c.name: c for c in md1_cases}
        self.assertEqual(md1_cases_pro['name-1'].get_case_property('artist'),
                         'artist-1')

        # Asserting mirror domain 2
        md2_case_ids = CaseAccessors(
            mirror_domain2.mirror).get_case_ids_in_domain()
        md2_cases = list(self.accessor.get_cases(md2_case_ids))
        self.assertEqual(1, len(md2_cases))
        # Asserting mirror domain 2 case propperty
        md2_cases_pro = {c.name: c for c in md2_cases}
        self.assertEqual(md2_cases_pro['name-2'].get_case_property('artist'),
                         'artist-2')

    # This test will only run on SQL backend because of a bug in couch backend
    # that overrides current domain with the 'domain' column value from excel
    @override_settings(TESTS_SHOULD_USE_SQL_BACKEND=True)
    @flag_disabled('DOMAIN_PERMISSIONS_MIRROR')
    def test_multiple_domain_case_import_mirror_domain_disabled(self):
        headers_with_domain = ['case_id', 'name', 'artist', 'domain']
        config_1 = self._config(headers_with_domain,
                                create_new_cases=True,
                                search_column='case_id')
        case_with_domain_file = make_worksheet_wrapper(
            ['case_id', 'name', 'artist', 'domain'],
            ['', 'name-0', 'artist-0', self.domain],
            ['', 'name-1', 'artist-1', 'domain-1'],
            ['', 'name-2', 'artist-2', 'domain-2'],
            ['', 'name-3', 'artist-3', self.domain],
            ['', 'name-4', 'artist-4', self.domain],
            ['', 'name-5', 'artist-5', 'not-existing-domain'])
        res = do_import(case_with_domain_file, config_1, self.domain)
        self.assertEqual(6, res['created_count'])
        self.assertEqual(0, res['match_count'])
        self.assertEqual(0, res['failed_count'])
        case_ids = self.accessor.get_case_ids_in_domain()
        # Asserting current domain
        cur_cases = list(self.accessor.get_cases(case_ids))
        self.assertEqual(6, len(cur_cases))
        #Asserting domain case property
        cases = {c.name: c for c in cur_cases}
        self.assertEqual(cases['name-0'].get_case_property('domain'),
                         self.domain)

    def import_mock_file(self, rows):
        config = self._config(rows[0])
        xls_file = make_worksheet_wrapper(*rows)
        return do_import(xls_file, config, self.domain)

    @run_with_all_backends
    def testLocationOwner(self):
        # This is actually testing several different things, but I figure it's
        # worth it, as each of these tests takes a non-trivial amount of time.
        non_case_sharing = LocationType.objects.create(domain=self.domain,
                                                       name='lt1',
                                                       shares_cases=False)
        case_sharing = LocationType.objects.create(domain=self.domain,
                                                   name='lt2',
                                                   shares_cases=True)
        location = make_loc('loc-1', 'Loc 1', self.domain, case_sharing.code)
        make_loc('loc-2', 'Loc 2', self.domain, case_sharing.code)
        duplicate_loc = make_loc('loc-3', 'Loc 2', self.domain,
                                 case_sharing.code)
        improper_loc = make_loc('loc-4', 'Loc 4', self.domain,
                                non_case_sharing.code)

        res = self.import_mock_file([
            ['case_id', 'name', 'owner_id', 'owner_name'],
            ['', 'location-owner-id', location.location_id, ''],
            ['', 'location-owner-code', '', location.site_code],
            ['', 'location-owner-name', '', location.name],
            ['', 'duplicate-location-name', '', duplicate_loc.name],
            ['', 'non-case-owning-name', '', improper_loc.name],
        ])
        case_ids = self.accessor.get_case_ids_in_domain()
        cases = {c.name: c for c in list(self.accessor.get_cases(case_ids))}

        self.assertEqual(cases['location-owner-id'].owner_id,
                         location.location_id)
        self.assertEqual(cases['location-owner-code'].owner_id,
                         location.location_id)
        self.assertEqual(cases['location-owner-name'].owner_id,
                         location.location_id)

        error_message = exceptions.DuplicateLocationName.title
        error_column_name = None
        self.assertIn(error_message, res['errors'])
        self.assertEqual(
            res['errors'][error_message][error_column_name]['rows'], [5])

        error_message = exceptions.InvalidOwner.title
        self.assertIn(error_message, res['errors'])
        error_column_name = 'owner_name'
        self.assertEqual(
            res['errors'][error_message][error_column_name]['rows'], [6])

    @run_with_all_backends
    def test_opened_on(self):
        case = self.factory.create_case()
        new_date = '2015-04-30T14:41:53.000000Z'
        with flag_enabled('BULK_UPLOAD_DATE_OPENED'):
            self.import_mock_file([['case_id', 'date_opened'],
                                   [case.case_id, new_date]])
        case = CaseAccessors(self.domain).get_case(case.case_id)
        self.assertEqual(case.opened_on,
                         PhoneTime(parse_datetime(new_date)).done())
Example #15
0
class APIResourceTest(TestCase, metaclass=PatchMeta):
    """
    Base class for shared API tests. Sets up a domain and user and provides
    some helper methods and properties for accessing the API
    """
    patch = flag_enabled('API_THROTTLE_WHITELIST')

    resource = None  # must be set by subclasses
    api_name = 'v0.4'  # can be overridden by subclasses
    maxDiff = None

    @classmethod
    def setUpClass(cls):
        super(APIResourceTest, cls).setUpClass()

        Role.get_cache().clear()
        cls.domain = Domain.get_or_create_with_name('qwerty', is_active=True)
        cls.list_endpoint = cls._get_list_endpoint()
        cls.username = '******'
        cls.password = '******'
        cls.user = WebUser.create(cls.domain.name, cls.username, cls.password,
                                  None, None)
        cls.user.set_role(cls.domain.name, 'admin')
        cls.user.save()

        cls.account = BillingAccount.get_or_create_account_by_domain(
            cls.domain.name, created_by="automated-test")[0]
        plan = DefaultProductPlan.get_default_plan_version(
            edition=SoftwarePlanEdition.ADVANCED)
        cls.subscription = Subscription.new_domain_subscription(
            cls.account, cls.domain.name, plan)
        cls.subscription.is_active = True
        cls.subscription.save()

        cls.api_key, _ = HQApiKey.objects.get_or_create(
            user=WebUser.get_django_user(cls.user))

    @classmethod
    def _get_list_endpoint(cls):
        return reverse('api_dispatch_list',
                       kwargs=dict(
                           domain=cls.domain.name,
                           api_name=cls.api_name,
                           resource_name=cls.resource._meta.resource_name))

    @classmethod
    def tearDownClass(cls):
        cls.api_key.delete()
        cls.user.delete(deleted_by=None)

        for domain in Domain.get_all():
            Subscription._get_active_subscription_by_domain.clear(
                Subscription, domain.name)
            domain.delete()

        super(APIResourceTest, cls).tearDownClass()

    def single_endpoint(self, id):
        return reverse('api_dispatch_detail',
                       kwargs=dict(
                           domain=self.domain.name,
                           api_name=self.api_name,
                           resource_name=self.resource._meta.resource_name,
                           pk=id))

    def _api_url(self, url, username=None):
        if 'api_key' in url:
            return url

        username = username or self.username
        api_key = self.api_key.key
        if username != self.username:
            web_user = WebUser.get_by_username(username)
            api_key, _ = HQApiKey.objects.get_or_create(
                user=WebUser.get_django_user(web_user))
            api_key = api_key.key

        api_params = urlencode({'username': username, 'api_key': api_key})

        if "?" in url:
            api_url = "%s&%s" % (url, api_params)
        else:
            api_url = "%s?%s" % (url, api_params)
        return api_url

    def _assert_auth_get_resource(self,
                                  url,
                                  username=None,
                                  password=None,
                                  failure_code=401,
                                  headers=None):
        """
        This tests that the given URL fails when accessed via sessions and returns the response
        obtained via using API auth. It's callers' responsibility to test resource specific logic
        using response returned.

        The user authentication is attempted via default self.username creds, other creds can be passed
        via username and password kwargs
        """
        username = username or self.username
        password = password or self.password
        headers = headers or {}

        # session based auth should fail
        self.client.login(username=username, password=password)
        response = self.client.get(url, **headers)
        self.assertEqual(response.status_code, failure_code)

        # api_key auth should succeed, caller can check for expected code
        api_url = self._api_url(url, username)
        response = self.client.get(api_url, **headers)
        return response

    def _assert_auth_post_resource(self,
                                   url,
                                   post_data,
                                   content_type='application/json',
                                   method="POST",
                                   failure_code=401):
        """
        See docstring for _assert_auth_get_resource()
        """
        # session based auth should fail
        self.client.login(username=self.username, password=self.password)
        if method == "POST":
            response = self.client.post(url,
                                        post_data,
                                        content_type=content_type)
        elif method == "PUT":
            response = self.client.put(url,
                                       post_data,
                                       content_type=content_type)
        elif method == "DELETE":
            response = self.client.delete(url,
                                          post_data,
                                          content_type=content_type)
        self.assertEqual(response.status_code, failure_code)

        # api_key auth should succeed, caller should check expected response status and content
        api_url = self._api_url(url)
        if method == "POST":
            response = self.client.post(api_url,
                                        post_data,
                                        content_type=content_type)
        elif method == "PUT":
            response = self.client.put(api_url,
                                       post_data,
                                       content_type=content_type)
        elif method == "DELETE":
            response = self.client.delete(api_url,
                                          post_data,
                                          content_type=content_type)
        return response
Example #16
0
 def test_no_credentials(self):
     with flag_enabled('ODATA'):
         response = self.client.get(self.view_url)
     self.assertEqual(response.status_code, 401)
Example #17
0
 def test_success_with_two_factor_api_key(self):
     with flag_enabled('TWO_FACTOR_SUPERUSER_ROLLOUT'):
         self.test_success_with_api_key()
 def test_should_sync_flat_format_default_toggle(self):
     with flag_enabled('FLAT_LOCATION_FIXTURE'):
         self.assertEqual(True, should_sync_flat_fixture('some-domain'))
 def test_should_sync_flat_format_disabled_toggle(self):
     location_settings = LocationFixtureConfiguration.objects.create(
         domain='some-domain', sync_flat_fixture=False)
     self.addCleanup(location_settings.delete)
     with flag_enabled('FLAT_LOCATION_FIXTURE'):
         self.assertEqual(False, should_sync_flat_fixture('some-domain'))
Example #20
0
    def test_case_list_form_followup_form(self, *args):
        # * Register house (case type = house, basic)
        #   * Register house form
        # * Register person (case type = person, parent select = 'Register house', advanced)
        #   * Register person form
        # * Manager person (case type = person, case list form = 'Register person form', basic)
        #   * Manage person form
        factory = AppFactory(build_version='2.9.0')
        register_house_module, register_house_form = factory.new_basic_module(
            'register_house', 'house')
        factory.form_opens_case(register_house_form)

        register_person_module, register_person_form = factory.new_advanced_module(
            'register_person', 'person')
        factory.form_requires_case(register_person_form, 'house')
        factory.form_opens_case(register_person_form,
                                'person',
                                is_subcase=True)

        house_module, update_house_form = factory.new_advanced_module(
            'update_house',
            'house',
        )
        factory.form_requires_case(update_house_form)

        person_module, update_person_form = factory.new_basic_module(
            'update_person', 'person', case_list_form=update_house_form)
        factory.form_requires_case(update_person_form)

        def _assert_app_build_error(error):
            errors = factory.app.validate_app()
            self.assertIn(
                (error, person_module.unique_id),
                [(e["type"], e.get("module", {}).get("unique_id", {}))
                 for e in errors])
            self.assertXmlPartialEqual("<partial></partial>",
                                       factory.app.create_suite(),
                                       "./detail[@id='m3_case_short']/action")

        # should fail since feature flag isn't enabled
        _assert_app_build_error('case list form not registration')
        with flag_enabled('FOLLOWUP_FORMS_AS_CASE_LIST_FORM'):
            # should fail since module doesn't have active parent_select
            _assert_app_build_error("invalid case list followup form")

            person_module.parent_select.active = True
            person_module.parent_select.module_id = register_house_module.unique_id
            person_module.case_list_form.relevancy_expression = "count(instance('casedb')/casedb/case) != 0"
            errors = factory.app.validate_app()
            self.assertNotIn(
                ('case list form not registration', person_module.unique_id),
                [(e["type"], e.get("module", {}).get("unique_id", {}))
                 for e in errors])
            xml = """
            <partial>
            <action relevant="count(instance('casedb')/casedb/case) != 0">
                <display>
                    <text><locale id="case_list_form.m3"/></text>
                </display>
                <stack>
                <push>
                    <command value="'m2-f0'"/>
                    <datum id="case_id_load_house_0" value="instance('commcaresession')/session/data/parent_id"/>
                    <datum id="return_to" value="'m3'"/>
                </push>
                </stack>
            </action>
            </partial>
            """
            self.assertXmlPartialEqual(xml, factory.app.create_suite(),
                                       "./detail[@id='m3_case_short']/action")
            person_module.parent_select.active = False
Example #21
0
 def test_request_succeeded(self):
     correct_credentials = self._get_correct_credentials()
     with flag_enabled('ODATA'):
         response = self._execute_query(correct_credentials)
     self.assertEqual(response.status_code, 200)
Example #22
0
    def test_modules_case_search_app_strings(self):
        factory = AppFactory(build_version='2.40.0')
        factory.app.langs = ['en', 'es']
        factory.app.build_profiles = OrderedDict({
            'en':
            BuildProfile(langs=['en'], name='en-profile'),
            'es':
            BuildProfile(langs=['es'], name='es-profile'),
        })
        module, form = factory.new_basic_module('my_module', 'cases')
        module.search_config = CaseSearch(
            search_label=CaseSearchLabel(
                label={
                    'en': 'Get them',
                    'es': 'Conseguirlos'
                },
                media_image={
                    'en': "jr://file/commcare/image/1.png",
                    'es': "jr://file/commcare/image/1_es.png"
                },
                media_audio={'en': "jr://file/commcare/image/2.mp3"}),
            search_again_label=CaseSearchAgainLabel(
                label={'en': 'Get them all'}),
            properties=[CaseSearchProperty(name="name", label={'en': 'Name'})])
        # wrap to have assign_references called
        app = Application.wrap(factory.app.to_json())

        with flag_disabled('USH_CASE_CLAIM_UPDATES'):
            # default language
            self.assertEqual(app.default_language, 'en')
            en_app_strings = self._generate_app_strings(app,
                                                        'default',
                                                        build_profile_id='en')
            self.assertEqual(en_app_strings['case_search.m0'],
                             'Search All Cases')
            self.assertEqual(en_app_strings['case_search.m0.again'],
                             'Search Again')
            self.assertFalse('case_search.m0.icon' in en_app_strings)
            self.assertFalse('case_search.m0.audio' in en_app_strings)

            # non-default language
            es_app_strings = self._generate_app_strings(app,
                                                        'es',
                                                        build_profile_id='es')
            self.assertEqual(es_app_strings['case_search.m0'],
                             'Search All Cases')
            self.assertEqual(es_app_strings['case_search.m0.again'],
                             'Search Again')

        with flag_enabled('USH_CASE_CLAIM_UPDATES'):
            # default language
            en_app_strings = self._generate_app_strings(app,
                                                        'default',
                                                        build_profile_id='en')
            self.assertEqual(en_app_strings['case_search.m0'], 'Get them')
            self.assertEqual(en_app_strings['case_search.m0.icon'],
                             'jr://file/commcare/image/1.png')
            self.assertEqual(en_app_strings['case_search.m0.audio'],
                             'jr://file/commcare/image/2.mp3')
            self.assertEqual(en_app_strings['case_search.m0.again'],
                             'Get them all')

            # non-default language
            es_app_strings = self._generate_app_strings(app,
                                                        'es',
                                                        build_profile_id='es')
            self.assertEqual(es_app_strings['case_search.m0'], 'Conseguirlos')
            self.assertEqual(es_app_strings['case_search.m0.icon'],
                             'jr://file/commcare/image/1_es.png')
            self.assertEqual(es_app_strings['case_search.m0.again'],
                             'Get them all')
Example #23
0
def contractor():
    with domain_admin(), flag_enabled('IS_CONTRACTOR'):
        yield