# Python standard library imports. from types import FunctionType # Python third-party library imports. import mock # Django imports. from django.core.exceptions import PermissionDenied from django.contrib.auth.models import User, Permission from django.test import RequestFactory def create_get_request(url="/fake-path/", user=None): """ Helper function for generating a GET request that can be passed on to a view. Arguments: url - URL that should be used for the request. Default is "/fake-path/". user - Django user to be passed on into the request. Default is mock.Mock(). """ request = RequestFactory().get(url) # If user was not provided, construct one using mocking. if user is None: user = mock.Mock() request.user = user return request def generate_get_response(view, request=None, *args, **kwargs): """ Generates a get response, passing the request, positional and keyword arguments to it as well. Attributes: view - View function that should be called. request - Request object to pass into view. Default is to create a new request using the create_get_request() call. *args - Additional positional arguments that will be passed into view. *kwargs - Additional keyword arguments that will be passed into view. """ # If no request was provided, construct it. if request is None: request = create_get_request() return view(request, *args, **kwargs) class PermissionTestMixin(object): """ Mixin class for testing if permission requirement is applied properly for accessing a view. In order to use this mixin, add it the left side of the class list the test is inheriting from, and configure it providing the following class options: view_class - Class used for the CBV that will be tested. view_function - View function that will be tested. sufficient_permissions - Permissions sufficient to gain access to view. permission_test_view_args - Positional arguments to pass to the view. permission_test_view_kwargs - Keyword arguments to pass to the view. """ view_class = None view_function = None permission_test_view_args = () permission_test_view_kwargs = {} sufficient_permissions = () def __init__(self, *args, **kwargs): """ Initialises the mixin. Takes care of some basic validation of passed configuration options. """ super(PermissionTestMixin, self).__init__(*args, **kwargs) if self.view_class is None and self.view_function is None: raise ValueError("Permission test mixin configured improperly - no CBV class or function was supplied via parameters 'view_class' or 'view_function'.") if self.view_function is not None and type(self.view_function) is not FunctionType: raise ValueError("Permission test mixin configured improperly - provided 'view_function' is not function. Did you forget to wrap the function with staticmethod() perhaps?") if type(self.permission_test_view_kwargs) is not dict: raise ValueError("Permission text mixin configured improperly - parameter 'permission_test_view_kwargs' must be a dictionary.") if type(self.permission_test_view_args) is not tuple: raise ValueError("Permission text mixin configured improperly - parameter 'permission_test_view_args' must be a tuple.") if type(self.sufficient_permissions) is not tuple: raise ValueError("Permission text mixin configured improperly - parameter 'sufficient_permissions' must be a tuple.") def test_permission_granted(self): # Set-up a request from user with sufficient privileges. request = RequestFactory().get("/fake-path") user = User.objects.create(username="user", password="password") for permission in self.sufficient_permissions: user.user_permissions.add(Permission.objects.get(codename=permission)) request.user = user # Get the view. if self.view_class is not None: view = self.view_class.as_view() elif self.view_function is not None: view = self.view_function # Verify that permission is granted args = self.permission_test_view_args kwargs = self.permission_test_view_kwargs try: response = view(request, *args, **kwargs) except PermissionDenied: self.fail("Failed to access view with user privileges: %s" % str(self.sufficient_permissions)) self.assertEqual(response.status_code, 200) def test_permission_denied(self): # Set-up a request from user with insufficient privileges. request = RequestFactory().get("/fake-path") request.user = User.objects.create(username="user", password="password") # Get the view. if self.view_class: view = self.view_class.as_view() elif self.view_function: view = self.view_function # Verify that permission is denied. args = self.permission_test_view_args kwargs = self.permission_test_view_kwargs self.assertRaises(PermissionDenied, view, request, *args, **kwargs) class FakeMessages(object): """ Helper class for mocking the Django messages framework. """ def __init__(self): """ Initalises the message framework mocker. Set-ups the messages list prpoperty. """ self.messages = [] def add(self, level, message, extra_tags): """ Adds a message. """ self.messages.append(message)