Add tests for search page

This commit is contained in:
Jake Howard 2022-08-28 12:57:10 +01:00
parent edbedcd0fa
commit 6403aca2a2
Signed by: jake
GPG key ID: 57AFB45680EDD477
3 changed files with 142 additions and 5 deletions

View file

@ -0,0 +1,8 @@
from website.common.factories import BaseContentFactory
from .models import SearchPage
class SearchPageFactory(BaseContentFactory):
class Meta:
model = SearchPage

View file

@ -1,7 +1,7 @@
from django.core.paginator import EmptyPage, Paginator from django.core.paginator import EmptyPage, Paginator
from django.http.request import HttpRequest from django.http.request import HttpRequest
from django.http.response import HttpResponse, HttpResponseBadRequest from django.http.response import Http404, HttpResponse, HttpResponseBadRequest
from django.shortcuts import render from django.template.response import TemplateResponse
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.views.decorators.http import require_GET from django.views.decorators.http import require_GET
@ -46,7 +46,7 @@ class SearchPage(RoutablePageMixin, BaseContentPage):
serializer = SearchParamsSerializer(data=request.GET) serializer = SearchParamsSerializer(data=request.GET)
if not serializer.is_valid(): if not serializer.is_valid():
return render( return TemplateResponse(
request, request,
"search/enter-search-term.html", "search/enter-search-term.html",
{"MIN_SEARCH_LENGTH": MIN_SEARCH_LENGTH}, {"MIN_SEARCH_LENGTH": MIN_SEARCH_LENGTH},
@ -82,8 +82,8 @@ class SearchPage(RoutablePageMixin, BaseContentPage):
) )
except EmptyPage: except EmptyPage:
results = [] raise Http404
context["results"] = results context["results"] = results
return render(request, "search/search_results.html", context) return TemplateResponse(request, "search/search_results.html", context)

129
website/search/tests.py Normal file
View file

@ -0,0 +1,129 @@
from bs4 import BeautifulSoup
from django.test import TestCase
from website.common.factories import ContentPageFactory
from website.home.models import HomePage
from .factories import SearchPageFactory
from .models import SearchPage
class SearchPageTestCase(TestCase):
@classmethod
def setUpTestData(cls) -> None:
cls.home_page = HomePage.objects.get()
cls.page = SearchPageFactory(parent=cls.home_page)
def test_accessible(self) -> None:
response = self.client.get(self.page.url)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.context["search_url"], "results/")
self.assertEqual(response.context["MIN_SEARCH_LENGTH"], 3)
def test_initial_query(self) -> None:
response = self.client.get(self.page.url, {"q": "post 1"})
self.assertEqual(response.context["search_query"], "post 1")
self.assertTemplateNotUsed(response, "search/enter-search-term.html")
search_input = BeautifulSoup(response.content, "lxml").find("input")
self.assertEqual(search_input.attrs["value"], "post 1")
def test_search_input(self) -> None:
response = self.client.get(self.page.url)
self.assertEqual(response.status_code, 200)
soup = BeautifulSoup(response.content, "lxml")
search_input = soup.find("input")
self.assertEqual(search_input.attrs["name"], "q")
self.assertEqual(search_input.attrs["hx-get"], "results/")
self.assertEqual(search_input.attrs["value"], "")
self.assertEqual(len(soup.select(search_input.attrs["hx-target"])), 1)
self.assertEqual(len(soup.select(search_input.attrs["hx-indicator"])), 1)
class SearchPageResultsTestCase(TestCase):
@classmethod
def setUpTestData(cls) -> None:
cls.home_page = HomePage.objects.get()
cls.page = SearchPageFactory(parent=cls.home_page)
for i in range(SearchPage.PAGE_SIZE + 1):
ContentPageFactory(parent=cls.home_page, title=f"Post {i}")
cls.url = cls.page.url + cls.page.reverse_subpage("results")
def test_returns_results(self) -> None:
with self.assertNumQueries(11):
response = self.client.get(self.url, {"q": "post"}, HTTP_HX_REQUEST="true")
self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.context["results"]), SearchPage.PAGE_SIZE)
self.assertEqual(response.context["paginator"].count, SearchPage.PAGE_SIZE + 1)
self.assertEqual(response.context["search_query"], "post")
self.assertEqual(response.context["page_num"], 1)
def test_page_trigger(self) -> None:
response = self.client.get(self.url, {"q": "post"}, HTTP_HX_REQUEST="true")
self.assertEqual(response.status_code, 200)
trigger = BeautifulSoup(response.content, "lxml").find(
"span", attrs={"hx-trigger": "revealed"}
)
self.assertEqual(trigger.attrs["hx-swap"], "outerHTML")
self.assertEqual(trigger.attrs["hx-get"], "results/?q=post&page=2")
def test_pagination(self) -> None:
response = self.client.get(
self.url, {"q": "post", "page": 2}, HTTP_HX_REQUEST="true"
)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.context["page_num"], 2)
self.assertEqual(len(response.context["results"]), 1)
self.assertIsNone(
BeautifulSoup(response.content, "lxml").find(
"span", attrs={"hx-trigger": "revealed"}
)
)
def test_too_high_page(self) -> None:
with self.assertNumQueries(46):
response = self.client.get(
self.url, {"q": "post", "page": 3}, HTTP_HX_REQUEST="true"
)
self.assertEqual(response.status_code, 404)
def test_returns_result(self) -> None:
response = self.client.get(self.url, {"q": "post 1"}, HTTP_HX_REQUEST="true")
self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.context["results"]), 1)
self.assertEqual(list(response.context["results"])[0].title, "Post 1")
def test_no_results(self) -> None:
response = self.client.get(self.url, {"q": "nothing"}, HTTP_HX_REQUEST="true")
self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.context["results"]), 0)
self.assertContains(response, "No results found")
def test_no_query(self) -> None:
with self.assertNumQueries(7):
response = self.client.get(self.url, HTTP_HX_REQUEST="true")
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, "search/enter-search-term.html")
def test_empty_query(self) -> None:
with self.assertNumQueries(7):
response = self.client.get(self.url, {"q": ""}, HTTP_HX_REQUEST="true")
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, "search/enter-search-term.html")
def test_not_htmx(self) -> None:
with self.assertNumQueries(7):
response = self.client.get(self.url)
self.assertEqual(response.status_code, 400)