def test_recall_notification_without_email( client, patron_sion_without_email1, lib_martigny, json_header, patron2_martigny, item3_lib_martigny, librarian_martigny, circulation_policies, loc_public_martigny, mailbox): """Test recall notification.""" mailbox.clear() login_user_via_session(client, librarian_martigny.user) res, data = postdata( client, 'api_item.checkout', dict( item_pid=item3_lib_martigny.pid, patron_pid=patron_sion_without_email1.pid, transaction_location_pid=loc_public_martigny.pid, transaction_user_pid=librarian_martigny.pid, )) assert res.status_code == 200 loan_pid = data.get('action_applied')[LoanAction.CHECKOUT].get('pid') loan = Loan.get_record_by_pid(loan_pid) assert not loan.is_notified( notification_type=Notification.RECALL_NOTIFICATION_TYPE) # test notification res, data = postdata( client, 'api_item.librarian_request', dict(item_pid=item3_lib_martigny.pid, pickup_location_pid=loc_public_martigny.pid, patron_pid=patron2_martigny.pid, transaction_library_pid=lib_martigny.pid, transaction_user_pid=librarian_martigny.pid)) assert res.status_code == 200 request_loan_pid = data.get('action_applied')[LoanAction.REQUEST].get( 'pid') flush_index(NotificationsSearch.Meta.index) assert loan.is_notified( notification_type=Notification.RECALL_NOTIFICATION_TYPE) notification = get_notification( loan, notification_type=Notification.RECALL_NOTIFICATION_TYPE) assert notification.loan_pid == loan.pid assert not loan.is_notified( notification_type=Notification.AVAILABILITY_NOTIFICATION_TYPE) assert not get_notification( loan, notification_type=Notification.AVAILABILITY_NOTIFICATION_TYPE) # one new email for the librarian assert mailbox[0].recipients == [ lib_martigny.email_notification_type(notification['notification_type']) ] mailbox.clear()
def test_patron_information(client, librarian_martigny, selfcheck_patron_martigny, loc_public_martigny, item_lib_martigny, item2_lib_martigny, circulation_policies, lib_martigny): """Test patron information.""" login_user_via_session(client, librarian_martigny.user) # checkout res, data = postdata( client, 'api_item.checkout', dict(item_pid=item_lib_martigny.pid, patron_pid=selfcheck_patron_martigny.pid, transaction_user_pid=librarian_martigny.pid, transaction_location_pid=loc_public_martigny.pid)) assert res.status_code == 200 actions = data.get('action_applied') loan_pid = actions[LoanAction.CHECKOUT].get('pid') loan = Loan.get_record_by_pid(loan_pid) assert not loan.is_loan_overdue() # set loan on overdue end_date = datetime.now(timezone.utc) - timedelta(days=7) loan['end_date'] = end_date.isoformat() loan.update(loan, dbcommit=True, reindex=True) loan = Loan.get_record_by_pid(loan_pid) assert loan.is_loan_overdue() loan.create_notification( notification_type=Notification.OVERDUE_NOTIFICATION_TYPE) flush_index(NotificationsSearch.Meta.index) flush_index(LoansSearch.Meta.index) assert number_of_reminders_sent(loan) == 1 # create request res, data = postdata( client, 'api_item.librarian_request', dict(item_pid=item2_lib_martigny.pid, patron_pid=selfcheck_patron_martigny.pid, pickup_location_pid=loc_public_martigny.pid, transaction_library_pid=lib_martigny.pid, transaction_user_pid=librarian_martigny.pid)) assert res.status_code == 200 # get patron information response = patron_information( selfcheck_patron_martigny.get('patron', {}).get('barcode')[0]) assert response # checkin res, _ = postdata( client, 'api_item.checkin', dict(item_pid=item_lib_martigny.pid, pid=loan_pid, transaction_user_pid=librarian_martigny.pid, transaction_location_pid=loc_public_martigny.pid)) assert res.status_code == 200
def test_local_fields_post_put_delete(client, org_sion, document, local_field_sion_data, json_header): """Test POST and PUT on local fields.""" lf_pid = local_field_sion_data['pid'] item_url = url_for('invenio_records_rest.lofi_item', pid_value=lf_pid) list_url = url_for('invenio_records_rest.lofi_list', q=f'pid:{lf_pid}') res, data = postdata(client, 'invenio_records_rest.lofi_list', local_field_sion_data) assert res.status_code == 201 assert data['metadata'] == local_field_sion_data res = client.get(item_url) assert res.status_code == 200 data = get_json(res) assert local_field_sion_data == data['metadata'] data = deepcopy(local_field_sion_data) data['fields']['field_2'] = ['field 2'] res = client.put( item_url, data=json.dumps(data), headers=json_header ) assert res.status_code == 200 data = get_json(res) assert data['metadata']['fields']['field_2'][0] == 'field 2' res = client.get(list_url) assert res.status_code == 200 data = get_json(res)['hits']['hits'][0] assert data['metadata']['fields']['field_2'][0] == 'field 2' # Check duplicate record res, _ = postdata(client, 'invenio_records_rest.lofi_list', data) assert res.status_code == 400 res = client.get(url_for( 'invenio_records_rest.lofi_list', q=f'organisation.pid:{data["metadata"]["organisation"]["pid"]}')) data = get_json(res) assert data['hits']['total']['value'] == 1 # Delete record res = client.delete(item_url) assert res.status_code == 204 res = client.get(item_url) assert res.status_code == 410
def test_checking_out_external_items_at_non_circ_library( client, librarian_martigny, lib_martigny, lib_martigny_bourg, patron_martigny, loc_public_martigny, loc_public_martigny_bourg, item_lib_martigny_bourg, circulation_policies, item_lib_martigny, librarian_martigny_bourg): """Test checkout of external items at non-circ library.""" login_user_via_session(client, librarian_martigny_bourg.user) # A non-circulation library (has no pickup configured) and library hours is # well configured opening_hours = [ { "day": "monday", "is_open": True, "times": [ { "start_time": "07:00", "end_time": "19:00" } ] } ] lib_martigny_bourg['opening_hours'] = opening_hours lib_martigny_bourg.update(lib_martigny_bourg, dbcommit=True, reindex=True) # a librarian from the non-circulating library can checkout items from # another library into his library params = dict( item_pid=item_lib_martigny.pid, patron_pid=patron_martigny.pid, transaction_user_pid=librarian_martigny_bourg.pid, transaction_library_pid=lib_martigny_bourg.pid, ) res, data = postdata( client, 'api_item.checkout', params ) assert res.status_code == 200 # the checkin is possible at the non-circulating library and the item goes # directly to in-transit res, data = postdata( client, 'api_item.checkin', dict( item_pid=item_lib_martigny.pid, transaction_library_pid=lib_martigny_bourg.pid, transaction_user_pid=librarian_martigny_bourg.pid, ) ) assert res.status_code == 200 item = Item.get_record_by_pid(item_lib_martigny.pid) assert item.status == ItemStatus.IN_TRANSIT
def test_create_over_and_due_soon_notifications_task( client, librarian_martigny_no_email, patron_martigny_no_email, item_lib_martigny, circ_policy_short_martigny, loc_public_martigny, lib_martigny): """Test overdue and due_soon loans.""" login_user_via_session(client, librarian_martigny_no_email.user) item = item_lib_martigny item_pid = item.pid patron_pid = patron_martigny_no_email.pid # checkout res, data = postdata(client, 'api_item.checkout', dict(item_pid=item_pid, patron_pid=patron_pid)) assert res.status_code == 200 loan_pid = data.get('action_applied')[LoanAction.CHECKOUT].get('pid') loan = Loan.get_record_by_pid(loan_pid) # test due_soon notification end_date = datetime.now(timezone.utc) + timedelta(days=3) loan['end_date'] = end_date.isoformat() loan.update(loan, dbcommit=True, reindex=True) due_soon_loans = get_due_soon_loans() assert due_soon_loans[0].get('pid') == loan_pid create_over_and_due_soon_notifications() flush_index(NotificationsSearch.Meta.index) flush_index(LoansSearch.Meta.index) assert loan.is_notified(notification_type='due_soon') # test overdue notification end_date = datetime.now(timezone.utc) - timedelta(days=7) loan['end_date'] = end_date.isoformat() loan.update(loan, dbcommit=True, reindex=True) overdue_loans = get_overdue_loans() assert overdue_loans[0].get('pid') == loan_pid create_over_and_due_soon_notifications() flush_index(NotificationsSearch.Meta.index) flush_index(LoansSearch.Meta.index) assert loan.is_notified(notification_type='overdue') assert number_of_reminders_sent(loan) == 1 # checkin the item to put it back to it's original state res, _ = postdata(client, 'api_item.checkin', dict(item_pid=item_pid, pid=loan_pid)) assert res.status_code == 200
def test_patron_authenticate(client, patron_martigny, patron_martigny_data, system_librarian_martigny): """Test for patron authenticate.""" # parameters token = 'Or7DTg1WT34cLKuSMcS7WzhdhxtKklpTizb1Hn2H0aaV5Vig6nden63VEqBE' token_url_data = {'access_token': token} username = patron_martigny_data['username'] password = patron_martigny_data['birth_date'] create_personal(name='token_test', user_id=system_librarian_martigny['user_id'], access_token=token) # Missing access_token parameter res, _ = postdata(client, 'api_patrons.patron_authenticate') assert res.status_code == 401 # Missing parameters (username and password) res, _ = postdata(client, 'api_patrons.patron_authenticate', url_data=token_url_data) assert res.status_code == 400 # User not found post_data = {'username': '******', 'password': '******'} res, _ = postdata(client, 'api_patrons.patron_authenticate', post_data, url_data=token_url_data) assert res.status_code == 404 # User found, bad password post_data = {'username': username, 'password': '******'} res, _ = postdata(client, 'api_patrons.patron_authenticate', post_data, url_data=token_url_data) assert res.status_code == 401 # User found post_data = {'username': username, 'password': password} res, output = postdata(client, 'api_patrons.patron_authenticate', post_data, url_data=token_url_data) assert res.status_code == 200 assert output['city'] == patron_martigny_data['city'] assert output['fullname'] == patron_martigny_data['first_name'] + ' ' +\ patron_martigny_data['last_name'] assert 'blocked' not in output
def test_item_different_actions(client, librarian_martigny_no_email, lib_martigny, patron_martigny_no_email, loc_public_martigny, item_lib_martigny, json_header, item_type_standard_martigny, circ_policy_short_martigny, patron_type_children_martigny, lib_saxon, loc_public_saxon, librarian_saxon_no_email): """Test item possible actions other scenarios.""" login_user_via_session(client, librarian_martigny_no_email.user) circ_policy_origin = deepcopy(circ_policy_short_martigny) circ_policy = circ_policy_short_martigny patron_pid = patron_martigny_no_email.pid res = client.get( url_for('api_item.item', item_barcode='does not exist', patron_pid=patron_pid)) assert res.status_code == 404 res, data = postdata( client, 'api_item.checkout', dict(item_pid=item_lib_martigny.pid, patron_pid=patron_pid)) assert res.status_code == 200 loan_pid = data.get('action_applied')[LoanAction.CHECKOUT].get('pid') record = Item.get_record_by_pid(item_lib_martigny.pid) res, _ = postdata( client, 'api_item.checkin', dict(item_pid='does not exist', pid=loan_pid, transaction_location_pid=loc_public_saxon.pid), ) assert res.status_code == 404 res, data = postdata( client, 'api_item.checkin', dict(item_pid=item_lib_martigny.pid, pid=loan_pid, transaction_location_pid=loc_public_saxon.pid), ) assert res.status_code == 200 loan_pid = data.get('action_applied')[LoanAction.CHECKIN].get('pid') data = {'pid': loan_pid} params, actions = item_lib_martigny.prior_checkout_actions(data) assert 'cancel' in actions
def test_recall_notification(client, patron_martigny_no_email, lib_martigny, json_header, patron2_martigny_no_email, item_lib_martigny, librarian_martigny_no_email, circulation_policies, loc_public_martigny): """Test recall notification.""" # process all notifications still in the queue Notification.process_notifications() login_user_via_session(client, librarian_martigny_no_email.user) res, data = postdata( client, 'api_item.checkout', dict( item_pid=item_lib_martigny.pid, patron_pid=patron_martigny_no_email.pid, transaction_location_pid=loc_public_martigny.pid, transaction_user_pid=librarian_martigny_no_email.pid, ) ) assert res.status_code == 200 loan_pid = data.get('action_applied')[LoanAction.CHECKOUT].get('pid') loan = Loan.get_record_by_pid(loan_pid) assert not loan.is_notified(notification_type='recall') # test notification permissions res, _ = postdata( client, 'api_item.librarian_request', dict( item_pid=item_lib_martigny.pid, pickup_location_pid=loc_public_martigny.pid, patron_pid=patron2_martigny_no_email.pid, transaction_library_pid=lib_martigny.pid, transaction_user_pid=librarian_martigny_no_email.pid ) ) assert res.status_code == 200 flush_index(NotificationsSearch.Meta.index) assert loan.is_notified(notification_type='recall') notification = get_recall_notification(loan) assert notification.loan_pid == loan.pid assert not loan.is_notified(notification_type='availability') assert not get_availability_notification(loan) assert Notification.process_notifications() == { 'send': 1, 'reject': 0, 'error': 0}
def test_document_with_one_item_attached_bug( client, librarian_martigny_no_email, patron_martigny_no_email, patron2_martigny_no_email, loc_public_martigny, item_type_standard_martigny, item_lib_martigny, json_header, circulation_policies, lib_martigny): """Test document with one item.""" login_user_via_session(client, librarian_martigny_no_email.user) # checkout first item1 to patron res, data = postdata( client, 'api_item.checkout', dict(item_pid=item_lib_martigny.pid, patron_pid=patron_martigny_no_email.pid, transaction_library_pid=lib_martigny.pid, transaction_user_pid=librarian_martigny_no_email.pid)) assert res.status_code == 200 actions = data.get('action_applied') loan_pid = actions[LoanAction.CHECKOUT].get('pid') # request first item by patron2 res, data = postdata( client, 'api_item.librarian_request', dict(item_pid=item_lib_martigny.pid, pickup_location_pid=loc_public_martigny.pid, patron_pid=patron2_martigny_no_email.pid, transaction_library_pid=lib_martigny.pid, transaction_user_pid=librarian_martigny_no_email.pid)) assert res.status_code == 200 actions = data.get('action_applied') loan2_pid = actions[LoanAction.REQUEST].get('pid') # checkin the first item res, data = postdata( client, 'api_item.checkin', dict(item_pid=item_lib_martigny.pid, pid=loan_pid, transaction_location_pid=loc_public_martigny.pid, transaction_user_pid=librarian_martigny_no_email.pid)) assert res.status_code == 200 assert item_lib_martigny.number_of_requests() == 1 res, data = postdata( client, 'api_item.cancel_item_request', dict(pid=loan2_pid, transaction_location_pid=loc_public_martigny.pid, transaction_user_pid=librarian_martigny_no_email.pid)) assert res.status_code == 200 assert item_lib_martigny.number_of_requests() == 0
def test_patron_can_delete(client, librarian_martigny_no_email, patron_martigny_no_email, loc_public_martigny, item_lib_martigny, json_header, lib_martigny, circulation_policies): """Test patron can delete.""" login_user_via_session(client, librarian_martigny_no_email.user) item = item_lib_martigny patron = patron_martigny_no_email location = loc_public_martigny data = deepcopy(patron_martigny_no_email) del data['patron']['type'] assert not data.get_organisation() # request res, data = postdata( client, 'api_item.librarian_request', dict( item_pid=item.pid, pickup_location_pid=location.pid, patron_pid=patron.pid, transaction_library_pid=lib_martigny.pid, transaction_user_pid=librarian_martigny_no_email.pid ) ) assert res.status_code == 200 loan_pid = data.get('action_applied')[LoanAction.REQUEST].get('pid') links = patron_martigny_no_email.get_links_to_me() assert 'loans' in links assert not patron_martigny_no_email.can_delete reasons = patron_martigny_no_email.reasons_not_to_delete() assert 'links' in reasons res, data = postdata( client, 'api_item.cancel_item_request', dict( pid=loan_pid, transaction_location_pid=loc_public_martigny.pid, transaction_user_pid=librarian_martigny_no_email.pid ) ) assert res.status_code == 200 assert item.status == ItemStatus.ON_SHELF
def test_acq_order_secure_api_create(client, json_header, org_martigny, vendor_martigny, vendor2_martigny, acq_order_fiction_martigny, librarian_martigny, librarian_sion, acq_order_fiction_saxon, system_librarian_martigny): """Test acq order secure api create.""" # Martigny login_user_via_session(client, librarian_martigny.user) post_entrypoint = 'invenio_records_rest.acor_list' data = acq_order_fiction_saxon del acq_order_fiction_saxon['pid'] res, _ = postdata( client, post_entrypoint, data ) assert res.status_code == 403 data = deepcopy(acq_order_fiction_martigny) del data['pid'] res, _ = postdata( client, post_entrypoint, data ) assert res.status_code == 201 login_user_via_session(client, system_librarian_martigny.user) res, _ = postdata( client, post_entrypoint, data ) assert res.status_code == 201 # Sion login_user_via_session(client, librarian_sion.user) res, _ = postdata( client, post_entrypoint, acq_order_fiction_saxon ) assert res.status_code == 403
def test_request_notifications_temp_item_type( client, patron_martigny, patron_sion, lib_martigny, lib_fully, item_lib_martigny, librarian_martigny, loc_public_martigny, circulation_policies, loc_public_fully, item_type_missing_martigny, mailbox ): """Test request notifications with item type with negative availability.""" mailbox.clear() login_user_via_session(client, librarian_martigny.user) item_lib_martigny['temporary_item_type'] = { '$ref': get_ref_for_pid('itty', item_type_missing_martigny.pid) } item_lib_martigny.update(item_lib_martigny, dbcommit=True, reindex=True) res, data = postdata( client, 'api_item.librarian_request', dict( item_pid=item_lib_martigny.pid, pickup_location_pid=loc_public_fully.pid, patron_pid=patron_martigny.pid, transaction_library_pid=lib_martigny.pid, transaction_user_pid=librarian_martigny.pid ) ) assert res.status_code == 200 request_loan_pid = data.get( 'action_applied')[LoanAction.REQUEST].get('pid') flush_index(NotificationsSearch.Meta.index) assert len(mailbox) == 0 # cancel request res, _ = postdata( client, 'api_item.cancel_item_request', dict( item_pid=item_lib_martigny.pid, pid=request_loan_pid, transaction_user_pid=librarian_martigny.pid, transaction_library_pid=lib_martigny.pid ) ) assert res.status_code == 200 mailbox.clear() del(item_lib_martigny['temporary_item_type']) item_lib_martigny.update(item_lib_martigny, dbcommit=True, reindex=True)
def test_items_extend_end_date(client, librarian_martigny_no_email, patron_martigny_no_email, loc_public_martigny, item_type_standard_martigny, item_lib_martigny, json_header, circ_policy_short_martigny): """Test correct renewal due date for items.""" login_user_via_session(client, librarian_martigny_no_email.user) item = item_lib_martigny item_pid = item.pid patron_pid = patron_martigny_no_email.pid # checkout res, data = postdata(client, 'api_item.checkout', dict(item_pid=item_pid, patron_pid=patron_pid)) assert res.status_code == 200 actions = data.get('action_applied') loan_pid = actions[LoanAction.CHECKOUT].get('pid') loan = Loan.get_record_by_pid(loan_pid) assert not item.get_extension_count() max_count = get_extension_params(loan=loan, parameter_name='max_count') renewal_duration_policy = circ_policy_short_martigny['renewal_duration'] renewal_duration = get_extension_params(loan=loan, parameter_name='duration_default') assert renewal_duration_policy <= renewal_duration.days # extend loan res, data = postdata(client, 'api_item.extend_loan', dict(item_pid=item_pid, pid=loan_pid)) assert res.status_code == 200 # Compare expected loan date with processed one # first get loan UTC date actions = data.get('action_applied') loan_pid = actions[LoanAction.EXTEND].get('pid') loan = Loan.get_record_by_pid(loan_pid) loan_date = loan.get('end_date') # then process a date with current UTC date + renewal current_date = datetime.now(timezone.utc) calc_date = current_date + renewal_duration # finally the comparison should give the same date (in UTC)! assert (calc_date.strftime('%Y-%m-%d') == ciso8601.parse_datetime( loan_date).astimezone(timezone.utc).strftime('%Y-%m-%d')) # checkin res, _ = postdata(client, 'api_item.checkin', dict(item_pid=item_pid, pid=loan_pid)) assert res.status_code == 200
def test_item_secure_api_create(client, json_header, item_lib_martigny, librarian_martigny, librarian_sion, item_lib_martigny_data, item_lib_saxon_data, system_librarian_martigny): """Test item secure api create.""" # Martigny login_user_via_session(client, librarian_martigny.user) post_url = 'invenio_records_rest.item_list' del item_lib_martigny_data['pid'] res, _ = postdata( client, post_url, item_lib_martigny_data ) # librarian can create items on its affiliated library assert res.status_code == 201 del item_lib_saxon_data['pid'] res, _ = postdata( client, post_url, item_lib_saxon_data ) # librarian can not create items for another library assert res.status_code == 403 login_user_via_session(client, system_librarian_martigny.user) res, _ = postdata( client, post_url, item_lib_saxon_data ) # sys_librarian can create items for any library assert res.status_code == 201 # Sion login_user_via_session(client, librarian_sion.user) res, _ = postdata( client, post_url, item_lib_martigny_data ) # librarian can not create items in another organisation assert res.status_code == 403
def test_requested_loans_to_validate(client, librarian_martigny, loc_public_martigny, item_type_standard_martigny, item2_lib_martigny, json_header, patron_sion, circulation_policies): """Test requested loans to validate.""" login_user_via_session(client, librarian_martigny.user) library_pid = librarian_martigny\ .replace_refs()['libraries'][0]['pid'] res, _ = postdata( client, 'api_item.librarian_request', dict(item_pid=item2_lib_martigny.pid, patron_pid=patron_sion.pid, pickup_location_pid=loc_public_martigny.pid, transaction_user_pid=librarian_martigny.pid, transaction_location_pid=loc_public_martigny.pid)) res = client.get( url_for('api_item.requested_loans', library_pid=library_pid)) assert res.status_code == 200 data = get_json(res) assert 1 == data['hits']['total']['value'] requested_loan = data['hits']['hits'][0] assert item2_lib_martigny.pid == requested_loan['item']['pid'] assert item2_lib_martigny.pid == \ requested_loan['loan']['item_pid']['value'] assert LoanState.PENDING == requested_loan['loan']['state'] assert patron_sion.pid == requested_loan['loan']['patron_pid']
def test_patrons_post_without_email(client, lib_martigny, patron_type_children_martigny, patron_martigny_data_tmp, json_header, roles, mailbox): """Test record retrieval.""" patron_data = patron_martigny_data_tmp pids = Patron.count() assert len(mailbox) == 0 # Create record / POST del patron_data['pid'] del patron_data['email'] patron_data['patron']['communication_channel'] = 'mail' patron_data['patron']['additional_communication_email'] = '*****@*****.**' patron_data['username'] = '******' res, _ = postdata(client, 'invenio_records_rest.ptrn_list', patron_data) assert res.status_code == 201 assert Patron.count() == pids + 1 assert len(mailbox) == 0 # Check that the returned record matches the given data data = get_json(res) # remove dynamic property del data['metadata']['user_id'] del data['metadata']['pid'] assert data['metadata'] == patron_data
def test_acq_receipt_lines_post_put_delete(client, org_martigny, vendor2_martigny, acq_order_line_fiction_saxon, acq_receipt_fiction_sion, acq_receipt_line_fiction_saxon, json_header): """Test record retrieval.""" # Create record / POST item_url = url_for('invenio_records_rest.acrl_item', pid_value='1') list_url = url_for('invenio_records_rest.acrl_list', q='pid:1') acq_receipt_line_fiction_saxon['pid'] = '1' res, data = postdata( client, 'invenio_records_rest.acrl_list', acq_receipt_line_fiction_saxon ) assert res.status_code == 201 # Check that the returned record matches the given data assert data['metadata'] == acq_receipt_line_fiction_saxon res = client.get(item_url) assert res.status_code == 200 data = get_json(res) assert acq_receipt_line_fiction_saxon == data['metadata'] # Update record/PUT data = acq_receipt_line_fiction_saxon notes = [{'content': 'test', 'type': AcqReceiptLineNoteType.STAFF}] data['notes'] = notes res = client.put( item_url, data=json.dumps(data), headers=json_header ) assert res.status_code == 200 # Check that the returned record matches the given data data = get_json(res) assert data['metadata']['notes'] == notes res = client.get(item_url) assert res.status_code == 200 data = get_json(res) assert data['metadata']['notes'] == notes res = client.get(list_url) assert res.status_code == 200 data = get_json(res)['hits']['hits'][0] assert data['metadata']['notes'] == notes # Delete record/DELETE res = client.delete(item_url) assert res.status_code == 204 res = client.get(item_url) assert res.status_code == 410
def test_issues_permissions(client, json_header, holding_lib_martigny_w_patterns, librarian_martigny): """Test specific items issues permissions.""" # receive a regular issue holding = holding_lib_martigny_w_patterns holding = Holding.get_record_by_pid(holding.pid) login_user_via_session(client, librarian_martigny.user) res, data = postdata(client, 'api_holding.receive_regular_issue', url_data=dict(holding_pid=holding.pid)) assert res.status_code == 200 data = get_json(res) issue_item = Item.get_record_by_pid(data.get('issue', {}).get('pid')) assert issue_item is not None assert issue_item.issue_is_regular # a regular issue cannot be deleted res = client.get( url_for('api_blueprint.permissions', route_name='items', record_pid=issue_item.pid)) assert res.status_code == 200 data = get_json(res) assert not data['delete']['can']
def test_vendor_post_update_delete(client, librarian_martigny_no_email, vendor3_martigny_data, json_header): """Test CRUD on vendor.""" login_user_via_session(client, librarian_martigny_no_email.user) item_url = url_for('invenio_records_rest.vndr_item', pid_value='vndr3') # create vendor3_martigny_data['pid'] = 'vndr3' res, data = postdata(client, 'invenio_records_rest.vndr_list', vendor3_martigny_data) assert res.status_code == 201 # read res = client.get(item_url) assert res.status_code == 200 data = get_json(res) assert data['metadata'] == vendor3_martigny_data # update data = vendor3_martigny_data data['name'] = 'Test update Name' res = client.put(item_url, data=json.dumps(data), headers=json_header) assert res.status_code == 200 # Check that the returned record matches the given data data = get_json(res) assert data['metadata']['name'] == 'Test update Name' # delete res = client.delete(item_url) assert res.status_code == 204 res = client.get(item_url) assert res.status_code == 410
def test_operation_logs_rest(client, loan_pending_martigny, librarian_martigny, json_header, loan_overdue_martigny): """Test operation logs REST API.""" login_user_via_session(client, librarian_martigny.user) item_url = url_for('invenio_records_rest.oplg_item', pid_value='1') item_list = url_for('invenio_records_rest.oplg_list') res = client.get(item_url) assert res.status_code == 404 res = client.get(item_list) assert res.status_code == 200 data = get_json(res) assert data['hits']['total']['value'] > 0 pid = data['hits']['hits'][0]['metadata']['pid'] assert pid assert data['hits']['hits'][0]['id'] == pid assert data['hits']['hits'][0]['created'] assert data['hits']['hits'][0]['updated'] res, _ = postdata(client, 'invenio_records_rest.oplg_list', {}) assert res.status_code == 403 res = client.put(url_for('invenio_records_rest.oplg_item', pid_value='1'), data={}, headers=json_header) assert res.status_code == 404 res = client.delete(item_url) assert res.status_code == 404
def test_circ_policies_permissions( client, circ_policy_default_martigny, json_header): """Test policy retrieval.""" item_url = url_for('invenio_records_rest.cipo_item', pid_value='cipo1') res = client.get(item_url) assert res.status_code == 401 res, _ = postdata( client, 'invenio_records_rest.cipo_list', {} ) assert res.status_code == 401 res = client.put( url_for('invenio_records_rest.cipo_item', pid_value='cipo1'), data={}, headers=json_header ) res = client.delete(item_url) assert res.status_code == 401 res = client.get(url_for('circ_policies.name_validate', name='standard')) assert res.status_code == 401
def test_selfcheck_checkout(client, sip2_librarian_martigny_no_email, sip2_patron_martigny_no_email, loc_public_martigny, item_lib_martigny, librarian2_martigny_no_email, circulation_policies): """Test selfcheck checkout.""" patron_barcode = sip2_patron_martigny_no_email \ .get('patron', {}).get('barcode') item_barcode = item_lib_martigny.get('barcode') # selfcheck checkout checkout = selfcheck_checkout( user_pid=sip2_librarian_martigny_no_email.pid, institution_id=sip2_librarian_martigny_no_email.library_pid, patron_barcode=patron_barcode, item_barcode=item_barcode, ) assert checkout assert checkout.is_success assert checkout.due_date # librarian checkin login_user_via_session(client, librarian2_martigny_no_email.user) res, _ = postdata( client, 'api_item.checkin', dict(item_pid=item_lib_martigny.pid, transaction_user_pid=librarian2_martigny_no_email.pid, transaction_location_pid=loc_public_martigny.pid)) assert res.status_code == 200
def test_selfcheck_checkout(client, selfcheck_librarian_martigny, selfcheck_patron_martigny, loc_public_martigny, item_lib_martigny, librarian_martigny, librarian2_martigny, circulation_policies): """Test selfcheck checkout.""" patron_barcode = selfcheck_patron_martigny \ .get('patron', {}).get('barcode')[0] item_barcode = item_lib_martigny.get('barcode') # selfcheck checkout checkout = selfcheck_checkout(transaction_user_pid=librarian_martigny.pid, item_barcode=item_barcode, patron_barcode=patron_barcode, terminal=selfcheck_librarian_martigny.name) assert checkout assert checkout.is_success assert checkout.due_date # librarian checkin login_user_via_session(client, librarian2_martigny.user) res, _ = postdata( client, 'api_item.checkin', dict(item_pid=item_lib_martigny.pid, transaction_user_pid=librarian2_martigny.pid, transaction_location_pid=loc_public_martigny.pid)) assert res.status_code == 200
def test_loans_logged_permissions(client, loan_pending_martigny, librarian_martigny_no_email, json_header): """Test record retrieval.""" login_user_via_session(client, librarian_martigny_no_email.user) item_url = url_for('invenio_records_rest.loanid_item', pid_value='1') res = client.get(item_url) assert res.status_code == 200 res, _ = postdata( client, 'invenio_records_rest.loanid_list', {} ) assert res.status_code == 403 res = client.put( url_for('invenio_records_rest.loanid_item', pid_value='1'), data={}, headers=json_header ) res = client.delete(item_url) assert res.status_code == 403
def test_patrons_post_without_email(app, client, lib_martigny, patron_type_children_martigny, patron_martigny_data_tmp, json_header, roles, mailbox): """Test record retrieval.""" patron_data = deepcopy(patron_martigny_data_tmp) patron_data['email'] = '*****@*****.**' patron_data['username'] = '******' del patron_data['pid'] del patron_data['email'] patron_data['patron']['communication_channel'] = 'mail' patron_data = create_user_from_data(patron_data) pids = Patron.count() assert len(mailbox) == 0 # Create record / POST res, _ = postdata(client, 'invenio_records_rest.ptrn_list', patron_data) assert res.status_code == 201 assert Patron.count() == pids + 1 assert len(mailbox) == 0 # Check that the returned record matches the given data data = get_json(res) data['metadata']['patron']['communication_channel'] = 'mail' ds = app.extensions['invenio-accounts'].datastore ds.delete_user(ds.find_user(id=patron_data['user_id']))
def test_patrons_permissions(client, librarian_martigny_no_email, json_header): """Test record retrieval.""" item_url = url_for( 'invenio_records_rest.ptrn_item', pid_value=librarian_martigny_no_email.pid) res = client.get(item_url) assert res.status_code == 401 res, _ = postdata( client, 'invenio_records_rest.ptrn_list', {} ) assert res.status_code == 401 res = client.put( item_url, data={}, headers=json_header ) res = client.delete(item_url) assert res.status_code == 401
def test_ilsrecord_pid_after_validationerror(client, loc_online_martigny_data, librarian_martigny_no_email): """Check PID before and after a ValidationError: it should be the same""" loc = Location.create(loc_online_martigny_data, delete_pid=True) next_pid = str(int(loc.pid) + 1) # post invalid data and post them login_user_via_session(client, librarian_martigny_no_email.user) res, _ = postdata( client, 'invenio_records_rest.loc_list', { '$schema': 'https://ils.rero.ch/schemas/locations/location-v0.0.1.json', 'library': { '$ref': 'https://ils.rero.ch/api/libraries/lib1' }, 'name': 'Library of Foo' }) # check http status for invalid record assert res.status_code == 400 # the pid should be unchanged loc.provider.identifier.query.first().recid == loc.pid # check that we can create a new location loc2 = Location.create(loc_online_martigny_data, delete_pid=True) loc2.pid == next_pid
def test_notifications_permissions( client, notification_availability_martigny, json_header): """Test notification permissions.""" notif = notification_availability_martigny pid = notif.get('pid') item_url = url_for('invenio_records_rest.notif_item', pid_value=pid) res = client.get(item_url) assert res.status_code == 401 res, _ = postdata( client, 'invenio_records_rest.notif_list', {} ) assert res.status_code == 401 res = client.put( item_url, data={}, headers=json_header ) res = client.delete(item_url) assert res.status_code == 401
def test_items_deny_requests(client, librarian_martigny_no_email, patron_martigny_no_email, loc_public_martigny, item_type_standard_martigny, item_lib_martigny, json_header, circ_policy_short_martigny): """Test items when requests are denied.""" location = loc_public_martigny circ_policy_short_martigny['allow_requests'] = False circ_policy_short_martigny.update(data=circ_policy_short_martigny, dbcommit=True, reindex=True) flush_index(CircPoliciesSearch.Meta.index) login_user_via_session(client, librarian_martigny_no_email.user) item = item_lib_martigny item_pid = item.pid patron = patron_martigny_no_email patron_pid = patron.pid # request res, _ = postdata( client, 'api_item.librarian_request', dict(item_pid=item_pid, pickup_location_pid=location.pid, patron_pid=patron_pid)) assert res.status_code == 403 circ_policy_short_martigny['allow_requests'] = True circ_policy_short_martigny.update(data=circ_policy_short_martigny, dbcommit=True, reindex=True) flush_index(CircPoliciesSearch.Meta.index) assert circ_policy_short_martigny.get('allow_requests')
def test_create_fee(client, librarian_martigny_no_email, librarian_sion_no_email, patron_martigny_no_email, loc_public_martigny, item_type_standard_martigny, item_lib_martigny, json_header, circ_policy_short_martigny): """Test overdue loans.""" login_user_via_session(client, librarian_martigny_no_email.user) # checkout res, data = postdata( client, 'api_item.checkout', dict(item_pid=item_lib_martigny.pid, patron_pid=patron_martigny_no_email.pid)) assert res.status_code == 200 loan_pid = data.get('action_applied')[LoanAction.CHECKOUT].get('pid') loan = Loan.get_record_by_pid(loan_pid) end_date = datetime.now(timezone.utc) - timedelta(days=7) loan['end_date'] = end_date.isoformat() loan.update(loan, dbcommit=True, reindex=True) overdue_loans = get_overdue_loans() assert overdue_loans[0].get('pid') == loan_pid notification = loan.create_notification(notification_type='overdue') flush_index(NotificationsSearch.Meta.index) flush_index(LoansSearch.Meta.index) fee = list(notification.fees)[0] assert fee.get('amount') == 2 assert fee.get('currency') == 'CHF' fee_url = url_for('invenio_records_rest.fee_item', pid_value=fee.pid) res = client.get(fee_url) assert res.status_code == 200 login_user_via_session(client, librarian_sion_no_email.user) res = client.get(fee_url) assert res.status_code == 403 login_user_via_session(client, librarian_martigny_no_email.user) # checkin res, _ = postdata(client, 'api_item.checkin', dict(item_pid=item_lib_martigny.pid, pid=loan_pid)) assert res.status_code == 200