Kevin D.
Kevin D.

Reputation: 315

Django testing - test if logged in user is owner of userdetails

So I've made this little app where users have an account page were they can see and update their own details.

Now I'm writing some tests for the DetailView and UpdateView. I would like to verify that the logged in user is indeed the owner of the user details.

I've created a testdatabase with different users and added three tests.

The problem is in the last test, I tried to retrieve the logged in user and compare this with the current user details but this isn't working. Any ideas?

Edit: The test now passes successfully, so the user data belongs to the user who is logged in.

However this doesn't feel like a valid test method. Even though the user matches the owner of the details I'm looking for a way to verify if a user would be able to access the details of someone else.

Before, I would use the user id in the url like;

urls.py

path('account/<int:pk>/', views.AccountDetailView.as_view(), name='account_detail'),

So someone would be able to edit the urlpath and access someone else his details if the LoginRequiredMixin wasn't added.

By using get_object(self):, this is no longer possible, what's the best way to test this possibility?

views.py

class AccountDetailView(LoginRequiredMixin, DetailView):
    model = User
    template_name = 'account.html'

    '''
    Retrieve user id from "self.request.user" instead of retrieving the user_id
    from the URL. This way we can eliminate the user id in the URL.
    '''
    def get_object(self):
        return self.request.user

test_views.py

class LoggedInTestCase(TestCase):
    '''
    Setup LoginInTestCase 
    '''
    def setUp(self):
        guest = User.objects.create_user(username='john.doe', email='[email protected]', password='1234')
        guest_other = User.objects.create_user(username='david.doe', email='[email protected]', password='5678')


class AccountDetailViewTests(LoggedInTestCase):
    '''
    Test the UserDetailView which shows the user details
    '''
    def test_login_required_redirection(self):
        '''
        Test if only logged in users can view the user detail page
        '''
        self.url = reverse('account_detail')
        login_url = reverse('account_login')
        response = self.client.get(self.url)
        self.assertRedirects(response, '{login_url}?next={url}'.format(login_url=login_url, url=self.url))

    def test_logged_in_uses_correct_template(self):
        '''
        Test if logged in user gets to see the correct template
        '''
        login = self.client.login(username='john.doe', password='1234')
        response = self.client.get(reverse('account_detail'))
        # Check if our guest is logged in
        self.assertEqual(str(response.context['user']), 'john.doe')
        # Check for response "succes"
        self.assertEqual(response.status_code, 200)
        # Check if we get the correct template
        self.assertTemplateUsed(response, 'account.html')

    def test_accountdetails_belong_to_logged_in_user(self):
        '''
        Test if logged in user can only see the details that belong to him
        '''
        login = self.client.login(username='john.doe', password='1234')
        response = self.client.get(reverse('account_detail'))
        # Check if our guest is logged in matches the
        user = User.objects.get(username='john.doe') #edited
        self.assertEqual(response.context['user'], user)
        # Check for response "success"
        self.assertEqual(response.status_code, 200)

Upvotes: 0

Views: 811

Answers (1)

Alasdair
Alasdair

Reputation: 309109

The client.login method returns True if the login succeeded, it does not return the user.

You can fetch the user from the database.

user = User.objects.get(username='john.doe')
self.assertEqual(response.context['user'], user)

Or compare the string as in your other test.

self.assertEqual(str(response.context['user']), 'john.doe')

Upvotes: 1

Related Questions