browser_test_helper.rb 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. ENV["RAILS_ENV"] = "test"
  2. require File.expand_path('../../config/environment', __FILE__)
  3. require 'selenium-webdriver'
  4. class TestCase < Test::Unit::TestCase
  5. def browser
  6. ENV['BROWSER'] || 'firefox'
  7. end
  8. def browser_support_cookies
  9. if browser =~ /(internet_explorer|ie)/i
  10. return false
  11. end
  12. return true
  13. end
  14. def browser_url
  15. ENV['BROWSER_URL'] || 'http://localhost:3000'
  16. end
  17. def browser_instance
  18. if !@browsers
  19. @browsers = []
  20. end
  21. if !ENV['REMOTE_URL'] || ENV['REMOTE_URL'].empty?
  22. local_browser = Selenium::WebDriver.for( browser.to_sym )
  23. browser_instance_preferences(local_browser)
  24. @browsers.push local_browser
  25. return local_browser
  26. end
  27. caps = Selenium::WebDriver::Remote::Capabilities.send( browser )
  28. caps.platform = ENV['BROWSER_OS'] || 'Windows 2008'
  29. caps.version = ENV['BROWSER_VERSION'] || '8'
  30. local_browser = Selenium::WebDriver.for(
  31. :remote,
  32. :url => ENV['REMOTE_URL'],
  33. :desired_capabilities => caps,
  34. )
  35. browser_instance_preferences(local_browser)
  36. @browsers.push local_browser
  37. return local_browser
  38. end
  39. def browser_instance_preferences(local_browser)
  40. #local_browser.manage.window.resize_to(1024, 1024)
  41. if ENV['REMOTE_URL'] !~ /saucelabs/i
  42. if @browsers.size < 1
  43. local_browser.manage.window.move_to(0, 0)
  44. else
  45. local_browser.manage.window.move_to(1024, 0)
  46. end
  47. end
  48. local_browser.manage.timeouts.implicit_wait = 3 # seconds
  49. end
  50. def teardown
  51. return if !@browsers
  52. # only shut down browser type once on local webdriver tests
  53. # otherwise this error will happen "Errno::ECONNREFUSED: Connection refused - connect(2)"
  54. if !ENV['REMOTE_URL']
  55. shutdown = {}
  56. @browsers.each{ |local_browser|
  57. next if shutdown[ local_browser.browser ]
  58. shutdown[ local_browser.browser ] = true
  59. local_browser.quit
  60. }
  61. else
  62. @browsers.each{ |local_browser|
  63. local_browser.quit
  64. }
  65. end
  66. end
  67. # Add more helper methods to be used by all tests here...
  68. def browser_login(data)
  69. all_tests = [
  70. {
  71. :name => 'login',
  72. :instance => data[:instance] || browser_instance,
  73. :url => data[:url] || browser_url,
  74. :action => [
  75. {
  76. :execute => 'login',
  77. :username => data[:username] || 'nicole.braun@zammad.org',
  78. :password => data[:password] || 'test'
  79. },
  80. ],
  81. },
  82. ];
  83. return all_tests
  84. end
  85. def browser_signle_test_with_login(tests, login = {})
  86. all_tests = browser_login( login )
  87. all_tests = all_tests.concat( tests )
  88. browser_single_test(all_tests)
  89. end
  90. def browser_double_test(tests)
  91. instance1 = browser_single_test( browser_login({
  92. :instance => tests[0][:instance1],
  93. :username => tests[0][:instance1_username],
  94. :password => tests[0][:instance1_password],
  95. :url => tests[0][:url],
  96. }), true )
  97. instance2 = browser_single_test( browser_login({
  98. :instance => tests[0][:instance2],
  99. :username => tests[0][:instance2_username],
  100. :password => tests[0][:instance2_password],
  101. :url => tests[0][:url],
  102. }), true )
  103. tests.each { |test|
  104. if test[:action]
  105. test[:action].each { |action|
  106. if action[:execute] == 'wait'
  107. sleep action[:value]
  108. next
  109. end
  110. next if !action[:where]
  111. if action[:where] == :instance1
  112. instance = instance1
  113. else
  114. instance = instance2
  115. end
  116. browser_element_action(test, action, instance)
  117. }
  118. end
  119. }
  120. instance1.close
  121. instance2.close
  122. end
  123. def browser_single_test(tests, keep_connection = false)
  124. instance = nil
  125. @stack = nil
  126. tests.each { |test|
  127. if test[:instance]
  128. instance = test[:instance]
  129. end
  130. if test[:url]
  131. instance.get( test[:url] )
  132. end
  133. if test[:action]
  134. test[:action].each { |action|
  135. if action[:execute] == 'wait'
  136. sleep action[:value]
  137. next
  138. end
  139. browser_element_action(test, action, instance)
  140. }
  141. end
  142. }
  143. if keep_connection
  144. return instance
  145. end
  146. instance.close
  147. end
  148. def browser_element_action(test, action, instance)
  149. puts "NOTICE #{Time.now.to_s}: " + action.inspect
  150. if action[:execute] !~ /accept|dismiss/i
  151. #cookies = instance.manage.all_cookies
  152. #cookies.each {|cookie|
  153. # puts " COOKIE " + cookie.to_s
  154. #}
  155. end
  156. sleep 0.1
  157. if action[:css]
  158. if action[:css].match '###stack###'
  159. action[:css].gsub! '###stack###', @stack
  160. end
  161. begin
  162. if action[:range] == 'all'
  163. element = instance.find_elements( { :css => action[:css] } )
  164. else
  165. element = instance.find_element( { :css => action[:css] } )
  166. end
  167. rescue
  168. element = nil
  169. end
  170. if action[:result] == false
  171. assert( !element, "(#{test[:name]}) Element with css '#{action[:css]}' exists" )
  172. else
  173. assert( element, "(#{test[:name]}) Element with css '#{action[:css]}' doesn't exist" )
  174. end
  175. elsif action[:element] == :url
  176. if instance.current_url =~ /#{Regexp.quote(action[:result])}/
  177. assert( true, "(#{test[:name]}) url #{instance.current_url} is matching #{action[:result]}" )
  178. else
  179. assert( false, "(#{test[:name]}) url #{instance.current_url} is not matching #{action[:result]}" )
  180. end
  181. elsif action[:element] == :title
  182. title = instance.title
  183. if title =~ /#{action[:value]}/i
  184. assert( true, "(#{test[:name]}) matching '#{action[:value]}' in title '#{title}'" )
  185. else
  186. assert( false, "(#{test[:name]}) not matching '#{action[:value]}' in title '#{title}'" )
  187. end
  188. return
  189. elsif action[:element] == :cookie
  190. if !browser_support_cookies
  191. assert( true, "(#{test[:name]}) '#{action[:value]}' ups browser is not supporting reading cookies")
  192. return
  193. end
  194. cookies = instance.manage.all_cookies
  195. cookies.each {|cookie|
  196. if cookie.to_s =~ /#{action[:value]}/i
  197. assert( true, "(#{test[:name]}) matching '#{action[:value]}' in cookie '#{cookie.to_s}'" )
  198. return
  199. end
  200. }
  201. assert( false, "(#{test[:name]}) not matching '#{action[:value]}' in cookie '#{cookies.to_s}'" )
  202. return
  203. elsif action[:element] == :alert
  204. element = instance.switch_to.alert
  205. elsif action[:execute] == 'login'
  206. element = instance.find_element( { :css => '#login input[name="username"]' } )
  207. if !element
  208. assert( false, "(#{test[:name]}) no login box found!" )
  209. return
  210. end
  211. element.clear
  212. element.send_keys( action[:username] )
  213. element = instance.find_element( { :css => '#login input[name="password"]' } )
  214. element.clear
  215. element.send_keys( action[:password] )
  216. if action[:remember_me]
  217. instance.find_element( { :css => '#login [name="remember_me"]' } ).click
  218. end
  219. instance.find_element( { :css => '#login button' } ).click
  220. sleep 4
  221. login = instance.find_element( { :css => '.user-menu .user a' } ).attribute('title')
  222. if login != action[:username]
  223. assert( false, "(#{test[:name]}) login failed" )
  224. return
  225. end
  226. assert( true, "(#{test[:name]}) login success" )
  227. return
  228. elsif action[:execute] == 'logout'
  229. instance.find_element( { :css => 'a[href="#current_user"]' } ).click
  230. sleep 0.1
  231. instance.find_element( { :css => 'a[href="#logout"]' } ).click
  232. (1..6).each {|loop|
  233. login = instance.find_element( { :css => '#login' } )
  234. if login
  235. assert( true, "(#{test[:name]}) logout" )
  236. return
  237. end
  238. }
  239. assert( false, "(#{test[:name]}) no login box found!" )
  240. return
  241. elsif action[:execute] == 'watch_for'
  242. timeout = 16
  243. if action[:timeout]
  244. timeout = action[:timeout]
  245. end
  246. loops = (timeout / 0.5).to_i
  247. text = ''
  248. (1..loops).each { |loop|
  249. element = instance.find_element( { :css => action[:area] } )
  250. if element.displayed?
  251. text = element.text
  252. if text =~ /#{action[:value]}/i
  253. assert( true, "(#{test[:name]}) '#{action[:value]}' found in '#{text}'" )
  254. sleep 0.4
  255. return
  256. end
  257. end
  258. sleep 0.5
  259. }
  260. assert( false, "(#{test[:name]}) '#{action[:value]}' found in '#{text}'" )
  261. return
  262. elsif action[:execute] == 'create_user'
  263. instance.find_element( { :css => 'a[href="#manage"]' } ).click
  264. instance.find_element( { :css => 'a[href="#manage/users"]' } ).click
  265. sleep 2
  266. instance.find_element( { :css => 'a[data-type="new"]' } ).click
  267. sleep 2
  268. #element = instance.find_element( { :css => '.modal input[name=login]' } )
  269. #element.clear
  270. #element.send_keys( action[:login] )
  271. element = instance.find_element( { :css => '.modal input[name=firstname]' } )
  272. element.clear
  273. element.send_keys( action[:firstname] )
  274. element = instance.find_element( { :css => '.modal input[name=lastname]' } )
  275. element.clear
  276. element.send_keys( action[:lastname] )
  277. element = instance.find_element( { :css => '.modal input[name=email]' } )
  278. element.clear
  279. element.send_keys( action[:email] )
  280. element = instance.find_element( { :css => '.modal input[name=password]' } )
  281. element.clear
  282. element.send_keys( action[:password] )
  283. element = instance.find_element( { :css => '.modal input[name=password_confirm]' } )
  284. element.clear
  285. element.send_keys( action[:password] )
  286. instance.find_element( { :css => '.modal input[name="role_ids"][value="3"]' } ).click
  287. instance.find_element( { :css => '.modal button.js-submit' } ).click
  288. (1..14).each {|loop|
  289. element = instance.find_element( { :css => 'body' } )
  290. text = element.text
  291. if text =~ /#{Regexp.quote(action[:lastname])}/
  292. assert( true, "(#{test[:name]}) user created" )
  293. return
  294. end
  295. sleep 0.5
  296. }
  297. assert( true, "(#{test[:name]}) user creation failed" )
  298. return
  299. elsif action[:execute] == 'verify_task_attributes'
  300. if action[:title]
  301. element = instance.find_element( { :css => '.tasks .active' } )
  302. assert_equal( action[:title], element.text.strip )
  303. end
  304. return
  305. elsif action[:execute] == 'verify_ticket_attributes'
  306. if action[:title]
  307. element = instance.find_element( { :css => '.content.active .page-header .ticket-title-update' } )
  308. assert_equal( action[:title], element.text.strip )
  309. end
  310. if action[:body]
  311. element = instance.find_element( { :css => '.content.active [data-name="body"]' } )
  312. assert_equal( action[:body], element.text.strip )
  313. end
  314. return
  315. elsif action[:execute] == 'set_ticket_attributes'
  316. if action[:title]
  317. element = instance.find_element( { :css => '.content.active .page-header .ticket-title-update' } )
  318. instance.execute_script( '$(".content.active .page-header .ticket-title-update").focus()' )
  319. instance.execute_script( '$(".content.active .page-header .ticket-title-update").text("' + action[:title] + '")' )
  320. instance.execute_script( '$(".content.active .page-header .ticket-title-update").blur()' )
  321. instance.execute_script( '$(".content.active .page-header .ticket-title-update").trigger("blur")' )
  322. # {
  323. # :where => :instance2,
  324. # :execute => 'sendkey',
  325. # :css => '.content.active .page-header .ticket-title-update',
  326. # :value => 'TTT',
  327. # },
  328. # {
  329. # :where => :instance2,
  330. # :execute => 'sendkey',
  331. # :css => '.content.active .page-header .ticket-title-update',
  332. # :value => :tab,
  333. # },
  334. end
  335. if action[:body]
  336. element = instance.find_element( { :css => '.content.active [data-name="body"]' } )
  337. element.clear
  338. element.send_keys( action[:body] )
  339. # check if body is filled / in case use workaround
  340. body = element.text
  341. #puts "body '#{body}'"
  342. if !body || body.empty? || body == '' || body == ' '
  343. result = instance.execute_script( '$(".content.active [data-name=body]").text("' + action[:body] + '")' )
  344. #puts "r #{result.inspect}"
  345. end
  346. end
  347. return
  348. elsif action[:execute] == 'create_ticket'
  349. instance.find_element( { :css => 'a[href="#new"]' } ).click
  350. instance.find_element( { :css => 'a[href="#ticket/create"]' } ).click
  351. element = instance.find_element( { :css => '.active .newTicket' } )
  352. if !element
  353. assert( false, "(#{test[:name]}) no ticket create screen found!" )
  354. return
  355. end
  356. sleep 2
  357. if action[:customer] == nil
  358. element = instance.find_element( { :css => '.active .newTicket input[name="customer_id_completion"]' } )
  359. element.click
  360. element.clear
  361. element.send_keys( 'nico*' )
  362. sleep 4
  363. element = instance.find_element( { :css => '.active .newTicket input[name="customer_id_completion"]' } )
  364. element.send_keys( :arrow_down )
  365. sleep 0.3
  366. element = instance.find_element( { :css => '.active .newTicket input[name="customer_id_completion"]' } )
  367. element.send_keys( :enter )
  368. sleep 0.3
  369. end
  370. if action[:group]
  371. element = instance.find_element( { :css => '.active .newTicket select[name="group_id"]' } )
  372. dropdown = Selenium::WebDriver::Support::Select.new(element)
  373. dropdown.select_by( :text, action[:group])
  374. sleep 0.2
  375. end
  376. if action[:subject]
  377. element = instance.find_element( { :css => '.active .newTicket input[name="title"]' } )
  378. element.clear
  379. element.send_keys( action[:subject] )
  380. sleep 0.2
  381. end
  382. if action[:body]
  383. element = instance.find_element( { :css => '.active .newTicket [data-name="body"]' } )
  384. element.clear
  385. element.send_keys( action[:body] )
  386. # check if body is filled / in case use workaround
  387. body = element.text
  388. #puts "body '#{body}'"
  389. if !body || body.empty? || body == '' || body == ' '
  390. result = instance.execute_script( '$(".content.active .newTicket [data-name=body]").text("' + action[:body] + '")' )
  391. #puts "r #{result.inspect}"
  392. end
  393. end
  394. if action[:do_not_submit]
  395. assert( true, "(#{test[:name]}) ticket created without submit" )
  396. return
  397. end
  398. sleep 0.8
  399. instance.find_element( { :css => '.content.active button.submit' } ).click
  400. sleep 1
  401. (1..14).each {|loop|
  402. if instance.current_url =~ /#{Regexp.quote('#ticket/zoom/')}/
  403. assert( true, "(#{test[:name]}) ticket created" )
  404. return
  405. end
  406. sleep 0.5
  407. }
  408. assert( false, "(#{test[:name]}) ticket creation failed, can't get zoom url" )
  409. return
  410. elsif action[:execute] == 'close_all_tasks'
  411. for i in 1..100
  412. begin
  413. sleep 0.8
  414. hover_element = instance.find_element( { :css => '.navigation .tasks .task:first-child' } )
  415. if hover_element
  416. instance.mouse.move_to(hover_element)
  417. sleep 0.1
  418. click_element = instance.find_element( { :css => '.navigation .tasks .task:first-child .js-close' } )
  419. if click_element
  420. click_element.click
  421. sleep 0.2
  422. end
  423. else
  424. break
  425. end
  426. rescue => e
  427. puts e.message
  428. break
  429. end
  430. end
  431. assert( true, "(#{test[:name]}) all tasks closed" )
  432. return
  433. elsif action[:execute] == 'navigate'
  434. instance.navigate.to( action[:to] )
  435. return
  436. elsif action[:execute] == 'reload'
  437. instance.navigate.refresh
  438. return
  439. elsif action[:execute] == 'js'
  440. result = instance.execute_script( action[:value] )
  441. elsif action[:execute] == 'sendkey'
  442. if action[:value].class == Array
  443. action[:value].each {|key|
  444. instance.action.send_keys(key).perform
  445. }
  446. else
  447. instance.action.send_keys(action[:value]).perform
  448. #instance.action.send_keys(:enter).perform
  449. end
  450. # element.send_keys( action[:value] )
  451. elsif action[:link]
  452. if action[:link].match '###stack###'
  453. action[:link].gsub! '###stack###', @stack
  454. end
  455. element = instance.find_element( { :partial_link_text => action[:link] } )
  456. else
  457. assert( false, "(#{test[:name]}) unknow selector for '#{action[:element]}'" )
  458. end
  459. if action[:execute] == 'setCheck'
  460. checked = element.attribute('checked')
  461. if !checked
  462. element.click
  463. end
  464. elsif action[:execute] == 'setUncheck'
  465. checked = element.attribute('checked')
  466. if checked
  467. element.click
  468. end
  469. elsif action[:execute] == 'set'
  470. element.clear
  471. if action[:value] == '###stack###'
  472. element.send_keys( @stack )
  473. else
  474. element.send_keys( '' )
  475. keys = action[:value].to_s.split('')
  476. keys.each {|key|
  477. instance.action.send_keys(key).perform
  478. }
  479. #element.send_keys( action[:value] )
  480. sleep 0.3
  481. end
  482. elsif action[:execute] == 'select'
  483. dropdown = Selenium::WebDriver::Support::Select.new(element)
  484. dropdown.select_by(:text, action[:value])
  485. elsif action[:execute] == 'click'
  486. if element.class == Array
  487. element.each {|item|
  488. item.click
  489. }
  490. else
  491. element.click
  492. end
  493. elsif action[:execute] == 'accept'
  494. element.accept
  495. elsif action[:execute] == 'dismiss'
  496. element.dismiss
  497. elsif action[:execute] == 'send_key'
  498. element.send_keys action[:value]
  499. elsif action[:execute] == 'match'
  500. if action[:css] =~ /select/
  501. dropdown = Selenium::WebDriver::Support::Select.new(element)
  502. success = false
  503. if dropdown.selected_options
  504. dropdown.selected_options.each {|option|
  505. if option.text == action[:value]
  506. success = true
  507. end
  508. }
  509. end
  510. if action[:match_result]
  511. if success
  512. assert( true, "(#{test[:name]}) matching '#{action[:value]}' in select list" )
  513. else
  514. assert( false, "(#{test[:name]}) not matching '#{action[:value]}' in select list" )
  515. end
  516. else
  517. if success
  518. assert( false, "(#{test[:name]}) not matching '#{action[:value]}' in select list" )
  519. else
  520. assert( true, "(#{test[:name]}) matching '#{action[:value]}' in select list" )
  521. end
  522. end
  523. else
  524. if action[:attribute]
  525. text = element.attribute( action[:attribute] )
  526. elsif action[:css] =~ /(input|textarea)/i
  527. text = element.attribute('value')
  528. else
  529. text = element.text
  530. end
  531. if action[:value] == '###stack###'
  532. action[:value] = @stack
  533. end
  534. match = false
  535. if action[:no_quote]
  536. #puts "aaaa #{text}/#{action[:value]}"
  537. if text =~ /#{action[:value]}/
  538. if $1
  539. @stack = $1
  540. end
  541. match = $1 || true
  542. end
  543. else
  544. if text =~ /#{Regexp.quote(action[:value])}/
  545. match = true
  546. end
  547. end
  548. if match
  549. if action[:match_result]
  550. assert( true, "(#{test[:name]}) matching '#{action[:value]}' in content '#{text}'" )
  551. else
  552. assert( false, "(#{test[:name]}) matching '#{action[:value]}' in content '#{text}' but should not!" )
  553. end
  554. else
  555. if !action[:match_result]
  556. assert( true, "(#{test[:name]}) not matching '#{action[:value]}' in content '#{text}'" )
  557. else
  558. assert( false, "(#{test[:name]}) not matching '#{action[:value]}' in content '#{text}' but should not!" )
  559. end
  560. end
  561. end
  562. elsif action[:execute] == 'check'
  563. elsif action[:execute] == 'js'
  564. elsif action[:execute] == 'sendkey'
  565. else
  566. assert( false, "(#{test[:name]}) unknow action '#{action[:execute]}'" )
  567. end
  568. end
  569. end