selenium-webdriver 2.1.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +8 -0
- data/lib/selenium/webdriver.rb +8 -4
- data/lib/selenium/webdriver/android/bridge.rb +12 -12
- data/lib/selenium/webdriver/common/driver.rb +14 -10
- data/lib/selenium/webdriver/common/element.rb +4 -2
- data/lib/selenium/webdriver/common/search_context.rb +12 -18
- data/lib/selenium/webdriver/firefox/extension/webdriver.xpi +0 -0
- data/lib/selenium/webdriver/firefox/native/linux/x86/x_ignore_nofocus.so +0 -0
- data/lib/selenium/webdriver/ie/native/win32/IEDriver.dll +0 -0
- data/lib/selenium/webdriver/ie/native/x64/IEDriver.dll +0 -0
- data/lib/selenium/webdriver/iphone/bridge.rb +12 -10
- data/lib/selenium/webdriver/remote/bridge.rb +2 -68
- data/lib/selenium/webdriver/support.rb +3 -0
- data/lib/selenium/webdriver/support/abstract_event_listener.rb +28 -0
- data/lib/selenium/webdriver/support/block_event_listener.rb +17 -0
- data/lib/selenium/webdriver/support/event_firing_bridge.rb +108 -0
- metadata +8 -4
data/CHANGES
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
2.2.0 (2011-07-26)
|
2
|
+
==================
|
3
|
+
|
4
|
+
* Add ability to listen for WebDriver events
|
5
|
+
* Fix Android/iPhone bridges to work similar to others (https://github.com/jnicklas/capybara/issues/425)
|
6
|
+
* Various atoms fixes
|
7
|
+
* Element equality now works properly with the remote server (#251).
|
8
|
+
|
1
9
|
2.1.0 (2011-07-18)
|
2
10
|
==================
|
3
11
|
|
data/lib/selenium/webdriver.rb
CHANGED
@@ -35,11 +35,12 @@ module Selenium
|
|
35
35
|
|
36
36
|
autoload :Android, 'selenium/webdriver/android'
|
37
37
|
autoload :Chrome, 'selenium/webdriver/chrome'
|
38
|
+
autoload :Firefox, 'selenium/webdriver/firefox'
|
38
39
|
autoload :IE, 'selenium/webdriver/ie'
|
39
40
|
autoload :IPhone, 'selenium/webdriver/iphone'
|
40
|
-
autoload :Remote, 'selenium/webdriver/remote'
|
41
|
-
autoload :Firefox, 'selenium/webdriver/firefox'
|
42
41
|
autoload :Opera, 'selenium/webdriver/opera'
|
42
|
+
autoload :Remote, 'selenium/webdriver/remote'
|
43
|
+
autoload :Support, 'selenium/webdriver/support'
|
43
44
|
|
44
45
|
# @api private
|
45
46
|
|
@@ -71,6 +72,11 @@ module Selenium
|
|
71
72
|
# WebDriver.for :firefox, :profile => Profile.new
|
72
73
|
# WebDriver.for :remote, :url => "http://localhost:4444/wd/hub", :desired_capabilities => caps
|
73
74
|
#
|
75
|
+
# One special argument is not passed on to the bridges, :listener. You can pass a listener for this option
|
76
|
+
# to get notified of WebDriver events. The passed object must respond to #call or implement the methods from AbstractEventListener.
|
77
|
+
#
|
78
|
+
# @see Selenium::WebDriver::Support::AbstractEventListener
|
79
|
+
#
|
74
80
|
|
75
81
|
def self.for(*args)
|
76
82
|
WebDriver::Driver.for(*args)
|
@@ -78,5 +84,3 @@ module Selenium
|
|
78
84
|
|
79
85
|
end # WebDriver
|
80
86
|
end # Selenium
|
81
|
-
|
82
|
-
Thread.abort_on_exception = true
|
@@ -3,17 +3,16 @@ module Selenium
|
|
3
3
|
module Android
|
4
4
|
class Bridge < Remote::Bridge
|
5
5
|
|
6
|
-
DEFAULT_URL = "http://#{Platform.localhost}:8080/hub"
|
7
|
-
|
8
|
-
def initialize(opts =
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
end
|
6
|
+
DEFAULT_URL = "http://#{Platform.localhost}:8080/hub/"
|
7
|
+
|
8
|
+
def initialize(opts = {})
|
9
|
+
remote_opts = {
|
10
|
+
:url => opts.fetch(:url, DEFAULT_URL),
|
11
|
+
:desired_capabilities => opts.fetch(:desired_capabilities, capabilities),
|
12
|
+
:http_client => opts[:http_client]
|
13
|
+
}
|
14
|
+
|
15
|
+
super remote_opts
|
17
16
|
end
|
18
17
|
|
19
18
|
def browser
|
@@ -23,7 +22,8 @@ module Selenium
|
|
23
22
|
def driver_extensions
|
24
23
|
[
|
25
24
|
DriverExtensions::TakesScreenshot,
|
26
|
-
DriverExtensions::Rotatable
|
25
|
+
DriverExtensions::Rotatable,
|
26
|
+
DriverExtensions::HasInputDevices
|
27
27
|
]
|
28
28
|
end
|
29
29
|
|
@@ -21,27 +21,31 @@ module Selenium
|
|
21
21
|
# @see Selenium::WebDriver.for
|
22
22
|
#
|
23
23
|
|
24
|
-
def for(browser,
|
24
|
+
def for(browser, opts = {})
|
25
|
+
listener = opts.delete(:listener)
|
26
|
+
|
25
27
|
bridge = case browser
|
26
28
|
when :firefox, :ff
|
27
|
-
Firefox::Bridge.new(
|
29
|
+
Firefox::Bridge.new(opts)
|
28
30
|
when :remote
|
29
|
-
Remote::Bridge.new(
|
31
|
+
Remote::Bridge.new(opts)
|
30
32
|
when :ie, :internet_explorer
|
31
|
-
IE::Bridge.new(
|
33
|
+
IE::Bridge.new(opts)
|
32
34
|
when :chrome
|
33
|
-
Chrome::Bridge.new(
|
35
|
+
Chrome::Bridge.new(opts)
|
34
36
|
when :android
|
35
|
-
Android::Bridge.new(
|
37
|
+
Android::Bridge.new(opts)
|
36
38
|
when :iphone
|
37
|
-
IPhone::Bridge.new(
|
39
|
+
IPhone::Bridge.new(opts)
|
38
40
|
when :opera
|
39
|
-
Opera::Bridge.new(
|
41
|
+
Opera::Bridge.new(opts)
|
40
42
|
else
|
41
43
|
raise ArgumentError, "unknown driver: #{browser.inspect}"
|
42
44
|
end
|
43
45
|
|
44
|
-
|
46
|
+
bridge = Support::EventFiringBridge.new(bridge, listener) if listener
|
47
|
+
|
48
|
+
new(bridge)
|
45
49
|
end
|
46
50
|
end
|
47
51
|
|
@@ -270,7 +274,7 @@ module Selenium
|
|
270
274
|
def capabilities
|
271
275
|
bridge.capabilities
|
272
276
|
end
|
273
|
-
|
277
|
+
|
274
278
|
#
|
275
279
|
# @api private
|
276
280
|
# @see SearchContext
|
@@ -3,8 +3,6 @@ module Selenium
|
|
3
3
|
class Element
|
4
4
|
include SearchContext
|
5
5
|
|
6
|
-
attr_reader :bridge
|
7
|
-
|
8
6
|
#
|
9
7
|
# Creates a new Element
|
10
8
|
#
|
@@ -255,6 +253,10 @@ module Selenium
|
|
255
253
|
|
256
254
|
private
|
257
255
|
|
256
|
+
def bridge
|
257
|
+
@bridge
|
258
|
+
end
|
259
|
+
|
258
260
|
def selectable?
|
259
261
|
tn = tag_name.downcase
|
260
262
|
type = attribute(:type).to_s.downcase
|
@@ -3,16 +3,16 @@ module Selenium
|
|
3
3
|
module SearchContext
|
4
4
|
|
5
5
|
FINDERS = {
|
6
|
-
:class => '
|
7
|
-
:class_name => '
|
8
|
-
:css => '
|
9
|
-
:id => '
|
10
|
-
:link => '
|
11
|
-
:link_text => '
|
12
|
-
:name => '
|
13
|
-
:partial_link_text => '
|
14
|
-
:tag_name => '
|
15
|
-
:xpath => '
|
6
|
+
:class => 'class name',
|
7
|
+
:class_name => 'class name',
|
8
|
+
:css => 'css selector',
|
9
|
+
:id => 'id',
|
10
|
+
:link => 'link text',
|
11
|
+
:link_text => 'link text',
|
12
|
+
:name => 'name',
|
13
|
+
:partial_link_text => 'partial link text',
|
14
|
+
:tag_name => 'tag name',
|
15
|
+
:xpath => 'xpath',
|
16
16
|
}
|
17
17
|
|
18
18
|
#
|
@@ -38,10 +38,7 @@ module Selenium
|
|
38
38
|
raise ArgumentError, "cannot find element by #{how.inspect}"
|
39
39
|
end
|
40
40
|
|
41
|
-
|
42
|
-
what = what.to_s
|
43
|
-
|
44
|
-
bridge.send meth, ref, what
|
41
|
+
bridge.find_element_by by, what.to_s, ref
|
45
42
|
end
|
46
43
|
|
47
44
|
#
|
@@ -61,10 +58,7 @@ module Selenium
|
|
61
58
|
raise ArgumentError, "cannot find elements by #{how.inspect}"
|
62
59
|
end
|
63
60
|
|
64
|
-
|
65
|
-
what = what.to_s
|
66
|
-
|
67
|
-
bridge.send meth, ref, what
|
61
|
+
bridge.find_elements_by by, what.to_s, ref
|
68
62
|
end
|
69
63
|
|
70
64
|
private
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -5,15 +5,14 @@ module Selenium
|
|
5
5
|
|
6
6
|
DEFAULT_URL = "http://#{Platform.localhost}:3001/hub/"
|
7
7
|
|
8
|
-
def initialize(opts =
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
end
|
8
|
+
def initialize(opts = {})
|
9
|
+
remote_opts = {
|
10
|
+
:url => opts.fetch(:url, DEFAULT_URL),
|
11
|
+
:desired_capabilities => opts.fetch(:desired_capabilities, capabilities),
|
12
|
+
:http_client => opts[:http_client]
|
13
|
+
}
|
14
|
+
|
15
|
+
super remote_opts
|
17
16
|
end
|
18
17
|
|
19
18
|
def browser
|
@@ -21,7 +20,10 @@ module Selenium
|
|
21
20
|
end
|
22
21
|
|
23
22
|
def driver_extensions
|
24
|
-
[
|
23
|
+
[
|
24
|
+
DriverExtensions::TakesScreenshot,
|
25
|
+
DriverExtensions::HasInputDevices
|
26
|
+
]
|
25
27
|
end
|
26
28
|
|
27
29
|
def capabilities
|
@@ -228,72 +228,6 @@ module Selenium
|
|
228
228
|
execute :deleteAllCookies
|
229
229
|
end
|
230
230
|
|
231
|
-
# finding elements
|
232
|
-
|
233
|
-
def findElementByClassName(parent, class_name)
|
234
|
-
find_element_by 'class name', class_name, parent
|
235
|
-
end
|
236
|
-
|
237
|
-
def findElementsByClassName(parent, class_name)
|
238
|
-
find_elements_by 'class name', class_name, parent
|
239
|
-
end
|
240
|
-
|
241
|
-
def findElementByCssSelector(parent, selector)
|
242
|
-
find_element_by 'css selector', selector, parent
|
243
|
-
end
|
244
|
-
|
245
|
-
def findElementsByCssSelector(parent, selector)
|
246
|
-
find_elements_by 'css selector', selector, parent
|
247
|
-
end
|
248
|
-
|
249
|
-
def findElementById(parent, id)
|
250
|
-
find_element_by 'id', id, parent
|
251
|
-
end
|
252
|
-
|
253
|
-
def findElementsById(parent, id)
|
254
|
-
find_elements_by 'id', id, parent
|
255
|
-
end
|
256
|
-
|
257
|
-
def findElementByLinkText(parent, link_text)
|
258
|
-
find_element_by 'link text', link_text, parent
|
259
|
-
end
|
260
|
-
|
261
|
-
def findElementsByLinkText(parent, link_text)
|
262
|
-
find_elements_by 'link text', link_text, parent
|
263
|
-
end
|
264
|
-
|
265
|
-
def findElementByPartialLinkText(parent, link_text)
|
266
|
-
find_element_by 'partial link text', link_text, parent
|
267
|
-
end
|
268
|
-
|
269
|
-
def findElementsByPartialLinkText(parent, link_text)
|
270
|
-
find_elements_by 'partial link text', link_text, parent
|
271
|
-
end
|
272
|
-
|
273
|
-
def findElementByName(parent, name)
|
274
|
-
find_element_by 'name', name, parent
|
275
|
-
end
|
276
|
-
|
277
|
-
def findElementsByName(parent, name)
|
278
|
-
find_elements_by 'name', name, parent
|
279
|
-
end
|
280
|
-
|
281
|
-
def findElementByTagName(parent, tag_name)
|
282
|
-
find_element_by 'tag name', tag_name, parent
|
283
|
-
end
|
284
|
-
|
285
|
-
def findElementsByTagName(parent, tag_name)
|
286
|
-
find_elements_by 'tag name', tag_name, parent
|
287
|
-
end
|
288
|
-
|
289
|
-
def findElementByXpath(parent, xpath)
|
290
|
-
find_element_by 'xpath', xpath, parent
|
291
|
-
end
|
292
|
-
|
293
|
-
def findElementsByXpath(parent, xpath)
|
294
|
-
find_elements_by 'xpath', xpath, parent
|
295
|
-
end
|
296
|
-
|
297
231
|
def clickElement(element)
|
298
232
|
execute :clickElement, :id => element
|
299
233
|
end
|
@@ -411,8 +345,6 @@ module Selenium
|
|
411
345
|
execute :elementEquals, :id => element.ref, :other => other.ref
|
412
346
|
end
|
413
347
|
|
414
|
-
private
|
415
|
-
|
416
348
|
def find_element_by(how, what, parent = nil)
|
417
349
|
if parent
|
418
350
|
id = execute :findChildElement, {:id => parent}, {:using => how, :value => what}
|
@@ -433,6 +365,8 @@ module Selenium
|
|
433
365
|
ids.map { |id| Element.new self, element_id_from(id) }
|
434
366
|
end
|
435
367
|
|
368
|
+
private
|
369
|
+
|
436
370
|
def assert_javascript_enabled
|
437
371
|
unless capabilities.javascript_enabled?
|
438
372
|
raise Error::UnsupportedOperationError, "underlying webdriver instance does not support javascript"
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Selenium
|
2
|
+
module WebDriver
|
3
|
+
module Support
|
4
|
+
|
5
|
+
class AbstractEventListener
|
6
|
+
def before_navigate_to(url) end
|
7
|
+
def after_navigate_to(url) end
|
8
|
+
def before_navigate_back() end
|
9
|
+
def after_navigate_back() end
|
10
|
+
def before_navigate_forward() end
|
11
|
+
def after_navigate_forward() end
|
12
|
+
def before_find(by, what) end
|
13
|
+
def after_find(by, what) end
|
14
|
+
def before_click(element) end
|
15
|
+
def after_click(element) end
|
16
|
+
def before_change_value_of(element) end
|
17
|
+
def after_change_value_of(element) end
|
18
|
+
def before_execute_script(script) end
|
19
|
+
def after_execute_script(script) end
|
20
|
+
def before_quit() end
|
21
|
+
def after_quit() end
|
22
|
+
def before_close() end
|
23
|
+
def after_close() end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Selenium
|
2
|
+
module WebDriver
|
3
|
+
module Support
|
4
|
+
|
5
|
+
class BlockEventListener
|
6
|
+
def initialize(callback)
|
7
|
+
@callback = callback
|
8
|
+
end
|
9
|
+
|
10
|
+
def method_missing(meth, *args, &blk)
|
11
|
+
@callback.call meth, *args
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module Selenium
|
2
|
+
module WebDriver
|
3
|
+
module Support
|
4
|
+
|
5
|
+
#
|
6
|
+
# @api private
|
7
|
+
#
|
8
|
+
|
9
|
+
class EventFiringBridge
|
10
|
+
def initialize(delegate, listener)
|
11
|
+
@delegate = delegate
|
12
|
+
|
13
|
+
if listener.respond_to? :call
|
14
|
+
@listener = BlockEventListener.new(listener)
|
15
|
+
else
|
16
|
+
@listener = listener
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def get(url)
|
21
|
+
dispatch(:navigate_to, url) {
|
22
|
+
@delegate.get(url)
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def goForward
|
27
|
+
dispatch(:navigate_forward) {
|
28
|
+
@delegate.goForward
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
def goBack
|
33
|
+
dispatch(:navigate_back) {
|
34
|
+
@delegate.goBack
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def clickElement(ref)
|
39
|
+
dispatch(:click, create_element(ref)) {
|
40
|
+
@delegate.clickElement(ref)
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
def clearElement(ref)
|
45
|
+
dispatch(:change_value_of, create_element(ref)) {
|
46
|
+
@delegate.clearElement(ref)
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
def sendKeysToElement(ref, keys)
|
51
|
+
dispatch(:change_value_of, create_element(ref)) {
|
52
|
+
@delegate.sendKeysToElement(ref, keys)
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
def find_element_by(how, what, parent = nil)
|
57
|
+
e = dispatch(:find, how, what) {
|
58
|
+
@delegate.find_element_by how, what, parent
|
59
|
+
}
|
60
|
+
|
61
|
+
Element.new self, e.ref
|
62
|
+
end
|
63
|
+
|
64
|
+
def find_elements_by(how, what, parent = nil)
|
65
|
+
es = dispatch(:find, how, what) {
|
66
|
+
@delegate.find_elements_by(how, what, parent)
|
67
|
+
}
|
68
|
+
|
69
|
+
es.map { |e| Element.new self, e.ref }
|
70
|
+
end
|
71
|
+
|
72
|
+
def executeScript(script, *args)
|
73
|
+
dispatch(:execute_script, script) {
|
74
|
+
@delegate.executeScript(script, *args)
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
def quit
|
79
|
+
dispatch(:quit) { @delegate.quit }
|
80
|
+
end
|
81
|
+
|
82
|
+
def close
|
83
|
+
dispatch(:close) { @delegate.close }
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
def create_element(ref)
|
89
|
+
# hmm. we're not passing self here to not fire events for potential calls made by the listener
|
90
|
+
Element.new @delegate, ref
|
91
|
+
end
|
92
|
+
|
93
|
+
def dispatch(name, *args, &blk)
|
94
|
+
@listener.__send__("before_#{name}", *args)
|
95
|
+
returned = yield
|
96
|
+
@listener.__send__("after_#{name}", *args)
|
97
|
+
|
98
|
+
returned
|
99
|
+
end
|
100
|
+
|
101
|
+
def method_missing(meth, *args, &blk)
|
102
|
+
@delegate.__send__(meth, *args, &blk)
|
103
|
+
end
|
104
|
+
end # EventFiringBridge
|
105
|
+
|
106
|
+
end # Support
|
107
|
+
end # WebDriver
|
108
|
+
end # Selenium
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: selenium-webdriver
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 7
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 2
|
8
|
-
-
|
8
|
+
- 2
|
9
9
|
- 0
|
10
|
-
version: 2.
|
10
|
+
version: 2.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jari Bakken
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-07-
|
18
|
+
date: 2011-07-26 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: json_pure
|
@@ -210,6 +210,10 @@ files:
|
|
210
210
|
- lib/selenium/webdriver/remote/response.rb
|
211
211
|
- lib/selenium/webdriver/remote/server_error.rb
|
212
212
|
- lib/selenium/webdriver/remote.rb
|
213
|
+
- lib/selenium/webdriver/support/abstract_event_listener.rb
|
214
|
+
- lib/selenium/webdriver/support/block_event_listener.rb
|
215
|
+
- lib/selenium/webdriver/support/event_firing_bridge.rb
|
216
|
+
- lib/selenium/webdriver/support.rb
|
213
217
|
- lib/selenium/webdriver.rb
|
214
218
|
- lib/selenium-client.rb
|
215
219
|
- lib/selenium-webdriver.rb
|