browser_test_helper.rb 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. ENV["RAILS_ENV"] = "test"
  2. require File.expand_path('../../config/environment', __FILE__)
  3. require 'rails/test_help'
  4. require 'selenium-webdriver'
  5. class TestCase < Test::Unit::TestCase
  6. def browser
  7. ENV['BROWSER'] || 'firefox'
  8. end
  9. def browser_support_cookies
  10. if browser =~ /(internet_explorer|ie)/i
  11. return false
  12. end
  13. return true
  14. end
  15. def browser_url
  16. ENV['BROWSER_URL'] || 'http://localhost:3000'
  17. end
  18. def browser_instance
  19. if !@browsers
  20. @browsers = []
  21. end
  22. if !ENV['REMOTE_URL'] || ENV['REMOTE_URL'].empty?
  23. local_browser = Selenium::WebDriver.for( browser.to_sym )
  24. browser_instance_preferences(local_browser)
  25. @browsers.push local_browser
  26. return local_browser
  27. end
  28. caps = Selenium::WebDriver::Remote::Capabilities.send( browser )
  29. caps.platform = ENV['BROWSER_OS'] || 'Windows 2008'
  30. caps.version = ENV['BROWSER_VERSION'] || '8'
  31. local_browser = Selenium::WebDriver.for(
  32. :remote,
  33. :url => ENV['REMOTE_URL'],
  34. :desired_capabilities => caps,
  35. )
  36. browser_instance_preferences(local_browser)
  37. @browsers.push local_browser
  38. return local_browser
  39. end
  40. def browser_instance_preferences(local_browser)
  41. local_browser.manage.window.resize_to(1024, 1024)
  42. if ENV['REMOTE_URL'] !~ /saucelabs/i
  43. if @browsers.size < 1
  44. local_browser.manage.window.move_to(0, 0)
  45. else
  46. local_browser.manage.window.move_to(1024, 0)
  47. end
  48. end
  49. local_browser.manage.timeouts.implicit_wait = 3 # seconds
  50. end
  51. def teardown
  52. return if !@browsers
  53. # only shut down browser type once on local webdriver tests
  54. # otherwise this error will happen "Errno::ECONNREFUSED: Connection refused - connect(2)"
  55. if !ENV['REMOTE_URL']
  56. shutdown = {}
  57. @browsers.each{ |local_browser|
  58. next if shutdown[ local_browser.browser ]
  59. shutdown[ local_browser.browser ] = true
  60. local_browser.quit
  61. }
  62. else
  63. @browsers.each{ |local_browser|
  64. local_browser.quit
  65. }
  66. end
  67. end
  68. # Add more helper methods to be used by all tests here...
  69. def browser_login(data)
  70. all_tests = [
  71. {
  72. :name => 'login',
  73. :instance => data[:instance] || browser_instance,
  74. :url => data[:url] || browser_url,
  75. :action => [
  76. {
  77. :execute => 'login',
  78. :username => data[:username] || 'nicole.braun@zammad.org',
  79. :password => data[:password] || 'test'
  80. },
  81. ],
  82. },
  83. ];
  84. return all_tests
  85. end
  86. def browser_signle_test_with_login(tests, login = {})
  87. all_tests = browser_login( login )
  88. all_tests = all_tests.concat( tests )
  89. browser_single_test(all_tests)
  90. end
  91. def browser_double_test(tests)
  92. instance1 = browser_single_test( browser_login({
  93. :instance => tests[0][:instance1],
  94. :username => tests[0][:instance1_username],
  95. :password => tests[0][:instance1_password],
  96. :url => tests[0][:url],
  97. }), true )
  98. instance2 = browser_single_test( browser_login({
  99. :instance => tests[0][:instance2],
  100. :username => tests[0][:instance2_username],
  101. :password => tests[0][:instance2_password],
  102. :url => tests[0][:url],
  103. }), true )
  104. tests.each { |test|
  105. if test[:action]
  106. test[:action].each { |action|
  107. if action[:execute] == 'wait'
  108. sleep action[:value]
  109. next
  110. end
  111. next if !action[:where]
  112. if action[:where] == :instance1
  113. instance = instance1
  114. else
  115. instance = instance2
  116. end
  117. browser_element_action(test, action, instance)
  118. }
  119. end
  120. }
  121. instance1.close
  122. instance2.close
  123. end
  124. def browser_single_test(tests, keep_connection = false)
  125. instance = nil
  126. @stack = nil
  127. tests.each { |test|
  128. if test[:instance]
  129. instance = test[:instance]
  130. end
  131. if test[:url]
  132. instance.get( test[:url] )
  133. end
  134. if test[:action]
  135. test[:action].each { |action|
  136. if action[:execute] == 'wait'
  137. sleep action[:value]
  138. next
  139. end
  140. browser_element_action(test, action, instance)
  141. }
  142. end
  143. }
  144. if keep_connection
  145. return instance
  146. end
  147. instance.close
  148. end
  149. def browser_element_action(test, action, instance)
  150. puts "NOTICE #{Time.now.to_s}: " + action.inspect
  151. if action[:execute] !~ /accept|dismiss/i
  152. cookies = instance.manage.all_cookies
  153. cookies.each {|cookie|
  154. puts " COOKIE " + cookie.to_s
  155. }
  156. end
  157. sleep 0.1
  158. if action[:css]
  159. if action[:css].match '###stack###'
  160. action[:css].gsub! '###stack###', @stack
  161. end
  162. begin
  163. if action[:range] == 'all'
  164. element = instance.find_elements( { :css => action[:css] } )
  165. else
  166. element = instance.find_element( { :css => action[:css] } )
  167. end
  168. rescue
  169. element = nil
  170. end
  171. if action[:result] == false
  172. assert( !element, "(#{test[:name]}) Element with css '#{action[:css]}' exists" )
  173. else
  174. assert( element, "(#{test[:name]}) Element with css '#{action[:css]}' doesn't exist" )
  175. end
  176. elsif action[:element] == :url
  177. if instance.current_url =~ /#{Regexp.quote(action[:result])}/
  178. assert( true, "(#{test[:name]}) url #{instance.current_url} is matching #{action[:result]}" )
  179. else
  180. assert( false, "(#{test[:name]}) url #{instance.current_url} is not matching #{action[:result]}" )
  181. end
  182. elsif action[:element] == :title
  183. title = instance.title
  184. if title =~ /#{action[:value]}/i
  185. assert( true, "(#{test[:name]}) matching '#{action[:value]}' in title '#{title}'" )
  186. else
  187. assert( false, "(#{test[:name]}) not matching '#{action[:value]}' in title '#{title}'" )
  188. end
  189. return
  190. elsif action[:element] == :cookie
  191. if !browser_support_cookies
  192. assert( true, "(#{test[:name]}) '#{action[:value]}' ups browser is not supporting reading cookies")
  193. return
  194. end
  195. cookies = instance.manage.all_cookies
  196. cookies.each {|cookie|
  197. if cookie.to_s =~ /#{action[:value]}/i
  198. assert( true, "(#{test[:name]}) matching '#{action[:value]}' in cookie '#{cookie.to_s}'" )
  199. return
  200. end
  201. }
  202. assert( false, "(#{test[:name]}) not matching '#{action[:value]}' in cookie '#{cookies.to_s}'" )
  203. return
  204. elsif action[:element] == :alert
  205. element = instance.switch_to.alert
  206. elsif action[:execute] == 'login'
  207. element = instance.find_element( { :css => '#login input[name="username"]' } )
  208. if !element
  209. assert( false, "(#{test[:name]}) no login box found!" )
  210. return
  211. end
  212. element.clear
  213. element.send_keys( action[:username] )
  214. element = instance.find_element( { :css => '#login input[name="password"]' } )
  215. element.clear
  216. element.send_keys( action[:password] )
  217. instance.find_element( { :css => '#login button' } ).click
  218. sleep 4
  219. return
  220. elsif action[:execute] == 'logout'
  221. instance.find_element( { :css => 'a[href="#current_user"]' } ).click
  222. sleep 0.1
  223. instance.find_element( { :css => 'a[href="#logout"]' } ).click
  224. (1..6).each {|loop|
  225. login = instance.find_element( { :css => '#login' } )
  226. if login
  227. assert( true, "(#{test[:name]}) logout" )
  228. return
  229. end
  230. }
  231. assert( false, "(#{test[:name]}) no login box found!" )
  232. return
  233. elsif action[:execute] == 'watch_for'
  234. text = ''
  235. (1..36).each { |loop|
  236. element = instance.find_element( { :css => action[:area] } )
  237. text = element.text
  238. if text =~ /#{action[:value]}/i
  239. assert( true, "(#{test[:name]}) '#{action[:value]}' found in '#{text}'" )
  240. return
  241. end
  242. sleep 0.33
  243. }
  244. assert( false, "(#{test[:name]}) '#{action[:value]}' found in '#{text}'" )
  245. return
  246. elsif action[:execute] == 'create_ticket'
  247. instance.find_element( { :css => 'a[href="#new"]' } ).click
  248. instance.find_element( { :css => 'a[href="#ticket_create/call_inbound"]' } ).click
  249. element = instance.find_element( { :css => '.active .ticket_create' } )
  250. if !element
  251. assert( false, "(#{test[:name]}) no ticket create screen found!" )
  252. return
  253. end
  254. sleep 2
  255. element = instance.find_element( { :css => '.active .ticket_create input[name="customer_id_autocompletion"]' } )
  256. element.clear
  257. element.send_keys( 'nico' )
  258. sleep 4
  259. element = instance.find_element( { :css => '.active .ticket_create input[name="customer_id_autocompletion"]' } )
  260. element.send_keys( :arrow_down )
  261. sleep 0.2
  262. element = instance.find_element( { :css => '.active .ticket_create input[name="customer_id_autocompletion"]' } )
  263. element.send_keys( :tab )
  264. sleep 0.1
  265. element = instance.find_element( { :css => '.active .ticket_create select[name="group_id"]' } )
  266. dropdown = Selenium::WebDriver::Support::Select.new(element)
  267. dropdown.select_by( :text, action[:group])
  268. sleep 0.1
  269. element = instance.find_element( { :css => '.active .ticket_create input[name="subject"]' } )
  270. element.clear
  271. element.send_keys( action[:subject] )
  272. sleep 0.1
  273. element = instance.find_element( { :css => '.active .ticket_create textarea[name="body"]' } )
  274. element.clear
  275. element.send_keys( action[:body] )
  276. if action[:do_not_submit]
  277. assert( true, "(#{test[:name]}) ticket created without submit" )
  278. return
  279. end
  280. sleep 0.1
  281. instance.find_element( { :css => '.active .form-actions button[type="submit"]' } ).click
  282. (1..14).each {|loop|
  283. if instance.current_url =~ /#{Regexp.quote('#ticket/zoom/')}/
  284. assert( true, "(#{test[:name]}) ticket created" )
  285. return
  286. end
  287. sleep 0.5
  288. }
  289. assert( true, "(#{test[:name]}) ticket creation failed, can't get zoom url" )
  290. return
  291. elsif action[:execute] == 'close_all_tasks'
  292. for i in 1..100
  293. begin
  294. element = instance.find_element( { :css => '.taskbar [data-type="close"]' } )
  295. if element
  296. element.click
  297. sleep 0.8
  298. else
  299. break
  300. end
  301. rescue
  302. break
  303. end
  304. end
  305. assert( true, "(#{test[:name]}) all tasks closed" )
  306. return
  307. elsif action[:execute] == 'navigate'
  308. instance.navigate.to( action[:to] )
  309. return
  310. elsif action[:execute] == 'reload'
  311. instance.navigate.refresh
  312. return
  313. elsif action[:execute] == 'js'
  314. result = instance.execute_script( action[:value] )
  315. elsif action[:link]
  316. if action[:link].match '###stack###'
  317. action[:link].gsub! '###stack###', @stack
  318. end
  319. element = instance.find_element( { :partial_link_text => action[:link] } )
  320. else
  321. assert( false, "(#{test[:name]}) unknow selector for '#{action[:element]}'" )
  322. end
  323. if action[:execute] == 'setCheck'
  324. checked = element.attribute('checked')
  325. if !checked
  326. element.click
  327. end
  328. elsif action[:execute] == 'setUncheck'
  329. checked = element.attribute('checked')
  330. if checked
  331. element.click
  332. end
  333. elsif action[:execute] == 'set'
  334. element.clear
  335. if action[:value] == '###stack###'
  336. element.send_keys( @stack )
  337. else
  338. element.send_keys( action[:value] )
  339. end
  340. elsif action[:execute] == 'sendkey'
  341. element.send_keys( action[:value] )
  342. elsif action[:execute] == 'select'
  343. dropdown = Selenium::WebDriver::Support::Select.new(element)
  344. dropdown.select_by(:text, action[:value])
  345. elsif action[:execute] == 'click'
  346. if element.class == Array
  347. element.each {|item|
  348. item.click
  349. }
  350. else
  351. element.click
  352. end
  353. elsif action[:execute] == 'accept'
  354. element.accept
  355. elsif action[:execute] == 'dismiss'
  356. element.dismiss
  357. elsif action[:execute] == 'send_key'
  358. element.send_keys action[:value]
  359. elsif action[:execute] == 'match'
  360. if action[:css] =~ /select/
  361. dropdown = Selenium::WebDriver::Support::Select.new(element)
  362. success = false
  363. if dropdown.selected_options
  364. dropdown.selected_options.each {|option|
  365. if option.text == action[:value]
  366. success = true
  367. end
  368. }
  369. end
  370. if action[:match_result]
  371. if success
  372. assert( true, "(#{test[:name]}) matching '#{action[:value]}' in select list" )
  373. else
  374. assert( false, "(#{test[:name]}) not matching '#{action[:value]}' in select list" )
  375. end
  376. else
  377. if success
  378. assert( false, "(#{test[:name]}) not matching '#{action[:value]}' in select list" )
  379. else
  380. assert( true, "(#{test[:name]}) matching '#{action[:value]}' in select list" )
  381. end
  382. end
  383. else
  384. if action[:css] =~ /(input|textarea)/i
  385. text = element.attribute('value')
  386. else
  387. text = element.text
  388. end
  389. if action[:value] == '###stack###'
  390. action[:value] = @stack
  391. end
  392. match = false
  393. if action[:no_quote]
  394. if text =~ /#{action[:value]}/
  395. if $1
  396. @stack = $1
  397. end
  398. match = $1 || true
  399. end
  400. else
  401. if text =~ /#{Regexp.quote(action[:value])}/
  402. match = true
  403. end
  404. end
  405. if match
  406. if action[:match_result]
  407. assert( true, "(#{test[:name]}) matching '#{action[:value]}' in content '#{text}'" )
  408. else
  409. assert( false, "(#{test[:name]}) matching '#{action[:value]}' in content '#{text}' but should not!" )
  410. end
  411. else
  412. if !action[:match_result]
  413. assert( true, "(#{test[:name]}) not matching '#{action[:value]}' in content '#{text}'" )
  414. else
  415. assert( false, "(#{test[:name]}) not matching '#{action[:value]}' in content '#{text}' but should not!" )
  416. end
  417. end
  418. end
  419. elsif action[:execute] == 'check'
  420. elsif action[:execute] == 'js'
  421. else
  422. assert( false, "(#{test[:name]}) unknow action '#{action[:execute]}'" )
  423. end
  424. end
  425. end