checklist_spec.rb 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. require 'rails_helper'
  3. RSpec.describe 'Ticket zoom > Checklist', authenticated_as: :authenticate, type: :system do
  4. let(:other_agent) { create(:agent, groups: Group.all) }
  5. let(:ticket) { create(:ticket, group: Group.first) }
  6. def authenticate
  7. Setting.set('checklist', true)
  8. true
  9. end
  10. def perform_item_action(id, action)
  11. page.find(".checklistShow tr[data-id='#{id}'] .js-action", wait: 0).click
  12. page.find(".checklistShow tr[data-id='#{id}'] li[data-table-action='#{action}']", wait: 0).click
  13. rescue => e
  14. retry_click ||= 5
  15. retry_click -= 1
  16. sleep 1
  17. raise e if retry_click < 1
  18. retry
  19. end
  20. def perform_checklist_action(text)
  21. click '.sidebar[data-tab=checklist] .js-actions'
  22. click_on text
  23. rescue => e
  24. retry_click ||= 5
  25. retry_click -= 1
  26. sleep 1
  27. raise e if retry_click < 1
  28. retry
  29. end
  30. before do
  31. visit "#ticket/zoom/#{ticket.id}"
  32. end
  33. it 'does show the sidebar for the checklists' do
  34. expect(page).to have_css('.tabsSidebar-tab[data-tab=checklist]')
  35. Setting.set('checklist', false)
  36. expect(page).to have_no_css('.tabsSidebar-tab[data-tab=checklist]')
  37. end
  38. it 'does create a checklist' do
  39. click '.tabsSidebar-tab[data-tab=checklist]'
  40. expect(page).to have_button('Add empty checklist')
  41. click_on('Add empty checklist')
  42. expect(page).to have_no_button('Add empty checklist')
  43. wait.until { Checklist.where(ticket: ticket).present? }
  44. end
  45. it 'does show handle subscriptions for badge when sidebar is not opened' do
  46. create(:checklist, ticket: ticket)
  47. expect(page).to have_css(".tabsSidebar-tab[data-tab='checklist'] .js-tabCounter", text: ticket.checklist.items.count)
  48. end
  49. context 'when checklist exists' do
  50. let(:checklist) { create(:checklist, ticket: ticket) }
  51. let(:item) { checklist.items.last }
  52. before do
  53. checklist
  54. click '.tabsSidebar-tab[data-tab=checklist]'
  55. wait.until { page.text.include?(checklist.name) }
  56. await_empty_ajax_queue
  57. end
  58. it 'does show handle subscriptions' do
  59. item.update(text: SecureRandom.uuid)
  60. expect(page).to have_text(item.text)
  61. item.destroy
  62. expect(page).to have_no_text(item.text)
  63. checklist.destroy
  64. expect(page).to have_button('Add empty checklist')
  65. end
  66. it 'does remove the checklist' do
  67. perform_checklist_action('Remove checklist')
  68. click_on 'delete'
  69. expect(page).to have_text('Add empty checklist')
  70. end
  71. it 'does rename the checklist' do
  72. perform_checklist_action('Rename checklist')
  73. checklist_name = SecureRandom.uuid
  74. find('#checklistTitleEditText').fill_in with: checklist_name, fill_options: { clear: :backspace }
  75. page.find('.js-confirm').click
  76. wait.until { checklist.reload.name == checklist_name }
  77. end
  78. it 'does add item' do
  79. find('.checklistShowButtons .js-add').click
  80. wait.until { checklist.items.last.text == '' }
  81. end
  82. it 'does check item' do
  83. perform_item_action(item.id, 'check')
  84. wait.until { item.reload.checked == true }
  85. end
  86. it 'does uncheck item' do
  87. item.update(checked: true)
  88. perform_item_action(item.id, 'uncheck')
  89. wait.until { item.reload.checked == false }
  90. end
  91. it 'does edit item' do
  92. perform_item_action(item.id, 'edit')
  93. item_text = SecureRandom.uuid
  94. find(".checklistShow tr[data-id='#{item.id}'] .js-input").fill_in with: item_text, fill_options: { clear: :backspace }
  95. page.find('.js-confirm').click
  96. wait.until { item.reload.text == item_text }
  97. end
  98. it 'does edit item with a ticket link' do
  99. perform_item_action(item.id, 'edit')
  100. item_text = "Ticket##{Ticket.first.number}"
  101. find(".checklistShow tr[data-id='#{item.id}'] .js-input").fill_in with: item_text, fill_options: { clear: :backspace }
  102. page.find('.js-confirm').click
  103. expect(page).to have_link(Ticket.first.title)
  104. end
  105. it 'does reorder item' do
  106. click_on 'Reorder'
  107. first_item = checklist.items.first
  108. last_item = checklist.items.last
  109. element = page.find(".checklistShow tr[data-id='#{first_item.id}'] .draggable")
  110. element.drag_to(page.find(".checklistShow tr[data-id='#{last_item.id}'] .draggable"))
  111. click_on 'Save'
  112. wait.until { page.text.index(first_item.text) > page.text.index(last_item.text) }
  113. wait.until { checklist.reload.sorted_item_ids.last.to_s == first_item.id.to_s }
  114. end
  115. it 'does not abort edit when subscription is updating but including it afterwards' do
  116. perform_item_action(item.id, 'edit')
  117. item_text = SecureRandom.uuid
  118. find(".checklistShow tr[data-id='#{item.id}'] .js-input").fill_in with: item_text, fill_options: { clear: :backspace }
  119. # simulate other users change
  120. other_item_text = SecureRandom.uuid
  121. checklist.items.create!(text: other_item_text, created_by: other_agent, updated_by: other_agent)
  122. # not really another way to be absolutely sure that this works
  123. sleep 5
  124. # the new item will be synced after saving
  125. expect(page).to have_no_text(other_item_text)
  126. # it's important that the old edit mode does not abort
  127. page.find('.js-confirm').click
  128. # then both items arrive in the UI
  129. expect(page).to have_text(item_text)
  130. expect(page).to have_text(other_item_text)
  131. end
  132. it 'does delete item' do
  133. perform_item_action(item.id, 'delete')
  134. click_on 'delete'
  135. wait.until { Checklist::Item.find_by(id: item.id).blank? }
  136. end
  137. context 'with links' do
  138. let(:checklist) do
  139. checklist = create(:checklist, ticket: ticket)
  140. checklist.items.last.update(text: 'http://google.de test')
  141. checklist
  142. end
  143. it 'does edit item with link' do
  144. expect(page).to have_link('google.de')
  145. perform_item_action(item.id, 'edit')
  146. item_text = SecureRandom.uuid
  147. find(".checklistShow tr[data-id='#{item.id}'] .js-input").fill_in with: item_text, fill_options: { clear: :backspace }
  148. page.find('.js-confirm').click
  149. wait.until { item.reload.text == item_text }
  150. end
  151. end
  152. context 'with ticket links' do
  153. context 'with access' do
  154. let(:ticket_link) { create(:ticket, title: SecureRandom.uuid, group: Group.first) }
  155. let(:checklist) do
  156. checklist = create(:checklist, ticket: ticket)
  157. checklist.items.last.update(text: "Ticket##{ticket_link.number}")
  158. checklist
  159. end
  160. it 'does show link to the ticket' do
  161. expect(page).to have_link(ticket_link.title)
  162. end
  163. end
  164. context 'without access' do
  165. let(:ticket_link) { create(:ticket, title: SecureRandom.uuid) }
  166. let(:checklist) do
  167. checklist = create(:checklist, ticket: ticket)
  168. checklist.items.last.update(text: "Ticket##{ticket_link.number}")
  169. checklist
  170. end
  171. it 'does show the not authorized for the item' do
  172. expect(page).to have_text('Not authorized')
  173. end
  174. end
  175. end
  176. end
  177. context 'when using a checklist template' do
  178. let(:checklist_template) { create(:checklist_template) }
  179. before do
  180. checklist_template
  181. click '.tabsSidebar-tab[data-tab=checklist]'
  182. wait.until { page.find('[name="checklist_template_id"]') }
  183. await_empty_ajax_queue
  184. end
  185. it 'does add checklist from template' do
  186. expect(page).to have_button('Add from a template')
  187. expect(page).to have_select('checklist_template_id')
  188. # Sometimes, by clicking the button, nothing happens.
  189. sleep 0.1
  190. click_on('Add from a template')
  191. wait.until { page.has_content?('Please select a checklist template.') }
  192. select checklist_template.name, from: 'checklist_template_id'
  193. wait.until { page.has_no_content?('Please select a checklist template.') }
  194. click_on('Add from a template')
  195. wait.until { Checklist.where(ticket: ticket).present? }
  196. expect(Checklist.where(ticket: ticket).last.items.count).to eq(checklist_template.items.count)
  197. checklist_template.items.each do |item|
  198. expect(page).to have_text(item.text)
  199. end
  200. end
  201. end
  202. context 'when checklist modal on submit' do
  203. let(:checklist) { create(:checklist, ticket: ticket, name: SecureRandom.uuid) }
  204. def authenticate
  205. pre_auth
  206. true
  207. end
  208. context 'when activated and set' do
  209. let(:pre_auth) do
  210. Setting.set('checklist', true)
  211. checklist
  212. end
  213. it 'does show modal' do
  214. select 'closed', from: 'State'
  215. click '.js-submit'
  216. expect(page).to have_text('You have unchecked items in the checklist')
  217. end
  218. it 'does switch to sidebar' do
  219. select 'closed', from: 'State'
  220. click '.js-submit'
  221. page.find('.modal-footer .js-submit').click
  222. expect(page).to have_text(checklist.name.upcase)
  223. end
  224. context 'when ticket is closed' do
  225. let(:pre_auth) do
  226. Setting.set('checklist', true)
  227. checklist
  228. other_agent
  229. ticket.update(state: Ticket::State.find_by(name: 'closed'))
  230. end
  231. it 'does not show modal' do
  232. select other_agent.fullname, from: 'Owner'
  233. click '.js-submit'
  234. wait.until { ticket.reload.owner.fullname == other_agent.fullname }
  235. expect(page).to have_no_text('You have unchecked items in the checklist')
  236. end
  237. end
  238. context 'when time accounting is also activated' do
  239. let(:pre_auth) do
  240. Setting.set('checklist', true)
  241. Setting.set('time_accounting', true)
  242. checklist
  243. end
  244. it 'does show both modals' do
  245. find('.articleNewEdit-body').send_keys('Forwarding with the attachment')
  246. select 'closed', from: 'State'
  247. click '.js-submit'
  248. expect(page.find('.modal-body')).to have_text('You have unchecked items in the checklist')
  249. page.find('.modal-footer .js-skip').click
  250. expect(page.find('.modal-body')).to have_text('Accounted Time'.upcase)
  251. page.find('.modal-footer .js-skip').click
  252. wait.until { ticket.reload.state.name == 'closed' }
  253. end
  254. end
  255. end
  256. context 'when deactivated and set' do
  257. let(:pre_auth) do
  258. Setting.set('checklist', false)
  259. checklist
  260. end
  261. it 'does not show modal' do
  262. select 'closed', from: 'State'
  263. click '.js-submit'
  264. wait.until { ticket.reload.state.name == 'closed' }
  265. expect(page).to have_no_text('You have unchecked items in the checklist')
  266. end
  267. end
  268. context 'when activated and completed' do
  269. let(:pre_auth) do
  270. Setting.set('checklist', true)
  271. checklist.items.map { |item| item.update(checked: true) }
  272. end
  273. it 'does not show modal' do
  274. select 'closed', from: 'State'
  275. click '.js-submit'
  276. wait.until { ticket.reload.state.name == 'closed' }
  277. expect(page).to have_no_text('You have unchecked items in the checklist')
  278. end
  279. end
  280. context 'when activated and no checklist' do
  281. let(:pre_auth) do
  282. Setting.set('checklist', true)
  283. end
  284. it 'does not show modal' do
  285. select 'closed', from: 'State'
  286. click '.js-submit'
  287. wait.until { ticket.reload.state.name == 'closed' }
  288. expect(page).to have_no_text('You have unchecked items in the checklist')
  289. end
  290. end
  291. end
  292. end