browserstack-webdriver 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (202) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +791 -0
  3. data/README.md +31 -0
  4. data/build.desc +334 -0
  5. data/lib/selenium-client.rb +2 -0
  6. data/lib/selenium-webdriver.rb +1 -0
  7. data/lib/selenium/client.rb +37 -0
  8. data/lib/selenium/client/base.rb +132 -0
  9. data/lib/selenium/client/driver.rb +10 -0
  10. data/lib/selenium/client/errors.rb +9 -0
  11. data/lib/selenium/client/extensions.rb +118 -0
  12. data/lib/selenium/client/idiomatic.rb +488 -0
  13. data/lib/selenium/client/javascript_expression_builder.rb +116 -0
  14. data/lib/selenium/client/javascript_frameworks/jquery.rb +13 -0
  15. data/lib/selenium/client/javascript_frameworks/prototype.rb +13 -0
  16. data/lib/selenium/client/legacy_driver.rb +1720 -0
  17. data/lib/selenium/client/protocol.rb +104 -0
  18. data/lib/selenium/client/selenium_helper.rb +34 -0
  19. data/lib/selenium/rake/server_task.rb +157 -0
  20. data/lib/selenium/server.rb +248 -0
  21. data/lib/selenium/webdriver.rb +71 -0
  22. data/lib/selenium/webdriver/android.rb +9 -0
  23. data/lib/selenium/webdriver/android/bridge.rb +47 -0
  24. data/lib/selenium/webdriver/chrome.rb +26 -0
  25. data/lib/selenium/webdriver/chrome/bridge.rb +120 -0
  26. data/lib/selenium/webdriver/chrome/profile.rb +90 -0
  27. data/lib/selenium/webdriver/chrome/service.rb +75 -0
  28. data/lib/selenium/webdriver/common.rb +44 -0
  29. data/lib/selenium/webdriver/common/action_builder.rb +352 -0
  30. data/lib/selenium/webdriver/common/alert.rb +30 -0
  31. data/lib/selenium/webdriver/common/bridge_helper.rb +67 -0
  32. data/lib/selenium/webdriver/common/core_ext/base64.rb +9 -0
  33. data/lib/selenium/webdriver/common/core_ext/dir.rb +42 -0
  34. data/lib/selenium/webdriver/common/core_ext/string.rb +5 -0
  35. data/lib/selenium/webdriver/common/driver.rb +301 -0
  36. data/lib/selenium/webdriver/common/driver_extensions/has_browser_connection.rb +17 -0
  37. data/lib/selenium/webdriver/common/driver_extensions/has_input_devices.rb +39 -0
  38. data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +25 -0
  39. data/lib/selenium/webdriver/common/driver_extensions/has_remote_status.rb +13 -0
  40. data/lib/selenium/webdriver/common/driver_extensions/has_session_id.rb +22 -0
  41. data/lib/selenium/webdriver/common/driver_extensions/has_touch_screen.rb +19 -0
  42. data/lib/selenium/webdriver/common/driver_extensions/has_web_storage.rb +22 -0
  43. data/lib/selenium/webdriver/common/driver_extensions/rotatable.rb +45 -0
  44. data/lib/selenium/webdriver/common/driver_extensions/takes_screenshot.rb +43 -0
  45. data/lib/selenium/webdriver/common/driver_extensions/uploads_files.rb +46 -0
  46. data/lib/selenium/webdriver/common/element.rb +293 -0
  47. data/lib/selenium/webdriver/common/error.rb +207 -0
  48. data/lib/selenium/webdriver/common/file_reaper.rb +47 -0
  49. data/lib/selenium/webdriver/common/html5/local_storage.rb +42 -0
  50. data/lib/selenium/webdriver/common/html5/location.rb +0 -0
  51. data/lib/selenium/webdriver/common/html5/session_storage.rb +44 -0
  52. data/lib/selenium/webdriver/common/html5/shared_web_storage.rb +42 -0
  53. data/lib/selenium/webdriver/common/json_helper.rb +34 -0
  54. data/lib/selenium/webdriver/common/keyboard.rb +55 -0
  55. data/lib/selenium/webdriver/common/keys.rb +109 -0
  56. data/lib/selenium/webdriver/common/log_entry.rb +29 -0
  57. data/lib/selenium/webdriver/common/logs.rb +23 -0
  58. data/lib/selenium/webdriver/common/mouse.rb +72 -0
  59. data/lib/selenium/webdriver/common/navigation.rb +43 -0
  60. data/lib/selenium/webdriver/common/options.rb +136 -0
  61. data/lib/selenium/webdriver/common/platform.rb +218 -0
  62. data/lib/selenium/webdriver/common/port_prober.rb +42 -0
  63. data/lib/selenium/webdriver/common/profile_helper.rb +67 -0
  64. data/lib/selenium/webdriver/common/proxy.rb +149 -0
  65. data/lib/selenium/webdriver/common/search_context.rb +92 -0
  66. data/lib/selenium/webdriver/common/socket_poller.rb +105 -0
  67. data/lib/selenium/webdriver/common/target_locator.rb +81 -0
  68. data/lib/selenium/webdriver/common/timeouts.rb +38 -0
  69. data/lib/selenium/webdriver/common/touch_action_builder.rb +64 -0
  70. data/lib/selenium/webdriver/common/touch_screen.rb +105 -0
  71. data/lib/selenium/webdriver/common/wait.rb +63 -0
  72. data/lib/selenium/webdriver/common/window.rb +104 -0
  73. data/lib/selenium/webdriver/common/zipper.rb +82 -0
  74. data/lib/selenium/webdriver/firefox.rb +37 -0
  75. data/lib/selenium/webdriver/firefox/binary.rb +158 -0
  76. data/lib/selenium/webdriver/firefox/bridge.rb +70 -0
  77. data/lib/selenium/webdriver/firefox/extension.rb +52 -0
  78. data/lib/selenium/webdriver/firefox/launcher.rb +106 -0
  79. data/lib/selenium/webdriver/firefox/profile.rb +263 -0
  80. data/lib/selenium/webdriver/firefox/profiles_ini.rb +62 -0
  81. data/lib/selenium/webdriver/firefox/socket_lock.rb +61 -0
  82. data/lib/selenium/webdriver/firefox/util.rb +29 -0
  83. data/lib/selenium/webdriver/ie.rb +19 -0
  84. data/lib/selenium/webdriver/ie/bridge.rb +68 -0
  85. data/lib/selenium/webdriver/ie/server.rb +86 -0
  86. data/lib/selenium/webdriver/iphone.rb +9 -0
  87. data/lib/selenium/webdriver/iphone/bridge.rb +45 -0
  88. data/lib/selenium/webdriver/opera.rb +24 -0
  89. data/lib/selenium/webdriver/opera/bridge.rb +112 -0
  90. data/lib/selenium/webdriver/opera/service.rb +49 -0
  91. data/lib/selenium/webdriver/phantomjs.rb +22 -0
  92. data/lib/selenium/webdriver/phantomjs/bridge.rb +59 -0
  93. data/lib/selenium/webdriver/phantomjs/service.rb +90 -0
  94. data/lib/selenium/webdriver/remote.rb +22 -0
  95. data/lib/selenium/webdriver/remote/bridge.rb +644 -0
  96. data/lib/selenium/webdriver/remote/capabilities.rb +267 -0
  97. data/lib/selenium/webdriver/remote/commands.rb +193 -0
  98. data/lib/selenium/webdriver/remote/http/common.rb +74 -0
  99. data/lib/selenium/webdriver/remote/http/curb.rb +79 -0
  100. data/lib/selenium/webdriver/remote/http/default.rb +139 -0
  101. data/lib/selenium/webdriver/remote/http/persistent.rb +38 -0
  102. data/lib/selenium/webdriver/remote/response.rb +97 -0
  103. data/lib/selenium/webdriver/remote/server_error.rb +17 -0
  104. data/lib/selenium/webdriver/safari.rb +46 -0
  105. data/lib/selenium/webdriver/safari/bridge.rb +110 -0
  106. data/lib/selenium/webdriver/safari/browser.rb +20 -0
  107. data/lib/selenium/webdriver/safari/extension.rb +120 -0
  108. data/lib/selenium/webdriver/safari/server.rb +145 -0
  109. data/lib/selenium/webdriver/support.rb +5 -0
  110. data/lib/selenium/webdriver/support/abstract_event_listener.rb +28 -0
  111. data/lib/selenium/webdriver/support/block_event_listener.rb +17 -0
  112. data/lib/selenium/webdriver/support/color.rb +110 -0
  113. data/lib/selenium/webdriver/support/event_firing_bridge.rb +112 -0
  114. data/lib/selenium/webdriver/support/select.rb +293 -0
  115. data/ruby.iml +13 -0
  116. data/spec/integration/selenium/client/api/backward_compatible_api_spec.rb +22 -0
  117. data/spec/integration/selenium/client/api/browser_xpath_library_spec.rb +17 -0
  118. data/spec/integration/selenium/client/api/click_spec.rb +39 -0
  119. data/spec/integration/selenium/client/api/cookie_spec.rb +39 -0
  120. data/spec/integration/selenium/client/api/element_spec.rb +14 -0
  121. data/spec/integration/selenium/client/api/highlight_located_element_spec.rb +19 -0
  122. data/spec/integration/selenium/client/api/retrieve_last_remote_control_logs_spec.rb +33 -0
  123. data/spec/integration/selenium/client/api/screenshot_spec.rb +31 -0
  124. data/spec/integration/selenium/client/api/select_window_spec.rb +46 -0
  125. data/spec/integration/selenium/client/api/start_stop_spec.rb +9 -0
  126. data/spec/integration/selenium/client/api/wait_for_ajax_spec.rb +27 -0
  127. data/spec/integration/selenium/client/api/wait_for_element_spec.rb +56 -0
  128. data/spec/integration/selenium/client/api/wait_for_field_value_spec.rb +52 -0
  129. data/spec/integration/selenium/client/api/wait_for_text_spec.rb +98 -0
  130. data/spec/integration/selenium/client/api/webdriver_backed_spec.rb +21 -0
  131. data/spec/integration/selenium/client/sample-app/public/jquery-1.3.2.js +4376 -0
  132. data/spec/integration/selenium/client/sample-app/public/jquery.html +55 -0
  133. data/spec/integration/selenium/client/sample-app/public/prototype-1.6.0.3.js +4320 -0
  134. data/spec/integration/selenium/client/sample-app/public/prototype.html +59 -0
  135. data/spec/integration/selenium/client/sample-app/sample_app.rb +32 -0
  136. data/spec/integration/selenium/client/spec_helper.rb +139 -0
  137. data/spec/integration/selenium/webdriver/app_cache_spec.rb +47 -0
  138. data/spec/integration/selenium/webdriver/browser_connection_spec.rb +20 -0
  139. data/spec/integration/selenium/webdriver/chrome/driver_spec.rb +28 -0
  140. data/spec/integration/selenium/webdriver/chrome/profile_spec.rb +63 -0
  141. data/spec/integration/selenium/webdriver/driver_spec.rb +266 -0
  142. data/spec/integration/selenium/webdriver/element_spec.rb +191 -0
  143. data/spec/integration/selenium/webdriver/error_spec.rb +30 -0
  144. data/spec/integration/selenium/webdriver/firefox/driver_spec.rb +21 -0
  145. data/spec/integration/selenium/webdriver/firefox/profile_spec.rb +141 -0
  146. data/spec/integration/selenium/webdriver/keyboard_spec.rb +57 -0
  147. data/spec/integration/selenium/webdriver/location_spec.rb +29 -0
  148. data/spec/integration/selenium/webdriver/mouse_spec.rb +57 -0
  149. data/spec/integration/selenium/webdriver/navigation_spec.rb +46 -0
  150. data/spec/integration/selenium/webdriver/opera/driver_spec.rb +47 -0
  151. data/spec/integration/selenium/webdriver/options_spec.rb +77 -0
  152. data/spec/integration/selenium/webdriver/remote/driver_spec.rb +19 -0
  153. data/spec/integration/selenium/webdriver/remote/element_spec.rb +26 -0
  154. data/spec/integration/selenium/webdriver/spec_helper.rb +36 -0
  155. data/spec/integration/selenium/webdriver/spec_support.rb +12 -0
  156. data/spec/integration/selenium/webdriver/spec_support/guards.rb +110 -0
  157. data/spec/integration/selenium/webdriver/spec_support/helpers.rb +51 -0
  158. data/spec/integration/selenium/webdriver/spec_support/rack_server.rb +123 -0
  159. data/spec/integration/selenium/webdriver/spec_support/test_environment.rb +239 -0
  160. data/spec/integration/selenium/webdriver/sql_database_spec.rb +59 -0
  161. data/spec/integration/selenium/webdriver/storage_spec.rb +96 -0
  162. data/spec/integration/selenium/webdriver/target_locator_spec.rb +186 -0
  163. data/spec/integration/selenium/webdriver/timeout_spec.rb +69 -0
  164. data/spec/integration/selenium/webdriver/touch_spec.rb +176 -0
  165. data/spec/integration/selenium/webdriver/window_spec.rb +70 -0
  166. data/spec/integration/selenium/webdriver/zipper_spec.rb +66 -0
  167. data/spec/unit/selenium/client/base_spec.rb +239 -0
  168. data/spec/unit/selenium/client/extensions_spec.rb +174 -0
  169. data/spec/unit/selenium/client/idiomatic_spec.rb +500 -0
  170. data/spec/unit/selenium/client/javascript_expression_builder_spec.rb +79 -0
  171. data/spec/unit/selenium/client/javascript_frameworks/jquery_spec.rb +10 -0
  172. data/spec/unit/selenium/client/javascript_frameworks/prototype_spec.rb +10 -0
  173. data/spec/unit/selenium/client/protocol_spec.rb +124 -0
  174. data/spec/unit/selenium/client/selenium_helper_spec.rb +56 -0
  175. data/spec/unit/selenium/client/spec_helper.rb +24 -0
  176. data/spec/unit/selenium/rake/task_spec.rb +79 -0
  177. data/spec/unit/selenium/server_spec.rb +150 -0
  178. data/spec/unit/selenium/webdriver/action_builder_spec.rb +97 -0
  179. data/spec/unit/selenium/webdriver/android/bridge_spec.rb +43 -0
  180. data/spec/unit/selenium/webdriver/chrome/bridge_spec.rb +137 -0
  181. data/spec/unit/selenium/webdriver/chrome/profile_spec.rb +57 -0
  182. data/spec/unit/selenium/webdriver/chrome/service_spec.rb +44 -0
  183. data/spec/unit/selenium/webdriver/error_spec.rb +41 -0
  184. data/spec/unit/selenium/webdriver/firefox/bridge_spec.rb +47 -0
  185. data/spec/unit/selenium/webdriver/ie/bridge_spec.rb +91 -0
  186. data/spec/unit/selenium/webdriver/iphone/bridge_spec.rb +42 -0
  187. data/spec/unit/selenium/webdriver/log_entry_spec.rb +11 -0
  188. data/spec/unit/selenium/webdriver/opera/bridge_spec.rb +44 -0
  189. data/spec/unit/selenium/webdriver/phantomjs/bridge_spec.rb +55 -0
  190. data/spec/unit/selenium/webdriver/proxy_spec.rb +106 -0
  191. data/spec/unit/selenium/webdriver/remote/bridge_spec.rb +16 -0
  192. data/spec/unit/selenium/webdriver/remote/capabilities_spec.rb +115 -0
  193. data/spec/unit/selenium/webdriver/remote/http/common_spec.rb +24 -0
  194. data/spec/unit/selenium/webdriver/remote/http/default_spec.rb +124 -0
  195. data/spec/unit/selenium/webdriver/search_context_spec.rb +61 -0
  196. data/spec/unit/selenium/webdriver/socket_poller_spec.rb +68 -0
  197. data/spec/unit/selenium/webdriver/spec_helper.rb +27 -0
  198. data/spec/unit/selenium/webdriver/support/color_spec.rb +119 -0
  199. data/spec/unit/selenium/webdriver/support/event_firing_spec.rb +111 -0
  200. data/spec/unit/selenium/webdriver/support/select_spec.rb +290 -0
  201. data/spec/unit/selenium/webdriver/wait_spec.rb +49 -0
  202. metadata +370 -0
@@ -0,0 +1,104 @@
1
+ module Selenium
2
+ module Client
3
+
4
+ HTTP_HEADERS = { 'Content-Type' => 'application/x-www-form-urlencoded; charset=utf-8' }
5
+
6
+ # Module in charge of handling Selenium over-the-wire HTTP protocol
7
+ module Protocol
8
+ attr_reader :session_id
9
+
10
+ def remote_control_command(verb, args=[])
11
+ timeout(@default_timeout_in_seconds) do
12
+ status, response = http_post(http_request_for(verb, args))
13
+ raise CommandError, response unless status == "OK"
14
+ response[3..-1] # strip "OK," from response
15
+ end
16
+ end
17
+
18
+ def string_command(verb, args=[])
19
+ remote_control_command(verb, args)
20
+ end
21
+
22
+ def string_array_command(verb, args=[])
23
+ csv = string_command(verb, args)
24
+ token = ""
25
+ tokens = []
26
+ escape = false
27
+ csv.split(//).each do |letter|
28
+ if escape
29
+ token += letter
30
+ escape = false
31
+ next
32
+ end
33
+ case letter
34
+ when '\\'
35
+ escape = true
36
+ when ','
37
+ tokens << token
38
+ token = ""
39
+ else
40
+ token += letter
41
+ end
42
+ end
43
+ tokens << token
44
+ return tokens
45
+ end
46
+
47
+ def number_command(verb, args)
48
+ string_command verb, args
49
+ end
50
+
51
+ def number_array_command(verb, args)
52
+ string_array_command verb, args
53
+ end
54
+
55
+ def boolean_command(verb, args=[])
56
+ parse_boolean_value string_command(verb, args)
57
+ end
58
+
59
+ def boolean_array_command(verb, args)
60
+ string_array_command(verb, args).collect {|value| parse_boolean_value(value)}
61
+ end
62
+
63
+ protected
64
+
65
+ def parse_boolean_value(value)
66
+ if ("true" == value)
67
+ return true
68
+ elsif ("false" == value)
69
+ return false
70
+ end
71
+ raise ProtocolError, "Invalid Selenese boolean value that is neither 'true' nor 'false': got '#{value}'"
72
+ end
73
+
74
+ def http_request_for(verb, args)
75
+ data = "cmd=#{CGI::escape(verb)}"
76
+ args.each_with_index do |arg, index|
77
+ data << "&#{index.succ}=#{CGI::escape(arg.to_s)}"
78
+ end
79
+ data << "&sessionId=#{session_id}" unless session_id.nil?
80
+ data
81
+ end
82
+
83
+ def http_post(data)
84
+ start = Time.now
85
+ called_from = caller.detect{|line| line !~ /(selenium-client|vendor|usr\/lib\/ruby|\(eval\))/i}
86
+ http = Net::HTTP.new(@host, @port)
87
+ http.open_timeout = default_timeout_in_seconds
88
+ http.read_timeout = default_timeout_in_seconds
89
+ response = http.post('/selenium-server/driver/', data, HTTP_HEADERS)
90
+ if response.body !~ /^OK/
91
+ puts "#{start} selenium-client received failure from selenium server:"
92
+ puts "requested:"
93
+ puts "\t" + CGI::unescape(data.split('&').join("\n\t"))
94
+ puts "received:"
95
+ puts "\t#{response.body.inspect}"
96
+ puts "\tcalled from #{called_from}"
97
+ end
98
+ [ response.body[0..1], response.body ]
99
+ end
100
+
101
+ end
102
+
103
+ end
104
+ end
@@ -0,0 +1,34 @@
1
+ # Defines a mixin module that you can use to write Selenium tests
2
+ # without typing "@selenium." in front of every command. Every
3
+ # call to a missing method will be automatically sent to the @selenium
4
+ # object.
5
+ module Selenium
6
+ module Client
7
+
8
+ module SeleniumHelper
9
+
10
+ # Overrides default open method to actually delegates to @selenium
11
+ def open(url)
12
+ @selenium.open url
13
+ end
14
+
15
+ # Overrides default type method to actually delegates to @selenium
16
+ def type(locator, value)
17
+ @selenium.type locator, value
18
+ end
19
+
20
+ # Overrides default select method to actually delegates to @selenium
21
+ def select(input_locator, option_locator)
22
+ @selenium.select input_locator, option_locator
23
+ end
24
+
25
+ # Delegates to @selenium on method missing
26
+ def method_missing(method_name, *args)
27
+ return super unless @selenium.respond_to?(method_name)
28
+
29
+ @selenium.send(method_name, *args)
30
+ end
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,157 @@
1
+ require 'selenium/server'
2
+ require 'rake'
3
+
4
+ module Selenium
5
+ module Rake
6
+
7
+ class MissingJarFileError < StandardError
8
+ end
9
+
10
+ #
11
+ # Defines rake tasks for starting, stopping and restarting the Selenium server.
12
+ #
13
+ # Usage:
14
+ #
15
+ # require 'selenium/rake/server_task'
16
+ #
17
+ # Selenium::Rake::ServerTask.new do |t|
18
+ # t.jar = "/path/to/selenium-server-standalone.jar"
19
+ # t.port = 4444
20
+ # t.opts = %w[-some options]
21
+ # end
22
+ #
23
+ # Alternatively, you can have the task download a specific version of the server:
24
+ #
25
+ # Selenium::Rake::ServerTask.new(:server) do |t|
26
+ # t.version = '2.6.0'
27
+ # end
28
+ #
29
+ # or the latest version
30
+ #
31
+ # Selenium::Rake::ServerTask.new(:server) do |t|
32
+ # t.version = :latest
33
+ # end
34
+ #
35
+ #
36
+ # Tasks defined:
37
+ #
38
+ # rake selenium:server:start
39
+ # rake selenium:server:stop
40
+ # rake selenium:server:restart
41
+ #
42
+
43
+ class ServerTask
44
+ include ::Rake::DSL if defined?(::Rake::DSL)
45
+
46
+ #
47
+ # Path to the selenium server jar
48
+ #
49
+
50
+ attr_accessor :jar
51
+
52
+ #
53
+ # Port to use for the server.
54
+ # Default: 4444
55
+ #
56
+ #
57
+
58
+ attr_accessor :port
59
+
60
+ #
61
+ # Timeout in seconds for the server to start/stop.
62
+ # Default: 30
63
+ #
64
+
65
+ attr_accessor :timeout
66
+
67
+ #
68
+ # Whether we should detach from the server process.
69
+ # Default: true
70
+ #
71
+
72
+ attr_accessor :background
73
+ alias_method :background?, :background
74
+
75
+ #
76
+ # Configure logging. Pass a log file path or a boolean.
77
+ # Default: true
78
+ #
79
+ # true - log to stdout/stderr
80
+ # false - no logging
81
+ # String - log to the specified file
82
+ #
83
+
84
+ attr_accessor :log
85
+
86
+ #
87
+ # Add additional options passed to the server jar.
88
+ #
89
+
90
+ attr_accessor :opts
91
+
92
+ #
93
+ # Specify the version of the server jar to download
94
+ #
95
+
96
+ attr_accessor :version
97
+
98
+
99
+ def initialize(prefix = "selenium:server")
100
+ @jar = nil
101
+ @prefix = prefix
102
+ @port = 4444
103
+ @timeout = 30
104
+ @background = true
105
+ @log = true
106
+ @opts = []
107
+ @version = nil
108
+
109
+ yield self if block_given?
110
+
111
+ if @version
112
+ @jar = Selenium::Server.download(@version)
113
+ end
114
+
115
+ unless @jar
116
+ raise MissingJarFileError, "must provide path to the selenium server jar"
117
+ end
118
+
119
+ @server = Selenium::Server.new(@jar, :port => @port,
120
+ :timeout => @timeout,
121
+ :background => @background,
122
+ :log => @log )
123
+
124
+ @server << @opts
125
+
126
+ define_start_task
127
+ define_stop_task
128
+ define_restart_task
129
+ end
130
+
131
+ private
132
+
133
+ def define_start_task
134
+ desc "Start the Selenium server"
135
+ task "#{@prefix}:start" do
136
+ @server.start
137
+ end
138
+ end
139
+
140
+ def define_stop_task
141
+ desc 'Stop the Selenium server'
142
+ task "#{@prefix}:stop" do
143
+ @server.stop
144
+ end
145
+ end
146
+
147
+ def define_restart_task
148
+ desc 'Restart the Selenium server'
149
+ task "#{@prefix}:restart" do
150
+ @server.stop
151
+ @server.start
152
+ end
153
+ end
154
+
155
+ end # ServerTask
156
+ end # Rake
157
+ end # Selenium
@@ -0,0 +1,248 @@
1
+ require 'childprocess'
2
+ require 'selenium/webdriver/common/socket_poller'
3
+ require 'net/http'
4
+
5
+ module Selenium
6
+
7
+ #
8
+ # Wraps the remote server jar
9
+ #
10
+ # Usage:
11
+ #
12
+ # server = Selenium::Server.new('/path/to/selenium-server-standalone.jar')
13
+ # server.start
14
+ #
15
+ # Automatically download the given version:
16
+ #
17
+ # server = Selenium::Server.get '2.6.0'
18
+ # server.start
19
+ #
20
+ # or the latest version:
21
+ #
22
+ # server = Selenium::Server.get :latest
23
+ # server.start
24
+ #
25
+ # Run the server in the background:
26
+ #
27
+ # server = Selenium::Server.new(jar, :background => true)
28
+ # server.start
29
+ #
30
+ # Add additional arguments:
31
+ #
32
+ # server = Selenium::Server.new(jar)
33
+ # server << ["--additional", "args"]
34
+ # server.start
35
+ #
36
+
37
+ class Server
38
+ class Error < StandardError; end
39
+
40
+ CL_RESET = WebDriver::Platform.windows? ? '' : "\r\e[0K"
41
+
42
+ def self.get(required_version, opts = {})
43
+ new(download(required_version), opts)
44
+ end
45
+
46
+ #
47
+ # Download the given version of the selenium-server-standalone jar.
48
+ #
49
+
50
+ def self.download(required_version)
51
+ required_version = latest if required_version == :latest
52
+ download_file_name = "selenium-server-standalone-#{required_version}.jar"
53
+
54
+ if File.exists? download_file_name
55
+ return download_file_name
56
+ end
57
+
58
+ begin
59
+ open(download_file_name, "wb") do |destination|
60
+ net_http.start("selenium.googlecode.com") do |http|
61
+ resp = http.request_get("/files/#{download_file_name}") do |response|
62
+ total = response.content_length
63
+ progress = 0
64
+ segment_count = 0
65
+
66
+ response.read_body do |segment|
67
+ progress += segment.length
68
+ segment_count += 1
69
+
70
+ if segment_count % 15 == 0
71
+ percent = (progress.to_f / total.to_f) * 100
72
+ print "#{CL_RESET}Downloading #{download_file_name}: #{percent.to_i}% (#{progress} / #{total})"
73
+ segment_count = 0
74
+ end
75
+
76
+ destination.write(segment)
77
+ end
78
+ end
79
+
80
+ unless resp.kind_of? Net::HTTPSuccess
81
+ raise Error, "#{resp.code} for #{download_file_name}"
82
+ end
83
+ end
84
+ end
85
+ rescue
86
+ FileUtils.rm download_file_name if File.exists? download_file_name
87
+ raise
88
+ end
89
+
90
+ download_file_name
91
+ end
92
+
93
+ #
94
+ # Ask Google Code what the latest selenium-server-standalone version is.
95
+ #
96
+
97
+ def self.latest
98
+ net_http.start("code.google.com") do |http|
99
+ resp = http.get("/p/selenium/downloads/list")
100
+ resp.body.to_s[/selenium-server-standalone-(\d+.\d+.\d+).jar/, 1]
101
+ end
102
+ end
103
+
104
+ #
105
+ # The server port
106
+ #
107
+
108
+ attr_accessor :port
109
+
110
+ #
111
+ # The server timeout
112
+ #
113
+
114
+ attr_accessor :timeout
115
+
116
+ #
117
+ # Whether to launch the server in the background
118
+ #
119
+
120
+ attr_accessor :background
121
+
122
+ #
123
+ # Path to log file, or 'true' for stdout.
124
+ #
125
+
126
+ attr_accessor :log
127
+
128
+ #
129
+ # @param [String] jar Path to the server jar.
130
+ # @param [Hash] opts the options to create the server process with
131
+ #
132
+ # @option opts [Integer] :port Port the server should listen on (default: 4444).
133
+ # @option opts [Integer] :timeout Seconds to wait for server launch/shutdown (default: 30)
134
+ # @option opts [true,false] :background Run the server in the background (default: false)
135
+ # @option opts [true,false,String] :log Either a path to a log file,
136
+ # or true to pass server log to stdout.
137
+ # @raise [Errno::ENOENT] if the jar file does not exist
138
+ #
139
+
140
+ def initialize(jar, opts = {})
141
+ raise Errno::ENOENT, jar unless File.exist?(jar)
142
+
143
+ @jar = jar
144
+ @host = "127.0.0.1"
145
+ @port = opts.fetch(:port, 4444)
146
+ @timeout = opts.fetch(:timeout, 30)
147
+ @background = opts.fetch(:background, false)
148
+ @log = opts[:log]
149
+
150
+ @additional_args = []
151
+ end
152
+
153
+ def start
154
+ process.start
155
+ poll_for_service
156
+
157
+ process.wait unless @background
158
+ end
159
+
160
+ def stop
161
+ begin
162
+ Net::HTTP.get(@host, "/selenium-server/driver/?cmd=shutDownSeleniumServer", @port)
163
+ rescue Errno::ECONNREFUSED
164
+ end
165
+
166
+ stop_process if @process
167
+ poll_for_shutdown
168
+
169
+ @log_file.close if @log_file
170
+ end
171
+
172
+ def webdriver_url
173
+ "http://#{@host}:#{@port}/wd/hub"
174
+ end
175
+
176
+ def <<(arg)
177
+ if arg.kind_of?(Array)
178
+ @additional_args += arg
179
+ else
180
+ @additional_args << arg.to_s
181
+ end
182
+ end
183
+
184
+ private
185
+
186
+ def self.net_http
187
+ http_proxy = ENV['http_proxy'] || ENV['HTTP_PROXY']
188
+
189
+ if http_proxy
190
+ http_proxy = "http://#{http_proxy}" unless http_proxy.start_with?("http://")
191
+ uri = URI.parse(http_proxy)
192
+
193
+ Net::HTTP::Proxy(uri.host, uri.port)
194
+ else
195
+ Net::HTTP
196
+ end
197
+ end
198
+
199
+ def stop_process
200
+ return unless @process.alive?
201
+
202
+ begin
203
+ @process.poll_for_exit(5)
204
+ rescue ChildProcess::TimeoutError
205
+ @process.stop
206
+ end
207
+ rescue Errno::ECHILD
208
+ # already dead
209
+ ensure
210
+ @process = nil
211
+ end
212
+
213
+ def process
214
+ @process ||= (
215
+ cp = ChildProcess.build("java", "-jar", @jar, "-port", @port.to_s, *@additional_args)
216
+ io = cp.io
217
+
218
+ if @log.kind_of?(String)
219
+ @log_file = File.open(@log, "w")
220
+ io.stdout = io.stderr = @log_file
221
+ elsif @log
222
+ io.inherit!
223
+ end
224
+
225
+ cp.detach = @background
226
+
227
+ cp
228
+ )
229
+ end
230
+
231
+ def poll_for_service
232
+ unless socket.connected?
233
+ raise Error, "remote server not launched in #{@timeout} seconds"
234
+ end
235
+ end
236
+
237
+ def poll_for_shutdown
238
+ unless socket.closed?
239
+ raise Error, "remote server not stopped in #{@timeout} seconds"
240
+ end
241
+ end
242
+
243
+ def socket
244
+ @socket ||= WebDriver::SocketPoller.new(@host, @port, @timeout)
245
+ end
246
+
247
+ end # Server
248
+ end # Selenium