selenium-webdriver 0.1.2 → 0.1.3.dev

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 +18 -1
  2. data/lib/selenium/client/legacy_driver.rb +9 -0
  3. data/lib/selenium/webdriver/android/bridge.rb +1 -1
  4. data/lib/selenium/webdriver/chrome/bridge.rb +0 -4
  5. data/lib/selenium/webdriver/chrome/command_executor.rb +2 -2
  6. data/lib/selenium/webdriver/chrome/extension.zip +0 -0
  7. data/lib/selenium/webdriver/common.rb +3 -0
  8. data/lib/selenium/webdriver/common/driver_extensions/has_input_devices.rb +22 -0
  9. data/lib/selenium/webdriver/common/element.rb +10 -0
  10. data/lib/selenium/webdriver/common/keyboard.rb +48 -0
  11. data/lib/selenium/webdriver/common/mouse.rb +63 -0
  12. data/lib/selenium/webdriver/common/platform.rb +26 -11
  13. data/lib/selenium/webdriver/common/proxy.rb +1 -1
  14. data/lib/selenium/webdriver/common/zipper.rb +0 -1
  15. data/lib/selenium/webdriver/firefox/bridge.rb +8 -8
  16. data/lib/selenium/webdriver/firefox/extension/webdriver.xpi +0 -0
  17. data/lib/selenium/webdriver/firefox/launcher.rb +1 -1
  18. data/lib/selenium/webdriver/firefox/native/linux/amd64/x_ignore_nofocus.so +0 -0
  19. data/lib/selenium/webdriver/firefox/native/linux/x86/x_ignore_nofocus.so +0 -0
  20. data/lib/selenium/webdriver/firefox/profile.rb +9 -5
  21. data/lib/selenium/webdriver/firefox/socket_lock.rb +1 -11
  22. data/lib/selenium/webdriver/ie.rb +3 -1
  23. data/lib/selenium/webdriver/ie/bridge.rb +23 -12
  24. data/lib/selenium/webdriver/ie/native/win32/IEDriver.dll +0 -0
  25. data/lib/selenium/webdriver/ie/native/x64/IEDriver.dll +0 -0
  26. data/lib/selenium/webdriver/ie/server.rb +64 -0
  27. data/lib/selenium/webdriver/iphone/bridge.rb +1 -1
  28. data/lib/selenium/webdriver/remote/bridge.rb +62 -8
  29. data/lib/selenium/webdriver/remote/capabilities.rb +10 -3
  30. data/lib/selenium/webdriver/remote/commands.rb +67 -59
  31. data/lib/selenium/webdriver/remote/http/common.rb +4 -0
  32. data/lib/selenium/webdriver/remote/http/default.rb +10 -4
  33. data/lib/selenium/webdriver/remote/http/persistent.rb +34 -0
  34. metadata +169 -196
  35. data/lib/selenium/webdriver/ie/lib.rb +0 -26
data/CHANGES CHANGED
@@ -1,4 +1,21 @@
1
- 0.1.2 (2010-12-??)
1
+ 0.1.3 (???)
2
+ ============
3
+
4
+ * Screenshot support in the IE and Remote drivers.
5
+ * Fixed paths for IE DLLs on Cygwin.
6
+ * Several crashing bugs fixed in the IE driver.
7
+ * Fix #1152 by avoiding IPv6 loopback.
8
+ * Added Mouse and Keyboard classes, accessible as Driver#{mouse,keyboard}. Considered experimental (IE + HtmlUnit only at the moment).
9
+ * Automation atoms now used extensively in the IE driver.
10
+ * Firefox::Bridge is now easier to extend (i.e. with a custom launcher).
11
+ * Add S::W::Remote::Http::Persistent (currently only usable with the remote server).
12
+ * IE driver passes along options like the other remote drivers, enabling user-specified HTTP clients.
13
+ * :firefox_profile added to Remote::Capabilities, enabling passing a profile to remote Firefoxes.
14
+ * IE driver now supports launching multiple instances of the browser.
15
+ * Remove some Ruby warnings (uninitialized ivars, URI.escape).
16
+
17
+
18
+ 0.1.2 (2010-12-22)
2
19
  ============
3
20
 
4
21
  * Changed frame switching behaviour (http://groups.google.com/group/selenium-developers/browse_thread/thread/8dc7938c35bb3968)
@@ -1334,6 +1334,15 @@ module Selenium
1334
1334
  end
1335
1335
 
1336
1336
 
1337
+ # Returns the number of nodes that match the specified css selector, eg. "css=table" would give
1338
+ # the number of tables.
1339
+ #
1340
+ # 'css' is the css selector to evaluate. do NOT wrap this expression in a 'count()' function; we will do that for you.
1341
+ def get_css_count(css)
1342
+ return number_command("getCssCount", [css,])
1343
+ end
1344
+
1345
+
1337
1346
  # Temporarily sets the "id" attribute of the specified element, so you can locate it in the future
1338
1347
  # using its ID rather than a slow/complicated XPath. This ID will disappear once the page is
1339
1348
  # reloaded.
@@ -3,7 +3,7 @@ module Selenium
3
3
  module Android
4
4
  class Bridge < Remote::Bridge
5
5
 
6
- DEFAULT_URL = "http://localhost:8080/hub"
6
+ DEFAULT_URL = "http://#{Platform.localhost}:8080/hub"
7
7
 
8
8
  def initialize(opts = nil)
9
9
  if opts
@@ -37,10 +37,6 @@ module Selenium
37
37
  @launcher.quit
38
38
  end
39
39
 
40
- def getScreenshot
41
- execute :screenshot
42
- end
43
-
44
40
  def setSpeed(value)
45
41
  @speed = value
46
42
  end
@@ -46,13 +46,13 @@ module Selenium
46
46
  end
47
47
 
48
48
  def uri
49
- "http://localhost:#{port}/chromeCommandExecutor"
49
+ "http://#{Platform.localhost}:#{port}/chromeCommandExecutor"
50
50
  end
51
51
 
52
52
  private
53
53
 
54
54
  def localhost
55
- Platform.ironruby? ? "localhost" : "0.0.0.0" # yeah, weird..
55
+ Platform.ironruby? ? Platform.localhost : "0.0.0.0" # yeah, weird..
56
56
  end
57
57
 
58
58
  def start_run_loop
@@ -8,6 +8,8 @@ require "selenium/webdriver/common/socket_poller"
8
8
  require "selenium/webdriver/common/zipper"
9
9
  require "selenium/webdriver/common/wait"
10
10
  require "selenium/webdriver/common/alert"
11
+ require "selenium/webdriver/common/mouse"
12
+ require "selenium/webdriver/common/keyboard"
11
13
  require "selenium/webdriver/common/target_locator"
12
14
  require "selenium/webdriver/common/navigation"
13
15
  require "selenium/webdriver/common/timeouts"
@@ -15,6 +17,7 @@ require "selenium/webdriver/common/options"
15
17
  require "selenium/webdriver/common/find"
16
18
  require "selenium/webdriver/common/driver_extensions/takes_screenshot"
17
19
  require "selenium/webdriver/common/driver_extensions/rotatable"
20
+ require "selenium/webdriver/common/driver_extensions/has_input_devices"
18
21
  require "selenium/webdriver/common/keys"
19
22
  require "selenium/webdriver/common/bridge_helper"
20
23
  require "selenium/webdriver/common/driver"
@@ -0,0 +1,22 @@
1
+ module Selenium
2
+ module WebDriver
3
+
4
+ #
5
+ # @api private
6
+ #
7
+
8
+ module DriverExtensions
9
+ module HasInputDevices
10
+
11
+ def mouse
12
+ Mouse.new @bridge
13
+ end
14
+
15
+ def keyboard
16
+ Keyboard.new @bridge
17
+ end
18
+
19
+ end # HasInputDevices
20
+ end # DriverExtensions
21
+ end # WebDriver
22
+ end # Selenium
@@ -213,6 +213,16 @@ module Selenium
213
213
  bridge.getElementLocation @id
214
214
  end
215
215
 
216
+ #
217
+ # Determine an element's location on the screen once it has been scrolled into view.
218
+ #
219
+ # @return [WebDriver::Point]
220
+ #
221
+
222
+ def location_once_scrolled_into_view
223
+ bridge.getElementLocationOnceScrolledIntoView @id
224
+ end
225
+
216
226
  #
217
227
  # Get the size of this element
218
228
  #
@@ -0,0 +1,48 @@
1
+ module Selenium
2
+ module WebDriver
3
+ class Keyboard
4
+
5
+ def initialize(bridge)
6
+ @bridge = bridge
7
+ end
8
+
9
+ def send_keys(*keys)
10
+ @bridge.getActiveElement.send_keys(*keys)
11
+ end
12
+
13
+ #
14
+ # Release a modifier key
15
+ #
16
+ # @see Selenium::WebDriver::Keys
17
+ #
18
+
19
+ def press(key)
20
+ assert_modifier key
21
+ @bridge.sendModifierKeyToActiveElement Keys[key], true
22
+ end
23
+
24
+ #
25
+ # Release a modifier key
26
+ #
27
+ # @see Selenium::WebDriver::Keys
28
+ #
29
+
30
+ def release(key)
31
+ assert_modifier key
32
+ @bridge.sendModifierKeyToActiveElement Keys[key], false
33
+ end
34
+
35
+ private
36
+
37
+ MODIFIERS = [:control, :shift, :alt, :command, :meta]
38
+
39
+ def assert_modifier(key)
40
+ unless MODIFIERS.include? key
41
+ raise Error::UnsupportedOperationError,
42
+ "#{key.inspect} is not a modifier key, expected one of #{MODIFIERS.inspect}"
43
+ end
44
+ end
45
+
46
+ end # Keyboard
47
+ end # WebDriver
48
+ end # Selenium
@@ -0,0 +1,63 @@
1
+ module Selenium
2
+ module WebDriver
3
+ class Mouse
4
+
5
+ def initialize(bridge)
6
+ @bridge = bridge
7
+ end
8
+
9
+ def click(element = nil)
10
+ move_if_needed element
11
+ @bridge.click
12
+ end
13
+
14
+ def double_click(element = nil)
15
+ move_if_needed element
16
+ @bridge.doubleClick
17
+ end
18
+
19
+ def context_click(element = nil)
20
+ move_if_needed element
21
+ @bridge.contextClick
22
+ end
23
+
24
+ def down(element = nil)
25
+ move_if_needed element
26
+ @bridge.mouseDown
27
+ end
28
+
29
+ def up(element = nil)
30
+ move_if_needed element
31
+ @bridge.mouseUp
32
+ end
33
+
34
+ #
35
+ # Move the mouse.
36
+ #
37
+ # Examples:
38
+ #
39
+ # driver.mouse.move_to(element)
40
+ # driver.mouse.move_to(element, 5, 5)
41
+ #
42
+
43
+ def move_to(element, down_by = nil, right_by = nil)
44
+ unless element.kind_of? Element
45
+ raise TypeError, "expected #{Element}, got #{element.inspect}:#{element.class}"
46
+ end
47
+
48
+ @bridge.mouseMoveTo element.ref, down_by, right_by
49
+ end
50
+
51
+ def move_by(down_by, right_by)
52
+ @bridge.mouseMoveTo nil, down_by, right_by
53
+ end
54
+
55
+ private
56
+
57
+ def move_if_needed(element)
58
+ move_to element if element
59
+ end
60
+
61
+ end # Mouse
62
+ end # WebDriver
63
+ end # Selenium
@@ -1,4 +1,5 @@
1
1
  require "rbconfig"
2
+ require "socket"
2
3
 
3
4
  module Selenium
4
5
  module WebDriver
@@ -84,15 +85,18 @@ module Selenium
84
85
  end
85
86
 
86
87
  def cygwin?
87
- RUBY_PLATFORM =~ /cygwin/
88
+ !!(RUBY_PLATFORM =~ /cygwin/)
88
89
  end
89
90
 
90
91
  def wrap_in_quotes_if_necessary(str)
91
92
  win? && !cygwin? ? %{"#{str}"} : str
92
93
  end
93
94
 
94
- def cygwin_path(path)
95
- `cygpath "#{path}"`.strip
95
+ def cygwin_path(path, opts = {})
96
+ flags = []
97
+ opts.each { |k,v| flags << "--#{k}" if v }
98
+
99
+ `cygpath #{flags.join ' '} "#{path}"`.strip
96
100
  end
97
101
 
98
102
  def make_writable(file)
@@ -123,17 +127,28 @@ module Selenium
123
127
  nil
124
128
  end
125
129
 
130
+ def localhost
131
+ info = Socket.getaddrinfo "localhost", 80, Socket::AF_INET, Socket::SOCK_STREAM
132
+
133
+ if info.empty?
134
+ raise Error::WebDriverError, "unable to translate 'localhost' for TCP+IPv6"
135
+ end
136
+
137
+ info[0][3]
138
+ end
139
+
126
140
  end # Platform
127
141
  end # WebDriver
128
142
  end # Selenium
129
143
 
130
144
  if __FILE__ == $0
131
- p :engine => Selenium::WebDriver::Platform.engine,
132
- :os => Selenium::WebDriver::Platform.os,
133
- :ruby187? => Selenium::WebDriver::Platform.ruby187?,
134
- :ruby19? => Selenium::WebDriver::Platform.ruby19?,
135
- :jruby? => Selenium::WebDriver::Platform.jruby?,
136
- :win? => Selenium::WebDriver::Platform.win?,
137
- :home => Selenium::WebDriver::Platform.home,
138
- :bitsize => Selenium::WebDriver::Platform.bitsize
145
+ p :engine => Selenium::WebDriver::Platform.engine,
146
+ :os => Selenium::WebDriver::Platform.os,
147
+ :ruby187? => Selenium::WebDriver::Platform.ruby187?,
148
+ :ruby19? => Selenium::WebDriver::Platform.ruby19?,
149
+ :jruby? => Selenium::WebDriver::Platform.jruby?,
150
+ :win? => Selenium::WebDriver::Platform.win?,
151
+ :home => Selenium::WebDriver::Platform.home,
152
+ :bitsize => Selenium::WebDriver::Platform.bitsize,
153
+ :localhost => Selenium::WebDriver::Platform.localhost
139
154
  end
@@ -73,7 +73,7 @@ module Selenium
73
73
  raise ArgumentError, "invalid proxy type: #{type.inspect}, expected one of #{TYPES.keys.inspect}"
74
74
  end
75
75
 
76
- if @type && type != @type
76
+ if defined?(@type) && type != @type
77
77
  raise ArgumentError, "incompatible proxy type #{type.inspect} (already set to #{@type.inspect})"
78
78
  end
79
79
 
@@ -37,7 +37,6 @@ module Selenium
37
37
 
38
38
  zos.put_next_entry(entry)
39
39
  zos << File.read(file)
40
- p :added => file, :as => entry
41
40
  end
42
41
 
43
42
  zos.close
@@ -6,14 +6,12 @@ module Selenium
6
6
  class Bridge < Remote::Bridge
7
7
 
8
8
  def initialize(opts = {})
9
- @launcher = Launcher.new(
10
- Binary.new,
11
- opts.delete(:port) || DEFAULT_PORT,
12
- opts.delete(:profile)
13
- )
14
-
9
+ port = opts.delete(:port) || DEFAULT_PORT
10
+ profile = opts.delete(:profile)
15
11
  http_client = opts.delete(:http_client)
16
12
 
13
+ @launcher = create_launcher(port, profile)
14
+
17
15
  unless opts.empty?
18
16
  raise ArgumentError, "unknown option#{'s' if opts.size != 1}: #{opts.inspect}"
19
17
  end
@@ -45,8 +43,10 @@ module Selenium
45
43
  nil
46
44
  end
47
45
 
48
- def getScreenshot
49
- execute :screenshot
46
+ private
47
+
48
+ def create_launcher(port, profile)
49
+ Launcher.new Binary.new, port, profile
50
50
  end
51
51
 
52
52
  end # Bridge
@@ -78,7 +78,7 @@ module Selenium
78
78
  poller = SocketPoller.new(@host, @port, STABLE_CONNECTION_TIMEOUT)
79
79
  unless poller.connected?
80
80
  @binary.quit
81
- raise Error::WebDriverError, "unable to obtain stable firefox connection in #{STABLE_CONNECTION_TIMEOUT} seconds"
81
+ raise Error::WebDriverError, "unable to obtain stable firefox connection in #{STABLE_CONNECTION_TIMEOUT} seconds (#{@host}:#{@port})"
82
82
  end
83
83
  end
84
84
 
@@ -49,14 +49,18 @@ module Selenium
49
49
  @secure_ssl = DEFAULT_SECURE_SSL
50
50
  @untrusted_issuer = DEFAULT_ASSUME_UNTRUSTED_ISSUER
51
51
  @load_no_focus_lib = DEFAULT_LOAD_NO_FOCUS_LIB
52
+
53
+ @additional_prefs = {}
52
54
  else
53
- @native_events = model_prefs[WEBDRIVER_PREFS[:native_events]] == "true"
54
- @secure_ssl = model_prefs[WEBDRIVER_PREFS[:untrusted_certs]] != "true" # FIXME: 'untrusted_certs' vs 'secure_ssl'
55
- @untrusted_issuer = model_prefs[WEBDRIVER_PREFS[:untrusted_issuer]] == "true"
56
- @load_no_focus_lib = model_prefs[WEBDRIVER_PREFS[:load_no_focus_lib]] == "true" # not stored in profile atm, so will always be false.
55
+ # TODO: clean this up
56
+ @native_events = model_prefs.delete(WEBDRIVER_PREFS[:native_events]) == "true"
57
+ @secure_ssl = model_prefs.delete(WEBDRIVER_PREFS[:untrusted_certs]) != "true"
58
+ @untrusted_issuer = model_prefs.delete(WEBDRIVER_PREFS[:untrusted_issuer]) == "true"
59
+ @load_no_focus_lib = model_prefs.delete(WEBDRIVER_PREFS[:load_no_focus_lib]) == "true" # not stored in profile atm, so will always be false.
60
+
61
+ @additional_prefs = model_prefs
57
62
  end
58
63
 
59
- @additional_prefs = {}
60
64
  @extensions = {}
61
65
  end
62
66
 
@@ -10,16 +10,6 @@ module Selenium
10
10
 
11
11
  class SocketLock
12
12
 
13
- #
14
- # Need to be really specific about what host to use
15
- #
16
- # On os x, "localhost" will resolve to 3 different addresses (see /etc/hosts).
17
- # Ruby will loop over these and happily bind to the same port on each one,
18
- # making it completely unusable for our purposes.
19
- #
20
-
21
- HOST = "127.0.0.1"
22
-
23
13
  def initialize(port, timeout)
24
14
  @port = port
25
15
  @timeout = timeout
@@ -54,7 +44,7 @@ module Selenium
54
44
  end
55
45
 
56
46
  def can_lock?
57
- @server = TCPServer.new(HOST, @port)
47
+ @server = TCPServer.new(Platform.localhost, @port)
58
48
  ChildProcess.close_on_exec @server
59
49
 
60
50
  true
@@ -7,11 +7,13 @@ module Selenium
7
7
  :win32 => "#{WebDriver.root}/selenium/webdriver/ie/native/win32/IEDriver.dll",
8
8
  :x64 => "#{WebDriver.root}/selenium/webdriver/ie/native/x64/IEDriver.dll"
9
9
  }
10
+
11
+ DLLS.each { |k,v| DLLS[k] = Platform.cygwin_path(v, :dos => true) } if Platform.cygwin?
10
12
  end
11
13
  end
12
14
  end
13
15
 
14
16
  require "ffi"
15
17
 
16
- require "selenium/webdriver/ie/lib"
18
+ require "selenium/webdriver/ie/server"
17
19
  require "selenium/webdriver/ie/bridge"