elasticsearch_test.rb 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. # Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
  2. require 'test_helper'
  3. class ElasticsearchTest < ActiveSupport::TestCase
  4. include BackgroundJobsHelper
  5. include SearchindexHelper
  6. setup do
  7. configure_elasticsearch(required: true)
  8. rebuild_searchindex
  9. groups = Group.where(name: 'Users')
  10. roles = Role.where(name: 'Agent')
  11. @agent = User.create!(
  12. login: 'es-agent@example.com',
  13. firstname: 'E',
  14. lastname: 'S',
  15. email: 'es-agent@example.com',
  16. password: 'agentpw',
  17. active: true,
  18. roles: roles,
  19. groups: groups,
  20. updated_by_id: 1,
  21. created_by_id: 1,
  22. )
  23. Group.create_if_not_exists(
  24. name: 'WithoutAccess',
  25. note: 'Test for not access check.',
  26. updated_by_id: 1,
  27. created_by_id: 1
  28. )
  29. roles = Role.where(name: 'Customer')
  30. @organization1 = Organization.create_if_not_exists(
  31. name: 'Customer Organization Update',
  32. note: 'some note',
  33. updated_by_id: 1,
  34. created_by_id: 1,
  35. )
  36. @customer1 = User.create!(
  37. login: 'es-customer1@example.com',
  38. firstname: 'ES',
  39. lastname: 'Customer1',
  40. email: 'es-customer1@example.com',
  41. password: 'customerpw',
  42. active: true,
  43. organization_id: @organization1.id,
  44. roles: roles,
  45. updated_by_id: 1,
  46. created_by_id: 1,
  47. )
  48. @customer2 = User.create!(
  49. login: 'es-customer2@example.com',
  50. firstname: 'ES',
  51. lastname: 'Customer2',
  52. email: 'es-customer2@example.com',
  53. password: 'customerpw',
  54. active: true,
  55. organization_id: @organization1.id,
  56. roles: roles,
  57. updated_by_id: 1,
  58. created_by_id: 1,
  59. )
  60. @customer3 = User.create!(
  61. login: 'es-customer3@example.com',
  62. firstname: 'ES',
  63. lastname: 'Customer3',
  64. email: 'es-customer3@example.com',
  65. password: 'customerpw',
  66. active: true,
  67. roles: roles,
  68. updated_by_id: 1,
  69. created_by_id: 1,
  70. )
  71. # execute background jobs to index created/changed objects
  72. perform_enqueued_jobs
  73. SearchIndexBackend.refresh
  74. end
  75. # check search attributes
  76. test 'a - objects' do
  77. # user
  78. attributes = @agent.search_index_attribute_lookup
  79. assert_equal('E', attributes['firstname'])
  80. assert_equal('S', attributes['lastname'])
  81. assert_equal('es-agent@example.com', attributes['email'])
  82. assert(attributes['preferences'])
  83. assert_not(attributes['password'])
  84. assert_not(attributes['organization'])
  85. attributes = @customer1.search_index_attribute_lookup
  86. assert_equal('ES', attributes['firstname'])
  87. assert_equal('Customer1', attributes['lastname'])
  88. assert_equal('es-customer1@example.com', attributes['email'])
  89. assert(attributes['preferences'])
  90. assert_not(attributes['password'])
  91. assert_equal('Customer Organization Update', attributes['organization']['name'])
  92. # organization
  93. attributes = @organization1.search_index_attribute_lookup
  94. assert_equal('Customer Organization Update', attributes['name'])
  95. assert_equal('some note', attributes['note'])
  96. assert(attributes['members'])
  97. # ticket/article
  98. ticket1 = Ticket.create!(
  99. title: 'some title äöüß',
  100. group: Group.lookup(name: 'Users'),
  101. customer_id: @customer1.id,
  102. state: Ticket::State.lookup(name: 'new'),
  103. priority: Ticket::Priority.lookup(name: '2 normal'),
  104. updated_by_id: 1,
  105. created_by_id: 1,
  106. )
  107. article1 = Ticket::Article.create!(
  108. ticket_id: ticket1.id,
  109. from: 'some_sender@example.com',
  110. to: 'some_recipient@example.com',
  111. subject: 'some subject',
  112. message_id: 'some@id',
  113. body: 'some message',
  114. internal: false,
  115. sender: Ticket::Article::Sender.where(name: 'Customer').first,
  116. type: Ticket::Article::Type.where(name: 'email').first,
  117. updated_by_id: 1,
  118. created_by_id: 1,
  119. )
  120. Store.create!(
  121. object: 'Ticket::Article',
  122. o_id: article1.id,
  123. data: File.binread(Rails.root.join('test/data/elasticsearch/es-normal.txt')),
  124. filename: 'es-normal.txt',
  125. preferences: {},
  126. created_by_id: 1,
  127. )
  128. attributes = ticket1.search_index_attribute_lookup
  129. assert_equal('Users', attributes['group']['name'])
  130. assert_equal('new', attributes['state']['name'])
  131. assert_equal('2 normal', attributes['priority']['name'])
  132. assert_equal('ES', attributes['customer']['firstname'])
  133. assert_equal('Customer1', attributes['customer']['lastname'])
  134. assert_equal('es-customer1@example.com', attributes['customer']['email'])
  135. assert_not(attributes['customer']['password'])
  136. assert_nil(attributes['customer']['organization'])
  137. assert_equal('-', attributes['owner']['login'])
  138. assert_equal('-', attributes['owner']['firstname'])
  139. assert_not(attributes['owner']['password'])
  140. assert_not(attributes['owner']['organization'])
  141. assert(attributes['article'][0]['attachment'])
  142. assert(attributes['article'][0]['attachment'][0])
  143. assert_not(attributes['article'][0]['attachment'][1])
  144. assert_equal('es-normal.txt', attributes['article'][0]['attachment'][0]['_name'])
  145. assert_equal('c29tZSBub3JtYWwgdGV4dDY2Cg==', attributes['article'][0]['attachment'][0]['_content'])
  146. ticket1.destroy!
  147. # execute background jobs
  148. perform_enqueued_jobs
  149. SearchIndexBackend.refresh
  150. ticket1 = Ticket.create!(
  151. title: "some title\n äöüß",
  152. group: Group.lookup(name: 'Users'),
  153. customer_id: @customer1.id,
  154. state: Ticket::State.lookup(name: 'new'),
  155. priority: Ticket::Priority.lookup(name: '2 normal'),
  156. updated_by_id: 1,
  157. created_by_id: 1,
  158. )
  159. article1 = Ticket::Article.create!(
  160. ticket_id: ticket1.id,
  161. from: 'some_sender@example.com',
  162. to: 'some_recipient@example.com',
  163. subject: 'some subject',
  164. message_id: 'some@id',
  165. body: 'some message',
  166. internal: false,
  167. sender: Ticket::Article::Sender.where(name: 'Customer').first,
  168. type: Ticket::Article::Type.where(name: 'email').first,
  169. updated_by_id: 1,
  170. created_by_id: 1,
  171. )
  172. # add attachments which should get index / .txt
  173. # "some normal text66"
  174. Store.create!(
  175. object: 'Ticket::Article',
  176. o_id: article1.id,
  177. data: File.binread(Rails.root.join('test/data/elasticsearch/es-normal.txt')),
  178. filename: 'es-normal.txt',
  179. preferences: {},
  180. created_by_id: 1,
  181. )
  182. # add attachments which should get index / .pdf
  183. # "Zammad Test77"
  184. Store.create!(
  185. object: 'Ticket::Article',
  186. o_id: article1.id,
  187. data: File.binread(Rails.root.join('test/data/elasticsearch/es-pdf1.pdf')),
  188. filename: 'es-pdf1.pdf',
  189. preferences: {},
  190. created_by_id: 1,
  191. )
  192. # add attachments which should get index / .box
  193. # "Old programmers never die test99"
  194. Store.create!(
  195. object: 'Ticket::Article',
  196. o_id: article1.id,
  197. data: File.binread(Rails.root.join('test/data/elasticsearch/es-box1.box')),
  198. filename: 'mail1.box',
  199. preferences: {},
  200. created_by_id: 1,
  201. )
  202. # add to big attachment which should not get index
  203. # "some too big text88"
  204. Store.create!(
  205. object: 'Ticket::Article',
  206. o_id: article1.id,
  207. data: File.binread(Rails.root.join('test/data/elasticsearch/es-too-big.txt')),
  208. filename: 'es-too-big.txt',
  209. preferences: {},
  210. created_by_id: 1,
  211. )
  212. ticket1.tag_add('someTagA', 1)
  213. travel 1.minute
  214. ticket2 = Ticket.create!(
  215. title: 'something else',
  216. group: Group.lookup(name: 'Users'),
  217. customer_id: @customer2.id,
  218. state: Ticket::State.lookup(name: 'open'),
  219. priority: Ticket::Priority.lookup(name: '2 normal'),
  220. updated_by_id: 1,
  221. created_by_id: 1,
  222. )
  223. Ticket::Article.create!(
  224. ticket_id: ticket2.id,
  225. from: 'some_sender@example.org',
  226. to: 'some_recipient@example.org',
  227. subject: 'some subject2 / autobahn what else?',
  228. message_id: 'some@id',
  229. body: 'some other message <b>with s<u>t</u>rong text<b>',
  230. content_type: 'text/html',
  231. internal: false,
  232. sender: Ticket::Article::Sender.where(name: 'Customer').first,
  233. type: Ticket::Article::Type.where(name: 'email').first,
  234. updated_by_id: 1,
  235. created_by_id: 1,
  236. )
  237. ticket2.tag_add('someTagB', 1)
  238. travel 1.minute
  239. ticket3 = Ticket.create!(
  240. title: 'something else',
  241. group: Group.lookup(name: 'WithoutAccess'),
  242. customer_id: @customer3.id,
  243. state: Ticket::State.lookup(name: 'open'),
  244. priority: Ticket::Priority.lookup(name: '2 normal'),
  245. updated_by_id: 1,
  246. created_by_id: 1,
  247. )
  248. Ticket::Article.create!(
  249. ticket_id: ticket3.id,
  250. from: 'some_sender@example.org',
  251. to: 'some_recipient@example.org',
  252. subject: 'some subject3',
  253. message_id: 'some@id',
  254. body: 'some other message 3 / kindergarden what else?',
  255. internal: false,
  256. sender: Ticket::Article::Sender.where(name: 'Customer').first,
  257. type: Ticket::Article::Type.where(name: 'email').first,
  258. updated_by_id: 1,
  259. created_by_id: 1,
  260. )
  261. # execute background jobs
  262. perform_enqueued_jobs
  263. SearchIndexBackend.refresh
  264. # search as @agent
  265. # search for article data
  266. result = Ticket.search(
  267. current_user: @agent,
  268. query: 'autobahn',
  269. limit: 15,
  270. )
  271. assert(result.present?, 'result exists not')
  272. assert(result[0], 'record 1')
  273. assert_not(result[1], 'record 2')
  274. assert_equal(result[0].id, ticket2.id)
  275. # search for html content
  276. result = Ticket.search(
  277. current_user: @agent,
  278. query: 'strong',
  279. limit: 15,
  280. )
  281. assert(result.present?, 'result exists not')
  282. assert(result[0], 'record 1')
  283. assert_not(result[1], 'record 2')
  284. assert_equal(result[0].id, ticket2.id)
  285. # search for indexed attachment
  286. result = Ticket.search(
  287. current_user: @agent,
  288. query: '"some normal text66"',
  289. limit: 15,
  290. )
  291. assert(result[0], 'record 1')
  292. assert_equal(result[0].id, ticket1.id)
  293. result = Ticket.search(
  294. current_user: @agent,
  295. query: 'test77',
  296. limit: 15,
  297. )
  298. assert(result[0], 'record 1')
  299. assert_equal(result[0].id, ticket1.id)
  300. # search for not indexed attachment
  301. result = Ticket.search(
  302. current_user: @agent,
  303. query: 'test88',
  304. limit: 15,
  305. )
  306. assert_not(result[0], 'record 1')
  307. result = Ticket.search(
  308. current_user: @agent,
  309. query: 'test99',
  310. limit: 15,
  311. )
  312. assert_not(result[0], 'record 1')
  313. # search for ticket with no permissions
  314. result = Ticket.search(
  315. current_user: @agent,
  316. query: 'kindergarden',
  317. limit: 15,
  318. )
  319. assert(result.blank?, 'result should be empty')
  320. assert_not(result[0], 'record 1')
  321. # search as @customer1
  322. result = Ticket.search(
  323. current_user: @customer1,
  324. query: 'title OR else',
  325. limit: 15,
  326. )
  327. assert(result.present?, 'result exists not')
  328. assert(result[0], 'record 1')
  329. assert(result[1], 'record 2')
  330. assert_not(result[2], 'record 3')
  331. assert_equal(result[0].id, ticket2.id)
  332. assert_equal(result[1].id, ticket1.id)
  333. # search as @customer2
  334. result = Ticket.search(
  335. current_user: @customer2,
  336. query: 'title OR else',
  337. limit: 15,
  338. )
  339. assert(result.present?, 'result exists not')
  340. assert(result[0], 'record 1')
  341. assert(result[1], 'record 2')
  342. assert_not(result[2], 'record 3')
  343. assert_equal(result[0].id, ticket2.id)
  344. assert_equal(result[1].id, ticket1.id)
  345. # search as @customer3
  346. result = Ticket.search(
  347. current_user: @customer3,
  348. query: 'title OR else',
  349. limit: 15,
  350. )
  351. assert(result.present?, 'result exists not')
  352. assert(result[0], 'record 1')
  353. assert_not(result[1], 'record 2')
  354. assert_equal(result[0].id, ticket3.id)
  355. # search for tags
  356. result = Ticket.search(
  357. current_user: @agent,
  358. query: 'tags:someTagA',
  359. limit: 15,
  360. )
  361. assert(result[0], 'record 1')
  362. assert_not(result[1], 'record 1')
  363. assert_equal(result[0].id, ticket1.id)
  364. result = Ticket.search(
  365. current_user: @agent,
  366. query: 'tags:someTagB',
  367. limit: 15,
  368. )
  369. assert(result[0], 'record 2')
  370. assert_not(result[1], 'record 2')
  371. assert_equal(result[0].id, ticket2.id)
  372. # rename tag (e. g. via admin interface)
  373. tag_item = Tag::Item.lookup(name: 'someTagA')
  374. Tag::Item.rename(
  375. id: tag_item.id,
  376. name: 'someTagC',
  377. updated_by_id: 1,
  378. )
  379. # execute background jobs
  380. perform_enqueued_jobs
  381. SearchIndexBackend.refresh
  382. # search for tags
  383. result = Ticket.search(
  384. current_user: @agent,
  385. query: 'tags:someTagA',
  386. limit: 15,
  387. )
  388. assert_not(result[0], 'record 1')
  389. assert_not(result[1], 'record 1')
  390. result = Ticket.search(
  391. current_user: @agent,
  392. query: 'tags:someTagB',
  393. limit: 15,
  394. )
  395. assert(result[0], 'record 2')
  396. assert_not(result[1], 'record 2')
  397. assert_equal(result[0].id, ticket2.id)
  398. result = Ticket.search(
  399. current_user: @agent,
  400. query: 'tags:someTagC',
  401. limit: 15,
  402. )
  403. assert(result[0], 'record 1')
  404. assert_not(result[1], 'record 2')
  405. assert_equal(result[0].id, ticket1.id)
  406. result = Ticket.search(
  407. current_user: @agent,
  408. query: 'state.name:open',
  409. limit: 15,
  410. )
  411. assert(result[0], 'record 1')
  412. assert_not(result[1], 'record 2')
  413. assert_equal(result[0].id, ticket2.id)
  414. result = Ticket.search(
  415. current_user: @agent,
  416. query: '"some_sender@example.com"',
  417. limit: 15,
  418. )
  419. assert(result[0], 'record 1')
  420. assert_not(result[1], 'record 2')
  421. assert_equal(result[0].id, ticket1.id)
  422. result = Ticket.search(
  423. current_user: @agent,
  424. query: 'article.from:"some_sender@example.com"',
  425. limit: 15,
  426. )
  427. assert(result[0], 'record 1')
  428. assert_not(result[1], 'record 2')
  429. assert_equal(result[0].id, ticket1.id)
  430. # check users and search it
  431. # search as @agent
  432. result = User.search(
  433. current_user: @agent,
  434. query: 'customer1',
  435. limit: 15,
  436. )
  437. assert(result.present?, 'result should not be empty')
  438. assert(result[0], 'record 1')
  439. assert_not(result[1], 'record 2')
  440. assert_equal(result[0].id, @customer1.id)
  441. # search as @customer1
  442. result = User.search(
  443. current_user: @customer1,
  444. query: 'customer1',
  445. limit: 15,
  446. )
  447. assert(result.blank?, 'result should be empty')
  448. assert_not(result[0], 'record 1')
  449. # cleanup
  450. Rake::Task['zammad:searchindex:drop'].execute
  451. end
  452. end