1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
|
import logging as std_logging
import pickle
from django.test import TestCase
from haystack import connections
from haystack.models import SearchResult
from haystack.utils import log as logging
from haystack.utils.loading import UnifiedIndex
from test_haystack.core.models import MockModel
from .mocks import MockSearchResult
from .test_indexes import ReadQuerySetTestSearchIndex
class CaptureHandler(std_logging.Handler):
logs_seen = []
def emit(self, record):
CaptureHandler.logs_seen.append(record)
class SearchResultTestCase(TestCase):
fixtures = ["base_data"]
def setUp(self):
super().setUp()
cap = CaptureHandler()
logging.getLogger("haystack").addHandler(cap)
self.no_data = {}
self.extra_data = {"stored": "I am stored data. How fun."}
self.no_overwrite_data = {
"django_id": 2,
"django_ct": "haystack.anothermockmodel",
"stored": "I am stored data. How fun.",
}
# The str(1) bit might seem unnecessary but it avoids test_unicode needing to handle
# the differences between repr() output on Python 2 and 3 for a unicode literal:
self.no_data_sr = MockSearchResult("haystack", "mockmodel", str(1), 2)
self.extra_data_sr = MockSearchResult(
"haystack", "mockmodel", str(1), 3, **self.extra_data
)
self.no_overwrite_data_sr = MockSearchResult(
"haystack", "mockmodel", str(1), 4, **self.no_overwrite_data
)
def test_init(self):
self.assertEqual(self.no_data_sr.app_label, "haystack")
self.assertEqual(self.no_data_sr.model_name, "mockmodel")
self.assertEqual(self.no_data_sr.model, MockModel)
self.assertEqual(self.no_data_sr.verbose_name, "Mock model")
self.assertEqual(self.no_data_sr.verbose_name_plural, "Mock models")
self.assertEqual(self.no_data_sr.pk, "1")
self.assertEqual(self.no_data_sr.score, 2)
self.assertEqual(self.no_data_sr.stored, None)
self.assertEqual(self.extra_data_sr.app_label, "haystack")
self.assertEqual(self.extra_data_sr.model_name, "mockmodel")
self.assertEqual(self.extra_data_sr.model, MockModel)
self.assertEqual(self.extra_data_sr.verbose_name, "Mock model")
self.assertEqual(self.extra_data_sr.verbose_name_plural, "Mock models")
self.assertEqual(self.extra_data_sr.pk, "1")
self.assertEqual(self.extra_data_sr.score, 3)
self.assertEqual(self.extra_data_sr.stored, "I am stored data. How fun.")
self.assertEqual(self.no_overwrite_data_sr.app_label, "haystack")
self.assertEqual(self.no_overwrite_data_sr.model_name, "mockmodel")
self.assertEqual(self.no_overwrite_data_sr.model, MockModel)
self.assertEqual(self.no_overwrite_data_sr.verbose_name, "Mock model")
self.assertEqual(self.no_overwrite_data_sr.verbose_name_plural, "Mock models")
self.assertEqual(self.no_overwrite_data_sr.pk, "1")
self.assertEqual(self.no_overwrite_data_sr.score, 4)
self.assertEqual(self.no_overwrite_data_sr.stored, "I am stored data. How fun.")
def test_get_additional_fields(self):
self.assertEqual(self.no_data_sr.get_additional_fields(), {})
self.assertEqual(
self.extra_data_sr.get_additional_fields(),
{"stored": "I am stored data. How fun."},
)
self.assertEqual(
self.no_overwrite_data_sr.get_additional_fields(),
{
"django_ct": "haystack.anothermockmodel",
"django_id": 2,
"stored": "I am stored data. How fun.",
},
)
def test_unicode(self):
self.assertEqual(
self.no_data_sr.__str__(), "<SearchResult: haystack.mockmodel (pk='1')>"
)
self.assertEqual(
self.extra_data_sr.__str__(),
"<SearchResult: haystack.mockmodel (pk='1')>",
)
self.assertEqual(
self.no_overwrite_data_sr.__str__(),
"<SearchResult: haystack.mockmodel (pk='1')>",
)
def test_content_type(self):
self.assertEqual(self.no_data_sr.content_type(), "core.mockmodel")
self.assertEqual(self.extra_data_sr.content_type(), "core.mockmodel")
self.assertEqual(self.no_overwrite_data_sr.content_type(), "core.mockmodel")
def test_stored_fields(self):
# Stow.
old_unified_index = connections["default"]._index
ui = UnifiedIndex()
ui.build(indexes=[])
connections["default"]._index = ui
# Without registering, we should receive an empty dict.
self.assertEqual(self.no_data_sr.get_stored_fields(), {})
self.assertEqual(self.extra_data_sr.get_stored_fields(), {})
self.assertEqual(self.no_overwrite_data_sr.get_stored_fields(), {})
from haystack import indexes
class TestSearchIndex(indexes.SearchIndex, indexes.Indexable):
stored = indexes.CharField(model_attr="author", document=True)
def get_model(self):
return MockModel
# Include the index & try again.
ui.document_field = "stored"
ui.build(indexes=[TestSearchIndex()])
self.assertEqual(self.no_data_sr.get_stored_fields(), {"stored": None})
self.assertEqual(
self.extra_data_sr.get_stored_fields(),
{"stored": "I am stored data. How fun."},
)
self.assertEqual(
self.no_overwrite_data_sr.get_stored_fields(),
{"stored": "I am stored data. How fun."},
)
# Restore.
connections["default"]._index = old_unified_index
def test_missing_object(self):
awol1 = SearchResult("core", "mockmodel", "1000000", 2)
self.assertEqual(awol1.app_label, "core")
self.assertEqual(awol1.model_name, "mockmodel")
self.assertEqual(awol1.pk, "1000000")
self.assertEqual(awol1.score, 2)
awol2 = SearchResult("core", "yetanothermockmodel", "1000000", 2)
self.assertEqual(awol2.app_label, "core")
self.assertEqual(awol2.model_name, "yetanothermockmodel")
self.assertEqual(awol2.pk, "1000000")
self.assertEqual(awol2.score, 2)
# Failed lookups should fail gracefully.
CaptureHandler.logs_seen = []
self.assertEqual(awol1.model, MockModel)
self.assertEqual(awol1.object, None)
self.assertEqual(awol1.verbose_name, "Mock model")
self.assertEqual(awol1.verbose_name_plural, "Mock models")
self.assertEqual(awol1.stored, None)
self.assertEqual(len(CaptureHandler.logs_seen), 4)
CaptureHandler.logs_seen = []
self.assertEqual(awol2.model, None)
self.assertEqual(awol2.object, None)
self.assertEqual(awol2.verbose_name, "")
self.assertEqual(awol2.verbose_name_plural, "")
self.assertEqual(awol2.stored, None)
self.assertEqual(len(CaptureHandler.logs_seen), 12)
def test_read_queryset(self):
# The model is flagged deleted so not returned by the default manager.
deleted1 = SearchResult("core", "afifthmockmodel", 2, 2)
self.assertEqual(deleted1.object, None)
# Stow.
old_unified_index = connections["default"]._index
ui = UnifiedIndex()
ui.document_field = "author"
ui.build(indexes=[ReadQuerySetTestSearchIndex()])
connections["default"]._index = ui
# The soft delete manager returns the object.
deleted2 = SearchResult("core", "afifthmockmodel", 2, 2)
self.assertNotEqual(deleted2.object, None)
self.assertEqual(deleted2.object.author, "sam2")
# Restore.
connections["default"]._index = old_unified_index
def test_pickling(self):
pickle_me_1 = SearchResult("core", "mockmodel", "1000000", 2)
picklicious = pickle.dumps(pickle_me_1)
pickle_me_2 = pickle.loads(picklicious)
self.assertEqual(pickle_me_1.app_label, pickle_me_2.app_label)
self.assertEqual(pickle_me_1.model_name, pickle_me_2.model_name)
self.assertEqual(pickle_me_1.pk, pickle_me_2.pk)
self.assertEqual(pickle_me_1.score, pickle_me_2.score)
|