test_query.py 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. # SPDX-License-Identifier: AGPL-3.0-or-later
  2. # pylint: disable=missing-module-docstring
  3. from parameterized.parameterized import parameterized
  4. import searx.search
  5. from searx.query import RawTextQuery
  6. from tests import SearxTestCase
  7. TEST_ENGINES = [
  8. {
  9. 'name': 'dummy engine',
  10. 'engine': 'dummy',
  11. 'categories': 'general',
  12. 'shortcut': 'du',
  13. 'timeout': 3.0,
  14. 'tokens': [],
  15. },
  16. ]
  17. class TestQuery(SearxTestCase): # pylint:disable=missing-class-docstring
  18. def test_simple_query(self):
  19. query_text = 'the query'
  20. query = RawTextQuery(query_text, [])
  21. self.assertEqual(query.getFullQuery(), query_text)
  22. self.assertEqual(len(query.query_parts), 0)
  23. self.assertEqual(len(query.user_query_parts), 2)
  24. self.assertEqual(len(query.languages), 0)
  25. self.assertFalse(query.specific)
  26. def test_multiple_spaces_query(self):
  27. query_text = '\tthe query'
  28. query = RawTextQuery(query_text, [])
  29. self.assertEqual(query.getFullQuery(), 'the query')
  30. self.assertEqual(len(query.query_parts), 0)
  31. self.assertEqual(len(query.user_query_parts), 2)
  32. self.assertEqual(len(query.languages), 0)
  33. self.assertFalse(query.specific)
  34. def test_str_method(self):
  35. query_text = '<7 the query'
  36. query = RawTextQuery(query_text, [])
  37. self.assertEqual(str(query), '<7 the query')
  38. def test_repr_method(self):
  39. query_text = '<8 the query'
  40. query = RawTextQuery(query_text, [])
  41. r = repr(query)
  42. self.assertTrue(r.startswith(f"<RawTextQuery query='{query_text}' "))
  43. def test_change_query(self):
  44. query_text = '<8 the query'
  45. query = RawTextQuery(query_text, [])
  46. another_query = query.changeQuery('another text')
  47. self.assertEqual(query, another_query)
  48. self.assertEqual(query.getFullQuery(), '<8 another text')
  49. class TestLanguageParser(SearxTestCase): # pylint:disable=missing-class-docstring
  50. def test_language_code(self):
  51. language = 'es-ES'
  52. query_text = 'the query'
  53. full_query = ':' + language + ' ' + query_text
  54. query = RawTextQuery(full_query, [])
  55. self.assertEqual(query.getFullQuery(), full_query)
  56. self.assertEqual(len(query.query_parts), 1)
  57. self.assertEqual(len(query.languages), 1)
  58. self.assertIn(language, query.languages)
  59. self.assertFalse(query.specific)
  60. def test_language_name(self):
  61. language = 'english'
  62. query_text = 'the query'
  63. full_query = ':' + language + ' ' + query_text
  64. query = RawTextQuery(full_query, [])
  65. self.assertEqual(query.getFullQuery(), full_query)
  66. self.assertEqual(len(query.query_parts), 1)
  67. self.assertIn('en', query.languages)
  68. self.assertFalse(query.specific)
  69. def test_unlisted_language_code(self):
  70. language = 'all'
  71. query_text = 'the query'
  72. full_query = ':' + language + ' ' + query_text
  73. query = RawTextQuery(full_query, [])
  74. self.assertEqual(query.getFullQuery(), full_query)
  75. self.assertEqual(len(query.query_parts), 1)
  76. self.assertIn('all', query.languages)
  77. self.assertFalse(query.specific)
  78. def test_auto_language_code(self):
  79. language = 'auto'
  80. query_text = 'una consulta'
  81. full_query = ':' + language + ' ' + query_text
  82. query = RawTextQuery(full_query, [])
  83. self.assertEqual(query.getFullQuery(), full_query)
  84. self.assertEqual(len(query.query_parts), 1)
  85. self.assertIn('auto', query.languages)
  86. self.assertFalse(query.specific)
  87. def test_invalid_language_code(self):
  88. language = 'not_a_language'
  89. query_text = 'the query'
  90. full_query = ':' + language + ' ' + query_text
  91. query = RawTextQuery(full_query, [])
  92. self.assertEqual(query.getFullQuery(), full_query)
  93. self.assertEqual(len(query.query_parts), 0)
  94. self.assertEqual(len(query.languages), 0)
  95. self.assertFalse(query.specific)
  96. def test_empty_colon_in_query(self):
  97. query_text = 'the : query'
  98. query = RawTextQuery(query_text, [])
  99. self.assertEqual(query.getFullQuery(), query_text)
  100. self.assertEqual(len(query.query_parts), 0)
  101. self.assertEqual(len(query.languages), 0)
  102. self.assertFalse(query.specific)
  103. def test_autocomplete_empty(self):
  104. query_text = 'the query :'
  105. query = RawTextQuery(query_text, [])
  106. self.assertEqual(query.autocomplete_list, [":en", ":en_us", ":english", ":united_kingdom"])
  107. @parameterized.expand(
  108. [
  109. (':englis', [":english"]),
  110. (':deutschla', [":deutschland"]),
  111. (':new_zea', [":new_zealand"]),
  112. (':zh-', [':zh-cn', ':zh-hk', ':zh-tw']),
  113. ]
  114. )
  115. def test_autocomplete(self, query: str, autocomplete_list: list):
  116. query = RawTextQuery(query, [])
  117. self.assertEqual(query.autocomplete_list, autocomplete_list)
  118. class TestTimeoutParser(SearxTestCase): # pylint:disable=missing-class-docstring
  119. @parameterized.expand(
  120. [
  121. ('<3 the query', 3),
  122. ('<350 the query', 0.35),
  123. ('<3500 the query', 3.5),
  124. ]
  125. )
  126. def test_timeout_limit(self, query_text: str, timeout_limit: float):
  127. query = RawTextQuery(query_text, [])
  128. self.assertEqual(query.getFullQuery(), query_text)
  129. self.assertEqual(len(query.query_parts), 1)
  130. self.assertEqual(query.timeout_limit, timeout_limit)
  131. self.assertFalse(query.specific)
  132. def test_timeout_invalid(self):
  133. # invalid number: it is not bang but it is part of the query
  134. query_text = '<xxx the query'
  135. query = RawTextQuery(query_text, [])
  136. self.assertEqual(query.getFullQuery(), query_text)
  137. self.assertEqual(len(query.query_parts), 0)
  138. self.assertEqual(query.getQuery(), query_text)
  139. self.assertIsNone(query.timeout_limit)
  140. self.assertFalse(query.specific)
  141. def test_timeout_autocomplete(self):
  142. # invalid number: it is not bang but it is part of the query
  143. query_text = 'the query <'
  144. query = RawTextQuery(query_text, [])
  145. self.assertEqual(query.getFullQuery(), query_text)
  146. self.assertEqual(len(query.query_parts), 0)
  147. self.assertEqual(query.getQuery(), query_text)
  148. self.assertIsNone(query.timeout_limit)
  149. self.assertFalse(query.specific)
  150. self.assertEqual(query.autocomplete_list, ['<3', '<850'])
  151. class TestExternalBangParser(SearxTestCase): # pylint:disable=missing-class-docstring
  152. def test_external_bang(self):
  153. query_text = '!!ddg the query'
  154. query = RawTextQuery(query_text, [])
  155. self.assertEqual(query.getFullQuery(), query_text)
  156. self.assertEqual(len(query.query_parts), 1)
  157. self.assertFalse(query.specific)
  158. def test_external_bang_not_found(self):
  159. query_text = '!!notfoundbang the query'
  160. query = RawTextQuery(query_text, [])
  161. self.assertEqual(query.getFullQuery(), query_text)
  162. self.assertIsNone(query.external_bang)
  163. self.assertFalse(query.specific)
  164. def test_external_bang_autocomplete(self):
  165. query_text = 'the query !!dd'
  166. query = RawTextQuery(query_text, [])
  167. self.assertEqual(query.getFullQuery(), '!!dd the query')
  168. self.assertEqual(len(query.query_parts), 1)
  169. self.assertFalse(query.specific)
  170. self.assertGreater(len(query.autocomplete_list), 0)
  171. a = query.autocomplete_list[0]
  172. self.assertEqual(query.get_autocomplete_full_query(a), a + ' the query')
  173. class TestBang(SearxTestCase): # pylint:disable=missing-class-docstring
  174. SPECIFIC_BANGS = ['!dummy_engine', '!du', '!general']
  175. THE_QUERY = 'the query'
  176. def setUp(self):
  177. searx.search.initialize(TEST_ENGINES)
  178. def tearDown(self):
  179. searx.search.load_engines([])
  180. @parameterized.expand(SPECIFIC_BANGS)
  181. def test_bang(self, bang: str):
  182. with self.subTest(msg="Check bang", bang=bang):
  183. query_text = TestBang.THE_QUERY + ' ' + bang
  184. query = RawTextQuery(query_text, [])
  185. self.assertEqual(query.getFullQuery(), bang + ' ' + TestBang.THE_QUERY)
  186. self.assertEqual(query.query_parts, [bang])
  187. self.assertEqual(query.user_query_parts, TestBang.THE_QUERY.split(' '))
  188. @parameterized.expand(SPECIFIC_BANGS)
  189. def test_specific(self, bang: str):
  190. with self.subTest(msg="Check bang is specific", bang=bang):
  191. query_text = TestBang.THE_QUERY + ' ' + bang
  192. query = RawTextQuery(query_text, [])
  193. self.assertTrue(query.specific)
  194. def test_bang_not_found(self):
  195. query = RawTextQuery('the query !bang_not_found', [])
  196. self.assertEqual(query.getFullQuery(), 'the query !bang_not_found')
  197. def test_bang_autocomplete(self):
  198. query = RawTextQuery('the query !dum', [])
  199. self.assertEqual(query.autocomplete_list, ['!dummy_engine'])
  200. query = RawTextQuery('!dum the query', [])
  201. self.assertEqual(query.autocomplete_list, [])
  202. self.assertEqual(query.getQuery(), '!dum the query')
  203. def test_bang_autocomplete_empty(self):
  204. query = RawTextQuery('the query !', [])
  205. self.assertEqual(query.autocomplete_list, ['!images', '!wikipedia', '!osm'])
  206. query = RawTextQuery('the query !', ['osm'])
  207. self.assertEqual(query.autocomplete_list, ['!images', '!wikipedia'])