0

I have a Test Class, that test the access of all page with different user.

Those access are defined by decorator on each of my views.

views.py :

@login_required
def afficher(request):
    ...
    ...

@creation_permission_required
def ajouter(request):
    ...
    ...

Some of these decorator are defined by me.

decorators.py :

def creation_permission_required(function):
    @wraps(function)
    @login_required
    def decorateur(request, *k, **a):
        user = get_object_or_404(User, username__iexact=request.user.username)
        if user.is_superuser or user.get_profile().creation:
            return function(request, *k, **a)
        else:
            return HttpResponseRedirect(reverse("non_autorise"))# <--- PROBLEM
    return decorateur
    return function

When I test them, I use the status_code attribute to verify if the user can access or not the page

test.py :

c = Client()
c.login(username='aucun', password='aucun')
for url in self.url_aucun:
    r = c.get(reverse(url['url'], args=url['args']))
    self.assertEqual(r.status_code, 200)
for url in self.url_creation:
    r = c.get(reverse(url['url'], args=url['args']))
    self.assertEqual(r.status_code, 302)      # <--- SECOND PROBLEM 

When a user doesn't have the right to access a page, the page should return a 403 error (forbidden). How can I do to test 403 instead of 302 ?

EDIT : I tried to use HttpResponseForbidden(reverse("non_autorise")), but couldn't get any content. So then I tried to make my own HttpResponse which is an exact copy of HttpResponseRedirect but with another status_code (403) still didn't get any content...

decorators.py :

class HttpResponseTest(HttpResponse):
    def __init__(self, redirect_to):
        super(HttpResponseTest, self).__init__()
        self['Location'] = iri_to_uri(redirect_to)
        self.status_code = 403

def creation_permission_required(function):
    @wraps(function)
    @login_required
    def decorateur(request, *k, **a):
        user = get_object_or_404(User, username__iexact=request.user.username)
        if user.is_superuser or user.get_profile().creation:
            return function(request, *k, **a)
        else:
            return HttpResponseTest(reverse("non_autorise"))# <--- PROBLEM
    return decorateur
    return function
James A Mohler
  • 11,060
  • 15
  • 46
  • 72
BlueMagma
  • 2,392
  • 1
  • 22
  • 46
  • Do you want to redirect to the view "non_autorise" or do you want to have a status code of 302? You can't have both. – Daniel Hepper Jul 03 '12 at 15:00
  • I can't ? Because that's exactly what I want : 403 code + redirection – BlueMagma Jul 04 '12 at 07:14
  • The probleme is not anymore about the question I ask, so I start a new question which are more precise about what I want : http://stackoverflow.com/questions/11324909/redirection-403-error – BlueMagma Jul 04 '12 at 08:08

3 Answers3

1
self.assertEqual(r.status_code, 403)
Steve Jalim
  • 11,989
  • 1
  • 37
  • 54
1

If you want a 403 response, you can raise a PermissionDenied exception in your decorator if you are using Django 1.4. Alternatively, you can return a HttpResponseForbidden in your decorator. You will also have to build a custom login_required decorator.

Daniel Hepper
  • 28,981
  • 10
  • 72
  • 75
  • I tried to use HttpResponseForbidden, but couldn't get any content. I just edit my post to explain that – BlueMagma Jul 03 '12 at 14:04
1

I had this same issue and solved it by instructing the test get() to follow the redirect using follow=True. Using BlueMagma's example it would look something like this:

for url in self.url_creation:
    r = c.get(reverse(url['url'], args=url['args']), follow=True)
    self.assertEqual(r.status_code, 403)      # <--- SECOND PROBLEM NO MORE!!!

Hope this helps someone else!

Fiver
  • 9,909
  • 9
  • 43
  • 63