Skip to content

Commit

Permalink
Convert search view to class-based view
Browse files Browse the repository at this point in the history
  • Loading branch information
clairempr committed Apr 16, 2022
1 parent 1c2efc9 commit b1e65cc
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 19 deletions.
4 changes: 2 additions & 2 deletions letterpress/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from django.conf.urls import include, url
from django.contrib.auth import views as auth_views
from letters.views import export, GetStatsView, GetTextSentimentView, GetWordCloudView, letter_by_id, \
LetterSentimentView, LettersView, logout_view, place_by_id, places_view, random_letter, search, search_places, \
LetterSentimentView, LettersView, logout_view, place_by_id, places_view, random_letter, SearchView, search_places, \
SentimentView, StatsView, TextSentimentView, WordCloudView
from letterpress.views import HomeView

Expand All @@ -24,7 +24,7 @@
url(r'^letters/(?P<letter_id>[0-9]+)/$', letter_by_id, name='letter_by_id'),
url(r'^letters/', LettersView.as_view(), name='letters_view'),
url(r'^search_places/', search_places, name='search_places'),
url(r'^search/', search, name='search'),
url(r'^search/', SearchView.as_view(), name='search'),
url(r'^random_letter/', random_letter, name='random_letter'),
url(r'^stats/', StatsView.as_view(), name='stats_view'),
url(r'^get_stats/', GetStatsView.as_view(), name='get_stats'),
Expand Down
35 changes: 18 additions & 17 deletions letters/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from letters.tests.factories import LetterFactory, PlaceFactory
from letters.views import export, export_csv, export_text, get_letter_export_text, GetStatsView, GetTextSentimentView, \
GetWordCloudView, highlight_for_sentiment, highlight_letter_for_sentiment, LettersView, object_not_found, \
random_letter, search, search_places, show_letter_content, get_highlighted_letter_sentiment
random_letter, SearchView, search_places, show_letter_content, get_highlighted_letter_sentiment


class LettersViewTestCase(SimpleTestCase):
Expand Down Expand Up @@ -526,20 +526,21 @@ def test_highlight_for_sentiment(self, mock_highlight_for_custom_sentiment, mock
mock_highlight_for_custom_sentiment.reset_mock()


class SearchTestCase(TestCase):
class SearchViewTestCase(TestCase):
"""
Test search()
Test SearchView
"""

@patch('letters.views.letter_search.do_letter_search')
def test_search(self, mock_do_letter_search):
def test_search_view(self, mock_do_letter_search):
"""
search() should return list of letters containing search text
SearchView should return list of letters containing search text
"""

# GET request should raise ValueError
with self.assertRaises(ValueError):
self.client.get(reverse('search'), follow=True)
# GET request should return HttpResponseNotAllowed
response = self.client.get(reverse('search'), follow=True)
self.assertEqual(response.status_code, 405,
'Making a GET request to SearchView should return HttpResponseNotAllowed')

letter = LetterFactory()

Expand All @@ -556,40 +557,40 @@ def test_search(self, mock_do_letter_search):

# If search_text is supplied, the size passed to do_letter_search() should be 5
request.POST = {'page_number': '1', 'search_text': 'Bacon ipsum dolor amet ball tip salami kielbasa'}
search(request)
SearchView().dispatch(request)

args, kwargs = mock_do_letter_search.call_args
self.assertEqual(args, (request, 5, 1),
'If search_text supplied to search(), the size passed to do_letter_search() should be 5')
'If search_text supplied to SearchView, the size passed to do_letter_search() should be 5')
mock_do_letter_search.reset_mock()

# If search_text not supplied, the size passed to do_letter_search() should be 10
request.POST = {'page_number': '1'}
response = search(request)
response = SearchView().dispatch(request)

args, kwargs = mock_do_letter_search.call_args
self.assertEqual(args, (request, 10, 1),
'If search_text not supplied to search(), the size passed to do_letter_search() should be 10')
'If search_text not supplied to SearchView, the size passed to do_letter_search() should be 10')
mock_do_letter_search.reset_mock()

# response content['pages'] should contain do_letter_search() result.pages
# and response content['letters'] should contain letter from do_letter_search() result.search_results
content = json.loads(response.content.decode('utf-8'))
self.assertEqual(content['pages'], mock_do_letter_search.return_value.pages,
"search() response content['pages'] should contain do_letter_search() result.pages")
"SearchView response content['pages'] should contain do_letter_search() result.pages")
self.assertTrue(str(letter.writer) in content['letters'],
"search() response content['letters'] should contain letter found by do_letter_search()")
"SearchView response content['letters'] should contain letter found by do_letter_search()")

# If page_number isn't 0, response content['pagination'] should be empty string
self.assertEqual(content['pagination'], '',
"search() response content['pagination'] should be empty string if page_number isn't 0")
"SearchView response content['pagination'] should be empty string if page_number isn't 0")

# If page_number is 0, response content['pagination'] shouldn't be empty string
request.POST = {'page_number': '0'}
response = search(request)
response = SearchView().dispatch(request)
content = json.loads(response.content.decode('utf-8'))
self.assertNotEqual(content['pagination'], '',
"search() response content['pagination'] shouldn't be empty string if page_number is 0")
"SearchView response content['pagination'] shouldn't be empty string if page_number is 0")


class LetterByIdTestCase(TestCase):
Expand Down
30 changes: 30 additions & 0 deletions letters/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,36 @@ def highlight_for_sentiment(text, sentiment_id):
return [mark_safe(highlight_for_custom_sentiment(text, sentiment_id))]


class SearchView(View):
"""
Return list of letters containing search text
page_number is optional
"""

def post(self, request, *args, **kwargs):
if request.POST.get('search_text'):
size = 5
else:
size = 10
page_number = int(request.POST.get('page_number'))
es_result = letter_search.do_letter_search(request, size, page_number)
result_html = render_to_string('snippets/search_list.html', {'search_results': es_result.search_results})
# First request, no pagination yet
if page_number == 0:
# There is no built-in way to do something N times in a django template,
# so generate a string of length <es_result.pages> and use that in the template
# Yes, it's silly, but it's simpler than adding another template filter
pages_string = 'x' * es_result.pages
pagination_html = render_to_string('snippets/pagination.html',
{'pages': pages_string, 'total': es_result.total})
else:
pagination_html = ''
# This was Ajax
return HttpResponse(json.dumps({
'letters': result_html, 'pagination': pagination_html, 'pages': es_result.pages}),
content_type="application/json")


# return list of letters containing search text
# page_number is optional
def search(request):
Expand Down

0 comments on commit b1e65cc

Please sign in to comment.