browser_test_helper.rb 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  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. instance.find_element( { :css => '#login button' } ).click
  217. sleep 4
  218. return
  219. elsif action[:execute] == 'logout'
  220. instance.find_element( { :css => 'a[href="#current_user"]' } ).click
  221. sleep 0.1
  222. instance.find_element( { :css => 'a[href="#logout"]' } ).click
  223. (1..6).each {|loop|
  224. login = instance.find_element( { :css => '#login' } )
  225. if login
  226. assert( true, "(#{test[:name]}) logout" )
  227. return
  228. end
  229. }
  230. assert( false, "(#{test[:name]}) no login box found!" )
  231. return
  232. elsif action[:execute] == 'watch_for'
  233. text = ''
  234. (1..36).each { |loop|
  235. element = instance.find_element( { :css => action[:area] } )
  236. text = element.text
  237. if text =~ /#{action[:value]}/i
  238. assert( true, "(#{test[:name]}) '#{action[:value]}' found in '#{text}'" )
  239. return
  240. end
  241. sleep 0.33
  242. }
  243. assert( false, "(#{test[:name]}) '#{action[:value]}' found in '#{text}'" )
  244. return
  245. elsif action[:execute] == 'create_user'
  246. instance.find_element( { :css => 'a[href="#manage"]' } ).click
  247. instance.find_element( { :css => 'a[href="#manage/users"]' } ).click
  248. sleep 2
  249. instance.find_element( { :css => 'a[data-type="new"]' } ).click
  250. sleep 2
  251. element = instance.find_element( { :css => '.modal input[name=login]' } )
  252. element.clear
  253. element.send_keys( action[:login] )
  254. element = instance.find_element( { :css => '.modal input[name=firstname]' } )
  255. element.clear
  256. element.send_keys( action[:firstname] )
  257. element = instance.find_element( { :css => '.modal input[name=lastname]' } )
  258. element.clear
  259. element.send_keys( action[:lastname] )
  260. element = instance.find_element( { :css => '.modal input[name=email]' } )
  261. element.clear
  262. element.send_keys( action[:email] )
  263. element = instance.find_element( { :css => '.modal input[name=password]' } )
  264. element.clear
  265. element.send_keys( action[:password] )
  266. element = instance.find_element( { :css => '.modal input[name=password_confirm]' } )
  267. element.clear
  268. element.send_keys( action[:password] )
  269. instance.find_element( { :css => '.modal input[name="role_ids"][value="3"]' } ).click
  270. instance.find_element( { :css => '.modal button.submit' } ).click
  271. (1..14).each {|loop|
  272. element = instance.find_element( { :css => 'body' } )
  273. text = element.text
  274. if text =~ /#{Regexp.quote(action[:lastname])}/
  275. assert( true, "(#{test[:name]}) user created" )
  276. return
  277. end
  278. sleep 0.5
  279. }
  280. assert( true, "(#{test[:name]}) user creation failed" )
  281. return
  282. elsif action[:execute] == 'create_ticket'
  283. instance.find_element( { :css => 'a[href="#new"]' } ).click
  284. instance.find_element( { :css => 'a[href="#ticket/create/call_inbound"]' } ).click
  285. element = instance.find_element( { :css => '.active .ticket-create' } )
  286. if !element
  287. assert( false, "(#{test[:name]}) no ticket create screen found!" )
  288. return
  289. end
  290. sleep 2
  291. element = instance.find_element( { :css => '.active .ticket-create input[name="customer_id_autocompletion"]' } )
  292. element.clear
  293. element.send_keys( 'nico*' )
  294. sleep 4
  295. element = instance.find_element( { :css => '.active .ticket-create input[name="customer_id_autocompletion"]' } )
  296. element.send_keys( :arrow_down )
  297. sleep 0.2
  298. element = instance.find_element( { :css => '.active .ticket-create input[name="customer_id_autocompletion"]' } )
  299. element.send_keys( :tab )
  300. sleep 0.1
  301. element = instance.find_element( { :css => '.active .ticket-create select[name="group_id"]' } )
  302. dropdown = Selenium::WebDriver::Support::Select.new(element)
  303. dropdown.select_by( :text, action[:group])
  304. sleep 0.1
  305. element = instance.find_element( { :css => '.active .ticket-create input[name="title"]' } )
  306. element.clear
  307. element.send_keys( action[:subject] )
  308. sleep 0.1
  309. element = instance.find_element( { :css => '.active .ticket-create textarea[name="body"]' } )
  310. element.clear
  311. element.send_keys( action[:body] )
  312. if action[:do_not_submit]
  313. assert( true, "(#{test[:name]}) ticket created without submit" )
  314. return
  315. end
  316. sleep 0.8
  317. instance.find_element( { :css => '.active .form-actions button[type="submit"]' } ).click
  318. sleep 1
  319. (1..14).each {|loop|
  320. if instance.current_url =~ /#{Regexp.quote('#ticket/zoom/')}/
  321. assert( true, "(#{test[:name]}) ticket created" )
  322. return
  323. end
  324. sleep 0.5
  325. }
  326. assert( false, "(#{test[:name]}) ticket creation failed, can't get zoom url" )
  327. return
  328. elsif action[:execute] == 'close_all_tasks'
  329. for i in 1..100
  330. begin
  331. element = instance.find_element( { :css => '.taskbar [data-type="close"]' } )
  332. if element
  333. element.click
  334. sleep 0.8
  335. else
  336. break
  337. end
  338. rescue
  339. break
  340. end
  341. end
  342. assert( true, "(#{test[:name]}) all tasks closed" )
  343. return
  344. elsif action[:execute] == 'navigate'
  345. instance.navigate.to( action[:to] )
  346. return
  347. elsif action[:execute] == 'reload'
  348. instance.navigate.refresh
  349. return
  350. elsif action[:execute] == 'js'
  351. result = instance.execute_script( action[:value] )
  352. elsif action[:link]
  353. if action[:link].match '###stack###'
  354. action[:link].gsub! '###stack###', @stack
  355. end
  356. element = instance.find_element( { :partial_link_text => action[:link] } )
  357. else
  358. assert( false, "(#{test[:name]}) unknow selector for '#{action[:element]}'" )
  359. end
  360. if action[:execute] == 'setCheck'
  361. checked = element.attribute('checked')
  362. if !checked
  363. element.click
  364. end
  365. elsif action[:execute] == 'setUncheck'
  366. checked = element.attribute('checked')
  367. if checked
  368. element.click
  369. end
  370. elsif action[:execute] == 'set'
  371. element.clear
  372. if action[:value] == '###stack###'
  373. element.send_keys( @stack )
  374. else
  375. element.send_keys( action[:value] )
  376. end
  377. elsif action[:execute] == 'sendkey'
  378. element.send_keys( action[:value] )
  379. elsif action[:execute] == 'select'
  380. dropdown = Selenium::WebDriver::Support::Select.new(element)
  381. dropdown.select_by(:text, action[:value])
  382. elsif action[:execute] == 'click'
  383. if element.class == Array
  384. element.each {|item|
  385. item.click
  386. }
  387. else
  388. element.click
  389. end
  390. elsif action[:execute] == 'accept'
  391. element.accept
  392. elsif action[:execute] == 'dismiss'
  393. element.dismiss
  394. elsif action[:execute] == 'send_key'
  395. element.send_keys action[:value]
  396. elsif action[:execute] == 'match'
  397. if action[:css] =~ /select/
  398. dropdown = Selenium::WebDriver::Support::Select.new(element)
  399. success = false
  400. if dropdown.selected_options
  401. dropdown.selected_options.each {|option|
  402. if option.text == action[:value]
  403. success = true
  404. end
  405. }
  406. end
  407. if action[:match_result]
  408. if success
  409. assert( true, "(#{test[:name]}) matching '#{action[:value]}' in select list" )
  410. else
  411. assert( false, "(#{test[:name]}) not matching '#{action[:value]}' in select list" )
  412. end
  413. else
  414. if success
  415. assert( false, "(#{test[:name]}) not matching '#{action[:value]}' in select list" )
  416. else
  417. assert( true, "(#{test[:name]}) matching '#{action[:value]}' in select list" )
  418. end
  419. end
  420. else
  421. if action[:css] =~ /(input|textarea)/i
  422. text = element.attribute('value')
  423. else
  424. text = element.text
  425. end
  426. if action[:value] == '###stack###'
  427. action[:value] = @stack
  428. end
  429. match = false
  430. if action[:no_quote]
  431. if text =~ /#{action[:value]}/
  432. if $1
  433. @stack = $1
  434. end
  435. match = $1 || true
  436. end
  437. else
  438. if text =~ /#{Regexp.quote(action[:value])}/
  439. match = true
  440. end
  441. end
  442. if match
  443. if action[:match_result]
  444. assert( true, "(#{test[:name]}) matching '#{action[:value]}' in content '#{text}'" )
  445. else
  446. assert( false, "(#{test[:name]}) matching '#{action[:value]}' in content '#{text}' but should not!" )
  447. end
  448. else
  449. if !action[:match_result]
  450. assert( true, "(#{test[:name]}) not matching '#{action[:value]}' in content '#{text}'" )
  451. else
  452. assert( false, "(#{test[:name]}) not matching '#{action[:value]}' in content '#{text}' but should not!" )
  453. end
  454. end
  455. end
  456. elsif action[:execute] == 'check'
  457. elsif action[:execute] == 'js'
  458. else
  459. assert( false, "(#{test[:name]}) unknow action '#{action[:execute]}'" )
  460. end
  461. end
  462. end