Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
89 changes: 89 additions & 0 deletions bakerydemo/search/tests/test_search_view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
from django.test import TestCase, override_settings
from django.urls import reverse
from wagtail.models import Page, Site

from bakerydemo.blog.models import BlogPage
from bakerydemo.breads.models import BreadPage
from bakerydemo.locations.models import LocationPage
from bakerydemo.recipes.models import RecipePage
from django.core.management import call_command

@override_settings(STORAGES={
"default": {"BACKEND": "django.core.files.storage.FileSystemStorage"},
"staticfiles": {"BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage"},
})
class SearchViewTest(TestCase):
@classmethod
def setUpTestData(cls):
root = Page.get_first_root_node()
cls.site = Site.objects.create(
hostname="testserver",
root_page=root,
is_default_site=True,
)
cls.recipe = RecipePage(
title="Hot Cross Bun", slug="hot-cross-bun", introduction="spiced bun"
)
root.add_child(instance=cls.recipe)
cls.recipe.save_revision().publish()

cls.blog = BlogPage(
title="Sourdough Guide", slug="sourdough-guide", introduction="sourdough"
)
root.add_child(instance=cls.blog)
cls.blog.save_revision().publish()

cls.bread = BreadPage(title="Rye Bread", slug="rye-bread", introduction="rye")
root.add_child(instance=cls.bread)
cls.bread.save_revision().publish()

cls.location = LocationPage(
title="Maputo Bakery",
slug="maputo-bakery",
address="123 Maputo St",
lat_long="-25.969248, 32.573289",
)
root.add_child(instance=cls.location)
cls.location.save_revision().publish()

call_command("update_index", verbosity=0)

def test_search_returns_200(self):
response = self.client.get(reverse("search"), {"q": "bread"})
self.assertEqual(response.status_code, 200)

def test_search_uses_correct_template(self):
response = self.client.get(reverse("search"), {"q": "bread"})
self.assertTemplateUsed(response, "search/search_results.html")

def test_empty_query_returns_200(self):
response = self.client.get(reverse("search"))
self.assertEqual(response.status_code, 200)

def test_empty_query_returns_no_results(self):
response = self.client.get(reverse("search"))
self.assertQuerySetEqual(response.context["search_results"], [])

def test_search_finds_blog_page(self):
response = self.client.get(reverse("search"), {"q": "sourdough"})
self.assertContains(response, "Sourdough Guide")

def test_search_finds_bread_page(self):
response = self.client.get(reverse("search"), {"q": "rye"})
self.assertContains(response, "Rye Bread")

def test_search_finds_location_page(self):
response = self.client.get(reverse("search"), {"q": "maputo"})
self.assertContains(response, "Maputo Bakery")

def test_fallback_search_preserves_ordering(self):
"""Merged fallback results should preserve the intended ID ordering via Case/When."""
response = self.client.get(reverse("search"), {"q": "bread"})
self.assertEqual(response.status_code, 200)
results = response.context["search_results"].object_list
ids = [p.id for p in results]
self.assertEqual(ids, sorted(ids, key=lambda pk: ids.index(pk)))

def test_search_finds_recipe_page(self):
response = self.client.get(reverse("search"), {"q": "hot cross bun"})
self.assertContains(response, "Hot Cross Bun")
30 changes: 17 additions & 13 deletions bakerydemo/search/views.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,24 @@
from django.conf import settings
from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
from django.db.models import Case, When
from django.shortcuts import render
from wagtail.contrib.search_promotions.models import Query
from wagtail.models import Page

from bakerydemo.blog.models import BlogPage
from bakerydemo.breads.models import BreadPage
from bakerydemo.locations.models import LocationPage
from bakerydemo.recipes.models import (
RecipePage, # fixed typo: bakerydemo not backerydemo
)


def search(request):
# Search
search_query = request.GET.get("q", None)
if search_query:
if "elasticsearch" in settings.WAGTAILSEARCH_BACKENDS["default"]["BACKEND"]:
# In production, use ElasticSearch and a simplified search query, per
# https://docs.wagtail.org/en/stable/topics/search/backends.html
# like this:
search_results = Page.objects.live().search(search_query)
else:
# If we aren't using ElasticSearch for the demo, fall back to native db search.
# But native DB search can't search specific fields in our models on a `Page` query.
# So for demo purposes ONLY, we hard-code in the model names we want to search.
blog_results = BlogPage.objects.live().search(search_query)
blog_page_ids = [p.page_ptr.id for p in blog_results]

Expand All @@ -31,18 +28,25 @@ def search(request):
location_results = LocationPage.objects.live().search(search_query)
location_result_ids = [p.page_ptr.id for p in location_results]

page_ids = blog_page_ids + bread_page_ids + location_result_ids
search_results = Page.objects.live().filter(id__in=page_ids)
recipe_results = RecipePage.objects.live().search(search_query) # added
recipe_page_ids = [p.page_ptr.id for p in recipe_results] # added

query = Query.get(search_query)
page_ids = (
blog_page_ids + bread_page_ids + location_result_ids + recipe_page_ids
) # added recipe_page_ids

# Record hit
query.add_hit()
preserved_order = Case(
*[When(id=pk, then=pos) for pos, pk in enumerate(page_ids)]
)
search_results = (
Page.objects.live().filter(id__in=page_ids).order_by(preserved_order)
)

query = Query.get(search_query)
query.add_hit()
else:
search_results = Page.objects.none()

# Pagination
page = request.GET.get("page", 1)
paginator = Paginator(search_results, 10)
try:
Expand Down