Reorganize reusable test code
Extract test views and user code into their own separate test case mixins. Append TestCase to test case mixins with base test code to differentiate them from test mixins with reusable view calls. Signed-off-by: Roberto Rosario <Roberto.Rosario@mayan-edms.com>
This commit is contained in:
@@ -1,47 +1,27 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.contrib.auth import get_user_model
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.contrib.auth.models import Group
|
|
||||||
|
|
||||||
from mayan.apps.permissions.models import Role
|
from mayan.apps.permissions.tests.mixins import RoleTestCaseMixin
|
||||||
from mayan.apps.permissions.tests.literals import TEST_ROLE_LABEL
|
from mayan.apps.user_management.tests.mixins import UserTestCaseMixin
|
||||||
from mayan.apps.user_management.tests import (
|
|
||||||
TEST_ADMIN_EMAIL, TEST_ADMIN_PASSWORD, TEST_ADMIN_USERNAME,
|
|
||||||
TEST_GROUP_NAME, TEST_USER_EMAIL, TEST_USER_PASSWORD, TEST_USER_USERNAME
|
|
||||||
)
|
|
||||||
|
|
||||||
from ..models import AccessControlList
|
from ..models import AccessControlList
|
||||||
|
|
||||||
|
|
||||||
class ACLBaseTestMixin(object):
|
class ACLTestCaseMixin(RoleTestCaseMixin, UserTestCaseMixin):
|
||||||
auto_create_group = True
|
|
||||||
auto_create_users = True
|
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(ACLBaseTestMixin, self).setUp()
|
super(ACLTestCaseMixin, self).setUp()
|
||||||
if self.auto_create_users:
|
if hasattr(self, '_test_case_user'):
|
||||||
self.admin_user = get_user_model().objects.create_superuser(
|
self._test_case_role.groups.add(self._test_case_group)
|
||||||
username=TEST_ADMIN_USERNAME, email=TEST_ADMIN_EMAIL,
|
|
||||||
password=TEST_ADMIN_PASSWORD
|
|
||||||
)
|
|
||||||
|
|
||||||
self.user = get_user_model().objects.create_user(
|
|
||||||
username=TEST_USER_USERNAME, email=TEST_USER_EMAIL,
|
|
||||||
password=TEST_USER_PASSWORD
|
|
||||||
)
|
|
||||||
|
|
||||||
if self.auto_create_group:
|
|
||||||
self.group = Group.objects.create(name=TEST_GROUP_NAME)
|
|
||||||
self.role = Role.objects.create(label=TEST_ROLE_LABEL)
|
|
||||||
self.group.user_set.add(self.user)
|
|
||||||
self.role.groups.add(self.group)
|
|
||||||
|
|
||||||
def grant_access(self, obj, permission):
|
def grant_access(self, obj, permission):
|
||||||
return AccessControlList.objects.grant(
|
if not hasattr(self, '_test_case_role'):
|
||||||
obj=obj, permission=permission, role=self.role
|
raise ImproperlyConfigured(
|
||||||
)
|
'Enable the creation of the test case user, group, and role '
|
||||||
|
'in order to enable the usage of ACLs in tests.'
|
||||||
|
)
|
||||||
|
|
||||||
def grant_permission(self, permission):
|
return AccessControlList.objects.grant(
|
||||||
self.role.permissions.add(
|
obj=obj, permission=permission, role=self._test_case_role
|
||||||
permission.stored_permission
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,30 +1,21 @@
|
|||||||
from __future__ import absolute_import, unicode_literals
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
from django.conf.urls import url
|
|
||||||
from django.contrib.auth import get_user_model
|
|
||||||
from django.http import HttpResponse
|
|
||||||
from django.template import Context, Template
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.test.utils import ContextList
|
from django.urls import reverse
|
||||||
from django.urls import clear_url_caches, reverse
|
|
||||||
from django_downloadview import assert_download_response
|
from django_downloadview import assert_download_response
|
||||||
|
|
||||||
from mayan.apps.acls.tests.mixins import ACLBaseTestMixin
|
from mayan.apps.acls.tests.mixins import ACLTestCaseMixin
|
||||||
from mayan.apps.permissions.classes import Permission
|
from mayan.apps.permissions.classes import Permission
|
||||||
from mayan.apps.smart_settings.classes import Namespace
|
from mayan.apps.smart_settings.classes import Namespace
|
||||||
from mayan.apps.user_management.tests import (
|
|
||||||
TEST_ADMIN_PASSWORD, TEST_ADMIN_USERNAME, TEST_USER_PASSWORD,
|
|
||||||
TEST_USER_USERNAME
|
|
||||||
)
|
|
||||||
|
|
||||||
from .literals import TEST_VIEW_NAME, TEST_VIEW_URL
|
|
||||||
from .mixins import (
|
from .mixins import (
|
||||||
ContentTypeCheckMixin, DatabaseConversionMixin, OpenFileCheckMixin,
|
ClientMethodsTestCaseMixin, ContentTypeCheckMixin, DatabaseConversionMixin,
|
||||||
TempfileCheckMixin
|
OpenFileCheckTestCaseMixin, TempfileCheckTestCaseMixin,
|
||||||
|
TestViewTestCaseMixin
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class BaseTestCase(DatabaseConversionMixin, ACLBaseTestMixin, ContentTypeCheckMixin, OpenFileCheckMixin, TempfileCheckMixin, TestCase):
|
class BaseTestCase(DatabaseConversionMixin, ACLTestCaseMixin, ContentTypeCheckMixin, OpenFileCheckTestCaseMixin, TempfileCheckTestCaseMixin, TestCase):
|
||||||
"""
|
"""
|
||||||
This is the most basic test case class any test in the project should use.
|
This is the most basic test case class any test in the project should use.
|
||||||
"""
|
"""
|
||||||
@@ -36,76 +27,9 @@ class BaseTestCase(DatabaseConversionMixin, ACLBaseTestMixin, ContentTypeCheckMi
|
|||||||
Permission.invalidate_cache()
|
Permission.invalidate_cache()
|
||||||
|
|
||||||
|
|
||||||
class GenericViewTestCase(BaseTestCase):
|
class GenericViewTestCase(ClientMethodsTestCaseMixin, TestViewTestCaseMixin, BaseTestCase):
|
||||||
has_test_view = False
|
"""
|
||||||
|
A generic view test case built on top of the base test case providing
|
||||||
def tearDown(self):
|
single user test view to test object resolution and shorthand HTTP
|
||||||
from mayan.urls import urlpatterns
|
method functions.
|
||||||
|
"""
|
||||||
self.client.logout()
|
|
||||||
if self.has_test_view:
|
|
||||||
urlpatterns.pop(0)
|
|
||||||
super(GenericViewTestCase, self).tearDown()
|
|
||||||
|
|
||||||
def add_test_view(self, test_object):
|
|
||||||
from mayan.urls import urlpatterns
|
|
||||||
|
|
||||||
def test_view(request):
|
|
||||||
template = Template('{{ object }}')
|
|
||||||
context = Context(
|
|
||||||
{'object': test_object, 'resolved_object': test_object}
|
|
||||||
)
|
|
||||||
return HttpResponse(template.render(context=context))
|
|
||||||
|
|
||||||
urlpatterns.insert(0, url(TEST_VIEW_URL, test_view, name=TEST_VIEW_NAME))
|
|
||||||
clear_url_caches()
|
|
||||||
self.has_test_view = True
|
|
||||||
|
|
||||||
def get_test_view(self):
|
|
||||||
response = self.get(TEST_VIEW_NAME)
|
|
||||||
if isinstance(response.context, ContextList):
|
|
||||||
# template widget rendering causes test client response to be
|
|
||||||
# ContextList rather than RequestContext. Typecast to dictionary
|
|
||||||
# before updating.
|
|
||||||
result = dict(response.context).copy()
|
|
||||||
result.update({'request': response.wsgi_request})
|
|
||||||
return Context(result)
|
|
||||||
else:
|
|
||||||
response.context.update({'request': response.wsgi_request})
|
|
||||||
return Context(response.context)
|
|
||||||
|
|
||||||
def get(self, viewname=None, path=None, *args, **kwargs):
|
|
||||||
data = kwargs.pop('data', {})
|
|
||||||
follow = kwargs.pop('follow', False)
|
|
||||||
|
|
||||||
if viewname:
|
|
||||||
path = reverse(viewname=viewname, *args, **kwargs)
|
|
||||||
|
|
||||||
return self.client.get(
|
|
||||||
path=path, data=data, follow=follow
|
|
||||||
)
|
|
||||||
|
|
||||||
def login(self, *args, **kwargs):
|
|
||||||
logged_in = self.client.login(*args, **kwargs)
|
|
||||||
|
|
||||||
return logged_in
|
|
||||||
|
|
||||||
def login_user(self):
|
|
||||||
self.login(username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD)
|
|
||||||
|
|
||||||
def login_admin_user(self):
|
|
||||||
self.login(username=TEST_ADMIN_USERNAME, password=TEST_ADMIN_PASSWORD)
|
|
||||||
|
|
||||||
def logout(self):
|
|
||||||
self.client.logout()
|
|
||||||
|
|
||||||
def post(self, viewname=None, path=None, *args, **kwargs):
|
|
||||||
data = kwargs.pop('data', {})
|
|
||||||
follow = kwargs.pop('follow', False)
|
|
||||||
|
|
||||||
if viewname:
|
|
||||||
path = reverse(viewname=viewname, *args, **kwargs)
|
|
||||||
|
|
||||||
return self.client.post(
|
|
||||||
path=path, data=data, follow=follow
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -4,18 +4,16 @@ import glob
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth import get_user_model
|
from django.conf.urls import url
|
||||||
from django.contrib.auth.models import Group
|
|
||||||
from django.core import management
|
from django.core import management
|
||||||
|
from django.http import HttpResponse
|
||||||
from mayan.apps.user_management.tests import (
|
from django.template import Context, Template
|
||||||
TEST_ADMIN_EMAIL, TEST_ADMIN_PASSWORD, TEST_ADMIN_USERNAME,
|
from django.test.utils import ContextList
|
||||||
TEST_GROUP_NAME, TEST_USER_EMAIL, TEST_USER_PASSWORD,
|
from django.urls import clear_url_caches, reverse
|
||||||
TEST_USER_USERNAME
|
|
||||||
)
|
|
||||||
|
|
||||||
from ..settings import setting_temporary_directory
|
from ..settings import setting_temporary_directory
|
||||||
|
|
||||||
|
from .literals import TEST_VIEW_NAME, TEST_VIEW_URL
|
||||||
from .utils import mute_stdout
|
from .utils import mute_stdout
|
||||||
|
|
||||||
|
|
||||||
@@ -23,6 +21,63 @@ if getattr(settings, 'COMMON_TEST_FILE_HANDLES', False):
|
|||||||
import psutil
|
import psutil
|
||||||
|
|
||||||
|
|
||||||
|
class ClientMethodsTestCaseMixin(object):
|
||||||
|
def delete(self, viewname=None, path=None, *args, **kwargs):
|
||||||
|
data = kwargs.pop('data', {})
|
||||||
|
follow = kwargs.pop('follow', False)
|
||||||
|
|
||||||
|
if viewname:
|
||||||
|
path = reverse(viewname=viewname, *args, **kwargs)
|
||||||
|
|
||||||
|
return self.client.delete(
|
||||||
|
path=path, data=data, follow=follow
|
||||||
|
)
|
||||||
|
|
||||||
|
def get(self, viewname=None, path=None, *args, **kwargs):
|
||||||
|
data = kwargs.pop('data', {})
|
||||||
|
follow = kwargs.pop('follow', False)
|
||||||
|
|
||||||
|
if viewname:
|
||||||
|
path = reverse(viewname=viewname, *args, **kwargs)
|
||||||
|
|
||||||
|
return self.client.get(
|
||||||
|
path=path, data=data, follow=follow
|
||||||
|
)
|
||||||
|
|
||||||
|
def patch(self, viewname=None, path=None, *args, **kwargs):
|
||||||
|
data = kwargs.pop('data', {})
|
||||||
|
follow = kwargs.pop('follow', False)
|
||||||
|
|
||||||
|
if viewname:
|
||||||
|
path = reverse(viewname=viewname, *args, **kwargs)
|
||||||
|
|
||||||
|
return self.client.patch(
|
||||||
|
path=path, data=data, follow=follow
|
||||||
|
)
|
||||||
|
|
||||||
|
def post(self, viewname=None, path=None, *args, **kwargs):
|
||||||
|
data = kwargs.pop('data', {})
|
||||||
|
follow = kwargs.pop('follow', False)
|
||||||
|
|
||||||
|
if viewname:
|
||||||
|
path = reverse(viewname=viewname, *args, **kwargs)
|
||||||
|
|
||||||
|
return self.client.post(
|
||||||
|
path=path, data=data, follow=follow
|
||||||
|
)
|
||||||
|
|
||||||
|
def put(self, viewname=None, path=None, *args, **kwargs):
|
||||||
|
data = kwargs.pop('data', {})
|
||||||
|
follow = kwargs.pop('follow', False)
|
||||||
|
|
||||||
|
if viewname:
|
||||||
|
path = reverse(viewname=viewname, *args, **kwargs)
|
||||||
|
|
||||||
|
return self.client.put(
|
||||||
|
path=path, data=data, follow=follow
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ContentTypeCheckMixin(object):
|
class ContentTypeCheckMixin(object):
|
||||||
expected_content_type = 'text/html; charset=utf-8'
|
expected_content_type = 'text/html; charset=utf-8'
|
||||||
|
|
||||||
@@ -55,7 +110,7 @@ class DatabaseConversionMixin(object):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class OpenFileCheckMixin(object):
|
class OpenFileCheckTestCaseMixin(object):
|
||||||
def _get_descriptor_count(self):
|
def _get_descriptor_count(self):
|
||||||
process = psutil.Process()
|
process = psutil.Process()
|
||||||
return process.num_fds()
|
return process.num_fds()
|
||||||
@@ -65,7 +120,7 @@ class OpenFileCheckMixin(object):
|
|||||||
return process.open_files()
|
return process.open_files()
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(OpenFileCheckMixin, self).setUp()
|
super(OpenFileCheckTestCaseMixin, self).setUp()
|
||||||
if getattr(settings, 'COMMON_TEST_FILE_HANDLES', False):
|
if getattr(settings, 'COMMON_TEST_FILE_HANDLES', False):
|
||||||
self._open_files = self._get_open_files()
|
self._open_files = self._get_open_files()
|
||||||
|
|
||||||
@@ -80,10 +135,10 @@ class OpenFileCheckMixin(object):
|
|||||||
|
|
||||||
self._skip_file_descriptor_test = False
|
self._skip_file_descriptor_test = False
|
||||||
|
|
||||||
super(OpenFileCheckMixin, self).tearDown()
|
super(OpenFileCheckTestCaseMixin, self).tearDown()
|
||||||
|
|
||||||
|
|
||||||
class TempfileCheckMixin(object):
|
class TempfileCheckTestCaseMixin(object):
|
||||||
# Ignore the jvmstat instrumentation and GitLab's CI .config files
|
# Ignore the jvmstat instrumentation and GitLab's CI .config files
|
||||||
# Ignore LibreOffice fontconfig cache dir
|
# Ignore LibreOffice fontconfig cache dir
|
||||||
ignore_globs = ('hsperfdata_*', '.config', '.cache')
|
ignore_globs = ('hsperfdata_*', '.config', '.cache')
|
||||||
@@ -108,7 +163,7 @@ class TempfileCheckMixin(object):
|
|||||||
) - set(ignored_result)
|
) - set(ignored_result)
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TempfileCheckMixin, self).setUp()
|
super(TempfileCheckTestCaseMixin, self).setUp()
|
||||||
if getattr(settings, 'COMMON_TEST_TEMP_FILES', False):
|
if getattr(settings, 'COMMON_TEST_TEMP_FILES', False):
|
||||||
self._temporary_items = self._get_temporary_entries()
|
self._temporary_items = self._get_temporary_entries()
|
||||||
|
|
||||||
@@ -123,4 +178,43 @@ class TempfileCheckMixin(object):
|
|||||||
','.join(final_temporary_items - self._temporary_items)
|
','.join(final_temporary_items - self._temporary_items)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
super(TempfileCheckMixin, self).tearDown()
|
super(TempfileCheckTestCaseMixin, self).tearDown()
|
||||||
|
|
||||||
|
|
||||||
|
class TestViewTestCaseMixin(object):
|
||||||
|
has_test_view = False
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
from mayan.urls import urlpatterns
|
||||||
|
|
||||||
|
self.client.logout()
|
||||||
|
if self.has_test_view:
|
||||||
|
urlpatterns.pop(0)
|
||||||
|
super(TestViewTestCaseMixin, self).tearDown()
|
||||||
|
|
||||||
|
def add_test_view(self, test_object):
|
||||||
|
from mayan.urls import urlpatterns
|
||||||
|
|
||||||
|
def test_view(request):
|
||||||
|
template = Template('{{ object }}')
|
||||||
|
context = Context(
|
||||||
|
{'object': test_object, 'resolved_object': test_object}
|
||||||
|
)
|
||||||
|
return HttpResponse(template.render(context=context))
|
||||||
|
|
||||||
|
urlpatterns.insert(0, url(TEST_VIEW_URL, test_view, name=TEST_VIEW_NAME))
|
||||||
|
clear_url_caches()
|
||||||
|
self.has_test_view = True
|
||||||
|
|
||||||
|
def get_test_view(self):
|
||||||
|
response = self.get(TEST_VIEW_NAME)
|
||||||
|
if isinstance(response.context, ContextList):
|
||||||
|
# template widget rendering causes test client response to be
|
||||||
|
# ContextList rather than RequestContext. Typecast to dictionary
|
||||||
|
# before updating.
|
||||||
|
result = dict(response.context).copy()
|
||||||
|
result.update({'request': response.wsgi_request})
|
||||||
|
return Context(result)
|
||||||
|
else:
|
||||||
|
response.context.update({'request': response.wsgi_request})
|
||||||
|
return Context(response.context)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
TEST_ROLE_2_LABEL = 'test role 2'
|
TEST_CASE_ROLE_LABEL = 'test case role'
|
||||||
TEST_ROLE_LABEL = 'test role'
|
TEST_ROLE_LABEL = 'test role 2'
|
||||||
TEST_ROLE_LABEL_EDITED = 'test role label edited'
|
TEST_ROLE_LABEL_EDITED = 'test role label edited'
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from ..models import Role
|
||||||
|
|
||||||
|
from .literals import TEST_CASE_ROLE_LABEL, TEST_ROLE_LABEL
|
||||||
|
|
||||||
|
|
||||||
|
class RoleTestCaseMixin(object):
|
||||||
|
def setUp(self):
|
||||||
|
super(RoleTestCaseMixin, self).setUp()
|
||||||
|
if hasattr(self, '_test_case_group'):
|
||||||
|
self.create_role()
|
||||||
|
|
||||||
|
def create_role(self):
|
||||||
|
self._test_case_role = Role.objects.create(label=TEST_CASE_ROLE_LABEL)
|
||||||
|
|
||||||
|
def grant_permission(self, permission):
|
||||||
|
self._test_case_role.grant(permission=permission)
|
||||||
|
|
||||||
|
|
||||||
|
class RoleTestMixin(object):
|
||||||
|
def _create_test_role(self):
|
||||||
|
self.test_role = Role.objects.create(label=TEST_ROLE_LABEL)
|
||||||
@@ -3,6 +3,7 @@ from __future__ import absolute_import
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
|
from django.http import Http404
|
||||||
|
|
||||||
from rest_framework.permissions import BasePermission
|
from rest_framework.permissions import BasePermission
|
||||||
|
|
||||||
@@ -33,6 +34,10 @@ class MayanPermission(BasePermission):
|
|||||||
view, 'mayan_object_permissions', {}
|
view, 'mayan_object_permissions', {}
|
||||||
).get(request.method, None)
|
).get(request.method, None)
|
||||||
|
|
||||||
|
object_permissions_raise_404 = getattr(
|
||||||
|
view, 'mayan_object_permissions_raise_404', ()
|
||||||
|
)
|
||||||
|
|
||||||
if required_permission:
|
if required_permission:
|
||||||
try:
|
try:
|
||||||
if hasattr(view, 'mayan_permission_attribute_check'):
|
if hasattr(view, 'mayan_permission_attribute_check'):
|
||||||
@@ -47,7 +52,10 @@ class MayanPermission(BasePermission):
|
|||||||
obj=obj
|
obj=obj
|
||||||
)
|
)
|
||||||
except PermissionDenied:
|
except PermissionDenied:
|
||||||
return False
|
if request.method in object_permissions_raise_404:
|
||||||
|
raise Http404
|
||||||
|
else:
|
||||||
|
return False
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -1,20 +1,15 @@
|
|||||||
from __future__ import absolute_import, unicode_literals
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
from django.contrib.auth import get_user_model
|
|
||||||
from django.urls import reverse
|
|
||||||
|
|
||||||
from rest_framework.test import APITestCase
|
from rest_framework.test import APITestCase
|
||||||
|
|
||||||
from mayan.apps.acls.tests.mixins import ACLBaseTestMixin
|
from mayan.apps.acls.tests.mixins import ACLTestCaseMixin
|
||||||
|
from mayan.apps.common.tests.mixins import ClientMethodsTestCaseMixin
|
||||||
from mayan.apps.permissions.classes import Permission
|
from mayan.apps.permissions.classes import Permission
|
||||||
from mayan.apps.smart_settings.classes import Namespace
|
from mayan.apps.smart_settings.classes import Namespace
|
||||||
from mayan.apps.user_management.tests import (
|
from mayan.apps.user_management.tests.mixins import UserTestCaseMixin
|
||||||
TEST_ADMIN_PASSWORD, TEST_ADMIN_USERNAME, TEST_USER_USERNAME,
|
|
||||||
TEST_USER_PASSWORD
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class BaseAPITestCase(ACLBaseTestMixin, APITestCase):
|
class BaseAPITestCase(ClientMethodsTestCaseMixin, ACLTestCaseMixin, UserTestCaseMixin, APITestCase):
|
||||||
"""
|
"""
|
||||||
API test case class that invalidates permissions and smart settings
|
API test case class that invalidates permissions and smart settings
|
||||||
"""
|
"""
|
||||||
@@ -24,78 +19,4 @@ class BaseAPITestCase(ACLBaseTestMixin, APITestCase):
|
|||||||
Permission.invalidate_cache()
|
Permission.invalidate_cache()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.client.logout()
|
|
||||||
super(BaseAPITestCase, self).tearDown()
|
super(BaseAPITestCase, self).tearDown()
|
||||||
|
|
||||||
def delete(self, viewname=None, path=None, *args, **kwargs):
|
|
||||||
data = kwargs.pop('data', {})
|
|
||||||
follow = kwargs.pop('follow', False)
|
|
||||||
|
|
||||||
if viewname:
|
|
||||||
path = reverse(viewname=viewname, *args, **kwargs)
|
|
||||||
|
|
||||||
return self.client.delete(
|
|
||||||
path=path, data=data, follow=follow
|
|
||||||
)
|
|
||||||
|
|
||||||
def get(self, viewname=None, path=None, *args, **kwargs):
|
|
||||||
data = kwargs.pop('data', {})
|
|
||||||
follow = kwargs.pop('follow', False)
|
|
||||||
|
|
||||||
if viewname:
|
|
||||||
path = reverse(viewname=viewname, *args, **kwargs)
|
|
||||||
|
|
||||||
return self.client.get(
|
|
||||||
path=path, data=data, follow=follow
|
|
||||||
)
|
|
||||||
|
|
||||||
def login(self, username, password):
|
|
||||||
logged_in = self.client.login(username=username, password=password)
|
|
||||||
|
|
||||||
user = get_user_model().objects.get(username=username)
|
|
||||||
|
|
||||||
self.assertTrue(logged_in)
|
|
||||||
self.assertTrue(user.is_authenticated)
|
|
||||||
return user.is_authenticated
|
|
||||||
|
|
||||||
def login_user(self):
|
|
||||||
self.login(username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD)
|
|
||||||
|
|
||||||
def login_admin_user(self):
|
|
||||||
self.login(username=TEST_ADMIN_USERNAME, password=TEST_ADMIN_PASSWORD)
|
|
||||||
|
|
||||||
def logout(self):
|
|
||||||
self.client.logout()
|
|
||||||
|
|
||||||
def patch(self, viewname=None, path=None, *args, **kwargs):
|
|
||||||
data = kwargs.pop('data', {})
|
|
||||||
follow = kwargs.pop('follow', False)
|
|
||||||
|
|
||||||
if viewname:
|
|
||||||
path = reverse(viewname=viewname, *args, **kwargs)
|
|
||||||
|
|
||||||
return self.client.patch(
|
|
||||||
path=path, data=data, follow=follow
|
|
||||||
)
|
|
||||||
|
|
||||||
def post(self, viewname=None, path=None, *args, **kwargs):
|
|
||||||
data = kwargs.pop('data', {})
|
|
||||||
follow = kwargs.pop('follow', False)
|
|
||||||
|
|
||||||
if viewname:
|
|
||||||
path = reverse(viewname=viewname, *args, **kwargs)
|
|
||||||
|
|
||||||
return self.client.post(
|
|
||||||
path=path, data=data, follow=follow
|
|
||||||
)
|
|
||||||
|
|
||||||
def put(self, viewname=None, path=None, *args, **kwargs):
|
|
||||||
data = kwargs.pop('data', {})
|
|
||||||
follow = kwargs.pop('follow', False)
|
|
||||||
|
|
||||||
if viewname:
|
|
||||||
path = reverse(viewname=viewname, *args, **kwargs)
|
|
||||||
|
|
||||||
return self.client.put(
|
|
||||||
path=path, data=data, follow=follow
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -1,18 +1,22 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'TEST_ADMIN_EMAIL', 'TEST_ADMIN_PASSWORD', 'TEST_ADMIN_USERNAME',
|
|
||||||
'TEST_GROUP_NAME', 'TEST_GROUP_NAME_EDITED', 'TEST_USER_EMAIL',
|
'TEST_GROUP_NAME', 'TEST_GROUP_NAME_EDITED', 'TEST_USER_EMAIL',
|
||||||
'TEST_USER_PASSWORD', 'TEST_USER_PASSWORD_EDITED', 'TEST_USER_USERNAME'
|
'TEST_USER_PASSWORD', 'TEST_USER_PASSWORD_EDITED', 'TEST_USER_USERNAME'
|
||||||
)
|
)
|
||||||
|
|
||||||
TEST_ADMIN_EMAIL = 'admin@example.com'
|
TEST_CASE_ADMIN_EMAIL = 'admin@example.com'
|
||||||
TEST_ADMIN_PASSWORD = 'test admin password'
|
TEST_CASE_ADMIN_PASSWORD = 'test admin password'
|
||||||
TEST_ADMIN_USERNAME = 'test_admin'
|
TEST_CASE_ADMIN_USERNAME = 'test_admin'
|
||||||
|
|
||||||
|
TEST_CASE_GROUP_NAME = 'test group'
|
||||||
|
TEST_CASE_USER_EMAIL = 'user@example.com'
|
||||||
|
TEST_CASE_USER_PASSWORD = 'test user password'
|
||||||
|
TEST_CASE_USER_USERNAME = 'test_user'
|
||||||
|
|
||||||
TEST_GROUP_NAME = 'test group'
|
TEST_GROUP_NAME = 'test group'
|
||||||
TEST_GROUP_2_NAME = 'test group 2'
|
|
||||||
TEST_GROUP_NAME_EDITED = 'test group edited'
|
TEST_GROUP_NAME_EDITED = 'test group edited'
|
||||||
|
TEST_GROUP_2_NAME = 'test group 2'
|
||||||
TEST_GROUP_2_NAME_EDITED = 'test group 2 edited'
|
TEST_GROUP_2_NAME_EDITED = 'test group 2 edited'
|
||||||
TEST_USER_EMAIL = 'user@example.com'
|
TEST_USER_EMAIL = 'user@example.com'
|
||||||
TEST_USER_PASSWORD = 'test user password'
|
TEST_USER_PASSWORD = 'test user password'
|
||||||
|
|||||||
@@ -4,11 +4,60 @@ from django.contrib.auth import get_user_model
|
|||||||
from django.contrib.auth.models import Group
|
from django.contrib.auth.models import Group
|
||||||
|
|
||||||
from .literals import (
|
from .literals import (
|
||||||
TEST_GROUP_2_NAME, TEST_GROUP_2_NAME_EDITED, TEST_USER_2_EMAIL,
|
TEST_CASE_ADMIN_EMAIL, TEST_CASE_ADMIN_PASSWORD, TEST_CASE_ADMIN_USERNAME,
|
||||||
TEST_USER_2_PASSWORD, TEST_USER_2_USERNAME, TEST_USER_2_USERNAME_EDITED
|
TEST_CASE_GROUP_NAME, TEST_CASE_USER_EMAIL, TEST_CASE_USER_PASSWORD,
|
||||||
|
TEST_CASE_USER_USERNAME, TEST_GROUP_NAME, TEST_GROUP_2_NAME,
|
||||||
|
TEST_GROUP_2_NAME_EDITED, TEST_USER_2_EMAIL, TEST_USER_2_PASSWORD,
|
||||||
|
TEST_USER_EMAIL, TEST_USER_USERNAME, TEST_USER_PASSWORD,
|
||||||
|
TEST_USER_2_USERNAME, TEST_USER_2_USERNAME_EDITED
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class UserTestCaseMixin(object):
|
||||||
|
auto_login_admin = False
|
||||||
|
auto_login_user = True
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(UserTestCaseMixin, self).setUp()
|
||||||
|
if self.auto_login_user:
|
||||||
|
self._test_case_user = get_user_model().objects.create_user(
|
||||||
|
username=TEST_CASE_USER_USERNAME, email=TEST_CASE_USER_EMAIL,
|
||||||
|
password=TEST_CASE_USER_PASSWORD
|
||||||
|
)
|
||||||
|
self.login_user()
|
||||||
|
self._test_case_group = Group.objects.create(name=TEST_GROUP_NAME)
|
||||||
|
self._test_case_group.user_set.add(self._test_case_user)
|
||||||
|
elif self.auto_login_admin:
|
||||||
|
self._test_case_admin_user = get_user_model().objects.create_superuser(
|
||||||
|
username=TEST_CASE_ADMIN_USERNAME, email=TEST_CASE_ADMIN_EMAIL,
|
||||||
|
password=TEST_CASE_ADMIN_PASSWORD
|
||||||
|
)
|
||||||
|
self.login_admin_user()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
self.client.logout()
|
||||||
|
super(UserTestCaseMixin, self).tearDown()
|
||||||
|
|
||||||
|
def login(self, *args, **kwargs):
|
||||||
|
logged_in = self.client.login(*args, **kwargs)
|
||||||
|
|
||||||
|
return logged_in
|
||||||
|
|
||||||
|
def login_user(self):
|
||||||
|
self.login(
|
||||||
|
username=TEST_CASE_USER_USERNAME, password=TEST_CASE_USER_PASSWORD
|
||||||
|
)
|
||||||
|
|
||||||
|
def login_admin_user(self):
|
||||||
|
self.login(
|
||||||
|
username=TEST_CASE_ADMIN_USERNAME,
|
||||||
|
password=TEST_CASE_ADMIN_PASSWORD
|
||||||
|
)
|
||||||
|
|
||||||
|
def logout(self):
|
||||||
|
self.client.logout()
|
||||||
|
|
||||||
|
|
||||||
class UserTestMixin(object):
|
class UserTestMixin(object):
|
||||||
def _create_test_group(self):
|
def _create_test_group(self):
|
||||||
self.test_group = Group.objects.create(name=TEST_GROUP_2_NAME)
|
self.test_group = Group.objects.create(name=TEST_GROUP_2_NAME)
|
||||||
@@ -23,6 +72,8 @@ class UserTestMixin(object):
|
|||||||
password=TEST_USER_2_PASSWORD
|
password=TEST_USER_2_PASSWORD
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Group views
|
||||||
|
|
||||||
def _request_test_group_create_view(self):
|
def _request_test_group_create_view(self):
|
||||||
reponse = self.post(
|
reponse = self.post(
|
||||||
viewname='user_management:group_create', data={
|
viewname='user_management:group_create', data={
|
||||||
@@ -32,19 +83,38 @@ class UserTestMixin(object):
|
|||||||
self.test_group = Group.objects.filter(name=TEST_GROUP_2_NAME).first()
|
self.test_group = Group.objects.filter(name=TEST_GROUP_2_NAME).first()
|
||||||
return reponse
|
return reponse
|
||||||
|
|
||||||
|
def _request_test_group_delete_view(self):
|
||||||
|
return self.post(
|
||||||
|
viewname='user_management:group_delete', kwargs={
|
||||||
|
'group_pk': self.test_group.pk
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
def _request_test_group_edit_view(self):
|
def _request_test_group_edit_view(self):
|
||||||
return self.post(
|
return self.post(
|
||||||
viewname='user_management:group_edit', kwargs={
|
viewname='user_management:group_edit', kwargs={
|
||||||
'pk': self.test_group.pk
|
'group_pk': self.test_group.pk
|
||||||
}, data={
|
}, data={
|
||||||
'name': TEST_GROUP_2_NAME_EDITED
|
'name': TEST_GROUP_2_NAME_EDITED
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _request_test_group_list_view(self):
|
||||||
|
return self.get(viewname='user_management:group_list')
|
||||||
|
|
||||||
|
def _request_test_group_members_view(self):
|
||||||
|
return self.get(
|
||||||
|
viewname='user_management:group_members',
|
||||||
|
kwargs={'group_pk': self.test_group.pk}
|
||||||
|
)
|
||||||
|
|
||||||
|
# User views
|
||||||
|
|
||||||
def _request_test_user_create_view(self):
|
def _request_test_user_create_view(self):
|
||||||
reponse = self.post(
|
reponse = self.post(
|
||||||
viewname='user_management:user_create', data={
|
viewname='user_management:user_create', data={
|
||||||
'username': TEST_USER_2_USERNAME
|
'username': TEST_USER_2_USERNAME,
|
||||||
|
'password': TEST_USER_2_PASSWORD
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -53,11 +123,23 @@ class UserTestMixin(object):
|
|||||||
).first()
|
).first()
|
||||||
return reponse
|
return reponse
|
||||||
|
|
||||||
|
def _request_test_user_delete_view(self):
|
||||||
|
return self.post(
|
||||||
|
viewname='user_management:user_delete',
|
||||||
|
kwargs={'user_pk': self.test_user.pk}
|
||||||
|
)
|
||||||
|
|
||||||
def _request_test_user_edit_view(self):
|
def _request_test_user_edit_view(self):
|
||||||
return self.post(
|
return self.post(
|
||||||
viewname='user_management:user_edit', kwargs={
|
viewname='user_management:user_edit', kwargs={
|
||||||
'pk': self.test_user.pk
|
'user_pk': self.test_user.pk
|
||||||
}, data={
|
}, data={
|
||||||
'username': TEST_USER_2_USERNAME_EDITED
|
'username': TEST_USER_2_USERNAME_EDITED
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _request_test_user_groups_view(self):
|
||||||
|
return self.get(
|
||||||
|
viewname='user_management:user_groups',
|
||||||
|
kwargs={'user_pk': self.test_user.pk}
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user