22Tests for Documents API endpoint in impress's core app: list
33"""
44
5+ import random
56from json import loads as json_loads
67
8+ from django .test import RequestFactory
9+
710import pytest
811import responses
912from faker import Faker
1619pytestmark = pytest .mark .django_db
1720
1821
22+ def build_search_url (** kwargs ):
23+ """Build absolute uri for search endpoint with ORDERED query arguments"""
24+ return (
25+ RequestFactory ()
26+ .get ("/api/v1.0/documents/search/" , dict (sorted (kwargs .items ())))
27+ .build_absolute_uri ()
28+ )
29+
30+
1931@pytest .mark .parametrize ("role" , models .LinkRoleChoices .values )
2032@pytest .mark .parametrize ("reach" , models .LinkReachChoices .values )
2133@responses .activate
@@ -191,8 +203,62 @@ def test_api_documents_search_format(indexer_settings):
191203
192204
193205@responses .activate
194- def test_api_documents_search_pagination (indexer_settings ):
195- """Documents should be ordered by descending "updated_at" by default"""
206+ @pytest .mark .parametrize (
207+ "pagination, status, expected" ,
208+ (
209+ (
210+ {"page" : 1 , "page_size" : 10 },
211+ 200 ,
212+ {
213+ "count" : 10 ,
214+ "previous" : None ,
215+ "next" : None ,
216+ "range" : (0 , None ),
217+ },
218+ ),
219+ (
220+ {},
221+ 200 ,
222+ {
223+ "count" : 10 ,
224+ "previous" : None ,
225+ "next" : None ,
226+ "range" : (0 , None ),
227+ "api_page_size" : 21 , # default page_size is 20
228+ },
229+ ),
230+ (
231+ {"page" : 2 , "page_size" : 10 },
232+ 404 ,
233+ {},
234+ ),
235+ (
236+ {"page" : 1 , "page_size" : 5 },
237+ 200 ,
238+ {
239+ "count" : 10 ,
240+ "previous" : None ,
241+ "next" : {"page" : 2 , "page_size" : 5 },
242+ "range" : (0 , 5 ),
243+ },
244+ ),
245+ (
246+ {"page" : 2 , "page_size" : 5 },
247+ 200 ,
248+ {
249+ "count" : 10 ,
250+ "previous" : {"page_size" : 5 },
251+ "next" : None ,
252+ "range" : (5 , None ),
253+ },
254+ ),
255+ ({"page" : 3 , "page_size" : 5 }, 404 , {}),
256+ ),
257+ )
258+ def test_api_documents_search_pagination (
259+ indexer_settings , pagination , status , expected
260+ ):
261+ """Documents should be ordered by descending "score" by default"""
196262 indexer_settings .SEARCH_INDEXER_QUERY_URL = "http://find/api/v1.0/search"
197263
198264 assert get_document_indexer () is not None
@@ -202,35 +268,159 @@ def test_api_documents_search_pagination(indexer_settings):
202268 client = APIClient ()
203269 client .force_login (user )
204270
205- docs = factories .DocumentFactory .create_batch (10 )
271+ docs = factories .DocumentFactory .create_batch (10 , title = "alpha" , users = [user ])
272+
273+ docs_by_uuid = {str (doc .pk ): doc for doc in docs }
274+ api_results = [{"_id" : id } for id in docs_by_uuid .keys ()]
275+
276+ # reorder randomly to simulate score ordering
277+ random .shuffle (api_results )
206278
207279 # Find response
208280 # pylint: disable-next=assignment-from-none
209281 api_search = responses .add (
210282 responses .POST ,
211283 "http://find/api/v1.0/search" ,
212- json = [{ "_id" : str ( doc . pk )} for doc in docs ] ,
284+ json = api_results ,
213285 status = 200 ,
214286 )
215287
216288 response = client .get (
217- "/api/v1.0/documents/search/" , data = {"q" : "alpha" , "page" : 2 , "page_size" : 5 }
289+ "/api/v1.0/documents/search/" ,
290+ data = {
291+ "q" : "alpha" ,
292+ ** pagination ,
293+ },
218294 )
219295
220- assert response .status_code == 200
221- content = response .json ()
222- results = content .pop ("results" )
223- assert len (results ) == 5
224-
225- # Check the query parameters.
226- assert api_search .call_count == 1
227- assert api_search .calls [0 ].response .status_code == 200
228- assert json_loads (api_search .calls [0 ].request .body ) == {
229- "q" : "alpha" ,
230- "visited" : [],
231- "services" : ["docs" ],
232- "page_number" : 2 ,
233- "page_size" : 5 ,
234- "order_by" : "updated_at" ,
235- "order_direction" : "desc" ,
236- }
296+ assert response .status_code == status
297+
298+ if response .status_code < 300 :
299+ previous_url = (
300+ build_search_url (q = "alpha" , ** expected ["previous" ])
301+ if expected ["previous" ]
302+ else None
303+ )
304+ next_url = (
305+ build_search_url (q = "alpha" , ** expected ["next" ])
306+ if expected ["next" ]
307+ else None
308+ )
309+ start , end = expected ["range" ]
310+
311+ content = response .json ()
312+
313+ assert content ["count" ] == expected ["count" ]
314+ assert content ["previous" ] == previous_url
315+ assert content ["next" ] == next_url
316+
317+ results = content .pop ("results" )
318+
319+ # The find api results ordering by score is kept
320+ assert [r ["id" ] for r in results ] == [r ["_id" ] for r in api_results [start :end ]]
321+
322+ # Check the query parameters.
323+ assert api_search .call_count == 1
324+ assert api_search .calls [0 ].response .status_code == 200
325+ assert json_loads (api_search .calls [0 ].request .body ) == {
326+ "q" : "alpha" ,
327+ "visited" : [],
328+ "services" : ["docs" ],
329+ "page_number" : 1 ,
330+ "page_size" : 100 ,
331+ "order_by" : "updated_at" ,
332+ "order_direction" : "desc" ,
333+ }
334+
335+
336+ @responses .activate
337+ @pytest .mark .parametrize (
338+ "pagination, status, expected" ,
339+ (
340+ (
341+ {"page" : 1 , "page_size" : 10 },
342+ 200 ,
343+ {"count" : 10 , "previous" : None , "next" : None , "range" : (0 , None )},
344+ ),
345+ (
346+ {},
347+ 200 ,
348+ {"count" : 10 , "previous" : None , "next" : None , "range" : (0 , None )},
349+ ),
350+ (
351+ {"page" : 2 , "page_size" : 10 },
352+ 404 ,
353+ {},
354+ ),
355+ (
356+ {"page" : 1 , "page_size" : 5 },
357+ 200 ,
358+ {
359+ "count" : 10 ,
360+ "previous" : None ,
361+ "next" : {"page" : 2 , "page_size" : 5 },
362+ "range" : (0 , 5 ),
363+ },
364+ ),
365+ (
366+ {"page" : 2 , "page_size" : 5 },
367+ 200 ,
368+ {
369+ "count" : 10 ,
370+ "previous" : {"page_size" : 5 },
371+ "next" : None ,
372+ "range" : (5 , None ),
373+ },
374+ ),
375+ ({"page" : 3 , "page_size" : 5 }, 404 , {}),
376+ ),
377+ )
378+ def test_api_documents_search_pagination_endpoint_is_none (
379+ indexer_settings , pagination , status , expected
380+ ):
381+ """Documents should be ordered by descending "-updated_at" by default"""
382+ indexer_settings .SEARCH_INDEXER_QUERY_URL = None
383+
384+ assert get_document_indexer () is None
385+
386+ user = factories .UserFactory ()
387+
388+ client = APIClient ()
389+ client .force_login (user )
390+
391+ factories .DocumentFactory .create_batch (10 , title = "alpha" , users = [user ])
392+
393+ response = client .get (
394+ "/api/v1.0/documents/search/" ,
395+ data = {
396+ "q" : "alpha" ,
397+ ** pagination ,
398+ },
399+ )
400+
401+ assert response .status_code == status
402+
403+ if response .status_code < 300 :
404+ previous_url = (
405+ build_search_url (q = "alpha" , ** expected ["previous" ])
406+ if expected ["previous" ]
407+ else None
408+ )
409+ next_url = (
410+ build_search_url (q = "alpha" , ** expected ["next" ])
411+ if expected ["next" ]
412+ else None
413+ )
414+ queryset = models .Document .objects .order_by ("-updated_at" )
415+ start , end = expected ["range" ]
416+ expected_results = [str (d .pk ) for d in queryset [start :end ]]
417+
418+ content = response .json ()
419+
420+ assert content ["count" ] == expected ["count" ]
421+ assert content ["previous" ] == previous_url
422+ assert content ["next" ] == next_url
423+
424+ results = content .pop ("results" )
425+
426+ assert [r ["id" ] for r in results ] == expected_results
0 commit comments