selenium-webdriver 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. data/CHANGES +15 -0
  2. data/lib/selenium-client.rb +1 -1
  3. data/lib/selenium-webdriver.rb +1 -1
  4. data/lib/selenium/client.rb +1 -1
  5. data/lib/selenium/server.rb +3 -3
  6. data/lib/selenium/webdriver.rb +6 -6
  7. data/lib/selenium/webdriver/android.rb +1 -1
  8. data/lib/selenium/webdriver/android/bridge.rb +1 -1
  9. data/lib/selenium/webdriver/chrome.rb +2 -2
  10. data/lib/selenium/webdriver/chrome/bridge.rb +14 -3
  11. data/lib/selenium/webdriver/common.rb +26 -26
  12. data/lib/selenium/webdriver/common/action_builder.rb +11 -11
  13. data/lib/selenium/webdriver/common/driver.rb +7 -8
  14. data/lib/selenium/webdriver/common/platform.rb +2 -2
  15. data/lib/selenium/webdriver/common/search_context.rb +4 -2
  16. data/lib/selenium/webdriver/common/socket_poller.rb +42 -12
  17. data/lib/selenium/webdriver/common/timeouts.rb +2 -2
  18. data/lib/selenium/webdriver/firefox.rb +11 -11
  19. data/lib/selenium/webdriver/firefox/binary.rb +1 -1
  20. data/lib/selenium/webdriver/firefox/extension.rb +0 -2
  21. data/lib/selenium/webdriver/firefox/extension/webdriver.xpi +0 -0
  22. data/lib/selenium/webdriver/firefox/launcher.rb +5 -2
  23. data/lib/selenium/webdriver/firefox/native/linux/amd64/x_ignore_nofocus.so +0 -0
  24. data/lib/selenium/webdriver/firefox/native/linux/x86/x_ignore_nofocus.so +0 -0
  25. data/lib/selenium/webdriver/firefox/profile.rb +0 -2
  26. data/lib/selenium/webdriver/firefox/socket_lock.rb +1 -1
  27. data/lib/selenium/webdriver/ie.rb +3 -3
  28. data/lib/selenium/webdriver/ie/native/win32/IEDriver.dll +0 -0
  29. data/lib/selenium/webdriver/ie/native/x64/IEDriver.dll +0 -0
  30. data/lib/selenium/webdriver/iphone.rb +1 -1
  31. data/lib/selenium/webdriver/remote.rb +8 -8
  32. data/lib/selenium/webdriver/remote/capabilities.rb +98 -51
  33. data/lib/selenium/webdriver/remote/http/default.rb +1 -1
  34. data/lib/selenium/webdriver/remote/http/persistent.rb +1 -1
  35. metadata +46 -4
data/CHANGES CHANGED
@@ -1,3 +1,18 @@
1
+ 0.2.1 (2011-06-01)
2
+ ==================
3
+
4
+ * Allow passing custom command line switches to Chrome (requires today's release of the Chrome server)
5
+ * Avoid mutating arguments to find_element (issue #1273).
6
+ * Avoid conflicts when SUT modifies Array.prototype
7
+ * Allow setting arbitrary capabilities by adding Capabilities#[]=
8
+ * The Chrome driver is extended with TakesScreenshot.
9
+ * IE driver detects bad protected mode settings.
10
+ * Firefox driver no longer considers opacity when determining visibility.
11
+ * Fix for ActionBuilder#move_by.
12
+ * Treat Errno::EBADF as an indication that we failed to grab the socket lock (issue #1611).
13
+ * Ensure Firefox launches don't hang on some Ruby versions (by improving Selenium::WebDriver::SocketPoller).
14
+ * Various internal driver improvements.
15
+
1
16
  0.2.0 (2011-04-22)
2
17
  ==================
3
18
 
@@ -1,2 +1,2 @@
1
- require "selenium/client"
1
+ require 'selenium/client'
2
2
 
@@ -1 +1 @@
1
- require "selenium/webdriver"
1
+ require 'selenium/webdriver'
@@ -1,7 +1,7 @@
1
1
  require 'net/http'
2
2
  require 'uri'
3
3
  require 'cgi'
4
- require "digest/md5"
4
+ require 'digest/md5'
5
5
  require 'fileutils'
6
6
  require 'tmpdir'
7
7
 
@@ -1,6 +1,6 @@
1
- require "childprocess"
2
- require "selenium/webdriver/common/socket_poller"
3
- require "net/http"
1
+ require 'childprocess'
2
+ require 'selenium/webdriver/common/socket_poller'
3
+ require 'net/http'
4
4
 
5
5
  module Selenium
6
6
 
@@ -1,7 +1,7 @@
1
- require "childprocess"
2
- require "tmpdir"
3
- require "fileutils"
4
- require "date"
1
+ require 'childprocess'
2
+ require 'tmpdir'
3
+ require 'fileutils'
4
+ require 'date'
5
5
  require 'base64'
6
6
 
7
7
  have_lib = lambda { |lib|
@@ -13,7 +13,7 @@ have_lib = lambda { |lib|
13
13
  end
14
14
  }
15
15
 
16
- unless have_lib["yajl/json_gem"] || have_lib["json"]
16
+ unless have_lib['yajl/json_gem'] || have_lib['json']
17
17
  raise LoadError, <<-END
18
18
 
19
19
  You need to require rubygems or install one of these gems:
@@ -26,7 +26,7 @@ unless have_lib["yajl/json_gem"] || have_lib["json"]
26
26
  END
27
27
  end
28
28
 
29
- require "selenium/webdriver/common"
29
+ require 'selenium/webdriver/common'
30
30
 
31
31
  module Selenium
32
32
  module WebDriver
@@ -6,4 +6,4 @@ module Selenium
6
6
  end # WebDriver
7
7
  end # Selenium
8
8
 
9
- require "selenium/webdriver/android/bridge"
9
+ require 'selenium/webdriver/android/bridge'
@@ -10,7 +10,7 @@ module Selenium
10
10
  super
11
11
  else
12
12
  super(
13
- :url => DEFAULT_URL,
13
+ :url => DEFAULT_URL,
14
14
  :desired_capabilities => capabilities
15
15
  )
16
16
  end
@@ -1,7 +1,7 @@
1
1
  require 'net/http'
2
2
 
3
- require "selenium/webdriver/chrome/service"
4
- require "selenium/webdriver/chrome/bridge"
3
+ require 'selenium/webdriver/chrome/service'
4
+ require 'selenium/webdriver/chrome/bridge'
5
5
 
6
6
 
7
7
  module Selenium
@@ -6,19 +6,30 @@ module Selenium
6
6
  class Bridge < Remote::Bridge
7
7
 
8
8
  def initialize(opts = {})
9
- # TODO: pass options to Chrome::Service
10
9
  http_client = opts.delete(:http_client)
10
+ switches = opts.delete(:switches)
11
11
 
12
12
  unless opts.empty?
13
13
  raise ArgumentError, "unknown option#{'s' if opts.size != 1}: #{opts.inspect}"
14
14
  end
15
15
 
16
+ caps = Remote::Capabilities.chrome
17
+
18
+ if switches
19
+ unless switches.kind_of? Array
20
+ raise ArgumentError, ":switches must be an Array of Strings"
21
+ end
22
+
23
+ caps.merge! 'chrome.switches' => switches.map { |e| e.to_s }
24
+ end
25
+
26
+
16
27
  @service = Service.default_service
17
28
  @service.start
18
29
 
19
30
  remote_opts = {
20
31
  :url => @service.uri,
21
- :desired_capabilities => :chrome
32
+ :desired_capabilities => caps
22
33
  }
23
34
 
24
35
  remote_opts.merge!(:http_client => http_client) if http_client
@@ -31,7 +42,7 @@ module Selenium
31
42
  end
32
43
 
33
44
  def driver_extensions
34
- []
45
+ [DriverExtensions::TakesScreenshot]
35
46
  end
36
47
 
37
48
  def capabilities
@@ -1,26 +1,26 @@
1
- require "selenium/webdriver/common/core_ext/dir"
2
- require "selenium/webdriver/common/core_ext/string"
3
- require "selenium/webdriver/common/error"
4
- require "selenium/webdriver/common/platform"
5
- require "selenium/webdriver/common/proxy"
6
- require "selenium/webdriver/common/file_reaper"
7
- require "selenium/webdriver/common/socket_poller"
8
- require "selenium/webdriver/common/port_prober"
9
- require "selenium/webdriver/common/zipper"
10
- require "selenium/webdriver/common/wait"
11
- require "selenium/webdriver/common/alert"
12
- require "selenium/webdriver/common/mouse"
13
- require "selenium/webdriver/common/keyboard"
14
- require "selenium/webdriver/common/target_locator"
15
- require "selenium/webdriver/common/navigation"
16
- require "selenium/webdriver/common/timeouts"
17
- require "selenium/webdriver/common/options"
18
- require "selenium/webdriver/common/search_context"
19
- require "selenium/webdriver/common/action_builder"
20
- require "selenium/webdriver/common/driver_extensions/takes_screenshot"
21
- require "selenium/webdriver/common/driver_extensions/rotatable"
22
- require "selenium/webdriver/common/driver_extensions/has_input_devices"
23
- require "selenium/webdriver/common/keys"
24
- require "selenium/webdriver/common/bridge_helper"
25
- require "selenium/webdriver/common/driver"
26
- require "selenium/webdriver/common/element"
1
+ require 'selenium/webdriver/common/core_ext/dir'
2
+ require 'selenium/webdriver/common/core_ext/string'
3
+ require 'selenium/webdriver/common/error'
4
+ require 'selenium/webdriver/common/platform'
5
+ require 'selenium/webdriver/common/proxy'
6
+ require 'selenium/webdriver/common/file_reaper'
7
+ require 'selenium/webdriver/common/socket_poller'
8
+ require 'selenium/webdriver/common/port_prober'
9
+ require 'selenium/webdriver/common/zipper'
10
+ require 'selenium/webdriver/common/wait'
11
+ require 'selenium/webdriver/common/alert'
12
+ require 'selenium/webdriver/common/mouse'
13
+ require 'selenium/webdriver/common/keyboard'
14
+ require 'selenium/webdriver/common/target_locator'
15
+ require 'selenium/webdriver/common/navigation'
16
+ require 'selenium/webdriver/common/timeouts'
17
+ require 'selenium/webdriver/common/options'
18
+ require 'selenium/webdriver/common/search_context'
19
+ require 'selenium/webdriver/common/action_builder'
20
+ require 'selenium/webdriver/common/driver_extensions/takes_screenshot'
21
+ require 'selenium/webdriver/common/driver_extensions/rotatable'
22
+ require 'selenium/webdriver/common/driver_extensions/has_input_devices'
23
+ require 'selenium/webdriver/common/keys'
24
+ require 'selenium/webdriver/common/bridge_helper'
25
+ require 'selenium/webdriver/common/driver'
26
+ require 'selenium/webdriver/common/element'
@@ -13,7 +13,7 @@ module Selenium
13
13
 
14
14
  def key_down(*args)
15
15
  if args.first.kind_of? Element
16
- @actions << [:mouse, :click, args.shift]
16
+ @actions << [:mouse, :click, [args.shift]]
17
17
  end
18
18
 
19
19
  @actions << [:keyboard, :press, args]
@@ -22,7 +22,7 @@ module Selenium
22
22
 
23
23
  def key_up(*args)
24
24
  if args.first.kind_of? Element
25
- @actions << [:mouse, :click, args.shift]
25
+ @actions << [:mouse, :click, [args.shift]]
26
26
  end
27
27
 
28
28
  @actions << [:keyboard, :release, args]
@@ -31,7 +31,7 @@ module Selenium
31
31
 
32
32
  def send_keys(*args)
33
33
  if args.first.kind_of? Element
34
- @actions << [:mouse, :click, args.shift]
34
+ @actions << [:mouse, :click, [args.shift]]
35
35
  end
36
36
 
37
37
  @actions << [:keyboard, :send_keys, args]
@@ -39,42 +39,42 @@ module Selenium
39
39
  end
40
40
 
41
41
  def click_and_hold(element)
42
- @actions << [:mouse, :down, element]
42
+ @actions << [:mouse, :down, [element]]
43
43
  self
44
44
  end
45
45
 
46
46
  def release(element = nil)
47
- @actions << [:mouse, :up, element]
47
+ @actions << [:mouse, :up, [element]]
48
48
  self
49
49
  end
50
50
 
51
51
  def click(element = nil)
52
- @actions << [:mouse, :click, element]
52
+ @actions << [:mouse, :click, [element]]
53
53
  self
54
54
  end
55
55
 
56
56
  def double_click(element = nil)
57
- @actions << [:mouse, :double_click, element]
57
+ @actions << [:mouse, :double_click, [element]]
58
58
  self
59
59
  end
60
60
 
61
61
  def move_to(element, down_by = nil, right_by = nil)
62
62
  if down_by && right_by
63
- @actions << [:mouse, :move_to, element, down_by, right_by]
63
+ @actions << [:mouse, :move_to, [element, down_by, right_by]]
64
64
  else
65
- @actions << [:mouse, :move_to, element]
65
+ @actions << [:mouse, :move_to, [element]]
66
66
  end
67
67
 
68
68
  self
69
69
  end
70
70
 
71
71
  def move_by(down_by, right_by)
72
- @actions << [:mouse, :move_by, down_by, right_by]
72
+ @actions << [:mouse, :move_by, [down_by, right_by]]
73
73
  self
74
74
  end
75
75
 
76
76
  def context_click(element = nil)
77
- @actions << [:mouse, :context_click, element]
77
+ @actions << [:mouse, :context_click, [element]]
78
78
  self
79
79
  end
80
80
 
@@ -261,7 +261,14 @@ module Selenium
261
261
  find_element sel
262
262
  end
263
263
 
264
+ def browser
265
+ bridge.browser
266
+ end
264
267
 
268
+ def capabilities
269
+ bridge.capabilities
270
+ end
271
+
265
272
  #
266
273
  # @api private
267
274
  # @see SearchContext
@@ -271,14 +278,6 @@ module Selenium
271
278
  nil
272
279
  end
273
280
 
274
- def browser
275
- bridge.browser
276
- end
277
-
278
- def capabilities
279
- bridge.capabilities
280
- end
281
-
282
281
  private
283
282
 
284
283
  def bridge
@@ -1,5 +1,5 @@
1
- require "rbconfig"
2
- require "socket"
1
+ require 'rbconfig'
2
+ require 'socket'
3
3
 
4
4
  module Selenium
5
5
  module WebDriver
@@ -20,7 +20,7 @@ module Selenium
20
20
  #
21
21
  # When using Element#find_element with :xpath, be aware that webdriver
22
22
  # follows standard conventions: a search prefixed with "//" will search
23
- # the entire document, not just the children of this current node. Use
23
+ # the entire document, not just the children of this current node. Use
24
24
  # ".//" to limit your search to the children of the receiving Element.
25
25
  #
26
26
  # @param [:class, :class_name, :id, :link_text, :link, :partial_link_text, :name, :tag_name, :xpath] how
@@ -75,11 +75,13 @@ module Selenium
75
75
  args
76
76
  when 1
77
77
  arg = args.first
78
+
78
79
  unless arg.respond_to?(:shift)
79
80
  raise ArgumentError, "expected #{arg.inspect}:#{arg.class} to respond to #shift"
80
81
  end
81
82
 
82
- arr = arg.shift
83
+ # this will be a single-entry hash, so use #shift over #first or #[]
84
+ arr = arg.dup.shift
83
85
  unless arr.size == 2
84
86
  raise ArgumentError, "expected #{arr.inspect} to have 2 elements"
85
87
  end
@@ -1,5 +1,5 @@
1
- require "selenium/webdriver/common/platform"
2
- require "socket"
1
+ require 'selenium/webdriver/common/platform'
2
+ require 'socket'
3
3
 
4
4
  module Selenium
5
5
  module WebDriver
@@ -36,17 +36,47 @@ module Selenium
36
36
 
37
37
  private
38
38
 
39
- SOCKET_ERRORS = [Errno::ECONNREFUSED, Errno::ENOTCONN, SocketError]
40
- SOCKET_ERRORS << Errno::EPERM if Platform.cygwin?
39
+ CONNECT_TIMEOUT = 5
41
40
 
42
- def listening?
43
- # There's a bug in 1.9.1 on Windows where this will succeed even if no
44
- # one is listening. Users who hit that should upgrade their Ruby.
45
- TCPSocket.new(@host, @port).close
46
- true
47
- rescue *SOCKET_ERRORS => e
48
- $stderr.puts [@host, @port].inspect if $DEBUG
49
- false
41
+ NOT_CONNECTED_ERRORS = [Errno::ECONNREFUSED, Errno::ENOTCONN, SocketError]
42
+ NOT_CONNECTED_ERRORS << Errno::EPERM if Platform.cygwin?
43
+
44
+ CONNECTED_ERRORS = [Errno::EISCONN]
45
+ CONNECTED_ERRORS << Errno::EINVAL if Platform.win?
46
+
47
+ if Platform.jruby?
48
+ # we use a plain TCPSocket here since JRuby has issues select()ing on a connecting socket
49
+ # see http://jira.codehaus.org/browse/JRUBY-5165
50
+ def listening?
51
+ TCPSocket.new(@host, @port).close
52
+ true
53
+ rescue *NOT_CONNECTED_ERRORS
54
+ false
55
+ end
56
+ else
57
+ def listening?
58
+ addr = Socket.getaddrinfo(@host, @port, Socket::AF_INET, Socket::SOCK_STREAM)
59
+ sock = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
60
+ sockaddr = Socket.pack_sockaddr_in(@port, addr[0][3])
61
+
62
+ begin
63
+ sock.connect_nonblock sockaddr
64
+ rescue Errno::EINPROGRESS
65
+ if IO.select(nil, [sock], nil, CONNECT_TIMEOUT)
66
+ retry
67
+ else
68
+ raise Errno::ECONNREFUSED
69
+ end
70
+ rescue *CONNECTED_ERRORS
71
+ # yay!
72
+ end
73
+
74
+ sock.close
75
+ true
76
+ rescue *NOT_CONNECTED_ERRORS => e
77
+ $stderr.puts [@host, @port].inspect if $DEBUG
78
+ false
79
+ end
50
80
  end
51
81
 
52
82
  def with_timeout(&blk)
@@ -11,7 +11,7 @@ module Selenium
11
11
  #
12
12
 
13
13
  def implicit_wait=(seconds)
14
- @bridge.setImplicitWaitTimeout seconds * 1000
14
+ @bridge.setImplicitWaitTimeout Integer(seconds * 1000)
15
15
  end
16
16
 
17
17
  #
@@ -21,7 +21,7 @@ module Selenium
21
21
  #
22
22
 
23
23
  def script_timeout=(seconds)
24
- @bridge.setScriptTimeout seconds * 1000
24
+ @bridge.setScriptTimeout Integer(seconds * 1000)
25
25
  end
26
26
 
27
27
  end # Timeouts
@@ -1,15 +1,15 @@
1
- require "timeout"
2
- require "socket"
3
- require "rexml/document"
1
+ require 'timeout'
2
+ require 'socket'
3
+ require 'rexml/document'
4
4
 
5
- require "selenium/webdriver/firefox/util"
6
- require "selenium/webdriver/firefox/extension"
7
- require "selenium/webdriver/firefox/socket_lock"
8
- require "selenium/webdriver/firefox/binary"
9
- require "selenium/webdriver/firefox/profiles_ini"
10
- require "selenium/webdriver/firefox/profile"
11
- require "selenium/webdriver/firefox/launcher"
12
- require "selenium/webdriver/firefox/bridge"
5
+ require 'selenium/webdriver/firefox/util'
6
+ require 'selenium/webdriver/firefox/extension'
7
+ require 'selenium/webdriver/firefox/socket_lock'
8
+ require 'selenium/webdriver/firefox/binary'
9
+ require 'selenium/webdriver/firefox/profiles_ini'
10
+ require 'selenium/webdriver/firefox/profile'
11
+ require 'selenium/webdriver/firefox/launcher'
12
+ require 'selenium/webdriver/firefox/bridge'
13
13
 
14
14
  module Selenium
15
15
  module WebDriver
@@ -133,7 +133,7 @@ module Selenium
133
133
  end
134
134
 
135
135
  def windows_registry_path
136
- require "win32/registry"
136
+ require 'win32/registry'
137
137
 
138
138
  lm = Win32::Registry::HKEY_LOCAL_MACHINE
139
139
  lm.open("SOFTWARE\\Mozilla\\Mozilla Firefox") do |reg|
@@ -4,8 +4,6 @@ module Selenium
4
4
 
5
5
  # @api private
6
6
  class Extension
7
- EM_NAMESPACE_URI = "http://www.mozilla.org/2004/em-rdf#" # not used?
8
-
9
7
  def initialize(path)
10
8
  unless File.exist?(path)
11
9
  raise Error::WebDriverError, "could not find extension at #{path.inspect}"
@@ -50,7 +50,7 @@ module Selenium
50
50
  end
51
51
 
52
52
  def create_profile
53
- fetch_profile if @profile.nil?
53
+ fetch_profile unless @profile
54
54
 
55
55
  @profile.add_webdriver_extension
56
56
  @profile.port = @port
@@ -64,12 +64,14 @@ module Selenium
64
64
 
65
65
  def start_silent_and_wait
66
66
  assert_profile
67
+
67
68
  @binary.start_with @profile, @profile_dir, "-silent"
68
69
  @binary.wait
69
70
  end
70
71
 
71
72
  def connect_until_stable
72
73
  poller = SocketPoller.new(@host, @port, STABLE_CONNECTION_TIMEOUT)
74
+
73
75
  unless poller.connected?
74
76
  @binary.quit
75
77
  raise Error::WebDriverError, "unable to obtain stable firefox connection in #{STABLE_CONNECTION_TIMEOUT} seconds (#{@host}:#{@port})"
@@ -79,7 +81,8 @@ module Selenium
79
81
  def fetch_profile
80
82
  if @profile_name
81
83
  @profile = Profile.from_name @profile_name
82
- if @profile.nil?
84
+
85
+ unless @profile
83
86
  raise Error::WebDriverError, "unable to find profile named: #{@profile_name.inspect}"
84
87
  end
85
88
  else
@@ -3,8 +3,6 @@ module Selenium
3
3
  module Firefox
4
4
  class Profile
5
5
 
6
- ANONYMOUS_PROFILE_NAME = "WEBDRIVER_ANONYMOUS_PROFILE"
7
- EXTENSION_NAME = "fxdriver@googlecode.com"
8
6
  WEBDRIVER_EXTENSION_PATH = File.expand_path("#{WebDriver.root}/selenium/webdriver/firefox/extension/webdriver.xpi")
9
7
  WEBDRIVER_PREFS = {
10
8
  :native_events => 'webdriver_enable_native_events',
@@ -46,7 +46,7 @@ module Selenium
46
46
  ChildProcess.close_on_exec @server
47
47
 
48
48
  true
49
- rescue SocketError, Errno::EADDRINUSE => ex
49
+ rescue SocketError, Errno::EADDRINUSE, Errno::EBADF => ex
50
50
  $stderr.puts "#{self}: #{ex.message}" if $DEBUG
51
51
  false
52
52
  end
@@ -13,7 +13,7 @@ module Selenium
13
13
  end
14
14
  end
15
15
 
16
- require "ffi"
16
+ require 'ffi'
17
17
 
18
- require "selenium/webdriver/ie/server"
19
- require "selenium/webdriver/ie/bridge"
18
+ require 'selenium/webdriver/ie/server'
19
+ require 'selenium/webdriver/ie/bridge'
@@ -6,4 +6,4 @@ module Selenium
6
6
  end # WebDriver
7
7
  end # Selenium
8
8
 
9
- require "selenium/webdriver/iphone/bridge"
9
+ require 'selenium/webdriver/iphone/bridge'
@@ -1,12 +1,12 @@
1
- require "uri"
1
+ require 'uri'
2
2
 
3
- require "selenium/webdriver/remote/capabilities"
4
- require "selenium/webdriver/remote/bridge"
5
- require "selenium/webdriver/remote/server_error"
6
- require "selenium/webdriver/remote/response"
7
- require "selenium/webdriver/remote/commands"
8
- require "selenium/webdriver/remote/http/common"
9
- require "selenium/webdriver/remote/http/default"
3
+ require 'selenium/webdriver/remote/capabilities'
4
+ require 'selenium/webdriver/remote/bridge'
5
+ require 'selenium/webdriver/remote/server_error'
6
+ require 'selenium/webdriver/remote/response'
7
+ require 'selenium/webdriver/remote/commands'
8
+ require 'selenium/webdriver/remote/http/common'
9
+ require 'selenium/webdriver/remote/http/default'
10
10
 
11
11
  module Selenium
12
12
  module WebDriver
@@ -7,17 +7,28 @@ module Selenium
7
7
  #
8
8
  class Capabilities
9
9
 
10
- attr_reader :proxy
11
-
12
- attr_accessor :css_selectors_enabled,
13
- :javascript_enabled,
14
- :native_events,
15
- :platform,
16
- :takes_screenshot,
17
- :rotatable,
18
- :version,
19
- :browser_name,
20
- :firefox_profile
10
+ DEFAULTS = {
11
+ :browser_name => "",
12
+ :version => "",
13
+ :platform => :any,
14
+ :javascript_enabled => false,
15
+ :css_selectors_enabled => false,
16
+ :takes_screenshot => false,
17
+ :native_events => false,
18
+ :rotatable => false,
19
+ :firefox_profile => nil,
20
+ :proxy => nil
21
+ }
22
+
23
+ DEFAULTS.each_key do |key|
24
+ define_method key do
25
+ @capabilities.fetch(key)
26
+ end
27
+
28
+ define_method "#{key}=" do |value|
29
+ @capabilities[key] = value
30
+ end
31
+ end
21
32
 
22
33
  alias_method :css_selectors_enabled?, :css_selectors_enabled
23
34
  alias_method :javascript_enabled? , :javascript_enabled
@@ -92,17 +103,23 @@ module Selenium
92
103
  #
93
104
 
94
105
  def json_create(data)
95
- new(
96
- :browser_name => data["browserName"],
97
- :version => data["version"],
98
- :platform => data["platform"].downcase.to_sym,
99
- :javascript_enabled => data["javascriptEnabled"],
100
- :css_selectors_enabled => data["cssSelectorsEnabled"],
101
- :takes_screenshot => data["takesScreenshot"],
102
- :native_events => data["nativeEvents"],
103
- :rotatable => data["rotatable"],
104
- :proxy => (Proxy.json_create(data['proxy']) if data['proxy'])
105
- )
106
+ data = data.dup
107
+
108
+ caps = new
109
+ caps.browser_name = data.delete("browserName")
110
+ caps.version = data.delete("version")
111
+ caps.platform = data.delete("platform").downcase.to_sym
112
+ caps.javascript_enabled = data.delete("javascriptEnabled")
113
+ caps.css_selectors_enabled = data.delete("cssSelectorsEnabled")
114
+ caps.takes_screenshot = data.delete("takesScreenshot")
115
+ caps.native_events = data.delete("nativeEvents")
116
+ caps.rotatable = data.delete("rotatable")
117
+ caps.proxy = Proxy.json_create(data['proxy']) if data.has_key?('proxy')
118
+
119
+ # any remaining pairs will be added as is, with no conversion
120
+ caps.merge!(data)
121
+
122
+ caps
106
123
  end
107
124
  end
108
125
 
@@ -112,36 +129,49 @@ module Selenium
112
129
  # @option :javascript_enabled [Boolean] does the driver have javascript enabled?
113
130
  # @option :css_selectors_enabled [Boolean] does the driver support CSS selectors?
114
131
  # @option :takes_screenshot [Boolean] can this driver take screenshots?
115
- # @option :native_events [Boolean] does this driver use native events?
116
- # @option :proxy [Selenium::WebDriver::Proxy, Hash] proxy configuration
132
+ # @option :native_events [Boolean] does this driver use native events?
133
+ # @option :proxy [Selenium::WebDriver::Proxy, Hash] proxy configuration
117
134
  #
118
135
  # Firefox-specific options:
119
136
  #
120
- # @option :firefox_profile [Selenium::WebDriver::Firefox::Profile] the firefox profile to use
137
+ # @option :firefox_profile [Selenium::WebDriver::Firefox::Profile] the firefox profile to use
121
138
  #
122
139
  # @api public
123
140
  #
124
141
 
125
142
  def initialize(opts = {})
126
- @browser_name = opts[:browser_name] || ""
127
- @version = opts[:version] || ""
128
- @platform = opts[:platform] || :any
129
- @javascript_enabled = opts[:javascript_enabled] || false
130
- @css_selectors_enabled = opts[:css_selectors_enabled] || false
131
- @takes_screenshot = opts[:takes_screenshot] || false
132
- @native_events = opts[:native_events] || false
133
- @rotatable = opts[:rotatable] || false
134
- @firefox_profile = opts[:firefox_profile]
135
-
136
- self.proxy = opts[:proxy]
143
+ @capabilities = DEFAULTS.merge(opts)
144
+ self.proxy = opts.delete(:proxy)
145
+ end
146
+
147
+ #
148
+ # Allows setting arbitrary capabilities.
149
+ #
150
+
151
+ def []=(key, value)
152
+ @capabilities[key] = value
153
+ end
154
+
155
+ def [](key)
156
+ @capabilities[key]
157
+ end
158
+
159
+ def merge!(other)
160
+ if other.respond_to?(:capabilities) && other.capabilities.kind_of?(Hash)
161
+ @capabilities.merge! other.capabilities
162
+ elsif other.kind_of? Hash
163
+ @capabilities.merge! other
164
+ else
165
+ raise ArgumentError, "argument should be a Hash or implement #capabilities"
166
+ end
137
167
  end
138
168
 
139
169
  def proxy=(proxy)
140
170
  case proxy
141
171
  when Hash
142
- @proxy = Proxy.new(proxy)
172
+ @capabilities[:proxy] = Proxy.new(proxy)
143
173
  when Proxy, nil
144
- @proxy = proxy
174
+ @capabilities[:proxy] = proxy
145
175
  else
146
176
  raise TypeError, "expected Hash or #{Proxy.name}, got #{proxy.inspect}:#{proxy.class}"
147
177
  end
@@ -151,19 +181,24 @@ module Selenium
151
181
  #
152
182
 
153
183
  def as_json(opts = nil)
154
- hash = {
155
- "browserName" => browser_name,
156
- "version" => version,
157
- "platform" => platform.to_s.upcase,
158
- "javascriptEnabled" => javascript_enabled?,
159
- "cssSelectorsEnabled" => css_selectors_enabled?,
160
- "takesScreenshot" => takes_screenshot?,
161
- "nativeEvents" => native_events?,
162
- "rotatable" => rotatable?,
163
- }
164
-
165
- hash["proxy"] = proxy.as_json if proxy
166
- hash['firefox_profile'] = firefox_profile.as_json['zip'] if firefox_profile
184
+ hash = {}
185
+
186
+ @capabilities.each do |key, value|
187
+ case key
188
+ when :platform
189
+ hash['platform'] = value.to_s.upcase
190
+ when :firefox_profile
191
+ hash['firefox_profile'] = value.as_json['zip'] if value
192
+ when :proxy
193
+ hash['proxy'] = value.as_json if value
194
+ when String
195
+ hash[key] = value
196
+ when Symbol
197
+ hash[camel_case(key.to_s)] = value
198
+ else
199
+ raise TypeError, "expected String or Symbol, got #{key.inspect}:#{key.class} / #{value.inspect}"
200
+ end
201
+ end
167
202
 
168
203
  hash
169
204
  end
@@ -178,6 +213,18 @@ module Selenium
178
213
  end
179
214
  alias_method :eql?, :==
180
215
 
216
+ protected
217
+
218
+ def capabilities
219
+ @capabilities
220
+ end
221
+
222
+ private
223
+
224
+ def camel_case(str)
225
+ str.gsub(/_([a-z])/) { $1.upcase }
226
+ end
227
+
181
228
  end # Capabilities
182
229
  end # Remote
183
230
  end # WebDriver
@@ -1,4 +1,4 @@
1
- require "net/https"
1
+ require 'net/https'
2
2
 
3
3
  module Selenium
4
4
  module WebDriver
@@ -1,4 +1,4 @@
1
- require "net/http/persistent"
1
+ require 'net/http/persistent'
2
2
 
3
3
  module Selenium
4
4
  module WebDriver
metadata CHANGED
@@ -1,8 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: selenium-webdriver
3
3
  version: !ruby/object:Gem::Version
4
- prerelease:
5
- version: 0.2.0
4
+ hash: 21
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 2
9
+ - 1
10
+ version: 0.2.1
6
11
  platform: ruby
7
12
  authors:
8
13
  - Jari Bakken
@@ -10,7 +15,8 @@ autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
17
 
13
- date: 2011-04-22 00:00:00 Z
18
+ date: 2011-06-01 00:00:00 +02:00
19
+ default_executable:
14
20
  dependencies:
15
21
  - !ruby/object:Gem::Dependency
16
22
  name: json_pure
@@ -20,6 +26,9 @@ dependencies:
20
26
  requirements:
21
27
  - - ">="
22
28
  - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
23
32
  version: "0"
24
33
  type: :runtime
25
34
  version_requirements: *id001
@@ -31,6 +40,9 @@ dependencies:
31
40
  requirements:
32
41
  - - ">="
33
42
  - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
34
46
  version: "0"
35
47
  type: :runtime
36
48
  version_requirements: *id002
@@ -42,6 +54,11 @@ dependencies:
42
54
  requirements:
43
55
  - - ">="
44
56
  - !ruby/object:Gem::Version
57
+ hash: 21
58
+ segments:
59
+ - 0
60
+ - 1
61
+ - 7
45
62
  version: 0.1.7
46
63
  type: :runtime
47
64
  version_requirements: *id003
@@ -53,6 +70,11 @@ dependencies:
53
70
  requirements:
54
71
  - - ">="
55
72
  - !ruby/object:Gem::Version
73
+ hash: 25
74
+ segments:
75
+ - 1
76
+ - 0
77
+ - 7
56
78
  version: 1.0.7
57
79
  type: :runtime
58
80
  version_requirements: *id004
@@ -64,6 +86,10 @@ dependencies:
64
86
  requirements:
65
87
  - - ~>
66
88
  - !ruby/object:Gem::Version
89
+ hash: 3
90
+ segments:
91
+ - 2
92
+ - 0
67
93
  version: "2.0"
68
94
  type: :development
69
95
  version_requirements: *id005
@@ -75,6 +101,10 @@ dependencies:
75
101
  requirements:
76
102
  - - ~>
77
103
  - !ruby/object:Gem::Version
104
+ hash: 15
105
+ segments:
106
+ - 1
107
+ - 0
78
108
  version: "1.0"
79
109
  type: :development
80
110
  version_requirements: *id006
@@ -86,6 +116,11 @@ dependencies:
86
116
  requirements:
87
117
  - - ~>
88
118
  - !ruby/object:Gem::Version
119
+ hash: 11
120
+ segments:
121
+ - 1
122
+ - 6
123
+ - 2
89
124
  version: 1.6.2
90
125
  type: :development
91
126
  version_requirements: *id007
@@ -178,6 +213,7 @@ files:
178
213
  - lib/selenium-webdriver.rb
179
214
  - CHANGES
180
215
  - README
216
+ has_rdoc: true
181
217
  homepage: http://selenium.googlecode.com
182
218
  licenses: []
183
219
 
@@ -191,17 +227,23 @@ required_ruby_version: !ruby/object:Gem::Requirement
191
227
  requirements:
192
228
  - - ">="
193
229
  - !ruby/object:Gem::Version
230
+ hash: 3
231
+ segments:
232
+ - 0
194
233
  version: "0"
195
234
  required_rubygems_version: !ruby/object:Gem::Requirement
196
235
  none: false
197
236
  requirements:
198
237
  - - ">="
199
238
  - !ruby/object:Gem::Version
239
+ hash: 3
240
+ segments:
241
+ - 0
200
242
  version: "0"
201
243
  requirements: []
202
244
 
203
245
  rubyforge_project:
204
- rubygems_version: 1.7.2
246
+ rubygems_version: 1.3.7
205
247
  signing_key:
206
248
  specification_version: 3
207
249
  summary: The next generation developer focused tool for automated testing of webapps