From c9bdb433268330df1ff711a6c74ad8721d269e65 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Tue, 11 Feb 2014 12:34:04 +0000 Subject: [PATCH 01/12] Search: Unit tests --- wagtail/wagtailsearch/models.py | 3 +++ wagtail/wagtailsearch/tests.py | 36 +++++++++++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/wagtail/wagtailsearch/models.py b/wagtail/wagtailsearch/models.py index 79aa38f511..5b4a78a171 100644 --- a/wagtail/wagtailsearch/models.py +++ b/wagtail/wagtailsearch/models.py @@ -21,6 +21,9 @@ class Query(models.Model): daily_hits.hits = models.F('hits') + 1 daily_hits.save() + def __unicode__(self): + return self.query_string + @property def hits(self): return self.daily_hits.aggregate(models.Sum('hits'))['hits__sum'] diff --git a/wagtail/wagtailsearch/tests.py b/wagtail/wagtailsearch/tests.py index ca6e71994a..388368a369 100644 --- a/wagtail/wagtailsearch/tests.py +++ b/wagtail/wagtailsearch/tests.py @@ -1,12 +1,12 @@ from django.test import TestCase import models -from wagtail.wagtailsearch.backends import get_search_backend() +from wagtail.wagtailsearch.backends import get_search_backend class TestSearch(TestCase): def test_search(self): - # Create search backend and reset the index + # Get search backend and reset the index s = get_search_backend() s.reset_index() @@ -48,3 +48,35 @@ class TestSearch(TestCase): # Searcher search on child results = models.SearchTestChild.title_search("Hello") self.assertEqual(len(results), 1) + + def test_hit_counter(self): + # Add 10 hits to hello query + for i in range(10): + models.Query.get("Hello").add_hit() + + # Check that each hit was registered + self.assertEqual(models.Query.get("Hello").hits, 10) + + def test_query_string_normalisation(self): + # Get a query + query = models.Query.get("Hello World!") + + # Check queries that should be the same + self.assertEqual(query, models.Query.get("Hello World")) + self.assertEqual(query, models.Query.get("Hello World!!")) + self.assertEqual(query, models.Query.get("hello world")) + self.assertEqual(query, models.Query.get("Hello' world")) + + # Check queries that should be different + self.assertNotEqual(query, models.Query.get("HelloWorld")) + self.assertNotEqual(query, models.Query.get("Hello orld!!")) + self.assertNotEqual(query, models.Query.get("Hello")) + + def test_popularity(self): + pass + + def test_editors_picks(self): + pass + + def test_garbage_collect(self): + pass \ No newline at end of file From e7174e75a0267f612225b7bcf8607b4c08fbd0b3 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Tue, 11 Feb 2014 12:39:52 +0000 Subject: [PATCH 02/12] Search: Fixed issue with query string normalisation not removing double spaces --- wagtail/wagtailsearch/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wagtail/wagtailsearch/models.py b/wagtail/wagtailsearch/models.py index 5b4a78a171..4b36cc93bb 100644 --- a/wagtail/wagtailsearch/models.py +++ b/wagtail/wagtailsearch/models.py @@ -52,7 +52,7 @@ class Query(models.Model): query_string = ''.join([c for c in query_string if c not in string.punctuation]) # Remove double spaces - ' '.join(query_string.split()) + query_string = ' '.join(query_string.split()) return query_string From dacdacfc0da218fdd1585583b49c97160f5b536b Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Tue, 11 Feb 2014 13:02:25 +0000 Subject: [PATCH 03/12] More unit tests --- wagtail/wagtailsearch/models.py | 7 ++- wagtail/wagtailsearch/tests.py | 81 ++++++++++++++++++++++++++++++++- 2 files changed, 85 insertions(+), 3 deletions(-) diff --git a/wagtail/wagtailsearch/models.py b/wagtail/wagtailsearch/models.py index 4b36cc93bb..2becb556a5 100644 --- a/wagtail/wagtailsearch/models.py +++ b/wagtail/wagtailsearch/models.py @@ -16,8 +16,10 @@ class Query(models.Model): super(Query, self).save(*args, **kwargs) - def add_hit(self): - daily_hits, created = QueryDailyHits.objects.get_or_create(query=self, date=timezone.now().date()) + def add_hit(self, date=None): + if date is None: + date = timezone.now().date() + daily_hits, created = QueryDailyHits.objects.get_or_create(query=self, date=date) daily_hits.hits = models.F('hits') + 1 daily_hits.save() @@ -41,6 +43,7 @@ class Query(models.Model): @classmethod def get_most_popular(cls, date_since=None): + # TODO: Implement date_since return cls.objects.filter(daily_hits__isnull=False).annotate(_hits=models.Sum('daily_hits__hits')).distinct().order_by('-_hits') @staticmethod diff --git a/wagtail/wagtailsearch/tests.py b/wagtail/wagtailsearch/tests.py index 388368a369..a275a24fc1 100644 --- a/wagtail/wagtailsearch/tests.py +++ b/wagtail/wagtailsearch/tests.py @@ -1,4 +1,7 @@ from django.test import TestCase +from django.utils import timezone +import datetime +import unittest import models from wagtail.wagtailsearch.backends import get_search_backend @@ -49,6 +52,9 @@ class TestSearch(TestCase): results = models.SearchTestChild.title_search("Hello") self.assertEqual(len(results), 1) + def test_backend_loader(self): + pass + def test_hit_counter(self): # Add 10 hits to hello query for i in range(10): @@ -73,7 +79,80 @@ class TestSearch(TestCase): self.assertNotEqual(query, models.Query.get("Hello")) def test_popularity(self): - pass + # Add 3 hits to unpopular query + for i in range(3): + models.Query.get("unpopular query").add_hit() + + # Add 10 hits to popular query + for i in range(10): + models.Query.get("popular query").add_hit() + + # Get most popular queries + popular_queries = models.Query.get_most_popular() + + # Check list + self.assertEqual(popular_queries.count(), 2) + self.assertEqual(popular_queries[0], models.Query.get("popular query")) + self.assertEqual(popular_queries[1], models.Query.get("unpopular query")) + + # Add 5 hits to little popular query + for i in range(5): + models.Query.get("little popular query").add_hit() + + # Check list again, little popular query should be in the middle + self.assertEqual(popular_queries.count(), 3) + self.assertEqual(popular_queries[0], models.Query.get("popular query")) + self.assertEqual(popular_queries[1], models.Query.get("little popular query")) + self.assertEqual(popular_queries[2], models.Query.get("unpopular query")) + + # Unpopular query goes viral! + for i in range(20): + models.Query.get("unpopular query").add_hit() + + # Unpopular query should be most popular now + self.assertEqual(popular_queries.count(), 3) + self.assertEqual(popular_queries[0], models.Query.get("unpopular query")) + self.assertEqual(popular_queries[1], models.Query.get("popular query")) + self.assertEqual(popular_queries[2], models.Query.get("little popular query")) + + @unittest.expectedFailure # Time based popularity isn't implemented yet + def test_popularity_over_time(self): + today = timezone.now().date() + two_days_ago = today - datetime.timedelta(days=2) + a_week_ago = today - datetime.timedelta(days=7) + a_month_ago = today - datetime.timedelta(days=30) + + # Add 10 hits to a query that was very popular query a month ago + for i in range(10): + models.Query.get("old popular query").add_hit(date=a_month_ago) + + # Add 5 hits to a query that is was popular 2 days ago + for i in range(5): + models.Query.get("new popular query").add_hit(date=two_days_ago) + + # Get most popular queries + popular_queries = models.Query.get_most_popular() + + # Old popular query should be most popular + self.assertEqual(popular_queries.count(), 2) + self.assertEqual(popular_queries[0], models.Query.get("old popular query")) + self.assertEqual(popular_queries[1], models.Query.get("new popular query")) + + # Get most popular queries for past week + past_week_popular_queries = models.Query.get_most_popular(date_since=a_week_ago) + + # Only new popular query should be in this list + self.assertEqual(past_week_popular_queries.count(), 1) + self.assertEqual(past_week_popular_queries[0], models.Query.get("new popular query")) + + # Old popular query gets a couple more hits! + for i in range(2): + models.Query.get("old popular query").add_hit() + + # Old popular query should now be in the most popular queries + self.assertEqual(past_week_popular_queries.count(), 2) + self.assertEqual(past_week_popular_queries[0], models.Query.get("new popular query")) + self.assertEqual(past_week_popular_queries[1], models.Query.get("old popular query")) def test_editors_picks(self): pass From ae6bd25d179abd5b1220ab3c790973ce619dd4f7 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Tue, 11 Feb 2014 13:46:13 +0000 Subject: [PATCH 04/12] Search: Various tweaks to backend importer --- wagtail/wagtailsearch/backends/__init__.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/wagtail/wagtailsearch/backends/__init__.py b/wagtail/wagtailsearch/backends/__init__.py index ee037497b5..b1b991066b 100644 --- a/wagtail/wagtailsearch/backends/__init__.py +++ b/wagtail/wagtailsearch/backends/__init__.py @@ -4,7 +4,9 @@ from importlib import import_module from django.utils import six +import sys from django.conf import settings +from base import InvalidSearchBackendError # Pinched from django 1.7 source code. @@ -45,8 +47,13 @@ def get_search_backend(backend='default', **kwargs): # Try to get the WAGTAILSEARCH_BACKENDS entry for the given backend name first conf = WAGTAILSEARCH_BACKENDS[backend] except KeyError: - raise InvalidSearchBackendError("Could not find backend '%s': %s" % ( - backend, e)) + try: + # Trying to import the given backend, in case it's a dotted path + import_string(backend) + except ImportError as e: + raise InvalidSearchBackendError("Could not find backend '%s': %s" % ( + backend, e)) + params = kwargs else: # Backend is a conf entry params = conf.copy() From daa1f7fd9cdcdf3ece20731fea1358b725a19a37 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Tue, 11 Feb 2014 13:46:38 +0000 Subject: [PATCH 05/12] Search: more unit tests --- wagtail/wagtailsearch/tests.py | 41 ++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/wagtail/wagtailsearch/tests.py b/wagtail/wagtailsearch/tests.py index a275a24fc1..9e9782fa89 100644 --- a/wagtail/wagtailsearch/tests.py +++ b/wagtail/wagtailsearch/tests.py @@ -6,11 +6,36 @@ import unittest import models from wagtail.wagtailsearch.backends import get_search_backend +from wagtail.wagtailsearch.backends.base import InvalidSearchBackendError +from wagtail.wagtailsearch.backends.db import DBSearch +from wagtail.wagtailsearch.backends.elasticsearch import ElasticSearch +from django.conf import settings + +def find_backend(cls): + if not hasattr(settings, 'WAGTAILSEARCH_BACKENDS') and cls == DBSearch: + return 'default' + + for backend in settings.WAGTAILSEARCH_BACKENDS.keys(): + if isinstance(get_search_backend(backend), cls): + return backend + class TestSearch(TestCase): - def test_search(self): + def test_backend_loader(self): + # Test DB backend import + db = get_search_backend(backend='wagtail.wagtailsearch.backends.db.DBSearch') + self.assertIsInstance(db, DBSearch) + + # Test Elastic search backend import + elasticsearch = get_search_backend(backend='wagtail.wagtailsearch.backends.elasticsearch.ElasticSearch') + self.assertIsInstance(elasticsearch, ElasticSearch) + + # Test loading a non existant backend + self.assertRaises(InvalidSearchBackendError, get_search_backend, backend='wagtail.wagtailsearch.backends.doesntexist.DoesntExist') + + def test_search(self, backend='default'): # Get search backend and reset the index - s = get_search_backend() + s = get_search_backend(backend=backend) s.reset_index() # Create a couple of objects and add them to the index @@ -52,8 +77,16 @@ class TestSearch(TestCase): results = models.SearchTestChild.title_search("Hello") self.assertEqual(len(results), 1) - def test_backend_loader(self): - pass + def test_db_backend(self): + self.test_search(backend='wagtail.wagtailsearch.backends.db.DBSearch') + + def test_elastic_search_backend(self): + backend = find_backend(ElasticSearch) + + if backend is not None: + self.test_search(backend) + else: + print "WARNING: Cannot find an ElasticSearch search backend in configuration. Not testing." def test_hit_counter(self): # Add 10 hits to hello query From f8d2c0bc81f476bfdf8f646805603973ca6f3032 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Tue, 11 Feb 2014 14:28:20 +0000 Subject: [PATCH 06/12] update_index command is now callable from unit tests --- .../wagtailsearch/backends/elasticsearch.py | 4 ++- .../management/commands/update_index.py | 35 +++++++++++++------ 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/wagtail/wagtailsearch/backends/elasticsearch.py b/wagtail/wagtailsearch/backends/elasticsearch.py index 56fa2b04dd..00c1bda0e9 100644 --- a/wagtail/wagtailsearch/backends/elasticsearch.py +++ b/wagtail/wagtailsearch/backends/elasticsearch.py @@ -178,9 +178,11 @@ class ElasticSearch(BaseSearch): type_set[obj_type].append(obj.indexed_build_document()) # Loop through each type and bulk add them + results = [] for type_name, type_objects in type_set.items(): - print type_name, len(type_objects) + results.append((type_name, len(type_objects))) self.es.bulk_index(self.es_index, type_name, type_objects) + return results def delete(self, obj): # Object must be a decendant of Indexed and be a django model diff --git a/wagtail/wagtailsearch/management/commands/update_index.py b/wagtail/wagtailsearch/management/commands/update_index.py index 7e901bf813..e9c6fdd96e 100644 --- a/wagtail/wagtailsearch/management/commands/update_index.py +++ b/wagtail/wagtailsearch/management/commands/update_index.py @@ -1,13 +1,19 @@ -from django.core.management.base import NoArgsCommand +from django.core.management.base import BaseCommand from django.db import models from wagtail.wagtailsearch import Indexed, get_search_backend -class Command(NoArgsCommand): - def handle_noargs(self, **options): +class Command(BaseCommand): + def handle(self, backend='default', **options): + # Check of we need to be quiet + quiet = False + if 'quiet' in options and options['quiet']: + quiet = True + # Print info - print "Getting object list" + if not quiet: + print "Getting object list" # Get list of indexed models indexed_models = [model for model in models.get_models() if issubclass(model, Indexed)] @@ -46,21 +52,30 @@ class Command(NoArgsCommand): object_set[key] = obj # Search backend - s = get_search_backend() + s = get_search_backend(backend=backend) # Reset the index - print "Reseting index" + if not quiet: + print "Reseting index" s.reset_index() # Add types - print "Adding types" + if not quiet: + print "Adding types" for model in indexed_models: s.add_type(model) # Add objects to index - print "Adding objects" - s.add_bulk(object_set.values()) + if not quiet: + print "Adding objects" + results = s.add_bulk(object_set.values()) + + # Print results + if not quiet and results: + for result in results: + print result[0], result[1] # Refresh index - print "Refreshing index" + if not quiet: + print "Refreshing index" s.refresh_index() From cb1a412c3c52e3ff56d016fe591401bb557782f7 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Tue, 11 Feb 2014 14:28:47 +0000 Subject: [PATCH 07/12] DB backend now doesnt attempt to search on callable fields --- wagtail/wagtailsearch/backends/db.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/wagtail/wagtailsearch/backends/db.py b/wagtail/wagtailsearch/backends/db.py index ad16b082bf..419d8a99be 100644 --- a/wagtail/wagtailsearch/backends/db.py +++ b/wagtail/wagtailsearch/backends/db.py @@ -47,6 +47,13 @@ class DBSearch(BaseSearch): for term in terms: term_query = None for field_name in fields: + # Check if the field exists (this will filter out indexed callables) + try: + model._meta.get_field_by_name(field_name) + except: + continue + + # Filter on this field field_filter = {'%s__icontains' % field_name: term} if term_query is None: term_query = models.Q(**field_filter) From 9db3e1ce5b0343fbe8787155304e8fe8bfdabfdc Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Tue, 11 Feb 2014 14:29:36 +0000 Subject: [PATCH 08/12] More improvements to unit tests --- wagtail/wagtailsearch/models.py | 10 +++++++++- wagtail/wagtailsearch/tests.py | 34 +++++++++++++++++++++++++++++---- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/wagtail/wagtailsearch/models.py b/wagtail/wagtailsearch/models.py index 2becb556a5..8527cfe579 100644 --- a/wagtail/wagtailsearch/models.py +++ b/wagtail/wagtailsearch/models.py @@ -96,10 +96,18 @@ class SearchTest(models.Model, Indexed): title = models.CharField(max_length=255) content = models.TextField() - indexed_fields = ("title", "content") + indexed_fields = ("title", "content", "callable_indexed_field") title_search = Searcher(["title"]) + def object_indexed(self): + if self.title == "Don't index me!": + return False + return True + + def callable_indexed_field(self): + return "Callable" + class SearchTestChild(SearchTest): extra_content = models.TextField() diff --git a/wagtail/wagtailsearch/tests.py b/wagtail/wagtailsearch/tests.py index 9e9782fa89..6939cafadd 100644 --- a/wagtail/wagtailsearch/tests.py +++ b/wagtail/wagtailsearch/tests.py @@ -1,15 +1,18 @@ from django.test import TestCase from django.utils import timezone +from django.core import management +from django.conf import settings + import datetime import unittest -import models +from wagtail.wagtailsearch import models from wagtail.wagtailsearch.backends import get_search_backend from wagtail.wagtailsearch.backends.base import InvalidSearchBackendError from wagtail.wagtailsearch.backends.db import DBSearch from wagtail.wagtailsearch.backends.elasticsearch import ElasticSearch -from django.conf import settings + def find_backend(cls): if not hasattr(settings, 'WAGTAILSEARCH_BACKENDS') and cls == DBSearch: @@ -21,6 +24,11 @@ def find_backend(cls): class TestSearch(TestCase): + def __init__(self, *args, **kwargs): + super(TestSearch, self).__init__(*args, **kwargs) + + self.backends_tested = [] + def test_backend_loader(self): # Test DB backend import db = get_search_backend(backend='wagtail.wagtailsearch.backends.db.DBSearch') @@ -34,6 +42,11 @@ class TestSearch(TestCase): self.assertRaises(InvalidSearchBackendError, get_search_backend, backend='wagtail.wagtailsearch.backends.doesntexist.DoesntExist') def test_search(self, backend='default'): + # Don't test the same backend more than once! + if backend in self.backends_tested: + return + self.backends_tested.append(backend) + # Get search backend and reset the index s = get_search_backend(backend=backend) s.reset_index() @@ -61,7 +74,7 @@ class TestSearch(TestCase): results = s.search("Hello", models.SearchTest) self.assertEqual(len(results), 3) - # Ordinary search on "World" + # Ordinary search on "World" results = s.search("World", models.SearchTest) self.assertEqual(len(results), 1) @@ -77,6 +90,16 @@ class TestSearch(TestCase): results = models.SearchTestChild.title_search("Hello") self.assertEqual(len(results), 1) + # Reset the index, this should clear out the index (but doesn't have to!) + s.reset_index() + + # Run update_index command + management.call_command('update_index', backend, interactive=False, quiet=True) + + # Should have results again now + results = s.search("Hello", models.SearchTest) + self.assertEqual(len(results), 3) + def test_db_backend(self): self.test_search(backend='wagtail.wagtailsearch.backends.db.DBSearch') @@ -191,4 +214,7 @@ class TestSearch(TestCase): pass def test_garbage_collect(self): - pass \ No newline at end of file + pass + + def test_suggestions(self): + pass From c159e273f91694b4d876a5c24bc109dc67e8a0b2 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Tue, 11 Feb 2014 15:21:21 +0000 Subject: [PATCH 09/12] Added multi backend support into searcher --- wagtail/wagtailsearch/searcher.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/wagtail/wagtailsearch/searcher.py b/wagtail/wagtailsearch/searcher.py index 24510c257b..0861390fcd 100644 --- a/wagtail/wagtailsearch/searcher.py +++ b/wagtail/wagtailsearch/searcher.py @@ -8,7 +8,17 @@ class Searcher(object): def __get__(self, instance, cls): def dosearch(query_string, **kwargs): + # Get backend + if 'backend' in kwargs: + backend = kwargs['backend'] + del kwargs['backend'] + else: + backend = 'default' + + # Build search kwargs search_kwargs = dict(model=cls, fields=self.fields, filters=self.filters) search_kwargs.update(kwargs) - return get_search_backend().search(query_string, **search_kwargs) + + # Run search + return get_search_backend(backend=backend).search(query_string, **search_kwargs) return dosearch From c80956521705aef54830ef407b24e3597786ef93 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Tue, 11 Feb 2014 15:21:54 +0000 Subject: [PATCH 10/12] Search: Use self.stdout.write for messages in management commands --- .../commands/search_garbage_collect.py | 8 +++--- .../management/commands/update_index.py | 26 +++++-------------- 2 files changed, 11 insertions(+), 23 deletions(-) diff --git a/wagtail/wagtailsearch/management/commands/search_garbage_collect.py b/wagtail/wagtailsearch/management/commands/search_garbage_collect.py index ae37534b4b..08d8d8c1b5 100644 --- a/wagtail/wagtailsearch/management/commands/search_garbage_collect.py +++ b/wagtail/wagtailsearch/management/commands/search_garbage_collect.py @@ -6,11 +6,11 @@ from wagtail.wagtailsearch import models class Command(NoArgsCommand): def handle_noargs(self, **options): # Clean daily hits - print "Cleaning daily hits records... ", + self.stdout.write("Cleaning daily hits records... ") models.QueryDailyHits.garbage_collect() - print "Done" + self.stdout.write("Done") # Clean queries - print "Cleaning query records... ", + self.stdout.write("Cleaning query records... ") models.Query.garbage_collect() - print "Done" + self.stdout.write("Done") diff --git a/wagtail/wagtailsearch/management/commands/update_index.py b/wagtail/wagtailsearch/management/commands/update_index.py index e9c6fdd96e..522e206236 100644 --- a/wagtail/wagtailsearch/management/commands/update_index.py +++ b/wagtail/wagtailsearch/management/commands/update_index.py @@ -6,14 +6,8 @@ from wagtail.wagtailsearch import Indexed, get_search_backend class Command(BaseCommand): def handle(self, backend='default', **options): - # Check of we need to be quiet - quiet = False - if 'quiet' in options and options['quiet']: - quiet = True - # Print info - if not quiet: - print "Getting object list" + self.stdout.write("Getting object list") # Get list of indexed models indexed_models = [model for model in models.get_models() if issubclass(model, Indexed)] @@ -55,27 +49,21 @@ class Command(BaseCommand): s = get_search_backend(backend=backend) # Reset the index - if not quiet: - print "Reseting index" + self.stdout.write("Reseting index") s.reset_index() # Add types - if not quiet: - print "Adding types" + self.stdout.write("Adding types") for model in indexed_models: s.add_type(model) # Add objects to index - if not quiet: - print "Adding objects" + self.stdout.write("Adding objects") results = s.add_bulk(object_set.values()) - - # Print results - if not quiet and results: + if results: for result in results: - print result[0], result[1] + self.stdout.write(result[0] + ' ' + str(result[1])) # Refresh index - if not quiet: - print "Refreshing index" + self.stdout.write("Refreshing index") s.refresh_index() From a3463c978728167562bea75cb5353844cc8b24f3 Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Tue, 11 Feb 2014 15:22:11 +0000 Subject: [PATCH 11/12] More unit tests changes --- wagtail/wagtailsearch/tests.py | 60 ++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 7 deletions(-) diff --git a/wagtail/wagtailsearch/tests.py b/wagtail/wagtailsearch/tests.py index 6939cafadd..d19cdcb68e 100644 --- a/wagtail/wagtailsearch/tests.py +++ b/wagtail/wagtailsearch/tests.py @@ -5,7 +5,9 @@ from django.conf import settings import datetime import unittest +from StringIO import StringIO +from wagtail.wagtailcore import models as core_models from wagtail.wagtailsearch import models from wagtail.wagtailsearch.backends import get_search_backend @@ -79,7 +81,7 @@ class TestSearch(TestCase): self.assertEqual(len(results), 1) # Searcher search - results = models.SearchTest.title_search("Hello") + results = models.SearchTest.title_search("Hello", backend=backend) self.assertEqual(len(results), 3) # Ordinary search on child @@ -87,14 +89,14 @@ class TestSearch(TestCase): self.assertEqual(len(results), 1) # Searcher search on child - results = models.SearchTestChild.title_search("Hello") + results = models.SearchTestChild.title_search("Hello", backend=backend) self.assertEqual(len(results), 1) # Reset the index, this should clear out the index (but doesn't have to!) s.reset_index() # Run update_index command - management.call_command('update_index', backend, interactive=False, quiet=True) + management.call_command('update_index', backend, interactive=False, stdout=StringIO()) # Should have results again now results = s.search("Hello", models.SearchTest) @@ -111,7 +113,7 @@ class TestSearch(TestCase): else: print "WARNING: Cannot find an ElasticSearch search backend in configuration. Not testing." - def test_hit_counter(self): + def test_query_hit_counter(self): # Add 10 hits to hello query for i in range(10): models.Query.get("Hello").add_hit() @@ -134,7 +136,7 @@ class TestSearch(TestCase): self.assertNotEqual(query, models.Query.get("Hello orld!!")) self.assertNotEqual(query, models.Query.get("Hello")) - def test_popularity(self): + def test_query_popularity(self): # Add 3 hits to unpopular query for i in range(3): models.Query.get("unpopular query").add_hit() @@ -172,7 +174,7 @@ class TestSearch(TestCase): self.assertEqual(popular_queries[2], models.Query.get("little popular query")) @unittest.expectedFailure # Time based popularity isn't implemented yet - def test_popularity_over_time(self): + def test_query_popularity_over_time(self): today = timezone.now().date() two_days_ago = today - datetime.timedelta(days=2) a_week_ago = today - datetime.timedelta(days=7) @@ -211,7 +213,51 @@ class TestSearch(TestCase): self.assertEqual(past_week_popular_queries[1], models.Query.get("old popular query")) def test_editors_picks(self): - pass + # Get root page + root = core_models.Page.objects.first() + + # Create an editors pick to the root page + models.EditorsPick.objects.create( + query=models.Query.get("root page"), + page=root, + sort_order=0, + description="First editors pick", + ) + + # Get editors pick + self.assertEqual(models.Query.get("root page").editors_picks.count(), 1) + self.assertEqual(models.Query.get("root page").editors_picks.first().page, root) + + # Create a couple more editors picks to test the ordering + models.EditorsPick.objects.create( + query=models.Query.get("root page"), + page=root, + sort_order=2, + description="Last editors pick", + ) + models.EditorsPick.objects.create( + query=models.Query.get("root page"), + page=root, + sort_order=1, + description="Middle editors pick", + ) + + # Check + self.assertEqual(models.Query.get("root page").editors_picks.count(), 3) + self.assertEqual(models.Query.get("root page").editors_picks.first().description, "First editors pick") + self.assertEqual(models.Query.get("root page").editors_picks.last().description, "Last editors pick") + + # Add editors pick with different terms + models.EditorsPick.objects.create( + query=models.Query.get("root page 2"), + page=root, + sort_order=0, + description="Other terms", + ) + + # Check + self.assertEqual(models.Query.get("root page 2").editors_picks.count(), 1) + self.assertEqual(models.Query.get("root page").editors_picks.count(), 3) def test_garbage_collect(self): pass From e40265cf40ca791d12711e7739022128d085936b Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Tue, 11 Feb 2014 15:30:55 +0000 Subject: [PATCH 12/12] Search: test retrieval of results --- wagtail/wagtailsearch/tests.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/wagtail/wagtailsearch/tests.py b/wagtail/wagtailsearch/tests.py index d19cdcb68e..6849d3907f 100644 --- a/wagtail/wagtailsearch/tests.py +++ b/wagtail/wagtailsearch/tests.py @@ -76,6 +76,23 @@ class TestSearch(TestCase): results = s.search("Hello", models.SearchTest) self.assertEqual(len(results), 3) + # Retrieve single result + self.assertIsInstance(results[0], models.SearchTest) + + # Retrieve results through iteration + iterations = 0 + for result in results: + self.assertIsInstance(result, models.SearchTest) + iterations += 1 + self.assertEqual(iterations, 3) + + # Retrieve results through slice + iterations = 0 + for result in results[:]: + self.assertIsInstance(result, models.SearchTest) + iterations += 1 + self.assertEqual(iterations, 3) + # Ordinary search on "World" results = s.search("World", models.SearchTest) self.assertEqual(len(results), 1)