selenium-webdriver 0.0.28 → 0.0.29

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 (44) hide show
  1. data/CHANGES +25 -0
  2. data/lib/selenium/webdriver.rb +6 -29
  3. data/lib/selenium/webdriver/chrome.rb +4 -2
  4. data/lib/selenium/webdriver/chrome/extension.zip +0 -0
  5. data/lib/selenium/webdriver/chrome/launcher.rb +15 -16
  6. data/lib/selenium/webdriver/common.rb +18 -0
  7. data/lib/selenium/webdriver/{bridge_helper.rb → common/bridge_helper.rb} +0 -0
  8. data/lib/selenium/webdriver/{core_ext → common/core_ext}/dir.rb +0 -0
  9. data/lib/selenium/webdriver/{core_ext → common/core_ext}/string.rb +0 -0
  10. data/lib/selenium/webdriver/{driver.rb → common/driver.rb} +19 -7
  11. data/lib/selenium/webdriver/{driver_extensions → common/driver_extensions}/takes_screenshot.rb +2 -2
  12. data/lib/selenium/webdriver/{element.rb → common/element.rb} +30 -3
  13. data/lib/selenium/webdriver/{error.rb → common/error.rb} +0 -0
  14. data/lib/selenium/webdriver/{file_reaper.rb → common/file_reaper.rb} +0 -0
  15. data/lib/selenium/webdriver/{find.rb → common/find.rb} +9 -1
  16. data/lib/selenium/webdriver/{keys.rb → common/keys.rb} +0 -0
  17. data/lib/selenium/webdriver/{navigation.rb → common/navigation.rb} +3 -3
  18. data/lib/selenium/webdriver/{options.rb → common/options.rb} +47 -5
  19. data/lib/selenium/webdriver/{platform.rb → common/platform.rb} +10 -0
  20. data/lib/selenium/webdriver/common/socket_poller.rb +47 -0
  21. data/lib/selenium/webdriver/{target_locator.rb → common/target_locator.rb} +11 -8
  22. data/lib/selenium/webdriver/{timeouts.rb → common/timeouts.rb} +0 -0
  23. data/lib/selenium/webdriver/common/wait.rb +60 -0
  24. data/lib/selenium/webdriver/common/zipper.rb +54 -0
  25. data/lib/selenium/webdriver/firefox.rb +6 -3
  26. data/lib/selenium/webdriver/firefox/binary.rb +46 -43
  27. data/lib/selenium/webdriver/firefox/bridge.rb +2 -10
  28. data/lib/selenium/webdriver/firefox/extension.rb +51 -0
  29. data/lib/selenium/webdriver/firefox/extension/webdriver.xpi +0 -0
  30. data/lib/selenium/webdriver/firefox/launcher.rb +25 -69
  31. data/lib/selenium/webdriver/firefox/profile.rb +123 -89
  32. data/lib/selenium/webdriver/firefox/profiles_ini.rb +2 -1
  33. data/lib/selenium/webdriver/firefox/socket_lock.rb +77 -0
  34. data/lib/selenium/webdriver/ie/bridge.rb +25 -38
  35. data/lib/selenium/webdriver/ie/lib.rb +11 -1
  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/ie/util.rb +3 -17
  39. data/lib/selenium/webdriver/remote/bridge.rb +9 -1
  40. data/lib/selenium/webdriver/remote/capabilities.rb +53 -20
  41. data/lib/selenium/webdriver/remote/http/default.rb +2 -2
  42. metadata +52 -31
  43. data/lib/selenium/webdriver/child_process.rb +0 -243
  44. data/lib/selenium/webdriver/zip_helper.rb +0 -27
@@ -91,6 +91,16 @@ module Selenium
91
91
  File.chmod 0766, file
92
92
  end
93
93
 
94
+ def assert_executable(path)
95
+ unless File.file? path
96
+ raise Error::WebDriverError, "not a file: #{path.inspect}"
97
+ end
98
+
99
+ unless File.executable? path
100
+ raise Error::WebDriverError, "not executable: #{path.inspect}"
101
+ end
102
+ end
103
+
94
104
  def find_binary(*binary_names)
95
105
  paths = ENV['PATH'].split(File::PATH_SEPARATOR)
96
106
  binary_names.map! { |n| "#{n}.exe" } if win?
@@ -0,0 +1,47 @@
1
+ require "socket"
2
+
3
+ module Selenium
4
+ module WebDriver
5
+ class SocketPoller
6
+
7
+ def initialize(host, port, timeout = 0, interval = 0.25)
8
+ @host = host
9
+ @port = Integer(port)
10
+ @timeout = Integer(timeout)
11
+ @interval = interval
12
+ end
13
+
14
+ #
15
+ # @return true if the socket can be connected to
16
+ #
17
+
18
+ def success?
19
+ max_time = Time.now + @timeout
20
+
21
+ (
22
+ return true if can_connect?
23
+ wait
24
+ ) until Time.now >= max_time
25
+
26
+ false
27
+ end
28
+
29
+ private
30
+
31
+ def can_connect?
32
+ # There's a bug in 1.9.1 on Windows where this will succeed even if no
33
+ # one is listening. Users who hit that should upgrade their Ruby.
34
+ TCPSocket.new(@host, @port).close
35
+ true
36
+ rescue Errno::ECONNREFUSED, Errno::ENOTCONN, SocketError => e
37
+ $stderr.puts [@host, @port].inspect if $DEBUG
38
+ false
39
+ end
40
+
41
+ def wait
42
+ sleep @interval
43
+ end
44
+
45
+ end # SocketPoller
46
+ end # WebDriver
47
+ end # Selenium
@@ -6,8 +6,8 @@ module Selenium
6
6
  # @api private
7
7
  #
8
8
 
9
- def initialize(driver)
10
- @bridge = driver.bridge
9
+ def initialize(bridge)
10
+ @bridge = bridge
11
11
  end
12
12
 
13
13
  #
@@ -33,15 +33,18 @@ module Selenium
33
33
  original = @bridge.getCurrentWindowHandle
34
34
  @bridge.switchToWindow id
35
35
 
36
- yield
36
+ begin
37
+ returned = yield
38
+ ensure
39
+ current_handles = @bridge.getWindowHandles
37
40
 
38
- current_handles = @bridge.getWindowHandles
41
+ if current_handles.size == 1
42
+ original = current_handles.shift
43
+ end
39
44
 
40
- if current_handles.size == 1
41
- original = current_handles.shift
45
+ @bridge.switchToWindow original
46
+ returned
42
47
  end
43
-
44
- @bridge.switchToWindow original
45
48
  else
46
49
  @bridge.switchToWindow id
47
50
  end
@@ -0,0 +1,60 @@
1
+ module Selenium
2
+ module WebDriver
3
+ class Wait
4
+
5
+ DEFAULT_TIMEOUT = 30
6
+ DEFAULT_INTERVAL = 0.5
7
+
8
+ #
9
+ # Create a new Wait instance
10
+ #
11
+ # @param [Hash] opts Options for this instance
12
+ # @option opts [Numeric] :timeout (30) Seconds to wait before timing out.
13
+ # @option opts [Numeric] :interval (0.5) Seconds to sleep between polls.
14
+ # @option opts [String] :message Exception mesage if timed out.
15
+
16
+ def initialize(opts = {})
17
+ @timeout = opts.fetch(:timeout, DEFAULT_TIMEOUT)
18
+ @interval = opts.fetch(:interval, DEFAULT_INTERVAL)
19
+ @message = opts[:message]
20
+ end
21
+
22
+
23
+ #
24
+ # Wait until the given block returns a true value.
25
+ #
26
+ # @raise [Error::TimeOutError]
27
+ # @return [Object] the result of the block
28
+ #
29
+
30
+ def until(&blk)
31
+ end_time = Time.now + @timeout
32
+ last_error = nil
33
+
34
+ until Time.now > end_time
35
+ begin
36
+ result = yield
37
+ return result if result
38
+ rescue Error::NoSuchElementError => last_error
39
+ # swallowed
40
+ end
41
+
42
+ sleep @interval
43
+ end
44
+
45
+
46
+ if @message
47
+ msg = @message.dup
48
+ else
49
+ msg = "timed out after #{@timeout} seconds"
50
+ end
51
+
52
+ msg << " (#{last_error.message})}" if last_error
53
+
54
+ raise Error::TimeOutError, msg
55
+ end
56
+
57
+ end # Wait
58
+ end # WebDriver
59
+ end # Selenium
60
+
@@ -0,0 +1,54 @@
1
+ require 'zip/zip'
2
+ require 'tempfile'
3
+ require 'find'
4
+
5
+ module Selenium
6
+ module WebDriver
7
+ module Zipper
8
+
9
+ EXTENSIONS = %w[.zip .xpi]
10
+
11
+ def self.unzip(path)
12
+ destination = Dir.mktmpdir("unzip")
13
+ FileReaper << destination
14
+
15
+ Zip::ZipFile.open(path) do |zip|
16
+ zip.each do |entry|
17
+ to = File.join(destination, entry.name)
18
+ dirname = File.dirname(to)
19
+
20
+ FileUtils.mkdir_p dirname unless File.exist? dirname
21
+ zip.extract(entry, to)
22
+ end
23
+ end
24
+
25
+ destination
26
+ end
27
+
28
+ def self.zip(path)
29
+ tmp_zip = Tempfile.new("webdriver-zip")
30
+
31
+ begin
32
+ zos = Zip::ZipOutputStream.new(tmp_zip.path)
33
+
34
+ ::Find.find(path) do |file|
35
+ next if File.directory?(file)
36
+ entry = file.sub("#{path}/", '')
37
+
38
+ zos.put_next_entry(entry)
39
+ zos << File.read(file)
40
+ p :added => file, :as => entry
41
+ end
42
+
43
+ zos.close
44
+ tmp_zip.rewind
45
+
46
+ [tmp_zip.read].pack("m")
47
+ ensure
48
+ tmp_zip.close
49
+ end
50
+ end
51
+
52
+ end # Zipper
53
+ end # WebDriver
54
+ end # Selenium
@@ -3,6 +3,8 @@ require "socket"
3
3
  require "rexml/document"
4
4
 
5
5
  require "selenium/webdriver/firefox/util"
6
+ require "selenium/webdriver/firefox/extension"
7
+ require "selenium/webdriver/firefox/socket_lock"
6
8
  require "selenium/webdriver/firefox/binary"
7
9
  require "selenium/webdriver/firefox/profiles_ini"
8
10
  require "selenium/webdriver/firefox/profile"
@@ -11,17 +13,18 @@ require "selenium/webdriver/firefox/bridge"
11
13
 
12
14
  module Selenium
13
15
  module WebDriver
14
-
15
- # @private
16
16
  module Firefox
17
17
 
18
- DEFAULT_PROFILE_NAME = "WebDriver".freeze
19
18
  DEFAULT_PORT = 7055
20
19
  DEFAULT_ENABLE_NATIVE_EVENTS = Platform.os == :windows
21
20
  DEFAULT_SECURE_SSL = false
22
21
  DEFAULT_ASSUME_UNTRUSTED_ISSUER = true
23
22
  DEFAULT_LOAD_NO_FOCUS_LIB = false
24
23
 
24
+ def self.path=(path)
25
+ Binary.path = path
26
+ end
27
+
25
28
  end
26
29
  end
27
30
  end
@@ -6,78 +6,66 @@ module Selenium
6
6
  class Binary
7
7
 
8
8
  NO_FOCUS_LIBRARY_NAME = "x_ignore_nofocus.so"
9
- NO_FOCUS_LIBRARIES = [
9
+ NO_FOCUS_LIBRARIES = [
10
10
  ["#{WebDriver.root}/selenium/webdriver/firefox/native/linux/amd64/#{NO_FOCUS_LIBRARY_NAME}", "amd64/#{NO_FOCUS_LIBRARY_NAME}"],
11
11
  ["#{WebDriver.root}/selenium/webdriver/firefox/native/linux/x86/#{NO_FOCUS_LIBRARY_NAME}", "x86/#{NO_FOCUS_LIBRARY_NAME}"],
12
12
  ]
13
13
 
14
- def create_base_profile(name)
15
- execute("-CreateProfile", name)
14
+ WAIT_TIMEOUT = 90
16
15
 
17
- status = nil
18
- Timeout.timeout(15, Error::TimeOutError) do
19
- _, status = wait
20
- end
21
-
22
- if status && status.to_i != 0
23
- raise Error::WebDriverError, "could not create base profile: (exit status: #{status})"
24
- end
25
- end
16
+ def start_with(profile, profile_path, *args)
17
+ profile_path = profile_path.gsub("/", "\\") if Platform.win?
26
18
 
27
- def start_with(profile, *args)
28
- ENV['XRE_PROFILE_PATH'] = profile.absolute_path
19
+ ENV['XRE_PROFILE_PATH'] = profile_path
29
20
  ENV['MOZ_NO_REMOTE'] = '1' # able to launch multiple instances
30
21
 
31
22
  if Platform.linux? && (profile.native_events? || profile.load_no_focus_lib?)
32
- modify_link_library_path profile
23
+ modify_link_library_path profile_path
33
24
  end
34
25
 
26
+ ENV['XRE_CONSOLE_LOG'] = profile.log_file if profile.log_file
27
+
35
28
  execute(*args)
36
29
  cope_with_mac_strangeness(args) if Platform.mac?
37
30
  end
38
31
 
32
+ def quit
33
+ return unless @process
34
+ @process.poll_for_exit 5
35
+ rescue ChildProcess::TimeoutError
36
+ # ok, force quit
37
+ @process.stop 5
38
+ end
39
+
40
+ def wait
41
+ @process.poll_for_exit(WAIT_TIMEOUT) if @process
42
+ end
43
+
44
+ private
45
+
39
46
  def execute(*extra_args)
40
47
  args = [self.class.path, "-no-remote", "--verbose"] + extra_args
41
- @process = ChildProcess.new(*args).start
48
+ @process = ChildProcess.build(*args).start
42
49
  end
43
50
 
44
51
  def cope_with_mac_strangeness(args)
45
52
  sleep 0.3
46
53
 
47
- if @process.ugly_death?
48
- # process crashed, trying a restart. sleeping 5 seconds shorter than the java driver
49
- sleep 5
54
+ if @process.crashed?
55
+ # ok, trying a restart
56
+ sleep 7
50
57
  execute(*args)
51
58
  end
52
59
 
53
60
  # ensure we're ok
54
61
  sleep 0.3
55
- if @process.ugly_death?
62
+ if @process.crashed?
56
63
  raise Error::WebDriverError, "unable to start Firefox cleanly, args: #{args.inspect}"
57
64
  end
58
65
  end
59
66
 
60
- def quit
61
- @process.ensure_death if @process
62
- end
63
-
64
- def kill
65
- @process.kill if @process
66
- end
67
-
68
- def wait
69
- @process.wait if @process
70
- end
71
-
72
- def pid
73
- @process.pid if @process
74
- end
75
-
76
- private
77
-
78
- def modify_link_library_path(profile)
67
+ def modify_link_library_path(profile_path)
79
68
  paths = []
80
- profile_path = profile.absolute_path
81
69
 
82
70
  NO_FOCUS_LIBRARIES.each do |from, to|
83
71
  dest = File.join(profile_path, to)
@@ -94,7 +82,17 @@ module Selenium
94
82
  end
95
83
 
96
84
  class << self
97
- attr_writer :path
85
+
86
+ #
87
+ # @private
88
+ #
89
+ # @see Firefox.path=
90
+ #
91
+
92
+ def path=(path)
93
+ Platform.assert_executable(path)
94
+ @path = path
95
+ end
98
96
 
99
97
  def path
100
98
  @path ||= case Platform.os
@@ -108,7 +106,7 @@ module Selenium
108
106
  raise Error::WebDriverError, "unknown platform: #{Platform.os}"
109
107
  end
110
108
 
111
- unless File.file?(@path)
109
+ unless File.file?(@path.to_s)
112
110
  raise Error::WebDriverError, "Could not find Firefox binary (os=#{Platform.os}). Make sure Firefox is installed or set the path manually with #{self}.path="
113
111
  end
114
112
 
@@ -118,7 +116,7 @@ module Selenium
118
116
  private
119
117
 
120
118
  def windows_path
121
- windows_registry_path || "#{ ENV['PROGRAMFILES'] || "\\Program Files" }\\Mozilla Firefox\\firefox.exe"
119
+ windows_registry_path || likely_windows_path || Platform.find_binary("firefox")
122
120
  end
123
121
 
124
122
  def windows_registry_path
@@ -135,6 +133,11 @@ module Selenium
135
133
  # older JRuby or IronRuby does not have win32/registry
136
134
  rescue Win32::Registry::Error
137
135
  end
136
+
137
+ def likely_windows_path
138
+ path = "#{ ENV['PROGRAMFILES'] || "\\Program Files" }\\Mozilla Firefox\\firefox.exe"
139
+ path if File.executable?(path)
140
+ end
138
141
  end # class << self
139
142
 
140
143
  end # Binary
@@ -9,8 +9,8 @@ module Selenium
9
9
  @binary = Binary.new
10
10
  @launcher = Launcher.new(
11
11
  @binary,
12
- opts.delete(:port) || DEFAULT_PORT,
13
- opts.delete(:profile) || DEFAULT_PROFILE_NAME
12
+ opts.delete(:port) || DEFAULT_PORT,
13
+ opts.delete(:profile)
14
14
  )
15
15
 
16
16
  http_client = opts.delete(:http_client)
@@ -50,14 +50,6 @@ module Selenium
50
50
  execute :screenshot
51
51
  end
52
52
 
53
- def findElementByCssSelector(parent, selector)
54
- find_element_by 'css selector', selector, parent
55
- end
56
-
57
- def findElementsByCssSelector(parent, selector)
58
- find_elements_by 'css selector', selector, parent
59
- end
60
-
61
53
  end # Bridge
62
54
  end # Firefox
63
55
  end # WebDriver
@@ -0,0 +1,51 @@
1
+ module Selenium
2
+ module WebDriver
3
+ module Firefox
4
+
5
+ # @private
6
+ class Extension
7
+ EM_NAMESPACE_URI = "http://www.mozilla.org/2004/em-rdf#" # not used?
8
+
9
+ def initialize(path)
10
+ unless File.exist?(path)
11
+ raise Error::WebDriverError, "could not find extension at #{path.inspect}"
12
+ end
13
+
14
+ @path = path
15
+ end
16
+
17
+ def write_to(extensions_dir)
18
+ ext_path = File.join extensions_dir, read_id_from_install_rdf(root)
19
+
20
+ FileUtils.rm_rf ext_path
21
+ FileUtils.mkdir_p File.dirname(ext_path), :mode => 0700
22
+ FileUtils.cp_r root, ext_path
23
+ end
24
+
25
+ private
26
+
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)
37
+ end
38
+ )
39
+ end
40
+
41
+ def read_id_from_install_rdf(directory)
42
+ rdf_path = File.join(directory, "install.rdf")
43
+ doc = REXML::Document.new(File.read(rdf_path))
44
+
45
+ REXML::XPath.first(doc, "//em:id").text
46
+ end
47
+
48
+ end # Extension
49
+ end # Firefox
50
+ end # WebDriver
51
+ end # Selenium