test_search.py 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. from django.urls import reverse
  2. from .. import test
  3. from ...categories.models import Category
  4. from ...users.test import AuthenticatedUserTestCase
  5. def index_post(post):
  6. if post.id == post.thread.first_post_id:
  7. post.set_search_document(post.thread.title)
  8. else:
  9. post.set_search_document()
  10. post.save(update_fields=["search_document"])
  11. post.update_search_vector()
  12. post.save(update_fields=["search_vector"])
  13. class SearchApiTests(AuthenticatedUserTestCase):
  14. def setUp(self):
  15. super().setUp()
  16. self.category = Category.objects.get(slug="first-category")
  17. self.api_link = reverse("misago:api:search")
  18. def test_no_query(self):
  19. """api handles no search query"""
  20. response = self.client.get(self.api_link)
  21. self.assertEqual(response.status_code, 200)
  22. reponse_json = response.json()
  23. self.assertIn("threads", [p["id"] for p in reponse_json])
  24. for provider in reponse_json:
  25. if provider["id"] == "threads":
  26. self.assertEqual(provider["results"]["results"], [])
  27. def test_empty_query(self):
  28. """api handles empty search query"""
  29. response = self.client.get("%s?q=" % self.api_link)
  30. self.assertEqual(response.status_code, 200)
  31. reponse_json = response.json()
  32. self.assertIn("threads", [p["id"] for p in reponse_json])
  33. for provider in reponse_json:
  34. if provider["id"] == "threads":
  35. self.assertEqual(provider["results"]["results"], [])
  36. def test_short_query(self):
  37. """api handles short search query"""
  38. thread = test.post_thread(self.category)
  39. post = test.reply_thread(thread, message="Lorem ipsum dolor.")
  40. index_post(post)
  41. response = self.client.get("%s?q=ip" % self.api_link)
  42. self.assertEqual(response.status_code, 200)
  43. reponse_json = response.json()
  44. self.assertIn("threads", [p["id"] for p in reponse_json])
  45. for provider in reponse_json:
  46. if provider["id"] == "threads":
  47. self.assertEqual(provider["results"]["results"], [])
  48. def test_wrong_query(self):
  49. """api handles query miss"""
  50. thread = test.post_thread(self.category)
  51. post = test.reply_thread(thread, message="Lorem ipsum dolor.")
  52. index_post(post)
  53. response = self.client.get("%s?q=elit" % self.api_link)
  54. self.assertEqual(response.status_code, 200)
  55. reponse_json = response.json()
  56. self.assertIn("threads", [p["id"] for p in reponse_json])
  57. for provider in reponse_json:
  58. if provider["id"] == "threads":
  59. self.assertEqual(provider["results"]["results"], [])
  60. def test_hidden_post(self):
  61. """hidden posts are extempt from search"""
  62. thread = test.post_thread(self.category)
  63. post = test.reply_thread(thread, message="Lorem ipsum dolor.", is_hidden=True)
  64. index_post(post)
  65. response = self.client.get("%s?q=ipsum" % self.api_link)
  66. self.assertEqual(response.status_code, 200)
  67. reponse_json = response.json()
  68. self.assertIn("threads", [p["id"] for p in reponse_json])
  69. for provider in reponse_json:
  70. if provider["id"] == "threads":
  71. self.assertEqual(provider["results"]["results"], [])
  72. def test_unapproved_post(self):
  73. """unapproves posts are extempt from search"""
  74. thread = test.post_thread(self.category)
  75. post = test.reply_thread(
  76. thread, message="Lorem ipsum dolor.", is_unapproved=True
  77. )
  78. index_post(post)
  79. response = self.client.get("%s?q=ipsum" % self.api_link)
  80. self.assertEqual(response.status_code, 200)
  81. reponse_json = response.json()
  82. self.assertIn("threads", [p["id"] for p in reponse_json])
  83. for provider in reponse_json:
  84. if provider["id"] == "threads":
  85. self.assertEqual(provider["results"]["results"], [])
  86. def test_query(self):
  87. """api handles search query"""
  88. thread = test.post_thread(self.category)
  89. post = test.reply_thread(thread, message="Lorem ipsum dolor.")
  90. index_post(post)
  91. response = self.client.get("%s?q=ipsum" % self.api_link)
  92. self.assertEqual(response.status_code, 200)
  93. reponse_json = response.json()
  94. self.assertIn("threads", [p["id"] for p in reponse_json])
  95. for provider in reponse_json:
  96. if provider["id"] == "threads":
  97. results = provider["results"]["results"]
  98. self.assertEqual(len(results), 1)
  99. self.assertEqual(results[0]["id"], post.id)
  100. def test_thread_title_search(self):
  101. """api searches threads by title"""
  102. thread = test.post_thread(self.category, title="Atmosphere of mars")
  103. index_post(thread.first_post)
  104. post = test.reply_thread(thread, message="Lorem ipsum dolor.")
  105. index_post(post)
  106. response = self.client.get("%s?q=mars atmosphere" % self.api_link)
  107. self.assertEqual(response.status_code, 200)
  108. reponse_json = response.json()
  109. self.assertIn("threads", [p["id"] for p in reponse_json])
  110. for provider in reponse_json:
  111. if provider["id"] == "threads":
  112. results = provider["results"]["results"]
  113. self.assertEqual(len(results), 1)
  114. self.assertEqual(results[0]["id"], thread.first_post_id)
  115. def test_complex_query(self):
  116. """api handles complex query that uses fulltext search facilities"""
  117. thread = test.post_thread(self.category)
  118. post = test.reply_thread(thread, message="Atmosphere of Mars")
  119. index_post(post)
  120. response = self.client.get("%s?q=Mars atmosphere" % self.api_link)
  121. self.assertEqual(response.status_code, 200)
  122. reponse_json = response.json()
  123. self.assertIn("threads", [p["id"] for p in reponse_json])
  124. for provider in reponse_json:
  125. if provider["id"] == "threads":
  126. results = provider["results"]["results"]
  127. self.assertEqual(len(results), 1)
  128. self.assertEqual(results[0]["id"], post.id)
  129. def test_filtered_query(self):
  130. """search filters are used by search system"""
  131. thread = test.post_thread(self.category)
  132. post = test.reply_thread(
  133. thread, message="You just do MMM in 4th minute and its pwnt"
  134. )
  135. index_post(post)
  136. response = self.client.get("%s?q=MMM" % self.api_link)
  137. self.assertEqual(response.status_code, 200)
  138. reponse_json = response.json()
  139. self.assertIn("threads", [p["id"] for p in reponse_json])
  140. for provider in reponse_json:
  141. if provider["id"] == "threads":
  142. results = provider["results"]["results"]
  143. self.assertEqual(len(results), 1)
  144. self.assertEqual(results[0]["id"], post.id)
  145. response = self.client.get("%s?q=Marines Medics" % self.api_link)
  146. self.assertEqual(response.status_code, 200)
  147. for provider in reponse_json:
  148. if provider["id"] == "threads":
  149. results = provider["results"]["results"]
  150. self.assertEqual(len(results), 1)
  151. self.assertEqual(results[0]["id"], post.id)
  152. class SearchProviderApiTests(SearchApiTests):
  153. def setUp(self):
  154. super().setUp()
  155. self.api_link = reverse(
  156. "misago:api:search", kwargs={"search_provider": "threads"}
  157. )
  158. def test_post_search_filters_hook_is_used_by_threads_search(
  159. db, user_client, mocker, thread
  160. ):
  161. def search_filter(search):
  162. return search.replace("apple phone", "iphone")
  163. mocker.patch(
  164. "misago.threads.filtersearch.hooks.post_search_filters", [search_filter]
  165. )
  166. post = test.reply_thread(thread, message="Lorem ipsum iphone dolor met.")
  167. index_post(post)
  168. response = user_client.get("/api/search/?q=apple phone")
  169. reponse_json = response.json()
  170. assert "threads" in [p["id"] for p in reponse_json]
  171. for provider in reponse_json:
  172. if provider["id"] == "threads":
  173. results = provider["results"]["results"]
  174. assert len(results) == 1
  175. assert results[0]["id"] == post.id