|
225 | 225 | }, |
226 | 226 | ) |
227 | 227 |
|
| 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 | + |
228 | 329 | # HELPER FUNCTIONS for compiling test data into pytest parameters |
229 | 330 |
|
230 | 331 | def compile_params(parameters): |
@@ -693,3 +794,53 @@ def test_shelflistitem_put_data_missing_fields(fname_solr, fname_api, |
693 | 794 | assert resp.status_code == 200 |
694 | 795 | assert before.data[fname_api] == start_val |
695 | 796 | 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) |
0 commit comments