text_modules_examples.rb 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. # Copyright (C) 2012-2025 Zammad Foundation, https://zammad-foundation.org/
  2. RSpec.shared_examples 'text modules' do |path:, ticket: nil|
  3. describe 'basic examples', authenticated_as: :agent do
  4. let(:agent) { create(:agent, groups: [Group.find_by(name: 'Users'), group1, group2]) }
  5. let!(:agent_fixed_name) { create(:agent, firstname: 'FFFF1', lastname: 'GGGG1', groups: [Group.find_by(name: 'Users')]) }
  6. let!(:group1) { create(:group) }
  7. let!(:group2) { create(:group) }
  8. let!(:text_module_without_group1) { create(:text_module, name: 'aaa', keywords: "test dummy #{Faker::Superhero.prefix}") }
  9. let!(:text_module_without_group2) { create(:text_module, name: 'bbb', keywords: "test dummy #{Faker::Superhero.prefix}") }
  10. let!(:text_module_group1) { create(:text_module, name: 'ccc', keywords: "test dummy #{Faker::Superhero.prefix}", groups: [group1]) }
  11. let!(:text_module_group2) { create(:text_module, name: 'ddd', keywords: "test dummy #{Faker::Superhero.prefix}", groups: [group2]) }
  12. it 'shows when send ::' do
  13. refresh # workaround to get new created objects from db
  14. visit path
  15. within(:active_content) do
  16. set_tree_select_value('group_id', Group.first.name)
  17. find(:richtext).send_keys(':')
  18. find(:richtext).send_keys(':')
  19. expect(page).to have_selector(:text_module, text_module_without_group1.id)
  20. end
  21. end
  22. it 'does not break after usage of Ctrl/Command+Backspace' do
  23. visit path
  24. within(:active_content) do
  25. find(:richtext).send_keys(':')
  26. find(:richtext).send_keys(':')
  27. find(:richtext).send_keys('bur')
  28. # The click is needed to get the focus back to the field for chrome.
  29. find(:richtext).click
  30. find(:richtext).send_keys([magic_key, :backspace])
  31. find(:richtext).send_keys('Some other text')
  32. find(:richtext).send_keys(:enter)
  33. expect(find(:richtext)).to have_text 'Some other text'
  34. end
  35. end
  36. it 'does not show when send :enter:' do
  37. visit path
  38. within(:active_content) do
  39. set_tree_select_value('group_id', Group.first.name)
  40. find(:richtext).send_keys(':')
  41. find(:richtext).send_keys(:enter)
  42. find(:richtext).send_keys(':')
  43. expect(page).to have_no_selector(:text_module, text_module_without_group1.id)
  44. expect(page).to have_no_selector(:text_module, text_module_without_group2.id)
  45. end
  46. end
  47. it 'does not break search on backspace' do
  48. visit path
  49. within(:active_content) do
  50. set_tree_select_value('group_id', Group.first.name)
  51. find(:richtext).send_keys('@@agen')
  52. find(:richtext).send_keys(:backspace)
  53. expect(page).to have_no_text('No results found')
  54. end
  55. end
  56. it 'does delete empty mentions (issue #3636 / FF only)' do
  57. visit path
  58. within(:active_content) do
  59. set_tree_select_value('group_id', Group.first.name)
  60. find(:richtext).send_keys('@@FFFF1')
  61. await_empty_ajax_queue
  62. find(:richtext).send_keys(:enter)
  63. find(:richtext).send_keys(:enter)
  64. (agent_fixed_name.firstname.length + agent_fixed_name.lastname.length + 2).times do
  65. find(:richtext).send_keys(:backspace)
  66. end
  67. expect(find(:richtext)).to have_no_css('a[data-mention-user-id]', visible: :all)
  68. end
  69. end
  70. it 'does delete empty mentions (issue #3636 / simulation)' do
  71. visit path
  72. within(:active_content) do
  73. set_tree_select_value('group_id', Group.first.name)
  74. find(:richtext).send_keys('@@FFFF1')
  75. await_empty_ajax_queue
  76. find(:richtext).send_keys(:enter)
  77. find(:richtext).send_keys(:enter)
  78. find(:richtext).send_keys('test')
  79. page.execute_script("$('a[data-mention-user-id]').first().html('<br>')")
  80. find(:richtext).send_keys(:backspace)
  81. expect(find(:richtext).all('a[data-mention-user-id]', visible: :all).count).to eq(0)
  82. end
  83. end
  84. it 'does not delete parts of the text on multiple mentions (issue #3717)' do
  85. visit path
  86. within(:active_content) do
  87. set_tree_select_value('group_id', Group.first.name)
  88. find(:richtext).send_keys('Testing Testy')
  89. find(:richtext).send_keys('@@FFFF1')
  90. await_empty_ajax_queue
  91. find(:richtext).send_keys(:enter)
  92. await_empty_ajax_queue
  93. find(:richtext).send_keys(:enter)
  94. find(:richtext).send_keys('Testing Testy ')
  95. find(:richtext).send_keys('@@FFFF1')
  96. await_empty_ajax_queue
  97. find(:richtext).send_keys(:enter)
  98. await_empty_ajax_queue
  99. expect(find(:richtext).text).to include('Testing TestyFFFF1 GGGG1')
  100. expect(find(:richtext).text).to include('Testing Testy FFFF1 GGGG1')
  101. end
  102. end
  103. it 'does not delete line breaks of text with mentions (issue #3717)' do
  104. visit path
  105. within(:active_content) do
  106. set_tree_select_value('group_id', Group.first.name)
  107. find(:richtext).send_keys('@@FFFF1')
  108. await_empty_ajax_queue
  109. find(:richtext).send_keys(:enter)
  110. find(:richtext).send_keys(' Testing Testy')
  111. find(:richtext).send_keys(:enter)
  112. find(:richtext).send_keys(:enter)
  113. find(:richtext).send_keys(:backspace)
  114. find(:richtext).send_keys('@@FFFF1')
  115. await_empty_ajax_queue
  116. find(:richtext).send_keys(:enter)
  117. expect(find(:richtext).text).to include("FFFF1 GGGG1 Testing Testy\nFFFF1 GGGG1")
  118. end
  119. end
  120. it 'supports group-dependent text modules' do
  121. visit '/'
  122. # give user access to all groups including those created
  123. # by using FactoryBot outside of the example
  124. group_names_access_map = Group.pluck(:name).index_with do |_group_name|
  125. 'full'.freeze
  126. end
  127. current_user do |user|
  128. user.group_names_access_map = group_names_access_map
  129. user.save!
  130. end
  131. refresh # workaround to get changed settings from db
  132. visit path
  133. within(:active_content) do
  134. set_tree_select_value('group_id', group1.name)
  135. find(:richtext).send_keys('::')
  136. expect(page).to have_selector(:text_module, text_module_without_group1.id)
  137. expect(page).to have_selector(:text_module, text_module_without_group2.id)
  138. expect(page).to have_selector(:text_module, text_module_group1.id)
  139. expect(page).to have_no_selector(:text_module, text_module_group2.id)
  140. set_tree_select_value('group_id', group2.name)
  141. find(:richtext).send_keys('::')
  142. expect(page).to have_selector(:text_module, text_module_without_group1.id)
  143. expect(page).to have_selector(:text_module, text_module_without_group2.id)
  144. expect(page).to have_no_selector(:text_module, text_module_group1.id)
  145. expect(page).to have_selector(:text_module, text_module_group2.id)
  146. end
  147. end
  148. it 'orders text modules by alphabet' do
  149. refresh # workaround to get changed settings from db
  150. visit path
  151. within(:active_content) do
  152. find(:richtext).send_keys('::')
  153. find(:richtext).send_keys('dummy')
  154. find('.text-modules-box')
  155. expected_order = [
  156. "#{text_module_without_group2.name}\n#{text_module_without_group2.keywords}",
  157. "#{text_module_without_group1.name}\n#{text_module_without_group1.keywords}",
  158. ]
  159. if path == 'ticket/create'
  160. expected_order = [
  161. "#{text_module_group2.name}\n#{text_module_group2.keywords}",
  162. "#{text_module_group1.name}\n#{text_module_group1.keywords}",
  163. "#{text_module_without_group2.name}\n#{text_module_without_group2.keywords}",
  164. "#{text_module_without_group1.name}\n#{text_module_without_group1.keywords}",
  165. ]
  166. end
  167. shown_text_modules = find_all(:css, '.text-modules-box li')
  168. expect(shown_text_modules.length).to eq(expected_order.length)
  169. shown_text_modules_text = shown_text_modules.map(&:text)
  170. expect(shown_text_modules_text).to eq(expected_order)
  171. end
  172. end
  173. context 'when text module refers external data source', authenticated_as: :authenticate, db_strategy: :reset do
  174. let(:custom_attribute) { create(:object_manager_attribute_autocompletion_ajax_external_data_source) }
  175. let(:text_module_external) do
  176. create(:text_module,
  177. name: 'external data source',
  178. content: "external \#{ticket.#{custom_attribute.name}.value}")
  179. end
  180. def authenticate
  181. text_module_external
  182. custom_attribute
  183. ObjectManager::Attribute.migration_execute
  184. true
  185. end
  186. context 'when ticket external field value is not set' do
  187. it 'inserts text module with placeholder' do
  188. visit path
  189. within(:active_content) do
  190. find(:richtext).send_keys('::ext')
  191. page.send_keys(:enter)
  192. expect(find(:richtext)).to have_text 'external -'
  193. end
  194. end
  195. end
  196. if path.starts_with? '#ticket/zoom'
  197. context 'when ticket external field value is set' do
  198. before do
  199. ticket.reload[custom_attribute.name] = { value: 'aaa', label: 'AAA' }
  200. ticket.save!
  201. end
  202. it 'inserts text module with external value' do
  203. visit path
  204. within(:active_content) do
  205. find(:richtext).send_keys('::ext')
  206. page.send_keys(:enter)
  207. expect(find(:richtext)).to have_text 'external AAA'
  208. end
  209. end
  210. end
  211. end
  212. end
  213. context 'when Group restriction for text modules not working on ticket creation (specific scenario only) #4358', authenticated_as: :authenticate do
  214. let(:agent) { create(:agent, groups: [group1]) }
  215. def authenticate
  216. agent
  217. end
  218. it 'does show group related text modules when the group is hidden' do
  219. ticket&.update(group: group1)
  220. visit path
  221. within(:active_content) do
  222. expect(page).to have_css('[data-attribute-name=group_id].is-hidden', visible: :all)
  223. find(:richtext).send_keys(':')
  224. find(:richtext).send_keys(':')
  225. expect(page).to have_selector(:text_module, text_module_group1.id)
  226. end
  227. end
  228. end
  229. end
  230. end