invenio-app-ils 4.5.0__py2.py3-none-any.whl → 5.0.0__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. invenio_app_ils/__init__.py +1 -1
  2. invenio_app_ils/assets/semantic-ui/less/theme.config +103 -0
  3. invenio_app_ils/circulation/api.py +9 -5
  4. invenio_app_ils/circulation/config.py +1 -0
  5. invenio_app_ils/circulation/loaders/schemas/json/loan_checkout.py +1 -1
  6. invenio_app_ils/circulation/loaders/schemas/json/loan_request.py +2 -2
  7. invenio_app_ils/circulation/notifications/api.py +9 -1
  8. invenio_app_ils/circulation/notifications/messages.py +2 -1
  9. invenio_app_ils/circulation/templates/invenio_app_ils_circulation/notifications/update_dates.html +19 -0
  10. invenio_app_ils/cli.py +92 -64
  11. invenio_app_ils/config.py +10 -2
  12. invenio_app_ils/documents/loaders/jsonschemas/document.py +1 -1
  13. invenio_app_ils/eitems/loaders/jsonschemas/eitems.py +2 -2
  14. invenio_app_ils/patrons/anonymization.py +0 -4
  15. invenio_app_ils/series/loaders/jsonschemas/series.py +1 -1
  16. invenio_app_ils/webpack.py +27 -0
  17. {invenio_app_ils-4.5.0.dist-info → invenio_app_ils-5.0.0.dist-info}/METADATA +56 -43
  18. {invenio_app_ils-4.5.0.dist-info → invenio_app_ils-5.0.0.dist-info}/RECORD +24 -112
  19. {invenio_app_ils-4.5.0.dist-info → invenio_app_ils-5.0.0.dist-info}/entry_points.txt +3 -0
  20. {invenio_app_ils-4.5.0.dist-info → invenio_app_ils-5.0.0.dist-info}/top_level.txt +0 -1
  21. invenio_app_ils/notifications/admin.py +0 -57
  22. tests/__init__.py +0 -8
  23. tests/api/__init__.py +0 -8
  24. tests/api/acquisition/__init__.py +0 -8
  25. tests/api/acquisition/test_acq_orders_crud.py +0 -99
  26. tests/api/acquisition/test_acq_orders_permissions.py +0 -104
  27. tests/api/acquisition/test_acq_providers_permissions.py +0 -83
  28. tests/api/circulation/__init__.py +0 -8
  29. tests/api/circulation/test_expired_loans.py +0 -88
  30. tests/api/circulation/test_loan_bulk_extend.py +0 -169
  31. tests/api/circulation/test_loan_checkout.py +0 -422
  32. tests/api/circulation/test_loan_default_durations.py +0 -43
  33. tests/api/circulation/test_loan_document_resolver.py +0 -18
  34. tests/api/circulation/test_loan_extend.py +0 -122
  35. tests/api/circulation/test_loan_item_permissions.py +0 -135
  36. tests/api/circulation/test_loan_item_resolver.py +0 -26
  37. tests/api/circulation/test_loan_list_permissions.py +0 -98
  38. tests/api/circulation/test_loan_patron_resolver.py +0 -38
  39. tests/api/circulation/test_loan_request.py +0 -338
  40. tests/api/circulation/test_loan_update.py +0 -150
  41. tests/api/circulation/test_notifications.py +0 -221
  42. tests/api/conftest.py +0 -227
  43. tests/api/document_requests/__init__.py +0 -8
  44. tests/api/document_requests/test_document_requests.py +0 -131
  45. tests/api/document_requests/test_document_requests_permissions.py +0 -159
  46. tests/api/document_requests/test_notifications_filter.py +0 -35
  47. tests/api/ill/__init__.py +0 -8
  48. tests/api/ill/test_ill_brw_crud.py +0 -74
  49. tests/api/ill/test_ill_brw_reqs_patron_loan_create_action.py +0 -198
  50. tests/api/ill/test_ill_brw_reqs_patron_loan_extension_actions.py +0 -280
  51. tests/api/ill/test_ill_brw_reqs_permissions.py +0 -163
  52. tests/api/ill/test_ill_providers_permissions.py +0 -82
  53. tests/api/ils/__init__.py +0 -8
  54. tests/api/ils/documents/__init__.py +0 -8
  55. tests/api/ils/documents/test_document_crud.py +0 -57
  56. tests/api/ils/documents/test_document_permissions.py +0 -100
  57. tests/api/ils/documents/test_document_resolvers.py +0 -35
  58. tests/api/ils/eitems/__init__.py +0 -8
  59. tests/api/ils/eitems/test_eitems_crud.py +0 -42
  60. tests/api/ils/eitems/test_eitems_permissions.py +0 -85
  61. tests/api/ils/eitems/test_files.py +0 -162
  62. tests/api/ils/items/__init__.py +0 -8
  63. tests/api/ils/items/test_apis.py +0 -43
  64. tests/api/ils/items/test_items_crud.py +0 -99
  65. tests/api/ils/items/test_items_permissions.py +0 -107
  66. tests/api/ils/records_relations/__init__.py +0 -8
  67. tests/api/ils/records_relations/helpers.py +0 -115
  68. tests/api/ils/records_relations/test_records_relations_parentchild.py +0 -560
  69. tests/api/ils/records_relations/test_records_relations_sequence.py +0 -294
  70. tests/api/ils/records_relations/test_records_relations_siblings.py +0 -751
  71. tests/api/ils/series/__init__.py +0 -8
  72. tests/api/ils/series/test_series_permissions.py +0 -95
  73. tests/api/ils/test_anonymization.py +0 -181
  74. tests/api/ils/test_apis.py +0 -76
  75. tests/api/ils/test_closures.py +0 -353
  76. tests/api/ils/test_errors.py +0 -125
  77. tests/api/ils/test_facets.py +0 -88
  78. tests/api/ils/test_internal_locations.py +0 -96
  79. tests/api/ils/test_loaders.py +0 -51
  80. tests/api/ils/test_metadata_extensions.py +0 -206
  81. tests/api/ils/test_notifications.py +0 -173
  82. tests/api/ils/test_notifications_mails.py +0 -37
  83. tests/api/ils/test_notifications_permissions.py +0 -55
  84. tests/api/ils/test_patrons.py +0 -102
  85. tests/api/ils/test_record_delete.py +0 -42
  86. tests/api/ils/test_record_permissions.py +0 -132
  87. tests/api/ils/test_resolvers.py +0 -205
  88. tests/api/ils/test_stats.py +0 -142
  89. tests/api/ils/test_tasks.py +0 -209
  90. tests/api/ils/test_vocabularies.py +0 -35
  91. tests/conftest.py +0 -221
  92. tests/data/acq_orders.json +0 -110
  93. tests/data/acq_providers.json +0 -12
  94. tests/data/document_requests.json +0 -77
  95. tests/data/documents.json +0 -238
  96. tests/data/eitems.json +0 -71
  97. tests/data/ill_borrowing_requests.json +0 -77
  98. tests/data/ill_providers.json +0 -12
  99. tests/data/internal_locations.json +0 -22
  100. tests/data/items.json +0 -304
  101. tests/data/loans.json +0 -133
  102. tests/data/loans_most_loaned.json +0 -128
  103. tests/data/locations.json +0 -26
  104. tests/data/series.json +0 -33
  105. tests/helpers.py +0 -107
  106. tests/templates/notifications/title_body.html +0 -8
  107. tests/templates/notifications/title_body_html.html +0 -13
  108. tests/templates/notifications/title_body_html_ctx.html +0 -13
  109. tests/templates/notifications/title_only.html +0 -3
  110. tests/test_post_logout_redirect.py +0 -23
  111. tests/test_version.py +0 -17
  112. /tests/templates/notifications/blank.html → /invenio_app_ils/assets/semantic-ui/templates/.gitkeep +0 -0
  113. {invenio_app_ils-4.5.0.dist-info → invenio_app_ils-5.0.0.dist-info}/WHEEL +0 -0
  114. {invenio_app_ils-4.5.0.dist-info → invenio_app_ils-5.0.0.dist-info}/licenses/AUTHORS.rst +0 -0
  115. {invenio_app_ils-4.5.0.dist-info → invenio_app_ils-5.0.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,51 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
- # Copyright (C) 2018 CERN.
4
- #
5
- # invenio-app-ils is free software; you can redistribute it and/or modify it
6
- # under the terms of the MIT License; see LICENSE file for more details.
7
-
8
- """Test accesibility of resource endpoints."""
9
-
10
- import json
11
-
12
- from flask import url_for
13
-
14
- from tests.helpers import user_login, validate_response
15
-
16
- NEW_INTERNAL_LOCATION = {
17
- "location_pid": "locid-1",
18
- "legacy_ids": ["Test legacy id"],
19
- "name": "My test internal location",
20
- "physical_location": "Left from the right building",
21
- "notes": "In house",
22
- }
23
-
24
-
25
- def test_post_internal_location(client, json_headers, testdata, users):
26
- """Test POST of internal_location."""
27
- user_login(client, "admin", users)
28
- url = url_for("invenio_records_rest.ilocid_list")
29
- res = validate_response(
30
- client, "post", url, json_headers, NEW_INTERNAL_LOCATION, 201
31
- )
32
- data = json.loads(res.data.decode("utf-8"))["metadata"]
33
- assert "name" in data["location"]
34
-
35
-
36
- def test_post_partial_internal_location(client, json_headers, testdata, users):
37
- """Test POST of internal_location without all required data."""
38
- user_login(client, "admin", users)
39
- del NEW_INTERNAL_LOCATION["location_pid"]
40
- url = url_for("invenio_records_rest.ilocid_list")
41
- validate_response(client, "post", url, json_headers, NEW_INTERNAL_LOCATION, 400)
42
-
43
-
44
- def test_post_item(client, json_headers, testdata, users, item_record):
45
- """Test POST of an item."""
46
- user_login(client, "admin", users)
47
- url = url_for("invenio_records_rest.pitmid_list")
48
- del item_record["pid"]
49
- res = validate_response(client, "post", url, json_headers, item_record, 201)
50
- data = json.loads(res.data.decode("utf-8"))["metadata"]
51
- assert "name" in data["internal_location"]
@@ -1,206 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
- # Copyright (C) 2018-2020 CERN.
4
- #
5
- # invenio-app-ils is free software; you can redistribute it and/or modify it
6
- # under the terms of the MIT License; see LICENSE file for more details.
7
-
8
- """Test metadata extensions."""
9
-
10
- import pytest
11
- from invenio_indexer.api import RecordIndexer
12
- from invenio_records_rest.schemas.fields import DateString, SanitizedUnicode
13
- from marshmallow import ValidationError
14
- from marshmallow.fields import Bool, Integer, List
15
-
16
- from invenio_app_ils.documents.api import Document
17
- from invenio_app_ils.records.metadata_extensions import MetadataExtensions
18
-
19
-
20
- @pytest.fixture(scope="module")
21
- def app_config(app_config):
22
- """Override conftest.py's app_config"""
23
- app_config["ILS_RECORDS_METADATA_NAMESPACES"] = {
24
- "document": {
25
- "accelerator_experiments": {
26
- "@context": "https://example.com/accelerator_experiments/terms"
27
- },
28
- "standard_status": {
29
- "@context": "https://example.com/standard_status/terms"
30
- },
31
- }
32
- }
33
-
34
- app_config["ILS_RECORDS_METADATA_EXTENSIONS"] = {
35
- "document": {
36
- "schema": Document._schema,
37
- "fields": {
38
- "accelerator_experiments_accelerator": {
39
- "elasticsearch": "keyword",
40
- "marshmallow": SanitizedUnicode(required=True),
41
- },
42
- "accelerator_experiments_project": {
43
- "elasticsearch": "text",
44
- "marshmallow": SanitizedUnicode(),
45
- },
46
- "accelerator_experiments_number_in_sequence": {
47
- "elasticsearch": "long",
48
- "marshmallow": Integer(),
49
- },
50
- "accelerator_experiments_scientific_sequence": {
51
- "elasticsearch": "long",
52
- "marshmallow": List(Integer()),
53
- },
54
- "standard_status_original_presentation_date": {
55
- "elasticsearch": "date",
56
- "marshmallow": DateString(),
57
- },
58
- "standard_status_right_or_wrong": {
59
- "elasticsearch": "boolean",
60
- "marshmallow": Bool(),
61
- },
62
- },
63
- }
64
- }
65
-
66
- return app_config
67
-
68
-
69
- def assert_unordered_equality(array_dict1, array_dict2):
70
- array1 = sorted(array_dict1, key=lambda d: d["key"])
71
- array2 = sorted(array_dict2, key=lambda d: d["key"])
72
- assert array1 == array2
73
-
74
-
75
- def test_metadata_extensions(db, es, testdata):
76
- """Tests that a Record is indexed into Elasticsearch properly.
77
- - Tests that the before_record_index_hook is registered properly.
78
- - Tests add_es_metadata_extensions.
79
- - Tests jsonschema validates correctly
80
- - Tests that retrieved record document is fine.
81
- NOTE:
82
- - es fixture depends on appctx fixture, so we are in app context
83
- - this test requires a running ES instance
84
- """
85
- document = testdata["documents"][0]
86
- data = {
87
- "extensions": {
88
- "accelerator_experiments_accelerator": "LHCb",
89
- "accelerator_experiments_project": "A project for experiment.",
90
- "accelerator_experiments_number_in_sequence": 3,
91
- "accelerator_experiments_scientific_sequence": [1, 1, 2, 3, 5, 8],
92
- "standard_status_original_presentation_date": "2019-02-14",
93
- "standard_status_right_or_wrong": True,
94
- }
95
- }
96
- document.update(data)
97
- document.validate()
98
- db.session.commit()
99
- indexer = RecordIndexer()
100
- index_result = indexer.index(document)
101
-
102
- _index = index_result["_index"]
103
- _id = index_result["_id"]
104
- es_doc = es.get(index=_index, id=_id)
105
- source = es_doc["_source"]
106
- expected_keywords = [
107
- {"key": "accelerator_experiments_accelerator", "value": "LHCb"},
108
- ]
109
- expected_texts = [
110
- {
111
- "key": "accelerator_experiments_project",
112
- "value": "A project for experiment.",
113
- },
114
- ]
115
- expected_longs = [
116
- {"key": "accelerator_experiments_number_in_sequence", "value": 3},
117
- {
118
- "key": "accelerator_experiments_scientific_sequence",
119
- "value": [1, 1, 2, 3, 5, 8],
120
- },
121
- ]
122
- expected_dates = [
123
- {
124
- "key": "standard_status_original_presentation_date",
125
- "value": "2019-02-14",
126
- },
127
- ]
128
- expected_booleans = [
129
- {"key": "standard_status_right_or_wrong", "value": True},
130
- ]
131
- assert_unordered_equality(source["extensions_keywords"], expected_keywords)
132
- assert_unordered_equality(source["extensions_texts"], expected_texts)
133
- assert_unordered_equality(source["extensions_longs"], expected_longs)
134
- assert_unordered_equality(source["extensions_dates"], expected_dates)
135
- assert_unordered_equality(source["extensions_booleans"], expected_booleans)
136
-
137
-
138
- def test_extensions():
139
- """Test metadata extensions schema."""
140
- ILS_RECORDS_METADATA_NAMESPACES = {
141
- "accelerator_experiments": {
142
- "@context": "https://example.com/accelerator_experiments/terms"
143
- },
144
- "standard_status": {"@context": "https://example.com/standard_status/terms"},
145
- }
146
-
147
- ILS_RECORDS_METADATA_EXTENSIONS = {
148
- "accelerator_experiments_accelerator": {
149
- "elasticsearch": "keyword",
150
- "marshmallow": SanitizedUnicode(required=True),
151
- },
152
- "accelerator_experiments_project": {
153
- "elasticsearch": "text",
154
- "marshmallow": SanitizedUnicode(),
155
- },
156
- "accelerator_experiments_number_in_sequence": {
157
- "elasticsearch": "long",
158
- "marshmallow": Integer(),
159
- },
160
- "accelerator_experiments_scientific_sequence": {
161
- "elasticsearch": "long",
162
- "marshmallow": List(Integer()),
163
- },
164
- "standard_status_original_presentation_date": {
165
- "elasticsearch": "date",
166
- "marshmallow": DateString(),
167
- },
168
- "standard_status_right_or_wrong": {
169
- "elasticsearch": "boolean",
170
- "marshmallow": Bool(),
171
- },
172
- }
173
-
174
- extensions = MetadataExtensions(
175
- ILS_RECORDS_METADATA_NAMESPACES, ILS_RECORDS_METADATA_EXTENSIONS
176
- )
177
- ExtensionsSchema = extensions.to_schema()
178
-
179
- # Minimal if not absent
180
- valid_minimal = {"accelerator_experiments_accelerator": "LHCb"}
181
-
182
- data = ExtensionsSchema().load(valid_minimal)
183
-
184
- assert data == valid_minimal
185
-
186
- # Full
187
- valid_full = {
188
- "accelerator_experiments_accelerator": "LHCb",
189
- "accelerator_experiments_project": "A project for experiment.",
190
- "accelerator_experiments_number_in_sequence": 3,
191
- "accelerator_experiments_scientific_sequence": [1, 1, 2, 3, 5, 8],
192
- "standard_status_original_presentation_date": "2019-02-14",
193
- "standard_status_right_or_wrong": True,
194
- }
195
-
196
- data = ExtensionsSchema().load(valid_full)
197
-
198
- assert data == valid_full
199
-
200
- # Invalid
201
- invalid_number_in_sequence = {
202
- "accelerator_experiments_accelerator": "LHCb",
203
- "accelerator_experiments_scientific_sequence": [1, "l", 2, 3, 5, 8],
204
- }
205
- with pytest.raises(ValidationError):
206
- data = ExtensionsSchema().load(invalid_number_in_sequence)
@@ -1,173 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
- # Copyright (C) 2018-2021 CERN.
4
- #
5
- # invenio-app-ils is free software; you can redistribute it and/or modify it
6
- # under the terms of the MIT License; see LICENSE file for more details.
7
-
8
- """Test notifications."""
9
-
10
- import pytest
11
- from flask import url_for
12
- from jinja2.exceptions import TemplateError, TemplateNotFound
13
-
14
- from invenio_app_ils.notifications.api import (
15
- log_error_notification,
16
- log_successful_notification,
17
- send_notification,
18
- )
19
- from invenio_app_ils.notifications.messages import NotificationMsg
20
- from invenio_app_ils.notifications.models import NotificationsLogs
21
- from invenio_app_ils.patrons.api import Patron
22
- from tests.helpers import user_login
23
-
24
-
25
- def test_message_full(app_with_notifs):
26
- """Test that the title, body and html are read correctly."""
27
- with app_with_notifs.app_context():
28
- # remove footer
29
- app_with_notifs.config["ILS_NOTIFICATIONS_TEMPLATES"] = {}
30
-
31
- full = NotificationMsg("notifications/title_body_html.html")
32
- assert full.title == "Test title."
33
- assert "Test body." == full.body_plain
34
- assert "Test html." == full.body_html
35
-
36
-
37
- def test_message_body_same_as_html(app_with_notifs):
38
- """Test that the title and body are read correctly."""
39
- with app_with_notifs.app_context():
40
- # remove footer
41
- app_with_notifs.config["ILS_NOTIFICATIONS_TEMPLATES"] = {}
42
-
43
- blank = NotificationMsg("notifications/title_body.html")
44
- assert blank.title == "Test title."
45
- assert "Test body." == blank.body_plain
46
- assert "Test body." == blank.body_html
47
-
48
-
49
- def test_invalid_message_templates(app_with_notifs):
50
- """Test invalid templates."""
51
- with app_with_notifs.app_context():
52
- with pytest.raises(TemplateError) as ex:
53
- NotificationMsg("notifications/blank.html")
54
- assert "No block with name 'title'" in str(ex.value)
55
-
56
- with pytest.raises(TemplateError) as ex:
57
- NotificationMsg("notifications/title_only.html")
58
- assert "No block with name 'body_plain'" in str(ex.value)
59
-
60
-
61
- def test_message_templates_escaping(app_with_notifs):
62
- """Test templates escaping."""
63
- title = (
64
- "Spèciâl chäráctèrs: "
65
- "`,~,!,@,#,$,%,^,&,*,(,),_,-,+,=,{,[,},},|,\\,:,;,',<,>,.,?,/,º,ª "
66
- "<script>alert('test');</script>"
67
- )
68
- ctx = dict(title=title)
69
- with app_with_notifs.app_context():
70
- # remove footer
71
- app_with_notifs.config["ILS_NOTIFICATIONS_TEMPLATES"] = {}
72
-
73
- full = NotificationMsg("notifications/title_body_html_ctx.html", ctx)
74
-
75
- assert full.title == 'Test "{0}" title.'.format(title)
76
-
77
- from markupsafe import escape
78
-
79
- escaped = escape(title)
80
- assert 'Test "{0}" body.'.format(escaped) == full.body_plain
81
- assert 'Test "{0}" html.'.format(escaped) == full.body_html
82
-
83
-
84
- def test_message_with_missing_template(app_with_notifs):
85
- """Test that a missing template raises an exception."""
86
- with app_with_notifs.app_context():
87
- with pytest.raises(TemplateNotFound):
88
- NotificationMsg("missing.html")
89
-
90
-
91
- def test_send_message_backend(app_with_notifs, users, testdata, mocker):
92
- """Test that notifications backend is called when sending."""
93
- send_mocked = mocker.patch("invenio_app_ils.notifications.backends.mail.send")
94
- send_mocked.__name__ = "send"
95
- send_mocked.__annotations__ = "send"
96
- backends = mocker.patch(
97
- "invenio_app_ils.notifications.api._get_notification_backends",
98
- return_value=[send_mocked],
99
- )
100
- with app_with_notifs.app_context():
101
- # remove footer
102
- app_with_notifs.config["ILS_NOTIFICATIONS_TEMPLATES"] = {}
103
-
104
- msg = NotificationMsg("notifications/title_body_html.html")
105
- patrons = [Patron(users["patron1"].id)]
106
- send_notification(patrons, msg)
107
-
108
- assert send_mocked.apply_async.called
109
-
110
-
111
- class FakeMessage(NotificationMsg):
112
- def __init__(self, *args, **kwargs):
113
- template = kwargs.pop("template", "notifications/title_body_html.html")
114
- super().__init__(template, **kwargs)
115
-
116
-
117
- def test_log_successful_error_mail_task(app_with_notifs, users, testdata, mocker):
118
- """Test that a successfully sent email is logged."""
119
- # !attention the mocker has to patch function where it is used, not defined
120
- succ = mocker.patch("invenio_app_ils.notifications.api.log_successful_notification")
121
- err = mocker.patch("invenio_app_ils.notifications.api.log_error_notification")
122
-
123
- patron = Patron(users["patron1"].id)
124
-
125
- assert not succ.s.called
126
- assert not err.s.called
127
- send_notification([patron], FakeMessage())
128
- assert succ.s.called
129
- assert err.s.called
130
-
131
-
132
- def test_notifications_db_table_and_endpoint(
133
- users, client, json_headers, app_with_notifs
134
- ):
135
- """Test logging of notifs in db table and read from endpoint."""
136
- request = {"id": "test-id", "task": "test-task"}
137
- data = {
138
- "id": "test-id",
139
- "recipients": ["patron1@test.com"],
140
- "is_manually_triggered": True,
141
- "message_id": "1",
142
- "patron_id": "1",
143
- }
144
- exc = "An error occurred."
145
- log_successful_notification(None, data)
146
-
147
- log_error_notification(request=request, exc=exc, traceback=None, data=data)
148
-
149
- assert NotificationsLogs.query.filter_by(id=1).one().send_log == "Success"
150
- assert (
151
- NotificationsLogs.query.filter_by(id=2).one().send_log
152
- == "Error: 'An error occurred.'"
153
- )
154
-
155
- ITEM_ENDPOINT = "invenio_app_ils_notifications.get_notification"
156
- LIST_ENDPOINT = "invenio_app_ils_notifications.get_notifications"
157
-
158
- user_login(client, "librarian", users)
159
- url = url_for(LIST_ENDPOINT)
160
- res = client.get(url, headers=json_headers)
161
- assert res.get_json()["hits"][0]["send_log"] == "Error: 'An error occurred.'"
162
- assert res.get_json()["hits"][1]["send_log"] == "Success"
163
-
164
- url = url_for(ITEM_ENDPOINT, id=1)
165
- res = client.get(url, headers=json_headers)
166
- assert res.get_json()["send_log"] == "Success"
167
- assert res.get_json()["id"] == 1
168
-
169
- url = url_for(ITEM_ENDPOINT, id=2)
170
- res = client.get(url, headers=json_headers)
171
-
172
- assert res.get_json()["send_log"] == "Error: 'An error occurred.'"
173
- assert res.get_json()["id"] == 2
@@ -1,37 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
- # Copyright (C) 2021 CERN.
4
- #
5
- # invenio-app-ils is free software; you can redistribute it and/or modify it
6
- # under the terms of the MIT License; see LICENSE file for more details.
7
-
8
- """Test notifications backend emails."""
9
-
10
- from invenio_app_ils.notifications.api import send_notification
11
- from invenio_app_ils.notifications.messages import NotificationMsg
12
- from invenio_app_ils.patrons.api import Patron
13
-
14
-
15
- class FakeMessage(NotificationMsg):
16
- def __init__(self, *args, **kwargs):
17
- template = kwargs.pop("template", "notifications/title_body_html.html")
18
- super().__init__(template, **kwargs)
19
-
20
-
21
- def test_send_only_to_test_recipients(app_with_notifs, users, testdata, mocker):
22
- """Tests that send only to test recipients works."""
23
- app_with_notifs.config["ILS_MAIL_ENABLE_TEST_RECIPIENTS"] = True
24
- succ = mocker.patch("invenio_app_ils.notifications.api.log_successful_notification")
25
-
26
- msg = FakeMessage()
27
- patron = Patron(users["patron1"].id)
28
-
29
- fake_recipients = app_with_notifs.config["ILS_MAIL_NOTIFY_TEST_RECIPIENTS"]
30
- with app_with_notifs.extensions["mail"].record_messages() as outbox:
31
- assert len(outbox) == 0
32
- send_notification([patron], msg)
33
- assert succ.s.called
34
- assert len(outbox) == 1
35
- assert outbox[0].recipients == fake_recipients
36
-
37
- app_with_notifs.config["ILS_MAIL_ENABLE_TEST_RECIPIENTS"] = False
@@ -1,55 +0,0 @@
1
- # Copyright (C) 2021 CERN.
2
- #
3
- # invenio-app-ils is free software; you can redistribute it and/or modify it
4
- # under the terms of the MIT License; see LICENSE file for more details.
5
-
6
- """Test notifications permissions."""
7
-
8
- from flask import url_for
9
-
10
- from tests.helpers import user_login
11
-
12
- _HTTP_OK = [200, 201, 204]
13
- _HTTP_UNAUTHORIZED = [401]
14
- _HTTP_FORBIDDEN = [403]
15
- _HTTP_NOT_FOUND = [404]
16
- MAIL_ID = 1
17
- ITEM_ENDPOINT = "invenio_app_ils_notifications.get_notification"
18
- LIST_ENDPOINT = "invenio_app_ils_notifications.get_notifications"
19
-
20
-
21
- def test_notifications_read_permissions(client, json_headers, users):
22
- """Test notifications endpoints read permissions."""
23
- list_tests = [
24
- ("admin", _HTTP_OK),
25
- ("librarian", _HTTP_OK),
26
- ("patron1", _HTTP_FORBIDDEN),
27
- ("anonymous", _HTTP_UNAUTHORIZED),
28
- ]
29
-
30
- item_tests = [
31
- ("admin", _HTTP_NOT_FOUND),
32
- ("librarian", _HTTP_NOT_FOUND),
33
- ("patron1", _HTTP_FORBIDDEN),
34
- ("anonymous", _HTTP_UNAUTHORIZED),
35
- ]
36
-
37
- def _test_list(expected_status):
38
- """Test get list."""
39
- url = url_for(LIST_ENDPOINT)
40
- res = client.get(url, headers=json_headers)
41
- assert res.status_code in expected_status
42
-
43
- def _test_read(expected_status, id):
44
- """Test record read."""
45
- url = url_for(ITEM_ENDPOINT, id=id)
46
- res = client.get(url, headers=json_headers)
47
- assert res.status_code in expected_status
48
-
49
- for username, expected_status in list_tests:
50
- user_login(client, username, users)
51
- _test_list(expected_status)
52
-
53
- for username, expected_status in item_tests:
54
- user_login(client, username, users)
55
- _test_read(expected_status, MAIL_ID)
@@ -1,102 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
- # Copyright (C) 2019 CERN.
4
- #
5
- # invenio-app-ils is free software; you can redistribute it and/or modify it
6
- # under the terms of the MIT License; see LICENSE file for more details.
7
-
8
- """Test patrons endpoint."""
9
-
10
- import json
11
-
12
- from flask import url_for
13
-
14
- from tests.helpers import user_login
15
-
16
- _LIST_ENDPOINT = "invenio_records_rest.patid_list"
17
-
18
-
19
- def _patron_loans_request(client, json_headers, document_pid):
20
- """Perform a patron loans request."""
21
- response = client.get(
22
- url_for(
23
- "invenio_app_ils_patrons.get_user_information",
24
- document_pid=document_pid,
25
- ),
26
- headers=json_headers,
27
- )
28
- return json.loads(response.data.decode("utf-8"))
29
-
30
-
31
- def _assert_patron_loans_information(client, json_headers, document_pid, expect):
32
- """Assert patron loan information."""
33
- resp = _patron_loans_request(client, json_headers, document_pid)
34
- assert resp == expect
35
-
36
-
37
- def _assert_error_when_not_authenticated(client, json_headers, document_pid):
38
- """Assert user is not logged in."""
39
- resp = _patron_loans_request(client, json_headers, document_pid)
40
- assert resp["status"] == 401
41
-
42
-
43
- def test_patrons_permissions(client, testdata, json_headers, users):
44
- """Test patron endpoints permissions."""
45
- tests = [
46
- ("admin", [200]),
47
- ("librarian", [200]),
48
- ("patron1", [403]),
49
- ("anonymous", [401]),
50
- ]
51
-
52
- def _test_list(expected_status):
53
- """Test get list."""
54
- url = url_for(_LIST_ENDPOINT)
55
- res = client.get(url, headers=json_headers)
56
- assert res.status_code in expected_status
57
-
58
- for username, expected_status in tests:
59
- user_login(client, username, users)
60
- _test_list(expected_status)
61
-
62
-
63
- def test_patron_loans_information(client, json_headers, testdata_most_loaned, users):
64
- """Test patron loans information API endpoint."""
65
- _assert_error_when_not_authenticated(client, json_headers, "docid-1")
66
- user_login(client, "librarian", users)
67
-
68
- _assert_patron_loans_information(
69
- client,
70
- json_headers,
71
- "docid-1",
72
- expect={
73
- "has_active_loan": False,
74
- "is_requested": False,
75
- "last_loan": None,
76
- },
77
- )
78
-
79
- user_login(client, "patron1", users)
80
-
81
- _assert_patron_loans_information(
82
- client,
83
- json_headers,
84
- "docid-1",
85
- expect={
86
- "has_active_loan": False,
87
- "is_requested": True,
88
- "last_loan": "2019-04-02",
89
- },
90
- )
91
-
92
- user_login(client, "patron2", users)
93
- _assert_patron_loans_information(
94
- client,
95
- json_headers,
96
- "docid-3",
97
- expect={
98
- "has_active_loan": False,
99
- "is_requested": True,
100
- "last_loan": None,
101
- },
102
- )
@@ -1,42 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
- # Copyright (C) 2018-19 CERN.
4
- #
5
- # invenio-app-ils is free software; you can redistribute it and/or modify it
6
- # under the terms of the MIT License; see LICENSE file for more details.
7
-
8
- """Test record delete."""
9
-
10
- from flask import url_for
11
-
12
- from tests.helpers import user_login
13
-
14
-
15
- def test_delete_location(client, users, json_headers, testdata):
16
- """Test DELETE existing location."""
17
- user_login(client, "admin", users)
18
-
19
- location_pid = "locid-1"
20
- url = url_for("invenio_records_rest.locid_item", pid_value=location_pid)
21
- res = client.delete(url, headers=json_headers)
22
- assert res.status_code == 400
23
-
24
- location_pid = "locid-3"
25
- url = url_for("invenio_records_rest.locid_item", pid_value=location_pid)
26
- res = client.delete(url, headers=json_headers)
27
- assert res.status_code == 204
28
-
29
-
30
- def test_delete_internal_location(client, users, json_headers, testdata):
31
- """Test DELETE existing internal_location."""
32
- user_login(client, "admin", users)
33
-
34
- internal_location_pid = "ilocid-1"
35
- url = url_for("invenio_records_rest.ilocid_item", pid_value=internal_location_pid)
36
- res = client.delete(url, headers=json_headers)
37
- assert res.status_code == 400
38
-
39
- internal_location_pid = "ilocid-3"
40
- url = url_for("invenio_records_rest.ilocid_item", pid_value=internal_location_pid)
41
- res = client.delete(url, headers=json_headers)
42
- assert res.status_code == 204