browser_test_helper.rb 98 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766
  1. ENV['RAILS_ENV'] = 'test'
  2. # rubocop:disable HandleExceptions, ClassVars, NonLocalExitFromIterator, Style/GuardClause
  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. # currently console log not working for firefox
  18. # https://github.com/SeleniumHQ/selenium/issues/1161
  19. #browser_profile['loggingPref'] = { browser: :all }
  20. elsif browser == 'chrome'
  21. # profile are only working on remote selenium
  22. if ENV['REMOTE_URL']
  23. browser_profile = Selenium::WebDriver::Chrome::Profile.new
  24. browser_profile['intl.accept_languages'] = 'en'
  25. browser_profile['loggingPref'] = { browser: :all }
  26. end
  27. end
  28. browser_profile
  29. end
  30. def browser_support_cookies
  31. if browser.match?(/(internet_explorer|ie)/i)
  32. return false
  33. end
  34. true
  35. end
  36. def browser_url
  37. ENV['BROWSER_URL'] || 'http://localhost:3000'
  38. end
  39. def browser_instance
  40. if !@browsers
  41. @browsers = {}
  42. end
  43. if ENV['REMOTE_URL'].blank?
  44. local_browser = Selenium::WebDriver.for(browser.to_sym, profile: profile)
  45. @browsers[local_browser.hash] = local_browser
  46. browser_instance_preferences(local_browser)
  47. return local_browser
  48. end
  49. # avoid "Cannot read property 'get_Current' of undefined" issues
  50. (1..5).each do |count|
  51. begin
  52. local_browser = browser_instance_remote
  53. break
  54. rescue
  55. wait_until_ready = rand(9) + 5
  56. sleep wait_until_ready
  57. log('browser_instance', { rescure: true, count: count, sleep: wait_until_ready })
  58. end
  59. end
  60. local_browser
  61. end
  62. def browser_instance_remote
  63. caps = Selenium::WebDriver::Remote::Capabilities.send(browser)
  64. if ENV['BROWSER_OS']
  65. caps.platform = ENV['BROWSER_OS']
  66. end
  67. if ENV['BROWSER_VERSION']
  68. caps.version = ENV['BROWSER_VERSION']
  69. end
  70. local_browser = Selenium::WebDriver.for(
  71. :remote,
  72. url: ENV['REMOTE_URL'],
  73. desired_capabilities: caps,
  74. )
  75. @browsers[local_browser.hash] = local_browser
  76. browser_instance_preferences(local_browser)
  77. # upload files from remote dir
  78. local_browser.file_detector = lambda do |args|
  79. str = args.first.to_s
  80. str if File.file?(str)
  81. end
  82. local_browser
  83. end
  84. def browser_instance_close(local_browser)
  85. return if !@browsers[local_browser.hash]
  86. @browsers.delete(local_browser.hash)
  87. local_browser.quit
  88. end
  89. def browser_instance_preferences(local_browser)
  90. browser_width = ENV['BROWSER_WIDTH'] || 1024
  91. browser_height = ENV['BROWSER_HEIGHT'] || 800
  92. local_browser.manage.window.resize_to(browser_width, browser_height)
  93. if ENV['REMOTE_URL'] !~ /saucelabs|(grid|ci)\.(zammad\.org|znuny\.com)/i
  94. if @browsers.count == 1
  95. local_browser.manage.window.move_to(0, 0)
  96. else
  97. local_browser.manage.window.move_to(browser_width, 0)
  98. end
  99. end
  100. local_browser.manage.timeouts.implicit_wait = 3 # seconds
  101. end
  102. def teardown
  103. return if !@browsers
  104. @browsers.each_value do |local_browser|
  105. screenshot(browser: local_browser, comment: 'teardown')
  106. browser_instance_close(local_browser)
  107. end
  108. end
  109. def screenshot(params)
  110. instance = params[:browser] || @browser
  111. comment = params[:comment] || ''
  112. filename = "tmp/#{Time.zone.now.strftime('screenshot_%Y_%m_%d__%H_%M_%S_%L')}_#{comment}#{instance.hash}.png"
  113. log('screenshot', { filename: filename })
  114. instance.save_screenshot(filename)
  115. end
  116. =begin
  117. username = login(
  118. browser: browser1,
  119. username: 'someuser',
  120. password: 'somepassword',
  121. url: 'some url', # optional
  122. remember_me: true, # optional
  123. auto_wizard: false, # optional, in case of auto wizard, skip login
  124. success: false, #optional
  125. )
  126. =end
  127. def login(params)
  128. switch_window_focus(params)
  129. log('login', params)
  130. instance = params[:browser] || @browser
  131. if params[:url]
  132. instance.get(params[:url])
  133. end
  134. # submit logs anyway
  135. instance.execute_script('App.Track.force()')
  136. element = instance.find_elements(css: '#login input[name="username"]')[0]
  137. if !element
  138. if params[:auto_wizard]
  139. watch_for(
  140. browser: instance,
  141. css: 'body',
  142. value: 'auto wizard is enabled',
  143. timeout: 10,
  144. )
  145. location(url: "#{browser_url}/#getting_started/auto_wizard")
  146. sleep 10
  147. login = instance.find_elements(css: '.user-menu .user a')[0].attribute('title')
  148. if login != params[:username]
  149. screenshot(browser: instance, comment: 'auto wizard login failed')
  150. raise 'auto wizard login failed'
  151. end
  152. assert(true, 'auto wizard login ok')
  153. clues_close(
  154. browser: instance,
  155. optional: true,
  156. )
  157. return
  158. end
  159. screenshot(browser: instance, comment: 'login_failed')
  160. raise 'No login box found'
  161. end
  162. screenshot(browser: instance, comment: 'login')
  163. element.clear
  164. element.send_keys(params[:username])
  165. element = instance.find_elements(css: '#login input[name="password"]')[0]
  166. element.clear
  167. element.send_keys(params[:password])
  168. if params[:remember_me]
  169. instance.find_elements(css: '#login .checkbox-replacement')[0].click
  170. end
  171. instance.find_elements(css: '#login button')[0].click
  172. sleep 4
  173. login_failed = false
  174. if !instance.find_elements(css: '.user-menu .user a')[0]
  175. login_failed = true
  176. else
  177. login = instance.find_elements(css: '.user-menu .user a')[0].attribute('title')
  178. if login != params[:username]
  179. login_failed = true
  180. end
  181. end
  182. if login_failed
  183. if params[:success] == false
  184. assert(true, 'login not successfull, like wanted')
  185. return true
  186. end
  187. screenshot(browser: instance, comment: 'login_failed')
  188. raise 'login failed'
  189. end
  190. if params[:success] == false
  191. raise 'login successfull but should not'
  192. end
  193. clues_close(
  194. browser: instance,
  195. optional: true,
  196. )
  197. screenshot(browser: instance, comment: 'login_ok')
  198. assert(true, 'login ok')
  199. login
  200. end
  201. =begin
  202. logout(
  203. browser: browser1
  204. )
  205. =end
  206. def logout(params = {})
  207. switch_window_focus(params)
  208. log('logout', params)
  209. instance = params[:browser] || @browser
  210. click(
  211. browser: instance,
  212. css: 'a[href="#current_user"]',
  213. mute_log: true,
  214. )
  215. click(
  216. browser: instance,
  217. css: 'a[href="#logout"]',
  218. mute_log: true,
  219. )
  220. 5.times do
  221. sleep 1
  222. login = instance.find_elements(css: '#login')[0]
  223. next if !login
  224. screenshot(browser: instance, comment: 'logout_ok')
  225. assert(true, 'logout ok')
  226. return
  227. end
  228. screenshot(browser: instance, comment: 'logout_failed')
  229. raise 'no login box found, seems logout was not successfully!'
  230. end
  231. =begin
  232. clues_close(
  233. browser: browser1,
  234. optional: false,
  235. )
  236. =end
  237. def clues_close(params = {})
  238. switch_window_focus(params)
  239. log('clues_close', params)
  240. instance = params[:browser] || @browser
  241. clues = instance.find_elements(css: '.js-modal--clue .js-close')[0]
  242. if !params[:optional] && !clues
  243. screenshot(browser: instance, comment: 'no_clues')
  244. raise 'Unable to closes clues, no clues found!'
  245. end
  246. return if !clues
  247. instance.execute_script("$('.js-modal--clue .js-close').click()")
  248. assert(true, 'clues closed')
  249. sleep 1
  250. end
  251. =begin
  252. notify_close(
  253. browser: browser1,
  254. optional: false,
  255. )
  256. =end
  257. def notify_close(params = {})
  258. switch_window_focus(params)
  259. log('notify_close', params)
  260. instance = params[:browser] || @browser
  261. notify = instance.find_elements(css: '.noty_inline_layout_container.i-am-new')[0]
  262. if !params[:optional] && !notify
  263. screenshot(browser: instance, comment: 'no_notify')
  264. raise 'Unable to closes notify, no notify found!'
  265. end
  266. return if !notify
  267. notify.click
  268. assert(true, 'notify closed')
  269. sleep 1
  270. end
  271. =begin
  272. location(
  273. browser: browser1,
  274. url: 'http://someurl',
  275. )
  276. =end
  277. def location(params)
  278. switch_window_focus(params)
  279. log('location', params)
  280. instance = params[:browser] || @browser
  281. instance.get(params[:url])
  282. # check if reload was successfull
  283. if !instance.find_elements(css: 'body')[0] || instance.find_elements(css: 'body')[0].text =~ /unavailable or too busy/i
  284. instance.navigate.refresh
  285. end
  286. screenshot(browser: instance, comment: 'location')
  287. end
  288. =begin
  289. location_check(
  290. browser: browser1,
  291. url: 'http://someurl',
  292. )
  293. =end
  294. def location_check(params)
  295. switch_window_focus(params)
  296. log('location_check', params)
  297. instance = params[:browser] || @browser
  298. sleep 0.7
  299. current_url = instance.current_url
  300. if current_url !~ /#{Regexp.quote(params[:url])}/
  301. screenshot(browser: instance, comment: 'location_check_failed')
  302. raise "url #{current_url} is not matching #{params[:url]}"
  303. end
  304. assert(true, "url #{current_url} is matching #{params[:url]}")
  305. end
  306. =begin
  307. reload(
  308. browser: browser1,
  309. )
  310. =end
  311. def reload(params = {})
  312. switch_window_focus(params)
  313. log('reload', params)
  314. instance = params[:browser] || @browser
  315. screenshot(browser: instance, comment: 'reload_before')
  316. instance.navigate.refresh
  317. # check if reload was successfull
  318. if !instance.find_elements(css: 'body')[0] || instance.find_elements(css: 'body')[0].text =~ /unavailable or too busy/i
  319. instance.navigate.refresh
  320. end
  321. screenshot(browser: instance, comment: 'reload_after')
  322. end
  323. =begin
  324. click(
  325. browser: browser1,
  326. css: '.some_class',
  327. fast: false, # do not wait
  328. wait: 1, # wait 1 sec.
  329. )
  330. click(
  331. browser: browser1,
  332. text: '.partial_link_text',
  333. fast: false, # do not wait
  334. wait: 1, # wait 1 sec.
  335. )
  336. =end
  337. def click(params)
  338. switch_window_focus(params)
  339. log('click', params)
  340. instance = params[:browser] || @browser
  341. screenshot(browser: instance, comment: 'click_before')
  342. if params[:css]
  343. begin
  344. element = instance.find_elements(css: params[:css])[0]
  345. return if !element && params[:only_if_exists] == true
  346. #if element
  347. # instance.action.move_to(element).release.perform
  348. #end
  349. element.click
  350. rescue => e
  351. sleep 0.5
  352. # just try again
  353. log('click', { rescure: true })
  354. element = instance.find_elements(css: params[:css])[0]
  355. return if !element && params[:only_if_exists] == true
  356. #if element
  357. # instance.action.move_to(element).release.perform
  358. #end
  359. raise "No such element '#{params[:css]}'" if !element
  360. element.click
  361. end
  362. else
  363. sleep 0.5
  364. begin
  365. instance.find_elements(partial_link_text: params[:text])[0].click
  366. rescue => e
  367. sleep 0.5
  368. # just try again
  369. log('click', { rescure: true })
  370. element = instance.find_elements(partial_link_text: params[:text])[0]
  371. raise "No such element '#{params[:text]}'" if !element
  372. element.click
  373. end
  374. end
  375. sleep 0.2 if !params[:fast]
  376. sleep params[:wait] if params[:wait]
  377. end
  378. =begin
  379. scroll_to(
  380. browser: browser1,
  381. position: 'top', # botton
  382. css: '.some_class',
  383. )
  384. =end
  385. def scroll_to(params)
  386. switch_window_focus(params)
  387. log('scroll_to', params)
  388. instance = params[:browser] || @browser
  389. position = 'true'
  390. if params[:position] == 'botton'
  391. position = 'false'
  392. end
  393. screenshot(browser: instance, comment: 'scroll_to_before')
  394. execute(
  395. browser: instance,
  396. js: "\$('#{params[:css]}').get(0).scrollIntoView(#{position})",
  397. mute_log: params[:mute_log]
  398. )
  399. sleep 0.3
  400. screenshot(browser: instance, comment: 'scroll_to_after')
  401. end
  402. =begin
  403. modal_ready(
  404. browser: browser1,
  405. )
  406. =end
  407. def modal_ready(params = {})
  408. switch_window_focus(params)
  409. log('modal_ready', params)
  410. instance = params[:browser] || @browser
  411. screenshot(browser: instance, comment: 'modal_ready_before')
  412. sleep 3
  413. screenshot(browser: instance, comment: 'modal_ready_after')
  414. end
  415. =begin
  416. modal_disappear(
  417. browser: browser1,
  418. timeout: 12, # default 8
  419. )
  420. =end
  421. def modal_disappear(params = {})
  422. switch_window_focus(params)
  423. log('modal_disappear', params)
  424. instance = params[:browser] || @browser
  425. screenshot(browser: instance, comment: 'modal_disappear_before')
  426. watch_for_disappear(
  427. browser: instance,
  428. css: '.modal',
  429. timeout: params[:timeout] || 8,
  430. )
  431. screenshot(browser: instance, comment: 'modal_disappear_after')
  432. end
  433. =begin
  434. execute(
  435. browser: browser1,
  436. js: '.some_class',
  437. )
  438. =end
  439. def execute(params)
  440. switch_window_focus(params)
  441. log('js', params)
  442. instance = params[:browser] || @browser
  443. if params[:js]
  444. return instance.execute_script(params[:js])
  445. end
  446. raise "Invalid execute params #{params.inspect}"
  447. end
  448. =begin
  449. exists(
  450. browser: browser1,
  451. css: '.some_class',
  452. )
  453. exists(
  454. displayed: false, # true|false
  455. browser: browser1,
  456. css: '.some_class',
  457. )
  458. =end
  459. def exists(params)
  460. switch_window_focus(params)
  461. log('exists', params)
  462. instance = params[:browser] || @browser
  463. if !instance.find_elements(css: params[:css])[0]
  464. screenshot(browser: instance, comment: 'exists_failed')
  465. raise "#{params[:css]} dosn't exist, but should"
  466. end
  467. if params.key?(:displayed)
  468. if params[:displayed] == true && !instance.find_elements(css: params[:css])[0].displayed?
  469. raise "#{params[:css]} is not displayed, but should"
  470. end
  471. if params[:displayed] == false && instance.find_elements(css: params[:css])[0].displayed?
  472. raise "#{params[:css]} is displayed, but should not"
  473. end
  474. end
  475. true
  476. end
  477. =begin
  478. exists_not(
  479. browser: browser1,
  480. css: '.some_class',
  481. )
  482. =end
  483. def exists_not(params)
  484. switch_window_focus(params)
  485. log('exists_not', params)
  486. instance = params[:browser] || @browser
  487. if instance.find_elements(css: params[:css])[0]
  488. screenshot(browser: instance, comment: 'exists_not_failed')
  489. raise "#{params[:css]} exists but should not"
  490. end
  491. true
  492. end
  493. =begin
  494. set(
  495. browser: browser1,
  496. css: '.some_class',
  497. value: true,
  498. slow: false,
  499. blur: true, # default false
  500. clear: true, # todo | default: true
  501. no_click: true,
  502. )
  503. =end
  504. def set(params)
  505. switch_window_focus(params)
  506. log('set', params)
  507. instance = params[:browser] || @browser
  508. screenshot(browser: instance, comment: 'set_before')
  509. element = instance.find_elements(css: params[:css])[0]
  510. if !params[:no_click]
  511. element.click
  512. end
  513. element.clear
  514. begin
  515. if !params[:slow]
  516. element.send_keys(params[:value])
  517. else
  518. element.send_keys('')
  519. keys = params[:value].to_s.split('')
  520. keys.each do |key|
  521. instance.action.send_keys(key).perform
  522. end
  523. end
  524. rescue => e
  525. sleep 0.5
  526. # just try again
  527. log('set', { rescure: true })
  528. element = instance.find_elements(css: params[:css])[0]
  529. raise "No such element '#{params[:css]}'" if !element
  530. if !params[:slow]
  531. element.send_keys(params[:value])
  532. else
  533. element.send_keys('')
  534. keys = params[:value].to_s.split('')
  535. keys.each do |key|
  536. instance.action.send_keys(key).perform
  537. end
  538. end
  539. end
  540. # it's not working stable with ff via selenium, use js
  541. if browser =~ /firefox/i && params[:css] =~ /\[data-name=/
  542. log('set_ff_trigger_workaround', params)
  543. instance.execute_script("$('#{params[:css]}').trigger('focusout')")
  544. end
  545. if params[:blur]
  546. instance.execute_script("$('#{params[:css]}').blur()")
  547. end
  548. sleep 0.2
  549. screenshot(browser: instance, comment: 'set_after')
  550. end
  551. =begin
  552. select(
  553. browser: browser1,
  554. css: '.some_class',
  555. value: 'Some Value',
  556. deselect_all: false, # default false
  557. )
  558. =end
  559. def select(params)
  560. switch_window_focus(params)
  561. log('select', params)
  562. instance = params[:browser] || @browser
  563. screenshot(browser: instance, comment: 'select_before')
  564. # searchable select
  565. element = instance.find_elements(css: "#{params[:css]}.js-shadow")[0]
  566. if element
  567. element = instance.find_elements(css: "#{params[:css]}.js-shadow + .js-input")[0]
  568. element.click
  569. element.clear
  570. sleep 0.4
  571. element.send_keys(params[:value])
  572. sleep 0.2
  573. element.send_keys(:enter)
  574. sleep 0.2
  575. return
  576. end
  577. # native select
  578. begin
  579. element = instance.find_elements(css: params[:css])[0]
  580. dropdown = Selenium::WebDriver::Support::Select.new(element)
  581. if params[:deselect_all]
  582. dropdown.deselect_all
  583. end
  584. dropdown.select_by(:text, params[:value])
  585. #puts "select - #{params.inspect}"
  586. rescue
  587. sleep 0.4
  588. # just try again
  589. log('select', { rescure: true })
  590. element = instance.find_elements(css: params[:css])[0]
  591. dropdown = Selenium::WebDriver::Support::Select.new(element)
  592. if params[:deselect_all]
  593. dropdown.deselect_all
  594. end
  595. dropdown.select_by(:text, params[:value])
  596. #puts "select2 - #{params.inspect}"
  597. end
  598. sleep 0.4
  599. screenshot(browser: instance, comment: 'select_after')
  600. end
  601. =begin
  602. switch(
  603. browser: browser1,
  604. css: '.some_class',
  605. type: 'on', # 'off'
  606. no_check: true, # do not check is switch has changed, in case if js alert
  607. )
  608. =end
  609. def switch(params)
  610. switch_window_focus(params)
  611. log('switch', params)
  612. instance = params[:browser] || @browser
  613. screenshot(browser: instance, comment: 'switch_before')
  614. element = instance.find_elements(css: "#{params[:css]} input[type=checkbox]")[0]
  615. checked = element.attribute('checked')
  616. if !checked
  617. if params[:type] == 'on'
  618. instance.find_elements(css: "#{params[:css]} label")[0].click
  619. sleep 2
  620. if params[:no_check] != true
  621. element = instance.find_elements(css: "#{params[:css]} input[type=checkbox]")[0]
  622. checked = element.attribute('checked')
  623. raise 'Switch not on!' if !checked
  624. end
  625. end
  626. elsif params[:type] == 'off'
  627. instance.find_elements(css: "#{params[:css]} label")[0].click
  628. sleep 2
  629. if params[:no_check] != true
  630. element = instance.find_elements(css: "#{params[:css]} input[type=checkbox]")[0]
  631. checked = element.attribute('checked')
  632. raise 'Switch not off!' if checked
  633. end
  634. end
  635. screenshot(browser: instance, comment: 'switch_after')
  636. end
  637. =begin
  638. check(
  639. browser: browser1,
  640. css: '.some_class',
  641. )
  642. =end
  643. def check(params)
  644. switch_window_focus(params)
  645. log('check', params)
  646. instance = params[:browser] || @browser
  647. screenshot(browser: instance, comment: 'check_before')
  648. instance.execute_script("if (!$('#{params[:css]}').prop('checked')) { $('#{params[:css]}').click() }")
  649. #element = instance.find_elements(css: params[:css])[0]
  650. #checked = element.attribute('checked')
  651. #element.click if !checked
  652. screenshot(browser: instance, comment: 'check_after')
  653. end
  654. =begin
  655. uncheck(
  656. browser: browser1,
  657. css: '.some_class',
  658. )
  659. =end
  660. def uncheck(params)
  661. switch_window_focus(params)
  662. log('uncheck', params)
  663. instance = params[:browser] || @browser
  664. screenshot(browser: instance, comment: 'uncheck_before')
  665. instance.execute_script("if ($('#{params[:css]}').prop('checked')) { $('#{params[:css]}').click() }")
  666. #element = instance.find_elements(css: params[:css])[0]
  667. #checked = element.attribute('checked')
  668. #element.click if checked
  669. screenshot(browser: instance, comment: 'uncheck_after')
  670. end
  671. =begin
  672. sendkey(
  673. browser: browser1,
  674. value: :enter,
  675. slow: false, # default false
  676. )
  677. =end
  678. def sendkey(params)
  679. switch_window_focus(params)
  680. log('sendkey', params)
  681. instance = params[:browser] || @browser
  682. element = nil
  683. if params[:css]
  684. element = instance.find_elements(css: params[:css])[0]
  685. end
  686. screenshot(browser: instance, comment: 'sendkey_before')
  687. if params[:value].class == Array
  688. params[:value].each do |key|
  689. if element
  690. element.send_keys(key)
  691. else
  692. instance.action.send_keys(key).perform
  693. end
  694. end
  695. screenshot(browser: instance, comment: 'sendkey_after')
  696. return
  697. end
  698. if element
  699. element.send_keys(params[:value])
  700. else
  701. instance.action.send_keys(params[:value]).perform
  702. end
  703. if params[:slow]
  704. sleep 1.5
  705. else
  706. sleep 0.2
  707. end
  708. screenshot(browser: instance, comment: 'sendkey_after')
  709. end
  710. =begin
  711. match(
  712. browser: browser1,
  713. css: '#content .text-1',
  714. value: 'some test for browser and some other for browser',
  715. attribute: 'some_attribute', # match on attribute
  716. should_not_match: true,
  717. no_quote: false, # use regex
  718. )
  719. =end
  720. def match(params, fallback = false)
  721. switch_window_focus(params)
  722. log('match', params)
  723. instance = params[:browser] || @browser
  724. element = instance.find_elements(css: params[:css])[0]
  725. if params[:css].match?(/select/)
  726. dropdown = Selenium::WebDriver::Support::Select.new(element)
  727. success = false
  728. dropdown.selected_options&.each do |option|
  729. if option.text == params[:value]
  730. success = true
  731. end
  732. end
  733. if params[:should_not_match]
  734. if success
  735. screenshot(browser: instance, comment: 'match_failed')
  736. raise "should not match '#{params[:value]}' in select list, but is matching"
  737. end
  738. elsif !success
  739. screenshot(browser: instance, comment: 'match_failed')
  740. raise "not matching '#{params[:value]}' in select list"
  741. end
  742. return true
  743. end
  744. # match on attribute
  745. begin
  746. text = if params[:attribute]
  747. element.attribute(params[:attribute])
  748. elsif params[:css].match?(/(input|textarea)/i)
  749. element.attribute('value')
  750. else
  751. element.text
  752. end
  753. rescue => e
  754. # just try again
  755. if !fallback
  756. return match(params, true)
  757. end
  758. raise e.inspect
  759. end
  760. # do cleanups (needed for richtext tests)
  761. if params[:cleanup]
  762. text.gsub!(/\s+$/m, '')
  763. params[:value].gsub!(/\s+$/m, '')
  764. end
  765. match = false
  766. if params[:no_quote]
  767. #puts "aaaa #{text}/#{params[:value]}"
  768. if text =~ /#{params[:value]}/i
  769. match = $1 || true
  770. end
  771. elsif text.match?(/#{Regexp.quote(params[:value])}/i)
  772. match = true
  773. end
  774. if match
  775. if params[:should_not_match]
  776. screenshot(browser: instance, comment: 'match_failed')
  777. raise "matching '#{params[:value]}' in content '#{text}' but should not!"
  778. end
  779. elsif !params[:should_not_match]
  780. screenshot(browser: instance, comment: 'match_failed')
  781. raise "not matching '#{params[:value]}' in content '#{text}' but should!"
  782. end
  783. sleep 0.2
  784. match
  785. end
  786. =begin
  787. match_not(
  788. browser: browser1,
  789. css: '#content .text-1',
  790. value: 'some test for browser and some other for browser',
  791. attribute: 'some_attribute', # match on attribute
  792. should_not_match: true,
  793. no_quote: false, # use regex
  794. )
  795. =end
  796. def match_not(params)
  797. switch_window_focus(params)
  798. log('match_not', params)
  799. params[:should_not_match] = true
  800. match(params)
  801. end
  802. =begin
  803. set type of task (closeTab, closeNextInOverview, stayOnTab)
  804. task_type(
  805. browser: browser1,
  806. type: 'stayOnTab',
  807. )
  808. =end
  809. def task_type(params)
  810. switch_window_focus(params)
  811. log('task_type', params)
  812. instance = params[:browser] || @browser
  813. if params[:type]
  814. instance.find_elements(css: '.content.active .js-secondaryActionButtonLabel')[0].click
  815. instance.find_elements(css: ".content.active .js-secondaryActionLabel[data-type=#{params[:type]}]")[0].click
  816. return
  817. end
  818. raise "Unknown params for task_type: #{params.inspect}"
  819. end
  820. =begin
  821. cookie(
  822. browser: browser1,
  823. name: '^_zammad.+?',
  824. value: '.+?',
  825. expires: nil,
  826. )
  827. cookie(
  828. browser: browser1,
  829. name: '^_zammad.+?',
  830. should_not_exist: true,
  831. )
  832. =end
  833. def cookie(params)
  834. switch_window_focus(params)
  835. log('cookie', params)
  836. instance = params[:browser] || @browser
  837. if !browser_support_cookies
  838. assert(true, "'#{params[:value]}' ups browser is not supporting reading cookies, go ahead")
  839. return true
  840. end
  841. cookies = instance.manage.all_cookies
  842. cookies.each do |cookie|
  843. # :name=>"_zammad_session_c25832f4de2", :value=>"adc31cd21615cb0a7ab269184ec8b76f", :path=>"/", :domain=>"localhost", :expires=>nil, :secure=>false}
  844. next if cookie[:name] !~ /#{params[:name]}/i
  845. if params.key?(:value) && cookie[:value].to_s =~ /#{params[:value]}/i
  846. assert(true, "matching value '#{params[:value]}' in cookie '#{cookie}'")
  847. else
  848. raise "not matching value '#{params[:value]}' in cookie '#{cookie}'"
  849. end
  850. if params.key?(:expires) && cookie[:expires].to_s =~ /#{params[:expires]}/i
  851. assert(true, "matching expires '#{params[:expires].inspect}' in cookie '#{cookie}'")
  852. else
  853. raise "not matching expires '#{params[:expires]}' in cookie '#{cookie}'"
  854. end
  855. return if !params[:should_not_exist]
  856. raise "cookie with name '#{params[:name]}' should not exist, but exists '#{cookies}'"
  857. end
  858. if params[:should_not_exist]
  859. assert(true, "cookie with name '#{params[:name]}' is not existing")
  860. return
  861. end
  862. raise "not matching name '#{params[:name]}' in cookie '#{cookies}'"
  863. end
  864. =begin
  865. verify_title(
  866. browser: browser1,
  867. value: 'some title',
  868. )
  869. =end
  870. def verify_title(params = {})
  871. switch_window_focus(params)
  872. log('verify_title', params)
  873. instance = params[:browser] || @browser
  874. title = instance.title
  875. if title.match?(/#{params[:value]}/i)
  876. assert(true, "matching '#{params[:value]}' in title '#{title}'")
  877. else
  878. raise "not matching '#{params[:value]}' in title '#{title}'"
  879. end
  880. end
  881. =begin
  882. verify_task(
  883. browser: browser1,
  884. data: {
  885. title: 'some title',
  886. modified: true, # optional
  887. }
  888. )
  889. =end
  890. def verify_task(params = {}, fallback = false)
  891. switch_window_focus(params)
  892. log('verify_task', params)
  893. instance = params[:browser] || @browser
  894. data = params[:data]
  895. sleep 1
  896. begin
  897. # verify title
  898. if data[:title]
  899. title = instance.find_elements(css: '.tasks .is-active')[0].text.strip
  900. if title.match?(/#{data[:title]}/i)
  901. assert(true, "matching '#{data[:title]}' in title '#{title}'")
  902. else
  903. screenshot(browser: instance, comment: 'verify_task_failed')
  904. raise "not matching '#{data[:title]}' in title '#{title}'"
  905. end
  906. end
  907. # verify modified
  908. if data.key?(:modified)
  909. exists = instance.find_elements(css: '.tasks .is-active')[0]
  910. is_modified = instance.find_elements(css: '.tasks .is-modified')[0]
  911. puts "m #{data[:modified].inspect}"
  912. if exists
  913. puts ' exists'
  914. end
  915. if is_modified
  916. puts ' is_modified'
  917. end
  918. if data[:modified] == true
  919. if is_modified
  920. assert(true, "task '#{data[:title]}' is modifed")
  921. elsif !exists
  922. screenshot(browser: instance, comment: 'verify_task_failed')
  923. raise "task '#{data[:title]}' not exists, should not modified"
  924. else
  925. screenshot(browser: instance, comment: 'verify_task_failed')
  926. raise "task '#{data[:title]}' is not modifed"
  927. end
  928. elsif !is_modified
  929. assert(true, "task '#{data[:title]}' is modifed")
  930. elsif !exists
  931. screenshot(browser: instance, comment: 'verify_task_failed')
  932. raise "task '#{data[:title]}' not exists, should be not modified"
  933. else
  934. screenshot(browser: instance, comment: 'verify_task_failed')
  935. raise "task '#{data[:title]}' is modifed, but should not"
  936. end
  937. end
  938. rescue => e
  939. # just try again
  940. if !fallback
  941. verify_task(params, true)
  942. end
  943. raise 'ERROR: ' + e.inspect
  944. end
  945. true
  946. end
  947. =begin
  948. open_task(
  949. browser: browser1,
  950. data: {
  951. title: 'some title',
  952. }
  953. )
  954. =end
  955. def open_task(params = {})
  956. switch_window_focus(params)
  957. log('open_task', params)
  958. instance = params[:browser] || @browser
  959. data = params[:data]
  960. element = instance.find_element(css: '#navigation').find_element(partial_link_text: data[:title])
  961. if !element
  962. screenshot(browser: instance, comment: 'open_task_failed')
  963. raise "no task with title '#{data[:title]}' found"
  964. end
  965. # firefix/marionette issue with Selenium::WebDriver::Error::ElementNotInteractableError: could not be scrolled into view
  966. # use js workaround instead of native click
  967. instance.execute_script("$('#navigation .tasks .task:contains(\"#{data[:title]}\") .nav-tab-name').click()")
  968. #element.click
  969. true
  970. end
  971. =begin
  972. close_task(
  973. browser: browser1,
  974. data: {
  975. title: 'some title',
  976. },
  977. discard_changes: true,
  978. )
  979. =end
  980. def close_task(params = {})
  981. switch_window_focus(params)
  982. log('close_task', params)
  983. instance = params[:browser] || @browser
  984. data = params[:data]
  985. element = instance.find_element(css: '#navigation').find_element(partial_link_text: data[:title])
  986. if !element
  987. screenshot(browser: instance, comment: 'close_task_failed')
  988. raise "no task with title '#{data[:title]}' found"
  989. end
  990. instance.action.move_to(element).release.perform
  991. sleep 0.1
  992. instance.execute_script("$('#navigation .tasks .task:contains(\"#{data[:title]}\") .js-close').click()")
  993. # accept task close warning
  994. if params[:discard_changes]
  995. modal_ready(browser: instance)
  996. instance.find_elements(css: '.modal button.js-submit')[0].click
  997. modal_disappear(browser: instance)
  998. end
  999. true
  1000. end
  1001. =begin
  1002. file_upload(
  1003. browser: browser1,
  1004. css: '.content.active .attachmentPlaceholder-inputHolder input'
  1005. files: ['path/in/home/some_file.ext'], # 'test/fixtures/test1.pdf'
  1006. )
  1007. =end
  1008. def file_upload(params = {})
  1009. switch_window_focus(params)
  1010. log('file_upload', params)
  1011. instance = params[:browser] || @browser
  1012. params[:files].each do |file|
  1013. instance.find_elements(css: params[:css])[0].send_keys(Rails.root.join(file))
  1014. end
  1015. sleep 2 * params[:files].count
  1016. end
  1017. =begin
  1018. watch_for(
  1019. browser: browser1,
  1020. css: '#content .text-1',
  1021. value: 'some text',
  1022. attribute: 'some_attribute' # optional
  1023. timeout: 16, # in sec, default 16
  1024. )
  1025. =end
  1026. def watch_for(params = {})
  1027. switch_window_focus(params)
  1028. log('watch_for', params)
  1029. instance = params[:browser] || @browser
  1030. timeout = 16
  1031. if params[:timeout]
  1032. timeout = params[:timeout]
  1033. end
  1034. loops = timeout.to_i * 2
  1035. text = ''
  1036. (1..loops).each do
  1037. element = instance.find_elements(css: params[:css])[0]
  1038. if element #&& element.displayed?
  1039. begin
  1040. # watch for selector
  1041. if !params[:attribute] && !params[:value]
  1042. assert(true, "'#{params[:css]}' found")
  1043. sleep 0.5
  1044. return true
  1045. # match an attribute
  1046. else
  1047. text = if params[:attribute]
  1048. element.attribute(params[:attribute])
  1049. elsif params[:css].match?(/(input|textarea)/i)
  1050. element.attribute('value')
  1051. else
  1052. element.text
  1053. end
  1054. if text.match?(/#{params[:value]}/i)
  1055. assert(true, "'#{params[:value]}' found in '#{text}'")
  1056. sleep 0.5
  1057. return true
  1058. end
  1059. end
  1060. rescue
  1061. # try again
  1062. end
  1063. end
  1064. sleep 0.5
  1065. end
  1066. screenshot(browser: instance, comment: 'watch_for_failed')
  1067. if !params[:attribute] && !params[:value]
  1068. raise "'#{params[:css]}' not found"
  1069. end
  1070. raise "'#{params[:value]}' not found in '#{text}'"
  1071. end
  1072. =begin
  1073. wait untill selector disabppears
  1074. watch_for_disappear(
  1075. browser: browser1,
  1076. css: '#content .text-1',
  1077. timeout: 16, # in sec, default 16
  1078. )
  1079. wait untill text in selector disabppears
  1080. watch_for_disappear(
  1081. browser: browser1,
  1082. css: '#content .text-1',
  1083. value: 'some value as regexp',
  1084. timeout: 16, # in sec, default 16
  1085. )
  1086. =end
  1087. def watch_for_disappear(params = {})
  1088. switch_window_focus(params)
  1089. log('watch_for_disappear', params)
  1090. instance = params[:browser] || @browser
  1091. timeout = 16
  1092. if params[:timeout]
  1093. timeout = params[:timeout]
  1094. end
  1095. loops = timeout.to_i
  1096. text = ''
  1097. (1..loops).each do
  1098. element = instance.find_elements(css: params[:css])[0]
  1099. if !element #|| element.displayed?
  1100. assert(true, 'not found')
  1101. sleep 1
  1102. return true
  1103. end
  1104. if params[:value]
  1105. begin
  1106. text = instance.find_elements(css: params[:css])[0].text
  1107. if text !~ /#{params[:value]}/i
  1108. assert(true, "not matching '#{params[:value]}' in text '#{text}'")
  1109. sleep 1
  1110. return true
  1111. end
  1112. rescue
  1113. # try again
  1114. end
  1115. end
  1116. sleep 1
  1117. end
  1118. screenshot(browser: instance, comment: 'disappear_failed')
  1119. raise "#{params[:css]}) still exsists"
  1120. end
  1121. =begin
  1122. shortcut(
  1123. browser: browser1,
  1124. key: 'x',
  1125. )
  1126. =end
  1127. def shortcut(params = {})
  1128. switch_window_focus(params)
  1129. log('shortcut', params)
  1130. instance = params[:browser] || @browser
  1131. screenshot(browser: instance, comment: 'shortcut_before')
  1132. instance.action.key_down(:control)
  1133. .key_down(:shift)
  1134. .send_keys(params[:key])
  1135. .key_up(:shift)
  1136. .key_up(:control)
  1137. .perform
  1138. screenshot(browser: instance, comment: 'shortcut_after')
  1139. end
  1140. =begin
  1141. window_keys(
  1142. browser: browser1,
  1143. value: 'x',
  1144. )
  1145. =end
  1146. def window_keys(params = {})
  1147. switch_window_focus(params)
  1148. log('window_keys', params)
  1149. instance = params[:browser] || @browser
  1150. instance.action.send_keys(params[:value]).perform
  1151. end
  1152. =begin
  1153. tasks_close_all(
  1154. browser: browser1,
  1155. )
  1156. =end
  1157. def tasks_close_all(params = {})
  1158. switch_window_focus(params)
  1159. log('tasks_close_all', params)
  1160. instance = params[:browser] || @browser
  1161. 99.times do
  1162. #sleep 0.5
  1163. begin
  1164. if instance.find_elements(css: '#navigation .tasks .task:first-child')[0]
  1165. instance.action.move_to(instance.find_elements(css: '#navigation .tasks .task:first-child')[0]).release.perform
  1166. click_element = instance.find_elements(css: '#navigation .tasks .task:first-child .js-close')[0]
  1167. if click_element
  1168. click_element.click
  1169. # accept task close warning
  1170. if instance.find_elements(css: '.modal button.js-submit')[0]
  1171. sleep 0.4
  1172. instance.find_elements(css: '.modal button.js-submit')[0].click
  1173. end
  1174. end
  1175. else
  1176. break
  1177. end
  1178. rescue
  1179. # try again
  1180. end
  1181. end
  1182. assert(true, 'all tasks closed')
  1183. end
  1184. =begin
  1185. close_online_notitifcation(
  1186. browser: browser1,
  1187. data: {
  1188. #title: 'some title',
  1189. position: 3,
  1190. },
  1191. )
  1192. =end
  1193. def close_online_notitifcation(params = {})
  1194. switch_window_focus(params)
  1195. log('close_online_notitifcation', params)
  1196. instance = params[:browser] || @browser
  1197. data = params[:data]
  1198. if data[:title]
  1199. element = instance.find_elements(partial_link_text: data[:title])[0]
  1200. if !element
  1201. screenshot(browser: instance, comment: 'close_online_notitifcation')
  1202. raise "no online notification with title '#{data[:title]}' found"
  1203. end
  1204. instance.action.move_to(element).release.perform
  1205. sleep 0.1
  1206. instance.execute_script("$('.js-notificationsContainer .js-items .js-item .activity-text:contains(\"#{data[:title]}\") .js-remove').first().click()")
  1207. else
  1208. css = ".js-notificationsContainer .js-items .js-item:nth-child(#{data[:position]})"
  1209. element = instance.find_elements(css: css)[0]
  1210. if !element
  1211. screenshot(browser: instance, comment: 'close_online_notitifcation')
  1212. raise "no online notification with postion '#{css}' found"
  1213. end
  1214. instance.action.move_to(element).release.perform
  1215. sleep 0.1
  1216. instance.find_elements(css: "#{css} .js-remove")[0].click
  1217. end
  1218. true
  1219. end
  1220. =begin
  1221. online_notitifcation_close_all(
  1222. browser: browser1,
  1223. )
  1224. =end
  1225. def online_notitifcation_close_all(params = {})
  1226. switch_window_focus(params)
  1227. log('online_notitifcation_close_all', params)
  1228. instance = params[:browser] || @browser
  1229. 99.times do
  1230. sleep 0.5
  1231. begin
  1232. if instance.find_elements(css: '.js-notificationsContainer .js-item:first-child')[0]
  1233. instance.action.move_to(instance.find_elements(css: '.js-notificationsContainer .js-item:first-child')[0]).perform
  1234. sleep 0.1
  1235. click_element = instance.find_elements(css: '.js-notificationsContainer .js-item:first-child .js-remove')[0]
  1236. click_element&.click
  1237. else
  1238. break
  1239. end
  1240. rescue
  1241. # try again
  1242. end
  1243. end
  1244. assert(true, 'all online notification closed')
  1245. end
  1246. =begin
  1247. empty_search(
  1248. browser: browser1,
  1249. )
  1250. =end
  1251. def empty_search(params = {})
  1252. switch_window_focus(params)
  1253. log('empty_search', params)
  1254. instance = params[:browser] || @browser
  1255. # empty search box by x
  1256. begin
  1257. instance.find_elements(css: '.search .js-emptySearch')[0].click
  1258. rescue
  1259. # in issues with ff & selenium, sometimes exeption appears
  1260. # "Element is not currently visible and so may not be interacted with"
  1261. log('empty_search via js')
  1262. instance.execute_script('$(".search .js-emptySearch").click()')
  1263. end
  1264. sleep 0.5
  1265. text = instance.find_elements(css: '#global-search')[0].attribute('value')
  1266. if !text
  1267. raise '#global-search is not empty!'
  1268. end
  1269. true
  1270. end
  1271. =begin
  1272. ticket_customer_select(
  1273. browser: browser1,
  1274. css: '#content .text-1',
  1275. customer: '',
  1276. )
  1277. =end
  1278. def ticket_customer_select(params = {})
  1279. switch_window_focus(params)
  1280. log('ticket_customer_select', params)
  1281. instance = params[:browser] || @browser
  1282. element = instance.find_elements(css: params[:css] + ' input[name="customer_id_completion"]')[0]
  1283. element.click
  1284. element.clear
  1285. element.send_keys(params[:customer])
  1286. sleep 2.5
  1287. element.send_keys(:enter)
  1288. #instance.find_elements(css: params[:css] + ' .recipientList-entry.js-object.is-active')[0].click
  1289. sleep 0.4
  1290. assert(true, 'ticket_customer_select')
  1291. end
  1292. =begin
  1293. overview_create(
  1294. browser: browser1,
  1295. data: {
  1296. name: name,
  1297. roles: ['Agent'],
  1298. selector: {
  1299. 'Priority': '1 low',
  1300. },
  1301. 'order::direction' => 'down',
  1302. }
  1303. )
  1304. =end
  1305. def overview_create(params)
  1306. switch_window_focus(params)
  1307. log('overview_create', params)
  1308. instance = params[:browser] || @browser
  1309. data = params[:data]
  1310. click(
  1311. browser: instance,
  1312. css: 'a[href="#manage"]',
  1313. mute_log: true,
  1314. )
  1315. click(
  1316. browser: instance,
  1317. css: '.content.active a[href="#manage/overviews"]',
  1318. mute_log: true,
  1319. )
  1320. click(
  1321. browser: instance,
  1322. css: '.content.active a[data-type="new"]',
  1323. mute_log: true,
  1324. )
  1325. modal_ready(browser: instance)
  1326. if data[:name]
  1327. set(
  1328. browser: instance,
  1329. css: '.modal input[name=name]',
  1330. value: data[:name],
  1331. mute_log: true,
  1332. )
  1333. end
  1334. if data[:roles]
  1335. 99.times do
  1336. begin
  1337. element = instance.find_elements(css: '.modal .js-selected[data-name=role_ids] .js-option:not(.is-hidden)')[0]
  1338. break if !element
  1339. element.click
  1340. sleep 0.1
  1341. end
  1342. end
  1343. data[:roles].each do |role|
  1344. instance.execute_script("$(\".modal [data-name=role_ids] .js-pool .js-option:not(.is-hidden):contains('#{role}')\").first().click()")
  1345. end
  1346. end
  1347. data[:selector]&.each do |key, value|
  1348. select(
  1349. browser: instance,
  1350. css: '.modal .ticket_selector .js-attributeSelector select',
  1351. value: key,
  1352. mute_log: true,
  1353. )
  1354. sleep 0.5
  1355. select(
  1356. browser: instance,
  1357. css: '.modal .ticket_selector .js-value select',
  1358. value: value,
  1359. deselect_all: true,
  1360. mute_log: true,
  1361. )
  1362. end
  1363. if data['order::direction']
  1364. select(
  1365. browser: instance,
  1366. css: '.modal select[name="order::direction"]',
  1367. value: data['order::direction'],
  1368. mute_log: true,
  1369. )
  1370. end
  1371. instance.find_elements(css: '.modal button.js-submit')[0].click
  1372. modal_disappear(browser: instance)
  1373. 11.times do
  1374. element = instance.find_elements(css: 'body')[0]
  1375. text = element.text
  1376. if text.match?(/#{Regexp.quote(data[:name])}/)
  1377. assert(true, 'overview created')
  1378. overview = {
  1379. name: name,
  1380. }
  1381. sleep 1
  1382. return overview
  1383. end
  1384. sleep 1
  1385. end
  1386. screenshot(browser: instance, comment: 'overview_create_failed')
  1387. raise 'overview creation failed'
  1388. end
  1389. =begin
  1390. overview_update(
  1391. browser: browser1,
  1392. data: {
  1393. name: name,
  1394. roles: ['Agent'],
  1395. selector: {
  1396. 'Priority': '1 low',
  1397. },
  1398. 'order::direction' => 'down',
  1399. }
  1400. )
  1401. =end
  1402. def overview_update(params)
  1403. switch_window_focus(params)
  1404. log('overview_create', params)
  1405. instance = params[:browser] || @browser
  1406. data = params[:data]
  1407. click(
  1408. browser: instance,
  1409. css: 'a[href="#manage"]',
  1410. mute_log: true,
  1411. )
  1412. click(
  1413. browser: instance,
  1414. css: '.content.active a[href="#manage/overviews"]',
  1415. mute_log: true,
  1416. )
  1417. instance.execute_script("$(\".content.active td:contains('#{data[:name]}')\").first().click()")
  1418. sleep 2
  1419. if data[:name]
  1420. set(
  1421. browser: instance,
  1422. css: '.modal input[name=name]',
  1423. value: data[:name],
  1424. mute_log: true,
  1425. )
  1426. end
  1427. if data[:roles]
  1428. 99.times do
  1429. begin
  1430. element = instance.find_elements(css: '.modal .js-selected[data-name=role_ids] .js-option:not(.is-hidden)')[0]
  1431. break if !element
  1432. element.click
  1433. sleep 0.1
  1434. end
  1435. end
  1436. data[:roles].each do |role|
  1437. instance.execute_script("$(\".modal [data-name=role_ids] .js-pool .js-option:not(.is-hidden):contains('#{role}')\").first().click()")
  1438. end
  1439. end
  1440. data[:selector]&.each do |key, value|
  1441. select(
  1442. browser: instance,
  1443. css: '.modal .ticket_selector .js-attributeSelector select',
  1444. value: key,
  1445. mute_log: true,
  1446. )
  1447. sleep 0.5
  1448. select(
  1449. browser: instance,
  1450. css: '.modal .ticket_selector .js-value select',
  1451. value: value,
  1452. deselect_all: true,
  1453. mute_log: true,
  1454. )
  1455. end
  1456. if data['order::direction']
  1457. select(
  1458. browser: instance,
  1459. css: '.modal select[name="order::direction"]',
  1460. value: data['order::direction'],
  1461. mute_log: true,
  1462. )
  1463. end
  1464. instance.find_elements(css: '.modal button.js-submit')[0].click
  1465. modal_disappear(browser: instance)
  1466. 11.times do
  1467. element = instance.find_elements(css: 'body')[0]
  1468. text = element.text
  1469. if text.match?(/#{Regexp.quote(data[:name])}/)
  1470. assert(true, 'overview updated')
  1471. overview = {
  1472. name: name,
  1473. }
  1474. sleep 1
  1475. return overview
  1476. end
  1477. sleep 1
  1478. end
  1479. screenshot(browser: instance, comment: 'overview_update_failed')
  1480. raise 'overview update failed'
  1481. end
  1482. =begin
  1483. ticket = ticket_create(
  1484. browser: browser1,
  1485. data: {
  1486. customer: 'nico',
  1487. group: 'Users', # optional / '-NONE-' # if group selection should not be shown
  1488. priority: '2 normal',
  1489. state: 'open',
  1490. title: 'overview #1',
  1491. body: 'overview #1',
  1492. },
  1493. do_not_submit: true,
  1494. )
  1495. returns (in case of submitted)
  1496. {
  1497. id: 123,
  1498. number: '100001',
  1499. title: 'overview #1',
  1500. }
  1501. ticket = ticket_create(
  1502. browser: browser1,
  1503. data: {
  1504. customer: 'nico',
  1505. group: 'Users', # optional / '-NONE-' # if group selection should not be shown
  1506. priority: '2 normal',
  1507. state: 'open',
  1508. title: 'overview #1',
  1509. body: 'overview #1',
  1510. },
  1511. custom_data_select: {
  1512. key1: 'some value',
  1513. },
  1514. custom_data_input: {
  1515. key1: 'some value',
  1516. },
  1517. custom_data_date: {
  1518. key!: '02/28/2018',
  1519. }
  1520. disable_group_check: true,
  1521. )
  1522. =end
  1523. def ticket_create(params)
  1524. switch_window_focus(params)
  1525. log('ticket_create', params)
  1526. instance = params[:browser] || @browser
  1527. data = params[:data]
  1528. click(
  1529. browser: instance,
  1530. css: 'a[href="#new"]',
  1531. mute_log: true,
  1532. only_if_exists: true,
  1533. )
  1534. click(
  1535. browser: instance,
  1536. css: 'a[href="#ticket/create"]',
  1537. mute_log: true,
  1538. )
  1539. found = false
  1540. 7.times do
  1541. element = instance.find_elements(css: '.content.active .newTicket')[0]
  1542. if element
  1543. found = true
  1544. break
  1545. end
  1546. sleep 1
  1547. end
  1548. if !found
  1549. screenshot(browser: instance, comment: 'ticket_create_failed')
  1550. raise 'no ticket create screen found!'
  1551. end
  1552. if data[:group]
  1553. if data[:group] == '-NONE-'
  1554. # check if owner selection exists
  1555. count = instance.find_elements(css: '.content.active .newTicket select[name="group_id"] option').count
  1556. if count.nonzero?
  1557. instance.find_elements(css: '.content.active .newTicket select[name="group_id"] option').each do |element|
  1558. log('ticket_create invalid group count', text: element.text)
  1559. end
  1560. end
  1561. assert_equal(0, count, 'owner selection should not be showm')
  1562. # check count of agents, should be only 3 / - selection + master + agent on init screen
  1563. count = instance.find_elements(css: '.content.active .newTicket select[name="owner_id"] option').count
  1564. if count != 3
  1565. instance.find_elements(css: '.content.active .newTicket select[name="owner_id"] option').each do |element|
  1566. log('ticket_create invalid owner count', text: element.text)
  1567. end
  1568. end
  1569. assert_equal(3, count, 'check if owner selection is - selection + master + agent per default')
  1570. else
  1571. # check count of agents, should be only 1 / - selection on init screen
  1572. if !params[:disable_group_check]
  1573. count = instance.find_elements(css: '.content.active .newTicket select[name="owner_id"] option').count
  1574. if count != 1
  1575. instance.find_elements(css: '.content.active .newTicket select[name="owner_id"] option').each do |element|
  1576. log('ticket_create invalid owner count', text: element.text)
  1577. end
  1578. end
  1579. assert_equal(1, count, 'check if owner selection is empty per default')
  1580. end
  1581. select(
  1582. browser: instance,
  1583. css: '.content.active .newTicket select[name="group_id"]',
  1584. value: data[:group],
  1585. mute_log: true,
  1586. )
  1587. sleep 0.2
  1588. end
  1589. end
  1590. if data[:priority]
  1591. select(
  1592. browser: instance,
  1593. css: '.content.active .newTicket select[name="priority_id"]',
  1594. value: data[:priority],
  1595. mute_log: true,
  1596. )
  1597. end
  1598. if data[:state]
  1599. select(
  1600. browser: instance,
  1601. css: '.content.active .newTicket select[name="state_id"]',
  1602. value: data[:state],
  1603. mute_log: true,
  1604. )
  1605. end
  1606. if data[:title]
  1607. set(
  1608. browser: instance,
  1609. css: '.content.active .newTicket input[name="title"]',
  1610. value: data[:title],
  1611. clear: true,
  1612. mute_log: true,
  1613. )
  1614. end
  1615. if data[:body]
  1616. set(
  1617. browser: instance,
  1618. css: '.content.active .newTicket div[data-name=body]',
  1619. value: data[:body],
  1620. clear: true,
  1621. mute_log: true,
  1622. )
  1623. end
  1624. if data[:customer]
  1625. element = instance.find_elements(css: '.content.active .newTicket input[name="customer_id_completion"]')[0]
  1626. element.click
  1627. element.clear
  1628. # ff issue, sometimes focus event gets dropped
  1629. # if drowdown is not open, try it again
  1630. if !instance.find_elements(css: '.content.active .newTicket .js-recipientDropdown.open')[0]
  1631. instance.execute_script('$(".active .newTicket .js-recipientDropdown").addClass("open")')
  1632. end
  1633. element.send_keys(data[:customer])
  1634. sleep 2.5
  1635. element.send_keys(:enter)
  1636. sleep 0.4
  1637. # ff issue, sometimes enter event gets dropped
  1638. # take user manually
  1639. if instance.find_elements(css: '.content.active .newTicket .js-recipientDropdown.open')[0]
  1640. instance.find_elements(css: '.content.active .newTicket .recipientList-entry.js-object.is-active')[0].click
  1641. sleep 0.4
  1642. end
  1643. end
  1644. params[:custom_data_select]&.each do |local_key, local_value|
  1645. select(
  1646. browser: instance,
  1647. css: ".content.active .newTicket select[name=\"#{local_key}\"]",
  1648. value: local_value,
  1649. )
  1650. end
  1651. params[:custom_data_input]&.each do |local_key, local_value|
  1652. set(
  1653. browser: instance,
  1654. css: ".content.active .newTicket input[name=\"#{local_key}\"]",
  1655. value: local_value,
  1656. clear: true,
  1657. )
  1658. end
  1659. params[:custom_data_date]&.each do |local_key, local_value|
  1660. set(
  1661. browser: instance,
  1662. css: ".content.active .newTicket div[data-name=\"#{local_key}\"] input[data-item=\"date\"]",
  1663. value: local_value,
  1664. clear: true,
  1665. )
  1666. end
  1667. if data[:attachment]
  1668. file_upload(
  1669. browser: instance,
  1670. css: '.content.active .text-1',
  1671. value: 'some text',
  1672. )
  1673. end
  1674. if params[:do_not_submit]
  1675. assert(true, 'ticket created without submit')
  1676. return
  1677. end
  1678. sleep 0.5
  1679. #instance.execute_script('$(".content.active .newTicket form").submit();')
  1680. click(
  1681. browser: instance,
  1682. css: '.content.active .newTicket button.js-submit',
  1683. mute_log: true,
  1684. )
  1685. sleep 1
  1686. 9.times do
  1687. if instance.current_url.match?(/#{Regexp.quote('#ticket/zoom/')}/)
  1688. assert(true, 'ticket created')
  1689. sleep 2.5
  1690. id = instance.current_url
  1691. id.gsub!(//,)
  1692. id.gsub!(%r{^.+?/(\d+)$}, '\\1')
  1693. element = instance.find_elements(css: '.content.active .ticketZoom-header .ticket-number')[0]
  1694. if element
  1695. number = element.text
  1696. ticket = {
  1697. id: id,
  1698. number: number,
  1699. title: data[:title],
  1700. }
  1701. sleep 3 # wait until notify is gone
  1702. screenshot(browser: instance, comment: 'ticket_create_ok')
  1703. return ticket
  1704. end
  1705. end
  1706. sleep 1
  1707. end
  1708. screenshot(browser: instance, comment: 'ticket_create_failed')
  1709. raise "ticket creation failed, can't get zoom url (current url is '#{instance.current_url}')"
  1710. end
  1711. =begin
  1712. ticket_update(
  1713. browser: browser1,
  1714. data: {
  1715. title: '',
  1716. customer: 'some_customer@example.com',
  1717. body: 'some body',
  1718. group: 'some group', # optional
  1719. priority: '1 low',
  1720. state: 'closed',
  1721. },
  1722. do_not_submit: true,
  1723. )
  1724. ticket_update(
  1725. browser: browser1,
  1726. data: {
  1727. title: '',
  1728. customer: 'some_customer@example.com',
  1729. body: 'some body',
  1730. group: 'some group', # optional
  1731. priority: '1 low',
  1732. state: 'closed',
  1733. },
  1734. custom_data_select: {
  1735. key1: 'some value',
  1736. },
  1737. custom_data_input: {
  1738. key1: 'some value',
  1739. },
  1740. custom_data_date: {
  1741. key1: '02/21/2018',
  1742. },
  1743. do_not_submit: true,
  1744. task_type: 'stayOnTab', # default: stayOnTab / possible: closeTab, closeNextInOverview, stayOnTab
  1745. )
  1746. =end
  1747. def ticket_update(params)
  1748. switch_window_focus(params)
  1749. log('ticket_update', params)
  1750. instance = params[:browser] || @browser
  1751. data = params[:data]
  1752. if data[:title]
  1753. #element = instance.find_elements(:css => '.content.active .ticketZoom-header .js-objectTitle')[0]
  1754. #element.clear
  1755. #sleep 0.5
  1756. #element = instance.find_elements(:css => '.content.active .ticketZoom-header .js-objectTitle')[0]
  1757. #element.send_keys(data[:title])
  1758. #sleep 0.5
  1759. #element.send_keys(:tab)
  1760. instance.execute_script('$(".content.active .ticketZoom-header .js-objectTitle").focus()')
  1761. instance.execute_script('$(".content.active .ticketZoom-header .js-objectTitle").text("' + data[:title] + '")')
  1762. instance.execute_script('$(".content.active .ticketZoom-header .js-objectTitle").blur()')
  1763. instance.execute_script('$(".content.active .ticketZoom-header .js-objectTitle").trigger("blur")')
  1764. # {
  1765. # :where => :instance2,
  1766. # :execute => 'sendkey',
  1767. # :css => '.content.active .ticketZoom-header .js-objectTitle',
  1768. # :value => 'TTT',
  1769. # },
  1770. # {
  1771. # :where => :instance2,
  1772. # :execute => 'sendkey',
  1773. # :css => '.content.active .ticketZoom-header .js-objectTitle',
  1774. # :value => :tab,
  1775. # },
  1776. end
  1777. if data[:customer]
  1778. # select tab
  1779. click(browser: instance, css: '.content.active .tabsSidebar-tab[data-tab="customer"]')
  1780. click(browser: instance, css: '.content.active div[data-tab="customer"] .js-actions .icon-arrow-down')
  1781. click(browser: instance, css: '.content.active div[data-tab="customer"] .js-actions [data-type="customer-change"]')
  1782. watch_for(
  1783. browser: instance,
  1784. css: '.modal',
  1785. value: 'change',
  1786. )
  1787. element = instance.find_elements(css: '.modal input[name="customer_id_completion"]')[0]
  1788. element.click
  1789. element.clear
  1790. element.send_keys(data[:customer])
  1791. sleep 2.5
  1792. element.send_keys(:enter)
  1793. #instance.find_elements(css: '.modal .user_autocompletion .recipientList-entry.js-object.is-active')[0].click
  1794. sleep 0.2
  1795. click(browser: instance, css: '.modal .js-submit')
  1796. modal_disappear(browser: instance)
  1797. watch_for(
  1798. browser: instance,
  1799. css: '.content.active .tabsSidebar',
  1800. value: data[:customer],
  1801. )
  1802. # select tab
  1803. click(browser: instance, css: '.content.active .tabsSidebar-tab[data-tab="ticket"]')
  1804. end
  1805. if data[:body]
  1806. set(
  1807. browser: instance,
  1808. css: '.content.active div[data-name=body]',
  1809. value: data[:body],
  1810. no_click: true,
  1811. mute_log: true,
  1812. )
  1813. # it's not working stable via selenium, use js
  1814. value = instance.find_elements(css: '.content.active div[data-name=body]')[0].text
  1815. if value != data[:body]
  1816. body_quoted = quote(data[:body])
  1817. instance.execute_script("$('.content.active div[data-name=body]').html('#{body_quoted}').trigger('focusout')")
  1818. end
  1819. end
  1820. if data[:group]
  1821. if data[:group] == '-NONE-'
  1822. # check if owner selection exists
  1823. count = instance.find_elements(css: '.content.active .sidebar select[name="group_id"] option').count
  1824. assert_equal(0, count, 'owner selection should not be showm')
  1825. # check count of agents, should be only 3 / - selection + master + agent on init screen
  1826. count = instance.find_elements(css: '.content.active .sidebar select[name="owner_id"] option').count
  1827. assert_equal(3, count, 'check if owner selection is - selection + master + agent per default')
  1828. else
  1829. select(
  1830. browser: instance,
  1831. css: '.content.active .sidebar select[name="group_id"]',
  1832. value: data[:group],
  1833. mute_log: true,
  1834. )
  1835. sleep 0.2
  1836. end
  1837. end
  1838. if data[:priority]
  1839. select(
  1840. browser: instance,
  1841. css: '.content.active .sidebar select[name="priority_id"]',
  1842. value: data[:priority],
  1843. mute_log: true,
  1844. )
  1845. end
  1846. if data[:state]
  1847. select(
  1848. browser: instance,
  1849. css: '.content.active .sidebar select[name="state_id"]',
  1850. value: data[:state],
  1851. mute_log: true,
  1852. )
  1853. end
  1854. params[:custom_data_select]&.each do |local_key, local_value|
  1855. select(
  1856. browser: instance,
  1857. css: ".active .sidebar select[name=\"#{local_key}\"]",
  1858. value: local_value,
  1859. )
  1860. end
  1861. params[:custom_data_input]&.each do |local_key, local_value|
  1862. set(
  1863. browser: instance,
  1864. css: ".active .sidebar input[name=\"#{local_key}\"]",
  1865. value: local_value,
  1866. clear: true,
  1867. )
  1868. end
  1869. params[:custom_data_date]&.each do |local_key, local_value|
  1870. click(
  1871. browser: instance,
  1872. css: ".active .sidebar div[data-name=\"#{local_key}\"] input[data-item=\"date\"]",
  1873. mute_log: true,
  1874. )
  1875. # weird bug where you cannot "clear" for date/time input
  1876. # this is specific chrome problem, chrome bug report: https://bugs.chromium.org/p/chromedriver/issues/detail?id=1319#c2
  1877. # indirect issue: https://github.com/angular/protractor/issues/562#issuecomment-47745263
  1878. 11.times do
  1879. sendkey(
  1880. value: :backspace,
  1881. )
  1882. end
  1883. set(
  1884. browser: instance,
  1885. css: ".active .sidebar div[data-name=\"#{local_key}\"] input[data-item=\"date\"]",
  1886. value: local_value,
  1887. )
  1888. end
  1889. if data[:state] || data[:group] || data[:body] || params[:custom_data_select].present? || params[:custom_data_input].present?
  1890. found = nil
  1891. 9.times do
  1892. break if found
  1893. begin
  1894. text = instance.find_elements(css: '.content.active .js-reset')[0].text
  1895. if text.match?(/(Discard your unsaved changes.|Verwerfen der)/)
  1896. found = true
  1897. end
  1898. rescue
  1899. # try again
  1900. end
  1901. sleep 1
  1902. end
  1903. if !found
  1904. screenshot(browser: instance, comment: 'ticket_update_discard_message_failed')
  1905. raise 'no discard message found'
  1906. end
  1907. end
  1908. task_type(
  1909. browser: instance,
  1910. type: params[:task_type] || 'stayOnTab',
  1911. )
  1912. if params[:do_not_submit]
  1913. assert(true, 'ticket updated without submit')
  1914. return true
  1915. end
  1916. instance.find_elements(css: '.content.active .js-submit')[0].click
  1917. # do not stay on tab
  1918. if params[:task_type] == 'closeTab' || params[:task_type] == 'closeNextInOverview'
  1919. sleep 1
  1920. screenshot(browser: instance, comment: 'ticket_update')
  1921. return
  1922. end
  1923. 9.times do
  1924. begin
  1925. text = instance.find_elements(css: '.content.active .js-reset')[0].text
  1926. if text.blank?
  1927. screenshot(browser: instance, comment: 'ticket_update_ok')
  1928. sleep 1
  1929. return true
  1930. end
  1931. rescue
  1932. # try again
  1933. end
  1934. sleep 1
  1935. end
  1936. screenshot(browser: instance, comment: 'ticket_update_failed')
  1937. raise 'unable to update ticket'
  1938. end
  1939. =begin
  1940. ticket_verify(
  1941. browser: browser1,
  1942. data: {
  1943. title: 'some title',
  1944. body: 'some body',
  1945. ## group: 'some group',
  1946. ## state: 'closed',
  1947. custom_data_select: {
  1948. key1: 'some value',
  1949. },
  1950. custom_data_input: {
  1951. key1: 'some value',
  1952. },
  1953. },
  1954. )
  1955. =end
  1956. def ticket_verify(params)
  1957. switch_window_focus(params)
  1958. log('ticket_verify', params)
  1959. instance = params[:browser] || @browser
  1960. data = params[:data]
  1961. if data[:title]
  1962. title = instance.find_elements(css: '.content.active .ticketZoom-header .js-objectTitle').first.text.strip
  1963. if title.match?(/#{data[:title]}/i)
  1964. assert(true, "matching '#{data[:title]}' in title '#{title}'")
  1965. else
  1966. raise "not matching '#{data[:title]}' in title '#{title}'"
  1967. end
  1968. end
  1969. if data[:body]
  1970. body = instance.find_elements(css: '.content.active [data-name="body"]').first.text.strip
  1971. if body.match?(/#{data[:body]}/i)
  1972. assert(true, "matching '#{data[:body]}' in body '#{body}'")
  1973. else
  1974. raise "not matching '#{data[:body]}' in body '#{body}'"
  1975. end
  1976. end
  1977. params[:custom_data_select]&.each do |local_key, local_value|
  1978. element = instance.find_elements(css: ".active .sidebar select[name=\"#{local_key}\"] option[selected]").first
  1979. value = element.text.strip
  1980. if value.match?(/#{local_value}/i)
  1981. assert(true, "matching '#{value}' in #{local_key} '#{local_value}'")
  1982. else
  1983. raise "not matching '#{value}' in #{local_key} '#{local_value}'"
  1984. end
  1985. end
  1986. params[:custom_data_input]&.each do |local_key, local_value|
  1987. element = instance.find_elements(css: ".active .sidebar input[name=\"#{local_key}\"]").first
  1988. value = element.text.strip
  1989. if value.match?(/#{local_value}/i)
  1990. assert(true, "matching '#{value}' in #{local_key} '#{local_value}'")
  1991. else
  1992. raise "not matching '#{value}' in #{local_key} '#{local_value}'"
  1993. end
  1994. end
  1995. true
  1996. end
  1997. =begin
  1998. ticket_open_by_overview(
  1999. browser: browser2,
  2000. number: ticket1[:number],
  2001. link: "#ticket/view/#{name}",
  2002. )
  2003. ticket_open_by_overview(
  2004. browser: browser2,
  2005. number: ticket1[:number],
  2006. text: title,
  2007. link: "#ticket/view/#{name}",
  2008. )
  2009. =end
  2010. def ticket_open_by_overview(params)
  2011. switch_window_focus(params)
  2012. log('ticket_open_by_overview', params)
  2013. instance = params[:browser] || @browser
  2014. instance.find_elements(css: '.js-overviewsMenuItem')[0].click
  2015. sleep 1
  2016. execute(
  2017. browser: instance,
  2018. js: '$(".content.active .sidebar").css("display", "block")',
  2019. )
  2020. screenshot(browser: instance, comment: 'ticket_open_by_overview')
  2021. instance.find_elements(css: ".content.active .sidebar a[href=\"#{params[:link]}\"]")[0].click
  2022. sleep 1
  2023. execute(
  2024. browser: instance,
  2025. js: '$(".content.active .sidebar").css("display", "none")',
  2026. )
  2027. screenshot(browser: instance, comment: 'ticket_open_by_overview_search')
  2028. if params[:title]
  2029. element = instance.find_element(css: '.content.active').find_element(partial_link_text: params[:title])
  2030. if !element
  2031. screenshot(browser: instance, comment: 'ticket_open_by_overview_no_ticket_failed')
  2032. raise "unable to find ticket #{params[:title]} in overview #{params[:link]}!"
  2033. end
  2034. else
  2035. element = instance.find_elements(partial_link_text: params[:number])[0]
  2036. if !element
  2037. screenshot(browser: instance, comment: 'ticket_open_by_overview_no_ticket_failed')
  2038. raise "unable to find ticket #{params[:number]} in overview #{params[:link]}!"
  2039. end
  2040. end
  2041. element.click
  2042. sleep 1
  2043. number = instance.find_elements(css: '.content.active .ticketZoom-header .ticket-number')[0].text
  2044. if number !~ /#{params[:number]}/
  2045. screenshot(browser: instance, comment: 'ticket_open_by_overview_open_failed_failed')
  2046. raise "unable to open ticket #{params[:number]}!"
  2047. end
  2048. sleep 1
  2049. assert(true, "ticket #{params[:number]} found")
  2050. true
  2051. end
  2052. =begin
  2053. ticket_open_by_search(
  2054. browser: browser2,
  2055. number: ticket1[:number],
  2056. )
  2057. =end
  2058. def ticket_open_by_search(params)
  2059. switch_window_focus(params)
  2060. log('ticket_open_by_search', params)
  2061. instance = params[:browser] || @browser
  2062. # search by number
  2063. element = instance.find_elements(css: '#global-search')[0]
  2064. element.click
  2065. element.clear
  2066. element.send_keys(params[:number])
  2067. sleep 3
  2068. empty_search(browser: instance)
  2069. # search by number again
  2070. element = instance.find_elements(css: '#global-search')[0]
  2071. element.click
  2072. element.clear
  2073. element.send_keys(params[:number])
  2074. sleep 1
  2075. # open ticket
  2076. screenshot(browser: instance, comment: 'ticket_open_by_search')
  2077. #instance.find_element(partial_link_text: params[:number] } ).click
  2078. instance.execute_script("$(\".js-global-search-result a:contains('#{params[:number]}') .nav-tab-icon\").first().click()")
  2079. sleep 1
  2080. number = instance.find_elements(css: '.content.active .ticketZoom-header .ticket-number')[0].text
  2081. if number !~ /#{params[:number]}/
  2082. screenshot(browser: instance, comment: 'ticket_open_by_search_failed')
  2083. raise "unable to search/find ticket #{params[:number]}!"
  2084. end
  2085. sleep 1
  2086. true
  2087. end
  2088. =begin
  2089. ticket_open_by_title(
  2090. browser: browser2,
  2091. title: ticket1[:title],
  2092. )
  2093. =end
  2094. def ticket_open_by_title(params)
  2095. switch_window_focus(params)
  2096. log('ticket_open_by_title', params)
  2097. instance = params[:browser] || @browser
  2098. # search by number
  2099. element = instance.find_elements(css: '#global-search')[0]
  2100. element.click
  2101. element.clear
  2102. element.send_keys(params[:title])
  2103. sleep 3
  2104. # open ticket
  2105. screenshot(browser: instance, comment: 'ticket_open_by_title_search')
  2106. #instance.find_element(partial_link_text: params[:title] } ).click
  2107. instance.execute_script("$(\".js-global-search-result a:contains('#{params[:title]}') .nav-tab-icon\").click()")
  2108. sleep 1
  2109. title = instance.find_elements(css: '.content.active .ticketZoom-header .js-objectTitle')[0].text
  2110. if title !~ /#{params[:title]}/
  2111. screenshot(browser: instance, comment: 'ticket_open_by_title_failed')
  2112. raise "unable to search/find ticket #{params[:title]}!"
  2113. end
  2114. sleep 1
  2115. true
  2116. end
  2117. =begin
  2118. overview_count = overview_counter(
  2119. browser: browser2,
  2120. )
  2121. returns
  2122. {
  2123. '#ticket/view/all_unassigned' => 42,
  2124. }
  2125. =end
  2126. def overview_counter(params = {})
  2127. switch_window_focus(params)
  2128. log('overview_counter', params)
  2129. instance = params[:browser] || @browser
  2130. instance.find_elements(css: '.js-overviewsMenuItem')[0].click
  2131. sleep 2
  2132. execute(
  2133. browser: instance,
  2134. js: '$(".content.active .sidebar").css("display", "block")',
  2135. )
  2136. #execute(
  2137. # browser: instance,
  2138. # js: '$(".content.active .overview-header").css("display", "none")',
  2139. #)
  2140. overviews = {}
  2141. instance.find_elements(css: '.content.active .sidebar a[href]').each do |element|
  2142. url = element.attribute('href')
  2143. url.gsub!(%r{(http|https)://.+?/(.+?)$}, '\\2')
  2144. overviews[url] = 0
  2145. #puts url.inspect
  2146. #puts element.inspect
  2147. end
  2148. overviews.each_key do |url|
  2149. count = instance.find_elements(css: ".content.active .sidebar a[href=\"#{url}\"] .badge")[0].text
  2150. overviews[url] = count.to_i
  2151. end
  2152. log('overview_counter', overviews)
  2153. overviews
  2154. end
  2155. =begin
  2156. organization_open_by_search(
  2157. browser: browser2,
  2158. value: 'some value',
  2159. )
  2160. =end
  2161. def organization_open_by_search(params = {})
  2162. switch_window_focus(params)
  2163. log('organization_open_by_search', params)
  2164. instance = params[:browser] || @browser
  2165. element = instance.find_elements(css: '#global-search')[0]
  2166. element.click
  2167. element.clear
  2168. element.send_keys(params[:value])
  2169. sleep 3
  2170. empty_search(browser: instance)
  2171. element = instance.find_elements(css: '#global-search')[0]
  2172. element.click
  2173. element.clear
  2174. element.send_keys(params[:value])
  2175. sleep 2
  2176. #instance.find_element(partial_link_text: params[:value] } ).click
  2177. instance.execute_script("$(\".js-global-search-result a:contains('#{params[:value]}') .nav-tab-icon\").click()")
  2178. sleep 1
  2179. name = instance.find_elements(css: '.content.active h1')[0].text
  2180. if name !~ /#{params[:value]}/
  2181. screenshot(browser: instance, comment: 'organization_open_by_search_failed')
  2182. raise "unable to search/find org #{params[:value]}!"
  2183. end
  2184. assert(true, "org #{params[:value]} found")
  2185. sleep 2
  2186. true
  2187. end
  2188. =begin
  2189. user_open_by_search(
  2190. browser: browser2,
  2191. value: 'some value',
  2192. )
  2193. =end
  2194. def user_open_by_search(params = {})
  2195. switch_window_focus(params)
  2196. log('user_open_by_search', params)
  2197. instance = params[:browser] || @browser
  2198. element = instance.find_elements(css: '#global-search')[0]
  2199. element.click
  2200. element.clear
  2201. element.send_keys(params[:value])
  2202. sleep 3
  2203. screenshot(browser: instance, comment: 'user_open_by_search')
  2204. #instance.find_element(partial_link_text: params[:value]).click
  2205. instance.execute_script("$(\".js-global-search-result a:contains('#{params[:value]}') .nav-tab-icon\").click()")
  2206. sleep 1
  2207. name = instance.find_elements(css: '.content.active h1')[0].text
  2208. if name !~ /#{params[:value]}/
  2209. screenshot(browser: instance, comment: 'user_open_by_search_failed')
  2210. raise "unable to search/find user #{params[:value]}!"
  2211. end
  2212. assert(true, "user #{params[:term]} found")
  2213. sleep 2
  2214. true
  2215. end
  2216. =begin
  2217. user_create(
  2218. browser: browser2,
  2219. data: {
  2220. #login: 'some login' + random,
  2221. firstname: 'Manage Firstname' + random,
  2222. lastname: 'Manage Lastname' + random,
  2223. email: user_email,
  2224. password: 'some-pass',
  2225. },
  2226. )
  2227. =end
  2228. def user_create(params = {})
  2229. switch_window_focus(params)
  2230. log('user_create', params)
  2231. instance = params[:browser] || @browser
  2232. data = params[:data]
  2233. click(
  2234. browser: instance,
  2235. css: 'a[href="#manage"]',
  2236. mute_log: true,
  2237. )
  2238. click(
  2239. browser: instance,
  2240. css: '.content.active a[href="#manage/users"]',
  2241. mute_log: true,
  2242. )
  2243. click(
  2244. browser: instance,
  2245. css: '.content.active a[data-type="new"]',
  2246. mute_log: true,
  2247. )
  2248. modal_ready(browser: instance)
  2249. element = instance.find_elements(css: '.modal input[name=firstname]')[0]
  2250. element.clear
  2251. element.send_keys(data[:firstname])
  2252. element = instance.find_elements(css: '.modal input[name=lastname]')[0]
  2253. element.clear
  2254. element.send_keys(data[:lastname])
  2255. element = instance.find_elements(css: '.modal input[name=email]')[0]
  2256. element.clear
  2257. element.send_keys(data[:email])
  2258. element = instance.find_elements(css: '.modal input[name=password]')[0]
  2259. element.clear
  2260. element.send_keys(data[:password])
  2261. element = instance.find_elements(css: '.modal input[name=password_confirm]')[0]
  2262. element.clear
  2263. element.send_keys(data[:password])
  2264. check(
  2265. browser: instance,
  2266. css: '.modal input[name=role_ids][value=3]',
  2267. )
  2268. instance.find_elements(css: '.modal button.js-submit')[0].click
  2269. modal_disappear(
  2270. browser: instance,
  2271. timeout: 10,
  2272. )
  2273. set(
  2274. browser: instance,
  2275. css: '.content .js-search',
  2276. value: data[:email],
  2277. )
  2278. watch_for(
  2279. browser: instance,
  2280. css: 'body',
  2281. value: data[:lastname],
  2282. )
  2283. assert(true, 'user created')
  2284. end
  2285. =begin
  2286. sla_create(
  2287. browser: browser2,
  2288. data: {
  2289. name: 'some sla' + random,
  2290. first_response_time_in_text: 61
  2291. },
  2292. )
  2293. =end
  2294. def sla_create(params = {})
  2295. switch_window_focus(params)
  2296. log('sla_create', params)
  2297. instance = params[:browser] || @browser
  2298. data = params[:data]
  2299. click(
  2300. browser: instance,
  2301. css: 'a[href="#manage"]',
  2302. mute_log: true,
  2303. )
  2304. click(
  2305. browser: instance,
  2306. css: '.content.active a[href="#manage/slas"]',
  2307. mute_log: true,
  2308. )
  2309. click(
  2310. browser: instance,
  2311. css: '.content.active a.js-new',
  2312. mute_log: true,
  2313. )
  2314. modal_ready(browser: instance)
  2315. element = instance.find_elements(css: '.modal input[name=name]')[0]
  2316. element.clear
  2317. element.send_keys(data[:name])
  2318. element = instance.find_elements(css: '.modal input[name=first_response_time_in_text]')[0]
  2319. element.clear
  2320. element.send_keys(data[:first_response_time_in_text])
  2321. instance.find_elements(css: '.modal button.js-submit')[0].click
  2322. modal_disappear(browser: instance)
  2323. 7.times do
  2324. element = instance.find_elements(css: 'body')[0]
  2325. text = element.text
  2326. if text.match?(/#{Regexp.quote(data[:name])}/)
  2327. assert(true, 'sla created')
  2328. sleep 1
  2329. return true
  2330. end
  2331. sleep 1
  2332. end
  2333. screenshot(browser: instance, comment: 'sla_create_failed')
  2334. raise 'sla creation failed'
  2335. end
  2336. =begin
  2337. text_module_create(
  2338. browser: browser2,
  2339. data: {
  2340. name: 'some sla' + random,
  2341. keywords: 'some keywords',
  2342. content: 'some content',
  2343. },
  2344. )
  2345. =end
  2346. def text_module_create(params = {})
  2347. switch_window_focus(params)
  2348. log('text_module_create', params)
  2349. instance = params[:browser] || @browser
  2350. data = params[:data]
  2351. click(
  2352. browser: instance,
  2353. css: 'a[href="#manage"]',
  2354. mute_log: true,
  2355. )
  2356. click(
  2357. browser: instance,
  2358. css: '.content.active a[href="#manage/text_modules"]',
  2359. mute_log: true,
  2360. )
  2361. click(
  2362. browser: instance,
  2363. css: '.content.active a[data-type="new"]',
  2364. mute_log: true,
  2365. )
  2366. modal_ready(browser: instance)
  2367. set(
  2368. browser: instance,
  2369. css: '.modal input[name=name]',
  2370. value: data[:name],
  2371. )
  2372. set(
  2373. browser: instance,
  2374. css: '.modal input[name=keywords]',
  2375. value: data[:keywords],
  2376. )
  2377. set(
  2378. browser: instance,
  2379. css: '.modal [data-name=content]',
  2380. value: data[:content],
  2381. )
  2382. instance.find_elements(css: '.modal button.js-submit')[0].click
  2383. modal_disappear(browser: instance)
  2384. 7.times do
  2385. element = instance.find_elements(css: 'body')[0]
  2386. text = element.text
  2387. if text.match?(/#{Regexp.quote(data[:name])}/)
  2388. assert(true, 'text module created')
  2389. sleep 1
  2390. return true
  2391. end
  2392. sleep 1
  2393. end
  2394. screenshot(browser: instance, comment: 'text_module_create_failed')
  2395. raise 'text module creation failed'
  2396. end
  2397. =begin
  2398. signature_create(
  2399. browser: browser2,
  2400. data: {
  2401. name: 'some sla' + random,
  2402. body: 'some body',
  2403. },
  2404. )
  2405. =end
  2406. def signature_create(params = {})
  2407. switch_window_focus(params)
  2408. log('signature_create', params)
  2409. instance = params[:browser] || @browser
  2410. data = params[:data]
  2411. click(
  2412. browser: instance,
  2413. css: 'a[href="#manage"]',
  2414. mute_log: true,
  2415. )
  2416. click(
  2417. browser: instance,
  2418. css: '.content.active a[href="#channels/email"]',
  2419. mute_log: true,
  2420. )
  2421. click(
  2422. browser: instance,
  2423. css: '.content.active a[href="#c-signature"]',
  2424. mute_log: true,
  2425. )
  2426. sleep 4
  2427. click(
  2428. browser: instance,
  2429. css: '.content.active #c-signature a[data-type="new"]',
  2430. mute_log: true,
  2431. )
  2432. modal_ready(browser: instance)
  2433. set(
  2434. browser: instance,
  2435. css: '.modal input[name=name]',
  2436. value: data[:name],
  2437. )
  2438. set(
  2439. browser: instance,
  2440. css: '.modal [data-name=body]',
  2441. value: data[:body],
  2442. )
  2443. instance.find_elements(css: '.modal button.js-submit')[0].click
  2444. modal_disappear(browser: instance)
  2445. 11.times do
  2446. element = instance.find_elements(css: 'body')[0]
  2447. text = element.text
  2448. if text.match?(/#{Regexp.quote(data[:name])}/)
  2449. assert(true, 'signature created')
  2450. sleep 1
  2451. return true
  2452. end
  2453. sleep 1
  2454. end
  2455. screenshot(browser: instance, comment: 'signature_create_failed')
  2456. raise 'signature creation failed'
  2457. end
  2458. =begin
  2459. group_create(
  2460. browser: browser2,
  2461. data: {
  2462. name: 'some sla' + random,
  2463. signature: 'some signature bame',
  2464. member: [
  2465. {
  2466. login: 'some_user_login',
  2467. access: 'all',
  2468. },
  2469. ],
  2470. },
  2471. )
  2472. =end
  2473. def group_create(params = {})
  2474. switch_window_focus(params)
  2475. log('group_create', params)
  2476. instance = params[:browser] || @browser
  2477. data = params[:data]
  2478. click(
  2479. browser: instance,
  2480. css: 'a[href="#manage"]',
  2481. mute_log: true,
  2482. )
  2483. click(
  2484. browser: instance,
  2485. css: '.content.active a[href="#manage/groups"]',
  2486. mute_log: true,
  2487. )
  2488. click(
  2489. browser: instance,
  2490. css: '.content.active a[data-type="new"]',
  2491. mute_log: true,
  2492. )
  2493. modal_ready(browser: instance)
  2494. element = instance.find_elements(css: '.modal input[name=name]')[0]
  2495. element.clear
  2496. element.send_keys(data[:name])
  2497. element = instance.find_elements(css: '.modal select[name="email_address_id"]')[0]
  2498. dropdown = Selenium::WebDriver::Support::Select.new(element)
  2499. dropdown.select_by(:index, 1)
  2500. #dropdown.select_by(:text, action[:group])
  2501. if data[:signature]
  2502. element = instance.find_elements(css: '.modal select[name="signature_id"]')[0]
  2503. dropdown = Selenium::WebDriver::Support::Select.new(element)
  2504. dropdown.select_by(:text, data[:signature])
  2505. end
  2506. instance.find_elements(css: '.modal button.js-submit')[0].click
  2507. modal_disappear(browser: instance)
  2508. 11.times do
  2509. element = instance.find_elements(css: 'body')[0]
  2510. text = element.text
  2511. if text.match?(/#{Regexp.quote(data[:name])}/)
  2512. assert(true, 'group created')
  2513. modal_disappear(browser: instance) # wait until modal has gone
  2514. # add member
  2515. data[:member]&.each do |member|
  2516. instance.find_elements(css: 'a[href="#manage"]')[0].click
  2517. sleep 1
  2518. instance.find_elements(css: '.content.active a[href="#manage/users"]')[0].click
  2519. sleep 3
  2520. element = instance.find_elements(css: '.content.active [name="search"]')[0]
  2521. element.clear
  2522. element.send_keys(member[:login])
  2523. sleep 3
  2524. #instance.find_elements(:css => '.content.active table [data-id]')[0].click
  2525. instance.execute_script('$(".content.active table [data-id] td").first().click()')
  2526. modal_ready(browser: instance)
  2527. #instance.find_elements(:css => 'label:contains(" ' + action[:name] + '")')[0].click
  2528. instance.execute_script('$(".js-groupList tr:contains(\"' + data[:name] + '\") .js-groupListItem[value=' + member[:access] + ']").prop("checked", true)')
  2529. screenshot(browser: instance, comment: 'group_create_member')
  2530. instance.find_elements(css: '.modal button.js-submit')[0].click
  2531. modal_disappear(browser: instance)
  2532. end
  2533. end
  2534. sleep 1
  2535. return true
  2536. end
  2537. screenshot(browser: instance, comment: 'group_create_failed')
  2538. raise 'group creation failed'
  2539. end
  2540. =begin
  2541. role_create(
  2542. browser: browser2,
  2543. data: {
  2544. name: 'some role' + random,
  2545. default_at_signup: false,
  2546. permission: {
  2547. 'admin.group' => true,
  2548. 'preferences.password' => true,
  2549. },
  2550. member: [
  2551. 'some_user_login',
  2552. ],
  2553. },
  2554. )
  2555. =end
  2556. def role_create(params = {})
  2557. switch_window_focus(params)
  2558. log('role_create', params)
  2559. instance = params[:browser] || @browser
  2560. data = params[:data]
  2561. click(
  2562. browser: instance,
  2563. css: 'a[href="#manage"]',
  2564. mute_log: true,
  2565. )
  2566. click(
  2567. browser: instance,
  2568. css: '.content.active a[href="#manage/roles"]',
  2569. mute_log: true,
  2570. )
  2571. click(
  2572. browser: instance,
  2573. css: '.content.active a[data-type="new"]',
  2574. mute_log: true,
  2575. )
  2576. modal_ready(browser: instance)
  2577. element = instance.find_elements(css: '.modal input[name=name]')[0]
  2578. element.clear
  2579. element.send_keys(data[:name])
  2580. if data.key?(:default_at_signup)
  2581. element = instance.find_elements(css: '.modal select[name="default_at_signup"]')[0]
  2582. dropdown = Selenium::WebDriver::Support::Select.new(element)
  2583. if data[:default_at_signup] == true
  2584. dropdown.select_by(:text, 'yes')
  2585. else
  2586. dropdown.select_by(:text, 'no')
  2587. end
  2588. end
  2589. if data.key?(:permission)
  2590. data[:permission].each do |permission_name, permission_value|
  2591. if permission_value == false
  2592. uncheck(
  2593. browser: instance,
  2594. css: ".modal [data-permission-name=\"#{permission_name}\"]",
  2595. )
  2596. else
  2597. check(
  2598. browser: instance,
  2599. css: ".modal [data-permission-name=\"#{permission_name}\"]",
  2600. )
  2601. end
  2602. end
  2603. end
  2604. instance.find_elements(css: '.modal button.js-submit')[0].click
  2605. modal_disappear(browser: instance)
  2606. 11.times do
  2607. element = instance.find_elements(css: 'body')[0]
  2608. text = element.text
  2609. if text.match?(/#{Regexp.quote(data[:name])}/)
  2610. assert(true, 'role created')
  2611. modal_disappear(browser: instance) # wait until modal has gone
  2612. # add member
  2613. data[:member]&.each do |login|
  2614. instance.find_elements(css: 'a[href="#manage"]')[0].click
  2615. sleep 1
  2616. instance.find_elements(css: '.content.active a[href="#manage/users"]')[0].click
  2617. sleep 3
  2618. element = instance.find_elements(css: '.content.active [name="search"]')[0]
  2619. element.clear
  2620. element.send_keys(login)
  2621. sleep 3
  2622. #instance.find_elements(:css => '.content.active table [data-id]')[0].click
  2623. instance.execute_script('$(".content.active table [data-id] td").first().click()')
  2624. sleep 3
  2625. #instance.find_elements(:css => 'label:contains(" ' + action[:name] + '")')[0].click
  2626. instance.execute_script('$(\'label:contains(" ' + data[:name] + '")\').first().click()')
  2627. instance.find_elements(css: '.modal button.js-submit')[0].click
  2628. modal_disappear(browser: instance)
  2629. end
  2630. end
  2631. sleep 1
  2632. return true
  2633. end
  2634. screenshot(browser: instance, comment: 'role_create_failed')
  2635. raise 'role creation failed'
  2636. end
  2637. =begin
  2638. role_create(
  2639. browser: browser2,
  2640. data: {
  2641. name: 'some role' + random,
  2642. default_at_signup: false,
  2643. permission: {
  2644. 'admin.group' => true,
  2645. 'preferences.password' => true,
  2646. },
  2647. member: [
  2648. 'some_user_login',
  2649. ],
  2650. },
  2651. )
  2652. =end
  2653. def role_edit(params = {})
  2654. switch_window_focus(params)
  2655. log('role_edit', params)
  2656. instance = params[:browser] || @browser
  2657. data = params[:data]
  2658. click(
  2659. browser: instance,
  2660. css: 'a[href="#manage"]',
  2661. mute_log: true,
  2662. )
  2663. click(
  2664. browser: instance,
  2665. css: '.content.active a[href="#manage/roles"]',
  2666. mute_log: true,
  2667. )
  2668. instance.execute_script('$(\'.content.active table tr td:contains(" ' + data[:name] + '")\').first().click()')
  2669. modal_ready(browser: instance)
  2670. element = instance.find_elements(css: '.modal input[name=name]')[0]
  2671. element.clear
  2672. element.send_keys(data[:name])
  2673. if data.key?(:default_at_signup)
  2674. element = instance.find_elements(css: '.modal select[name="default_at_signup"]')[0]
  2675. dropdown = Selenium::WebDriver::Support::Select.new(element)
  2676. if data[:default_at_signup] == true
  2677. dropdown.select_by(:text, 'yes')
  2678. else
  2679. dropdown.select_by(:text, 'no')
  2680. end
  2681. end
  2682. if data.key?(:permission)
  2683. data[:permission].each do |permission_name, permission_value|
  2684. if permission_value == false
  2685. uncheck(
  2686. browser: instance,
  2687. css: ".modal [data-permission-name=\"#{permission_name}\"]",
  2688. )
  2689. else
  2690. check(
  2691. browser: instance,
  2692. css: ".modal [data-permission-name=\"#{permission_name}\"]",
  2693. )
  2694. end
  2695. end
  2696. end
  2697. if data.key?(:active)
  2698. element = instance.find_elements(css: '.modal select[name="active"]')[0]
  2699. dropdown = Selenium::WebDriver::Support::Select.new(element)
  2700. if data[:active] == true
  2701. dropdown.select_by(:text, 'active')
  2702. else
  2703. dropdown.select_by(:text, 'inactive')
  2704. end
  2705. end
  2706. instance.find_elements(css: '.modal button.js-submit')[0].click
  2707. modal_disappear(browser: instance)
  2708. 11.times do
  2709. element = instance.find_elements(css: 'body')[0]
  2710. text = element.text
  2711. if text.match?(/#{Regexp.quote(data[:name])}/)
  2712. assert(true, 'role created')
  2713. modal_disappear(browser: instance) # wait until modal has gone
  2714. # add member
  2715. data[:member]&.each do |login|
  2716. instance.find_elements(css: 'a[href="#manage"]')[0].click
  2717. sleep 1
  2718. instance.find_elements(css: '.content.active a[href="#manage/users"]')[0].click
  2719. sleep 3
  2720. element = instance.find_elements(css: '.content.active [name="search"]')[0]
  2721. element.clear
  2722. element.send_keys(login)
  2723. sleep 3
  2724. #instance.find_elements(:css => '.content.active table [data-id]')[0].click
  2725. instance.execute_script('$(".content.active table [data-id] td").first().click()')
  2726. sleep 3
  2727. #instance.find_elements(:css => 'label:contains(" ' + action[:name] + '")')[0].click
  2728. instance.execute_script('$(\'label:contains(" ' + data[:name] + '")\').first().click()')
  2729. instance.find_elements(css: '.modal button.js-submit')[0].click
  2730. modal_disappear(browser: instance)
  2731. end
  2732. end
  2733. sleep 1
  2734. return true
  2735. end
  2736. screenshot(browser: instance, comment: 'role_edit_failed')
  2737. raise 'role edit failed'
  2738. end
  2739. =begin
  2740. object_manager_attribute_create(
  2741. browser: browser2,
  2742. data: {
  2743. name: 'field_name' + random,
  2744. display: 'Display Name of Field',
  2745. data_type: 'Select',
  2746. data_option: {
  2747. options: {
  2748. 'aa' => 'AA',
  2749. 'bb' => 'BB',
  2750. },
  2751. default: 'abc',
  2752. },
  2753. },
  2754. error: 'already exists'
  2755. )
  2756. object_manager_attribute_create(
  2757. browser: browser2,
  2758. data: {
  2759. name: 'field_name' + random,
  2760. display: 'Display Name of Field',
  2761. data_type: 'Text',
  2762. data_option: {
  2763. default: 'abc',
  2764. },
  2765. },
  2766. error: 'already exists'
  2767. )
  2768. object_manager_attribute_create(
  2769. browser: browser2,
  2770. data: {
  2771. name: 'field_name' + random,
  2772. display: 'Display Name of Field',
  2773. data_type: 'Integer',
  2774. data_option: {
  2775. default: '15',
  2776. min: 1,
  2777. max: 999999,
  2778. },
  2779. },
  2780. error: 'already exists'
  2781. )
  2782. object_manager_attribute_create(
  2783. browser: browser2,
  2784. data: {
  2785. name: 'field_name' + random,
  2786. display: 'Display Name of Field',
  2787. data_type: 'Datetime',
  2788. data_option: {
  2789. future: true,
  2790. past: true,
  2791. diff: 24,
  2792. },
  2793. },
  2794. error: 'already exists'
  2795. )
  2796. object_manager_attribute_create(
  2797. browser: browser2,
  2798. data: {
  2799. name: 'field_name' + random,
  2800. display: 'Display Name of Field',
  2801. data_type: 'Date',
  2802. data_option: {
  2803. future: true,
  2804. past: true,
  2805. diff: 24,
  2806. },
  2807. },
  2808. error: 'already exists'
  2809. )
  2810. object_manager_attribute_create(
  2811. browser: browser2,
  2812. data: {
  2813. name: 'field_name' + random,
  2814. display: 'Display Name of Field',
  2815. data_type: 'Boolean',
  2816. data_option: {
  2817. options: {
  2818. true: 'YES',
  2819. false: 'NO',
  2820. }
  2821. default: undefined,
  2822. },
  2823. },
  2824. error: 'already exists'
  2825. )
  2826. =end
  2827. def object_manager_attribute_create(params = {})
  2828. switch_window_focus(params)
  2829. log('object_manager_attribute_create', params)
  2830. instance = params[:browser] || @browser
  2831. data = params[:data]
  2832. click(
  2833. browser: instance,
  2834. css: 'a[href="#manage"]',
  2835. mute_log: true,
  2836. )
  2837. click(
  2838. browser: instance,
  2839. css: '.content.active a[href="#system/object_manager"]',
  2840. mute_log: true,
  2841. )
  2842. sleep 4
  2843. click(
  2844. browser: instance,
  2845. css: '.content.active .js-new',
  2846. mute_log: true,
  2847. )
  2848. modal_ready(browser: instance)
  2849. element = instance.find_elements(css: '.modal input[name=name]')[0]
  2850. element.clear
  2851. element.send_keys(data[:name])
  2852. element = instance.find_elements(css: '.modal input[name=display]')[0]
  2853. element.clear
  2854. element.send_keys(data[:display])
  2855. select(
  2856. browser: instance,
  2857. css: '.modal select[name="data_type"]',
  2858. value: data[:data_type],
  2859. mute_log: true,
  2860. )
  2861. if data[:data_option]
  2862. if data[:data_option][:options]
  2863. if data[:data_type] == 'Boolean'
  2864. # rubocop:disable Lint/BooleanSymbol
  2865. element = instance.find_elements(css: '.modal .js-valueTrue').first
  2866. element.clear
  2867. element.send_keys(data[:data_option][:options][:true])
  2868. element = instance.find_elements(css: '.modal .js-valueFalse').first
  2869. element.clear
  2870. element.send_keys(data[:data_option][:options][:false])
  2871. # rubocop:enable Lint/BooleanSymbol
  2872. elsif data[:data_type] == 'Tree Select'
  2873. add_tree_options(
  2874. instance: instance,
  2875. options: data[:data_option][:options],
  2876. )
  2877. else
  2878. data[:data_option][:options].each do |key, value|
  2879. element = instance.find_elements(css: '.modal .js-Table .js-key').last
  2880. element.clear
  2881. element.send_keys(key)
  2882. element = instance.find_elements(css: '.modal .js-Table .js-value').last
  2883. element.clear
  2884. element.send_keys(value)
  2885. element = instance.find_elements(css: '.modal .js-Table .js-add')[0]
  2886. element.click
  2887. end
  2888. end
  2889. end
  2890. %i[default min max diff].each do |key|
  2891. next if !data[:data_option].key?(key)
  2892. element = instance.find_elements(css: ".modal [name=\"data_option::#{key}\"]").first
  2893. element.clear
  2894. element.send_keys(data[:data_option][key])
  2895. end
  2896. %i[future past].each do |key|
  2897. next if !data[:data_option].key?(key)
  2898. select(
  2899. browser: instance,
  2900. css: ".modal select[name=\"data_option::#{key}\"]",
  2901. value: data[:data_option][key],
  2902. mute_log: true,
  2903. )
  2904. end
  2905. end
  2906. instance.find_elements(css: '.modal button.js-submit')[0].click
  2907. if params[:error]
  2908. sleep 4
  2909. watch_for(
  2910. css: '.modal',
  2911. value: params[:error],
  2912. )
  2913. click(
  2914. browser: instance,
  2915. css: '.modal .js-close',
  2916. )
  2917. modal_disappear(browser: instance)
  2918. return
  2919. end
  2920. 11.times do
  2921. element = instance.find_elements(css: 'body')[0]
  2922. text = element.text
  2923. if text.match?(/#{Regexp.quote(data[:name])}/)
  2924. assert(true, 'object manager attribute created')
  2925. sleep 1
  2926. return true
  2927. end
  2928. sleep 1
  2929. end
  2930. screenshot(browser: instance, comment: 'object_manager_attribute_create_failed')
  2931. raise 'object manager attribute creation failed'
  2932. end
  2933. =begin
  2934. object_manager_attribute_update(
  2935. browser: browser2,
  2936. data: {
  2937. name: 'field_name' + random,
  2938. display: 'Display Name of Field',
  2939. data_type: 'Select',
  2940. data_option: {
  2941. options: {
  2942. 'aa' => 'AA',
  2943. 'bb' => 'BB',
  2944. },
  2945. default: 'abc',
  2946. },
  2947. },
  2948. error: 'already exists'
  2949. )
  2950. =end
  2951. def object_manager_attribute_update(params = {})
  2952. switch_window_focus(params)
  2953. log('object_manager_attribute_update', params)
  2954. instance = params[:browser] || @browser
  2955. data = params[:data]
  2956. click(
  2957. browser: instance,
  2958. css: 'a[href="#manage"]',
  2959. mute_log: true,
  2960. )
  2961. click(
  2962. browser: instance,
  2963. css: '.content.active a[href="#system/object_manager"]',
  2964. mute_log: true,
  2965. )
  2966. sleep 4
  2967. instance.execute_script("$(\".content.active td:contains('#{data[:name]}')\").first().click()")
  2968. modal_ready(browser: instance)
  2969. element = instance.find_elements(css: '.modal input[name=display]')[0]
  2970. element.clear
  2971. element.send_keys(data[:display])
  2972. select(
  2973. browser: instance,
  2974. css: '.modal select[name="data_type"]',
  2975. value: data[:data_type],
  2976. mute_log: true,
  2977. )
  2978. if data[:data_option]
  2979. if data[:data_option][:options]
  2980. if data[:data_type] == 'Boolean'
  2981. # rubocop:disable Lint/BooleanSymbol
  2982. element = instance.find_elements(css: '.modal .js-valueTrue').first
  2983. element.clear
  2984. element.send_keys(data[:data_option][:options][:true])
  2985. element = instance.find_elements(css: '.modal .js-valueFalse').first
  2986. element.clear
  2987. element.send_keys(data[:data_option][:options][:false])
  2988. # rubocop:enable Lint/BooleanSymbol
  2989. else
  2990. data[:data_option][:options].each do |key, value|
  2991. element = instance.find_elements(css: '.modal .js-Table .js-key').last
  2992. element.clear
  2993. element.send_keys(key)
  2994. element = instance.find_elements(css: '.modal .js-Table .js-value').last
  2995. element.clear
  2996. element.send_keys(value)
  2997. element = instance.find_elements(css: '.modal .js-Table .js-add')[0]
  2998. element.click
  2999. end
  3000. end
  3001. end
  3002. %i[default min max diff].each do |key|
  3003. next if !data[:data_option].key?(key)
  3004. element = instance.find_elements(css: ".modal [name=\"data_option::#{key}\"]").first
  3005. element.clear
  3006. element.send_keys(data[:data_option][key])
  3007. end
  3008. %i[future past].each do |key|
  3009. next if !data[:data_option].key?(key)
  3010. select(
  3011. browser: instance,
  3012. css: ".modal select[name=\"data_option::#{key}\"]",
  3013. value: data[:data_option][key],
  3014. mute_log: true,
  3015. )
  3016. end
  3017. end
  3018. instance.find_elements(css: '.modal button.js-submit')[0].click
  3019. if params[:error]
  3020. sleep 4
  3021. watch_for(
  3022. css: '.modal',
  3023. value: params[:error],
  3024. )
  3025. click(
  3026. browser: instance,
  3027. css: '.modal .js-close',
  3028. )
  3029. modal_disappear(browser: instance)
  3030. return
  3031. end
  3032. 11.times do
  3033. element = instance.find_elements(css: 'body')[0]
  3034. text = element.text
  3035. if text.match?(/#{Regexp.quote(data[:name])}/)
  3036. assert(true, 'object manager attribute updated')
  3037. sleep 1
  3038. return true
  3039. end
  3040. sleep 1
  3041. end
  3042. screenshot(browser: instance, comment: 'object_manager_attribute_update_failed')
  3043. raise 'object manager attribute update failed'
  3044. end
  3045. =begin
  3046. object_manager_attribute_delete(
  3047. browser: browser2,
  3048. data: {
  3049. name: 'field_name' + random,
  3050. },
  3051. )
  3052. =end
  3053. def object_manager_attribute_delete(params = {})
  3054. switch_window_focus(params)
  3055. log('object_manager_attribute_delete', params)
  3056. instance = params[:browser] || @browser
  3057. data = params[:data]
  3058. click(
  3059. browser: instance,
  3060. css: 'a[href="#manage"]',
  3061. mute_log: true,
  3062. )
  3063. click(
  3064. browser: instance,
  3065. css: '.content.active a[href="#system/object_manager"]',
  3066. mute_log: true,
  3067. )
  3068. sleep 4
  3069. instance = params[:browser] || @browser
  3070. data = params[:data]
  3071. r = instance.execute_script("$(\".content.active td:contains('#{data[:name]}')\").first().closest('tr').find('.js-delete').click()")
  3072. #p "rrr #{r.inspect}"
  3073. end
  3074. =begin
  3075. object_manager_attribute_discard_changes(
  3076. browser: browser2,
  3077. )
  3078. =end
  3079. def object_manager_attribute_discard_changes(params = {})
  3080. switch_window_focus(params)
  3081. log('object_manager_attribute_discard_changes', params)
  3082. instance = params[:browser] || @browser
  3083. click(
  3084. browser: instance,
  3085. css: 'a[href="#manage"]',
  3086. mute_log: true,
  3087. )
  3088. click(
  3089. browser: instance,
  3090. css: '.content.active a[href="#system/object_manager"]',
  3091. mute_log: true,
  3092. )
  3093. sleep 4
  3094. element = instance.find_elements(css: '.content.active .js-discard').first
  3095. element.click
  3096. watch_for_disappear(
  3097. browser: instance,
  3098. css: '.content.active .js-discard',
  3099. )
  3100. end
  3101. =begin
  3102. tags_verify(
  3103. browser: browser2,
  3104. tags: {
  3105. 'tag 1' => true,
  3106. 'tag 2' => true,
  3107. 'tag 3' => false,
  3108. },
  3109. )
  3110. =end
  3111. def tags_verify(params = {})
  3112. switch_window_focus(params)
  3113. log('tags_verify', params)
  3114. instance = params[:browser] || @browser
  3115. tags = instance.find_elements({ css: '.content.active .js-tag' })
  3116. assert(tags)
  3117. assert(tags[0])
  3118. tags_found = {}
  3119. params[:tags].each_key do |key|
  3120. tags_found[key] = false
  3121. end
  3122. tags.each do |element|
  3123. text = element.text
  3124. if tags_found.key?(text)
  3125. tags_found[text] = true
  3126. else
  3127. assert(false, "tag exists but is not in check to verify '#{text}'")
  3128. end
  3129. end
  3130. params[:tags].each do |key, value|
  3131. assert_equal(value, tags_found[key], "tag '#{key}'")
  3132. end
  3133. end
  3134. def quote(string)
  3135. string_quoted = string
  3136. string_quoted.gsub!(/&/, '&amp;')
  3137. string_quoted.gsub!(/</, '&lt;')
  3138. string_quoted.gsub!(/>/, '&gt;')
  3139. string_quoted
  3140. end
  3141. def switch_window_focus(params)
  3142. instance = params[:browser] || @browser
  3143. if instance != @last_used_browser
  3144. log('switch browser window focus', {})
  3145. instance.switch_to.window(instance.window_handles.first)
  3146. end
  3147. @last_used_browser = instance
  3148. end
  3149. def log(method, params = {})
  3150. begin
  3151. instance = params[:browser] || @browser
  3152. if instance
  3153. logs = instance.manage.logs.get(:browser)
  3154. logs.each do |log|
  3155. next if log.level == 'WARNING' && log.message =~ /Declaration\sdropped./ # ignore ff css warnings
  3156. time = Time.zone.parse(Time.zone.at(log.timestamp / 1000).to_datetime.to_s)
  3157. puts "#{time}/#{log.level}: #{log.message}"
  3158. end
  3159. end
  3160. rescue
  3161. # failed to get logs
  3162. end
  3163. return if !@@debug
  3164. return if params[:mute_log]
  3165. puts "#{Time.zone.now}/#{method}: #{params.inspect}"
  3166. end
  3167. private
  3168. def add_tree_options(instance:, options:)
  3169. # first level entries have to get added in regular order
  3170. options.each_key.with_index do |option, index|
  3171. if index != 0
  3172. element = instance.find_elements(css: '.modal .js-treeTable .js-addRow')[index - 1]
  3173. element.click
  3174. end
  3175. element = instance.find_elements(css: '.modal .js-treeTable .js-key')[index]
  3176. element.clear
  3177. element.send_keys(option)
  3178. end
  3179. add_sub_tree_recursion(
  3180. instance: instance,
  3181. options: options,
  3182. )
  3183. end
  3184. def add_sub_tree_recursion(instance:, options:, offset: 0)
  3185. options.each_value.inject(offset) do |child_offset, children|
  3186. child_offset += 1
  3187. # put your recursion glasses on 8-)
  3188. add_sub_tree_options(
  3189. instance: instance,
  3190. options: children,
  3191. offset: child_offset,
  3192. )
  3193. end
  3194. end
  3195. def add_sub_tree_options(instance:, options:, offset:)
  3196. # sub level entries have to get added in reversed order
  3197. level_options = options.to_a.reverse.to_h.keys
  3198. level_options.each do |option|
  3199. # sub level entries have to get added via 'add child row' link
  3200. click_index = offset - 1
  3201. element = instance.find_elements(css: '.modal .js-treeTable .js-addChild')[click_index]
  3202. element.click
  3203. element = instance.find_elements(css: '.modal .js-treeTable .js-key')[offset]
  3204. element.clear
  3205. element.send_keys(option)
  3206. sleep 0.25
  3207. end
  3208. add_sub_tree_recursion(
  3209. instance: instance,
  3210. options: options,
  3211. offset: offset,
  3212. )
  3213. end
  3214. end