Accessing Middleware value for testing a Django DetailView - django

I am writing a test for a DetailView that queries get_object() by accessing a value set in a Middleware. This is for a Companies application and Company Model. Each user is in a Company.
To access the company throughout the project, I set the current user's Company.uuid on the request via a custom middleware.
Middleware
from django.utils.deprecation import MiddlewareMixin
class DynamicCompanyUUIDMiddleware(MiddlewareMixin):
""" Adds the current organization's UUID from the current user."""
def process_request(self, request):
try:
company_uuid = request.user.company_uuid
except:
company_uuid = None
request.company_uuid = company_uuid
That is used in the CompanyDetailView's get_object() method via a Mixin that I use for the other Company Views.
Mixin
class CompanyMixin(LoginRequiredMixin, SetHeadlineMixin):
model = Company
def get_object(self):
return get_object_or_404(
self.model,
uuid=self.request.user.company_uuid)
Test
The test that I'm trying to write is:
from django.test import RequestFactory
from django.urls import reverse, resolve
from test_plus.test import TestCase
from ..models import Company
from ..views import CompanyDetailView
class BaseCompanyTestCase(TestCase):
def setUp(self):
self.user = self.make_user()
self.object = Company.objects.create(owner=self.user, name="testcompany")
self.user.company_uuid = self.object.uuid
self.factory = RequestFactory()
class TestCompanyDetailView(BaseCompanyTestCase):
def setUp(self):
super(TestCompanyDetailView, self).setUp()
self.client.login(username="testuser", password="password")
self.view = CompanyDetailView()
self.view.object = self.object
request = self.factory.get(reverse('companies:detail'))
request.user = self.user
request.company_uuid = self.user.company_uuid
response = CompanyDetailView.as_view()(request)
self.assertEqual(response.status_code, 200)
def test_get_headline(self):
self.assertEqual(
self.view.get_headline(),
'%s Members' % self.object.name
Result
This results in a 404 with the testuser's company not being found.
Walking through it:
I create the user
Create the company for this new testuser
Set the user.company_uuid
This should allow the mixin to access the company_uuid
Therefore return the user's company in the request
However I'm not returning the company as the 404 shows.
Question
Where am I going wrong on this? Thanks in advance for your help.
Answer
I was mixing Django's Client & RequestFactory. I have corrected the code above which is correct.

I was mixing Django's Client & RequestFactory. After stepping away, I figured it out below -
from django.test import RequestFactory
from django.urls import reverse, resolve
from test_plus.test import TestCase
from ..models import Company
from ..views import CompanyDetailView
class BaseCompanyTestCase(TestCase):
def setUp(self):
self.user = self.make_user()
self.object = Company.objects.create(owner=self.user, name="testcompany")
self.user.company_uuid = self.object.uuid
self.factory = RequestFactory()
class TestCompanyDetailView(BaseCompanyTestCase):
def setUp(self):
super(TestCompanyDetailView, self).setUp()
self.client.login(username="testuser", password="password")
self.view = CompanyDetailView()
self.view.object = self.object
request = self.factory.get(reverse('companies:detail'))
request.user = self.user
request.company_uuid = self.user.company_uuid
response = CompanyDetailView.as_view()(request)
self.assertEqual(response.status_code, 200)
def test_get_headline(self):
self.assertEqual(
self.view.get_headline(),
'%s Members' % self.object.name

Related

Testcase returning 401 even with force_autenthicate()

I'm trying to test a view of my project with the following TestCase:
def test_jump_story(self):
c = APIClient()
user = User.objects.get(username='test1')
c.login(username=user.username, password='123')
room_id = PokerRoom.objects.get(name='planning').id
room_index = PokerRoom.objects.get(name='planning').index
request = c.post(reverse('jumpstory', kwargs={'pk': room_id, 'index': room_index}))
c.force_authenticate(user=user)
self.assertEqual(200,request.status_code)
but it returns this <Response status_code=401, "application/json"> even using force_authenticate.
The view that i'm testing:
class jumpStory(APIView):
permission_classes = [IsAuthenticated]
def post(self, request, pk, index):
data= self.request.data
index = self.kwargs['index']
pk = self.kwargs['pk']
if PokerRoom.objects.filter(id=pk).exists():
body = {'index':index}
message_socket("JUMP_STORY", pk, body)
return Response({'success':"JUMP_STORY"}, status=200)
else:
return Response({'error':'message not sended'}, status=400)
What is wrong with my test?
Use APITestCase instead of django TestCase. from rest_framework.test import APITestCase.
from rest_framework.test import APITestCase
class MyTests(APITestCase)
def setUp(self):
user = User.objects.create(username=john)
user.set_password("1234")
user.save()
self.client.force_authenticate(user=user)
def test_jump_story(self):
# do your test

Writing Unit Test for my Class based views which also require LoginRequiredMixin

I have one ListView and one DetailView and both requires LoginRequiredMixin. Now i want to write unit test for these class based views. Can somebody help me with this. I want to test the template, context as well as right view is called. My Tests.py Looks like this:-
from django.test import TestCase, Client
from django.urls import reverse,resolve
from django.test.client import RequestFactory
from django.contrib.auth import get_user_model
from teams.models import Teams
from teams.views import TeamListView, TeamDetailView
class TestTeamsView(TestCase):
def setUp(self):
self.factory = RequestFactory()
def test_list_view(self):
request = self.factory.get(reverse('teams:team_list'))
response = TeamListView.as_view()(request)
self.assertEqual(response.status_code, 200)
print(response.status_code)
I am getting Response:
if not request.user.is_authenticated:
AttributeError: 'WSGIRequest' object has no attribute 'user'
I got the solution and its like this:
from django.test.client import RequestFactory
from django.contrib.auth.models import AnonymousUser
class TestTeamsView(TestCase):
def setUp(self):
self.factory = RequestFactory()
self.user = User.objects.create_user(
username='test1',
email='abc1#gmail.com',
first_name='t',
last_name='u',
password='password'
)
def test_team_list_view_with_valid_user(self):
request = self.factory.get('/team/')
request.user = self.user
response = TeamListView.as_view()(request)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.template_name[0], 'teams/teams_list.html')
def test_team_list_view_with_anonymous_user(self):
request = self.factory.get('/team/')
request.user = AnonymousUser()
response = TeamListView.as_view()(request)
self.assertEqual(response.status_code,302)

How to check user online and offline status

I am trying to check and display user online status with django and django rest framework.
I have tried this article: Django - detect if user is online / offline
But did not work on APIview only works on views with render and Httpresponse.
Updated
Here is the code for the middleware class
import datetime
from django.core.cache import cache
from django.conf import settings
from django.utils.deprecation import MiddlewareMixin
class ActiveUserMiddleware(MiddlewareMixin):
def process_request(self, request):
current_user = request.user
if request.user.is_authenticated:
now = datetime.datetime.now()
cache.set('seen_%s' % (current_user.username), now, settings.USER_LASTSEEN_TIMEOUT)
The APIView
class ProfilePersonal(APIView):
permission_classes = (permissions.IsAuthenticated,)
serializer_class = UserProfileSerializer
def get(self):
try:
queryset = Account.objects.get()
except Account.DoesNotExist:
return Response(data={'non_field_errors': 'Request could not be validated.'},
status=status.HTTP_400_BAD_REQUEST)
serializer_data = self.serializer_class(queryset)
return Response(
data=serializer_data,
status=status.HTTP_200_OK
)

Get the logged in user when there is request is not defined

I am having trouble to find a way to make it work;
I need to get the queryset with a list of the team created by the current logged in user.
My form look the following :
from django import forms
from django.contrib.auth.models import User
from registration.models import MyUser
from .models import Project, Team
from django.contrib.auth import get_user_model
User = get_user_model()
class EditSelectTeam(forms.Form):
team_choice = forms.ModelChoiceField(widget=forms.RadioSelect, queryset=Team.objects.all().filter(team_hr_admin=request.User))
#team_id = forms.ChoiceField(queryset = Team.objects.filter(team_hr_admin= MyUser))
def team_select(self):
data = self.cleaned_data['team_choice']
return data
views.py:
def TeamSelect(request):
if request.method == "POST":
select_form = EditSelectTeam(request.POST)
print('sucess')
else:
select_form = EditSelectTeam(request)
return render(request,'link_project.html',
{'select_form':select_form })
I get the error that request is not define
you can pass the request using init method like:
class EditSelectTeam(forms.Form):
team_choice = forms.ModelChoiceField(widget=forms.RadioSelect, queryset=None)
def __init__(self, request, *args, **kwargs):
super(EditSelecTeam, self).__init__(*args, **kwargs)
self.fields['team_choice'].queryset = Team.objects.all().filter(team_hr_admin=request.User))
def team_select(self):
data = self.cleaned_data['team_choice']
return data
Remember pass in your form the request like:
form = your_form(request)

how to test a django decorator?

I have a decorator where I can verify if the user has any permission. The code is working for me but I want to write a test for it.
How can I test the any_permission_required function?
from django.contrib.auth.decorators import user_passes_test
def any_permission_required(*perms):
return user_passes_test(lambda u: any(u.has_perm(perm) for perm in perms))
#any_permission_required('app.ticket_admin', 'app.ticket_read')
def ticket_list(request):
...
Finally with help of Alasdair and the Django test code I found a solution.
from django.test import RequestFactory
class TestFoo(TestCase):
def setUp(self):
self.user = models.User.objects.create(username='foo', password='bar')
self.factory = RequestFactory()
def test_any_permissions_pass(self):
perms = Permission.objects.filter(codename__in=('ticket_admin', 'ticket_read'))
self.user.user_permissions.add(*perms)
#any_permission_required('app.ticket_admin', 'app.ticket_read')
def a_view(request):
return HttpResponse()
request = self.factory.get('/foo')
request.user = self.user
resp = a_view(request)
self.assertEqual(resp.status_code, 200)