Source code for rest_framework_tricks.tests.test_nested_proxy_field

"""
Test NestedProxyField.
"""
from decimal import Decimal
from typing import Callable

from django.urls import reverse
import pytest
from rest_framework import status

import factories

from .base import BaseRestFrameworkTestCase

__author__ = "Artur Barseghyan <artur.barseghyan@gmail.com>"
__copyright__ = "2017-2022 Artur Barseghyan"
__license__ = "GPL-2.0-only OR LGPL-2.1-or-later"
__all__ = (
    "TestNestedProxyFieldCreateAction",
    "TestNestedProxyFieldUpdateAction",
)


@pytest.mark.django_db
class TestNestedProxyFieldActionBase(BaseRestFrameworkTestCase):
    """Test NestedProxyField - update action."""

    pytestmark = pytest.mark.django_db

    def get_status_code(self) -> int:
        """Get status code.

        :return: Status code expected as result of the action.
        :rtype: str
        """
        raise NotImplementedError

    def get_client_action(self) -> Callable:
        """Get client action.

        :return: Client action.
        :rtype: callable
        """
        raise NotImplementedError

    def _nested_proxy_field_hyperlinked_model_serializer(self, url=None):
        """Test NestedProxyField and HyperlinkedModelSerializer."""
        data = {
            "title": self.faker.sentence(nb_words=3, variable_nb_words=True),
            "description": self.faker.text(),
            "summary": self.faker.text(),
            "publishing_information": {
                "publication_date": self.faker.date(),
                "isbn": self.faker.isbn10(),
                "pages": self.faker.pyint(),
            },
            "stock_information": {
                "stock_count": self.faker.pyint(),
                "price": self.faker.pyint(),
                "state": "published",
            },
        }

        response = self.get_client_action()(url, data, format="json")

        self.assertEqual(response.status_code, self.get_status_code())
        for __key in ("title", "summary", "description"):
            self.assertEqual(response.data.get(__key), data.get(__key))

        for __key in ("publication_date", "isbn", "pages"):
            self.assertEqual(
                response.data["publishing_information"].get(__key),
                data["publishing_information"].get(__key),
            )

        for __key in ("stock_count", "state"):
            self.assertEqual(
                response.data["stock_information"].get(__key),
                data["stock_information"].get(__key),
            )
        self.assertEqual(
            Decimal(response.data["stock_information"].get("price")),
            Decimal(data["stock_information"].get("price")),
        )

    def _nested_proxy_field_model_serializer(self, url=None):
        """Test NestedProxyField and ModelSerializer."""
        data = {
            "name": self.faker.text(max_nb_chars=30),
            "info": self.faker.text(),
            "website": self.faker.url(),
            "address_information": {
                "address": self.faker.address(),
                "city": self.faker.city(),
                "state_province": self.faker.state(),
                "country": self.faker.country(),
            },
        }

        response = self.get_client_action()(url, data, format="json")

        self.assertEqual(response.status_code, self.get_status_code())
        for __key in ("name", "info", "website"):
            self.assertEqual(response.data.get(__key), data.get(__key))

        for __key in ("address", "city", "state_province", "country"):
            self.assertEqual(
                response.data["address_information"].get(__key),
                data["address_information"].get(__key),
            )

    def _nested_proxy_field_model_serializer_missing_all_nested_fields(
        self, url=None
    ):
        """Test NestedProxyField and ModelSerializer.

        All nested fields are missing.

        Note, that the `address_information` which contains the `address`,
        `city`, `state_province` and `country` fields is completely missing
        in the payload.
        """
        data = {
            "name": self.faker.text(max_nb_chars=30),
            "info": self.faker.text(),
            "website": self.faker.url(),
            # 'address_information': {
            #     'address': self.faker.address(),
            #     'city': self.faker.city(),
            #     'state_province': self.faker.state(),
            #     'country': self.faker.country()
            # }
        }

        response = self.get_client_action()(url, data, format="json")

        self.assertEqual(response.status_code, self.get_status_code())
        for __key in ("name", "info", "website"):
            self.assertEqual(response.data.get(__key), data.get(__key))

    def _nested_proxy_field_model_serializer_depth(self, url=None):
        """Test NestedProxyField and ModelSerializer with more depth."""
        data = {
            "salutation": self.faker.text(max_nb_chars=10),
            "name": self.faker.name(),
            "birth_date": self.faker.date(),
            "biography": self.faker.text(),
            "contact_information": {
                "personal_contact_information": {
                    "email": self.faker.email(),
                    "phone_number": self.faker.phone_number(),
                    "website": self.faker.url(),
                },
                "business_contact_information": {
                    "company": self.faker.company(),
                    "company_email": self.faker.email(),
                    "company_phone_number": self.faker.phone_number(),
                    "company_website": self.faker.url(),
                },
            },
        }

        response = self.get_client_action()(url, data, format="json")

        self.assertEqual(response.status_code, self.get_status_code())
        for __key in ("salutation", "name", "biography"):
            self.assertEqual(response.data.get(__key), data.get(__key))

        for __key in ("email", "phone_number", "website"):
            self.assertEqual(
                response.data["contact_information"][
                    "personal_contact_information"
                ].get(__key),
                data["contact_information"][
                    "personal_contact_information"
                ].get(__key),
            )

        for __key in (
            "company",
            "company_email",
            "company_phone_number",
            "company_website",
        ):
            self.assertEqual(
                response.data["contact_information"][
                    "business_contact_information"
                ].get(__key),
                data["contact_information"][
                    "business_contact_information"
                ].get(__key),
            )

    def _nested_proxy_field_model_serializer_more_depth(self, url=None):
        """Test NestedProxyField and ModelSerializer with more depth."""
        data = {
            "information": {
                "data": {
                    "personal_information": {
                        "salutation": self.faker.text(max_nb_chars=10),
                        "first_name": self.faker.first_name(),
                        "last_name": self.faker.last_name(),
                        "birth_date": self.faker.date(),
                        "biography": self.faker.text(),
                    },
                    "contact_information": {
                        "personal_contact_information": {
                            "email": self.faker.email(),
                            "phone_number": self.faker.phone_number(),
                            "website": self.faker.url(),
                        },
                        "business_contact_information": {
                            "company": self.faker.company(),
                            "company_email": self.faker.email(),
                            "company_phone_number": self.faker.phone_number(),
                            "company_website": self.faker.url(),
                        },
                    },
                    "bank_information": {
                        "bank_name": self.faker.company(),
                        "bank_account_name": self.faker.name(),
                        "bank_account_number": self.faker.pystr(),
                    },
                }
            }
        }

        response = self.get_client_action()(url, data, format="json")

        self.assertEqual(response.status_code, self.get_status_code())

        for __key in ("salutation", "first_name", "last_name", "biography"):
            self.assertEqual(
                response.data["information"]["data"][
                    "personal_information"
                ].get(__key),
                data["information"]["data"]["personal_information"].get(__key),
            )

        for __key in ("email", "phone_number", "website"):
            self.assertEqual(
                response.data["information"]["data"]["contact_information"][
                    "personal_contact_information"
                ].get(__key),
                data["information"]["data"]["contact_information"][
                    "personal_contact_information"
                ].get(__key),
            )

        for __key in (
            "company",
            "company_email",
            "company_phone_number",
            "company_website",
        ):
            self.assertEqual(
                response.data["information"]["data"]["contact_information"][
                    "business_contact_information"
                ].get(__key),
                data["information"]["data"]["contact_information"][
                    "business_contact_information"
                ].get(__key),
            )

        for __key in ("bank_name", "bank_account_name", "bank_account_number"):
            self.assertEqual(
                response.data["information"]["data"]["bank_information"].get(
                    __key
                ),
                data["information"]["data"]["bank_information"].get(__key),
            )

    def _nested_proxy_field_model_serializer_missing_fields(self, url=None):
        """Test NestedProxyField and ModelSerializer with missing fields.

        Several non-required fields are missing (in this case, it's the
        ``info`` field).
        """
        data = {
            "name": self.faker.text(max_nb_chars=30),
            "website": self.faker.url(),
            "address_information": {
                "address": self.faker.address(),
                "city": self.faker.city(),
                "state_province": self.faker.state(),
                "country": self.faker.country(),
            },
        }

        response = self.get_client_action()(url, data, format="json")

        self.assertEqual(response.status_code, self.get_status_code())
        for __key in ("name", "website"):
            self.assertEqual(response.data.get(__key), data.get(__key))

        for __key in ("address", "city", "state_province", "country"):
            self.assertEqual(
                response.data["address_information"].get(__key),
                data["address_information"].get(__key),
            )

    def _nested_proxy_field_model_serializer_depth_missing_fields(
        self, url=None
    ):
        """Test NestedProxyField and ModelSerializer with more depth.

        Several non-required fields are missing (in this case they are
        ``birth_date``, ``biography``, ``website`` and ``company_website``).
        """
        data = {
            "information": {
                "data": {
                    "personal_information": {
                        "salutation": self.faker.text(max_nb_chars=10),
                        "first_name": self.faker.first_name(),
                        "last_name": self.faker.last_name(),
                    },
                    "contact_information": {
                        "personal_contact_information": {
                            "email": self.faker.email(),
                            "phone_number": self.faker.phone_number(),
                        },
                        "business_contact_information": {
                            "company": self.faker.company(),
                            "company_email": self.faker.email(),
                            "company_phone_number": self.faker.phone_number(),
                        },
                    },
                    "bank_information": {
                        "bank_name": self.faker.company(),
                        "bank_account_name": self.faker.name(),
                        "bank_account_number": self.faker.pystr(),
                    },
                }
            }
        }

        response = self.get_client_action()(url, data, format="json")

        self.assertEqual(response.status_code, self.get_status_code())

        for __key in ("salutation", "first_name", "last_name"):
            self.assertEqual(
                response.data["information"]["data"][
                    "personal_information"
                ].get(__key),
                data["information"]["data"]["personal_information"].get(__key),
            )

        for __key in ("email", "phone_number"):
            self.assertEqual(
                response.data["information"]["data"]["contact_information"][
                    "personal_contact_information"
                ].get(__key),
                data["information"]["data"]["contact_information"][
                    "personal_contact_information"
                ].get(__key),
            )

        for __key in ("company", "company_email", "company_phone_number"):
            self.assertEqual(
                response.data["information"]["data"]["contact_information"][
                    "business_contact_information"
                ].get(__key),
                data["information"]["data"]["contact_information"][
                    "business_contact_information"
                ].get(__key),
            )

        for __key in ("bank_name", "bank_account_name", "bank_account_number"):
            self.assertEqual(
                response.data["information"]["data"]["bank_information"].get(
                    __key
                ),
                data["information"]["data"]["bank_information"].get(__key),
            )

    def _nested_proxy_field_model_serializer_depth_more_missing_fields(
        self, url=None
    ):
        """Test NestedProxyField and ModelSerializer with more depth.

        All non-required fields are missing (in this case they are
        ``birth_date``, ``biography``, ``website`` and ``company_website``).
        """
        data = {
            "information": {
                "data": {
                    "personal_information": {
                        "salutation": self.faker.text(max_nb_chars=10),
                        "first_name": self.faker.first_name(),
                        "last_name": self.faker.last_name(),
                    },
                    "contact_information": {
                        "personal_contact_information": {
                            "email": self.faker.email(),
                        },
                    },
                }
            }
        }

        response = self.get_client_action()(url, data, format="json")

        self.assertEqual(response.status_code, self.get_status_code())

        for __key in ("salutation", "first_name", "last_name"):
            self.assertEqual(
                response.data["information"]["data"][
                    "personal_information"
                ].get(__key),
                data["information"]["data"]["personal_information"].get(__key),
            )

        for __key in ("email",):
            self.assertEqual(
                response.data["information"]["data"]["contact_information"][
                    "personal_contact_information"
                ].get(__key),
                data["information"]["data"]["contact_information"][
                    "personal_contact_information"
                ].get(__key),
            )


[docs]class TestNestedProxyFieldCreateAction(TestNestedProxyFieldActionBase): """Test NestedProxyField - create action."""
[docs] def get_status_code(self) -> int: """Get status code. :return: Status code expected as result of the action. :rtype: str """ return status.HTTP_201_CREATED
[docs] def get_client_action(self) -> Callable: """Get client action. :return: Client action. :rtype: callable """ return self.client.post
[docs] @classmethod def setUpClass(cls): """Set up.""" super(TestNestedProxyFieldCreateAction, cls).setUpClass() cls.book_listing_url = reverse("book-list", kwargs={}) cls.publisher_listing_url = reverse("publisher-list", kwargs={}) cls.author_listing_url = reverse("author-list", kwargs={}) cls.profile_listing_url = reverse("profile-list", kwargs={}) cls.proxy_author_listing_url = reverse("authorproxy-list", kwargs={})
[docs] def test_nested_proxy_field_hyperlinked_model_serializer(self): """Test NestedProxyField and HyperlinkedModelSerializer.""" self._nested_proxy_field_hyperlinked_model_serializer( self.book_listing_url )
[docs] def test_nested_proxy_field_model_serializer_depth(self): """Test NestedProxyField and ModelSerializer with more depth.""" self._nested_proxy_field_model_serializer_depth( self.author_listing_url )
[docs] def test_another_nested_proxy_field_model_serializer_depth(self): """Test NestedProxyField and ModelSerializer with more depth.""" self._nested_proxy_field_model_serializer_depth( self.proxy_author_listing_url )
[docs] def test_another_nested_proxy_field_model_serializer_more_depth(self): """Test NestedProxyField and ModelSerializer with more depth.""" self._nested_proxy_field_model_serializer_more_depth( self.profile_listing_url )
[docs] def test_nested_proxy_field_model_serializer_missing_fields(self): """Test NestedProxyField and ModelSerializer with missing fields.""" self._nested_proxy_field_model_serializer_missing_fields( self.publisher_listing_url )
[docs] def test_nested_proxy_field_model_serializer_depth_missing_fields(self): """Test NestedProxyField and ModelSerializer with more depth. Several non-required fields are missing. """ self._nested_proxy_field_model_serializer_depth_missing_fields( self.profile_listing_url )
[docs] def test_nested_proxy_field_model_serializer_depth_more_missing_fields( self, ): """Test NestedProxyField and ModelSerializer with more depth. All of the non-required fields are missing. """ self._nested_proxy_field_model_serializer_depth_more_missing_fields( self.profile_listing_url )
[docs] def test_nested_proxy_field_model_serializer(self): """Test NestedProxyField and ModelSerializer.""" self._nested_proxy_field_model_serializer(self.publisher_listing_url)
[docs] def test_nested_proxy_field_model_serializer_missing_all_nested_fields( self, ): """Test NestedProxyField and ModelSerializer.""" self._nested_proxy_field_model_serializer_missing_all_nested_fields( self.publisher_listing_url )
[docs]@pytest.mark.django_db class TestNestedProxyFieldUpdateAction(TestNestedProxyFieldActionBase): """Test NestedProxyField - update action.""" pytestmark = pytest.mark.django_db
[docs] def get_status_code(self) -> int: """Get status code. :return: Status code expected as result of the action. :rtype: str """ return status.HTTP_200_OK
[docs] def get_client_action(self) -> Callable: """Get client action. :return: Client action. :rtype: callable """ return self.client.put
[docs] @classmethod def setUpClass(cls): """Set up.""" super(TestNestedProxyFieldUpdateAction, cls).setUpClass() cls.books = factories.BookFactory.create_batch(10) cls.profiles = factories.ProfileFactory.create_batch(10) cls.book_detail_url = reverse( "book-detail", kwargs={"pk": cls.books[0].pk} ) cls.publisher_detail_url = reverse( "publisher-detail", kwargs={"pk": cls.books[0].publisher.pk} ) cls.author_detail_url = reverse( "author-detail", kwargs={"pk": cls.books[0].authors.first().pk} ) cls.profile_detail_url = reverse( "profile-detail", kwargs={"pk": cls.profiles[0].pk} ) cls.proxy_author_detail_url = reverse( "authorproxy-detail", kwargs={"pk": cls.books[0].authors.first().pk}, )
[docs] def test_nested_proxy_field_hyperlinked_model_serializer(self): """Test NestedProxyField and HyperlinkedModelSerializer.""" self._nested_proxy_field_hyperlinked_model_serializer( self.book_detail_url )
[docs] def test_nested_proxy_field_model_serializer(self): """Test NestedProxyField and ModelSerializer.""" self._nested_proxy_field_model_serializer(self.publisher_detail_url)
[docs] def test_nested_proxy_field_model_serializer_missing_all_nested_fields( self, ): """Test NestedProxyField and ModelSerializer.""" self._nested_proxy_field_model_serializer_missing_all_nested_fields( self.publisher_detail_url )
[docs] def test_nested_proxy_field_model_serializer_depth(self): """Test NestedProxyField and ModelSerializer with more depth.""" self._nested_proxy_field_model_serializer_depth(self.author_detail_url)
[docs] def test_another_nested_proxy_field_model_serializer_depth(self): """Test NestedProxyField and ModelSerializer with more depth.""" self._nested_proxy_field_model_serializer_depth( self.proxy_author_detail_url )
[docs] def test_another_nested_proxy_field_model_serializer_more_depth(self): """Test NestedProxyField and ModelSerializer with more depth.""" self._nested_proxy_field_model_serializer_more_depth( self.profile_detail_url )
[docs] def test_nested_proxy_field_model_serializer_missing_fields(self): """Test NestedProxyField and ModelSerializer with missing fields.""" self._nested_proxy_field_model_serializer_missing_fields( self.publisher_detail_url )
[docs] def test_nested_proxy_field_model_serializer_depth_missing_fields(self): """Test NestedProxyField and ModelSerializer with more depth. Several non-required fields are missing. """ self._nested_proxy_field_model_serializer_depth_missing_fields( self.profile_detail_url )
[docs] def test_nested_proxy_field_model_serializer_depth_more_missing_fields( self, ): """Test NestedProxyField and ModelSerializer with more depth. All of the non-required fields are missing. """ self._nested_proxy_field_model_serializer_depth_more_missing_fields( self.profile_detail_url )