Skip to content

Commit ff73c5f

Browse files
committed
✨ [maykinmedia/commonground-api-common#142] Use exception handler registry from commonground-api-common
1 parent ff5f242 commit ff73c5f

File tree

13 files changed

+246
-197
lines changed

13 files changed

+246
-197
lines changed

requirements/base.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ click-plugins==1.1.1
6060
# via celery
6161
click-repl==0.3.0
6262
# via celery
63-
commonground-api-common==2.10.7
63+
commonground-api-common==2.11.0
6464
# via
6565
# -r requirements/base.in
6666
# open-api-framework

requirements/ci.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ click-repl==0.3.0
111111
# celery
112112
codecov==2.1.13
113113
# via -r requirements/test-tools.in
114-
commonground-api-common==2.10.7
114+
commonground-api-common==2.11.0
115115
# via
116116
# -c requirements/base.txt
117117
# -r requirements/base.txt

requirements/dev.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ codecov==2.1.13
139139
# via
140140
# -c requirements/ci.txt
141141
# -r requirements/ci.txt
142-
commonground-api-common==2.10.7
142+
commonground-api-common==2.11.0
143143
# via
144144
# -c requirements/ci.txt
145145
# -r requirements/ci.txt

src/objects/conf/api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"DEFAULT_VERSION": "v2", # NOT to be confused with API_VERSION - it's the major version part
1515
"ALLOWED_VERSIONS": ("v2",),
1616
"VERSION_PARAM": "version",
17-
"EXCEPTION_HANDLER": "objects.utils.views.exception_handler",
17+
"EXCEPTION_HANDLER": "vng_api_common.exception_handling.exception_handler",
1818
# test
1919
"TEST_REQUEST_DEFAULT_FORMAT": "json",
2020
}

src/objects/tests/v2/test_auth_fields.py

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
from rest_framework import status
66
from rest_framework.test import APITestCase
7+
from vng_api_common.tests import get_validation_errors
78

89
from objects.core.tests.factories import (
910
ObjectFactory,
@@ -109,9 +110,12 @@ def test_retrieve_incorrect_auth_fields(self):
109110
response = self.client.get(url)
110111

111112
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
113+
114+
error = get_validation_errors(response, "")
115+
112116
self.assertEqual(
113-
response.json(),
114-
["Fields in the configured authorization are absent in the data: 'some'"],
117+
error["reason"],
118+
"Fields in the configured authorization are absent in the data: 'some'",
115119
)
116120

117121
def test_retrieve_query_fields_not_allowed(self):
@@ -304,7 +308,9 @@ def test_list_incorrect_auth_fields(self):
304308
fields={"1": ["url", "uuid", "record"]},
305309
)
306310
ObjectRecordFactory.create(
307-
object__object_type=self.object_type, data={"name": "some"}, version=1
311+
object__object_type=self.object_type,
312+
data={"name": "some"},
313+
version=1,
308314
)
309315
ObjectRecordFactory.create(
310316
object__object_type=self.other_object_type,
@@ -315,9 +321,12 @@ def test_list_incorrect_auth_fields(self):
315321
response = self.client.get(self.url)
316322

317323
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
318-
self.assertEqual(
319-
response.json(),
320-
["Fields in the configured authorization are absent in the data: 'some'"],
324+
325+
error = get_validation_errors(response, "")
326+
327+
self.assertIn(
328+
"Fields in the configured authorization are absent in the data: 'some'",
329+
error["reason"],
321330
)
322331

323332
def test_retrieve_query_fields_not_allowed(self):
@@ -336,7 +345,9 @@ def test_retrieve_query_fields_not_allowed(self):
336345
fields={"1": ["url", "uuid", "record"]},
337346
)
338347
ObjectRecordFactory.create(
339-
object__object_type=self.object_type, data={"name": "some"}, version=1
348+
object__object_type=self.object_type,
349+
data={"name": "some"},
350+
version=1,
340351
)
341352
ObjectRecordFactory.create(
342353
object__object_type=self.other_object_type,
@@ -347,9 +358,12 @@ def test_retrieve_query_fields_not_allowed(self):
347358
response = self.client.get(self.url, {"fields": "uuid"})
348359

349360
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
361+
362+
data = response.json()
363+
350364
self.assertEqual(
351-
response.json(),
352-
["'fields' query parameter has invalid or unauthorized values: 'uuid'"],
365+
data["invalid_params"][0]["reason"],
366+
"'fields' query parameter has invalid or unauthorized values: 'uuid'",
353367
)
354368

355369
def test_list_no_allowed_fields(self):

src/objects/tests/v2/test_filters.py

Lines changed: 85 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from furl import furl
88
from rest_framework import status
99
from rest_framework.test import APITestCase
10+
from vng_api_common.tests import get_validation_errors
1011

1112
from objects.core.tests.factories import (
1213
ObjectFactory,
@@ -66,7 +67,11 @@ def test_filter_invalid_objecttype(self):
6667
response = self.client.get(self.url, {"type": "invalid-objecttype-url"})
6768

6869
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
69-
self.assertEqual(response.json()["type"], ["Invalid value."])
70+
71+
error = get_validation_errors(response, "type")
72+
73+
self.assertEqual(error["reason"], "Invalid value.")
74+
self.assertEqual(error["code"], "invalid")
7075

7176
def test_filter_unknown_objecttype(self):
7277
objecttype_url = (
@@ -75,19 +80,30 @@ def test_filter_unknown_objecttype(self):
7580
response = self.client.get(self.url, {"type": objecttype_url})
7681

7782
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
83+
84+
error = get_validation_errors(response, "type")
85+
7886
self.assertEqual(
79-
response.json()["type"],
80-
[
81-
f"Select a valid object type. {objecttype_url} is not one of the available choices."
82-
],
87+
error,
88+
{
89+
"name": "type",
90+
"code": "invalid_choice",
91+
"reason": (
92+
f"Select a valid object type. {objecttype_url} is not one of the available choices."
93+
),
94+
},
8395
)
8496

8597
def test_filter_too_long_object_type(self):
8698
object_type_long = f"{OBJECT_TYPES_API}{'a' * 1000}/{self.object_type.uuid}"
8799
response = self.client.get(self.url, {"type": object_type_long})
88100

89101
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
90-
self.assertEqual(response.json()["type"], ["The value has too many characters"])
102+
103+
error = get_validation_errors(response, "type")
104+
105+
self.assertEqual(error["code"], "max_length")
106+
self.assertEqual(error["reason"], "The value has too many characters")
91107

92108

93109
class FilterDataAttrsTests(TokenAuthMixin, APITestCase):
@@ -218,8 +234,12 @@ def test_filter_lte_not_numerical(self):
218234
response = self.client.get(self.url, {"data_attrs": "diameter__lt__value"})
219235

220236
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
237+
238+
error = get_validation_errors(response, "")
239+
221240
self.assertEqual(
222-
response.json(), ["Operator `lt` supports only dates and/or numeric values"]
241+
error["reason"],
242+
"Operator `lt` supports only dates and/or numeric values",
223243
)
224244

225245
def test_filter_lte_date(self):
@@ -255,20 +275,27 @@ def test_filter_lte_date(self):
255275

256276
def test_filter_invalid_operator(self):
257277
response = self.client.get(self.url, {"data_attrs": "diameter__not__value"})
258-
259278
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
260-
self.assertEqual(response.json(), ["Comparison operator `not` is unknown"])
279+
280+
error = get_validation_errors(response, "")
281+
282+
self.assertEqual(
283+
error["reason"],
284+
"Comparison operator `not` is unknown",
285+
)
286+
self.assertEqual(error["code"], "invalid-data-attrs-query")
261287

262288
def test_filter_invalid_param(self):
263289
response = self.client.get(self.url, {"data_attrs": "diameter__exact"})
264-
265290
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
291+
292+
error = get_validation_errors(response, "")
293+
266294
self.assertEqual(
267-
response.json(),
268-
[
269-
"Filter expression 'diameter__exact' doesn't have the shape 'key__operator__value'"
270-
],
295+
error["reason"],
296+
"Filter expression 'diameter__exact' doesn't have the shape 'key__operator__value'",
271297
)
298+
self.assertEqual(error["code"], "invalid-data-attrs-query")
272299

273300
def test_filter_nested_attr(self):
274301
record = ObjectRecordFactory.create(
@@ -570,8 +597,11 @@ def test_filter_lte_not_numerical(self):
570597
response = self.client.get(self.url, {"data_attr": "diameter__lt__value"})
571598

572599
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
573-
self.assertEqual(
574-
response.json(), ["Operator `lt` supports only dates and/or numeric values"]
600+
601+
error = get_validation_errors(response, "")
602+
603+
self.assertIn(
604+
"Operator `lt` supports only dates and/or numeric values", error["reason"]
575605
)
576606

577607
def test_filter_lte_date(self):
@@ -609,17 +639,24 @@ def test_filter_invalid_operator(self):
609639
response = self.client.get(self.url, {"data_attr": "diameter__not__value"})
610640

611641
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
612-
self.assertEqual(response.json(), ["Comparison operator `not` is unknown"])
642+
643+
error = get_validation_errors(response, "")
644+
645+
self.assertEqual(
646+
error["reason"],
647+
"Comparison operator `not` is unknown",
648+
)
613649

614650
def test_filter_invalid_param(self):
615651
response = self.client.get(self.url, {"data_attr": "diameter__exact"})
616652

617653
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
654+
655+
error = get_validation_errors(response, "")
656+
618657
self.assertEqual(
619-
response.json(),
620-
[
621-
"Filter expression 'diameter__exact' doesn't have the shape 'key__operator__value'"
622-
],
658+
error["reason"],
659+
"Filter expression 'diameter__exact' doesn't have the shape 'key__operator__value'",
623660
)
624661

625662
def test_filter_nested_attr(self):
@@ -819,18 +856,21 @@ def test_filter_two_icontains_with_comma(self):
819856

820857
def test_filter_comma_separated_invalid(self):
821858
response = self.client.get(
822-
self.url, {"data_attr": "dimensions__diameter__exact__4,name__exact__demo"}
859+
self.url,
860+
{"data_attr": "dimensions__diameter__exact__4,name__exact__demo"},
823861
)
824862

825863
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
864+
865+
error = get_validation_errors(response, "")
866+
826867
self.assertEqual(
827-
response.json(),
828-
[
829-
"Filter expression 'dimensions__diameter__exact__4,name__exact__demo' "
830-
"must have the shape 'key__operator__value', commas can only be present in "
831-
"the 'value'"
832-
],
868+
error["reason"],
869+
"Filter expression 'dimensions__diameter__exact__4,name__exact__demo' "
870+
"must have the shape 'key__operator__value', commas can only be present in "
871+
"the 'value'",
833872
)
873+
self.assertEqual(error["code"], "invalid-data-attr-query")
834874

835875

836876
class FilterDateTests(TokenAuthMixin, APITestCase):
@@ -941,6 +981,8 @@ def test_filter_registration_date_list(self):
941981

942982
response = self.client.get(url, {"registrationDate": "2020-07-01"})
943983

984+
self.assertEqual(response.status_code, status.HTTP_200_OK)
985+
944986
data = response.json()["results"]
945987

946988
self.assertEqual(len(data), 1)
@@ -952,17 +994,18 @@ def test_filter_registration_date_list(self):
952994

953995
def test_filter_on_both_date_and_registration_date(self):
954996
url = reverse_lazy("object-list")
955-
956997
response = self.client.get(
957-
url, {"date": "2020-07-01", "registrationDate": "2020-08-01"}
998+
url,
999+
{"date": "2020-07-01", "registrationDate": "2020-08-01"},
9581000
)
9591001

9601002
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
1003+
1004+
data = response.json()
1005+
9611006
self.assertEqual(
962-
response.json(),
963-
[
964-
"'date' and 'registrationDate' parameters can't be used in the same request"
965-
],
1007+
data["invalid_params"][0]["reason"],
1008+
"'date' and 'registrationDate' parameters can't be used in the same request",
9661009
)
9671010

9681011

@@ -1033,13 +1076,19 @@ def test_filter_db_error(self, mock_query):
10331076
response = self.client.get(self.url, {"data_icontains": "some"})
10341077

10351078
self.assertEqual(response.status_code, status.HTTP_500_INTERNAL_SERVER_ERROR)
1079+
1080+
data = response.json()
1081+
1082+
data.pop("instance", None)
1083+
10361084
self.assertEqual(
1037-
response.json(),
1085+
data,
10381086
{
1039-
"code": "error",
1087+
"code": "search-not-supported",
10401088
"title": "Internal Server Error",
10411089
"status": 500,
10421090
"detail": "This search operation is not supported by the underlying data store.",
1091+
"type": "http://testserver/ref/fouten/ProgrammingError/",
10431092
},
10441093
)
10451094

src/objects/tests/v2/test_object_api.py

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from freezegun import freeze_time
77
from rest_framework import status
88
from rest_framework.test import APITestCase
9+
from vng_api_common.tests import get_validation_errors
910

1011
from objects.core.models import Object, Reference
1112
from objects.core.tests.factories import (
@@ -869,7 +870,21 @@ def test_list_incorrect_date(self):
869870
response = self.client.get(self.url, {"date": "2024-31-08"})
870871

871872
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
872-
self.assertEqual(response.json(), {"date": ["Enter a valid date."]})
873+
874+
data = response.json()
875+
876+
self.assertEqual(data["status"], 400)
877+
self.assertEqual(data["code"], "invalid")
878+
self.assertEqual(data["title"], "Invalid input.")
879+
error = get_validation_errors(response, "date")
880+
self.assertEqual(
881+
error["name"],
882+
"date",
883+
)
884+
self.assertEqual(
885+
error["reason"],
886+
"Enter a valid date.",
887+
)
873888

874889
def test_list_available_for_registration_date(self):
875890
with self.subTest("filter on old name"):
@@ -903,4 +918,20 @@ def test_list_incorrect_registration_date(self):
903918
response = self.client.get(self.url, {"registrationDate": "2024-31-08"})
904919

905920
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
906-
self.assertEqual(response.json(), {"registrationDate": ["Enter a valid date."]})
921+
922+
data = response.json()
923+
924+
self.assertEqual(data["status"], 400)
925+
self.assertEqual(data["code"], "invalid")
926+
self.assertEqual(data["title"], "Invalid input.")
927+
928+
error = get_validation_errors(response, "registrationDate")
929+
930+
self.assertEqual(
931+
error["name"],
932+
"registrationDate",
933+
)
934+
self.assertEqual(
935+
error["reason"],
936+
"Enter a valid date.",
937+
)

0 commit comments

Comments
 (0)