selenium-webdriver 0.0.29 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/CHANGES +15 -1
  2. data/lib/selenium-client.rb +2 -0
  3. data/lib/selenium/client.rb +30 -0
  4. data/lib/selenium/client/base.rb +118 -0
  5. data/lib/selenium/client/driver.rb +10 -0
  6. data/lib/selenium/client/errors.rb +9 -0
  7. data/lib/selenium/client/extensions.rb +118 -0
  8. data/lib/selenium/client/idiomatic.rb +488 -0
  9. data/lib/selenium/client/javascript_expression_builder.rb +116 -0
  10. data/lib/selenium/client/javascript_frameworks/jquery.rb +13 -0
  11. data/lib/selenium/client/javascript_frameworks/prototype.rb +13 -0
  12. data/lib/selenium/client/legacy_driver.rb +1711 -0
  13. data/lib/selenium/client/protocol.rb +104 -0
  14. data/lib/selenium/client/selenium_helper.rb +34 -0
  15. data/lib/selenium/rake/server_task.rb +131 -0
  16. data/lib/selenium/server.rb +114 -0
  17. data/lib/selenium/webdriver.rb +3 -2
  18. data/lib/selenium/webdriver/android.rb +9 -0
  19. data/lib/selenium/webdriver/android/bridge.rb +45 -0
  20. data/lib/selenium/webdriver/chrome/extension.zip +0 -0
  21. data/lib/selenium/webdriver/chrome/launcher.rb +6 -3
  22. data/lib/selenium/webdriver/common.rb +2 -0
  23. data/lib/selenium/webdriver/common/driver.rb +8 -4
  24. data/lib/selenium/webdriver/common/driver_extensions/rotatable.rb +28 -0
  25. data/lib/selenium/webdriver/common/file_reaper.rb +10 -0
  26. data/lib/selenium/webdriver/common/proxy.rb +119 -0
  27. data/lib/selenium/webdriver/common/socket_poller.rb +27 -9
  28. data/lib/selenium/webdriver/firefox/binary.rb +8 -5
  29. data/lib/selenium/webdriver/firefox/bridge.rb +2 -3
  30. data/lib/selenium/webdriver/firefox/extension.rb +17 -14
  31. data/lib/selenium/webdriver/firefox/extension/webdriver.xpi +0 -0
  32. data/lib/selenium/webdriver/firefox/launcher.rb +8 -2
  33. data/lib/selenium/webdriver/firefox/profile.rb +45 -1
  34. data/lib/selenium/webdriver/firefox/socket_lock.rb +1 -5
  35. data/lib/selenium/webdriver/ie/bridge.rb +3 -3
  36. data/lib/selenium/webdriver/ie/native/win32/InternetExplorerDriver.dll +0 -0
  37. data/lib/selenium/webdriver/ie/native/x64/InternetExplorerDriver.dll +0 -0
  38. data/lib/selenium/webdriver/iphone.rb +9 -0
  39. data/lib/selenium/webdriver/iphone/bridge.rb +34 -0
  40. data/lib/selenium/webdriver/remote/bridge.rb +0 -1
  41. data/lib/selenium/webdriver/remote/capabilities.rb +46 -13
  42. data/lib/selenium/webdriver/remote/commands.rb +3 -4
  43. data/lib/selenium/webdriver/remote/http/common.rb +1 -1
  44. data/lib/selenium/webdriver/remote/http/default.rb +7 -1
  45. metadata +42 -7
@@ -75,7 +75,7 @@ module Selenium
75
75
  def launch_chrome(server_url)
76
76
  args = [
77
77
  Platform.wrap_in_quotes_if_necessary(self.class.binary_path),
78
- "--load-extension=#{Platform.wrap_in_quotes_if_necessary tmp_extension_dir}",
78
+ "--load-extension=#{Platform.wrap_in_quotes_if_necessary(tmp_extension_dir)}",
79
79
  "--activate-on-launch",
80
80
  "--disable-hang-monitor",
81
81
  "--disable-popup-blocking",
@@ -83,7 +83,7 @@ module Selenium
83
83
  ]
84
84
 
85
85
  unless @default_profile
86
- args << "--user-data-dir=#{Platform.wrap_in_quotes_if_necessary tmp_profile_dir}"
86
+ args << "--user-data-dir=#{Platform.wrap_in_quotes_if_necessary(tmp_profile_dir)}"
87
87
  end
88
88
 
89
89
  unless @secure_ssl
@@ -92,7 +92,10 @@ module Selenium
92
92
 
93
93
  args << server_url
94
94
 
95
- @process = ChildProcess.build(*args).start
95
+ @process = ChildProcess.build(*args)
96
+ @process.io.inherit! if $DEBUG
97
+
98
+ @process.start
96
99
  end
97
100
 
98
101
  def ext_path
@@ -2,6 +2,7 @@ require "selenium/webdriver/common/core_ext/dir"
2
2
  require "selenium/webdriver/common/core_ext/string"
3
3
  require "selenium/webdriver/common/error"
4
4
  require "selenium/webdriver/common/platform"
5
+ require "selenium/webdriver/common/proxy"
5
6
  require "selenium/webdriver/common/file_reaper"
6
7
  require "selenium/webdriver/common/socket_poller"
7
8
  require "selenium/webdriver/common/zipper"
@@ -12,6 +13,7 @@ require "selenium/webdriver/common/timeouts"
12
13
  require "selenium/webdriver/common/options"
13
14
  require "selenium/webdriver/common/find"
14
15
  require "selenium/webdriver/common/driver_extensions/takes_screenshot"
16
+ require "selenium/webdriver/common/driver_extensions/rotatable"
15
17
  require "selenium/webdriver/common/keys"
16
18
  require "selenium/webdriver/common/bridge_helper"
17
19
  require "selenium/webdriver/common/driver"
@@ -34,14 +34,18 @@ module Selenium
34
34
 
35
35
  def for(browser, *args)
36
36
  bridge = case browser
37
- when :ie, :internet_explorer
38
- IE::Bridge.new(*args)
37
+ when :firefox, :ff
38
+ Firefox::Bridge.new(*args)
39
39
  when :remote
40
40
  Remote::Bridge.new(*args)
41
+ when :ie, :internet_explorer
42
+ IE::Bridge.new(*args)
41
43
  when :chrome
42
44
  Chrome::Bridge.new(*args)
43
- when :firefox, :ff
44
- Firefox::Bridge.new(*args)
45
+ when :android
46
+ Android::Bridge.new(*args)
47
+ when :iphone
48
+ IPhone::Bridge.new(*args)
45
49
  else
46
50
  raise ArgumentError, "unknown driver: #{browser.inspect}"
47
51
  end
@@ -0,0 +1,28 @@
1
+ module Selenium
2
+ module WebDriver
3
+
4
+ #
5
+ # @private
6
+ #
7
+
8
+ module DriverExtensions
9
+ module Rotatable
10
+
11
+ ORIENTATIONS = [:landscape, :portrait]
12
+
13
+ def rotate(orientation)
14
+ unless ORIENTATIONS.include?(orientation)
15
+ raise ArgumentError, "expected #{ORIENTATIONS.inspect}, got #{orientation.inspect}"
16
+ end
17
+
18
+ bridge.setScreenOrientation(orientation.to_s.upcase)
19
+ end
20
+
21
+ def orientation
22
+ bridge.getScreenOrientation.to_sym.downcase
23
+ end
24
+
25
+ end # Rotatable
26
+ end # DriverExtensions
27
+ end # WebDriver
28
+ end # Selenium
@@ -20,6 +20,16 @@ module Selenium
20
20
  tmp_files << file
21
21
  end
22
22
 
23
+ def reap(file)
24
+ return unless reap?
25
+
26
+ unless tmp_files.include?(file)
27
+ raise Error::WebDriverError, "file not added for reaping: #{file.inspect}"
28
+ end
29
+
30
+ FileUtils.rm_rf tmp_files.delete(file)
31
+ end
32
+
23
33
  def reap!
24
34
  tmp_files.each { |file| FileUtils.rm_rf(file) } if reap?
25
35
  end
@@ -0,0 +1,119 @@
1
+ module Selenium
2
+ module WebDriver
3
+ class Proxy
4
+ TYPES = {
5
+ :direct => "DIRECT", # Direct connection, no proxy (default on Windows).
6
+ :manual => "MANUAL", # Manual proxy settings (e.g., for httpProxy).
7
+ :pac => "PAC", # Proxy autoconfiguration from URL.
8
+ :auto_detect => "AUTODETECT", # Proxy autodetection (presumably with WPAD).
9
+ :system => "SYSTEM" # Use system settings (default on Linux).
10
+ }
11
+
12
+ attr_reader :type,
13
+ :ftp,
14
+ :http,
15
+ :no_proxy,
16
+ :pac,
17
+ :ssl,
18
+ :auto_detect
19
+
20
+ def initialize(opts = {})
21
+ opts = opts.dup
22
+
23
+ self.type = opts.delete(:type) if opts.has_key? :type
24
+ self.ftp = opts.delete(:ftp) if opts.has_key? :ftp
25
+ self.http = opts.delete(:http) if opts.has_key? :http
26
+ self.no_proxy = opts.delete(:no_proxy) if opts.has_key? :no_proxy
27
+ self.ssl = opts.delete(:ssl) if opts.has_key? :ssl
28
+ self.pac = opts.delete(:pac) if opts.has_key? :pac
29
+ self.auto_detect = opts.delete(:auto_detect) if opts.has_key? :auto_detect
30
+
31
+ unless opts.empty?
32
+ raise ArgumentError, "unknown option#{'s' if opts.size != 1}: #{opts.inspect}"
33
+ end
34
+ end
35
+
36
+ def ==(other)
37
+ return false unless other.kind_of? self.class
38
+ as_json == other.as_json
39
+ end
40
+ alias_method :eql?, :==
41
+
42
+
43
+ def ftp=(value)
44
+ self.type = :manual
45
+ @ftp = value
46
+ end
47
+
48
+ def http=(value)
49
+ self.type = :manual
50
+ @http = value
51
+ end
52
+
53
+ def no_proxy=(value)
54
+ self.type = :manual
55
+ @no_proxy = value
56
+ end
57
+
58
+ def ssl=(value)
59
+ self.type = :manual
60
+ @ssl = value
61
+ end
62
+
63
+ def pac=(url)
64
+ self.type = :pac
65
+ @pac = url
66
+ end
67
+
68
+ def auto_detect=(bool)
69
+ self.type = :auto_detect
70
+ @auto_detect = bool
71
+ end
72
+
73
+ def type=(type)
74
+ unless TYPES.has_key? type
75
+ raise ArgumentError, "invalid proxy type: #{type.inspect}, expected one of #{TYPES.keys.inspect}"
76
+ end
77
+
78
+ if @type && type != @type
79
+ raise ArgumentError, "incompatible proxy type #{type.inspect} (already set to #{@type.inspect})"
80
+ end
81
+
82
+ @type = type
83
+ end
84
+
85
+ def as_json(opts = nil)
86
+ json_result = {
87
+ "proxyType" => TYPES[type]
88
+ }
89
+
90
+ json_result["ftpProxy"] = ftp if ftp
91
+ json_result["httpProxy"] = http if http
92
+ json_result["noProxy"] = no_proxy if no_proxy
93
+ json_result["proxyAutoconfigUrl"] = pac if pac
94
+ json_result["sslProxy"] = ssl if ssl
95
+ json_result["autodetect"] = auto_detect if auto_detect
96
+
97
+ json_result if json_result.length > 1
98
+ end
99
+
100
+ class << self
101
+ def json_create(data)
102
+ proxy = new
103
+
104
+ proxy.type = data['proxyType'].downcase.to_sym if data.has_key? 'proxyType'
105
+ proxy.ftp = data['ftpProxy'] if data.has_key? 'ftpProxy'
106
+ proxy.http = data['httpProxy'] if data.has_key? 'httpProxy'
107
+ proxy.no_proxy = data['noProxy'] if data.has_key? 'noProxy'
108
+ proxy.pac = data['proxyAutoconfigUrl'] if data.has_key? 'proxyAutoconfigUrl'
109
+ proxy.ssl = data['sslProxy'] if data.has_key? 'sslProxy'
110
+ proxy.auto_detect = data['autodetect'] if data.has_key? 'autodetect'
111
+
112
+ proxy
113
+ end
114
+
115
+ end # class << self
116
+
117
+ end # Proxy
118
+ end # WebDriver
119
+ end # Selenium
@@ -12,23 +12,30 @@ module Selenium
12
12
  end
13
13
 
14
14
  #
15
- # @return true if the socket can be connected to
15
+ # Returns true if the server is listening within the given timeout,
16
+ # false otherwise.
17
+ #
18
+ # @return [Boolean]
16
19
  #
17
20
 
18
- def success?
19
- max_time = Time.now + @timeout
21
+ def connected?
22
+ with_timeout { listening? }
23
+ end
20
24
 
21
- (
22
- return true if can_connect?
23
- wait
24
- ) until Time.now >= max_time
25
+ #
26
+ # Returns true if the server has stopped listening within the given timeout,
27
+ # false otherwise.
28
+ #
29
+ # @return [Boolean]
30
+ #
25
31
 
26
- false
32
+ def closed?
33
+ with_timeout { not listening? }
27
34
  end
28
35
 
29
36
  private
30
37
 
31
- def can_connect?
38
+ def listening?
32
39
  # There's a bug in 1.9.1 on Windows where this will succeed even if no
33
40
  # one is listening. Users who hit that should upgrade their Ruby.
34
41
  TCPSocket.new(@host, @port).close
@@ -38,6 +45,17 @@ module Selenium
38
45
  false
39
46
  end
40
47
 
48
+ def with_timeout(&blk)
49
+ max_time = Time.now + @timeout
50
+
51
+ (
52
+ return true if yield
53
+ wait
54
+ ) until Time.now > max_time
55
+
56
+ false
57
+ end
58
+
41
59
  def wait
42
60
  sleep @interval
43
61
  end
@@ -16,15 +16,16 @@ module Selenium
16
16
  def start_with(profile, profile_path, *args)
17
17
  profile_path = profile_path.gsub("/", "\\") if Platform.win?
18
18
 
19
- ENV['XRE_PROFILE_PATH'] = profile_path
20
- ENV['MOZ_NO_REMOTE'] = '1' # able to launch multiple instances
19
+ ENV['XRE_CONSOLE_LOG'] = profile.log_file if profile.log_file
20
+ ENV['XRE_PROFILE_PATH'] = profile_path
21
+ ENV['MOZ_NO_REMOTE'] = '1' # able to launch multiple instances
22
+ ENV['MOZ_CRASHREPORTER_DISABLE'] = '1' # disable breakpad
23
+ ENV['NO_EM_RESTART'] = '1' # prevent the binary from detaching from the console
21
24
 
22
25
  if Platform.linux? && (profile.native_events? || profile.load_no_focus_lib?)
23
26
  modify_link_library_path profile_path
24
27
  end
25
28
 
26
- ENV['XRE_CONSOLE_LOG'] = profile.log_file if profile.log_file
27
-
28
29
  execute(*args)
29
30
  cope_with_mac_strangeness(args) if Platform.mac?
30
31
  end
@@ -45,7 +46,9 @@ module Selenium
45
46
 
46
47
  def execute(*extra_args)
47
48
  args = [self.class.path, "-no-remote", "--verbose"] + extra_args
48
- @process = ChildProcess.build(*args).start
49
+ @process = ChildProcess.build(*args)
50
+ @process.io.inherit! if $DEBUG
51
+ @process.start
49
52
  end
50
53
 
51
54
  def cope_with_mac_strangeness(args)
@@ -6,9 +6,8 @@ module Selenium
6
6
  class Bridge < Remote::Bridge
7
7
 
8
8
  def initialize(opts = {})
9
- @binary = Binary.new
10
9
  @launcher = Launcher.new(
11
- @binary,
10
+ Binary.new,
12
11
  opts.delete(:port) || DEFAULT_PORT,
13
12
  opts.delete(:profile)
14
13
  )
@@ -41,7 +40,7 @@ module Selenium
41
40
 
42
41
  def quit
43
42
  super
44
- @binary.quit
43
+ @launcher.quit
45
44
 
46
45
  nil
47
46
  end
@@ -11,31 +11,34 @@ module Selenium
11
11
  raise Error::WebDriverError, "could not find extension at #{path.inspect}"
12
12
  end
13
13
 
14
- @path = path
14
+ @path = path
15
+ @should_reap_root = false
15
16
  end
16
17
 
17
18
  def write_to(extensions_dir)
18
- ext_path = File.join extensions_dir, read_id_from_install_rdf(root)
19
+ root_dir = create_root
20
+ ext_path = File.join extensions_dir, read_id_from_install_rdf(root_dir)
19
21
 
20
22
  FileUtils.rm_rf ext_path
21
23
  FileUtils.mkdir_p File.dirname(ext_path), :mode => 0700
22
- FileUtils.cp_r root, ext_path
24
+ FileUtils.cp_r root_dir, ext_path
25
+
26
+ FileReaper.reap(root_dir) if @should_reap_root
23
27
  end
24
28
 
25
29
  private
26
30
 
27
- def root
28
- @root ||= (
29
- if File.directory? @path
30
- @path
31
- else
32
- unless Zipper::EXTENSIONS.include? File.extname(@path)
33
- raise Error::WebDriverError, "expected #{Zipper::EXTENSIONS.join(" or ")}, got #{@path.inspect}"
34
- end
35
-
36
- Zipper.unzip(@path)
31
+ def create_root
32
+ if File.directory? @path
33
+ @path
34
+ else
35
+ unless Zipper::EXTENSIONS.include? File.extname(@path)
36
+ raise Error::WebDriverError, "expected #{Zipper::EXTENSIONS.join(" or ")}, got #{@path.inspect}"
37
37
  end
38
- )
38
+
39
+ @should_reap_root = true
40
+ Zipper.unzip(@path)
41
+ end
39
42
  end
40
43
 
41
44
  def read_id_from_install_rdf(directory)
@@ -40,6 +40,11 @@ module Selenium
40
40
  self
41
41
  end
42
42
 
43
+ def quit
44
+ @binary.quit
45
+ FileReaper.reap(@profile_dir) if @profile_dir
46
+ end
47
+
43
48
  def find_free_port
44
49
  port = @port
45
50
 
@@ -65,13 +70,14 @@ module Selenium
65
70
 
66
71
  def start_silent_and_wait
67
72
  assert_profile
68
- @binary.start_with @profile, @profile_dir, "--silent"
73
+ @binary.start_with @profile, @profile_dir, "-silent"
69
74
  @binary.wait
70
75
  end
71
76
 
72
77
  def connect_until_stable
73
78
  poller = SocketPoller.new(@host, @port, STABLE_CONNECTION_TIMEOUT)
74
- unless poller.success?
79
+ unless poller.connected?
80
+ @binary.quit
75
81
  raise Error::WebDriverError, "unable to obtain stable firefox connection in #{STABLE_CONNECTION_TIMEOUT} seconds"
76
82
  end
77
83
  end
@@ -156,8 +156,47 @@ module Selenium
156
156
  @untrusted_issuer = bool
157
157
  end
158
158
 
159
+ def proxy=(proxy)
160
+ unless proxy.kind_of? Proxy
161
+ raise TypeError, "expected #{Proxy.name}, got #{proxy.inspect}:#{proxy.class}"
162
+ end
163
+
164
+ case proxy.type
165
+ when :manual
166
+ self['network.proxy.type'] = 1
167
+
168
+ set_manual_proxy_preference "ftp", proxy.ftp
169
+ set_manual_proxy_preference "http", proxy.http
170
+ set_manual_proxy_preference "ssl", proxy.ssl
171
+
172
+ if proxy.no_proxy
173
+ self["network.proxy.no_proxies_on"] = proxy.no_proxy
174
+ else
175
+ self["network.proxy.no_proxies_on"] = ""
176
+ end
177
+ when :pac
178
+ self['network.proxy.type'] = 2
179
+ self['network.proxy.autoconfig_url'] = proxy.pac
180
+ when :auto_detect
181
+ self['network.proxy.type'] = 4
182
+ else
183
+ raise ArgumentError, "unsupported proxy type #{proxy.type}"
184
+ end
185
+
186
+ proxy
187
+ end
188
+
159
189
  private
160
190
 
191
+ def set_manual_proxy_preference(key, value)
192
+ return unless value
193
+
194
+ host, port = value.to_s.split(":", 2)
195
+
196
+ self["network.proxy.#{key}"] = host
197
+ self["network.proxy.#{key}_port"] = Integer(port) if port
198
+ end
199
+
161
200
  def install_extensions(directory)
162
201
  destination = File.join(directory, "extensions")
163
202
 
@@ -267,7 +306,10 @@ module Selenium
267
306
  "browser.shell.checkDefaultBrowser" => 'false',
268
307
  "browser.tabs.warnOnClose" => 'false',
269
308
  "browser.tabs.warnOnOpen" => 'false',
309
+ "devtools.errorconsole.enabled" => 'true',
270
310
  "dom.disable_open_during_load" => 'false',
311
+ "dom.max_script_run_time" => '30',
312
+ "extensions.logging.enabled" => 'true',
271
313
  "extensions.update.enabled" => 'false',
272
314
  "extensions.update.notifyUser" => 'false',
273
315
  "network.manage-offline-status" => 'false',
@@ -283,8 +325,10 @@ module Selenium
283
325
  "security.warn_viewing_mixed" => 'false',
284
326
  "security.warn_viewing_mixed.show_once" => 'false',
285
327
  "signon.rememberSignons" => 'false',
328
+ "toolkit.networkmanager.disable" => 'true',
286
329
  "javascript.options.showInConsole" => 'true',
287
- "browser.dom.window.dump.enabled" => 'true'
330
+ "browser.dom.window.dump.enabled" => 'true',
331
+ "dom.report_all_js_exceptions" => "true"
288
332
  }.freeze
289
333
 
290
334
  end # Profile