create_spec.rb 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451
  1. # Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/
  2. require 'rails_helper'
  3. require 'system/examples/core_workflow_examples'
  4. require 'system/examples/text_modules_examples'
  5. RSpec.describe 'Ticket Create', type: :system do
  6. context 'when calling without session' do
  7. describe 'redirect to' do
  8. it 'login screen after certain create was called', authenticated_as: false do
  9. visit '#ticket/create/id/1234'
  10. expect(page).to have_selector('#login')
  11. end
  12. it 'login screen after generic create was called', authenticated_as: false do
  13. visit '#ticket/create'
  14. expect(page).to have_selector('#login')
  15. end
  16. end
  17. end
  18. context 'when logged in as non admin' do
  19. let(:agent) { create(:agent) }
  20. it 'show manage templates text only', authenticated_as: :agent do
  21. visit 'ticket/create'
  22. expect(page).to have_no_css('div.js-createLink', visible: :all)
  23. expect(page).to have_no_css('div.js-createTextOnly', visible: :hidden)
  24. end
  25. end
  26. context 'when using the sidebar' do
  27. context 'when using a template' do
  28. before do
  29. visit 'ticket/create'
  30. use_template(create(:template, :dummy_data, customer: create(:customer, :with_org)))
  31. end
  32. it 'does show the edit link for the customer' do
  33. click '.tabsSidebar-tab[data-tab=customer]'
  34. click '#userAction'
  35. click_link 'Edit Customer'
  36. modal_ready
  37. end
  38. it 'does show the edit link for the organization' do
  39. click '.tabsSidebar-tab[data-tab=organization]'
  40. click '#userAction'
  41. click_link 'Edit Organization'
  42. modal_ready
  43. end
  44. end
  45. %w[idoit gitlab github].each do |service_name|
  46. it "#{service_name} tab is hidden" do
  47. visit 'ticket/create'
  48. expect(page).to have_no_css(".tabsSidebar-tab[data-tab=#{service_name}]")
  49. end
  50. context "when #{service_name} is enabled" do
  51. before do
  52. Setting.set("#{service_name}_integration", true)
  53. end
  54. context 'when agent' do
  55. it "#{service_name} tab is visible" do
  56. visit 'ticket/create'
  57. expect(page).to have_css(".tabsSidebar-tab[data-tab=#{service_name}]")
  58. end
  59. end
  60. context 'when customer', authenticated_as: :customer do
  61. let(:customer) { create(:customer) }
  62. it "#{service_name} tab is hidden" do
  63. visit 'customer_ticket_new'
  64. expect(page).to have_no_css(".tabsSidebar-tab[data-tab=#{service_name}]")
  65. end
  66. end
  67. end
  68. end
  69. end
  70. context 'when logged in as admin' do
  71. let(:admin) { create(:admin) }
  72. it 'show manage templates link', authenticated_as: :admin do
  73. visit 'ticket/create'
  74. expect(page).to have_no_css('div.js-createLink', visible: :hidden)
  75. expect(page).to have_no_css('div.js-createTextOnly', visible: :all)
  76. end
  77. end
  78. context 'when applying ticket templates' do
  79. let(:agent) { create(:agent, groups: [permitted_group]) }
  80. let(:permitted_group) { create(:group) }
  81. let(:unpermitted_group) { create(:group) }
  82. let!(:template_unpermitted_group) { create(:template, :dummy_data, group: unpermitted_group, owner: agent) }
  83. let!(:template_permitted_group) { create(:template, :dummy_data, group: permitted_group, owner: agent) }
  84. before { visit 'ticket/create' }
  85. # Regression test for issue #2424 - Unavailable ticket template attributes get applied
  86. it 'unavailable attributes do not get applied', authenticated_as: :agent do
  87. use_template(template_unpermitted_group)
  88. expect(all('[name="group_id"] option', visible: :all).map(&:value)).not_to eq unpermitted_group.id.to_s
  89. expect(find('[name="owner_id"]', visible: :all).value).to eq agent.id.to_s
  90. end
  91. it 'available attributes get applied', authenticated_as: :agent do
  92. use_template(template_permitted_group)
  93. expect(find('[name="group_id"]', visible: :all).value).to eq permitted_group.id.to_s
  94. expect(find('[name="owner_id"]', visible: :all).value).to eq agent.id.to_s
  95. end
  96. context 'with tag values' do
  97. let(:template) do
  98. create(:template,
  99. options: {
  100. 'ticket.tags': {
  101. value: template_value,
  102. operator: operator,
  103. }
  104. })
  105. end
  106. shared_examples 'merging with existing tags in a dirty form' do
  107. it 'merges with existing tags in a dirty form' do
  108. set_tokens_field_value('tags', %w[baz qux foo])
  109. use_template(template)
  110. check_tokens_field_value('tags', ['baz', 'qux', *template_value.split(', ')])
  111. end
  112. end
  113. shared_examples 'replacing tags in a clean form' do
  114. it 'replaces tags in a clean form' do
  115. use_template(template)
  116. check_tokens_field_value('tags', template_value.split(', '), visible: :all)
  117. end
  118. end
  119. shared_examples 'leaving tags empty in a clean form' do
  120. it 'does nothing in a clean form' do
  121. use_template(template)
  122. check_tokens_field_value('tags', '')
  123. end
  124. end
  125. context 'with add operator' do
  126. let(:operator) { 'add' }
  127. let(:template_value) { 'foo, bar' }
  128. it_behaves_like 'replacing tags in a clean form'
  129. it_behaves_like 'merging with existing tags in a dirty form'
  130. end
  131. context 'with remove operator' do
  132. let(:operator) { 'remove' }
  133. let(:template_value) { 'foo, bar' }
  134. it_behaves_like 'leaving tags empty in a clean form'
  135. it 'removes existing tags in a dirty form' do
  136. set_tokens_field_value('tags', %w[foo bar baz qux])
  137. use_template(template)
  138. check_tokens_field_value('tags', %w[baz qux])
  139. end
  140. end
  141. context 'without operator (legacy)' do
  142. let(:operator) { nil }
  143. let(:template_value) { 'foo, bar' }
  144. it_behaves_like 'replacing tags in a clean form'
  145. it_behaves_like 'merging with existing tags in a dirty form'
  146. end
  147. context 'with empty value' do
  148. let(:operator) { nil }
  149. let(:template_value) { nil }
  150. it_behaves_like 'leaving tags empty in a clean form'
  151. it 'leaves existing tags untouched in a dirty form' do
  152. set_tokens_field_value('tags', %w[baz qux])
  153. use_template(template)
  154. check_tokens_field_value('tags', %w[baz qux])
  155. end
  156. end
  157. end
  158. end
  159. context 'when using text modules' do
  160. include_examples 'text modules', path: 'ticket/create'
  161. end
  162. describe 'object manager attributes maxlength', authenticated_as: :authenticate, db_strategy: :reset do
  163. def authenticate
  164. create(:object_manager_attribute_text, :required_screen, name: 'maxtest', display: 'maxtest', data_option: {
  165. 'type' => 'text',
  166. 'maxlength' => 3,
  167. 'null' => true,
  168. 'translate' => false,
  169. 'default' => '',
  170. 'options' => {},
  171. 'relation' => '',
  172. })
  173. ObjectManager::Attribute.migration_execute
  174. true
  175. end
  176. it 'checks ticket create' do
  177. visit 'ticket/create'
  178. within(:active_content) do
  179. fill_in 'maxtest', with: 'hellu'
  180. expect(page.find_field('maxtest').value).to eq('hel')
  181. end
  182. end
  183. end
  184. describe 'object manager attributes default date', time_zone: 'Europe/London' do
  185. before :all do # rubocop:disable RSpec/BeforeAfterAll
  186. screens = {
  187. 'create_top' => {
  188. '-all-' => {
  189. 'null' => true
  190. }
  191. },
  192. }
  193. create(:object_manager_attribute_date, name: 'date_test', display: 'date_test', default: 24, screens: screens)
  194. create(:object_manager_attribute_datetime, name: 'datetime_test', display: 'datetime_test', default: 100, screens: screens)
  195. ObjectManager::Attribute.migration_execute # rubocop:disable Zammad/ExistsDbStrategy
  196. end
  197. after :all do # rubocop:disable RSpec/BeforeAfterAll
  198. ObjectManager::Attribute.where(name: %i[date_test datetime_test]).destroy_all
  199. end
  200. before do
  201. visit '/'
  202. template = create(:template, :dummy_data)
  203. travel 1.month
  204. browser_travel_to Time.current
  205. visit 'ticket/create'
  206. use_template template
  207. end
  208. let(:field_date) { find 'input[name="{date}date_test"]', visible: :all }
  209. let(:field_time) { find 'input[name="{datetime}datetime_test"]', visible: :all }
  210. it 'prefills date' do
  211. expect(field_date.value).to eq 1.day.from_now.to_date.to_s
  212. end
  213. it 'prefills datetime' do
  214. expect(Time.zone.parse(field_time.value)).to eq 100.minutes.from_now.change(sec: 0, usec: 0)
  215. end
  216. it 'saves dates' do
  217. click '.js-submit'
  218. date = 1.day.from_now.to_date
  219. time = 100.minutes.from_now.change(sec: 0)
  220. expect(Ticket.last).to have_attributes date_test: date, datetime_test: time
  221. end
  222. it 'allows to save with different values' do
  223. date = 2.days.from_now.to_date
  224. time = 200.minutes.from_now.change(sec: 0)
  225. field_date.sibling('[data-item=date]').set date.strftime('%m/%d/%Y')
  226. field_time.sibling('[data-item=date]').set time.strftime('%m/%d/%Y')
  227. field_time.sibling('[data-item=time]').set time.strftime('%H:%M')
  228. click '.js-submit'
  229. expect(Ticket.last).to have_attributes date_test: date, datetime_test: time
  230. end
  231. it 'allows to save with cleared value' do
  232. field_date.sibling('[data-item=date]').click
  233. find('.datepicker .clear').click
  234. field_time.sibling('[data-item=date]').click
  235. find('.datepicker .clear').click
  236. click '.js-submit'
  237. expect(Ticket.last).to have_attributes date_test: nil, datetime_test: nil
  238. end
  239. end
  240. describe 'GitLab Integration', :integration, authenticated_as: :authenticate, required_envs: %w[GITLAB_ENDPOINT GITLAB_APITOKEN] do
  241. let(:customer) { create(:customer) }
  242. let(:agent) { create(:agent, groups: [Group.find_by(name: 'Users')]) }
  243. let!(:template) { create(:template, :dummy_data, group: Group.find_by(name: 'Users'), owner: agent, customer: customer) }
  244. def authenticate
  245. Setting.set('gitlab_integration', true)
  246. Setting.set('gitlab_config', {
  247. api_token: ENV['GITLAB_APITOKEN'],
  248. endpoint: ENV['GITLAB_ENDPOINT'],
  249. })
  250. true
  251. end
  252. it 'creates a ticket with links' do
  253. visit 'ticket/create'
  254. within(:active_content) do
  255. use_template(template)
  256. # switch to gitlab sidebar
  257. click('.tabsSidebar-tab[data-tab=gitlab]')
  258. click('.sidebar-header-headline.js-headline')
  259. # add issue
  260. click_on 'Link issue'
  261. fill_in 'link', with: ENV['GITLAB_ISSUE_LINK']
  262. click_on 'Submit'
  263. # verify issue
  264. content = find('.sidebar-git-issue-content')
  265. expect(content).to have_text('#1 Example issue')
  266. expect(content).to have_text('critical')
  267. expect(content).to have_text('special')
  268. expect(content).to have_text('important milestone')
  269. expect(content).to have_text('zammad-robot')
  270. # create Ticket
  271. click '.js-submit'
  272. # check stored data
  273. expect(Ticket.last.preferences[:gitlab][:issue_links][0]).to eq(ENV['GITLAB_ISSUE_LINK'])
  274. end
  275. end
  276. end
  277. describe 'GitHub Integration', :integration, authenticated_as: :authenticate, required_envs: %w[GITHUB_ENDPOINT GITHUB_APITOKEN] do
  278. let(:customer) { create(:customer) }
  279. let(:agent) { create(:agent, groups: [Group.find_by(name: 'Users')]) }
  280. let!(:template) { create(:template, :dummy_data, group: Group.find_by(name: 'Users'), owner: agent, customer: customer) }
  281. def authenticate
  282. Setting.set('github_integration', true)
  283. Setting.set('github_config', {
  284. api_token: ENV['GITHUB_APITOKEN'],
  285. endpoint: ENV['GITHUB_ENDPOINT'],
  286. })
  287. true
  288. end
  289. it 'creates a ticket with links' do
  290. visit 'ticket/create'
  291. within(:active_content) do
  292. use_template(template)
  293. # switch to github sidebar
  294. click('.tabsSidebar-tab[data-tab=github]')
  295. click('.sidebar-header-headline.js-headline')
  296. # add issue
  297. click_on 'Link issue'
  298. fill_in 'link', with: ENV['GITHUB_ISSUE_LINK']
  299. click_on 'Submit'
  300. # verify issue
  301. content = find('.sidebar-git-issue-content')
  302. expect(content).to have_text('#1575 GitHub integration')
  303. expect(content).to have_text('enhancement')
  304. expect(content).to have_text('integration')
  305. expect(content).to have_text('4.0')
  306. expect(content).to have_text('Thorsten')
  307. # create Ticket
  308. click '.js-submit'
  309. # check stored data
  310. expect(Ticket.last.preferences[:github][:issue_links][0]).to eq(ENV['GITHUB_ISSUE_LINK'])
  311. end
  312. end
  313. end
  314. describe 'Core Workflow' do
  315. include_examples 'core workflow' do
  316. let(:object_name) { 'Ticket' }
  317. let(:before_it) do
  318. lambda {
  319. ensure_websocket(check_if_pinged: false) do
  320. visit 'ticket/create'
  321. end
  322. }
  323. end
  324. end
  325. end
  326. # https://github.com/zammad/zammad/issues/2669
  327. context 'when canceling new ticket creation' do
  328. it 'closes the dialog' do
  329. visit 'ticket/create'
  330. task_key = find(:task_active)['data-key']
  331. expect { click('.js-cancel') }.to change { has_selector?(:task_with, task_key, wait: 0) }.to(false)
  332. end
  333. it 'asks for confirmation if the dialog was modified' do
  334. visit 'ticket/create'
  335. task_key = find(:task_active)['data-key']
  336. find('[name=title]').fill_in with: 'Title'
  337. click '.js-cancel'
  338. in_modal do
  339. click '.js-submit'
  340. end
  341. expect(page).to have_no_selector(:task_with, task_key)
  342. end
  343. it 'asks for confirmation if attachment was added' do
  344. visit 'ticket/create'
  345. within :active_content do
  346. page.find('input#fileUpload_1[data-initialized="true"]', visible: :all).set(Rails.root.join('test/data/mail/mail001.box'))
  347. await_empty_ajax_queue
  348. expect(page).to have_css('.attachments .attachment-delete', visible: :all)
  349. find('.js-cancel').click
  350. end
  351. in_modal do
  352. expect(page).to have_text 'Tab has changed'
  353. end
  354. end
  355. end
  356. context 'when uploading attachment' do
  357. it 'shows an error if server throws an error' do
  358. allow(Store).to receive(:create!) { raise 'Error' }
  359. visit 'ticket/create'
  360. within :active_content do
  361. page.find('input#fileUpload_1[data-initialized="true"]', visible: :all).set(Rails.root.join('test/data/mail/mail001.box'))
  362. await_empty_ajax_queue
  363. end
  364. in_modal do
  365. expect(page).to have_text 'Error'
  366. end
  367. end
  368. end
  369. context 'when closing taskbar tab for new ticket creation' do
  370. it 'close task bar entry after some changes in ticket create form' do
  371. visit 'ticket/create'
  372. within(:active_content) do
  373. find('[name=title]').fill_in with: 'Title'
  374. end
  375. wait.until { find(:task_active)['data-key'].present? }
  376. taskbar_tab_close(find(:task_active)['data-key'])
  377. end
  378. end
  379. describe 'customer selection to check the field search' do
  380. before do
  381. create(:customer, active: true)
  382. create(:customer, active: false)
  383. end
  384. it 'check for inactive customer in customer/organization selection' do
  385. visit 'ticket/create'
  386. within(:active_content) do
  387. find('[name=customer_id] ~ .user-select.token-input').fill_in with: '**'
  388. expect(page).to have_css('ul.recipientList > li.recipientList-entry', minimum: 2)
  389. expect(page).to have_css('ul.recipientList > li.recipientList-entry.is-inactive', count: 1)
  390. end
  391. end
  392. end
  393. context 'when agent and customer user login after another' do
  394. let(:agent) { create(:agent, password: 'test') }
  395. let(:customer) { create(:customer, password: 'test') }
  396. it 'customer user should not have agent object attributes', authenticated_as: :agent do
  397. # Log out again, so that we can execute the next login.
  398. logout
  399. # Re-create agent session and fetch object attributes.
  400. login(
  401. username: agent.login,
  402. password: 'test'
  403. )
  404. visit 'ticket/create'
  405. # Re-remove local object attributes bound to the session
  406. # there was an issue (#1856) where the old attribute values
  407. # persisted and were stored as the original attributes.
  408. logout
  409. # Create customer session and fetch object attributes.
  410. login(
  411. username: customer.login,
  412. password: 'test'
  413. )
  414. visit 'customer_ticket_new'
  415. expect(page).to have_no_css('.newTicket input[name="customer_id"]')
  416. end
  417. end
  418. context 'when state options have a special translation', authenticated_as: :authenticate do
  419. let(:admin_de) { create(:admin, preferences: { locale: 'de-de' }) }
  420. context 'when translated state option has a single quote' do
  421. def authenticate
  422. open_tranlation = Translation.where(locale: 'de-de', source: 'open')
  423. open_tranlation.update(target: "off'en")
  424. admin_de
  425. end
  426. it 'shows the translated state options correctly' do
  427. visit 'ticket/create'
  428. expect(page).to have_select('state_id', with_options: ["off'en"])
  429. end
  430. end
  431. end
  432. describe 'It should be possible to show attributes which are configured shown false #3726', authenticated_as: :authenticate, db_strategy: :reset do
  433. let(:field_name) { SecureRandom.uuid }
  434. let(:field) do
  435. create(:object_manager_attribute_text, name: field_name, display: field_name, screens: {
  436. 'create_middle' => {
  437. 'ticket.agent' => {
  438. 'shown' => false,
  439. 'required' => false,
  440. }
  441. }
  442. })
  443. ObjectManager::Attribute.migration_execute
  444. end
  445. before do
  446. visit 'ticket/create'
  447. end
  448. context 'when field visible' do
  449. let(:workflow) do
  450. create(:core_workflow,
  451. object: 'Ticket',
  452. perform: { "ticket.#{field_name}" => { 'operator' => 'show', 'show' => 'true' } })
  453. end
  454. def authenticate
  455. field
  456. workflow
  457. true
  458. end
  459. it 'does show up the field' do
  460. expect(page).to have_css("div[data-attribute-name='#{field_name}']")
  461. end
  462. end
  463. context 'when field hidden' do
  464. def authenticate
  465. field
  466. true
  467. end
  468. it 'does not show the field' do
  469. expect(page).to have_css("div[data-attribute-name='#{field_name}'].is-hidden.is-removed", visible: :hidden)
  470. end
  471. end
  472. end
  473. describe 'Support workflow mechanism to do pending reminder state hide pending time use case #3790', authenticated_as: :authenticate do
  474. let(:template) { create(:template, :dummy_data) }
  475. def add_state
  476. Ticket::State.create_or_update(
  477. name: 'pending customer feedback',
  478. state_type: Ticket::StateType.find_by(name: 'pending reminder'),
  479. ignore_escalation: true,
  480. created_by_id: 1,
  481. updated_by_id: 1,
  482. )
  483. end
  484. def update_screens
  485. attribute = ObjectManager::Attribute.get(
  486. object: 'Ticket',
  487. name: 'state_id',
  488. )
  489. attribute.data_option[:filter] = Ticket::State.by_category(:viewable).pluck(:id)
  490. attribute.screens[:create_middle]['ticket.agent'][:filter] = Ticket::State.by_category(:viewable_agent_new).pluck(:id)
  491. attribute.screens[:create_middle]['ticket.customer'][:filter] = Ticket::State.by_category(:viewable_customer_new).pluck(:id)
  492. attribute.screens[:edit]['ticket.agent'][:filter] = Ticket::State.by_category(:viewable_agent_edit).pluck(:id)
  493. attribute.screens[:edit]['ticket.customer'][:filter] = Ticket::State.by_category(:viewable_customer_edit).pluck(:id)
  494. attribute.save!
  495. end
  496. def create_flow
  497. create(:core_workflow,
  498. object: 'Ticket',
  499. condition_selected: { 'ticket.state_id'=>{ 'operator' => 'is', 'value' => Ticket::State.find_by(name: 'pending customer feedback').id.to_s } },
  500. perform: { 'ticket.pending_time'=> { 'operator' => 'remove', 'remove' => 'true' } })
  501. end
  502. def authenticate
  503. add_state
  504. update_screens
  505. create_flow
  506. template
  507. true
  508. end
  509. before do
  510. visit 'ticket/create'
  511. use_template(template)
  512. end
  513. it 'does make it possible to create pending states where the pending time is optional and not visible' do
  514. select 'pending customer feedback', from: 'state_id'
  515. click '.js-submit'
  516. expect(current_url).to include('ticket/zoom')
  517. expect(Ticket.last.state_id).to eq(Ticket::State.find_by(name: 'pending customer feedback').id)
  518. expect(Ticket.last.pending_time).to be_nil
  519. end
  520. end
  521. context 'default priority', authenticated_as: :authenticate do
  522. let(:template) { create(:template, :dummy_data) }
  523. let(:ticket_priority) { create(:ticket_priority, default_create: true) }
  524. let(:another_priority) { Ticket::Priority.find(1) }
  525. let(:priority_field) { find('[name=priority_id]') }
  526. def authenticate
  527. template
  528. ticket_priority
  529. true
  530. end
  531. it 'shows default priority on load' do
  532. visit 'ticket/create'
  533. expect(priority_field.value).to eq ticket_priority.id.to_s
  534. end
  535. it 'does not reset to default priority on reload' do
  536. visit 'ticket/create'
  537. taskbar_timestamp = Taskbar.last.updated_at
  538. priority_field.select another_priority.name
  539. wait.until { Taskbar.last.updated_at != taskbar_timestamp }
  540. refresh
  541. expect(priority_field.reload.value).to eq another_priority.id.to_s
  542. end
  543. it 'saves default priority' do
  544. visit 'ticket/create'
  545. use_template template
  546. click '.js-submit'
  547. expect(Ticket.last).to have_attributes(priority: ticket_priority)
  548. end
  549. it 'saves different priority if overriden' do
  550. visit 'ticket/create'
  551. use_template template
  552. priority_field.select another_priority.name
  553. click '.js-submit'
  554. expect(Ticket.last).to have_attributes(priority: another_priority)
  555. end
  556. end
  557. describe 'When looking for customers, it is no longer possible to change into organizations #3815' do
  558. before do
  559. visit 'ticket/create'
  560. # modal reaper ;)
  561. sleep 3
  562. end
  563. context 'when less than 10 customers' do
  564. let(:organization) { Organization.first }
  565. it 'has no show more option' do
  566. find('[name=customer_id_completion]').fill_in with: 'zam'
  567. expect(page).to have_selector("li.js-organization[data-organization-id='#{organization.id}']")
  568. page.find("li.js-organization[data-organization-id='#{organization.id}']").click
  569. expect(page).to have_selector("ul.recipientList-organizationMembers[organization-id='#{organization.id}'] li.js-showMoreMembers.hidden", visible: :all)
  570. end
  571. end
  572. context 'when more than 10 customers', authenticated_as: :authenticate do
  573. def authenticate
  574. customers
  575. true
  576. end
  577. let(:organization) { create(:organization, name: 'Zammed') }
  578. let(:customers) do
  579. create_list(:customer, 50, organization: organization)
  580. end
  581. it 'does paginate through organization' do
  582. find('[name=customer_id_completion]').fill_in with: 'zam'
  583. expect(page).to have_selector("li.js-organization[data-organization-id='#{organization.id}']")
  584. page.find("li.js-organization[data-organization-id='#{organization.id}']").click
  585. wait.until { page.all("ul.recipientList-organizationMembers[organization-id='#{organization.id}'] li", visible: :all).count == 12 } # 10 users + back + show more button
  586. expect(page).to have_selector("ul.recipientList-organizationMembers[organization-id='#{organization.id}'] li.js-showMoreMembers[organization-member-limit='10']")
  587. scroll_into_view('li.js-showMoreMembers')
  588. page.find("ul.recipientList-organizationMembers[organization-id='#{organization.id}'] li.js-showMoreMembers").click
  589. wait.until { page.all("ul.recipientList-organizationMembers[organization-id='#{organization.id}'] li", visible: :all).count == 27 } # 25 users + back + show more button
  590. expect(page).to have_selector("ul.recipientList-organizationMembers[organization-id='#{organization.id}'] li.js-showMoreMembers[organization-member-limit='25']")
  591. scroll_into_view('li.js-showMoreMembers')
  592. page.find("ul.recipientList-organizationMembers[organization-id='#{organization.id}'] li.js-showMoreMembers").click
  593. wait.until { page.all("ul.recipientList-organizationMembers[organization-id='#{organization.id}'] li", visible: :all).count == 52 } # 50 users + back + show more button
  594. scroll_into_view('li.js-showMoreMembers')
  595. expect(page).to have_selector("ul.recipientList-organizationMembers[organization-id='#{organization.id}'] li.js-showMoreMembers.hidden", visible: :all)
  596. end
  597. end
  598. end
  599. describe 'Ticket create screen will loose attachments by time #3827' do
  600. before do
  601. visit 'ticket/create'
  602. end
  603. it 'does not loose attachments on rerender of the ui' do
  604. # upload two files
  605. page.find('input#fileUpload_1[data-initialized="true"]', visible: :all).set(Rails.root.join('test/data/mail/mail001.box'))
  606. await_empty_ajax_queue
  607. wait.until { page.all('div.attachment-delete.js-delete', visible: :all).count == 1 }
  608. expect(page).to have_text('mail001.box')
  609. page.find('input#fileUpload_1', visible: :all).set(Rails.root.join('test/data/mail/mail002.box'))
  610. await_empty_ajax_queue
  611. wait.until { page.all('div.attachment-delete.js-delete', visible: :all).count == 2 }
  612. expect(page).to have_text('mail002.box')
  613. # remove last file
  614. begin
  615. page.evaluate_script("$('div.attachment-delete.js-delete:last').trigger('click')") # not interactable
  616. rescue # Lint/SuppressedException
  617. # because its not interactable it also
  618. # returns this weird exception for the jquery
  619. # even tho it worked fine
  620. end
  621. await_empty_ajax_queue
  622. wait.until { page.all('div.attachment-delete.js-delete', visible: :all).count == 1 }
  623. expect(page).to have_text('mail001.box')
  624. expect(page).to have_no_text('mail002.box')
  625. # simulate rerender b
  626. page.evaluate_script("App.Event.trigger('ui:rerender')")
  627. expect(page).to have_text('mail001.box')
  628. expect(page).to have_no_text('mail002.box')
  629. end
  630. end
  631. describe 'Invalid group and owner list for tickets created via customer profile #3835' do
  632. let(:invalid_ticket) { create(:ticket) }
  633. before do
  634. visit "#ticket/create/id/#{invalid_ticket.id}/customer/#{User.find_by(firstname: 'Nicole').id}"
  635. end
  636. it 'does show an empty list of owners' do
  637. wait.until { page.all('select[name=owner_id] option').count == 1 }
  638. expect(page.all('select[name=owner_id] option').count).to eq(1)
  639. end
  640. end
  641. # https://github.com/zammad/zammad/issues/3825
  642. describe 'CC token field' do
  643. before do
  644. visit 'ticket/create'
  645. find('[data-type=email-out]').click
  646. end
  647. it 'can be cleared by cutting out text' do
  648. add_email 'asd@example.com'
  649. add_email 'def@example.com'
  650. find('.token', text: 'def@example.com').double_click
  651. send_keys([magic_key, 'x'])
  652. find('.token').click # trigger blur
  653. expect(find('[name="cc"]', visible: :all).value).to eq 'asd@example.com'
  654. end
  655. def add_email(input)
  656. fill_in 'CC', with: input
  657. send_keys(:enter) # trigger blur
  658. find '.token', text: input # wait for email to tokenize
  659. end
  660. end
  661. describe 'No signature on new ticket if email is default message type #3844', authenticated_as: :authenticate do
  662. def authenticate
  663. Setting.set('ui_ticket_create_default_type', 'email-out')
  664. Group.where.not(name: 'Users').each { |g| g.update(active: false) }
  665. true
  666. end
  667. before do
  668. visit 'ticket/create'
  669. end
  670. it 'does render the create screen with an initial core workflow state to set signatures and other defaults properly' do
  671. expect(page.find('.richtext-content')).to have_text('Support')
  672. end
  673. end
  674. describe 'Zammad 5 mail template double signature #3816', authenticated_as: :authenticate do
  675. let(:agent_template) { create(:agent) }
  676. let!(:template) do
  677. create(
  678. :template,
  679. :dummy_data,
  680. group: Group.first, owner: agent_template,
  681. body: 'Content dummy.<br><br><div data-signature="true" data-signature-id="1"> Test Other Agent<br><br>--<br> Super Support - Waterford Business Park<br> 5201 Blue Lagoon Drive - 8th Floor &amp; 9th Floor - Miami, 33126 USA<br> Email: hot@example.com - Web: <a href="http://www.example.com/" rel="nofollow noreferrer noopener" target="_blank">http://www.example.com/</a><br>--</div>'
  682. )
  683. end
  684. def authenticate
  685. Group.first.update(signature: Signature.first)
  686. true
  687. end
  688. before do
  689. visit 'ticket/create'
  690. find('[data-type=email-out]').click
  691. end
  692. it 'does not show double signature on template usage' do
  693. set_tree_select_value('group_id', Group.first.name)
  694. use_template(template)
  695. expect(page).to have_no_text('Test Other Agent')
  696. end
  697. end
  698. describe 'Tree select value cannot be set to "-" (empty) with Trigger/Scheduler/Core workflow #4024', authenticated_as: :authenticate, db_strategy: :reset do
  699. let(:field_name) { SecureRandom.uuid }
  700. let(:field) do
  701. create(:object_manager_attribute_tree_select, :required_screen, name: field_name, display: field_name)
  702. ObjectManager::Attribute.migration_execute
  703. end
  704. let(:workflow) do
  705. create(:core_workflow,
  706. object: 'Ticket',
  707. condition_selected: { 'ticket.priority_id'=>{ 'operator' => 'is', 'value' => Ticket::Priority.find_by(name: '3 high').id.to_s } },
  708. perform: { "ticket.#{field_name}" => { 'operator' => 'select', 'select' => 'Incident' } })
  709. end
  710. let(:workflow2) do
  711. create(:core_workflow,
  712. object: 'Ticket',
  713. condition_selected: { 'ticket.priority_id'=>{ 'operator' => 'is', 'value' => Ticket::Priority.find_by(name: '2 normal').id.to_s } },
  714. perform: { "ticket.#{field_name}" => { 'operator' => 'select', 'select' => '' } })
  715. end
  716. def authenticate
  717. field
  718. workflow
  719. workflow2
  720. true
  721. end
  722. before do
  723. visit 'ticket/create'
  724. end
  725. it 'does select the field value properly' do
  726. page.find('[name=priority_id]').select '3 high'
  727. wait.until { page.find("input[name='#{field_name}']", visible: :all).value == 'Incident' }
  728. page.find('[name=priority_id]').select '2 normal'
  729. wait.until { page.find("input[name='#{field_name}']", visible: :all).value == '' }
  730. end
  731. end
  732. describe 'Assign user to multiple organizations #1573' do
  733. let(:organization1) { create(:organization) }
  734. let(:organization2) { create(:organization) }
  735. let(:organization3) { create(:organization) }
  736. let(:organization4) { create(:organization) }
  737. let(:user1) { create(:agent, organization: organization1, organizations: [organization2, organization3]) }
  738. let(:user2) { create(:agent, organization: organization4) }
  739. let(:customer1) { create(:customer, organization: organization1, organizations: [organization2, organization3]) }
  740. let(:customer2) { create(:customer, organization: organization4) }
  741. context 'when agent', authenticated_as: :authenticate do
  742. def authenticate
  743. user1
  744. user2
  745. true
  746. end
  747. before do
  748. visit 'ticket/create'
  749. end
  750. it 'does not show the organization field for user 1' do
  751. find('[name=customer_id_completion]').fill_in with: user1.firstname
  752. find("li.recipientList-entry.js-object[data-object-id='#{user1.id}']").click
  753. expect(page).to have_css("div[data-attribute-name='organization_id']")
  754. end
  755. it 'does show the organization field for user 2' do
  756. find('[name=customer_id_completion]').fill_in with: user2.firstname
  757. find("li.recipientList-entry.js-object[data-object-id='#{user2.id}']").click
  758. expect(page).to have_no_css("div[data-attribute-name='organization_id']")
  759. end
  760. it 'can create tickets for secondary organizations' do
  761. fill_in 'Title', with: 'test'
  762. find('.richtext-content').send_keys 'test'
  763. set_tree_select_value('group_id', Group.first.name)
  764. find('[name=customer_id_completion]').fill_in with: user1.firstname
  765. wait.until { page.all("li.recipientList-entry.js-object[data-object-id='#{user1.id}']").present? }
  766. find("li.recipientList-entry.js-object[data-object-id='#{user1.id}']").click
  767. find('div[data-attribute-name=organization_id] .js-input').fill_in with: user1.organizations[0].name, fill_options: { clear: :backspace }
  768. wait.until { page.all("div[data-attribute-name=organization_id] .js-option[data-value='#{user1.organizations[0].id}']").present? }
  769. page.find("div[data-attribute-name=organization_id] .js-option[data-value='#{user1.organizations[0].id}'] span").click
  770. click '.js-submit'
  771. wait.until { Ticket.last.organization_id == user1.organizations[0].id }
  772. end
  773. end
  774. context 'when customer' do
  775. before do
  776. visit 'customer_ticket_new'
  777. end
  778. it 'does not show the organization field for user 1', authenticated_as: :customer1 do
  779. expect(page).to have_css("div[data-attribute-name='organization_id']")
  780. end
  781. it 'does show the organization field for user 2', authenticated_as: :customer2 do
  782. expect(page).to have_no_css("div[data-attribute-name='organization_id']")
  783. end
  784. it 'can create tickets for secondary organizations', authenticated_as: :customer1 do
  785. fill_in 'Title', with: 'test'
  786. find('.richtext-content').send_keys 'test'
  787. set_tree_select_value('group_id', Group.first.name)
  788. find('div[data-attribute-name=organization_id] .js-input').fill_in with: customer1.organizations[0].name, fill_options: { clear: :backspace }
  789. wait.until { page.all("div[data-attribute-name=organization_id] .js-option[data-value='#{customer1.organizations[0].id}']").present? }
  790. page.find("div[data-attribute-name=organization_id] .js-option[data-value='#{customer1.organizations[0].id}'] span").click
  791. click '.js-submit'
  792. wait.until { Ticket.last.organization_id == customer1.organizations[0].id }
  793. end
  794. end
  795. end
  796. describe 'Wrong default values in ticket create when creating from user profile #4088' do
  797. let(:customer) { create(:customer) }
  798. before do
  799. visit "ticket/create/customer/#{customer.id}"
  800. end
  801. it 'does show the default state when creating a ticket from a user profile' do
  802. expect(page).to have_select('state_id', selected: 'open')
  803. end
  804. end
  805. describe 'Ticket templates do not save the owner attribute #4175' do
  806. let(:agent) { create(:agent, groups: [Group.first]) }
  807. let!(:template) { create(:template, :dummy_data, group: Group.first, owner: agent) }
  808. before do
  809. visit 'ticket/create'
  810. # Wait for the initial taskbar update to finish
  811. taskbar_timestamp = Taskbar.last.updated_at
  812. wait.until { Taskbar.last.updated_at != taskbar_timestamp }
  813. end
  814. it 'does set owners properly by templates and taskbars' do
  815. use_template(template)
  816. expect(page).to have_select('owner_id', selected: agent.fullname)
  817. wait.until { Taskbar.last.state['owner_id'].to_i == agent.id }
  818. refresh
  819. expect(page).to have_select('owner_id', selected: agent.fullname)
  820. end
  821. end
  822. describe 'Ticket templates resets article body #2434' do
  823. let!(:template1) { create(:template, :dummy_data, title: 'template 1', body: 'body 1') }
  824. let!(:template2) { create(:template, :dummy_data, title: 'template 2', body: 'body 2') }
  825. before do
  826. visit 'ticket/create'
  827. end
  828. it 'preserves text input from the user' do
  829. set_editor_field_value('body', 'foobar')
  830. use_template(template1)
  831. check_input_field_value('title', 'template 1')
  832. check_editor_field_value('body', 'foobar')
  833. end
  834. it 'allows easy switching between templates' do
  835. use_template(template1)
  836. check_input_field_value('title', 'template 1')
  837. check_editor_field_value('body', 'body 1')
  838. use_template(template2)
  839. check_input_field_value('title', 'template 2')
  840. check_editor_field_value('body', 'body 2')
  841. set_editor_field_value('body', 'foobar')
  842. # This time body value should be left as-is
  843. use_template(template1)
  844. check_input_field_value('title', 'template 1')
  845. check_editor_field_value('body', 'foobar')
  846. end
  847. end
  848. describe 'Ticket templates are missing pending till option #4318', time_zone: 'Europe/London' do
  849. shared_examples 'check datetime field' do
  850. shared_examples 'calculated datetime value' do
  851. it 'applies correct datetime value' do
  852. use_template(template)
  853. check_date_field_value(field, date.strftime('%m/%d/%Y'))
  854. check_time_field_value(field, date.strftime('%H:%M'))
  855. end
  856. end
  857. context 'with static operator' do
  858. let(:operator) { 'static' }
  859. let(:date) { 3.days.from_now }
  860. let(:template_value) { date.to_datetime.to_s }
  861. it_behaves_like 'calculated datetime value'
  862. end
  863. context 'with relative operator' do
  864. let(:operator) { 'relative' }
  865. let(:template_value) { value.to_s }
  866. let(:date) do
  867. # Since front-end uses a JS-specific function to add a month value to the current date,
  868. # calculating the value here with Ruby code may lead to unexpected values.
  869. # Therefore, we use a reimplementation of the ECMAScript function instead.
  870. if range == 'month'
  871. frontend_relative_month(Time.current, value)
  872. else
  873. value.send(range).from_now
  874. end
  875. end
  876. %w[minute hour day week month year].each do |range|
  877. context "with #{range} range" do
  878. let(:range) { range }
  879. let(:value) do
  880. case range
  881. when 'minute' then [*(1..120)].sample
  882. when 'hour' then [*(1..48)].sample
  883. when 'day' then [*(1..31)].sample
  884. when 'week' then [*(1..53)].sample
  885. when 'month' then [*(1..12)].sample
  886. when 'year' then [*(1..20)].sample
  887. end
  888. end
  889. it_behaves_like 'calculated datetime value'
  890. end
  891. end
  892. end
  893. end
  894. shared_examples 'check date field' do
  895. let(:date) { 5.days.from_now }
  896. let(:template_value) { date.to_datetime.to_s }
  897. it 'applies correct date value' do
  898. use_template(template)
  899. check_date_field_value(field, date.strftime('%m/%d/%Y'))
  900. end
  901. end
  902. describe 'pending till support' do
  903. let(:field) { 'pending_time' }
  904. let(:template) do
  905. create(:template,
  906. options: {
  907. 'ticket.state_id': {
  908. value: Ticket::State.find_by(name: 'pending reminder').id.to_s,
  909. },
  910. "ticket.#{field}": {
  911. value: template_value,
  912. operator: operator,
  913. range: (range if defined? range),
  914. }
  915. })
  916. end
  917. before do
  918. freeze_time
  919. template
  920. visit '/'
  921. browser_travel_to Time.current
  922. visit 'ticket/create'
  923. end
  924. include_examples 'check datetime field'
  925. end
  926. describe 'custom attribute support' do
  927. let(:template) do
  928. create(:template,
  929. options: {
  930. "ticket.#{field}": {
  931. value: template_value,
  932. operator: (operator if defined? operator),
  933. range: (range if defined? range),
  934. }
  935. })
  936. end
  937. before :all do # rubocop:disable RSpec/BeforeAfterAll
  938. screens = {
  939. create_middle: {
  940. 'ticket.agent' => {
  941. shown: true,
  942. },
  943. },
  944. }
  945. create(:object_manager_attribute_date, name: 'test_date', display: 'test_date', screens: screens)
  946. create(:object_manager_attribute_datetime, name: 'test_datetime', display: 'test_datetime', screens: screens)
  947. ObjectManager::Attribute.migration_execute # rubocop:disable Zammad/ExistsDbStrategy
  948. end
  949. after :all do # rubocop:disable RSpec/BeforeAfterAll
  950. ObjectManager::Attribute.where(name: %w[test_date test_datetime]).destroy_all
  951. end
  952. before do
  953. freeze_time
  954. template
  955. visit '/'
  956. browser_travel_to Time.current
  957. visit 'ticket/create'
  958. end
  959. context 'with date attribute' do
  960. let(:field) { 'test_date' }
  961. include_examples 'check date field'
  962. end
  963. context 'with datetime attribute' do
  964. let(:field) { 'test_datetime' }
  965. include_examples 'check datetime field'
  966. end
  967. end
  968. end
  969. describe 'Ticket templates are missing active flag #4381' do
  970. let!(:active_template) { create(:template, :dummy_data, active: true) }
  971. let!(:inactive_template) { create(:template, :dummy_data, active: false) }
  972. before do
  973. visit 'ticket/create'
  974. end
  975. it 'filters active templates only' do
  976. expect(find('#form-template select[name="id"]')).to have_selector('option', text: active_template.name).and(have_no_selector('option', text: inactive_template.name))
  977. end
  978. end
  979. describe 'CC field cannot be customized in the new ticket templates #4421', authenticated_as: :agent do
  980. let(:group) { create(:group) }
  981. let(:agent) { create(:agent, groups: [group]) }
  982. let(:customer) { create(:customer) }
  983. let(:cc_recipients) { Array.new(3) { Faker::Internet.unique.email }.join(', ') }
  984. let!(:template) do
  985. create(:template,
  986. options: {
  987. 'ticket.title': {
  988. value: Faker::Name.unique.name_with_middle,
  989. },
  990. 'ticket.customer_id': {
  991. value: customer.id,
  992. value_completion: "#{customer.firstname} #{customer.lastname} <#{customer.email}>",
  993. },
  994. 'ticket.group_id': {
  995. value: group.id,
  996. },
  997. 'ticket.formSenderType': {
  998. value: form_sender_type,
  999. },
  1000. 'article.cc': {
  1001. value: cc_recipients,
  1002. },
  1003. 'article.body': {
  1004. value: Faker::Hacker.say_something_smart,
  1005. },
  1006. })
  1007. end
  1008. before do
  1009. visit 'ticket/create'
  1010. end
  1011. context 'with email article type' do
  1012. let(:form_sender_type) { 'email-out' }
  1013. it 'applies configured cc value' do
  1014. use_template(template)
  1015. await_empty_ajax_queue
  1016. expect(page).to have_css('label', text: 'CC')
  1017. check_input_field_value('cc', cc_recipients, visible: :all)
  1018. click '.js-submit'
  1019. expect(Ticket::Article.last).to have_attributes(cc: cc_recipients)
  1020. end
  1021. end
  1022. context 'with phone article type' do
  1023. let(:form_sender_type) { 'phone-out' }
  1024. it 'ignores configured cc value' do
  1025. use_template(template)
  1026. await_empty_ajax_queue
  1027. expect(page).to have_no_css('label', text: 'CC')
  1028. click '.js-submit'
  1029. expect(Ticket::Article.last).not_to have_attributes(cc: cc_recipients)
  1030. end
  1031. end
  1032. end
  1033. describe 'Open ticket indicator coloring setting' do
  1034. let(:elem) { find('[data-tab="customer"]') }
  1035. let(:customer) { create(:customer) }
  1036. let(:group) { Group.first }
  1037. before do
  1038. Setting.set 'ui_sidebar_open_ticket_indicator_colored', state
  1039. customer.preferences[:tickets_open] = tickets_count
  1040. customer.save!
  1041. visit 'ticket/create'
  1042. field = find '[name=customer_id]', visible: :hidden
  1043. field.execute_script "this.value = #{customer.id}"
  1044. field.execute_script '$(this).trigger("change")'
  1045. end
  1046. context 'when enabled' do
  1047. let(:state) { true }
  1048. context 'with 1 ticket' do
  1049. let(:tickets_count) { 1 }
  1050. it 'highlights as warning' do
  1051. create(:ticket, customer: customer, group: group)
  1052. expect(elem)
  1053. .to have_no_selector('.tabsSidebar-tab-count--danger')
  1054. .and have_selector('.tabsSidebar-tab-count--warning')
  1055. end
  1056. end
  1057. context 'with 2 tickets' do
  1058. let(:tickets_count) { 2 }
  1059. it 'highlights as danger' do
  1060. expect(elem)
  1061. .to have_selector('.tabsSidebar-tab-count--danger')
  1062. .and have_no_selector('.tabsSidebar-tab-count--warning')
  1063. end
  1064. end
  1065. end
  1066. context 'when disabled' do
  1067. let(:state) { false }
  1068. context 'with 2 tickets' do
  1069. let(:tickets_count) { 2 }
  1070. it 'does not highlight' do
  1071. expect(elem)
  1072. .to have_no_selector('.tabsSidebar-tab-count--danger, .tabsSidebar-tab-count--warning')
  1073. end
  1074. end
  1075. end
  1076. end
  1077. describe 'Not possible to select multiple values in a multi-tree select when a workflow with a select action is executed #4465', authenticated_as: :authenticate, db_strategy: :reset do
  1078. let(:field_name) { SecureRandom.uuid }
  1079. let(:screens) do
  1080. {
  1081. 'create_middle' => {
  1082. 'ticket.agent' => {
  1083. 'shown' => true,
  1084. 'required' => false,
  1085. }
  1086. }
  1087. }
  1088. end
  1089. def authenticate
  1090. create(:object_manager_attribute_multi_tree_select, name: field_name, display: field_name, screens: screens)
  1091. ObjectManager::Attribute.migration_execute
  1092. create(:core_workflow,
  1093. object: 'Ticket',
  1094. perform: {
  1095. 'ticket.priority_id': {
  1096. operator: 'select',
  1097. select: [Ticket::Priority.find_by(name: '3 high').id.to_s]
  1098. },
  1099. })
  1100. true
  1101. end
  1102. def multi_tree_select_click(value)
  1103. page.evaluate_script("document.querySelector(\"div[data-attribute-name='#{field_name}'] .js-optionsList li[data-value='#{value}'] .searchableSelect-option-text\").click()")
  1104. await_empty_ajax_queue
  1105. end
  1106. before do
  1107. visit 'ticket/create'
  1108. end
  1109. it 'does not clear the values of the multi tree select' do
  1110. multi_tree_select_click('Incident')
  1111. multi_tree_select_click('Service request')
  1112. multi_tree_select_click('Change request')
  1113. select '1 low', from: 'priority_id'
  1114. select 'pending reminder', from: 'state_id'
  1115. expect(page).to have_selector('span.token-label', text: 'Incident')
  1116. expect(page).to have_selector('span.token-label', text: 'Service request')
  1117. expect(page).to have_selector('span.token-label', text: 'Change request')
  1118. end
  1119. end
  1120. describe 'Support title and body in core workflow actions #4519', authenticated_as: :authenticate do
  1121. let(:workflow) do
  1122. create(:core_workflow,
  1123. object: 'Ticket',
  1124. condition_selected: { 'ticket.priority_id'=>{ 'operator' => 'is', 'value' => [Ticket::Priority.find_by(name: '2 normal').id.to_s] } },
  1125. perform: { 'ticket.title' => { 'operator' => %w[fill_in set_readonly], 'fill_in' => 'title 123', 'set_readonly' => true }, 'ticket.body' => { 'operator' => %w[fill_in set_readonly], 'fill_in' => '<b>text 123</b>', 'set_readonly' => true } })
  1126. end
  1127. context 'when agent' do
  1128. def authenticate
  1129. workflow
  1130. true
  1131. end
  1132. before do
  1133. visit '#ticket/create'
  1134. end
  1135. it 'has core workflow support for title and text' do
  1136. expect(page).to have_css('div[data-attribute-name=title].is-readonly')
  1137. expect(page).to have_css('div[data-attribute-name=body].is-readonly')
  1138. expect(page.find_field('Title').value).to eq('title 123')
  1139. expect(page.find('div[data-name=body]')['innerHTML']).to eq('<b>text 123</b>')
  1140. # unset readonly (https://github.com/zammad/zammad/issues/4540)
  1141. select '1 low', from: 'priority_id'
  1142. expect(page).to have_no_css('div[data-attribute-name=title].is-readonly')
  1143. expect(page).to have_no_css('div[data-attribute-name=body].is-readonly')
  1144. # reset readonly
  1145. select '2 normal', from: 'priority_id'
  1146. expect(page).to have_css('div[data-attribute-name=title].is-readonly')
  1147. expect(page).to have_css('div[data-attribute-name=body].is-readonly')
  1148. end
  1149. end
  1150. context 'when customer' do
  1151. def authenticate
  1152. workflow
  1153. create(:customer)
  1154. end
  1155. before do
  1156. visit '#customer_ticket_new'
  1157. end
  1158. it 'has core workflow support for title and text' do
  1159. expect(page).to have_css('div[data-attribute-name=title].is-readonly')
  1160. expect(page).to have_css('div[data-attribute-name=body].is-readonly')
  1161. expect(page.find_field('Title').value).to eq('title 123')
  1162. expect(page.find('div[data-name=body]')['innerHTML']).to eq('<b>text 123</b>')
  1163. end
  1164. end
  1165. end
  1166. end