diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 614cb1c1..ec8e8bfb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -46,6 +46,7 @@ repos: entry: pylint language: python types: [ python ] + args: [ "--extension-pkg-allow-list=orjson"] exclude: tests|test_project|manage.py additional_dependencies: - django @@ -60,3 +61,4 @@ repos: - drf-spectacular - pylint - faker + - orjson diff --git a/openapi_tester/clients.py b/openapi_tester/clients.py index 281262bd..aa3ae9c6 100644 --- a/openapi_tester/clients.py +++ b/openapi_tester/clients.py @@ -49,7 +49,6 @@ def request(self, *args, **kwargs) -> Response: # type: ignore[override] self.schema_tester.validate_response(response_handler=response_handler) return response - # pylint: disable=W0622 @serialize_json def post( self, @@ -63,7 +62,6 @@ def post( **kwargs, ) - # pylint: disable=W0622 @serialize_json def put( self, @@ -77,7 +75,6 @@ def put( **kwargs, ) - # pylint: disable=W0622 @serialize_json def patch(self, *args, content_type="application/json", **kwargs): return super().patch( @@ -86,7 +83,6 @@ def patch(self, *args, content_type="application/json", **kwargs): **kwargs, ) - # pylint: disable=W0622 @serialize_json def delete( self, @@ -100,7 +96,6 @@ def delete( **kwargs, ) - # pylint: disable=W0622 @serialize_json def options( self, diff --git a/openapi_tester/loaders.py b/openapi_tester/loaders.py index f2fefbdf..3ee4565b 100644 --- a/openapi_tester/loaders.py +++ b/openapi_tester/loaders.py @@ -3,13 +3,12 @@ from __future__ import annotations import difflib -import json import pathlib import re -from json import dumps, loads from typing import TYPE_CHECKING, cast from urllib.parse import urlparse +import orjson import requests import yaml from django.urls import Resolver404, resolve @@ -225,7 +224,8 @@ def load_schema(self) -> dict: Loads generated schema from drf-yasg and returns it as a dict. """ odict_schema = self.schema_generator.get_schema(None, True) - return cast("dict", loads(dumps(odict_schema.as_odict()))) + str_schema = orjson.dumps(odict_schema.as_odict()).decode("utf-8") + return cast("dict", orjson.loads(str_schema)) def resolve_path( self, endpoint_path: str, method: str @@ -253,7 +253,10 @@ def load_schema(self) -> dict: """ Loads generated schema from drf_spectacular and returns it as a dict. """ - return cast("dict", loads(dumps(self.schema_generator.get_schema(public=True)))) + str_schema = orjson.dumps(self.schema_generator.get_schema(public=True)).decode( + "utf-8" + ) + return cast("dict", orjson.loads(str_schema)) def resolve_path( self, endpoint_path: str, method: str @@ -290,7 +293,7 @@ def load_schema(self) -> dict[str, Any]: content = file.read() return cast( "dict", - json.loads(content) + orjson.loads(content) if ".json" in self.path else yaml.load(content, Loader=yaml.FullLoader), ) @@ -316,7 +319,7 @@ def load_schema(self) -> dict[str, Any]: return cast( "dict", ( - json.loads(response.content) + orjson.loads(response.content) if ".json" in self.url else yaml.load(response.content, Loader=yaml.FullLoader) ), diff --git a/openapi_tester/response_handler.py b/openapi_tester/response_handler.py index e720287e..c1bfb103 100644 --- a/openapi_tester/response_handler.py +++ b/openapi_tester/response_handler.py @@ -2,11 +2,12 @@ This module contains the concrete response handlers for both DRF and Django Ninja responses. """ -import json from abc import ABC, abstractmethod from dataclasses import dataclass, field from typing import TYPE_CHECKING, Any, Optional, Union +import orjson + if TYPE_CHECKING: from django.http.response import HttpResponse from rest_framework.response import Response @@ -95,6 +96,6 @@ def request(self) -> GenericRequest: def _build_request_data(self, request_data: Any) -> dict: try: - return json.loads(request_data) - except (json.JSONDecodeError, TypeError, ValueError): + return orjson.loads(request_data) + except (orjson.JSONDecodeError, TypeError, ValueError): return {} diff --git a/openapi_tester/utils.py b/openapi_tester/utils.py index 9c661476..d26c6156 100644 --- a/openapi_tester/utils.py +++ b/openapi_tester/utils.py @@ -4,11 +4,12 @@ from __future__ import annotations -import json from copy import deepcopy from itertools import chain, combinations from typing import TYPE_CHECKING +import orjson + if TYPE_CHECKING: from typing import Any, Iterator, Sequence @@ -57,7 +58,7 @@ def normalize_schema_section(schema_section: dict[str, Any]) -> dict[str, Any]: def serialize_schema_section_data(data: dict[str, Any]) -> str: - return json.dumps(data, indent=4, default=str) + return orjson.dumps(data, option=orjson.OPT_INDENT_2, default=str).decode("utf-8") def lazy_combinations(options_list: Sequence[dict[str, Any]]) -> Iterator[dict]: @@ -76,7 +77,7 @@ def wrapper(*args, **kwargs): content_type = kwargs.get("content_type") if data and content_type == "application/json": try: - kwargs["data"] = json.dumps(data) + kwargs["data"] = orjson.dumps(data) except (TypeError, OverflowError): kwargs["data"] = data return func(*args, **kwargs) diff --git a/openapi_tester/validators.py b/openapi_tester/validators.py index 75ad026b..3de7e0a0 100644 --- a/openapi_tester/validators.py +++ b/openapi_tester/validators.py @@ -3,11 +3,11 @@ from __future__ import annotations import base64 -import json import re from typing import TYPE_CHECKING from uuid import UUID +import orjson from django.core.exceptions import ValidationError from django.core.validators import ( EmailValidator, @@ -200,7 +200,9 @@ def validate_unique_items( unique_items = schema_section.get("uniqueItems") if unique_items: comparison_data = ( - json.dumps(item, sort_keys=True) if isinstance(item, dict) else item + orjson.dumps(item, option=orjson.OPT_SORT_KEYS).decode("utf-8") + if isinstance(item, dict) + else item for item in data ) if len(set(comparison_data)) != len(data): diff --git a/poetry.lock b/poetry.lock index ea8352ea..c6adda64 100644 --- a/poetry.lock +++ b/poetry.lock @@ -734,6 +734,72 @@ jsonschema-path = ">=0.3.1,<0.4.0" lazy-object-proxy = ">=1.7.1,<2.0.0" openapi-schema-validator = ">=0.6.0,<0.7.0" +[[package]] +name = "orjson" +version = "3.10.7" +description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" +optional = false +python-versions = ">=3.8" +files = [ + {file = "orjson-3.10.7-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:74f4544f5a6405b90da8ea724d15ac9c36da4d72a738c64685003337401f5c12"}, + {file = "orjson-3.10.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34a566f22c28222b08875b18b0dfbf8a947e69df21a9ed5c51a6bf91cfb944ac"}, + {file = "orjson-3.10.7-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bf6ba8ebc8ef5792e2337fb0419f8009729335bb400ece005606336b7fd7bab7"}, + {file = "orjson-3.10.7-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac7cf6222b29fbda9e3a472b41e6a5538b48f2c8f99261eecd60aafbdb60690c"}, + {file = "orjson-3.10.7-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:de817e2f5fc75a9e7dd350c4b0f54617b280e26d1631811a43e7e968fa71e3e9"}, + {file = "orjson-3.10.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:348bdd16b32556cf8d7257b17cf2bdb7ab7976af4af41ebe79f9796c218f7e91"}, + {file = "orjson-3.10.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:479fd0844ddc3ca77e0fd99644c7fe2de8e8be1efcd57705b5c92e5186e8a250"}, + {file = "orjson-3.10.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:fdf5197a21dd660cf19dfd2a3ce79574588f8f5e2dbf21bda9ee2d2b46924d84"}, + {file = "orjson-3.10.7-cp310-none-win32.whl", hash = "sha256:d374d36726746c81a49f3ff8daa2898dccab6596864ebe43d50733275c629175"}, + {file = "orjson-3.10.7-cp310-none-win_amd64.whl", hash = "sha256:cb61938aec8b0ffb6eef484d480188a1777e67b05d58e41b435c74b9d84e0b9c"}, + {file = "orjson-3.10.7-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:7db8539039698ddfb9a524b4dd19508256107568cdad24f3682d5773e60504a2"}, + {file = "orjson-3.10.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:480f455222cb7a1dea35c57a67578848537d2602b46c464472c995297117fa09"}, + {file = "orjson-3.10.7-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8a9c9b168b3a19e37fe2778c0003359f07822c90fdff8f98d9d2a91b3144d8e0"}, + {file = "orjson-3.10.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8de062de550f63185e4c1c54151bdddfc5625e37daf0aa1e75d2a1293e3b7d9a"}, + {file = "orjson-3.10.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6b0dd04483499d1de9c8f6203f8975caf17a6000b9c0c54630cef02e44ee624e"}, + {file = "orjson-3.10.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b58d3795dafa334fc8fd46f7c5dc013e6ad06fd5b9a4cc98cb1456e7d3558bd6"}, + {file = "orjson-3.10.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:33cfb96c24034a878d83d1a9415799a73dc77480e6c40417e5dda0710d559ee6"}, + {file = "orjson-3.10.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e724cebe1fadc2b23c6f7415bad5ee6239e00a69f30ee423f319c6af70e2a5c0"}, + {file = "orjson-3.10.7-cp311-none-win32.whl", hash = "sha256:82763b46053727a7168d29c772ed5c870fdae2f61aa8a25994c7984a19b1021f"}, + {file = "orjson-3.10.7-cp311-none-win_amd64.whl", hash = "sha256:eb8d384a24778abf29afb8e41d68fdd9a156cf6e5390c04cc07bbc24b89e98b5"}, + {file = "orjson-3.10.7-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:44a96f2d4c3af51bfac6bc4ef7b182aa33f2f054fd7f34cc0ee9a320d051d41f"}, + {file = "orjson-3.10.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76ac14cd57df0572453543f8f2575e2d01ae9e790c21f57627803f5e79b0d3c3"}, + {file = "orjson-3.10.7-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bdbb61dcc365dd9be94e8f7df91975edc9364d6a78c8f7adb69c1cdff318ec93"}, + {file = "orjson-3.10.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b48b3db6bb6e0a08fa8c83b47bc169623f801e5cc4f24442ab2b6617da3b5313"}, + {file = "orjson-3.10.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:23820a1563a1d386414fef15c249040042b8e5d07b40ab3fe3efbfbbcbcb8864"}, + {file = "orjson-3.10.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0c6a008e91d10a2564edbb6ee5069a9e66df3fbe11c9a005cb411f441fd2c09"}, + {file = "orjson-3.10.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d352ee8ac1926d6193f602cbe36b1643bbd1bbcb25e3c1a657a4390f3000c9a5"}, + {file = "orjson-3.10.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d2d9f990623f15c0ae7ac608103c33dfe1486d2ed974ac3f40b693bad1a22a7b"}, + {file = "orjson-3.10.7-cp312-none-win32.whl", hash = "sha256:7c4c17f8157bd520cdb7195f75ddbd31671997cbe10aee559c2d613592e7d7eb"}, + {file = "orjson-3.10.7-cp312-none-win_amd64.whl", hash = "sha256:1d9c0e733e02ada3ed6098a10a8ee0052dd55774de3d9110d29868d24b17faa1"}, + {file = "orjson-3.10.7-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:77d325ed866876c0fa6492598ec01fe30e803272a6e8b10e992288b009cbe149"}, + {file = "orjson-3.10.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ea2c232deedcb605e853ae1db2cc94f7390ac776743b699b50b071b02bea6fe"}, + {file = "orjson-3.10.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3dcfbede6737fdbef3ce9c37af3fb6142e8e1ebc10336daa05872bfb1d87839c"}, + {file = "orjson-3.10.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:11748c135f281203f4ee695b7f80bb1358a82a63905f9f0b794769483ea854ad"}, + {file = "orjson-3.10.7-cp313-none-win32.whl", hash = "sha256:a7e19150d215c7a13f39eb787d84db274298d3f83d85463e61d277bbd7f401d2"}, + {file = "orjson-3.10.7-cp313-none-win_amd64.whl", hash = "sha256:eef44224729e9525d5261cc8d28d6b11cafc90e6bd0be2157bde69a52ec83024"}, + {file = "orjson-3.10.7-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:6ea2b2258eff652c82652d5e0f02bd5e0463a6a52abb78e49ac288827aaa1469"}, + {file = "orjson-3.10.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:430ee4d85841e1483d487e7b81401785a5dfd69db5de01314538f31f8fbf7ee1"}, + {file = "orjson-3.10.7-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4b6146e439af4c2472c56f8540d799a67a81226e11992008cb47e1267a9b3225"}, + {file = "orjson-3.10.7-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:084e537806b458911137f76097e53ce7bf5806dda33ddf6aaa66a028f8d43a23"}, + {file = "orjson-3.10.7-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4829cf2195838e3f93b70fd3b4292156fc5e097aac3739859ac0dcc722b27ac0"}, + {file = "orjson-3.10.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1193b2416cbad1a769f868b1749535d5da47626ac29445803dae7cc64b3f5c98"}, + {file = "orjson-3.10.7-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:4e6c3da13e5a57e4b3dca2de059f243ebec705857522f188f0180ae88badd354"}, + {file = "orjson-3.10.7-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c31008598424dfbe52ce8c5b47e0752dca918a4fdc4a2a32004efd9fab41d866"}, + {file = "orjson-3.10.7-cp38-none-win32.whl", hash = "sha256:7122a99831f9e7fe977dc45784d3b2edc821c172d545e6420c375e5a935f5a1c"}, + {file = "orjson-3.10.7-cp38-none-win_amd64.whl", hash = "sha256:a763bc0e58504cc803739e7df040685816145a6f3c8a589787084b54ebc9f16e"}, + {file = "orjson-3.10.7-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:e76be12658a6fa376fcd331b1ea4e58f5a06fd0220653450f0d415b8fd0fbe20"}, + {file = "orjson-3.10.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed350d6978d28b92939bfeb1a0570c523f6170efc3f0a0ef1f1df287cd4f4960"}, + {file = "orjson-3.10.7-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:144888c76f8520e39bfa121b31fd637e18d4cc2f115727865fdf9fa325b10412"}, + {file = "orjson-3.10.7-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09b2d92fd95ad2402188cf51573acde57eb269eddabaa60f69ea0d733e789fe9"}, + {file = "orjson-3.10.7-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5b24a579123fa884f3a3caadaed7b75eb5715ee2b17ab5c66ac97d29b18fe57f"}, + {file = "orjson-3.10.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591bcfe7512353bd609875ab38050efe3d55e18934e2f18950c108334b4ff"}, + {file = "orjson-3.10.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:f4db56635b58cd1a200b0a23744ff44206ee6aa428185e2b6c4a65b3197abdcd"}, + {file = "orjson-3.10.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:0fa5886854673222618638c6df7718ea7fe2f3f2384c452c9ccedc70b4a510a5"}, + {file = "orjson-3.10.7-cp39-none-win32.whl", hash = "sha256:8272527d08450ab16eb405f47e0f4ef0e5ff5981c3d82afe0efd25dcbef2bcd2"}, + {file = "orjson-3.10.7-cp39-none-win_amd64.whl", hash = "sha256:974683d4618c0c7dbf4f69c95a979734bf183d0658611760017f6e70a145af58"}, + {file = "orjson-3.10.7.tar.gz", hash = "sha256:75ef0640403f945f3a1f9f6400686560dbfb0fb5b16589ad62cd477043c4eee3"}, +] + [[package]] name = "packaging" version = "24.0" @@ -1525,4 +1591,4 @@ drf-yasg = ["drf-yasg"] [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "7d6606b8a3317bcc4c2693245e62d4c57af1dd87bc9732f0c81277ec4f1e2541" +content-hash = "8ae3bc62904e349cff8554173aeb45ff8012fb8550ec8cf97898a601671ae08f" diff --git a/pyproject.toml b/pyproject.toml index 616fbbc3..d4d18a26 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -62,6 +62,7 @@ pyYAML = "*" drf-spectacular = { version = "*", optional = true } drf-yasg = { version = "*", optional = true } django-ninja = {version = "^1.1.0", optional = true} +orjson = "^3.10.7" [tool.poetry.extras] drf-yasg = ["drf-yasg"] diff --git a/tests/test_clients.py b/tests/test_clients.py index 22d6df33..46665735 100644 --- a/tests/test_clients.py +++ b/tests/test_clients.py @@ -1,7 +1,7 @@ import functools -import json from typing import TYPE_CHECKING +import orjson import pytest from django.test.testcases import SimpleTestCase from rest_framework import status @@ -129,7 +129,7 @@ def test_request_on_empty_list(openapi_client): { "method": "POST", "path": "/api/v1/vehicles", - "data": json.dumps({"vehicle_type": "1" * 50}), + "data": orjson.dumps({"vehicle_type": "1" * 50}).decode("utf-8"), "content_type": "application/json", }, { diff --git a/tests/test_django_ninja.py b/tests/test_django_ninja.py index 5219b874..cbc6f3a6 100644 --- a/tests/test_django_ninja.py +++ b/tests/test_django_ninja.py @@ -1,6 +1,6 @@ -import json from typing import TYPE_CHECKING +import orjson import pytest from openapi_tester import SchemaTester @@ -40,7 +40,7 @@ def test_create_user(client: OpenAPINinjaClient): } response = client.post( path="/", - data=json.dumps(payload), + data=orjson.dumps(payload).decode("utf-8"), content_type="application/json", ) assert response.status_code == 201 @@ -55,7 +55,7 @@ def test_update_user(client: OpenAPINinjaClient): } response = client.put( path="/1", - data=json.dumps(payload), + data=orjson.dumps(payload).decode("utf-8"), content_type="application/json", ) assert response.status_code == 200 @@ -75,6 +75,6 @@ def test_patch_user_undocumented_path(client: OpenAPINinjaClient): with pytest.raises(UndocumentedSchemaSectionError): client.patch( path="/1", - data=json.dumps(payload), + data=orjson.dumps(payload).decode("utf-8"), content_type="application/json", ) diff --git a/tests/test_openapi_object.py b/tests/test_openapi_object.py index cc6d516a..4db2269c 100644 --- a/tests/test_openapi_object.py +++ b/tests/test_openapi_object.py @@ -9,8 +9,8 @@ def test_missing_response_key_error(): expected_error_message = ( 'The following property was found in the schema definition, but is missing from the response data: "one"' "\n\nReference:\n\nPOST /endpoint > response > one" - '\n\nResponse body:\n {\n "two": 2\n}' - '\nSchema section:\n {\n "one": {\n "type": "int"\n }\n}' + '\n\nResponse body:\n {\n "two": 2\n}' + '\nSchema section:\n {\n "one": {\n "type": "int"\n }\n}' "\n\nHint: Remove the key from your OpenAPI docs, or include it in your API response" ) tester = SchemaTester() @@ -27,8 +27,8 @@ def test_missing_schema_key_error(): 'The following property was found in the response data, but is missing from the schema definition: "two"' "\n\nReference:" "\n\nPOST /endpoint > response > two" - '\n\nResponse body:\n {\n "one": 1,\n "two": 2\n}' - '\n\nSchema section:\n {\n "one": {\n "type": "int"\n }\n}' + '\n\nResponse body:\n {\n "one": 1,\n "two": 2\n}' + '\n\nSchema section:\n {\n "one": {\n "type": "int"\n }\n}' "\n\nHint: Remove the key from your API response, or include it in your OpenAPI docs" ) tester = SchemaTester() @@ -45,8 +45,8 @@ def test_key_in_write_only_properties_error(): 'The following property was found in the response, but is documented as being "writeOnly": "one"' "\n\nReference:" "\n\nPOST /endpoint > response > one" - '\n\nResponse body:\n {\n "one": 1\n}' - '\nSchema section:\n {\n "one": {\n "type": "int",\n "writeOnly": true\n }\n}' + '\n\nResponse body:\n {\n "one": 1\n}' + '\nSchema section:\n {\n "one": {\n "type": "int",\n "writeOnly": true\n }\n}' '\n\nHint: Remove the key from your API response, or remove the "WriteOnly" restriction' ) tester = SchemaTester() @@ -70,9 +70,10 @@ def test_date_serialization(): def test_wrong_date_error(): tester = SchemaTester() expected_error_message = ( - '\n\nExpected: a "date-time" formatted "string" value\n\nReceived: ' - '"not-a-date"\n\nReference: \n\nPOST /endpoint > response > updated_at\n\n Response value:\n ' - "not-a-date\n Schema description:\n {'type': 'string', 'format': 'date-time'}" + '\n\nExpected: a "date-time" formatted "string" value' + '\n\nReceived: "not-a-date"\n\nReference: ' + "\n\nPOST /endpoint > response > updated_at" + "\n\n Response value:\n not-a-date\n Schema description:\n {'type': 'string', 'format': 'date-time'}" ) with pytest.raises(DocumentationError, match=expected_error_message): diff --git a/tests/test_utils.py b/tests/test_utils.py index fefa94a8..602bc7c4 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -52,19 +52,12 @@ def test_serialize_schema_section_data(): } serialized_data = serialize_schema_section_data(data=data) assert serialized_data == ( - "{\n" - ' "type": "object",\n' - ' "required": [\n' - ' "key1",\n' - ' "key2"\n' - " ],\n" - ' "properties": {\n' - ' "key1": {\n' - ' "type": "string"\n' - " },\n" - ' "key2": {\n' - ' "type": "string"\n' - " }\n" - " }\n" - "}" + "{\n " + '"type": "object",' + '\n "required": [\n "key1",\n "key2"\n ],\n ' + '"properties": {\n' + ' "key1": {\n "type": "string"\n },\n' + ' "key2": {\n "type": "string"\n }\n' + " }" + "\n}" )