mirror of
https://github.com/graphql-python/graphene-django.git
synced 2025-12-07 10:14:21 +03:00
326 lines
8.8 KiB
Python
326 lines
8.8 KiB
Python
from datetime import datetime
|
|
|
|
import pytest
|
|
from py.test import raises
|
|
from mock import mock
|
|
|
|
from elasticsearch_dsl.query import Bool, Match, Term, Wildcard, MatchPhrase, MatchPhrasePrefix, Range, Terms, Exists
|
|
from graphene import Schema, ObjectType
|
|
|
|
from graphene_django.elasticsearch.filter.fields import DjangoESFilterConnectionField
|
|
from graphene_django.elasticsearch.filter.filterset import FilterSetES
|
|
from graphene_django.filter.tests.test_fields import ArticleNode
|
|
from graphene_django.tests.models import Article, Reporter
|
|
from graphene_django.utils import DJANGO_FILTER_INSTALLED, DJANGO_ELASTICSEARCH_DSL_INSTALLED
|
|
from graphene_django.elasticsearch.tests.filters import ESFilterQuery, ArticleDocument
|
|
|
|
pytestmark = []
|
|
|
|
if not DJANGO_FILTER_INSTALLED or not DJANGO_ELASTICSEARCH_DSL_INSTALLED:
|
|
pytestmark.append(
|
|
pytest.mark.skipif(
|
|
True, reason="django_filters not installed or not compatible"
|
|
)
|
|
)
|
|
|
|
pytestmark.append(pytest.mark.django_db)
|
|
|
|
|
|
def fake_data():
|
|
r1 = Reporter.objects.create(first_name="r1", last_name="r1", email="r1@test.com")
|
|
a1 = Article.objects.create(
|
|
headline="a1",
|
|
pub_date=datetime.now(),
|
|
pub_date_time=datetime.now(),
|
|
reporter=r1,
|
|
editor=r1,
|
|
)
|
|
a2 = Article.objects.create(
|
|
headline="a2",
|
|
pub_date=datetime.now(),
|
|
pub_date_time=datetime.now(),
|
|
reporter=r1,
|
|
editor=r1,
|
|
)
|
|
return a1, a2
|
|
|
|
|
|
def generate_query(field, query_str):
|
|
query = """
|
|
query {
|
|
%s(%s) {
|
|
edges {
|
|
node {
|
|
headline
|
|
}
|
|
}
|
|
}
|
|
}
|
|
""" % (field, query_str)
|
|
return query
|
|
|
|
|
|
def filter_generation(field, query_str, expected_arguments, method_to_mock="query"):
|
|
a1, a2 = fake_data()
|
|
|
|
query = generate_query(field, query_str)
|
|
|
|
mock_count = mock.Mock(return_value=3)
|
|
mock_slice = mock.Mock(return_value=mock.Mock(to_queryset=mock.Mock(
|
|
return_value=Article.objects.filter(pk__in=[a1.id, a2.id])
|
|
)))
|
|
mock_query = mock.Mock(return_value=ArticleDocument.search())
|
|
|
|
with mock.patch('django_elasticsearch_dsl.search.Search.count', mock_count), \
|
|
mock.patch('django_elasticsearch_dsl.search.Search.__getitem__', mock_slice), \
|
|
mock.patch("elasticsearch_dsl.Search.%s" % method_to_mock, mock_query):
|
|
schema = Schema(query=ESFilterQuery)
|
|
result = schema.execute(query)
|
|
|
|
assert not result.errors
|
|
|
|
mock_query.assert_called_with(expected_arguments)
|
|
|
|
assert len(result.data[field]["edges"]) == 2
|
|
assert result.data[field]["edges"][0]["node"]["headline"] == "a1"
|
|
assert result.data[field]["edges"][1]["node"]["headline"] == "a2"
|
|
|
|
|
|
def test_filter_string():
|
|
filter_generation(
|
|
"articlesAsField",
|
|
"headline: \"A text\"",
|
|
Bool(must=[Match(headline={'query': 'A text', 'fuzziness': 'auto'})]),
|
|
)
|
|
|
|
|
|
def test_filter_string_date():
|
|
filter_generation(
|
|
"articlesAsField",
|
|
"headline: \"A text\"",
|
|
Bool(must=[Match(headline={'query': 'A text', 'fuzziness': 'auto'})]),
|
|
)
|
|
|
|
|
|
def test_filter_as_field_order_by():
|
|
filter_generation(
|
|
"articlesAsField",
|
|
"headline: \"A text\", sort:{order:desc, field:id}",
|
|
{'id': {'order': 'desc'}},
|
|
"sort"
|
|
)
|
|
|
|
|
|
def test_filter_as_field_order_by_dict():
|
|
filter_generation(
|
|
"articlesInMeta",
|
|
"headline: \"A text\", sort:{order:desc, field:id}",
|
|
{'es_id': {'order': 'desc'}},
|
|
"sort"
|
|
)
|
|
|
|
|
|
def test_filter_in_meta():
|
|
filter_generation(
|
|
"articlesInMeta",
|
|
"headline: \"A text\"",
|
|
Bool(must=[Match(headline={'query': 'A text', 'fuzziness': 'auto'})]),
|
|
)
|
|
|
|
|
|
def test_filter_in_meta_dict():
|
|
filter_generation(
|
|
"articlesInMetaDict",
|
|
"headline: \"A text\"",
|
|
Bool(must=[Match(headline={'query': 'A text', 'fuzziness': 'auto'})]),
|
|
)
|
|
|
|
|
|
def test_filter_in_meta_dict_foreign():
|
|
filter_generation(
|
|
"articlesInMetaDict",
|
|
"reporterEamail: \"A mail\"",
|
|
Bool(must=[Match(reporter__email={'query': 'A mail', 'fuzziness': 'auto'})]),
|
|
)
|
|
|
|
|
|
def test_filter_in_multi_field():
|
|
filter_generation(
|
|
"articlesInMultiField",
|
|
"contain: \"A text\"",
|
|
Bool(must=[Bool(should=[
|
|
Match(headline={'query': 'A text', 'fuzziness': 'auto'}),
|
|
Match(lang={'query': 'A text', 'fuzziness': 'auto'})
|
|
])]),
|
|
)
|
|
|
|
|
|
def test_filter_generating_all():
|
|
filter_generation(
|
|
"articlesInGenerateAll",
|
|
"headline: \"A text\", "
|
|
"pubDate: \"0000-00-00\", "
|
|
"pubDateTime: \"00:00:00\", "
|
|
"lang: \"es\", "
|
|
"importance: 1, ",
|
|
Bool(must=[
|
|
Match(headline={'query': 'A text', 'fuzziness': 'auto'}),
|
|
Match(pub_date={'query': '0000-00-00', 'fuzziness': 'auto'}),
|
|
Match(pub_date_time={'query': '00:00:00', 'fuzziness': 'auto'}),
|
|
Match(lang={'query': 'es', 'fuzziness': 'auto'}),
|
|
Term(importance=1)
|
|
]),
|
|
)
|
|
|
|
|
|
def test_filter_generating_exclude():
|
|
query = generate_query("articlesInExcludes", "headline: \"A text\", ")
|
|
|
|
schema = Schema(query=ESFilterQuery)
|
|
result = schema.execute(query)
|
|
|
|
assert len(result.errors) > 0
|
|
|
|
|
|
def test_filter_bad_processor():
|
|
class ArticleFilterBadProcessor(FilterSetES):
|
|
"""Article Filter for ES"""
|
|
|
|
class Meta(object):
|
|
"""Metaclass data"""
|
|
index = ArticleDocument
|
|
includes = {
|
|
'headline': {
|
|
'lookup_expressions': ['bad_processor']
|
|
}
|
|
}
|
|
|
|
with raises(ValueError) as error_info:
|
|
DjangoESFilterConnectionField(
|
|
ArticleNode, filterset_class=ArticleFilterBadProcessor
|
|
)
|
|
|
|
assert "bad_processor" in str(error_info.value)
|
|
|
|
|
|
def test_filter_field_without_filterset_class():
|
|
with raises(ValueError) as error_info:
|
|
DjangoESFilterConnectionField(
|
|
ArticleNode
|
|
)
|
|
|
|
assert "filterset_class" in str(error_info.value)
|
|
|
|
|
|
def test_filter_field_with_fields():
|
|
with raises(ValueError) as error_info:
|
|
DjangoESFilterConnectionField(
|
|
ArticleNode, fields=['headline']
|
|
)
|
|
|
|
assert "fields" in str(error_info.value)
|
|
|
|
|
|
def test_filter_field_with_order_by():
|
|
with raises(ValueError) as error_info:
|
|
DjangoESFilterConnectionField(
|
|
ArticleNode, order_by=['headline']
|
|
)
|
|
|
|
assert "order_by" in str(error_info.value)
|
|
|
|
|
|
def test_filter_filterset_without_index():
|
|
with raises(ValueError) as error_info:
|
|
class ArticleFilterBadProcessor(FilterSetES):
|
|
"""Article Filter for ES"""
|
|
|
|
class Meta(object):
|
|
"""Metaclass data"""
|
|
|
|
DjangoESFilterConnectionField(
|
|
ArticleNode, filterset_class=ArticleFilterBadProcessor
|
|
)
|
|
|
|
assert "Index in Meta" in str(error_info.value)
|
|
|
|
|
|
def test_filter_filterset_without_xcludes():
|
|
with raises(ValueError) as error_info:
|
|
class ArticleFilterBadProcessor(FilterSetES):
|
|
"""Article Filter for ES"""
|
|
|
|
class Meta(object):
|
|
"""Metaclass data"""
|
|
index = ArticleDocument
|
|
|
|
DjangoESFilterConnectionField(
|
|
ArticleNode, filterset_class=ArticleFilterBadProcessor
|
|
)
|
|
|
|
assert "includes or excludes field in Meta" in str(error_info.value)
|
|
|
|
|
|
def test_processor_term():
|
|
filter_generation(
|
|
"articlesInMetaDict",
|
|
"headlineTerm: \"A text\"",
|
|
Bool(must=[Term(headline='A text')]),
|
|
)
|
|
|
|
|
|
def test_processor_regex():
|
|
filter_generation(
|
|
"articlesInMetaDict",
|
|
"headlineRegex: \"A text\"",
|
|
Bool(must=[Wildcard(headline='A text')]),
|
|
)
|
|
|
|
|
|
def test_processor_phrase():
|
|
filter_generation(
|
|
"articlesInMetaDict",
|
|
"headlinePhrase: \"A text\"",
|
|
Bool(must=[MatchPhrase(headline={'query': 'A text'})]),
|
|
)
|
|
|
|
|
|
def test_processor_prefix():
|
|
filter_generation(
|
|
"articlesInMetaDict",
|
|
"headlinePrefix: \"A text\"",
|
|
Bool(must=[MatchPhrasePrefix(headline={'query': 'A text'})]),
|
|
)
|
|
|
|
|
|
def test_processor_in():
|
|
filter_generation(
|
|
"articlesInMetaDict",
|
|
"headlineIn: [\"A text 1\", \"A text 2\"]",
|
|
Bool(must=[Terms(headline=['A text 1', 'A text 2'])]),
|
|
)
|
|
|
|
|
|
def test_processor_exits():
|
|
filter_generation(
|
|
"articlesInMetaDict",
|
|
"headlineExits: true",
|
|
Bool(must=[Bool(must=[Exists(field='headline')])]),
|
|
)
|
|
|
|
|
|
def test_processor_lte():
|
|
filter_generation(
|
|
"articlesInMetaDict",
|
|
"headlineLte: \"A text\"",
|
|
Bool(must=Range(headline={'lte': 'A text'})),
|
|
)
|
|
|
|
|
|
def test_processor_gte():
|
|
filter_generation(
|
|
"articlesInMetaDict",
|
|
"headlineGte: \"A text\"",
|
|
Bool(must=Range(headline={'gte': 'A text'})),
|
|
)
|