1
- from unittest . mock import MagicMock
1
+ from functools import reduce
2
2
3
3
import pytest
4
4
from django .db import models
25
25
)
26
26
27
27
28
- STORE = {"events" : []}
29
-
30
-
31
28
class Event (models .Model ):
32
29
name = models .CharField (max_length = 50 )
33
30
tags = ArrayField (models .CharField (max_length = 50 ))
34
31
tag_ids = ArrayField (models .IntegerField ())
35
32
random_field = ArrayField (models .BooleanField ())
36
33
34
+ def __repr__ (self ):
35
+ return f"Event [{ self .name } ]"
36
+
37
37
38
38
@pytest .fixture
39
39
def EventFilterSet ():
@@ -48,6 +48,14 @@ class Meta:
48
48
tags__contains = ArrayFilter (field_name = "tags" , lookup_expr = "contains" )
49
49
tags__overlap = ArrayFilter (field_name = "tags" , lookup_expr = "overlap" )
50
50
tags = ArrayFilter (field_name = "tags" , lookup_expr = "exact" )
51
+ tags__len = ArrayFilter (
52
+ field_name = "tags" , lookup_expr = "len" , input_type = graphene .Int
53
+ )
54
+ tags__len__in = ArrayFilter (
55
+ field_name = "tags" ,
56
+ method = "tags__len__in_filter" ,
57
+ input_type = graphene .List (graphene .Int ),
58
+ )
51
59
52
60
# Those are actually not usable and only to check type declarations
53
61
tags_ids__contains = ArrayFilter (field_name = "tag_ids" , lookup_expr = "contains" )
@@ -61,6 +69,14 @@ class Meta:
61
69
)
62
70
random_field = ArrayFilter (field_name = "random_field" , lookup_expr = "exact" )
63
71
72
+ def tags__len__in_filter (self , queryset , _name , value ):
73
+ if not value :
74
+ return queryset .none ()
75
+ return reduce (
76
+ lambda q1 , q2 : q1 .union (q2 ),
77
+ [queryset .filter (tags__len = v ) for v in value ],
78
+ ).distinct ()
79
+
64
80
return EventFilterSet
65
81
66
82
@@ -83,68 +99,94 @@ def Query(EventType):
83
99
we are running unit tests in sqlite which does not have ArrayFields.
84
100
"""
85
101
102
+ events = [
103
+ Event (name = "Live Show" , tags = ["concert" , "music" , "rock" ]),
104
+ Event (name = "Musical" , tags = ["movie" , "music" ]),
105
+ Event (name = "Ballet" , tags = ["concert" , "dance" ]),
106
+ Event (name = "Speech" , tags = []),
107
+ ]
108
+
86
109
class Query (graphene .ObjectType ):
87
110
events = DjangoFilterConnectionField (EventType )
88
111
89
112
def resolve_events (self , info , ** kwargs ):
90
- events = [
91
- Event (name = "Live Show" , tags = ["concert" , "music" , "rock" ]),
92
- Event (name = "Musical" , tags = ["movie" , "music" ]),
93
- Event (name = "Ballet" , tags = ["concert" , "dance" ]),
94
- Event (name = "Speech" , tags = []),
95
- ]
96
-
97
- STORE ["events" ] = events
98
-
99
- m_queryset = MagicMock (spec = QuerySet )
100
- m_queryset .model = Event
101
-
102
- def filter_events (** kwargs ):
103
- if "tags__contains" in kwargs :
104
- STORE ["events" ] = list (
105
- filter (
106
- lambda e : set (kwargs ["tags__contains" ]).issubset (
107
- set (e .tags )
108
- ),
109
- STORE ["events" ],
113
+ class FakeQuerySet (QuerySet ):
114
+ def __init__ (self , model = None ):
115
+ self .model = Event
116
+ self .__store = list (events )
117
+
118
+ def all (self ):
119
+ return self
120
+
121
+ def filter (self , ** kwargs ):
122
+ queryset = FakeQuerySet ()
123
+ queryset .__store = list (self .__store )
124
+ if "tags__contains" in kwargs :
125
+ queryset .__store = list (
126
+ filter (
127
+ lambda e : set (kwargs ["tags__contains" ]).issubset (
128
+ set (e .tags )
129
+ ),
130
+ queryset .__store ,
131
+ )
132
+ )
133
+ if "tags__overlap" in kwargs :
134
+ queryset .__store = list (
135
+ filter (
136
+ lambda e : not set (kwargs ["tags__overlap" ]).isdisjoint (
137
+ set (e .tags )
138
+ ),
139
+ queryset .__store ,
140
+ )
110
141
)
111
- )
112
- if "tags__overlap" in kwargs :
113
- STORE ["events" ] = list (
114
- filter (
115
- lambda e : not set (kwargs ["tags__overlap" ]).isdisjoint (
116
- set (e .tags )
117
- ),
118
- STORE ["events" ],
142
+ if "tags__exact" in kwargs :
143
+ queryset .__store = list (
144
+ filter (
145
+ lambda e : set (kwargs ["tags__exact" ]) == set (e .tags ),
146
+ queryset .__store ,
147
+ )
119
148
)
120
- )
121
- if "tags__exact" in kwargs :
122
- STORE [ "events" ] = list (
123
- filter (
124
- lambda e : set ( kwargs [ "tags__exact" ]) == set ( e . tags ) ,
125
- STORE [ "events" ],
149
+ if "tags__len" in kwargs :
150
+ queryset . __store = list (
151
+ filter (
152
+ lambda e : len ( e . tags ) == kwargs [ "tags__len" ],
153
+ queryset . __store ,
154
+ )
126
155
)
127
- )
156
+ return queryset
157
+
158
+ def union (self , * args ):
159
+ queryset = FakeQuerySet ()
160
+ queryset .__store = self .__store
161
+ for arg in args :
162
+ queryset .__store += arg .__store
163
+ return queryset
128
164
129
- def mock_queryset_filter (* args , ** kwargs ):
130
- filter_events (** kwargs )
131
- return m_queryset
165
+ def none (self ):
166
+ queryset = FakeQuerySet ()
167
+ queryset .__store = []
168
+ return queryset
132
169
133
- def mock_queryset_none (* args , ** kwargs ):
134
- STORE ["events" ] = []
135
- return m_queryset
170
+ def count (self ):
171
+ return len (self .__store )
136
172
137
- def mock_queryset_count (* args , ** kwargs ):
138
- return len (STORE ["events" ])
173
+ def distinct (self ):
174
+ queryset = FakeQuerySet ()
175
+ queryset .__store = []
176
+ for event in self .__store :
177
+ if event not in queryset .__store :
178
+ queryset .__store .append (event )
179
+ queryset .__store = sorted (queryset .__store , key = lambda e : e .name )
180
+ return queryset
139
181
140
- m_queryset .all .return_value = m_queryset
141
- m_queryset .filter .side_effect = mock_queryset_filter
142
- m_queryset .none .side_effect = mock_queryset_none
143
- m_queryset .count .side_effect = mock_queryset_count
144
- m_queryset .__getitem__ .side_effect = lambda index : STORE [
145
- "events"
146
- ].__getitem__ (index )
182
+ def __getitem__ (self , index ):
183
+ return self .__store [index ]
147
184
148
- return m_queryset
185
+ return FakeQuerySet ()
149
186
150
187
return Query
188
+
189
+
190
+ @pytest .fixture
191
+ def schema (Query ):
192
+ return graphene .Schema (query = Query )
0 commit comments