99from graphene .relay import Node
1010from graphene_django import DjangoObjectType
1111from graphene_django .utils import DJANGO_FILTER_INSTALLED
12+ from graphene_django .filter import ArrayFilter , ListFilter
1213
1314from ...compat import ArrayField
1415
2728STORE = {"events" : []}
2829
2930
30- @pytest .fixture
31- def Event ():
32- class Event (models .Model ):
33- name = models .CharField (max_length = 50 )
34- tags = ArrayField (models .CharField (max_length = 50 ))
35-
36- return Event
31+ class Event (models .Model ):
32+ name = models .CharField (max_length = 50 )
33+ tags = ArrayField (models .CharField (max_length = 50 ))
34+ tag_ids = ArrayField (models .IntegerField ())
35+ random_field = ArrayField (models .BooleanField ())
3736
3837
3938@pytest .fixture
40- def EventFilterSet (Event ):
41-
42- from django .contrib .postgres .forms import SimpleArrayField
43-
44- class ArrayFilter (filters .Filter ):
45- base_field_class = SimpleArrayField
46-
39+ def EventFilterSet ():
4740 class EventFilterSet (FilterSet ):
4841 class Meta :
4942 model = Event
5043 fields = {
51- "name" : ["exact" ],
44+ "name" : ["exact" , "contains" ],
5245 }
5346
47+ # Those are actually usable with our Query fixture bellow
5448 tags__contains = ArrayFilter (field_name = "tags" , lookup_expr = "contains" )
5549 tags__overlap = ArrayFilter (field_name = "tags" , lookup_expr = "overlap" )
50+ tags = ArrayFilter (field_name = "tags" , lookup_expr = "exact" )
51+
52+ # Those are actually not usable and only to check type declarations
53+ tags_ids__contains = ArrayFilter (field_name = "tag_ids" , lookup_expr = "contains" )
54+ tags_ids__overlap = ArrayFilter (field_name = "tag_ids" , lookup_expr = "overlap" )
55+ tags_ids = ArrayFilter (field_name = "tag_ids" , lookup_expr = "exact" )
56+ random_field__contains = ArrayFilter (
57+ field_name = "random_field" , lookup_expr = "contains"
58+ )
59+ random_field__overlap = ArrayFilter (
60+ field_name = "random_field" , lookup_expr = "overlap"
61+ )
62+ random_field = ArrayFilter (field_name = "random_field" , lookup_expr = "exact" )
5663
5764 return EventFilterSet
5865
5966
6067@pytest .fixture
61- def EventType (Event , EventFilterSet ):
68+ def EventType (EventFilterSet ):
6269 class EventType (DjangoObjectType ):
6370 class Meta :
6471 model = Event
6572 interfaces = (Node ,)
73+ fields = "__all__"
6674 filterset_class = EventFilterSet
6775
6876 return EventType
6977
7078
7179@pytest .fixture
72- def Query (Event , EventType ):
80+ def Query (EventType ):
81+ """
82+ Note that we have to use a custom resolver to replicate the arrayfield filter behavior as
83+ we are running unit tests in sqlite which does not have ArrayFields.
84+ """
85+
7386 class Query (graphene .ObjectType ):
7487 events = DjangoFilterConnectionField (EventType )
7588
@@ -79,6 +92,7 @@ def resolve_events(self, info, **kwargs):
7992 Event (name = "Live Show" , tags = ["concert" , "music" , "rock" ],),
8093 Event (name = "Musical" , tags = ["movie" , "music" ],),
8194 Event (name = "Ballet" , tags = ["concert" , "dance" ],),
95+ Event (name = "Speech" , tags = [],),
8296 ]
8397
8498 STORE ["events" ] = events
@@ -105,6 +119,13 @@ def filter_events(**kwargs):
105119 STORE ["events" ],
106120 )
107121 )
122+ if "tags__exact" in kwargs :
123+ STORE ["events" ] = list (
124+ filter (
125+ lambda e : set (kwargs ["tags__exact" ]) == set (e .tags ),
126+ STORE ["events" ],
127+ )
128+ )
108129
109130 def mock_queryset_filter (* args , ** kwargs ):
110131 filter_events (** kwargs )
@@ -121,7 +142,9 @@ def mock_queryset_count(*args, **kwargs):
121142 m_queryset .filter .side_effect = mock_queryset_filter
122143 m_queryset .none .side_effect = mock_queryset_none
123144 m_queryset .count .side_effect = mock_queryset_count
124- m_queryset .__getitem__ .side_effect = STORE ["events" ].__getitem__
145+ m_queryset .__getitem__ .side_effect = lambda index : STORE [
146+ "events"
147+ ].__getitem__ (index )
125148
126149 return m_queryset
127150
0 commit comments