def test_filter_on_multi_field_index_fields(self): # Test that we can filter on all index fields # TODO: Test filtering on subfields of IndexedField item = self.get_test_item() fields = [] for f in self._reduce_fields_for_filter(item, self.get_item_fields()): if not issubclass(f.value_cls, MultiFieldIndexedElement): continue fields.append(f) if not fields: self.skipTest('No matching multi index fields on this model') item.save() common_qs = self.test_folder.filter(categories__contains=self.categories) for f in fields: val = getattr(item, f.name) # Filter multi-value fields with =, __in and __contains # For these, we need to filter on the subfield filter_kwargs = [] for v in val: for subfield in f.value_cls.supported_fields(version=self.account.version): field_path = FieldPath(field=f, label=v.label, subfield=subfield) path, subval = field_path.path, field_path.get_value(item) if subval is None: continue filter_kwargs.extend([ {path: subval}, {'%s__in' % path: [subval]}, {'%s__contains' % path: [subval]} ]) self._run_filter_tests(common_qs, f, filter_kwargs, val)
def test_filter_on_single_field_index_fields(self): # Test that we can filter on all index fields item = self.get_test_item() fields = [] for f in self._reduce_fields_for_filter(item, self.get_item_fields()): if not issubclass(f.value_cls, SingleFieldIndexedElement): continue fields.append(f) if not fields: self.skipTest("No matching single index fields on this model") item.save() common_qs = self.test_folder.filter( categories__contains=self.categories) for f in fields: val = getattr(item, f.name) # For these, we may filter by item or subfield value filter_kwargs = [] for v in val: for subfield in f.value_cls.supported_fields( version=self.account.version): field_path = FieldPath(field=f, label=v.label, subfield=subfield) path, subval = field_path.path, field_path.get_value(item) if subval is None: continue filter_kwargs.extend([ { f.name: v }, { path: subval }, { f"{path}__in": [subval] }, { f"{path}__contains": get_random_substring(subval) }, ]) self._run_filter_tests(common_qs, f, filter_kwargs, val)
def test_raw_service_call(self): item = self.get_test_item(folder=self.test_folder) attached_item1 = self.get_test_item(folder=self.test_folder) attached_item1.body = HTMLBody("<html><body>Hello HTML</body></html>") att1 = ItemAttachment(name="attachment1", item=attached_item1) item.attach(att1) item.save() with self.assertRaises(ValueError): # Bad body_type GetAttachment(account=att1.parent_item.account).get( items=[att1.attachment_id], include_mime_content=True, body_type="XXX", filter_html_content=None, additional_fields=[], ) # Test body_type attachment = GetAttachment(account=att1.parent_item.account).get( items=[att1.attachment_id], include_mime_content=True, body_type="Text", filter_html_content=None, additional_fields=[FieldPath(field=self.ITEM_CLASS.get_field_by_fieldname("body"))], ) self.assertEqual(attachment.item.body, "Hello HTML\r\n") # Test filter_html_content. I wonder what unsafe HTML is. attachment = GetAttachment(account=att1.parent_item.account).get( items=[att1.attachment_id], include_mime_content=False, body_type="HTML", filter_html_content=True, additional_fields=[FieldPath(field=self.ITEM_CLASS.get_field_by_fieldname("body"))], ) self.assertEqual( attachment.item.body, '<html>\r\n<head>\r\n<meta http-equiv="Content-Type" content="text/html; charset=utf-8">\r\n' "</head>\r\n<body>\r\nHello HTML\r\n</body>\r\n</html>\r\n", )
def test_fetch(self): item = self.get_test_item() self.test_folder.bulk_create(items=[item, item]) ids = self.test_folder.filter(categories__contains=item.categories) items = list(self.account.fetch(ids=ids)) for item in items: self.assertIsInstance(item, self.ITEM_CLASS) self.assertEqual(len(items), 2) items = list(self.account.fetch(ids=ids, only_fields=['subject'])) self.assertEqual(len(items), 2) items = list(self.account.fetch(ids=ids, only_fields=[FieldPath.from_string('subject', self.test_folder)])) self.assertEqual(len(items), 2) items = list(self.account.fetch(ids=ids, only_fields=['id', 'changekey'])) self.assertEqual(len(items), 2)
def test_filter_on_all_fields(self): # Test that we can filter on all field names # TODO: Test filtering on subfields of IndexedField item = self.get_test_item().save() common_qs = self.test_folder.filter( categories__contains=self.categories) for f in self.get_item_fields(): if not f.supports_version(self.account.version): # Cannot be used with this EWS version continue if not f.is_searchable: # Cannot be used in a QuerySet continue val = getattr(item, f.name) if val is None: # We cannot filter on None values continue if self.ITEM_CLASS == Contact and f.name in ('body', 'display_name'): # filtering 'body' or 'display_name' on Contact items doesn't work at all. Error in EWS? continue if f.is_list: # Filter multi-value fields with =, __in and __contains if issubclass(f.value_cls, MultiFieldIndexedElement): # For these, we need to filter on the subfield filter_kwargs = [] for v in val: for subfield in f.value_cls.supported_fields( version=self.account.version): field_path = FieldPath(field=f, label=v.label, subfield=subfield) path, subval = field_path.path, field_path.get_value( item) if subval is None: continue filter_kwargs.extend([{ path: subval }, { '%s__in' % path: [subval] }, { '%s__contains' % path: [subval] }]) elif issubclass(f.value_cls, SingleFieldIndexedElement): # For these, we may filter by item or subfield value filter_kwargs = [] for v in val: for subfield in f.value_cls.supported_fields( version=self.account.version): field_path = FieldPath(field=f, label=v.label, subfield=subfield) path, subval = field_path.path, field_path.get_value( item) if subval is None: continue filter_kwargs.extend([{ f.name: v }, { path: subval }, { '%s__in' % path: [subval] }, { '%s__contains' % path: [subval] }]) else: filter_kwargs = [{ '%s__in' % f.name: val }, { '%s__contains' % f.name: val }] else: # Filter all others with =, __in and __contains. We could have more filters here, but these should # always match. filter_kwargs = [{f.name: val}, {'%s__in' % f.name: [val]}] if isinstance(f, TextField) and not isinstance(f, ChoiceField): # Choice fields cannot be filtered using __contains. Sort of makes sense. random_start = get_random_int(min_val=0, max_val=len(val) // 2) random_end = get_random_int(min_val=len(val) // 2 + 1, max_val=len(val)) filter_kwargs.append({ '%s__contains' % f.name: val[random_start:random_end] }) for kw in filter_kwargs: with self.subTest(f=f, kw=kw): matches = common_qs.filter(**kw).count() if isinstance(f, TextField) and f.is_complex: # Complex text fields sometimes fail a search using generated data. In production, # they almost always work anyway. Give it one more try after 10 seconds; it seems EWS does # some sort of indexing that needs to catch up. if not matches: time.sleep(10) matches = common_qs.filter(**kw).count() if not matches and isinstance(f, BodyField): # The body field is particularly nasty in this area. Give up continue self.assertEqual(matches, 1, (f.name, val, kw))