Search code examples
django-viewsdjango-testingdjango-usersdjango-unittestdjango-login

Django UnitTest check for Permission with self.user.has_perm in test_views.py for View(LoginRequiredMixin, PermissionRequiredMixin, ListView)


I Basically followed the Mozilla How-to: https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Testing#Views_that_are_restricted_to_logged_in_users

To get a Complete Picture here you can see the corresponding urls and view in views.py and urls.py below:

path('contexts/', views.ContextListView.as_view(), name='contexts'),
class ContextListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
    model = Context
    paginate_by = 10
    permission_required = 'catalog.view_context'
    def get_queryset(self):
        if self.request.user.is_staff:
            queryset = Context.objects.all()
        else:
            user = self.request.user
            queryset = Context.objects.filter(name=user)
        return queryset

I have Created two Users in two different ways that should do the same.
One of the ways is commented out.

class ContextListViewTest(TestCase):
    def setUp(self):
        number_of_contexts = 25
        number_of_extensions = 25
        # test_user1 = User.objects.create_user(username='testuser1')
        # test_user2 = User.objects.create_user(username='testuser2')
        # test_user1.set_password('1X<ISRUkw+tuK')
        # test_user2.set_password('2HJ1vRV0Z&3iD')
        test_user1 = User.objects.create_user(username='testuser1', password='1X<ISRUkw+tuK')
        test_user2 = User.objects.create_user(username='testuser2', password='2HJ1vRV0Z&3iD')
        test_user1.save()
        test_user2.save()

While a Simple Login test seems to Work:

    def test_login(self):
        c = Client()  # Login
        login = c.login(username='testuser1', password='1X<ISRUkw+tuK')
        self.assertTrue(login)

Testing For a specific Permissions does not:

    def test_logged_in_uses_correct_template(self):
        self.c = Client()  # Login
        self.user = User.objects.get(username="testuser1")
        login = self.c.login(username='testuser1', password='1X<ISRUkw+tuK')
        response = self.c.get(reverse('contexts'))

        # Check for HTTPResponseForbidden
        self.assertEqual(response.status_code, 403)

        # Check for Permission the User don't have but need to display that view.
        # self.assertFalse(self.user.has_perm('view_context', self.user.userprofile))
        # self.assertFalse(self.user.has_perm('view_context', self.user.profile))
        # self.assertFalse(self.user.has_perm('view_context', self.user))
        # self.assertFalse(self.user.has_perm('view_context', self.user.user_permissions))
        self.assertFalse(self.user.has_perm('view_context', self.user.user_permissions))

The Test self.assertEqual(response.status_code, 403) will pass because the Logged in User don't have the Permission catalog.view_context

After that i want to explicitly check that the User doesn't have that permission catalog.view_context with self.assertFalse(self.user.has_perm('view_context', self.user.user_permissions)) but i constantly get Errors like bool/user object/ XYZ has no Attribute profile/userprofile/user/user_permissions

I also looked into this: https://stackoverflow.com/a/10103291/4238752 and this https://stackoverflow.com/a/33294746/4238752 But no matter what I try it continues to throw the same Exceptions and Errors.


Solution

  • I Think i got it Working now like this: test_views.py

    #!/usr/bin/python3
    from django.test import TestCase
    from django.urls import reverse
    from catalog.models import Extension, Context
    from django.contrib.auth.models import User, Permission
    from django.test import Client
    
    
    class ContextListViewTest(TestCase):
        def setUp(self):
            number_of_contexts = 25
            number_of_extensions = 25
            test_user1 = User.objects.create_user(username='testuser1', password='1X<ISRUkw+tuK')
            test_user2 = User.objects.create_user(username='testuser2', password='2HJ1vRV0Z&3iD')
            test_user1.save()
            test_user2.save()
            # Create 25 Contexts
            for context_id in range(number_of_contexts):
                Context.objects.create(
                    name=f'test{context_id}.de',
                    countryprefix=f'{context_id}',
                    cityprefix=f'{context_id}',
                    number=f'90096{context_id}',
                    extensionsfrom=f'0',
                    extensionstill=f'Surname {context_id}',
                    portscount=f'Surname {context_id}',
                )
                # Create 25 Extensions per Context
                for extension_id in range(number_of_extensions):
                    Extension.objects.create(
                        username=f'test{context_id}.de_{extension_id}',
                        password=f'Password{context_id}',
                        firstname=f'Max{context_id}',
                        lastname=f'Mustermann{context_id}',
                        callerid=f'Max Msutermann <{context_id}>',
                        extension=f'{context_id}',
                        )
    
        def test__for_login_restriction_permission_and_template(self):
            # Create Client
            self.c = Client()
            # Try to call the Restricted View as Anonymous
            response = self.c.get(reverse('contexts'))
            # Check for Login Promt Redirection
            self.assertRedirects(response, '/accounts/login/?next=/catalog/contexts/')
    
            # Get Userobject
            self.user = User.objects.get(username="testuser1")
            # Login with the Client
            login = self.c.login(username='testuser1', password='1X<ISRUkw+tuK')
            # Check our user is logged in
            self.assertTrue(login)
            # Check for our username
            self.assertEqual(self.user.username, 'testuser1')
    
            # Try to call the Restricted View as logged in User again but without Permission
            response = self.c.get(reverse('contexts'))
            # Check for HTTPResponseForbidden
            self.assertEqual(response.status_code, 403)
    
            # Check for view_context Permission the User don't have but need to display that view.
            self.assertFalse(self.user.has_perm('catalog.view_context'))
            # now add the permission
            self.user.user_permissions.add(Permission.objects.get(codename='view_context'))
            # refetch user from the database
            self.user = User.objects.get(pk=self.user.pk)
            # Print all Permissions to Console / Should now include view_context
            # print(self.user.get_all_permissions())
            # Check for view_context Permission the User should now have
            self.assertTrue(self.user.has_perm('catalog.view_context'))
    
            # Try to call the Restricted View again but with Permission this time
            response = self.c.get(reverse('contexts'))
            # Check that we got a response "success"
            self.assertEqual(response.status_code, 200)
    
            # Check we used correct template
            self.assertTemplateUsed(response, 'catalog/context_list.html')
    
        # def test_pagination(self):