def test_metadata(self): location_type = self.location_types['state'] location = SQLLocation( id="854208", domain="test-domain", name="Braavos", location_type=location_type, metadata={ 'best_swordsman': "Sylvio Forel", 'in_westeros': "false", 'appeared_in_num_episodes': 3, }, ) location_db = LocationSet([location]) data_fields = [ Field(slug='best_swordsman'), Field(slug='in_westeros'), Field(slug='appeared_in_num_episodes'), ] fixture = _location_to_fixture(location_db, location, location_type, data_fields) location_data = {e.tag: e.text for e in fixture.find('location_data')} self.assertEqual(location_data, {k: str(v) for k, v in location.metadata.items()})
def setUpClass(cls): super(LocationFixturesDataTest, cls).setUpClass() cls.user = create_restore_user(cls.domain, 'user', '123') cls.loc_fields = CustomDataFieldsDefinition.get_or_create(cls.domain, LocationFieldsView.field_type) cls.loc_fields.set_fields([ Field(slug='baseball_team'), Field(slug='favorite_pastime'), ]) cls.loc_fields.save() cls.field_slugs = [f.slug for f in cls.loc_fields.get_fields()]
def setUpClass(cls): super().setUpClass() cls.domain_obj = create_domain(cls.domain) # APP_USER_PROFILES is on ENTERPRISE and above cls.setup_subscription(cls.domain, SoftwarePlanEdition.ENTERPRISE) cls.group_memoizer = GroupMemoizer(domain=cls.domain_obj.name) cls.group_memoizer.load_all() cls.definition = CustomDataFieldsDefinition( domain=cls.domain_obj.name, field_type=UserFieldsView.field_type) cls.definition.save() cls.definition.set_fields([ Field( slug='born', label='Year of Birth', ), Field( slug='_type', label='Type', choices=['fiction', 'non-fiction'], ), ]) cls.definition.save() cls.profile = CustomDataFieldsProfile( name='Novelist', fields={'_type': 'fiction'}, definition=cls.definition, ) cls.profile.save() cls.user1 = CommCareUser.create(cls.domain_obj.name, 'edith', 'badpassword', None, None, first_name='Edith', last_name='Wharton', metadata={'born': 1862}) cls.user2 = CommCareUser.create( cls.domain_obj.name, 'george', 'anotherbadpassword', None, None, first_name='George', last_name='Eliot', metadata={ 'born': 1849, PROFILE_SLUG: cls.profile.id }, )
def test_validate_regex(self): field = Field( slug='s_word', label='Word starting with the letter S', regex='^[Ss]', regex_msg='That does not start with S', ) self.assertIsNone(field.validate_regex('sibilant')) self.assertEqual( field.validate_regex('whisper'), "'whisper' is not a valid match for Word starting with the letter S" )
def test_validate_choices(self): field = Field( slug='warm_color', label='Warm Color', choices=[ 'red', 'orange', 'yellow', ], ) self.assertIsNone(field.validate_choices('orange')) self.assertEqual( field.validate_choices('squishy'), "'squishy' is not a valid choice for Warm Color. The available options are: red, orange, yellow." )
def setUpClass(cls): super(TestLocationsExport, cls).setUpClass() cls.loc_fields = CustomDataFieldsDefinition.get_or_create(cls.domain, LocationFieldsView.field_type) cls.loc_fields.set_fields([ Field(slug=slug) for slug in cls.custom_fields ]) cls.loc_fields.save() cls.boston = cls.locations['Boston'] cls.boston.metadata = { field: '{}-试验'.format(field) for field in cls.custom_fields + ['不知道'] } cls.boston.external_id = 'external_id' cls.boston.latitude = Decimal('42.36') cls.boston.longitude = Decimal('71.06') cls.boston.save() exporter = LocationExporter(cls.domain) writer = MockExportWriter() exporter.write_data(writer) cls.headers = dict(exporter.get_headers()) cls.city_headers = cls.headers['city'][0] cls.boston_data = [row for row in writer.data['city'] if row[0] == cls.boston.location_id][0]
def setUpClass(cls): super().setUpClass() cls.domain = 'user-esaccessors-test' cls.definition = CustomDataFieldsDefinition(domain=cls.domain, field_type=UserFieldsView.field_type) cls.definition.save() cls.definition.set_fields([ Field(slug='job', label='Job'), ]) cls.definition.save() cls.profile = CustomDataFieldsProfile( name='daily_planet_staff', fields={'job': 'reporter'}, definition=cls.definition, ) cls.profile.save() cls.user = CommCareUser.create( cls.domain, 'superman', 'secret agent man', None, None, first_name='clark', last_name='kent', is_active=True, metadata={PROFILE_SLUG: cls.profile.id, 'office': 'phone_booth'}, ) cls.user.save()
def test_sync_custom_user_data(self): definition = CustomDataFieldsDefinition( domain=TEST_DOMAIN, field_type=UserFieldsView.field_type) definition.save() definition.set_fields([ Field(slug='from_profile', label='From Profile'), ]) definition.save() profile = CustomDataFieldsProfile( name='callcenter_profile', fields={'from_profile': 'yes'}, definition=definition, ) profile.save() self.user.update_metadata({ '': 'blank_key', 'blank_val': '', 'ok': 'good', 'name with spaces': 'ok', '8starts_with_a_number': '0', 'xml_starts_with_xml': '0', '._starts_with_punctuation': '0', PROFILE_SLUG: profile.id, }) sync_call_center_user_case(self.user) case = self._get_user_case() self.assertIsNotNone(case) self.assertEqual(case.get_case_property('blank_val'), '') self.assertEqual(case.get_case_property('ok'), 'good') self.assertEqual(case.get_case_property(PROFILE_SLUG), str(profile.id)) self.assertEqual(case.get_case_property('from_profile'), 'yes') self.user.pop_metadata(PROFILE_SLUG) definition.delete()
def update_custom_data_models(domain_link, limit_types=None): if domain_link.is_remote: master_results = remote_custom_data_models(domain_link, limit_types) else: master_results = local_custom_data_models(domain_link.master_domain, limit_types) for field_type, data in master_results.items(): field_definitions = data.get('fields', []) model = CustomDataFieldsDefinition.get_or_create(domain_link.linked_domain, field_type) model.set_fields([ Field( slug=field_def['slug'], is_required=field_def['is_required'], label=field_def['label'], choices=field_def['choices'], regex=field_def['regex'], regex_msg=field_def['regex_msg'], ) for field_def in field_definitions ]) model.save() old_profiles = {profile.name: profile for profile in model.get_profiles()} for profile in data.get('profiles'): old_profile = old_profiles.get(profile['name'], None) if old_profile: old_profile.fields = profile['fields'] old_profile.save() else: CustomDataFieldsProfile( name=profile['name'], definition=model, fields=profile['fields'], ).save()
def test_user_data_profile(self): definition = CustomDataFieldsDefinition( domain='cloudcare-tests', field_type=UserFieldsView.field_type) definition.save() definition.set_fields([ Field(slug='word', label='A Word'), ]) definition.save() self.addCleanup(definition.delete) profile = CustomDataFieldsProfile(name='prof', fields={'word': 'supernova'}, definition=definition) profile.save() user = CommCareUser.create( 'cloudcare-tests', '*****@*****.**', 'do you want to know a secret', None, None, uuid=uuid.uuid4().hex, metadata={PROFILE_SLUG: profile.id}, ) self.addCleanup(user.delete, None, None) user_data = get_user_contributions_to_touchforms_session( 'cloudcare-tests', user)['user_data'] self.assertEqual(profile.id, user_data[PROFILE_SLUG]) self.assertEqual('supernova', user_data['word'])
def setUpClass(cls): super().setUpClass() cls.domain = 'a-domain' cls.definition = CustomDataFieldsDefinition( domain=cls.domain, field_type=UserFieldsView.field_type) cls.definition.save() cls.definition.set_fields([ Field( slug='corners', is_required=True, label='Number of corners', regex='^[0-9]+$', regex_msg='This should be a number', ), Field( slug='prefix', is_required=False, label='Prefix', choices=['tri', 'tetra', 'penta'], ), Field( slug='color', is_required=False, label='Color', ), ]) cls.definition.save() cls.profile3 = CustomDataFieldsProfile( name='three', fields={ 'corners': 3, 'prefix': 'tri' }, definition=cls.definition, ) cls.profile3.save() cls.profile5 = CustomDataFieldsProfile( name='five', fields={ 'corners': 5, 'prefix': 'penta' }, definition=cls.definition, ) cls.profile5.save()
def setUpClass(cls): super().setUpClass() delete_all_users() cls.domain_name = 'mydomain' cls.domain = Domain.get_or_create_with_name(name=cls.domain_name) cls.other_domain = Domain.get_or_create_with_name(name='other-domain') cls.uploading_user = WebUser.create(cls.domain_name, "*****@*****.**", 'password', None, None, is_superuser=True) permissions = Permissions(edit_apps=True, view_apps=True, view_reports=True) cls.role = UserRole.get_or_create_with_permissions( cls.domain.name, permissions, 'edit-apps') cls.other_role = UserRole.get_or_create_with_permissions( cls.domain.name, permissions, 'admin') cls.patcher = patch('corehq.apps.user_importer.tasks.UserUploadRecord') cls.patcher.start() cls.definition = CustomDataFieldsDefinition( domain=cls.domain_name, field_type=UserFieldsView.field_type) cls.definition.save() cls.definition.set_fields([ Field( slug='key', is_required=False, label='Key', regex='^[A-G]', regex_msg='Starts with A-G', ), Field(slug='mode', is_required=False, label='Mode', choices=['major', 'minor']), ]) cls.definition.save() cls.profile = CustomDataFieldsProfile( name='melancholy', fields={'mode': 'minor'}, definition=cls.definition, ) cls.profile.save()
def test_download_reupload_no_changes(self): # Make sure there's a bunch of data loc_fields = CustomDataFieldsDefinition.get_or_create(self.domain, 'LocationFields') loc_fields.set_fields([ Field(slug='favorite_color'), Field(slug='language'), ]) loc_fields.save() self.locations['City111'].latitude = Decimal('42.36') self.locations['City111'].longitude = Decimal('71.06') self.locations['City111'].external_id = '123' self.locations['County11'].metadata = {'favorite_color': 'purple', 'language': 'en'} self.locations['City111'].save() self.locations['County11'].external_id = '321' self.locations['County11'].metadata = {'favorite_color': 'blue'} self.locations['County11'].save() # Export locations exporter = LocationExporter(self.domain) writer = MockExportWriter() exporter.write_data(writer) # Re-upload that export worksheets = [] for sheet_title, headers in exporter.get_headers(): rows = [[val if val is not None else '' for val in row] for row in writer.data[sheet_title]] sheet = IteratorJSONReader(headers + rows) sheet.title = sheet_title worksheets.append(sheet) mock_importer = Mock() mock_importer.worksheets = worksheets with patch('corehq.apps.locations.models.SQLLocation.save') as save_location, \ patch('corehq.apps.locations.models.LocationType.save') as save_type: result = new_locations_import(self.domain, mock_importer, self.user) # The upload should succeed and not perform any updates assert_errors(result, []) self.assertFalse(save_location.called) self.assertFalse(save_type.called)
def setUpClass(cls): super().setUpClass() cls.definition = CustomDataFieldsDefinition( domain=cls.domain, field_type=UserFieldsView.field_type) cls.definition.save() cls.definition.set_fields([ Field( slug='has_legs', label='Has legs', choices=['yes', 'no'], ), Field( slug='can_swim', label='Can swim', choices=['yes', 'no'], ), Field( slug='color', label='Color', ), ]) cls.definition.save() cls.coral_profile = CustomDataFieldsProfile( name='Coral', fields={ 'has_legs': 'no', 'can_swim': 'no' }, definition=cls.definition, ) cls.coral_profile.save() cls.fish_profile = CustomDataFieldsProfile( name='Fish', fields={ 'has_legs': 'no', 'can_swim': 'yes' }, definition=cls.definition, ) cls.fish_profile.save()
def test_validate_required(self): required_field = Field( slug='favorite_chordata', is_required=True, label='Favorite Chordata', ) self.assertIsNone(required_field.validate_required('sea lamprey')) self.assertEqual(required_field.validate_required(None), 'Favorite Chordata is required.') optional_field = Field( slug='fav_echinoderm', is_required=False, label='Favorite Echinoderm', ) self.assertIsNone(optional_field.validate_required('sea cucumber')) self.assertIsNone(optional_field.validate_required(None))
def _setup_profile(self): definition = CustomDataFieldsDefinition( domain=self.domain, field_type=UserFieldsView.field_type) definition.save() definition.set_fields([ Field( slug='conflicting_field', label='Conflicting Field', choices=['yes', 'no'], ), ]) definition.save() profile = CustomDataFieldsProfile( name='character', fields={'conflicting_field': 'yes'}, definition=definition, ) profile.save() return profile.id
def update_or_create_sql_object(self, doc): model, created = self.sql_class().objects.update_or_create( couch_id=doc['_id'], defaults={ "domain": doc['domain'], "field_type": doc['field_type'], }, ) model.set_fields([ Field( slug=field['slug'], is_required=field.get('is_required', False), label=field.get('label', ''), choices=field.get('choices', []), regex=field.get('regex', ''), regex_msg=field.get('regex_msg', ''), ) for field in doc['fields'] ]) model.save() return (model, created)
def setUpClass(cls): reset_es_index(USER_INDEX_INFO) super().setUpClass() cls.definition = CustomDataFieldsDefinition( domain=cls.domain.name, field_type=UserFieldsView.field_type) cls.definition.save() cls.definition.set_fields([ Field( slug='imaginary', label='Imaginary Person', choices=['yes', 'no'], ), ]) cls.definition.save() cls.profile = CustomDataFieldsProfile( name='character', fields={'imaginary': 'yes'}, definition=cls.definition, ) cls.profile.save()
def update_custom_data_models(domain_link, limit_types=None): if domain_link.is_remote: master_results = remote_custom_data_models(domain_link, limit_types) else: master_results = local_custom_data_models(domain_link.master_domain, limit_types) for field_type, field_definitions in master_results.items(): model = CustomDataFieldsDefinition.get_or_create( domain_link.linked_domain, field_type) model.set_fields([ Field( slug=field_def['slug'], is_required=field_def['is_required'], label=field_def['label'], choices=field_def['choices'], regex=field_def['regex'], regex_msg=field_def['regex_msg'], ) for field_def in field_definitions ]) model.save()
def setUpClass(cls): super().setUpClass() cls.domain = 'test-domain' cls.domain_obj = create_domain(cls.domain) cls.addClassCleanup(cls.domain_obj.delete) cls.definition = CustomDataFieldsDefinition( domain=cls.domain, field_type=UserFieldsView.field_type) cls.definition.save() cls.definition.set_fields([ Field( slug='conflicting_field', label='Conflicting Field', choices=['yes', 'no'], ), ]) cls.definition.save() cls.profile = CustomDataFieldsProfile( name='character', fields={'conflicting_field': 'yes'}, definition=cls.definition, ) cls.profile.save()
def setUpClass(cls): super(SchedulingRecipientTest, cls).setUpClass() cls.domain_obj = create_domain(cls.domain) cls.location_types = setup_location_types(cls.domain, ['country', 'state', 'city']) cls.country_location = make_loc('usa', domain=cls.domain, type='country') cls.state_location = make_loc('ma', domain=cls.domain, type='state', parent=cls.country_location) cls.city_location = make_loc('boston', domain=cls.domain, type='city', parent=cls.state_location) cls.mobile_user = CommCareUser.create(cls.domain, 'mobile', 'abc', None, None) cls.mobile_user.set_location(cls.city_location) cls.mobile_user2 = CommCareUser.create(cls.domain, 'mobile2', 'abc', None, None) cls.mobile_user2.set_location(cls.state_location) cls.mobile_user3 = CommCareUser.create(cls.domain, 'mobile3', 'abc', None, None, metadata={ 'role': 'pharmacist', }) cls.mobile_user3.save() cls.mobile_user4 = CommCareUser.create(cls.domain, 'mobile4', 'abc', None, None, metadata={ 'role': 'nurse', }) cls.mobile_user4.save() cls.mobile_user5 = CommCareUser.create(cls.domain, 'mobile5', 'abc', None, None, metadata={ 'role': ['nurse', 'pharmacist'], }) cls.mobile_user5.save() full_username = normalize_username('mobile', cls.domain) cls.full_mobile_user = CommCareUser.create(cls.domain, full_username, 'abc', None, None) cls.definition = CustomDataFieldsDefinition( domain=cls.domain, field_type=UserFieldsView.field_type) cls.definition.save() cls.definition.set_fields([ Field( slug='role', label='Role', ), ]) cls.definition.save() cls.profile = CustomDataFieldsProfile( name='nurse_profile', fields={'role': ['nurse']}, definition=cls.definition, ) cls.profile.save() cls.mobile_user6 = CommCareUser.create(cls.domain, 'mobile6', 'abc', None, None, metadata={ PROFILE_SLUG: cls.profile.id, }) cls.mobile_user5.save() cls.web_user = WebUser.create(cls.domain, 'web', 'abc', None, None) cls.web_user2 = WebUser.create(cls.domain, 'web2', 'abc', None, None, metadata={ 'role': 'nurse', }) cls.web_user2.save() cls.group = Group(domain=cls.domain, users=[cls.mobile_user.get_id]) cls.group.save() cls.group2 = Group(domain=cls.domain, users=[ cls.mobile_user.get_id, cls.mobile_user3.get_id, cls.mobile_user4.get_id, cls.mobile_user5.get_id, cls.mobile_user6.get_id, ]) cls.group2.save() cls.case_group = CommCareCaseGroup(domain=cls.domain) cls.case_group.save() cls.process_pillow_changes = process_pillow_changes( 'DefaultChangeFeedPillow') cls.process_pillow_changes.add_pillow(get_case_messaging_sync_pillow())
def test_metadata_with_profile(self): definition = CustomDataFieldsDefinition( domain='my-domain', field_type=UserFieldsView.field_type) definition.save() definition.set_fields([Field(slug='start')]) definition.save() profile = CustomDataFieldsProfile( name='low', fields={'start': 'sometimes'}, definition=definition, ) profile.save() conflict_message = "metadata properties conflict with profile: start" # Custom user data profiles get their data added to metadata automatically for mobile users self.user.update_metadata({PROFILE_SLUG: profile.id}) self.assertEqual( self.user.metadata, { 'commcare_project': 'my-domain', PROFILE_SLUG: profile.id, 'start': 'sometimes', }) # Remove profile should remove it and related fields self.user.pop_metadata(PROFILE_SLUG) self.assertEqual(self.user.metadata, { 'commcare_project': 'my-domain', }) # Can't add profile that conflicts with existing data self.user.update_metadata({ 'start': 'never', 'end': 'yesterday', }) with self.assertRaisesMessage(ValueError, conflict_message): self.user.update_metadata({ PROFILE_SLUG: profile.id, }) # Can't add data that conflicts with existing profile self.user.pop_metadata('start') self.user.update_metadata({PROFILE_SLUG: profile.id}) with self.assertRaisesMessage(ValueError, conflict_message): self.user.update_metadata({'start': 'never'}) # Can't add both a profile and conflicting data self.user.pop_metadata(PROFILE_SLUG) with self.assertRaisesMessage(ValueError, conflict_message): self.user.update_metadata({ PROFILE_SLUG: profile.id, 'start': 'never', }) # Custom user data profiles don't get populated for web users web_user = WebUser.create(None, "imogen", "*****", None, None) self.assertEqual(web_user.metadata, { 'commcare_project': None, }) web_user.update_metadata({PROFILE_SLUG: profile.id}) self.assertEqual(web_user.metadata, { 'commcare_project': None, PROFILE_SLUG: profile.id, }) definition.delete() web_user.delete(self.domain, deleted_by=None)
def setUpClass(cls): super().setUpClass() cls.domain = 'bookshelf' cls.other_domain = 'book' cls.domain_obj = create_domain(cls.domain) cls.other_domain_obj = create_domain(cls.other_domain) cls.definition = CustomDataFieldsDefinition( domain=cls.domain_obj.name, field_type=UserFieldsView.field_type) cls.definition.save() cls.definition.set_fields([ Field( slug='born', label='Year of Birth', ), Field( slug='_type', label='Type', choices=['fiction', 'non-fiction'], ), ]) cls.definition.save() cls.profile = CustomDataFieldsProfile( name='Novelist', fields={'_type': 'fiction'}, definition=cls.definition, ) cls.profile.save() cls.user1 = CommCareUser.create(cls.domain_obj.name, 'edith', 'badpassword', None, None, first_name='Edith', last_name='Wharton', metadata={'born': 1862}) cls.user2 = CommCareUser.create( cls.domain_obj.name, 'george', 'anotherbadpassword', None, None, first_name='George', last_name='Eliot', metadata={ 'born': 1849, PROFILE_SLUG: cls.profile.id }, ) cls.user3 = CommCareUser.create( cls.other_domain_obj.name, 'emily', 'anothersuperbadpassword', None, None, first_name='Emily', last_name='Bronte', )