Testing CRUD function in Django Restaurant App - django

I am wondering if someone could help me. I am trying to test some views in a Django restaurant bookings system app I have created. I am doing well with jut testing the views but now I want to test the CRUD functionality of certain pages. In particular the create a booking on the bookings page and then redirect it back to the home page once the booking was successful (as is what happens on the site)
I just can't seem to figure out how to do it. Here is my current code. If someone could point me in the right direction that would be great. Thanks
setUp:
class TestViews(TestCase):
"""
Testing of the views taken from
the views.py file.
All HTTP testing includes the base.html template
as well as the view being tested to make sure everything
is being tested as it would appear for a user
"""
def setUp(self):
testing_user = User.objects.create_user(
username='JohnSmith',
first_name='John',
last_name='Smith',
email='johnsmith#email.com',
password='RandomWord1'
)
Booking.objects.create(
user=testing_user,
name='John Smith',
email_address='johnsmith#email.com',
phone='123654789',
number_of_people='2',
date='2022-10-20',
time='19:00',
table='Window',
occasion='none'
)
test:
def test_add_booking(self):
self.log_in()
response = self.client.post('/bookings', {Booking: Booking})
self.assertRedirects(response, '/')

You can check the status's code of your response, then also compare the response content.
self.assertEqual(response.status_code, 200)
self.assertContains(response, "No bookins.")
Or even to be more precisely self.assertQuerysetEqual(response.context["the name"], ["with real content"]

Related

Show different content for logged in(out) users. Django tests

Im following django tutorial and there is additional ideas how to test my code.
Perhaps logged-in admin users should be allowed to see unpublished
Questions, but not ordinary visitors. Again: whatever needs to be
added to the software to accomplish this should be accompanied by a
test,...
How can I create test to check if logged in User can see Questions witout choices and not logged in not?
class QuestionsAndChoices(TestCase):
def test_user_can_see_question_without_choices(self):
"""
A Question without choices should be displayed only for logged in Users
"""
#first make an empty question to use as a test
empty_question = create_question(question_text='Empty question', days=-1)
#so we can create choice but in this case we don't need it
#answer_for_question = past_question.choice_set.create(choice_text='Answer for "Question"', votes=0)
#create a response object to simulate someone using the site
response = self.client.get(reverse('polls:index'))
#if user logged in output should contain the question without choices
self.assertQuerysetEqual(response.context['latest_question_list'], []) #returns empty querylist
In the setUp method of your test class you can create a user.
class QuestionsAndChoices(TestCase):
def setUp(self):
self.user = User.objects.create_user(
username='user', password='top_secret')
Then in your test method, you can use force_login to log the user in, then use self.client.get() and make assertions as usual.
class QuestionsAndChoices(TestCase):
def test_user_can_see_question_without_choices(self):
...
self.client.force_login(self.user)
#create a response object to simulate someone using the site
response = self.client.get(reverse('polls:index'))
#if user logged in output should contain the question without choices
...

Django URL and making a portion of it optional, but using the same class API View

So I have this API URL on the back-end and I am wondering how to make a portion of it optional.
url(r'^api/documents/(?P<id>[0-9]+)$', GetDocumentsAPIView.as_view(), name='documents'),
So two things can happen coming from the front-end.
1) When the user logs in, it brings them to the /home which lists all of their projects. Clicking on the project brings them /documents/85 where the number is the number of the project and it lists all the documents for that project. This is sent to the API URL /api/documents/85. This much is working fine.
2) The other option is the user will just click on a Documents link in the navbar, which will just bring them to /documents. This should just go to the API URL /api/documents/ and eventually onto the serializer.py where their most recent project is determined and the documents for that are returned and rendered in the front-end
This I can't get working. Not sure if I can do it with just one url(), or if I need two. Was hoping the one I posted would look at the (?P<id>[0-9]+)$ as optional and if nothing was there would return the same GetDocumentsAPIView, but this is not the case.
EDIT: Including the view I am using for testing at this point. Just print() to see if anything is being routed to the view.
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
class GetDocumentsAPIView(APIView):
permission_classes = [IsAuthenticated]
def get(self, request, *args, **kwargs):
print(kwargs.get('id'))
return Response('Test')
No you need to add a URL pattern for r'^api/documents/$', which can launch the same view by the way. Only inside the view you'll have to assume id is optional:
if kwargs.get('id'):
# return specific document
else:
# return list of documents
I would rename your first URL pattern to 'view_document' so you can use the name 'documents' on the other, more generic view.
Note: I think your URL structure is wrong. Reading your URL, according to REST, I would expect to see the document with id 85 when fetching documents/85. If you actually are listing the docs of a project, the URL should be projects/85/documents/ or if unspecified projects/documents.

Testing Wagtail page views using client.get

I want to test my views functionality for a Wagtail Page that uses the RoutablePageMixin. I've found that Wagtail includes some testing functionality, but I'm trying to check the content on different urls. Although the Wagtail test functions work, testing using self.client.get doesn't work -- I get an 404 response. I'm trying the following test:
def test_subpage(self):
response = self.client.get(
self.page.full_url + self.page.reverse_subpage('subpage')
)
self.assertEqual(response.status_code, 200,
'Request the open positions page')
I assume the error lies in the way in which the page is created. I have used several ways, but cannot find one for which this works. The most intuitive way I found to create the page is the following:
def setUp(self):
self.login()
parent = Page.get_root_nodes()[0] # Home
self.assertCanCreate(parent, MyPage, {
'title': 'Title!',
'title_sv': 'Title2!',
'slug': 'test',
'published': datetime.datetime.now(),
})
self.page = MyPage.objects.get(slug='apply')
The subpages have been manually tested and do seem to work.
The simplest way to create a page within test code (or any other code...) is:
parent = Page.objects.get(url_path='/home/')
page = MyPage(title='Title!', slug='test', body='...')
parent.add_child(instance=page)
Note that Page.get_root_nodes()[0] will not return your site homepage - the tree root is a non-editable placeholder, and site homepages are usually children of it. You can create additional children of the root, but unless you give them a corresponding Site record, they won't be accessible under any URL (which is probably why you're getting a 404 in your test).

How to save the latest url requests in django?

I'd like to add a 'Last seen' url list to a project, so that last 5 articles requested by users can be displayed in the list to all users.
I've read the middleware docs but could not figure out how to use it in my case.
What I need is a simple working example of a middleware that captures the requests so that they can be saved and reused.
Hmm, don't know if I would do it with middleware, or right a decorator. But as your question is about Middleware, here my example:
class ViewLoggerMiddleware(object):
def process_response(self, request, response):
# We only want to save successful responses
if response.status_code not in [200, 302]:
return response
ViewLogger.objects.create(user_id=request.user.id,
view_url=request.get_full_path(), timestamp=timezone.now())
Showing Top 5 would be something like;
ViewLogger.objects.filter(user_id=request.user.id).order_by("-timestamp")[:5]
Note: Code is not tested, I'm not sure if status_code is a real attribute of response. Also, you could change your list of valid status codes.

django test client gets 404 for all urls

I am doing my first experiments with django testing and I am having the problem that I always get the 404 template regardless which url (even /) I am using.
If I throw the very same code into the django shell it's working as expected and always presents me the contents of the requested url.
class SimpleTest(TestCase):
def setUp(self):
self.user = User.objects.create_user('test', 'test', 'test')
self.user.is_staff = True
self.user.save()
self.client = Client()
def test_something(self):
self.assertTrue(self.client.login(username='test', password= 'test'))
self.client.get("/")
The login returns True, but the get() fails. Any hints what I am doing wrong here?
Keep in mind that most views use something like get_object_or_404, get_list_or_404, or simply raise Http404 when there's a problem accessing some object or another. You'll need to make sure that your test database is populated with sufficient objects to fulfill all these requirements to make the view not return a 404.
Remember, when running tests, the database is rolled back after each test (using transactions), so each test method must stand on its own or the setUp method must populate the database with any required dependencies.