ticket_create_spec.rb 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. require 'rails_helper'
  3. require 'system/apps/mobile_old/examples/core_workflow_examples'
  4. RSpec.describe 'Mobile > Ticket > Create', app: :mobile, authenticated_as: :user, type: :system do
  5. let(:group) { Group.find_by(name: 'Users') }
  6. let(:user) { create(:agent, groups: [group]) }
  7. let!(:customer) { create(:customer) }
  8. def next_step
  9. find_button('Continue').click
  10. end
  11. def check_is_step(step)
  12. expect(find("button[order=\"#{step}\"]").disabled?).to be(true)
  13. end
  14. def go_to_step(step)
  15. find("button[order=\"#{step}\"]").click
  16. end
  17. def submit_form
  18. find_button('Create').click
  19. wait_for_gql('shared/entities/ticket/graphql/mutations/create.graphql')
  20. end
  21. def check_is_focused(element)
  22. wait.until do
  23. page.driver.browser.switch_to.active_element == element.native
  24. end
  25. end
  26. before do
  27. visit '/tickets/create'
  28. wait_for_form_to_settle('ticket-create')
  29. end
  30. shared_examples 'creating a ticket' do |article_type:, direction: nil, redirect: nil|
  31. it 'can complete all steps' do
  32. expect(find_button('Create', disabled: true).disabled?).to be(true)
  33. within_form(form_updater_gql_number: 1) do
  34. # Step 1.
  35. find_input('Title').type(Faker::Name.unique.name_with_middle)
  36. next_step
  37. # Step 2.
  38. case article_type
  39. when 'email'
  40. find_radio('articleSenderType').select_choice('Send Email')
  41. when 'phone'
  42. if direction == 'out'
  43. find_radio('articleSenderType').select_choice('Outbound Call')
  44. end
  45. end
  46. find_select('Group').select_option('Users') if article_type == 'web'
  47. next_step
  48. if article_type != 'web'
  49. # Step 3.
  50. find_autocomplete('Customer').search_for_option(customer.email, label: customer.fullname)
  51. find_autocomplete('CC') if article_type == 'email'
  52. next_step
  53. end
  54. # Step 4.
  55. find_editor('Text').type(Faker::Hacker.say_something_smart)
  56. end
  57. submit_form
  58. find('[role=alert]', text: 'Ticket has been created successfully.')
  59. expect(page).to have_current_path(redirect || "/mobile/tickets/#{Ticket.last.id}")
  60. expect(Ticket.last.create_article_type_id).to eq(Ticket::Article::Type.find_by(name: article_type).id)
  61. end
  62. end
  63. context 'with different article types' do
  64. it_behaves_like 'creating a ticket', article_type: 'phone'
  65. it_behaves_like 'creating a ticket', article_type: 'phone', direction: 'out'
  66. it_behaves_like 'creating a ticket', article_type: 'email'
  67. context 'when dont have a "read" permission, but have "create" permission' do
  68. it_behaves_like 'creating a ticket', article_type: 'email', redirect: '/mobile/' do
  69. before do
  70. user.group_names_access_map = {
  71. group.name => ['create']
  72. }
  73. end
  74. end
  75. end
  76. context 'when a customer', authenticated_as: :customer do
  77. it_behaves_like 'creating a ticket', article_type: 'web'
  78. end
  79. end
  80. context 'with signatures' do
  81. let(:signature1) { create(:signature, body: '<strong>custom signature</strong>') }
  82. let(:group1) { create(:group, signature: signature1) }
  83. let(:group2) { Group.find_by(name: 'Users') }
  84. let(:group3) { create(:group) }
  85. let(:user) { create(:agent, groups: [group1, group2, group3]) }
  86. it 'adds signature' do
  87. within_form(form_updater_gql_number: 1) do
  88. find_input('Title').type(Faker::Name.unique.name_with_middle)
  89. next_step
  90. find_radio('articleSenderType').select_choice('Send Email')
  91. next_step
  92. next_step
  93. # only label is rendered as text
  94. expect(find_editor('Text')).to have_text_value('', exact: true)
  95. go_to_step(3)
  96. find_select('Group').select_option('Users')
  97. go_to_step(4)
  98. expect(find_editor('Text')).to have_text_value(user.fullname) # default signature is added
  99. end
  100. end
  101. it 'changes signature, when group is changed' do
  102. within_form(form_updater_gql_number: 1) do
  103. find_input('Title').type(Faker::Name.unique.name_with_middle)
  104. next_step
  105. find_radio('articleSenderType').select_choice('Send Email')
  106. next_step
  107. find_select('Group').select_option('Users')
  108. next_step
  109. expect(find_editor('Text')).to have_text_value(user.fullname)
  110. go_to_step(3)
  111. find_select('Group').select_option(group1.name)
  112. next_step
  113. expect(find_editor('Text')).to have_text_value('custom signature')
  114. end
  115. end
  116. it 'removes signature, when another group without signature is selected' do
  117. within_form(form_updater_gql_number: 1) do
  118. find_input('Title').type(Faker::Name.unique.name_with_middle)
  119. next_step
  120. find_radio('articleSenderType').select_choice('Send Email')
  121. next_step
  122. find_select('Group').select_option('Users')
  123. next_step
  124. expect(find_editor('Text')).to have_text_value(user.fullname)
  125. go_to_step(3)
  126. find_select('Group').select_option(group3.name)
  127. next_step
  128. expect(find_editor('Text')).to have_text_value('', exact: true)
  129. end
  130. end
  131. it 'removes signature when type is not email' do
  132. within_form(form_updater_gql_number: 1) do
  133. find_input('Title').type(Faker::Name.unique.name_with_middle)
  134. next_step
  135. find_radio('articleSenderType').select_choice('Send Email')
  136. next_step
  137. find_select('Group').select_option('Users')
  138. next_step
  139. expect(find_editor('Text')).to have_text_value(user.fullname)
  140. go_to_step(2)
  141. find_radio('articleSenderType').select_choice('Outbound Call')
  142. go_to_step(4)
  143. # only label is rendered as text
  144. expect(find_editor('Text')).to have_text_value('', exact: true)
  145. end
  146. end
  147. it 'removes signature when group is deselected' do
  148. within_form(form_updater_gql_number: 1) do
  149. find_input('Title').type(Faker::Name.unique.name_with_middle)
  150. next_step
  151. find_radio('articleSenderType').select_choice('Send Email')
  152. next_step
  153. find_select('Group').select_option('Users')
  154. next_step
  155. expect(find_editor('Text')).to have_text_value(user.fullname)
  156. go_to_step(3)
  157. find_select('Group').clear_selection
  158. go_to_step(4)
  159. # only label is rendered as text
  160. expect(find_editor('Text')).to have_text_value('', exact: true)
  161. end
  162. end
  163. end
  164. # TODO: Frontend tests!?
  165. context 'with entered form fields' do
  166. it 'remembers the data when switching between steps' do
  167. within_form(form_updater_gql_number: 1) do
  168. # Step 1.
  169. title = Faker::Name.unique.name_with_middle
  170. find_input('Title').type(title)
  171. next_step
  172. # Step 2.
  173. type = 'Outbound Call'
  174. find_radio('articleSenderType').select_choice(type)
  175. next_step
  176. # Step 3.
  177. find_autocomplete('Customer').search_for_option(customer.email, label: customer.fullname)
  178. next_step
  179. # Step 4.
  180. body = Faker::Hacker.say_something_smart
  181. find_editor('Text').type(body)
  182. # Step 1.
  183. go_to_step(1)
  184. expect(find_input('Title')).to have_value(title)
  185. # Step 3.
  186. go_to_step(3)
  187. expect(find_autocomplete('Customer')).to have_selected_option(customer.fullname)
  188. # Step 2.
  189. go_to_step(2)
  190. expect(find_radio('articleSenderType')).to have_selected_choice(type)
  191. # Step 4.
  192. go_to_step(4)
  193. expect(find_editor('Text')).to have_text_value(body)
  194. end
  195. end
  196. it 'shows a confirmation dialog when leaving the screen' do
  197. within_form(form_updater_gql_number: 1) do
  198. find_input('Title').type(Faker::Name.unique.name_with_middle)
  199. end
  200. find_button('Go home').click
  201. within '[role=alert]' do
  202. expect(page).to have_text('Are you sure? You have unsaved changes that will get lost.')
  203. end
  204. end
  205. it 'fills out new customer when it\'s created in place' do
  206. within_form(form_updater_gql_number: 1) do
  207. find_input('Title').type(Faker::Name.unique.name_with_middle)
  208. next_step
  209. next_step
  210. find_autocomplete('Customer').element.click
  211. find_button('Create new customer').click
  212. find_input('First name').type('John')
  213. find_input('Last name').type('Doe')
  214. click_on('Save')
  215. expect(find_autocomplete('Customer')).to have_selected_option('John Doe')
  216. end
  217. end
  218. end
  219. context 'with accessibility support' do
  220. it 'focuses first visible field when switching between steps' do
  221. wait_for_form_autofocus('ticket-create')
  222. # Step 1.
  223. check_is_focused find_input('Title').input_element
  224. next_step
  225. # Step 2.
  226. check_is_focused find_radio('articleSenderType').find('label', text: 'Received Call').find('input')
  227. next_step
  228. # Step 3.
  229. check_is_focused find_autocomplete('Customer').input_element
  230. next_step
  231. # Step 4.
  232. check_is_focused find_editor('Text').input_element
  233. # Step 1.
  234. go_to_step(1)
  235. check_is_focused find_input('Title').input_element
  236. # Step 3.
  237. go_to_step(3)
  238. check_is_focused find_autocomplete('Customer').input_element
  239. # Step 2.
  240. go_to_step(2)
  241. check_is_focused find_radio('articleSenderType').find('label', text: 'Received Call').find('input')
  242. # Step 4.
  243. go_to_step(4)
  244. check_is_focused find_editor('Text').input_element
  245. end
  246. it 'advances to the next step on submit' do
  247. find_input('Title').input_element.send_keys :enter
  248. check_is_step(2)
  249. find_radio('articleSenderType').find('label', text: 'Received Call').find('input').send_keys :enter
  250. check_is_step(3)
  251. end
  252. context 'with many object attributes', authenticated_as: :authenticate, db_strategy: :reset do
  253. let(:screens) do
  254. {
  255. create_middle: {
  256. '-all-' => {
  257. shown: true,
  258. required: false,
  259. },
  260. },
  261. }
  262. end
  263. def authenticate
  264. create(:object_manager_attribute_select, screens: screens)
  265. create(:object_manager_attribute_text, screens: screens)
  266. create(:object_manager_attribute_tree_select, screens: screens)
  267. create(:object_manager_attribute_select, screens: screens)
  268. ObjectManager::Attribute.migration_execute
  269. true
  270. end
  271. it 'can interact with the fields at the bottom of the form without any obstructions' do
  272. # Step 3.
  273. next_step
  274. next_step
  275. # Tags is the last field in the form.
  276. # In case the field is obscured, the following action would fail.
  277. find_autocomplete('Tags').search_for_option('tag 1')
  278. end
  279. end
  280. end
  281. context 'when using ticket create as customer' do
  282. let(:group1) { Group.find_by(name: 'Users') }
  283. let(:user) { create(:customer, :with_org, groups: [group1]) }
  284. shared_examples 'can complete all steps as customer' do
  285. it 'can complete all steps' do
  286. within_form(form_updater_gql_number: 1) do
  287. find_input('Title').type(Faker::Name.unique.name_with_middle)
  288. next_step
  289. find_select('Group').select_option('Users')
  290. if organizations
  291. find_select('Organization').select_option(organizations.last.name)
  292. else
  293. expect(page).to have_no_select('Organization')
  294. end
  295. next_step
  296. find_editor('Text').type(Faker::Hacker.say_something_smart)
  297. end
  298. submit_form
  299. find('[role=alert]', text: 'Ticket has been created successfully.')
  300. expect(page).to have_current_path("/mobile/tickets/#{Ticket.last.id}")
  301. end
  302. end
  303. context 'with secondary organizations' do
  304. include_examples 'can complete all steps as customer' do
  305. let(:user) { create(:customer, :with_org, organizations: organizations, groups: [group1]) }
  306. let(:organizations) { create_list(:organization, 3) }
  307. end
  308. end
  309. context 'without secondary organizations' do
  310. include_examples 'can complete all steps as customer' do
  311. let(:organizations) { nil }
  312. end
  313. end
  314. end
  315. context 'when using suggestions' do
  316. let(:text_option) { create(:text_module, name: 'test', content: "Hello, \#{ticket.customer.firstname}!") }
  317. it 'text suggestion parses correctly' do
  318. within_form(form_updater_gql_number: 1) do
  319. find_input('Title').type(Faker::Name.unique.name_with_middle)
  320. next_step
  321. next_step
  322. find_autocomplete('Customer').search_for_option(customer.email, label: customer.fullname)
  323. next_step
  324. editor = find_editor('Text')
  325. # only label is rendered as text
  326. expect(editor).to have_text_value('', exact: true)
  327. editor.type('::test')
  328. find('[role="option"]', text: text_option.name).click
  329. expect(editor).to have_text_value("Hello, #{customer.firstname}!")
  330. end
  331. end
  332. end
  333. describe 'Core Workflow' do
  334. include_examples 'mobile app: core workflow' do
  335. let(:object_name) { 'Ticket' }
  336. let(:form_updater_gql_number) { 2 }
  337. let(:before_it) do
  338. lambda {
  339. visit '/tickets/create'
  340. wait_for_form_to_settle('ticket-create')
  341. within_form(form_updater_gql_number: 1) do
  342. find_input('Title').type(Faker::Name.unique.name_with_middle)
  343. end
  344. next_step
  345. next_step
  346. }
  347. end
  348. end
  349. end
  350. end