File diff 744593ed423d → b95586a70595
conntrackt/tests/helpers.py
Show inline comments
 
new file 100644
 
# 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)