browser_test_helper.rb 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092
  1. ENV['RAILS_ENV'] = 'test'
  2. # rubocop:disable HandleExceptions, ClassVars, NonLocalExitFromIterator
  3. require File.expand_path('../../config/environment', __FILE__)
  4. require 'selenium-webdriver'
  5. class TestCase < Test::Unit::TestCase
  6. @@debug = true
  7. def browser
  8. ENV['BROWSER'] || 'firefox'
  9. end
  10. def profile
  11. browser_profile = nil
  12. if browser == 'firefox'
  13. browser_profile = Selenium::WebDriver::Firefox::Profile.new
  14. browser_profile['intl.locale.matchOS'] = false
  15. browser_profile['intl.accept_languages'] = 'en-US'
  16. browser_profile['general.useragent.locale'] = 'en-US'
  17. elsif browser == 'chrome'
  18. # profile are only working on remote selenium
  19. if ENV['REMOTE_URL']
  20. browser_profile = Selenium::WebDriver::Chrome::Profile.new
  21. browser_profile['intl.accept_languages'] = 'en'
  22. end
  23. end
  24. browser_profile
  25. end
  26. def browser_support_cookies
  27. if browser =~ /(internet_explorer|ie)/i
  28. return false
  29. end
  30. true
  31. end
  32. def browser_url
  33. ENV['BROWSER_URL'] || 'http://localhost:3000'
  34. end
  35. def browser_instance
  36. if !@browsers
  37. @browsers = {}
  38. end
  39. if !ENV['REMOTE_URL'] || ENV['REMOTE_URL'].empty?
  40. local_browser = Selenium::WebDriver.for(browser.to_sym, profile: profile)
  41. @browsers[local_browser.hash] = local_browser
  42. browser_instance_preferences(local_browser)
  43. return local_browser
  44. end
  45. caps = Selenium::WebDriver::Remote::Capabilities.send(browser)
  46. if ENV['BROWSER_OS']
  47. caps.platform = ENV['BROWSER_OS']
  48. end
  49. if ENV['BROWSER_VERSION']
  50. caps.version = ENV['BROWSER_VERSION']
  51. end
  52. local_browser = Selenium::WebDriver.for(
  53. :remote,
  54. url: ENV['REMOTE_URL'],
  55. desired_capabilities: caps,
  56. )
  57. @browsers[local_browser.hash] = local_browser
  58. # avoid "Cannot read property 'get_Current' of undefined" issues
  59. begin
  60. browser_instance_preferences(local_browser)
  61. rescue
  62. # just try again
  63. sleep 10
  64. browser_instance_preferences(local_browser)
  65. end
  66. # upload files from remote dir
  67. local_browser.file_detector = lambda do |args|
  68. str = args.first.to_s
  69. str if File.file?(str)
  70. end
  71. local_browser
  72. end
  73. def browser_instance_close(local_browser)
  74. return if !@browsers[local_browser.hash]
  75. @browsers.delete(local_browser.hash)
  76. local_browser.quit
  77. end
  78. def browser_instance_preferences(local_browser)
  79. local_browser.manage.window.resize_to(1024, 800)
  80. if ENV['REMOTE_URL'] !~ /saucelabs|(grid|ci)\.(zammad\.org|znuny\.com)/i
  81. if @browsers.count == 1
  82. local_browser.manage.window.move_to(0, 0)
  83. else
  84. local_browser.manage.window.move_to(1024, 0)
  85. end
  86. end
  87. local_browser.manage.timeouts.implicit_wait = 3 # seconds
  88. end
  89. def teardown
  90. return if !@browsers
  91. @browsers.each { |_hash, local_browser|
  92. screenshot(browser: local_browser, comment: 'teardown')
  93. browser_instance_close(local_browser)
  94. }
  95. end
  96. def screenshot(params)
  97. instance = params[:browser] || @browser
  98. comment = params[:comment] || ''
  99. filename = "tmp/#{Time.zone.now.strftime('screenshot_%Y_%m_%d__%H_%M_%S')}_#{comment}_#{instance.hash}.png"
  100. log('screenshot', { filename: filename })
  101. instance.save_screenshot(filename)
  102. end
  103. =begin
  104. username = login(
  105. browser: browser1,
  106. username: 'someuser',
  107. password: 'somepassword',
  108. url: 'some url', # optional
  109. remember_me: true, # optional
  110. auto_wizard: false, # optional, in case of auto wizard, skip login
  111. )
  112. =end
  113. def login(params)
  114. switch_window_focus(params)
  115. log('login', params)
  116. instance = params[:browser] || @browser
  117. if params[:url]
  118. instance.get(params[:url])
  119. end
  120. element = instance.find_elements({ css: '#login input[name="username"]' })[0]
  121. if !element
  122. if params[:auto_wizard]
  123. watch_for(
  124. browser: instance,
  125. css: 'body',
  126. value: 'auto wizard is enabled',
  127. timeout: 10,
  128. )
  129. location( url: "#{browser_url}/#getting_started/auto_wizard" )
  130. sleep 10
  131. login = instance.find_elements({ css: '.user-menu .user a' })[0].attribute('title')
  132. if login != params[:username]
  133. screenshot(browser: instance, comment: 'auto wizard login failed')
  134. fail 'auto wizard login failed'
  135. end
  136. assert(true, 'auto wizard login ok')
  137. return
  138. end
  139. screenshot(browser: instance, comment: 'login_failed')
  140. fail 'No login box found'
  141. end
  142. screenshot(browser: instance, comment: 'login')
  143. element.clear
  144. element.send_keys(params[:username])
  145. element = instance.find_elements({ css: '#login input[name="password"]' })[0]
  146. element.clear
  147. element.send_keys(params[:password])
  148. if params[:remember_me]
  149. instance.find_elements({ css: '#login .checkbox-replacement' })[0].click
  150. end
  151. instance.find_elements({ css: '#login button' })[0].click
  152. sleep 5
  153. login = instance.find_elements({ css: '.user-menu .user a' })[0].attribute('title')
  154. if login != params[:username]
  155. screenshot(browser: instance, comment: 'login_failed')
  156. fail 'login failed'
  157. end
  158. screenshot(browser: instance, comment: 'login_ok')
  159. assert(true, 'login ok')
  160. login
  161. end
  162. =begin
  163. logout(
  164. browser: browser1
  165. )
  166. =end
  167. def logout(params = {})
  168. switch_window_focus(params)
  169. log('logout', params)
  170. instance = params[:browser] || @browser
  171. instance.find_elements({ css: 'a[href="#current_user"]' })[0].click
  172. sleep 0.1
  173. instance.find_elements({ css: 'a[href="#logout"]' })[0].click
  174. (1..6).each {
  175. sleep 1
  176. login = instance.find_elements({ css: '#login' })[0]
  177. next if !login
  178. screenshot(browser: instance, comment: 'logout_ok')
  179. assert(true, 'logout ok')
  180. return
  181. }
  182. screenshot(browser: instance, comment: 'logout_failed')
  183. fail 'no login box found, seems logout was not successfully!'
  184. end
  185. =begin
  186. location(
  187. browser: browser1,
  188. url: 'http://someurl',
  189. )
  190. =end
  191. def location(params)
  192. switch_window_focus(params)
  193. log('location', params)
  194. instance = params[:browser] || @browser
  195. instance.get(params[:url])
  196. # check if reload was successfull
  197. if !instance.find_elements({ css: 'body' })[0] || instance.find_elements({ css: 'body' })[0].text =~ /unavailable or too busy/i
  198. instance.navigate.refresh
  199. end
  200. screenshot(browser: instance, comment: 'location')
  201. end
  202. =begin
  203. location_check(
  204. browser: browser1,
  205. url: 'http://someurl',
  206. )
  207. =end
  208. def location_check(params)
  209. switch_window_focus(params)
  210. log('location_check', params)
  211. instance = params[:browser] || @browser
  212. if instance.current_url !~ /#{Regexp.quote(params[:url])}/
  213. screenshot(browser: instance, comment: 'location_check_failed')
  214. fail "url #{instance.current_url} is not matching #{params[:url]}"
  215. end
  216. assert(true, "url #{instance.current_url} is matching #{params[:url]}")
  217. end
  218. =begin
  219. reload(
  220. browser: browser1,
  221. )
  222. =end
  223. def reload(params = {})
  224. switch_window_focus(params)
  225. log('reload', params)
  226. instance = params[:browser] || @browser
  227. screenshot(browser: instance, comment: 'reload_before')
  228. instance.navigate.refresh
  229. # check if reload was successfull
  230. if !instance.find_elements({ css: 'body' })[0] || instance.find_elements({ css: 'body' })[0].text =~ /unavailable or too busy/i
  231. instance.navigate.refresh
  232. end
  233. screenshot(browser: instance, comment: 'reload_after')
  234. end
  235. =begin
  236. click(
  237. browser: browser1,
  238. css: '.some_class',
  239. fast: false, # do not wait
  240. wait: 1, # wait 1 sec.
  241. )
  242. click(
  243. browser: browser1,
  244. text: '.partial_link_text',
  245. fast: false, # do not wait
  246. wait: 1, # wait 1 sec.
  247. )
  248. =end
  249. def click(params)
  250. switch_window_focus(params)
  251. log('click', params)
  252. instance = params[:browser] || @browser
  253. if params[:css]
  254. element = instance.find_elements({ css: params[:css] })[0]
  255. #instance.mouse.move_to(element)
  256. #sleep 0.2
  257. element.click
  258. # trigger also focus on input/select and textarea fields
  259. #if params[:css] =~ /(input|select|textarea)/
  260. # instance.execute_script("$('#{params[:css]}').trigger('focus')")
  261. # sleep 0.2
  262. #end
  263. else
  264. instance.find_elements({ partial_link_text: params[:text] })[0].click
  265. end
  266. sleep 0.4 if !params[:fast]
  267. sleep params[:wait] if params[:wait]
  268. end
  269. =begin
  270. scroll_to(
  271. browser: browser1,
  272. position: 'top', # botton
  273. css: '.some_class',
  274. )
  275. =end
  276. def scroll_to(params)
  277. switch_window_focus(params)
  278. log('scroll_to', params)
  279. instance = params[:browser] || @browser
  280. position = 'true'
  281. if params[:position] == 'botton'
  282. position = 'false'
  283. end
  284. execute(
  285. browser: instance,
  286. js: "\$('#{params[:css]}').get(0).scrollIntoView(#{position})",
  287. mute_log: params[:mute_log]
  288. )
  289. sleep 0.2
  290. end
  291. =begin
  292. execute(
  293. browser: browser1,
  294. js: '.some_class',
  295. )
  296. =end
  297. def execute(params)
  298. switch_window_focus(params)
  299. log('js', params)
  300. instance = params[:browser] || @browser
  301. if params[:js]
  302. return instance.execute_script(params[:js])
  303. end
  304. fail "Invalid execute params #{params.inspect}"
  305. end
  306. =begin
  307. exists(
  308. browser: browser1,
  309. css: '.some_class',
  310. )
  311. =end
  312. def exists(params)
  313. switch_window_focus(params)
  314. log('exists', params)
  315. instance = params[:browser] || @browser
  316. if !instance.find_elements({ css: params[:css] } )[0]
  317. screenshot(browser: instance, comment: 'exists_failed')
  318. fail "#{params[:css]} dosn't exist, but should"
  319. end
  320. true
  321. end
  322. =begin
  323. exists_not(
  324. browser: browser1,
  325. css: '.some_class',
  326. )
  327. =end
  328. def exists_not(params)
  329. switch_window_focus(params)
  330. log('exists_not', params)
  331. instance = params[:browser] || @browser
  332. if instance.find_elements({ css: params[:css] } )[0]
  333. screenshot(browser: instance, comment: 'exists_not_failed')
  334. fail "#{params[:css]} exists but should not"
  335. end
  336. true
  337. end
  338. =begin
  339. set(
  340. browser: browser1,
  341. css: '.some_class',
  342. value: true,
  343. slow: false,
  344. blur: true,
  345. clear: true, # todo | default: true
  346. no_click: true,
  347. )
  348. =end
  349. def set(params)
  350. switch_window_focus(params)
  351. log('set', params)
  352. instance = params[:browser] || @browser
  353. element = instance.find_elements({ css: params[:css] })[0]
  354. if !params[:no_click]
  355. element.click
  356. end
  357. element.clear
  358. if !params[:slow]
  359. element.send_keys(params[:value])
  360. else
  361. element.send_keys('')
  362. keys = params[:value].to_s.split('')
  363. keys.each {|key|
  364. instance.action.send_keys(key).perform
  365. }
  366. end
  367. if params[:blur]
  368. instance.execute_script("$('#{params[:css]}').blur()")
  369. end
  370. sleep 0.5
  371. end
  372. =begin
  373. select(
  374. browser: browser1,
  375. css: '.some_class',
  376. value: 'Some Value',
  377. )
  378. =end
  379. def select(params)
  380. switch_window_focus(params)
  381. log('select', params)
  382. instance = params[:browser] || @browser
  383. begin
  384. element = instance.find_elements({ css: params[:css] })[0]
  385. dropdown = Selenium::WebDriver::Support::Select.new(element)
  386. dropdown.select_by(:text, params[:value])
  387. puts "select - #{params.inspect}"
  388. rescue
  389. # just try again
  390. element = instance.find_elements({ css: params[:css] })[0]
  391. dropdown = Selenium::WebDriver::Support::Select.new(element)
  392. dropdown.select_by(:text, params[:value])
  393. puts "select2 - #{params.inspect}"
  394. end
  395. end
  396. =begin
  397. switch(
  398. browser: browser1,
  399. css: '.some_class',
  400. type: 'on', # 'off'
  401. )
  402. =end
  403. def switch(params)
  404. switch_window_focus(params)
  405. log('switch', params)
  406. instance = params[:browser] || @browser
  407. element = instance.find_elements({ css: "#{params[:css]} input[type=checkbox]" })[0]
  408. checked = element.attribute('checked')
  409. if !checked
  410. if params[:type] == 'on'
  411. instance.find_elements({ css: "#{params[:css]} label" })[0].click
  412. end
  413. elsif params[:type] == 'off'
  414. instance.find_elements({ css: "#{params[:css]} label" })[0].click
  415. end
  416. end
  417. =begin
  418. check(
  419. browser: browser1,
  420. css: '.some_class',
  421. )
  422. =end
  423. def check(params)
  424. switch_window_focus(params)
  425. log('check', params)
  426. instance = params[:browser] || @browser
  427. element = instance.find_elements({ css: params[:css] })[0]
  428. checked = element.attribute('checked')
  429. element.click if !checked
  430. end
  431. =begin
  432. uncheck(
  433. browser: browser1,
  434. css: '.some_class',
  435. )
  436. =end
  437. def uncheck(params)
  438. switch_window_focus(params)
  439. log('uncheck', params)
  440. instance = params[:browser] || @browser
  441. element = instance.find_elements({ css: params[:css] })[0]
  442. checked = element.attribute('checked')
  443. element.click if checked
  444. end
  445. =begin
  446. sendkey(
  447. browser: browser1,
  448. value: :enter,
  449. slow: false,
  450. )
  451. =end
  452. def sendkey(params)
  453. switch_window_focus(params)
  454. log('sendkey', params)
  455. instance = params[:browser] || @browser
  456. if params[:value].class == Array
  457. params[:value].each {|key|
  458. instance.action.send_keys(key).perform
  459. }
  460. return
  461. end
  462. instance.action.send_keys(params[:value]).perform
  463. if params[:slow]
  464. sleep 2
  465. else
  466. sleep 0.6
  467. end
  468. end
  469. =begin
  470. match(
  471. browser: browser1,
  472. css: '#content .text-1',
  473. value: 'some test for browser and some other for browser',
  474. attribute: 'some_attribute', # match on attribute
  475. should_not_match: true,
  476. no_quote: false, # use regex
  477. )
  478. =end
  479. def match(params, fallback = false)
  480. switch_window_focus(params)
  481. log('match', params)
  482. instance = params[:browser] || @browser
  483. element = instance.find_elements({ css: params[:css] })[0]
  484. if params[:css] =~ /select/
  485. dropdown = Selenium::WebDriver::Support::Select.new(element)
  486. success = false
  487. if dropdown.selected_options
  488. dropdown.selected_options.each {|option|
  489. if option.text == params[:value]
  490. success = true
  491. end
  492. }
  493. end
  494. if params[:should_not_match]
  495. if success
  496. fail "should not match '#{params[:value]}' in select list, but is matching"
  497. end
  498. elsif !success
  499. fail "not matching '#{params[:value]}' in select list"
  500. end
  501. return true
  502. end
  503. # match on attribute
  504. begin
  505. text = if params[:attribute]
  506. element.attribute(params[:attribute])
  507. elsif params[:css] =~ /(input|textarea)/i
  508. element.attribute('value')
  509. else
  510. element.text
  511. end
  512. rescue => e
  513. # just try again
  514. if !fallback
  515. return match(params, true)
  516. end
  517. raise e.inspect
  518. end
  519. # do cleanups (needed for richtext tests)
  520. if params[:cleanup]
  521. text.gsub!(/\s+$/m, '')
  522. params[:value].gsub!(/\s+$/m, '')
  523. end
  524. match = false
  525. if params[:no_quote]
  526. #puts "aaaa #{text}/#{params[:value]}"
  527. if text =~ /#{params[:value]}/i
  528. match = $1 || true
  529. end
  530. elsif text =~ /#{Regexp.quote(params[:value])}/i
  531. match = true
  532. end
  533. if match
  534. if params[:should_not_match]
  535. fail "matching '#{params[:value]}' in content '#{text}' but should not!"
  536. end
  537. elsif !params[:should_not_match]
  538. fail "not matching '#{params[:value]}' in content '#{text}' but should!"
  539. end
  540. sleep 0.8
  541. match
  542. end
  543. =begin
  544. match_not(
  545. browser: browser1,
  546. css: '#content .text-1',
  547. value: 'some test for browser and some other for browser',
  548. attribute: 'some_attribute', # match on attribute
  549. should_not_match: true,
  550. no_quote: false, # use regex
  551. )
  552. =end
  553. def match_not(params)
  554. switch_window_focus(params)
  555. log('match_not', params)
  556. params[:should_not_match] = true
  557. match(params)
  558. end
  559. =begin
  560. task_type(
  561. browser: browser1,
  562. type: 'stayOnTab',
  563. )
  564. =end
  565. def task_type(params)
  566. switch_window_focus(params)
  567. log('task_type', params)
  568. instance = params[:browser] || @browser
  569. if params[:type]
  570. instance.find_elements({ css: '.content.active .js-secondaryActionButtonLabel' })[0].click
  571. instance.find_elements({ css: ".content.active .js-secondaryActionLabel[data-type=#{params[:type]}]" })[0].click
  572. return
  573. end
  574. fail "Unknown params for task_type: #{params.inspect}"
  575. end
  576. =begin
  577. cookie(
  578. browser: browser1,
  579. name: '^_zammad.+?',
  580. value: '.+?',
  581. expires: nil,
  582. )
  583. cookie(
  584. browser: browser1,
  585. name: '^_zammad.+?',
  586. should_not_exist: true,
  587. )
  588. =end
  589. def cookie(params)
  590. switch_window_focus(params)
  591. log('cookie', params)
  592. instance = params[:browser] || @browser
  593. if !browser_support_cookies
  594. assert(true, "'#{params[:value]}' ups browser is not supporting reading cookies, go ahead")
  595. return true
  596. end
  597. cookies = instance.manage.all_cookies
  598. cookies.each {|cookie|
  599. #puts "CCC #{cookie.inspect}"
  600. # :name=>"_zammad_session_c25832f4de2", :value=>"adc31cd21615cb0a7ab269184ec8b76f", :path=>"/", :domain=>"localhost", :expires=>nil, :secure=>false}
  601. next if cookie[:name] !~ /#{params[:name]}/i
  602. if params.key?(:value ) && cookie[:value].to_s =~ /#{params[:value]}/i
  603. assert(true, "matching value '#{params[:value]}' in cookie '#{cookie}'")
  604. else
  605. fail "not matching value '#{params[:value]}' in cookie '#{cookie}'"
  606. end
  607. if params.key?(:expires) && cookie[:expires].to_s =~ /#{params[:expires]}/i
  608. assert(true, "matching expires '#{params[:expires].inspect}' in cookie '#{cookie}'")
  609. else
  610. fail "not matching expires '#{params[:expires]}' in cookie '#{cookie}'"
  611. end
  612. return if !params[:should_not_exist]
  613. fail "cookie with name '#{params[:name]}' should not exist, but exists '#{cookies}'"
  614. }
  615. if params[:should_not_exist]
  616. assert(true, "cookie with name '#{params[:name]}' is not existing")
  617. return
  618. end
  619. fail "not matching name '#{params[:name]}' in cookie '#{cookies}'"
  620. end
  621. =begin
  622. verify_title(
  623. browser: browser1,
  624. value: 'some title',
  625. )
  626. =end
  627. def verify_title(params = {})
  628. switch_window_focus(params)
  629. log('verify_title', params)
  630. instance = params[:browser] || @browser
  631. title = instance.title
  632. if title =~ /#{params[:value]}/i
  633. assert(true, "matching '#{params[:value]}' in title '#{title}'")
  634. else
  635. fail "not matching '#{params[:value]}' in title '#{title}'"
  636. end
  637. end
  638. =begin
  639. verify_task(
  640. browser: browser1,
  641. data: {
  642. title: 'some title',
  643. modified: true, # optional
  644. }
  645. )
  646. =end
  647. def verify_task(params = {}, fallback = false)
  648. switch_window_focus(params)
  649. log('verify_task', params)
  650. instance = params[:browser] || @browser
  651. data = params[:data]
  652. sleep 1
  653. begin
  654. # verify title
  655. if data[:title]
  656. title = instance.find_elements({ css: '.tasks .is-active' })[0].text.strip
  657. if title =~ /#{data[:title]}/i
  658. assert(true, "matching '#{data[:title]}' in title '#{title}'")
  659. else
  660. fail "not matching '#{data[:title]}' in title '#{title}'"
  661. end
  662. end
  663. puts "tv #{params.inspect}"
  664. # verify modified
  665. if data.key?(:modified)
  666. exists = instance.find_elements({ css: '.tasks .is-active' })[0]
  667. is_modified = instance.find_elements({ css: '.tasks .is-modified' })[0]
  668. puts "m #{data[:modified].inspect}"
  669. if exists
  670. puts ' exists'
  671. end
  672. if is_modified
  673. puts ' is_modified'
  674. end
  675. if data[:modified] == true
  676. if is_modified
  677. assert(true, "task '#{data[:title]}' is modifed")
  678. elsif !exists
  679. fail "task '#{data[:title]}' not exists, should not modified"
  680. else
  681. fail "task '#{data[:title]}' is not modifed"
  682. end
  683. elsif !is_modified
  684. assert(true, "task '#{data[:title]}' is modifed")
  685. elsif !exists
  686. fail "task '#{data[:title]}' not exists, should be not modified"
  687. else
  688. fail "task '#{data[:title]}' is modifed, but should not"
  689. end
  690. end
  691. rescue => e
  692. # just try again
  693. if !fallback
  694. verify_task(params, true)
  695. end
  696. raise 'ERROR: ' + e.inspect
  697. end
  698. true
  699. end
  700. =begin
  701. open_task(
  702. browser: browser1,
  703. data: {
  704. title: 'some title',
  705. }
  706. )
  707. =end
  708. def open_task(params = {}, _fallback = false)
  709. switch_window_focus(params)
  710. log('open_task', params)
  711. instance = params[:browser] || @browser
  712. data = params[:data]
  713. element = instance.find_elements({ partial_link_text: data[:title] })[0]
  714. if !element
  715. screenshot(browser: instance, comment: 'open_task_failed')
  716. fail "no task with title '#{data[:title]}' found"
  717. end
  718. element.click
  719. true
  720. end
  721. =begin
  722. file_upload(
  723. browser: browser1,
  724. css: '.active .attachmentPlaceholder-inputHolder input'
  725. files: ['path/in/home/some_file.ext'], # 'test/fixtures/test1.pdf'
  726. )
  727. =end
  728. def file_upload(params = {})
  729. switch_window_focus(params)
  730. log('file_upload', params)
  731. instance = params[:browser] || @browser
  732. params[:files].each {|file|
  733. instance.find_elements({ css: params[:css] })[0].send_keys "#{Rails.root}/#{file}"
  734. }
  735. sleep 2 * params[:files].count
  736. end
  737. =begin
  738. watch_for(
  739. browser: browser1,
  740. css: '#content .text-1',
  741. value: 'some text',
  742. attribute: 'some_attribute' # optional
  743. timeout: '16', # in sec, default 16
  744. )
  745. =end
  746. def watch_for(params = {})
  747. switch_window_focus(params)
  748. log('watch_for', params)
  749. instance = params[:browser] || @browser
  750. timeout = 16
  751. if params[:timeout]
  752. timeout = params[:timeout]
  753. end
  754. loops = timeout.to_i * 2
  755. text = ''
  756. (1..loops).each {
  757. element = instance.find_elements({ css: params[:css] })[0]
  758. if element #&& element.displayed?
  759. begin
  760. # match pn attribute
  761. text = if params[:attribute]
  762. element.attribute(params[:attribute])
  763. elsif params[:css] =~ /(input|textarea)/i
  764. element.attribute('value')
  765. else
  766. element.text
  767. end
  768. if text =~ /#{params[:value]}/i
  769. assert(true, "'#{params[:value]}' found in '#{text}'")
  770. sleep 0.5
  771. return true
  772. end
  773. rescue
  774. # try again
  775. end
  776. end
  777. sleep 0.5
  778. }
  779. screenshot(browser: instance, comment: 'watch_for_failed')
  780. fail "'#{params[:value]}' found in '#{text}'"
  781. end
  782. =begin
  783. wait untill selector disabppears
  784. watch_for_disappear(
  785. browser: browser1,
  786. css: '#content .text-1',
  787. timeout: '16', # in sec, default 16
  788. )
  789. wait untill text in selector disabppears
  790. watch_for_disappear(
  791. browser: browser1,
  792. css: '#content .text-1',
  793. value: 'some value as regexp',
  794. timeout: '16', # in sec, default 16
  795. )
  796. =end
  797. def watch_for_disappear(params = {})
  798. switch_window_focus(params)
  799. log('watch_for_disappear', params)
  800. instance = params[:browser] || @browser
  801. timeout = 16
  802. if params[:timeout]
  803. timeout = params[:timeout]
  804. end
  805. loops = timeout.to_i
  806. text = ''
  807. (1..loops).each {
  808. element = instance.find_elements({ css: params[:css] })[0]
  809. if !element #|| element.displayed?
  810. assert(true, 'not found')
  811. sleep 1
  812. return true
  813. end
  814. if params[:value]
  815. begin
  816. text = instance.find_elements({ css: params[:css] })[0].text
  817. if text !~ /#{params[:value]}/i
  818. assert(true, "not matching '#{params[:value]}' in text '#{text}'")
  819. sleep 1
  820. return true
  821. end
  822. rescue
  823. # try again
  824. end
  825. end
  826. sleep 1
  827. }
  828. screenshot(browser: instance, comment: 'disappear_failed')
  829. fail "#{params[:css]}) still exsists"
  830. end
  831. =begin
  832. tasks_close_all(
  833. browser: browser1,
  834. discard_changes: true,
  835. )
  836. =end
  837. def tasks_close_all(params = {})
  838. switch_window_focus(params)
  839. log('tasks_close_all', params)
  840. instance = params[:browser] || @browser
  841. (1..100).each do
  842. sleep 1
  843. begin
  844. if instance.find_elements({ css: '.navigation .tasks .task:first-child' })[0]
  845. instance.mouse.move_to(instance.find_elements({ css: '.navigation .tasks .task:first-child' })[0])
  846. sleep 0.1
  847. click_element = instance.find_elements({ css: '.navigation .tasks .task:first-child .js-close' })[0]
  848. if click_element
  849. click_element.click
  850. # accept task close warning
  851. if params[:discard_changes]
  852. sleep 1
  853. instance.find_elements({ css: '.modal button.js-submit' })[0].click
  854. end
  855. end
  856. else
  857. break
  858. end
  859. rescue
  860. # try again
  861. end
  862. end
  863. sleep 1
  864. assert(true, 'all tasks closed')
  865. end
  866. =begin
  867. ticket_customer_select(
  868. browser: browser1,
  869. css: '#content .text-1',
  870. customer: '',
  871. )
  872. =end
  873. def ticket_customer_select(params = {})
  874. switch_window_focus(params)
  875. log('ticket_customer_select', params)
  876. instance = params[:browser] || @browser
  877. element = instance.find_elements({ css: params[:css] + ' input[name="customer_id_completion"]' })[0]
  878. element.click
  879. element.clear
  880. # workaround, sometimes focus is not triggered
  881. element.send_keys(params[:customer] + '*')
  882. sleep 3.5
  883. # check if pulldown is open, it's not working stable via selenium
  884. #instance.execute_script("$('#{params[:css]} .js-recipientDropdown').addClass('open')")
  885. #sleep 0.5
  886. element.send_keys(:arrow_down)
  887. sleep 0.3
  888. element.send_keys(:enter)
  889. #instance.find_elements({ css: params[:css] + ' .recipientList-entry.js-user.is-active' })[0].click
  890. sleep 0.6
  891. assert(true, 'ticket_customer_select')
  892. end
  893. =begin
  894. username = overview_create(
  895. browser: browser1,
  896. data: {
  897. name: name,
  898. role: 'Agent',
  899. selector: {
  900. 'Priority': '1 low',
  901. },
  902. prio: 1000,
  903. 'order::direction' => 'down',
  904. }
  905. )
  906. =end
  907. def overview_create(params)
  908. switch_window_focus(params)
  909. log('overview_create', params)
  910. instance = params[:browser] || @browser
  911. data = params[:data]
  912. instance.find_elements({ css: 'a[href="#manage"]' })[0].click
  913. instance.find_elements({ css: 'a[href="#manage/overviews"]' })[0].click
  914. sleep 0.2
  915. instance.find_elements({ css: '#content a[data-type="new"]' })[0].click
  916. sleep 2
  917. if data[:name]
  918. element = instance.find_elements({ css: '.modal input[name=name]' })[0]
  919. element.clear
  920. element.send_keys(data[:name])
  921. end
  922. if data[:role]
  923. element = instance.find_elements({ css: '.modal select[name="role_id"]' })[0]
  924. dropdown = Selenium::WebDriver::Support::Select.new(element)
  925. dropdown.select_by(:text, data[:role])
  926. end
  927. if data[:selector]
  928. data[:selector].each {|key, value|
  929. element = instance.find_elements({ css: '.modal .ticket_selector .js-attributeSelector select' })[0]
  930. dropdown = Selenium::WebDriver::Support::Select.new(element)
  931. dropdown.select_by(:text, key)
  932. element = instance.find_elements({ css: '.modal .ticket_selector .js-value select' })[0]
  933. dropdown = Selenium::WebDriver::Support::Select.new(element)
  934. dropdown.deselect_all
  935. dropdown.select_by(:text, value)
  936. }
  937. end
  938. if data[:prio]
  939. element = instance.find_elements({ css: '.modal input[name=prio]' })[0]
  940. element.clear
  941. element.send_keys(data[:prio])
  942. end
  943. if data['order::direction']
  944. element = instance.find_elements({ css: '.modal select[name="order::direction"]' })[0]
  945. dropdown = Selenium::WebDriver::Support::Select.new(element)
  946. dropdown.select_by(:text, data['order::direction'])
  947. end
  948. instance.find_elements({ css: '.modal button.js-submit' })[0].click
  949. (1..12).each {
  950. element = instance.find_elements({ css: 'body' })[0]
  951. text = element.text
  952. if text =~ /#{Regexp.quote(data[:name])}/
  953. assert(true, 'overview created')
  954. overview = {
  955. name: name,
  956. }
  957. return overview
  958. end
  959. sleep 1
  960. }
  961. screenshot(browser: instance, comment: 'overview_create_failed')
  962. fail 'overview creation failed'
  963. end
  964. =begin
  965. ticket = ticket_create(
  966. browser: browser1,
  967. data: {
  968. customer: 'nico',
  969. group: 'Users',
  970. priority: '2 normal',
  971. title: 'overview #1',
  972. body: 'overview #1',
  973. },
  974. do_not_submit: true,
  975. )
  976. returns (in case of submitted)
  977. {
  978. id: 123,
  979. number: '100001',
  980. }
  981. =end
  982. def ticket_create(params)
  983. switch_window_focus(params)
  984. log('ticket_create', params)
  985. instance = params[:browser] || @browser
  986. data = params[:data]
  987. instance.find_elements({ css: 'a[href="#new"]' })[0].click
  988. instance.find_elements({ css: 'a[href="#ticket/create"]' })[0].click
  989. element = instance.find_elements({ css: '.active .newTicket' })[0]
  990. if !element
  991. screenshot(browser: instance, comment: 'ticket_create_failed')
  992. fail 'no ticket create screen found!'
  993. end
  994. sleep 1
  995. # check count of agents, should be only 1 / - selection on init screen
  996. count = instance.find_elements({ css: '.active .newTicket select[name="owner_id"] option' }).count
  997. assert_equal(1, count, 'check if owner selection is empty per default' )
  998. if data[:group]
  999. element = instance.find_elements({ css: '.active .newTicket select[name="group_id"]' })[0]
  1000. dropdown = Selenium::WebDriver::Support::Select.new(element)
  1001. dropdown.select_by(:text, data[:group])
  1002. sleep 0.2
  1003. end
  1004. if data[:priority]
  1005. element = instance.find_elements({ css: '.active .newTicket select[name="priority_id"]' })[0]
  1006. dropdown = Selenium::WebDriver::Support::Select.new(element)
  1007. dropdown.select_by(:text, data[:priority])
  1008. sleep 0.2
  1009. end
  1010. if data[:title]
  1011. element = instance.find_elements({ css: '.active .newTicket input[name="title"]' })[0]
  1012. element.clear
  1013. element.send_keys(data[:title])
  1014. sleep 0.2
  1015. end
  1016. if data[:body]
  1017. #instance.execute_script('$(".active .newTicket div[data-name=body]").focus()')
  1018. sleep 0.5
  1019. element = instance.find_elements({ css: '.active .newTicket div[data-name=body]' })[0]
  1020. element.clear
  1021. element.send_keys(data[:body])
  1022. # it's not working stable via selenium, use js
  1023. value = instance.find_elements({ css: '.content .newTicket div[data-name=body]' })[0].text
  1024. #puts "V #{value.inspect}"
  1025. if value != data[:body]
  1026. body_quoted = quote(data[:body])
  1027. instance.execute_script("$('.content.active div[data-name=body]').html('#{body_quoted}').trigger('focusout')")
  1028. end
  1029. end
  1030. if data[:customer]
  1031. element = instance.find_elements({ css: '.active .newTicket input[name="customer_id_completion"]' })[0]
  1032. element.click
  1033. element.clear
  1034. # workaround, sometimes focus is not triggered
  1035. element.send_keys(data[:customer] + '*')
  1036. sleep 3.5
  1037. # check if pulldown is open, it's not working stable via selenium
  1038. #instance.execute_script("$('.active .newTicket .js-recipientDropdown').addClass('open')")
  1039. #sleep 0.5
  1040. element.send_keys(:arrow_down)
  1041. sleep 0.3
  1042. element.send_keys(:enter)
  1043. #instance.find_elements({ css: '.active .newTicket .recipientList-entry.js-user.is-active' })[0].click
  1044. sleep 0.6
  1045. end
  1046. if data[:attachment]
  1047. file_upload(
  1048. browser: instance,
  1049. css: '#content .text-1',
  1050. value: 'some text',
  1051. )
  1052. end
  1053. if params[:do_not_submit]
  1054. assert(true, 'ticket created without submit')
  1055. return
  1056. end
  1057. sleep 0.8
  1058. #instance.execute_script('$(".content.active .newTicket form").submit();')
  1059. instance.find_elements({ css: '.active .newTicket button.js-submit' })[0].click
  1060. sleep 1
  1061. (1..10).each {
  1062. if instance.current_url =~ /#{Regexp.quote('#ticket/zoom/')}/
  1063. assert(true, 'ticket created')
  1064. sleep 2.5
  1065. id = instance.current_url
  1066. id.gsub!(//,)
  1067. id.gsub!(%r{^.+?/(\d+)$}, '\\1')
  1068. element = instance.find_elements({ css: '.active .ticketZoom-header .ticket-number' })[0]
  1069. if element
  1070. number = element.text
  1071. ticket = {
  1072. id: id,
  1073. number: number,
  1074. }
  1075. sleep 3 # wait until notify is gone
  1076. screenshot(browser: instance, comment: 'ticket_create_ok')
  1077. return ticket
  1078. end
  1079. end
  1080. sleep 1
  1081. }
  1082. screenshot(browser: instance, comment: 'ticket_create_failed')
  1083. fail "ticket creation failed, can't get zoom url (current url is '#{instance.current_url}')"
  1084. end
  1085. =begin
  1086. ticket_update(
  1087. browser: browser1,
  1088. data: {
  1089. title: '',
  1090. customer: 'some_customer@example.com',
  1091. body: 'some body',
  1092. group: 'some group',
  1093. priority: '1 low',
  1094. state: 'closed',
  1095. },
  1096. do_not_submit: true,
  1097. )
  1098. =end
  1099. def ticket_update(params)
  1100. switch_window_focus(params)
  1101. log('ticket_update', params)
  1102. instance = params[:browser] || @browser
  1103. data = params[:data]
  1104. if data[:title]
  1105. #element = instance.find_elements({ :css => '.content.active .ticketZoom-header .ticket-title-update' })[0]
  1106. #element.clear
  1107. #sleep 0.5
  1108. #element = instance.find_elements({ :css => '.content.active .ticketZoom-header .ticket-title-update' })[0]
  1109. #element.send_keys(data[:title])
  1110. #sleep 0.5
  1111. #element.send_keys(:tab)
  1112. instance.execute_script('$(".content.active .ticketZoom-header .ticket-title-update").focus()')
  1113. instance.execute_script('$(".content.active .ticketZoom-header .ticket-title-update").text("' + data[:title] + '")')
  1114. instance.execute_script('$(".content.active .ticketZoom-header .ticket-title-update").blur()')
  1115. instance.execute_script('$(".content.active .ticketZoom-header .ticket-title-update").trigger("blur")')
  1116. # {
  1117. # :where => :instance2,
  1118. # :execute => 'sendkey',
  1119. # :css => '.content.active .ticketZoom-header .ticket-title-update',
  1120. # :value => 'TTT',
  1121. # },
  1122. # {
  1123. # :where => :instance2,
  1124. # :execute => 'sendkey',
  1125. # :css => '.content.active .ticketZoom-header .ticket-title-update',
  1126. # :value => :tab,
  1127. # },
  1128. end
  1129. if data[:customer]
  1130. # select tab
  1131. click(browser: instance, css: '.active .tabsSidebar-tab[data-tab="customer"]')
  1132. click(browser: instance, css: '.active div[data-tab="customer"] .js-actions .icon-arrow-down')
  1133. click(browser: instance, css: '.active div[data-tab="customer"] .js-actions [data-type="customer-change"]')
  1134. watch_for(
  1135. browser: instance,
  1136. css: '.modal',
  1137. value: 'change',
  1138. )
  1139. element = instance.find_elements({ css: '.modal input[name="customer_id_completion"]' })[0]
  1140. element.click
  1141. element.clear
  1142. # workaround, sometimes focus is not triggered
  1143. element.send_keys(data[:customer])
  1144. sleep 3.5
  1145. # check if pulldown is open, it's not working stable via selenium
  1146. #instance.execute_script("$('.modal .user_autocompletion .js-recipientDropdown').addClass('open')")
  1147. #sleep 0.5
  1148. element.send_keys(:arrow_down)
  1149. sleep 0.6
  1150. element.send_keys(:enter)
  1151. #instance.find_elements({ css: '.modal .user_autocompletion .recipientList-entry.js-user.is-active' })[0].click
  1152. sleep 0.3
  1153. click(browser: instance, css: '.modal .js-submit')
  1154. watch_for_disappear(
  1155. browser: instance,
  1156. css: '.modal',
  1157. )
  1158. watch_for(
  1159. browser: instance,
  1160. css: '.active .tabsSidebar',
  1161. value: data[:customer],
  1162. )
  1163. # select tab
  1164. click(browser: instance, css: '.active .tabsSidebar-tab[data-tab="ticket"]')
  1165. end
  1166. if data[:body]
  1167. #instance.execute_script('$(".content.active div[data-name=body]").focus()')
  1168. sleep 0.5
  1169. element = instance.find_elements({ css: '.content.active div[data-name=body]' })[0]
  1170. element.clear
  1171. element.send_keys(data[:body])
  1172. # it's not working stable via selenium, use js
  1173. value = instance.find_elements({ css: '.content.active div[data-name=body]' })[0].text
  1174. if value != data[:body]
  1175. body_quoted = quote(data[:body])
  1176. instance.execute_script("$('.content.active div[data-name=body]').html('#{body_quoted}').trigger('focusout')")
  1177. end
  1178. end
  1179. if data[:group]
  1180. element = instance.find_elements({ css: '.active .sidebar select[name="group_id"]' })[0]
  1181. dropdown = Selenium::WebDriver::Support::Select.new(element)
  1182. dropdown.select_by(:text, data[:group])
  1183. sleep 0.2
  1184. end
  1185. if data[:priority]
  1186. element = instance.find_elements({ css: '.active .sidebar select[name="priority_id"]' })[0]
  1187. dropdown = Selenium::WebDriver::Support::Select.new(element)
  1188. dropdown.select_by(:text, data[:priority])
  1189. sleep 0.2
  1190. end
  1191. if data[:state]
  1192. element = instance.find_elements({ css: '.active .sidebar select[name="state_id"]' })[0]
  1193. dropdown = Selenium::WebDriver::Support::Select.new(element)
  1194. dropdown.select_by(:text, data[:state])
  1195. sleep 0.2
  1196. end
  1197. if data[:state] || data[:group] || data[:body]
  1198. found = nil
  1199. (1..10).each {
  1200. break if found
  1201. begin
  1202. text = instance.find_elements({ css: '.content.active .js-reset' })[0].text
  1203. if text =~ /(Discard your unsaved changes.|Verwerfen der)/
  1204. found = true
  1205. end
  1206. rescue
  1207. # try again
  1208. end
  1209. sleep 1
  1210. }
  1211. if !found
  1212. screenshot(browser: instance, comment: 'ticket_update_discard_message_failed')
  1213. fail 'no discard message found'
  1214. end
  1215. end
  1216. task_type(
  1217. browser: instance,
  1218. type: 'stayOnTab',
  1219. )
  1220. if params[:do_not_submit]
  1221. assert(true, 'ticket updated without submit')
  1222. return true
  1223. end
  1224. instance.find_elements({ css: '.content.active .js-submit' })[0].click
  1225. (1..10).each {
  1226. begin
  1227. text = instance.find_elements({ css: '.content.active .js-reset' })[0].text
  1228. if !text || text.empty?
  1229. screenshot(browser: instance, comment: 'ticket_update_ok')
  1230. return true
  1231. end
  1232. rescue
  1233. # try again
  1234. end
  1235. sleep 1
  1236. }
  1237. screenshot(browser: instance, comment: 'ticket_update_failed')
  1238. fail 'unable to update ticket'
  1239. end
  1240. =begin
  1241. ticket_verify(
  1242. browser: browser1,
  1243. data: {
  1244. title: 'some title',
  1245. body: 'some body',
  1246. ## group: 'some group',
  1247. ## state: 'closed',
  1248. },
  1249. )
  1250. =end
  1251. def ticket_verify(params)
  1252. switch_window_focus(params)
  1253. log('ticket_verify', params)
  1254. instance = params[:browser] || @browser
  1255. data = params[:data]
  1256. if data[:title]
  1257. title = instance.find_elements({ css: '.content.active .ticketZoom-header .ticket-title-update' })[0].text.strip
  1258. if title =~ /#{data[:title]}/i
  1259. assert(true, "matching '#{data[:title]}' in title '#{title}'")
  1260. else
  1261. fail "not matching '#{data[:title]}' in title '#{title}'"
  1262. end
  1263. end
  1264. if data[:body]
  1265. body = instance.find_elements({ css: '.content.active [data-name="body"]' })[0].text.strip
  1266. if body =~ /#{data[:body]}/i
  1267. assert(true, "matching '#{data[:body]}' in body '#{body}'")
  1268. else
  1269. fail "not matching '#{data[:body]}' in body '#{body}'"
  1270. end
  1271. end
  1272. true
  1273. end
  1274. =begin
  1275. ticket_open_by_overview(
  1276. browser: browser2,
  1277. number: ticket1[:number],
  1278. link: "#ticket/view/#{name}",
  1279. )
  1280. =end
  1281. def ticket_open_by_overview(params)
  1282. switch_window_focus(params)
  1283. log('ticket_open_by_overview', params)
  1284. instance = params[:browser] || @browser
  1285. instance.find_elements({ css: '.js-overviewsMenuItem' })[0].click
  1286. sleep 1
  1287. execute(
  1288. browser: instance,
  1289. js: '$(".content.active .sidebar").css("display", "block")',
  1290. )
  1291. instance.find_elements({ css: ".content.active .sidebar a[href=\"#{params[:link]}\"]" })[0].click
  1292. sleep 1
  1293. execute(
  1294. browser: instance,
  1295. js: '$(".content.active .sidebar").css("display", "none")',
  1296. )
  1297. instance.find_elements({ partial_link_text: params[:number] })[0].click
  1298. sleep 1
  1299. number = instance.find_elements({ css: '.active .ticketZoom-header .ticket-number' })[0].text
  1300. if number !~ /#{params[:number]}/
  1301. screenshot(browser: instance, comment: 'ticket_open_by_overview_failed')
  1302. fail "unable to search/find ticket #{params[:number]}!"
  1303. end
  1304. sleep 1
  1305. assert(true, "ticket #{params[:number]} found")
  1306. true
  1307. end
  1308. =begin
  1309. ticket_open_by_search(
  1310. browser: browser2,
  1311. number: ticket1[:number],
  1312. )
  1313. =end
  1314. def ticket_open_by_search(params)
  1315. switch_window_focus(params)
  1316. log('ticket_open_by_search', params)
  1317. instance = params[:browser] || @browser
  1318. # search by number
  1319. element = instance.find_elements({ css: '#global-search' })[0]
  1320. element.click
  1321. element.clear
  1322. element.send_keys(params[:number])
  1323. sleep 3
  1324. # empty search box by x
  1325. instance.find_elements({ css: '.search .empty-search' })[0].click
  1326. sleep 0.5
  1327. text = instance.find_elements({ css: '#global-search' })[0].attribute('value')
  1328. if !text
  1329. fail '#global-search is not empty!'
  1330. end
  1331. # search by number again
  1332. element = instance.find_elements({ css: '#global-search' })[0]
  1333. element.click
  1334. element.clear
  1335. element.send_keys(params[:number])
  1336. sleep 1
  1337. # open ticket
  1338. #instance.find_element({ partial_link_text: params[:number] } ).click
  1339. instance.execute_script("$(\"#global-search-result a:contains('#{params[:value]}') .nav-tab-icon\").click()")
  1340. number = instance.find_elements({ css: '.active .ticketZoom-header .ticket-number' })[0].text
  1341. if number !~ /#{params[:number]}/
  1342. screenshot(browser: instance, comment: 'ticket_open_by_search_failed')
  1343. fail "unable to search/find ticket #{params[:number]}!"
  1344. end
  1345. sleep 1
  1346. true
  1347. end
  1348. =begin
  1349. ticket_open_by_title(
  1350. browser: browser2,
  1351. title: ticket1[:title],
  1352. )
  1353. =end
  1354. def ticket_open_by_title(params)
  1355. switch_window_focus(params)
  1356. log('ticket_open_by_title', params)
  1357. instance = params[:browser] || @browser
  1358. # search by number
  1359. element = instance.find_elements({ css: '#global-search' })[0]
  1360. element.click
  1361. element.clear
  1362. element.send_keys(params[:title])
  1363. sleep 3
  1364. # open ticket
  1365. #instance.find_element({ partial_link_text: params[:title] } ).click
  1366. instance.execute_script("$(\"#global-search-result a:contains('#{params[:title]}') .nav-tab-icon\").click()")
  1367. title = instance.find_elements({ css: '.active .ticketZoom-header .ticket-title-update' })[0].text
  1368. if title !~ /#{params[:title]}/
  1369. screenshot(browser: instance, comment: 'ticket_open_by_title_failed')
  1370. fail "unable to search/find ticket #{params[:title]}!"
  1371. end
  1372. sleep 1
  1373. true
  1374. end
  1375. =begin
  1376. overview_count = overview_counter(
  1377. browser: browser2,
  1378. )
  1379. returns
  1380. {
  1381. '#ticket/view/all_unassigned' => 42,
  1382. }
  1383. =end
  1384. def overview_counter(params = {})
  1385. switch_window_focus(params)
  1386. log('overview_counter', params)
  1387. instance = params[:browser] || @browser
  1388. instance.find_elements({ css: '.js-overviewsMenuItem' })[0].click
  1389. sleep 2
  1390. execute(
  1391. browser: instance,
  1392. js: '$(".content.active .sidebar").css("display", "block")',
  1393. )
  1394. #execute(
  1395. # browser: instance,
  1396. # js: '$(".content.active .overview-header").css("display", "none")',
  1397. #)
  1398. overviews = {}
  1399. instance.find_elements({ css: '.content.active .sidebar a[href]' }).each {|element|
  1400. url = element.attribute('href')
  1401. url.gsub!(%r{(http|https)://.+?/(.+?)$}, '\\2')
  1402. overviews[url] = 0
  1403. #puts url.inspect
  1404. #puts element.inspect
  1405. }
  1406. overviews.each {|url, _value|
  1407. count = instance.find_elements({ css: ".content.active .sidebar a[href=\"#{url}\"] .badge" })[0].text
  1408. overviews[url] = count.to_i
  1409. }
  1410. log('overview_counter', overviews)
  1411. overviews
  1412. end
  1413. =begin
  1414. organization_open_by_search(
  1415. browser: browser2,
  1416. value: 'some value',
  1417. )
  1418. =end
  1419. def organization_open_by_search(params = {})
  1420. switch_window_focus(params)
  1421. log('organization_open_by_search', params)
  1422. instance = params[:browser] || @browser
  1423. element = instance.find_elements({ css: '#global-search' })[0]
  1424. element.click
  1425. element.clear
  1426. element.send_keys(params[:value])
  1427. sleep 3
  1428. instance.find_elements({ css: '.search .empty-search' })[0].click
  1429. sleep 0.5
  1430. text = instance.find_elements({ css: '#global-search' })[0].attribute('value')
  1431. if !text
  1432. fail '#global-search is not empty!'
  1433. end
  1434. element = instance.find_elements({ css: '#global-search' })[0]
  1435. element.click
  1436. element.clear
  1437. element.send_keys(params[:value])
  1438. sleep 2
  1439. #instance.find_element({ partial_link_text: params[:value] } ).click
  1440. instance.execute_script("$(\"#global-search-result a:contains('#{params[:value]}') .nav-tab-icon\").click()")
  1441. name = instance.find_elements({ css: '.active h1' })[0].text
  1442. if name !~ /#{params[:value]}/
  1443. screenshot(browser: instance, comment: 'organization_open_by_search_failed')
  1444. fail "unable to search/find org #{params[:value]}!"
  1445. end
  1446. assert(true, "org #{params[:value]} found")
  1447. sleep 2
  1448. true
  1449. end
  1450. =begin
  1451. user_open_by_search(
  1452. browser: browser2,
  1453. value: 'some value',
  1454. )
  1455. =end
  1456. def user_open_by_search(params = {})
  1457. switch_window_focus(params)
  1458. log('user_open_by_search', params)
  1459. instance = params[:browser] || @browser
  1460. element = instance.find_elements({ css: '#global-search' })[0]
  1461. element.click
  1462. element.clear
  1463. element.send_keys(params[:value])
  1464. sleep 3
  1465. #instance.find_element({ partial_link_text: params[:value] }).click
  1466. instance.execute_script("$(\"#global-search-result a:contains('#{params[:value]}') .nav-tab-icon\").click()")
  1467. name = instance.find_elements({ css: '.active h1' })[0].text
  1468. if name !~ /#{params[:value]}/
  1469. screenshot(browser: instance, comment: 'user_open_by_search_failed')
  1470. fail "unable to search/find user #{params[:value]}!"
  1471. end
  1472. assert(true, "user #{params[:term]} found")
  1473. sleep 2
  1474. true
  1475. end
  1476. =begin
  1477. user_create(
  1478. browser: browser2,
  1479. data: {
  1480. #login: 'some login' + random,
  1481. firstname: 'Manage Firstname' + random,
  1482. lastname: 'Manage Lastname' + random,
  1483. email: user_email,
  1484. password: 'some-pass',
  1485. },
  1486. )
  1487. =end
  1488. def user_create(params = {})
  1489. switch_window_focus(params)
  1490. log('user_create', params)
  1491. instance = params[:browser] || @browser
  1492. data = params[:data]
  1493. instance.find_elements({ css: 'a[href="#manage"]' })[0].click
  1494. sleep 1
  1495. instance.find_elements({ css: 'a[href="#manage/users"]' })[0].click
  1496. sleep 2
  1497. instance.find_elements({ css: 'a[data-type="new"]' })[0].click
  1498. sleep 2
  1499. element = instance.find_elements({ css: '.modal input[name=firstname]' })[0]
  1500. element.clear
  1501. element.send_keys(data[:firstname])
  1502. element = instance.find_elements({ css: '.modal input[name=lastname]' })[0]
  1503. element.clear
  1504. element.send_keys(data[:lastname])
  1505. element = instance.find_elements({ css: '.modal input[name=email]' })[0]
  1506. element.clear
  1507. element.send_keys(data[:email])
  1508. element = instance.find_elements({ css: '.modal input[name=password]' })[0]
  1509. element.clear
  1510. element.send_keys(data[:password])
  1511. element = instance.find_elements({ css: '.modal input[name=password_confirm]' })[0]
  1512. element.clear
  1513. element.send_keys(data[:password])
  1514. instance.find_elements({ css: '.modal input[name="role_ids"][value="3"]' })[0].click
  1515. instance.find_elements({ css: '.modal button.js-submit' })[0].click
  1516. sleep 3.5
  1517. set(
  1518. browser: instance,
  1519. css: '.content .js-search',
  1520. value: data[:email],
  1521. )
  1522. watch_for(
  1523. browser: instance,
  1524. css: 'body',
  1525. value: data[:lastname],
  1526. )
  1527. assert(true, 'user created')
  1528. end
  1529. =begin
  1530. sla_create(
  1531. browser: browser2,
  1532. data: {
  1533. name: 'some sla' + random,
  1534. first_response_time_in_text: 61
  1535. },
  1536. )
  1537. =end
  1538. def sla_create(params = {})
  1539. switch_window_focus(params)
  1540. log('sla_create', params)
  1541. instance = params[:browser] || @browser
  1542. data = params[:data]
  1543. instance.find_elements({ css: 'a[href="#manage"]' })[0].click
  1544. sleep 1
  1545. instance.find_elements({ css: 'a[href="#manage/slas"]' })[0].click
  1546. sleep 2
  1547. instance.find_elements({ css: 'a.js-new' })[0].click
  1548. sleep 2
  1549. element = instance.find_elements({ css: '.modal input[name=name]' })[0]
  1550. element.clear
  1551. element.send_keys(data[:name])
  1552. element = instance.find_elements({ css: '.modal input[name=first_response_time_in_text]' })[0]
  1553. element.clear
  1554. element.send_keys(data[:first_response_time_in_text])
  1555. instance.find_elements({ css: '.modal button.js-submit' })[0].click
  1556. (1..8).each {
  1557. element = instance.find_elements({ css: 'body' })[0]
  1558. text = element.text
  1559. if text =~ /#{Regexp.quote(data[:name])}/
  1560. assert(true, 'sla created')
  1561. return true
  1562. end
  1563. sleep 1
  1564. }
  1565. screenshot(browser: instance, comment: 'sla_create_failed')
  1566. fail 'sla creation failed'
  1567. end
  1568. =begin
  1569. text_module_create(
  1570. browser: browser2,
  1571. data: {
  1572. name: 'some sla' + random,
  1573. keywords: 'some keywords',
  1574. content: 'some content',
  1575. },
  1576. )
  1577. =end
  1578. def text_module_create(params = {})
  1579. switch_window_focus(params)
  1580. log('text_module_create', params)
  1581. instance = params[:browser] || @browser
  1582. data = params[:data]
  1583. instance.find_elements({ css: 'a[href="#manage"]' })[0].click
  1584. sleep 1
  1585. instance.find_elements({ css: 'a[href="#manage/text_modules"]' })[0].click
  1586. sleep 2
  1587. instance.find_elements({ css: 'a[data-type="new"]' })[0].click
  1588. sleep 2
  1589. element = instance.find_elements({ css: '.modal input[name=name]' })[0]
  1590. element.clear
  1591. element.send_keys(data[:name])
  1592. element = instance.find_elements({ css: '.modal input[name=keywords]' })[0]
  1593. element.clear
  1594. element.send_keys(data[:keywords])
  1595. element = instance.find_elements({ css: '.modal textarea[name=content]' })[0]
  1596. element.clear
  1597. element.send_keys(data[:content])
  1598. instance.find_elements({ css: '.modal button.js-submit' })[0].click
  1599. (1..8).each {
  1600. element = instance.find_elements({ css: 'body' })[0]
  1601. text = element.text
  1602. if text =~ /#{Regexp.quote(data[:name])}/
  1603. assert(true, 'text module created')
  1604. return true
  1605. end
  1606. sleep 1
  1607. }
  1608. screenshot(browser: instance, comment: 'text_module_create_failed')
  1609. fail 'text module creation failed'
  1610. end
  1611. =begin
  1612. signature_create(
  1613. browser: browser2,
  1614. data: {
  1615. name: 'some sla' + random,
  1616. body: 'some body',
  1617. },
  1618. )
  1619. =end
  1620. def signature_create(params = {})
  1621. switch_window_focus(params)
  1622. log('signature_create', params)
  1623. instance = params[:browser] || @browser
  1624. data = params[:data]
  1625. instance.find_elements({ css: 'a[href="#manage"]' })[0].click
  1626. sleep 1
  1627. instance.find_elements({ css: 'a[href="#channels/email"]' })[0].click
  1628. sleep 1
  1629. instance.find_elements({ css: 'a[href="#c-signature"]' })[0].click
  1630. sleep 8
  1631. instance.find_elements({ css: '#content #c-signature a[data-type="new"]' })[0].click
  1632. sleep 2
  1633. element = instance.find_elements({ css: '.modal input[name=name]' })[0]
  1634. element.clear
  1635. element.send_keys(data[:name])
  1636. element = instance.find_elements({ css: '.modal textarea[name=body]' })[0]
  1637. element.clear
  1638. element.send_keys(data[:body])
  1639. instance.find_elements({ css: '.modal button.js-submit' })[0].click
  1640. (1..12).each {
  1641. element = instance.find_elements({ css: 'body' })[0]
  1642. text = element.text
  1643. if text =~ /#{Regexp.quote(data[:name])}/
  1644. assert(true, 'signature created')
  1645. return true
  1646. end
  1647. sleep 1
  1648. }
  1649. screenshot(browser: instance, comment: 'signature_create_failed')
  1650. fail 'signature creation failed'
  1651. end
  1652. =begin
  1653. group_create(
  1654. browser: browser2,
  1655. data: {
  1656. name: 'some sla' + random,
  1657. signature: 'some signature bame',
  1658. member: [
  1659. 'some_user_login',
  1660. ],
  1661. },
  1662. )
  1663. =end
  1664. def group_create(params = {})
  1665. switch_window_focus(params)
  1666. log('group_create', params)
  1667. instance = params[:browser] || @browser
  1668. data = params[:data]
  1669. instance.find_elements({ css: 'a[href="#manage"]' })[0].click
  1670. sleep 0.5
  1671. instance.find_elements({ css: 'a[href="#manage/groups"]' })[0].click
  1672. sleep 2
  1673. instance.find_elements({ css: 'a[data-type="new"]' })[0].click
  1674. sleep 2
  1675. element = instance.find_elements({ css: '.modal input[name=name]' })[0]
  1676. element.clear
  1677. element.send_keys(data[:name])
  1678. element = instance.find_elements({ css: '.modal select[name="email_address_id"]' })[0]
  1679. dropdown = Selenium::WebDriver::Support::Select.new(element)
  1680. dropdown.select_by(:index, 1)
  1681. #dropdown.select_by(:text, action[:group])
  1682. if data[:signature]
  1683. element = instance.find_elements({ css: '.modal select[name="signature_id"]' })[0]
  1684. dropdown = Selenium::WebDriver::Support::Select.new(element)
  1685. dropdown.select_by(:text, data[:signature])
  1686. end
  1687. instance.find_elements({ css: '.modal button.js-submit' })[0].click
  1688. (1..12).each {
  1689. element = instance.find_elements({ css: 'body' })[0]
  1690. text = element.text
  1691. if text =~ /#{Regexp.quote(data[:name])}/
  1692. assert(true, 'group created')
  1693. # add member
  1694. if data[:member]
  1695. data[:member].each {|login|
  1696. instance.find_elements({ css: 'a[href="#manage"]' })[0].click
  1697. sleep 0.5
  1698. instance.find_elements({ css: 'a[href="#manage/users"]' })[0].click
  1699. sleep 3
  1700. element = instance.find_elements({ css: '#content [name="search"]' })[0]
  1701. element.clear
  1702. element.send_keys(login)
  1703. sleep 3
  1704. #instance.find_elements({ :css => '#content table [data-id]' })[0].click
  1705. instance.execute_script('$("#content table [data-id] td").first().click()')
  1706. sleep 3
  1707. #instance.find_elements({ :css => 'label:contains(" ' + action[:name] + '")' })[0].click
  1708. instance.execute_script('$(\'label:contains(" ' + data[:name] + '")\').first().click()')
  1709. instance.find_elements({ css: '.modal button.js-submit' })[0].click
  1710. }
  1711. end
  1712. end
  1713. sleep 1
  1714. return true
  1715. }
  1716. screenshot(browser: instance, comment: 'group_create_failed')
  1717. fail 'group creation failed'
  1718. end
  1719. def quote(string)
  1720. string_quoted = string
  1721. string_quoted.gsub!(/&/, '&amp;')
  1722. string_quoted.gsub!(/</, '&lt;')
  1723. string_quoted.gsub!(/>/, '&gt;')
  1724. string_quoted
  1725. end
  1726. def switch_window_focus(params)
  1727. instance = params[:browser] || @browser
  1728. if instance != @last_used_browser
  1729. log('switch browser window focus', {})
  1730. instance.switch_to.window(instance.window_handles.first)
  1731. end
  1732. @last_used_browser = instance
  1733. end
  1734. def log(method, params)
  1735. return if !@@debug
  1736. return if params[:mute_log]
  1737. puts "#{Time.zone.now}/#{method}: #{params.inspect}"
  1738. end
  1739. end