"""This module contains the test cases for the ``views_utils`` module"""

from django.http import Http404, HttpResponse
from django.views.generic.base import View
from django.test import Client, RequestFactory, TestCase
from django.test.utils import modify_settings, override_settings

from ..views_utils import CrsfExemptMixin, RequireMasterMixin, RequireSlaveMixin

@modify_settings(MIDDLEWARE_CLASSES={
    'remove': 'mtp.apps.accounts.middleware.PasswordExpiryMiddleware',
})
@override_settings(ROOT_URLCONF='mtp.apps.common.tests.fake_urls')
class CsrfExemptMixinTestCase(TestCase):
    """Test case for the ``CsrfExemptMixin`` view mixin"""

    @classmethod
    def setUpTestData(cls):
        """Setup a test client with the ``enforce_csrf_checks`` flag"""

        super().setUpTestData()

        cls.csrf_client = Client(enforce_csrf_checks=True)

    class SimpleView(View):
        """Simple view for the test needs"""

        def post(self, request, *args, **kwargs):  # pylint:disable=unused-argument
            """Simply return a string for the test needs"""

            return HttpResponse('test')

    class ViewWithCsrfDecorator(CrsfExemptMixin, SimpleView):
        """Simple view with the crsf exempt decorator"""

        pass

    def test_simple_view_without_decorator(self):
        """Test that the view without the decorator should output an ``HttpResponseNotAllowed``"""

        response = self.csrf_client.post('/url-with-csrf-protection/')

        self.assertEqual(
            response.status_code,
            403
        )

    def test_view_with_decorator(self):
        """Test that the view with the decorator should output the correct response"""

        response = self.csrf_client.post('/url-without-csrf-protection/')

        self.assertEqual(
            response.status_code,
            200
        )


class RequireMasterMixinTestCase(TestCase):
    """Test case for the ``RequireMasterMixin`` view mixin"""

    class SimpleView(RequireMasterMixin, View):
        """Simple view for the tests"""

        def get(self, request, *arg, **kwargs):  # pylint:disable=unused-argument
            """Simply returns a string for the test needs"""

            return 'test'

    def call_view(self):
        """Call the ``SimpleView``"""

        view = self.SimpleView.as_view()

        return view(RequestFactory().get('/fake/path/not/used'), [], {})

    @override_settings(INSTANCE_IS_MASTER=True)
    def test_call_view_with_master_true(self):
        """Call the view with a ``INSTANCE_IS_MASTER`` to ``True"""

        self.assertEqual(
            self.call_view(),
            'test'
        )

    @override_settings(INSTANCE_IS_MASTER=False)
    def test_call_view_with_master_false(self):
        """Call the view with a ``INSTANCE_IS_MASTER`` to ``False"""

        with self.assertRaises(Http404):
            self.call_view()


class RequireSlaveMixinTestCase(TestCase):
    """Test case for the ``RequireSlaveMixin`` view mixin"""

    class SimpleView(RequireSlaveMixin, View):
        """Simple view for the tests"""

        def get(self, request, *arg, **kwargs):  # pylint:disable=unused-argument
            """Simply returns a string for the test needs"""

            return 'test'

    def call_view(self):
        """Call the ``SimpleView``"""

        view = self.SimpleView.as_view()

        return view(RequestFactory().get('/fake/path/not/used'), [], {})

    @override_settings(INSTANCE_IS_SLAVE=True)
    def test_call_view_with_slave_true(self):
        """Call the view with a ``INSTANCE_IS_SLAVE`` to ``True"""

        self.assertEqual(
            self.call_view(),
            'test'
        )

    @override_settings(INSTANCE_IS_SLAVE=False)
    def test_call_view_with_slave_false(self):
        """Call the view with a ``INSTANCE_IS_SLAVE`` to ``False"""

        with self.assertRaises(Http404):
            self.call_view()
