diff options
-rw-r--r-- | askbot/search/haystack/__init__.py | 83 | ||||
-rw-r--r-- | askbot/tests/__init__.py | 1 | ||||
-rw-r--r-- | askbot/tests/form_tests.py | 12 | ||||
-rw-r--r-- | askbot/tests/haystack_search_tests.py | 95 | ||||
-rw-r--r-- | askbot/tests/utils.py | 18 |
5 files changed, 153 insertions, 56 deletions
diff --git a/askbot/search/haystack/__init__.py b/askbot/search/haystack/__init__.py index 7927aa87..71f04d00 100644 --- a/askbot/search/haystack/__init__.py +++ b/askbot/search/haystack/__init__.py @@ -1,58 +1,59 @@ try: from haystack import indexes, site from haystack.query import SearchQuerySet -except ImportError: - pass + from askbot.models import Post, Thread, User -from askbot.models import Post, Thread, User -class ThreadIndex(indexes.SearchIndex): - text = indexes.CharField(document=True, use_template=True) - title = indexes.CharField(model_attr='title') - post_text = indexes.CharField(model_attr='posts__text__search') + class ThreadIndex(indexes.SearchIndex): + text = indexes.CharField(document=True, use_template=True) + title = indexes.CharField(model_attr='title') + post_text = indexes.CharField(model_attr='posts__text__search') - def index_queryset(self): - return Thread.objects.filter(posts__deleted=False) + def index_queryset(self): + return Thread.objects.filter(posts__deleted=False) - def prepare(self, obj): - self.prepared_data = super(ThreadIndex, self).prepare(object) + def prepare(self, obj): + self.prepared_data = super(ThreadIndex, self).prepare(object) - self.prepared_data['tags'] = [tag.name for tag in objects.tags.all()] + self.prepared_data['tags'] = [tag.name for tag in objects.tags.all()] -class PostIndex(indexes.SearchIndex): - text = indexes.CharField(document=True, use_template=True) - post_text = indexes.CharField(model_attr='text') - author = indexes.CharField(model_attr='user') - thread_id = indexes.CharField(model_attr='thread') + class PostIndex(indexes.SearchIndex): + text = indexes.CharField(document=True, use_template=True) + post_text = indexes.CharField(model_attr='text') + author = indexes.CharField(model_attr='user') + thread_id = indexes.CharField(model_attr='thread') - def index_queryset(self): - return Post.objects.filter(deleted=False) + def index_queryset(self): + return Post.objects.filter(deleted=False) -class UserIndex(indexes.SearchIndex): - text = indexes.CharField(document=True, use_template=True) + class UserIndex(indexes.SearchIndex): + text = indexes.CharField(document=True, use_template=True) - def index_queryset(self): - return User.objects.all() + def index_queryset(self): + return User.objects.all() -site.register(Post, PostIndex) -site.register(Thread, ThreadIndex) -site.register(User, UserIndex) + site.register(Post, PostIndex) + site.register(Thread, ThreadIndex) + site.register(User, UserIndex) -class AskbotSearchQuerySet(SearchQuerySet): + class AskbotSearchQuerySet(SearchQuerySet): - def get_django_queryset(self, model_klass=Thread): - '''dirty hack because models() method from the - SearchQuerySet does not work </3''' - id_list = [] - for r in self: - if r.model_name in ['thread','post'] \ - and model_klass._meta.object_name.lower() == 'thread': - if getattr(r, 'thread_id'): - id_list.append(r.thread_id) - else: + def get_django_queryset(self, model_klass=Thread): + '''dirty hack because models() method from the + SearchQuerySet does not work </3''' + id_list = [] + for r in self: + if r.model_name in ['thread','post'] \ + and model_klass._meta.object_name.lower() == 'thread': + if getattr(r, 'thread_id'): + id_list.append(r.thread_id) + else: + id_list.append(r.pk) + elif r.model_name == model_klass._meta.object_name.lower(): + #FIXME: add a highlight here? id_list.append(r.pk) - elif r.model_name == model_klass._meta.object_name.lower(): - #FIXME: add a highlight here? - id_list.append(r.pk) - return model_klass.objects.filter(id__in=set(id_list)) + return model_klass.objects.filter(id__in=set(id_list)) + +except: + pass diff --git a/askbot/tests/__init__.py b/askbot/tests/__init__.py index 1b25e064..1b8b703a 100644 --- a/askbot/tests/__init__.py +++ b/askbot/tests/__init__.py @@ -15,3 +15,4 @@ from askbot.tests.markup_test import * from askbot.tests.misc_tests import * from askbot.tests.post_model_tests import * from askbot.tests.reply_by_email_tests import * +from askbot.tests.haystack_search_tests import * diff --git a/askbot/tests/form_tests.py b/askbot/tests/form_tests.py index 654272b3..5bca5eac 100644 --- a/askbot/tests/form_tests.py +++ b/askbot/tests/form_tests.py @@ -72,8 +72,8 @@ class AskByEmailFormTests(AskbotTestCase): askbot_settings.update('TAGS_ARE_REQUIRED', setting_backup) def test_email(self): - """loops through variants of the from field - in the emails and tests the email address + """loops through variants of the from field + in the emails and tests the email address extractor""" for test_case in EMAIL_CASES: self.data['sender'] = test_case[0] @@ -178,7 +178,7 @@ class EditQuestionAnonymouslyFormTests(AskbotTestCase): def setup_data(self, is_anon, can_be_anon, is_owner, box_checked): """sets up data in the same order as shown in the truth table above - + the four positional arguments are in the same order """ askbot_settings.update('ALLOW_ASK_ANONYMOUSLY', can_be_anon) @@ -264,7 +264,7 @@ class UserStatusFormTest(AskbotTestCase): self.moderator.set_status('m') self.subject = self.create_user('normal_user') self.subject.set_status('a') - self.form = forms.ChangeUserStatusForm(data, moderator = self.moderator, + self.form = forms.ChangeUserStatusForm(data, moderator = self.moderator, subject = self.subject) def test_moderator_can_suspend_user(self): self.setup_data('s') @@ -292,7 +292,7 @@ class UserNameFieldTest(AskbotTestCase): self.username_field.skip_clean = True self.assertEquals(self.username_field.clean('bar'), 'bar')#will pass anything - self.username_field.skip_clean = False + self.username_field.skip_clean = False #will not pass b/c instance is not User model self.username_field.user_instance = dict(foo=1) @@ -328,7 +328,7 @@ class AnswerEditorFieldTests(AskbotTestCase): self.field.clean, 'a' ) - + def test_pass_long_body(self): self.assertEquals( self.field.clean(10*'a'), diff --git a/askbot/tests/haystack_search_tests.py b/askbot/tests/haystack_search_tests.py new file mode 100644 index 00000000..853f4683 --- /dev/null +++ b/askbot/tests/haystack_search_tests.py @@ -0,0 +1,95 @@ +"""Tests haystack indexes and queries""" +from django.core import exceptions +from django.conf import settings +from django.contrib.auth.models import User +from askbot.tests.utils import AskbotTestCase, skipIf +from askbot.search.haystack import AskbotSearchQuerySet +from askbot import models +import datetime + +class HaystackSearchTests(AskbotTestCase): + """tests methods on User object, + that were added for askbot + """ + def setUp(self): + self.user = self.create_user(username='gepeto') + self.other_user = self.create_user(username = 'pinocho') + self.other_user.location = 'Managua' + self.other_user.about = "I'm made of wood, gepeto made me" + self.other_user.save() + body_1 = '''Lorem turpis purus? Amet mattis eu et sociis phasellus + montes elementum proin ut urna enim, velit, tincidunt quis ut, + et integer mus? Nunc! Vut sed? Ac tincidunt egestas adipiscing, + magna et pulvinar mid est urna ultricies, turpis tristique nisi, + cum. Urna. Purus elit porttitor nisi porttitor ridiculus tincidunt + amet duis, gepeto''' + #from Baldy of Nome by Esther Birdsall Darling + body_2 = ''' With unseeing eyes and dragging steps, the boy trudged along the snowy + trail, dreading the arrival at Golconda Camp. For there was the House of + Judgment, where all of the unfortunate events of that most unhappy day + would be reviewed sternly, lorem''' + self.question1 = self.post_question( + user=self.user, + body_text=body_1, + title='Test title 1' + ) + self.question2 = self.post_question( + user=self.other_user, + body_text=body_2, + title='Test title 2, Baldy of Nome' + ) + self.answer1 = self.post_answer( + user=self.user, + question = self.question1, + body_text="This is a answer for question 1" + ) + self.answer1 = self.post_answer( + user=self.other_user, + question = self.question2, + body_text="Just a random text to fill the space" + ) + + @skipIf('haystack' not in settings.INSTALLED_APPS, + 'Haystack not setup') + def test_title_search(self): + #title search + title_search_qs = models.Thread.objects.get_for_query('title') + self.assertEquals(title_search_qs.count(), 2) + title_search_qs_2 = models.Thread.objects.get_for_query('Nome') + self.assertEquals(title_search_qs_2.count(), 1) + + @skipIf('haystack' not in settings.INSTALLED_APPS, + 'Haystack not setup') + def test_body_search(self): + + #bodysearch + body_search_qs = models.Thread.objects.get_for_query('Lorem') + self.assertEquals(body_search_qs.count(), 2) + body_search_qs_2 = models.Thread.objects.get_for_query('steps') + self.assertEquals(body_search_qs_2.count(), 1) + + @skipIf('haystack' not in settings.INSTALLED_APPS, + 'Haystack not setup') + def test_user_profile_search(self): + #must return pinocho + user_profile_qs = models.get_users_by_text_query('wood') + self.assertEquals(user_profile_qs.count(), 1) + + #returns both gepeto and pinocho because gepeto nickname + #and gepeto name in pinocho's profile + user_profile_qs = models.get_users_by_text_query('gepeto') + self.assertEquals(user_profile_qs.count(), 2) + + @skipIf('haystack' not in settings.INSTALLED_APPS, + 'Haystack not setup') + def test_get_django_queryset(self): + '''makes a query that can return multiple models and test + get_django_queryset() method from AskbotSearchQuerySet''' + #gepeto is present in profile and in question + qs = AskbotSearchQuerySet().filter(content='gepeto').get_django_queryset(User) + for instance in qs: + self.assertTrue(isinstance(instance, User)) + + qs = AskbotSearchQuerySet().filter(content='gepeto').get_django_queryset(models.Thread) + for instance in qs: + self.assertTrue(isinstance(instance, models.Thread)) diff --git a/askbot/tests/utils.py b/askbot/tests/utils.py index 4bc69ac4..b672da1c 100644 --- a/askbot/tests/utils.py +++ b/askbot/tests/utils.py @@ -5,8 +5,8 @@ from functools import wraps from askbot import models def create_user( - username = None, - email = None, + username = None, + email = None, notification_schedule = None, date_joined = None, status = 'a', @@ -25,13 +25,13 @@ def create_user( * 'q_sel' - questions that user decides to follow * 'm_and_c' - comments and mentions of user anywhere - and values as keys in + and values as keys in :attr:`~askbot.models.EmailFeedSetting.FEED_TYPES`: * 'i' - instantly * 'd' - daily * 'w' - weekly - * 'n' - never + * 'n' - never """ user = models.User.objects.create_user(username, email) @@ -42,7 +42,7 @@ def create_user( user.set_status(status) if notification_schedule == None: notification_schedule = models.EmailFeedSetting.NO_EMAIL_SCHEDULE - + #a hack, we need to delete these, that will be created automatically #because just below we will be replacing them with the new values user.notification_subscriptions.all().delete() @@ -110,7 +110,7 @@ class AskbotTestCase(TestCase): def post_question( - self, + self, user = None, title = 'test question title', body_text = 'test question body text', @@ -151,7 +151,7 @@ class AskbotTestCase(TestCase): """reloads model object from the database """ return obj.__class__.objects.get(id = obj.id) - + def post_answer( self, user = None, @@ -194,8 +194,8 @@ class AskbotTestCase(TestCase): by_email = False, timestamp = None ): - """posts and returns a comment to parent post, uses - now timestamp if not given, dummy body_text + """posts and returns a comment to parent post, uses + now timestamp if not given, dummy body_text author is required """ if user is None: |