elasticsearch_spec.rb 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. require 'rails_helper'
  3. RSpec.describe 'Elasticsearch', searchindex: true do
  4. let(:assets) { 'spec/fixtures/files/integration/elasticsearch' }
  5. let(:group) { create(:group) }
  6. let(:agent) { create(:agent, groups: [group]) }
  7. let(:customer) { create(:customer, organization: create(:organization)) }
  8. let(:ticket) { create(:ticket, owner: agent, customer: customer, group: group) }
  9. let(:article) { create(:ticket_article, :inbound_phone, ticket_id: ticket.id) }
  10. let(:attachment) do
  11. create(:store,
  12. object: 'Ticket::Article',
  13. o_id: article.id,
  14. data: Rails.root.join("#{assets}/es-normal.txt").binread,
  15. filename: 'es-normal.txt')
  16. end
  17. let(:customers) do
  18. organization = create(:organization)
  19. [
  20. create(:customer, organization: organization),
  21. create(:customer, organization: organization),
  22. create(:customer),
  23. ]
  24. end
  25. let(:tickets) do
  26. tickets = [
  27. create(:ticket, title: 'First test ticket', customer: customers[0], owner: agent, group: group),
  28. create(:ticket,
  29. title: 'Second test ticket',
  30. customer: customers[1],
  31. owner: agent,
  32. group: group,
  33. state: Ticket::State.lookup(name: 'open')),
  34. create(:ticket, title: 'Third test ticket', customer: customers[2]),
  35. ]
  36. tickets.each_index do |index|
  37. tickets[index].tag_add("Tag#{index + 1}", 1)
  38. end
  39. end
  40. let(:articles) do
  41. [
  42. create(:ticket_article, ticket_id: tickets[0].id).tap do |article|
  43. create(:store,
  44. object: 'Ticket::Article',
  45. o_id: article.id,
  46. data: Rails.root.join("#{assets}/es-normal.txt").binread,
  47. filename: 'es-normal.txt')
  48. create(:store,
  49. object: 'Ticket::Article',
  50. o_id: article.id,
  51. data: Rails.root.join("#{assets}/es-pdf1.pdf").binread,
  52. filename: 'es-pdf1.pdf')
  53. create(:store,
  54. object: 'Ticket::Article',
  55. o_id: article.id,
  56. data: Rails.root.join("#{assets}/es-box1.box").binread,
  57. filename: 'mail1.box')
  58. create(:store,
  59. object: 'Ticket::Article',
  60. o_id: article.id,
  61. data: Rails.root.join("#{assets}/es-too-big.txt").binread,
  62. filename: 'es-too-big.txt')
  63. end,
  64. create(:ticket_article,
  65. :inbound_email,
  66. ticket_id: tickets[1].id,
  67. subject: 'some subject2 / autobahn what else?',
  68. body: 'some other message <b>with s<u>t</u>rong text<b>',
  69. content_type: 'text/html'),
  70. create(:ticket_article,
  71. :inbound_email,
  72. ticket_id: tickets[2].id,
  73. body: 'some other message 3 / kindergarden what else?')
  74. ]
  75. end
  76. shared_examples 'user findable' do
  77. describe 'and findable' do
  78. it 'as agent' do
  79. result = User.search(current_user: agent, query: query)
  80. expect(result).to be_present
  81. end
  82. it 'not as customer' do
  83. result = User.search(current_user: customer, query: query)
  84. expect(result).not_to be_present
  85. end
  86. end
  87. end
  88. describe 'indexes agents' do
  89. let(:query) { agent.lastname }
  90. before do
  91. agent
  92. searchindex_model_reload([User])
  93. end
  94. it 'without sensible data' do
  95. lookup = agent.search_index_attribute_lookup
  96. expect(lookup).to include('id' => agent.id).and not_include('password')
  97. end
  98. include_examples 'user findable'
  99. end
  100. describe 'indexes customers' do
  101. let(:query) { customer.lastname }
  102. before do
  103. customer
  104. searchindex_model_reload([User])
  105. end
  106. it 'without sensible data' do
  107. lookup = customer.search_index_attribute_lookup
  108. expect(lookup).to include('id' => customer.id).and not_include('password')
  109. end
  110. it 'with organization' do
  111. lookup = customer.search_index_attribute_lookup
  112. expect(lookup['organization']['id']).to eq(customer.organization.id)
  113. end
  114. include_examples 'user findable'
  115. end
  116. describe 'indexes tickets' do
  117. context 'without sensible data' do
  118. before do
  119. ticket
  120. searchindex_model_reload([Ticket])
  121. end
  122. it 'without sensible data', :aggregate_failures do
  123. lookup = ticket.search_index_attribute_lookup
  124. expect(lookup['owner']).to not_include('password')
  125. expect(lookup['customer']).to not_include('password')
  126. end
  127. end
  128. context 'with article' do
  129. before do
  130. ticket && article && attachment
  131. searchindex_model_reload([Ticket])
  132. end
  133. it 'with article + attachment', :aggregate_failures do
  134. lookup = ticket.search_index_attribute_lookup
  135. expect(lookup['article'][0]['id']).to eq(article.id)
  136. expect(lookup['article'][0]['attachment'][0]['_name']).to match(attachment.filename)
  137. end
  138. end
  139. describe 'and findable' do
  140. before do
  141. ticket
  142. searchindex_model_reload([Ticket])
  143. end
  144. it 'as agent' do
  145. result = Ticket.search(current_user: agent, query: ticket.title)
  146. expect(result).to be_present
  147. end
  148. it 'as customer' do
  149. result = Ticket.search(current_user: customer, query: ticket.title)
  150. expect(result).to be_present
  151. end
  152. end
  153. describe 'and searchable', :aggregate_failures do
  154. context 'with agent' do
  155. before do
  156. ticket
  157. article
  158. attachment
  159. tickets
  160. articles
  161. searchindex_model_reload([Ticket])
  162. end
  163. it 'by tag' do
  164. result = Ticket.search(current_user: agent, query: 'Tag1')
  165. expect(result[0]['id']).to eq(tickets[0].id)
  166. expect(result.size).to eq(1)
  167. end
  168. it 'by customer' do
  169. result = Ticket.search(current_user: agent, query: tickets[0].customer.email)
  170. expect(result[0]['id']).to eq(tickets[0].id)
  171. expect(result.size).to eq(1)
  172. end
  173. it 'by article subject' do
  174. result = Ticket.search(current_user: agent, query: articles[0].subject)
  175. expect(result[0]['id']).to eq(tickets[0].id)
  176. expect(result.size).to eq(2)
  177. end
  178. it 'by article attachment content' do
  179. result = Ticket.search(current_user: agent, query: '"some normal text66"')
  180. expect(result[0]['id']).to eq(tickets[0].id)
  181. expect(result.size).to eq(2)
  182. end
  183. it 'not by big attachments' do
  184. result = Ticket.search(current_user: agent, query: '"some too big text88"')
  185. expect(result).not_to be_present
  186. end
  187. it 'by article html content' do
  188. result = Ticket.search(current_user: agent, query: 'strong')
  189. expect(result[0]['id']).to eq(tickets[1].id)
  190. expect(result.size).to eq(1)
  191. end
  192. it 'not without permission' do
  193. result = Ticket.search(current_user: agent, query: 'kindergarden')
  194. expect(result).not_to be_present
  195. end
  196. describe 'by query filter' do
  197. it 'tags' do
  198. result = Ticket.search(current_user: agent, query: 'tags:Tag2')
  199. expect(result[0]['id']).to eq(tickets[1].id)
  200. expect(result.size).to eq(1)
  201. end
  202. it 'state.name' do
  203. result = Ticket.search(current_user: agent, query: 'state.name:open')
  204. expect(result[0]['id']).to eq(tickets[1].id)
  205. expect(result.size).to eq(1)
  206. end
  207. it 'article.from' do
  208. result = Ticket.search(current_user: agent, query: "article.from:\"#{tickets[0].articles[0].from}\"")
  209. expect(result[0]['id']).to eq(tickets[1].id)
  210. expect(result.size).to eq(2)
  211. end
  212. end
  213. describe 'after modification', performs_jobs: true do
  214. before do
  215. tag_item = Tag::Item.lookup(name: 'Tag1')
  216. Tag::Item.rename(
  217. id: tag_item.id,
  218. name: 'Tag4711',
  219. updated_by_id: agent.id,
  220. )
  221. searchindex_model_reload([Ticket])
  222. end
  223. it 'tags' do
  224. result = Ticket.search(current_user: agent, query: 'tags:Tag4711')
  225. expect(result[0]['id']).to eq(tickets[0].id)
  226. expect(result.size).to eq(1)
  227. end
  228. end
  229. end
  230. context 'with customer' do
  231. before do
  232. tickets
  233. searchindex_model_reload([Ticket])
  234. end
  235. it 'by query OR clause' do
  236. result = Ticket.search(current_user: customers[0], query: 'First OR ticket')
  237. expect(result[0]['id']).to eq(tickets[1].id)
  238. expect(result[1]['id']).to eq(tickets[0].id)
  239. expect(result.size).to eq(2)
  240. end
  241. it 'not without permission by query OR clause' do
  242. result = Ticket.search(current_user: customers[2], query: 'First OR Second')
  243. expect(result).not_to be_present
  244. end
  245. end
  246. end
  247. end
  248. end