# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['django_swagger_tester', 'django_swagger_tester.migrations']

package_data = \
{'': ['*']}

install_requires = \
['django>=2.2,<4.0', 'djangorestframework']

setup_kwargs = {
    'name': 'django-swagger-tester',
    'version': '2.1.3',
    'description': 'Django test utility for validating Swagger documentation',
    'long_description': 'Django Swagger Tester\n=====================\n\n.. role:: python(code)\n   :language: python\n\n.. image:: https://img.shields.io/pypi/v/django-swagger-tester.svg\n    :target: https://pypi.org/project/django-swagger-tester/\n\n.. image:: https://img.shields.io/pypi/pyversions/django-swagger-tester.svg\n    :target: https://pypi.org/project/django-swagger-tester/\n\n.. image:: https://img.shields.io/pypi/djversions/django-swagger-tester.svg\n    :target: https://pypi.python.org/pypi/django-swagger-tester\n\n.. image:: https://readthedocs.org/projects/django-swagger-tester/badge/?version=latest\n    :target: https://django-swagger-tester.readthedocs.io/en/latest/?badge=latest\n    :alt: Documentation Status\n\n.. image:: https://codecov.io/gh/snok/django-swagger-tester/branch/master/graph/badge.svg\n    :target: https://codecov.io/gh/snok/django-swagger-tester\n\n|\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n    :target: https://pypi.org/project/django-swagger-tester/\n\n.. image:: http://www.mypy-lang.org/static/mypy_badge.svg\n    :target: http://mypy-lang.org/\n    :alt: Checked with mypy\n\n.. image:: https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white\n    :target: https://github.com/pre-commit/pre-commit\n\n--------------\n\n**Documentation**: `https://django-swagger-tester.readthedocs.io <https://django-swagger-tester.readthedocs.io/en/latest/?badge=latest>`_\n\n**Repository**: `https://github.com/snok/django-swagger-tester <https://github.com/snok/django-swagger-tester>`_\n\n--------------\n\nDjango Swagger Tester\n=====================\n\nDjango Swagger Tester is a simple test utility for validating your Django Swagger documentation.\n\nIts aim is to make it easy for developers to catch and correct documentation errors in their Swagger/OpenAPI docs.\n\nFeatures\n--------\n\nThe package has two primary features:\n\n-  `Testing response documentation`_\n-  `Testing request body documentation`_\n\nSupport for other use cases could be added in the future, and contributions are welcome.\n\nImplementations\n---------------\n\nThis package currently supports:\n\n- Testing of dynamically rendered OpenAPI schemas using `drf-yasg`_\n- Testing of dynamically rendered OpenAPI schemas using `drf-spectacular`_\n- Testing any implementation which generates a static yaml or json file (e.g., like `DRF`_)\n\n\nIf you\'re using another method to generate your documentation and would like to use this package, feel free to add an issue, or create a PR. Adding a new implementation is as easy as adding the required logic needed to load the OpenAPI schema.\n\nInstallation\n============\n\nInstall using pip:\n\n.. code:: python\n\n   pip install django-swagger-tester\n\nConfiguration\n=============\n\nSettings\n--------\n\nTo use Django Swagger Settings in your project, you first need to add a ``django_swagger_tester`` to your installed apps.\n\n.. code:: python\n\n    INSTALLED_APPS = [\n        ...\n        \'django_swagger_tester\',\n    ]\n\nSecondly, you need to configure the ``SWAGGER_TESTER`` package settings in your ``settings.py``:\n\n.. code:: python\n\n    from django_swagger_tester.loaders import DrfSpectacularSchemaLoader\n    from django_swagger_tester.case_testers import is_camel_case\n\n    SWAGGER_TESTER = {\n        \'SCHEMA_LOADER\': DrfSpectacularSchemaLoader,\n        \'CASE_TESTER\': is_camel_case,\n        \'CAMEL_CASE_PARSER\': True,\n        \'CASE_PASSLIST\': [\'IP\', \'DHCP\'],\n        \'MIDDLEWARE\': {\n            \'RESPONSE_VALIDATION\': {\n                \'LOG_LEVEL\': \'ERROR\',\n                \'LOGGER_NAME\': \'middleware_response_validation\',\n                \'DEBUG\': True,\n                \'VALIDATION_EXEMPT_URLS\': [\'^api/v1/exempt-endpoint$\'],\n                \'VALIDATION_EXEMPT_STATUS_CODES\': [401],\n            }\n        },\n        \'VIEWS\': {\n            \'RESPONSE_VALIDATION\': {\n                \'LOG_LEVEL\': \'ERROR\',\n                \'LOGGER_NAME\': \'view_response_validation\',\n                \'DEBUG\': True,\n            }\n        },\n    }\n\nThe only required setting, is the schema loader class.\n\nParameters\n----------\n\nTo learn more about setting parameters, see the `parameter docs`_.\n\n\nResponse Validation\n===================\n\nThe primary function of this package (so far) is response validation. There are three ways you can go about making sure your documentation\nmatches the actual responses you are returning to your users:\n\n1. Add static tests\n2. Add live testing for your project (middleware)\n3. Add live testing for individual views (inherit ResponseValidation in place of an APIView)\n\nStatic testing\n--------------\n\nA pytest implementation might look like this:\n\n.. code:: python\n\n    from django_swagger_tester.testing import validate_response\n\n    def test_200_response_documentation(client):\n        route = \'api/v1/test/1\'\n        response = client.get(route)\n        assert response.status_code == 200\n        assert response.json() == expected_response\n\n        # test swagger documentation\n        validate_response(response=response, method=\'GET\', route=route)\n\nA Django-test implementation might look like this:\n\n.. code-block:: python\n\n    from django_swagger_tester.testing import validate_response\n\n    class MyApiTest(APITestCase):\n\n        path = \'/api/v1/test/\'\n\n        def setUp(self) -> None:\n            user, _ = User.objects.update_or_create(username=\'test_user\')\n            self.client.force_authenticate(user=user)\n\n        def test_get_200(self) -> None:\n            response = self.client.get(self.path, headers={\'Content-Type\': \'application/json\'})\n            expected_response = [...]\n\n            self.assertEqual(response.status_code, 200)\n            self.assertEqual(response.json(), expected_response)\n\n            # test swagger documentation\n            validate_response(response=response, method=\'GET\', route=self.path)\n\nIt is also possible to test more than a single response at the time:\n\n.. code:: python\n\n    def test_post_endpoint_responses(client):\n        # 201 - Resource created\n        response = client.post(...)\n        validate_response(response=response, method=\'POST\', route=\'api/v1/test/\')\n\n        # 400 - Bad data\n        response = client.post(...)\n        validate_response(response=response, method=\'POST\', route=\'api/v1/test/\')\n\n    def test_get_endpoint_responses(client):\n        # 200 - Fetch resource\n        response = client.get(...)\n        validate_response(response=response, method=\'GET\', route=\'api/v1/test/<id>\')\n\n        # 404 - Bad ID\n        response = client.get(...)\n        validate_response(response=response, method=\'GET\', route=\'api/v1/test/<bad id>\')\n\nLive testing with a middleware\n------------------------------\n\nIf you want to implement response validation for all outgoing API responses, simply add the middleware to your settings.py:\n\n.. code:: python\n\n    MIDDLEWARE = [\n        ...\n        \'django_swagger_tester.middleware.ResponseValidationMiddleware\',\n    ]\n\nThe middleware validates all outgoing responses with the ``application/json`` content-type. Any errors/inconsistencies are then logged using a settings-specified log-level.\n\nTo avoid validating the same responses over and over, the results are cached to a database table, making sure we only validate a response once. Two responses from the same endpoint *can* trigger duplicate validation, but only if the response structure has changed, i.e., the type of a response attribute has changed.\n\nLive testing for a single view\n------------------------------\n\nIf you\'re using DRF\'s ``APIView``, you can replace that with ``django_swagger_tester.views.ResponseValidationView``, to add response validation before a response is returned to the user.\n\nIf you\'re not using ``APIView``, but some closely related solution, you can very easily make your own response validation class. Just have a look at the ``ResposeValidationView`` for inspiration.\n\nError messages\n--------------\n\nWhen found, errors will be raised in the following format:\n\n.. code-block:: shell\n\n    django_swagger_tester.exceptions.SwaggerDocumentationError: Item is misspecified:\n\n    Summary\n    -------------------------------------------------------------------------------------------\n\n    Error:      The following properties seem to be missing from your response body: length, width.\n\n    Expected:   {\'name\': \'Saab\', \'color\': \'Yellow\', \'height\': \'Medium height\', \'width\': \'Very wide\', \'length\': \'2 meters\'}\n    Received:   {\'name\': \'Saab\', \'color\': \'Yellow\', \'height\': \'Medium height\'}\n\n    Hint:       Remove the key(s) from you Swagger docs, or include it in your API response.\n    Sequence:   init.list\n\n    -------------------------------------------------------------------------------------------\n\n    * If you need more details: set `verbose=True`\n\n- ``Expected`` describes the response data\n- ``Received`` describes the schema.\n- ``Hint`` will sometimes include a suggestion for what actions to take, to correct an error.\n- ``Sequence`` will indicate how the response tester iterated through the data structure, before finding the error.\n\nIn this example, the response data is missing two attributes, ``height`` and ``width``, documented in the OpenAPI schema indicating that either the response needs to include more data, or that the OpenAPI schema should be corrected. It might be useful to highlight that we can\'t be sure whether the response or the schema is wrong; only that they are inconsistent.\n\nInput Validation\n================\n\nTo make sure your request body documentation is accurate, and will stay accurate, you can use endpoint serializers to validate your schema directly.\n\n``validate_input_serializer`` constructs an example representation of the documented request body, and passes it to the serializer it is given. This means it\'s only useful if you use serializers for validating your incoming request data.\n\nA Django test implementation of input validation for a whole project could be structured like this:\n\n.. code:: python\n\n    from django.test import SimpleTestCase\n    from django_swagger_tester.testing import validate_input_serializer\n\n    from api.serializers.validation.request_bodies import ...\n\n\n    class TestSwaggerInput(SimpleTestCase):\n        endpoints = [\n            {\n                \'api/v1/orders/\': [\n                    (\'POST\', ValidatePostOrderBody),\n                    (\'PUT\', ValidatePutOrderBody),\n                    (\'DELETE\', ValidateDeleteOrderBody)\n                ]\n            },\n            {\n                \'api/v1/orders/<id>/entries/\': [\n                    (\'POST\', ValidatePostEntryBody),\n                    (\'PUT\', ValidatePutEntryBody),\n                    (\'DELETE\', ValidateEntryDeleteBody)\n                ]\n            },\n        ]\n\n        def test_swagger_input(self) -> None:\n            """\n            Verifies that the documented request bodies are valid.\n            """\n            for endpoint in self.endpoints:\n                for route, values in endpoint.items():\n                    for method, serializer in values:\n                        validate_input_serializer(serializer=serializer, method=method, route=route)\n\n.. _`https://django-swagger-tester.readthedocs.io/`: https://django-swagger-tester.readthedocs.io/en/latest/?badge=latest\n.. _Testing response documentation: https://django-swagger-tester.readthedocs.io/en/latest/implementation.html#response-validation\n.. _Testing request body documentation: https://django-swagger-tester.readthedocs.io/en/latest/implementation.html#input-validation\n.. _ensuring your docs comply with a single parameter naming standard (case type): https://django-swagger-tester.readthedocs.io/en/latest/implementation.html#case-checking\n.. _drf_yasg: https://github.com/axnsan12/drf-yasg\n.. _documentation: https://django-swagger-tester.readthedocs.io/\n.. _docs: https://django-swagger-tester.readthedocs.io/\n.. _drf: https://www.django-rest-framework.org/topics/documenting-your-api/#generating-documentation-from-openapi-schemas\n.. _drf-yasg: https://github.com/axnsan12/drf-yasg\n.. _drf-spectacular: https://github.com/tfranzel/drf-spectacular\n.. _parameter docs: https://django-swagger-tester.readthedocs.io/en/latest/configuration.html#parameters\n',
    'author': 'Sondre Lillebø Gundersen',
    'author_email': 'sondrelg@live.no',
    'maintainer': None,
    'maintainer_email': None,
    'url': 'https://github.com/snok/django-swagger-tester',
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'python_requires': '>=3.6,<4.0',
}


setup(**setup_kwargs)
