Skip to content

Commit 755dfa9

Browse files
committed
Fix shelflistitem.views.FirstItemPerLocationList
This corrects a small oversight in which I neglected to realize that the `shelflist` app implemented a specialized/extended version of `api.views.FirstItemPerLocationList`. When refactoring `api.simpleviews`, I broke the `SimpleGetMixin` `paginate` method into several smaller methods. I updated the `api.views.FirstItemPerLocationList` view to use the new method, but I didn't update the `shelflist.views.FirstItemPerLocationList`, and I didn't add tests to test it. This corrects that mistake--it addes the appropriate tests and fixes the issue by simply renaming that method on the `shelflist` version of the view.
1 parent 8c9772f commit 755dfa9

2 files changed

Lines changed: 158 additions & 7 deletions

File tree

django/sierra/shelflist/tests/test_api.py

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,107 @@
225225
},
226226
)
227227

228+
229+
# TESTDATA__FIRSTITEMPERLOCATION: We use a consistent set of test data
230+
# for testing the firstitemperlocation resource.
231+
TESTDATA__FIRSTITEMPERLOCATION = (
232+
( 'atest1', 1,
233+
{ 'location_code': 'atest',
234+
'barcode': '1',
235+
'call_number': 'BB 1234 C35 1990',
236+
'call_number_type': 'lc'} ),
237+
( 'atest2', 0,
238+
{ 'location_code': 'atest',
239+
'barcode': '2',
240+
'call_number': 'BB 1234 A22 2000',
241+
'call_number_type': 'lc' } ),
242+
( 'atest3', 2,
243+
{ 'location_code': 'atest',
244+
'barcode': '3',
245+
'call_number': 'BC 2345 F80',
246+
'call_number_type': 'lc' } ),
247+
( 'atest4', 3,
248+
{ 'location_code': 'atest',
249+
'barcode': '4',
250+
'call_number': 'BB 1234',
251+
'call_number_type': 'sudoc' } ),
252+
( 'btest1', 0,
253+
{ 'location_code': 'btest',
254+
'barcode': '3',
255+
'call_number': 'BB 1234 D99',
256+
'call_number_type': 'lc' } ),
257+
( 'btest2', 3,
258+
{ 'location_code': 'btest',
259+
'barcode': '4',
260+
'call_number': 'BB 1234 A22',
261+
'call_number_type': 'sudoc' } ),
262+
( 'btest3', 1,
263+
{ 'location_code': 'btest',
264+
'barcode': '5',
265+
'call_number': 'CC 9876 H43',
266+
'call_number_type': 'lc' } ),
267+
( 'btest4', 2,
268+
{ 'location_code': 'btest',
269+
'barcode': '6',
270+
'call_number': 'BB 1234',
271+
'call_number_type': 'sudoc' } ),
272+
( 'ctest1', 1,
273+
{ 'location_code': 'ctest',
274+
'barcode': '8',
275+
'call_number': 'BB 1234 D99 2016',
276+
'call_number_type': 'lc' } ),
277+
( 'ctest2', 3,
278+
{ 'location_code': 'ctest',
279+
'barcode': '9',
280+
'call_number': 'CC 1234 A22',
281+
'call_number_type': 'other' } ),
282+
( 'ctest3', 0,
283+
{ 'location_code': 'ctest',
284+
'barcode': '10',
285+
'call_number': '900.1 H43',
286+
'call_number_type': 'dewey' } ),
287+
( 'ctest4', 2,
288+
{ 'location_code': 'ctest',
289+
'barcode': '11',
290+
'call_number': 'AB 1234',
291+
'call_number_type': 'other' } ),
292+
)
293+
294+
295+
PARAMETERS__FIRSTITEMPERLOCATION = (
296+
('test_data, search, expected'),
297+
{ 'LC call number type | A match at each location':
298+
(TESTDATA__FIRSTITEMPERLOCATION,
299+
'callNumber[startswith]=BB 12&callNumberType=lc',
300+
['atest2', 'btest1', 'ctest1']),
301+
}, { 'LC call number type | A match at one location':
302+
(TESTDATA__FIRSTITEMPERLOCATION,
303+
'callNumber[startswith]=BC&callNumberType=lc',
304+
['atest3']),
305+
}, { 'LC call number type | No matches':
306+
(TESTDATA__FIRSTITEMPERLOCATION,
307+
'callNumber[startswith]=D&callNumberType=lc',
308+
None),
309+
}, { 'SUDOC call number type | A match at two locations':
310+
(TESTDATA__FIRSTITEMPERLOCATION,
311+
'callNumber[startswith]=BB&callNumberType=sudoc',
312+
['atest4', 'btest4']),
313+
}, { 'DEWEY call number type | A match at one location':
314+
(TESTDATA__FIRSTITEMPERLOCATION,
315+
'callNumber[startswith]=900&callNumberType=dewey',
316+
['ctest3']),
317+
}, { 'OTHER call number type | A match at one location':
318+
(TESTDATA__FIRSTITEMPERLOCATION,
319+
'callNumber[startswith]=C&callNumberType=other',
320+
['ctest2']),
321+
}, { 'BARCODE | A match at two locations':
322+
(TESTDATA__FIRSTITEMPERLOCATION,
323+
'barcode=3',
324+
['atest3', 'btest1']),
325+
},
326+
)
327+
328+
228329
# HELPER FUNCTIONS for compiling test data into pytest parameters
229330

230331
def compile_params(parameters):
@@ -693,3 +794,53 @@ def test_shelflistitem_put_data_missing_fields(fname_solr, fname_api,
693794
assert resp.status_code == 200
694795
assert before.data[fname_api] == start_val
695796
assert after.data[fname_api] is None
797+
798+
799+
@pytest.mark.parametrize('test_data, search, expected',
800+
compile_params(PARAMETERS__FIRSTITEMPERLOCATION),
801+
ids=compile_ids(PARAMETERS__FIRSTITEMPERLOCATION))
802+
def test_shelflist_firstitemperlocation_list(test_data, search, expected,
803+
api_settings, redis_obj,
804+
assemble_custom_shelflist,
805+
api_client, get_found_ids,
806+
do_filter_search):
807+
"""
808+
The `firstitemperlocation` resource is basically a custom filter
809+
for `items` that submits a facet-query to Solr asking for the first
810+
item at each location code that matches the provided call number
811+
(plus cn type) or barcode. (Used by the Inventory App when doing a
812+
call number or barcode lookup without providing a location.) The
813+
`api` app contains a basic implementation, but it lacks the
814+
`shelflist`-specific extensions needed to make the Inventory App
815+
functionality work--namely the rowNumber from the shelflistitem
816+
manifest. This tests to make sure the `shelflist` app version
817+
overrides the `api` version and includes the rowNumber field.
818+
"""
819+
test_data_by_location = {}
820+
for test_id, _, rec in test_data:
821+
lcode = rec['location_code']
822+
recs = test_data_by_location.get(lcode, []) + [(test_id, rec)]
823+
test_data_by_location[lcode] = recs
824+
825+
index = ShelflistItemIndex()
826+
for test_lcode, data in test_data_by_location.items():
827+
assemble_custom_shelflist(test_lcode, data, id_field='record_number')
828+
manifest = index.get_location_manifest(test_lcode)
829+
redis_key = '{}:{}'.format(REDIS_SHELFLIST_PREFIX, test_lcode)
830+
redis_obj(redis_key).set(manifest)
831+
832+
resource_url = '{}firstitemperlocation/'.format(API_ROOT)
833+
rsp = do_filter_search(resource_url, search, api_client)
834+
rsp_items = rsp.data['_embedded']['items']
835+
836+
if expected is None:
837+
for item in rsp_items:
838+
assert item['locationCode'] not in test_data_by_location.keys()
839+
else:
840+
for exp_id in expected:
841+
exp_row = [i[1] for i in test_data if i[0] == exp_id][0]
842+
item = [i for i in rsp_items if i['recordNumber'] == exp_id][0]
843+
exp_sli = '{}/shelflistitems/{}'.format(item['locationCode'],
844+
item['id'])
845+
assert item['rowNumber'] == exp_row
846+
assert item['_links']['shelflistItem']['href'].endswith(exp_sli)

django/sierra/shelflist/views.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@ def api_root(request):
3434

3535

3636
class ShelflistItemList(SimpleGetMixin, SimpleView):
37-
'''
37+
"""
3838
Paginated list of items. Use the 'page' query parameter to specify
3939
the page number.
40-
'''
40+
"""
4141
serializer_class = serializers.ShelflistItemSerializer
4242
ordering = None
4343
filter_fields = ['call_number', 'call_number_type', 'barcode',
@@ -54,9 +54,9 @@ def get_queryset(self):
5454
# Put/Patch behavior. Disabled for now for security in production.
5555
class ShelflistItemDetail(SimplePutMixin, SimplePatchMixin, SimpleGetMixin,
5656
SimpleView):
57-
'''
57+
"""
5858
Retrieve one item.
59-
'''
59+
"""
6060
queryset = solr.Queryset().filter(type='Item')
6161
serializer_class = serializers.ShelflistItemSerializer
6262
multi = False
@@ -91,9 +91,9 @@ class ItemDetail(api_views.ItemDetail):
9191

9292

9393
class FirstItemPerLocationList(api_views.FirstItemPerLocationList):
94-
def paginate(self, queryset, request):
95-
data = super(FirstItemPerLocationList, self).paginate(queryset,
96-
request)
94+
def get_page_data(self, queryset, request):
95+
data = super(FirstItemPerLocationList, self).get_page_data(queryset,
96+
request)
9797
for item in data['_embedded']['items']:
9898
l_code = item['locationCode']
9999
this_id = item['id']

0 commit comments

Comments
 (0)