simultaneously_with_two_user_spec.rb 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. require 'rails_helper'
  3. RSpec.describe 'Ticket > Update > Simultaneously with two different user', type: :system do
  4. let(:group) { Group.find_by(name: 'Users') }
  5. let(:ticket) { create(:ticket, group: group) }
  6. let(:agent) { User.find_by(login: 'agent1@example.com') }
  7. # rubocop:disable RSpec/InstanceVariable
  8. define :have_avatar do |expected|
  9. chain(:changed, :text)
  10. match do
  11. elem = find_element
  12. return false if elem.nil?
  13. return true if !@icon && !@no_icon
  14. return elem.has_no_css? '.icon' if @no_icon
  15. elem.has_css? ".icon-#{@icon}"
  16. end
  17. def find_element
  18. if expected.is_a? User
  19. actual.find "#{base_selector}#{select_by_user}"
  20. else
  21. actual.find base_selector, text: expected
  22. end
  23. rescue
  24. nil
  25. end
  26. match_when_negated do
  27. if expected.is_a? User
  28. return actual.has_no_css? "#{base_selector}#{select_by_user}"
  29. end
  30. actual.has_no_css? base_selector, text: expected
  31. end
  32. chain :changed! do
  33. @changed = true
  34. end
  35. chain :with_icon do |icon|
  36. @icon = icon
  37. end
  38. chain :with_no_icon! do
  39. @no_icon = true
  40. end
  41. def select_by_user
  42. "[data-id='#{expected.id}']"
  43. end
  44. def base_selector
  45. changed_class = @changed ? 'changed' : 'not-changed'
  46. ".js-attributeBar .js-avatar .avatar--#{changed_class}"
  47. end
  48. end
  49. # rubocop:enable RSpec/InstanceVariable
  50. def check_taskbar_tab(ticket_id, title: nil, modified: false)
  51. tab_data_key = "Ticket-#{ticket_id}"
  52. if title
  53. taskbar_tab = find(".tasks .task[data-key='#{tab_data_key}']")
  54. expect(taskbar_tab).to have_css('.nav-tab-name', text: title)
  55. end
  56. if modified
  57. expect(page).to have_css(".tasks .task[data-key='#{tab_data_key}'].is-modified")
  58. else
  59. expect(page).to have_no_css(".tasks .task[data-key='#{tab_data_key}'].is-modified")
  60. end
  61. end
  62. context 'when two different users are simultaneously in one ticket' do
  63. before do
  64. visit "#ticket/zoom/#{ticket.id}"
  65. using_session(:second_browser) do
  66. login(
  67. username: agent.login,
  68. password: 'test',
  69. )
  70. visit "#ticket/zoom/#{ticket.id}"
  71. end
  72. end
  73. it 'avatar from other user should be visible in ticket zoom' do
  74. expect(page).to have_avatar('AT')
  75. using_session(:second_browser) do
  76. expect(page).to have_avatar('TA')
  77. end
  78. end
  79. it 'check changes from the first user and added changes from the second user' do
  80. within(:active_content) do
  81. find('.js-textarea').send_keys('some note')
  82. expect(page).to have_css('.js-reset')
  83. end
  84. expect(page).to have_avatar('AT')
  85. using_session(:second_browser) do
  86. expect(page).to have_avatar('TA').changed!
  87. within(:active_content) do
  88. find('.js-textarea').send_keys('some other note')
  89. expect(page).to have_css('.js-reset')
  90. end
  91. end
  92. expect(page).to have_avatar('AT').changed!
  93. using_session(:second_browser) do
  94. within(:active_content) do
  95. click '.js-attributeBar .js-submit'
  96. expect(page).to have_no_css('.js-reset')
  97. expect(page).to have_css('.article-content', text: 'some other note')
  98. end
  99. expect(page).to have_avatar('TA').changed!
  100. end
  101. expect(page).to have_avatar('AT')
  102. check_taskbar_tab(ticket.id, title: ticket.title, modified: true)
  103. within(:active_content) do
  104. expect(page).to have_css('.article-content', text: 'some other note')
  105. click '.js-attributeBar .js-submit'
  106. expect(page).to have_no_css('.js-reset')
  107. expect(page).to have_css('.article-content', text: 'some note')
  108. end
  109. using_session(:second_browser) do
  110. expect(page).to have_avatar('TA')
  111. expect(page).to have_css('.article-content', text: 'some note')
  112. check_taskbar_tab(ticket.id, title: ticket.title, modified: true)
  113. end
  114. # Reload browsers and check if state is correct.
  115. refresh
  116. using_session(:second_browser) do
  117. refresh
  118. expect(page).to have_avatar('TA')
  119. expect(page).to have_no_css('.js-reset')
  120. end
  121. expect(page).to have_avatar('AT')
  122. expect(page).to have_no_css('.js-reset')
  123. end
  124. it 'check refresh for unsaved changes and reset after refresh' do
  125. using_session(:second_browser) do
  126. within(:active_content) do
  127. find('.js-textarea').send_keys('some other note')
  128. expect(page).to have_css('.js-reset')
  129. end
  130. expect(page).to have_avatar('TA')
  131. # We need to wait for the auto save feature.
  132. wait.until do
  133. Taskbar.find_by(key: "Ticket-#{ticket.id}", user_id: agent.id).state_changed?
  134. end
  135. refresh
  136. end
  137. expect(page).to have_avatar('AT').changed!
  138. using_session(:second_browser) do
  139. refresh
  140. within(:active_content) do
  141. click '.js-reset'
  142. expect(page).to have_css('.js-textarea', text: '')
  143. end
  144. end
  145. expect(page).to have_avatar('AT')
  146. end
  147. it 'change title with second user' do
  148. find('.js-textarea').send_keys('some note')
  149. using_session(:second_browser) do
  150. find('.js-textarea').send_keys('some other note')
  151. find('.ticketZoom-header .js-objectTitle').set('TTTsome level 2 <b>subject</b> 123äöü')
  152. # Click in the body field, to trigger the title update.
  153. find('.js-textarea').send_keys('trigger title')
  154. expect(page).to have_css('.js-objectTitle', text: 'TTTsome level 2 <b>subject</b> 123äöü')
  155. check_taskbar_tab(ticket.id, title: 'TTTsome level 2 <b>subject</b> 123äöü')
  156. expect(page).to have_css('.js-textarea', text: 'some other note')
  157. end
  158. expect(page).to have_css('.js-objectTitle', text: 'TTTsome level 2 <b>subject</b> 123äöü')
  159. expect(page).to have_css('.js-textarea', text: 'some note')
  160. check_taskbar_tab(ticket.id, title: 'TTTsome level 2 <b>subject</b> 123äöü', modified: true)
  161. # Refresh and check that modified flag is gone
  162. refresh
  163. check_taskbar_tab(ticket.id, title: 'TTTsome level 2 <b>subject</b> 123äöü', modified: false)
  164. end
  165. end
  166. context 'when working on multiple platforms', authenticated_as: :user do
  167. let(:ticket) { create(:ticket) }
  168. let(:user) { create(:agent, groups: [ticket.group]) }
  169. let(:another_user) { create(:agent, groups: [ticket.group]) }
  170. let(:key) { "Ticket-#{ticket.id}" }
  171. let(:path) { "ticket/zoom/#{ticket.id}" }
  172. let(:taskbar_mobile) { create(:taskbar, user: user, app: :mobile, key: key) }
  173. let(:taskbar_desktop) { create(:taskbar, user: user, app: :desktop, key: key) }
  174. let(:another_taskbar_mobile) { create(:taskbar, user: another_user, app: :mobile, key: key) }
  175. let(:another_taskbar_desktop) { create(:taskbar, user: another_user, app: :desktop, key: key) }
  176. context 'when looking on a ticket' do
  177. before do
  178. taskbar_desktop
  179. visit path
  180. end
  181. it 'does not show current user' do
  182. expect(page).not_to have_avatar(user)
  183. end
  184. end
  185. context 'when another user is looking on desktop' do
  186. before do
  187. another_taskbar_desktop
  188. taskbar_desktop
  189. visit path
  190. end
  191. it 'shows another user' do
  192. expect(page).to have_avatar(another_user).with_no_icon!
  193. end
  194. end
  195. context 'when another user is looking on mobile' do
  196. before do
  197. another_taskbar_mobile
  198. taskbar_desktop
  199. visit path
  200. end
  201. it 'shows another user' do
  202. expect(page).to have_avatar(another_user).with_icon(:mobile)
  203. end
  204. end
  205. context 'when another user is looking on mobile and desktop' do
  206. before do
  207. another_taskbar_mobile
  208. another_taskbar_desktop
  209. taskbar_desktop
  210. visit path
  211. end
  212. it 'shows another user' do
  213. expect(page).to have_avatar(another_user).with_no_icon!
  214. end
  215. end
  216. context 'when another user is editing on desktop' do
  217. before do
  218. another_taskbar_desktop.update!(state: { a: 1 })
  219. taskbar_desktop
  220. visit path
  221. end
  222. it 'shows another user' do
  223. expect(page).to have_avatar(another_user).with_icon(:pen).changed!
  224. end
  225. end
  226. context 'when another user is editing on mobile' do
  227. before do
  228. another_taskbar_mobile.update!(state: { a: 1 })
  229. taskbar_desktop
  230. visit path
  231. end
  232. it 'shows another user' do
  233. expect(page).to have_avatar(another_user).with_icon(:pen).changed!
  234. end
  235. end
  236. context 'when same user is looking on mobile too' do
  237. before do
  238. taskbar_mobile
  239. taskbar_desktop
  240. visit path
  241. end
  242. it 'shows same user' do
  243. expect(page).not_to have_avatar(user)
  244. end
  245. end
  246. context 'when same user is editing' do
  247. before do
  248. taskbar_desktop.update!(state: { a: 1 })
  249. visit path
  250. end
  251. it 'do not show same user' do
  252. expect(page).not_to have_avatar(user)
  253. end
  254. end
  255. context 'when same user is editing on mobile' do
  256. before do
  257. taskbar_mobile.update!(state: { a: 1 })
  258. taskbar_desktop
  259. visit path
  260. end
  261. it 'shows same user' do
  262. expect(page).to have_avatar(user).with_icon(:'mobile-edit').changed!
  263. end
  264. end
  265. end
  266. end