browserstack-webdriver 0.0.1
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.
- checksums.yaml +7 -0
- data/CHANGES +791 -0
- data/README.md +31 -0
- data/build.desc +334 -0
- data/lib/selenium-client.rb +2 -0
- data/lib/selenium-webdriver.rb +1 -0
- data/lib/selenium/client.rb +37 -0
- data/lib/selenium/client/base.rb +132 -0
- data/lib/selenium/client/driver.rb +10 -0
- data/lib/selenium/client/errors.rb +9 -0
- data/lib/selenium/client/extensions.rb +118 -0
- data/lib/selenium/client/idiomatic.rb +488 -0
- data/lib/selenium/client/javascript_expression_builder.rb +116 -0
- data/lib/selenium/client/javascript_frameworks/jquery.rb +13 -0
- data/lib/selenium/client/javascript_frameworks/prototype.rb +13 -0
- data/lib/selenium/client/legacy_driver.rb +1720 -0
- data/lib/selenium/client/protocol.rb +104 -0
- data/lib/selenium/client/selenium_helper.rb +34 -0
- data/lib/selenium/rake/server_task.rb +157 -0
- data/lib/selenium/server.rb +248 -0
- data/lib/selenium/webdriver.rb +71 -0
- data/lib/selenium/webdriver/android.rb +9 -0
- data/lib/selenium/webdriver/android/bridge.rb +47 -0
- data/lib/selenium/webdriver/chrome.rb +26 -0
- data/lib/selenium/webdriver/chrome/bridge.rb +120 -0
- data/lib/selenium/webdriver/chrome/profile.rb +90 -0
- data/lib/selenium/webdriver/chrome/service.rb +75 -0
- data/lib/selenium/webdriver/common.rb +44 -0
- data/lib/selenium/webdriver/common/action_builder.rb +352 -0
- data/lib/selenium/webdriver/common/alert.rb +30 -0
- data/lib/selenium/webdriver/common/bridge_helper.rb +67 -0
- data/lib/selenium/webdriver/common/core_ext/base64.rb +9 -0
- data/lib/selenium/webdriver/common/core_ext/dir.rb +42 -0
- data/lib/selenium/webdriver/common/core_ext/string.rb +5 -0
- data/lib/selenium/webdriver/common/driver.rb +301 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_browser_connection.rb +17 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_input_devices.rb +39 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +25 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_remote_status.rb +13 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_session_id.rb +22 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_touch_screen.rb +19 -0
- data/lib/selenium/webdriver/common/driver_extensions/has_web_storage.rb +22 -0
- data/lib/selenium/webdriver/common/driver_extensions/rotatable.rb +45 -0
- data/lib/selenium/webdriver/common/driver_extensions/takes_screenshot.rb +43 -0
- data/lib/selenium/webdriver/common/driver_extensions/uploads_files.rb +46 -0
- data/lib/selenium/webdriver/common/element.rb +293 -0
- data/lib/selenium/webdriver/common/error.rb +207 -0
- data/lib/selenium/webdriver/common/file_reaper.rb +47 -0
- data/lib/selenium/webdriver/common/html5/local_storage.rb +42 -0
- data/lib/selenium/webdriver/common/html5/location.rb +0 -0
- data/lib/selenium/webdriver/common/html5/session_storage.rb +44 -0
- data/lib/selenium/webdriver/common/html5/shared_web_storage.rb +42 -0
- data/lib/selenium/webdriver/common/json_helper.rb +34 -0
- data/lib/selenium/webdriver/common/keyboard.rb +55 -0
- data/lib/selenium/webdriver/common/keys.rb +109 -0
- data/lib/selenium/webdriver/common/log_entry.rb +29 -0
- data/lib/selenium/webdriver/common/logs.rb +23 -0
- data/lib/selenium/webdriver/common/mouse.rb +72 -0
- data/lib/selenium/webdriver/common/navigation.rb +43 -0
- data/lib/selenium/webdriver/common/options.rb +136 -0
- data/lib/selenium/webdriver/common/platform.rb +218 -0
- data/lib/selenium/webdriver/common/port_prober.rb +42 -0
- data/lib/selenium/webdriver/common/profile_helper.rb +67 -0
- data/lib/selenium/webdriver/common/proxy.rb +149 -0
- data/lib/selenium/webdriver/common/search_context.rb +92 -0
- data/lib/selenium/webdriver/common/socket_poller.rb +105 -0
- data/lib/selenium/webdriver/common/target_locator.rb +81 -0
- data/lib/selenium/webdriver/common/timeouts.rb +38 -0
- data/lib/selenium/webdriver/common/touch_action_builder.rb +64 -0
- data/lib/selenium/webdriver/common/touch_screen.rb +105 -0
- data/lib/selenium/webdriver/common/wait.rb +63 -0
- data/lib/selenium/webdriver/common/window.rb +104 -0
- data/lib/selenium/webdriver/common/zipper.rb +82 -0
- data/lib/selenium/webdriver/firefox.rb +37 -0
- data/lib/selenium/webdriver/firefox/binary.rb +158 -0
- data/lib/selenium/webdriver/firefox/bridge.rb +70 -0
- data/lib/selenium/webdriver/firefox/extension.rb +52 -0
- data/lib/selenium/webdriver/firefox/launcher.rb +106 -0
- data/lib/selenium/webdriver/firefox/profile.rb +263 -0
- data/lib/selenium/webdriver/firefox/profiles_ini.rb +62 -0
- data/lib/selenium/webdriver/firefox/socket_lock.rb +61 -0
- data/lib/selenium/webdriver/firefox/util.rb +29 -0
- data/lib/selenium/webdriver/ie.rb +19 -0
- data/lib/selenium/webdriver/ie/bridge.rb +68 -0
- data/lib/selenium/webdriver/ie/server.rb +86 -0
- data/lib/selenium/webdriver/iphone.rb +9 -0
- data/lib/selenium/webdriver/iphone/bridge.rb +45 -0
- data/lib/selenium/webdriver/opera.rb +24 -0
- data/lib/selenium/webdriver/opera/bridge.rb +112 -0
- data/lib/selenium/webdriver/opera/service.rb +49 -0
- data/lib/selenium/webdriver/phantomjs.rb +22 -0
- data/lib/selenium/webdriver/phantomjs/bridge.rb +59 -0
- data/lib/selenium/webdriver/phantomjs/service.rb +90 -0
- data/lib/selenium/webdriver/remote.rb +22 -0
- data/lib/selenium/webdriver/remote/bridge.rb +644 -0
- data/lib/selenium/webdriver/remote/capabilities.rb +267 -0
- data/lib/selenium/webdriver/remote/commands.rb +193 -0
- data/lib/selenium/webdriver/remote/http/common.rb +74 -0
- data/lib/selenium/webdriver/remote/http/curb.rb +79 -0
- data/lib/selenium/webdriver/remote/http/default.rb +139 -0
- data/lib/selenium/webdriver/remote/http/persistent.rb +38 -0
- data/lib/selenium/webdriver/remote/response.rb +97 -0
- data/lib/selenium/webdriver/remote/server_error.rb +17 -0
- data/lib/selenium/webdriver/safari.rb +46 -0
- data/lib/selenium/webdriver/safari/bridge.rb +110 -0
- data/lib/selenium/webdriver/safari/browser.rb +20 -0
- data/lib/selenium/webdriver/safari/extension.rb +120 -0
- data/lib/selenium/webdriver/safari/server.rb +145 -0
- data/lib/selenium/webdriver/support.rb +5 -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/color.rb +110 -0
- data/lib/selenium/webdriver/support/event_firing_bridge.rb +112 -0
- data/lib/selenium/webdriver/support/select.rb +293 -0
- data/ruby.iml +13 -0
- data/spec/integration/selenium/client/api/backward_compatible_api_spec.rb +22 -0
- data/spec/integration/selenium/client/api/browser_xpath_library_spec.rb +17 -0
- data/spec/integration/selenium/client/api/click_spec.rb +39 -0
- data/spec/integration/selenium/client/api/cookie_spec.rb +39 -0
- data/spec/integration/selenium/client/api/element_spec.rb +14 -0
- data/spec/integration/selenium/client/api/highlight_located_element_spec.rb +19 -0
- data/spec/integration/selenium/client/api/retrieve_last_remote_control_logs_spec.rb +33 -0
- data/spec/integration/selenium/client/api/screenshot_spec.rb +31 -0
- data/spec/integration/selenium/client/api/select_window_spec.rb +46 -0
- data/spec/integration/selenium/client/api/start_stop_spec.rb +9 -0
- data/spec/integration/selenium/client/api/wait_for_ajax_spec.rb +27 -0
- data/spec/integration/selenium/client/api/wait_for_element_spec.rb +56 -0
- data/spec/integration/selenium/client/api/wait_for_field_value_spec.rb +52 -0
- data/spec/integration/selenium/client/api/wait_for_text_spec.rb +98 -0
- data/spec/integration/selenium/client/api/webdriver_backed_spec.rb +21 -0
- data/spec/integration/selenium/client/sample-app/public/jquery-1.3.2.js +4376 -0
- data/spec/integration/selenium/client/sample-app/public/jquery.html +55 -0
- data/spec/integration/selenium/client/sample-app/public/prototype-1.6.0.3.js +4320 -0
- data/spec/integration/selenium/client/sample-app/public/prototype.html +59 -0
- data/spec/integration/selenium/client/sample-app/sample_app.rb +32 -0
- data/spec/integration/selenium/client/spec_helper.rb +139 -0
- data/spec/integration/selenium/webdriver/app_cache_spec.rb +47 -0
- data/spec/integration/selenium/webdriver/browser_connection_spec.rb +20 -0
- data/spec/integration/selenium/webdriver/chrome/driver_spec.rb +28 -0
- data/spec/integration/selenium/webdriver/chrome/profile_spec.rb +63 -0
- data/spec/integration/selenium/webdriver/driver_spec.rb +266 -0
- data/spec/integration/selenium/webdriver/element_spec.rb +191 -0
- data/spec/integration/selenium/webdriver/error_spec.rb +30 -0
- data/spec/integration/selenium/webdriver/firefox/driver_spec.rb +21 -0
- data/spec/integration/selenium/webdriver/firefox/profile_spec.rb +141 -0
- data/spec/integration/selenium/webdriver/keyboard_spec.rb +57 -0
- data/spec/integration/selenium/webdriver/location_spec.rb +29 -0
- data/spec/integration/selenium/webdriver/mouse_spec.rb +57 -0
- data/spec/integration/selenium/webdriver/navigation_spec.rb +46 -0
- data/spec/integration/selenium/webdriver/opera/driver_spec.rb +47 -0
- data/spec/integration/selenium/webdriver/options_spec.rb +77 -0
- data/spec/integration/selenium/webdriver/remote/driver_spec.rb +19 -0
- data/spec/integration/selenium/webdriver/remote/element_spec.rb +26 -0
- data/spec/integration/selenium/webdriver/spec_helper.rb +36 -0
- data/spec/integration/selenium/webdriver/spec_support.rb +12 -0
- data/spec/integration/selenium/webdriver/spec_support/guards.rb +110 -0
- data/spec/integration/selenium/webdriver/spec_support/helpers.rb +51 -0
- data/spec/integration/selenium/webdriver/spec_support/rack_server.rb +123 -0
- data/spec/integration/selenium/webdriver/spec_support/test_environment.rb +239 -0
- data/spec/integration/selenium/webdriver/sql_database_spec.rb +59 -0
- data/spec/integration/selenium/webdriver/storage_spec.rb +96 -0
- data/spec/integration/selenium/webdriver/target_locator_spec.rb +186 -0
- data/spec/integration/selenium/webdriver/timeout_spec.rb +69 -0
- data/spec/integration/selenium/webdriver/touch_spec.rb +176 -0
- data/spec/integration/selenium/webdriver/window_spec.rb +70 -0
- data/spec/integration/selenium/webdriver/zipper_spec.rb +66 -0
- data/spec/unit/selenium/client/base_spec.rb +239 -0
- data/spec/unit/selenium/client/extensions_spec.rb +174 -0
- data/spec/unit/selenium/client/idiomatic_spec.rb +500 -0
- data/spec/unit/selenium/client/javascript_expression_builder_spec.rb +79 -0
- data/spec/unit/selenium/client/javascript_frameworks/jquery_spec.rb +10 -0
- data/spec/unit/selenium/client/javascript_frameworks/prototype_spec.rb +10 -0
- data/spec/unit/selenium/client/protocol_spec.rb +124 -0
- data/spec/unit/selenium/client/selenium_helper_spec.rb +56 -0
- data/spec/unit/selenium/client/spec_helper.rb +24 -0
- data/spec/unit/selenium/rake/task_spec.rb +79 -0
- data/spec/unit/selenium/server_spec.rb +150 -0
- data/spec/unit/selenium/webdriver/action_builder_spec.rb +97 -0
- data/spec/unit/selenium/webdriver/android/bridge_spec.rb +43 -0
- data/spec/unit/selenium/webdriver/chrome/bridge_spec.rb +137 -0
- data/spec/unit/selenium/webdriver/chrome/profile_spec.rb +57 -0
- data/spec/unit/selenium/webdriver/chrome/service_spec.rb +44 -0
- data/spec/unit/selenium/webdriver/error_spec.rb +41 -0
- data/spec/unit/selenium/webdriver/firefox/bridge_spec.rb +47 -0
- data/spec/unit/selenium/webdriver/ie/bridge_spec.rb +91 -0
- data/spec/unit/selenium/webdriver/iphone/bridge_spec.rb +42 -0
- data/spec/unit/selenium/webdriver/log_entry_spec.rb +11 -0
- data/spec/unit/selenium/webdriver/opera/bridge_spec.rb +44 -0
- data/spec/unit/selenium/webdriver/phantomjs/bridge_spec.rb +55 -0
- data/spec/unit/selenium/webdriver/proxy_spec.rb +106 -0
- data/spec/unit/selenium/webdriver/remote/bridge_spec.rb +16 -0
- data/spec/unit/selenium/webdriver/remote/capabilities_spec.rb +115 -0
- data/spec/unit/selenium/webdriver/remote/http/common_spec.rb +24 -0
- data/spec/unit/selenium/webdriver/remote/http/default_spec.rb +124 -0
- data/spec/unit/selenium/webdriver/search_context_spec.rb +61 -0
- data/spec/unit/selenium/webdriver/socket_poller_spec.rb +68 -0
- data/spec/unit/selenium/webdriver/spec_helper.rb +27 -0
- data/spec/unit/selenium/webdriver/support/color_spec.rb +119 -0
- data/spec/unit/selenium/webdriver/support/event_firing_spec.rb +111 -0
- data/spec/unit/selenium/webdriver/support/select_spec.rb +290 -0
- data/spec/unit/selenium/webdriver/wait_spec.rb +49 -0
- metadata +370 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module Selenium
|
|
2
|
+
module WebDriver
|
|
3
|
+
module Support
|
|
4
|
+
|
|
5
|
+
class AbstractEventListener
|
|
6
|
+
def before_navigate_to(url, driver) end
|
|
7
|
+
def after_navigate_to(url, driver) end
|
|
8
|
+
def before_navigate_back(driver) end
|
|
9
|
+
def after_navigate_back(driver) end
|
|
10
|
+
def before_navigate_forward(driver) end
|
|
11
|
+
def after_navigate_forward(driver) end
|
|
12
|
+
def before_find(by, what, driver) end
|
|
13
|
+
def after_find(by, what, driver) end
|
|
14
|
+
def before_click(element, driver) end
|
|
15
|
+
def after_click(element, driver) end
|
|
16
|
+
def before_change_value_of(element, driver) end
|
|
17
|
+
def after_change_value_of(element, driver) end
|
|
18
|
+
def before_execute_script(script, driver) end
|
|
19
|
+
def after_execute_script(script, driver) end
|
|
20
|
+
def before_quit(driver) end
|
|
21
|
+
def after_quit(driver) end
|
|
22
|
+
def before_close(driver) end
|
|
23
|
+
def after_close(driver) 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,110 @@
|
|
|
1
|
+
module Selenium
|
|
2
|
+
module WebDriver
|
|
3
|
+
module Support
|
|
4
|
+
class Color
|
|
5
|
+
RGB_PATTERN = /^\s*rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)\s*$/
|
|
6
|
+
RGB_PCT_PATTERN = /^\s*rgb\(\s*(\d{1,3}|\d{1,2}\.\d+)%\s*,\s*(\d{1,3}|\d{1,2}\.\d+)%\s*,\s*(\d{1,3}|\d{1,2}\.\d+)%\s*\)\s*$/
|
|
7
|
+
RGBA_PATTERN = /^\s*rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(0|1|0\.\d+)\s*\)\s*$/
|
|
8
|
+
RGBA_PCT_PATTERN = /^\s*rgba\(\s*(\d{1,3}|\d{1,2}\.\d+)%\s*,\s*(\d{1,3}|\d{1,2}\.\d+)%\s*,\s*(\d{1,3}|\d{1,2}\.\d+)%\s*,\s*(0|1|0\.\d+)\s*\)\s*$/
|
|
9
|
+
HEX_PATTERN = /#([A-Fa-f0-9]{2})([A-Fa-f0-9]{2})([A-Fa-f0-9]{2})/ # \p{XDigit} or \h only works on Ruby 1.9
|
|
10
|
+
HEX3_PATTERN = /#([A-Fa-f0-9])([A-Fa-f0-9])([A-Fa-f0-9])/ # \p{XDigit} or \h only works on Ruby 1.9
|
|
11
|
+
HSL_PATTERN = /^\s*hsl\(\s*(\d{1,3})\s*,\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*\)\s*$/
|
|
12
|
+
HSLA_PATTERN = /^\s*hsla\(\s*(\d{1,3})\s*,\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*,\s*(0|1|0\.\d+)\s*\)\s*$/
|
|
13
|
+
|
|
14
|
+
attr_reader :red, :green, :blue, :alpha
|
|
15
|
+
|
|
16
|
+
def self.from_string(str)
|
|
17
|
+
case str
|
|
18
|
+
when RGB_PATTERN
|
|
19
|
+
new $1, $2, $3
|
|
20
|
+
when RGB_PCT_PATTERN
|
|
21
|
+
new(*[$1, $2, $3].map { |e| Float(e) / 100 * 255 })
|
|
22
|
+
when RGBA_PATTERN
|
|
23
|
+
new $1, $2, $3, $4
|
|
24
|
+
when RGBA_PCT_PATTERN
|
|
25
|
+
new(*[$1, $2, $3].map { |e| Float(e) / 100 * 255 } << $4)
|
|
26
|
+
when HEX_PATTERN
|
|
27
|
+
new(*[$1, $2, $3].map { |e| e.to_i(16) })
|
|
28
|
+
when HEX3_PATTERN
|
|
29
|
+
new(*[$1, $2, $3].map { |e| (e * 2).to_i(16) })
|
|
30
|
+
when HSL_PATTERN, HSLA_PATTERN
|
|
31
|
+
from_hsl($1, $2, $3, $4)
|
|
32
|
+
else
|
|
33
|
+
raise ArgumentError, "could not convert #{str.inspect} into color"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def self.from_hsl(h, s, l, a)
|
|
38
|
+
h = Float(h) / 360
|
|
39
|
+
s = Float(s) / 100
|
|
40
|
+
l = Float(l) / 100
|
|
41
|
+
a = Float(a || 1)
|
|
42
|
+
|
|
43
|
+
if s == 0
|
|
44
|
+
r = l
|
|
45
|
+
g = r
|
|
46
|
+
b = r
|
|
47
|
+
else
|
|
48
|
+
luminocity2 = (l < 0.5) ? l * (1 + s) : l + s - l * s
|
|
49
|
+
luminocity1 = 2 * l - luminocity2
|
|
50
|
+
|
|
51
|
+
hue_to_rgb = lambda do |lum1, lum2, hue|
|
|
52
|
+
hue += 1 if hue < 0.0
|
|
53
|
+
hue -= 1 if hue > 1.0
|
|
54
|
+
|
|
55
|
+
if hue < 1.0 / 6.0
|
|
56
|
+
(lum1 + (lum2 - lum1) * 6.0 * hue)
|
|
57
|
+
elsif hue < 1.0 / 2.0
|
|
58
|
+
lum2
|
|
59
|
+
elsif hue < 2.0 / 3.0
|
|
60
|
+
lum1 + (lum2 - lum1) * ((2.0 / 3.0) - hue) * 6.0
|
|
61
|
+
else
|
|
62
|
+
lum1
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
r = hue_to_rgb.call(luminocity1, luminocity2, h + 1.0 / 3.0)
|
|
67
|
+
g = hue_to_rgb.call(luminocity1, luminocity2, h)
|
|
68
|
+
b = hue_to_rgb.call(luminocity1, luminocity2, h - 1.0 / 3.0)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
new r * 256, g * 256, b * 256, a
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def initialize(red, green, blue, alpha = 1)
|
|
76
|
+
@red = Integer(red)
|
|
77
|
+
@green = Integer(green)
|
|
78
|
+
@blue = Integer(blue)
|
|
79
|
+
@alpha = Float(alpha)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def ==(other)
|
|
83
|
+
return true if equal?(other)
|
|
84
|
+
return false unless other.kind_of?(self.class)
|
|
85
|
+
|
|
86
|
+
[red, green, blue, alpha] == [other.red, other.green, other.blue, other.alpha]
|
|
87
|
+
end
|
|
88
|
+
alias_method :eql?, :==
|
|
89
|
+
|
|
90
|
+
def hash
|
|
91
|
+
[red, green, blue, alpha].hash ^ self.class.hash
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def rgb
|
|
95
|
+
"rgb(#{red}, #{green}, #{blue})"
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def rgba
|
|
99
|
+
a = alpha == 1 ? '1' : alpha
|
|
100
|
+
"rgba(#{red}, #{green}, #{blue}, #{a})"
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def hex
|
|
104
|
+
"#%02x%02x%02x" % [red, green, blue]
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
@@ -0,0 +1,112 @@
|
|
|
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, driver) {
|
|
22
|
+
@delegate.get(url)
|
|
23
|
+
}
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def goForward
|
|
27
|
+
dispatch(:navigate_forward, driver) {
|
|
28
|
+
@delegate.goForward
|
|
29
|
+
}
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def goBack
|
|
33
|
+
dispatch(:navigate_back, driver) {
|
|
34
|
+
@delegate.goBack
|
|
35
|
+
}
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def clickElement(ref)
|
|
39
|
+
dispatch(:click, create_element(ref), driver) {
|
|
40
|
+
@delegate.clickElement(ref)
|
|
41
|
+
}
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def clearElement(ref)
|
|
45
|
+
dispatch(:change_value_of, create_element(ref), driver) {
|
|
46
|
+
@delegate.clearElement(ref)
|
|
47
|
+
}
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def sendKeysToElement(ref, keys)
|
|
51
|
+
dispatch(:change_value_of, create_element(ref), driver) {
|
|
52
|
+
@delegate.sendKeysToElement(ref, keys)
|
|
53
|
+
}
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def find_element_by(how, what, parent = nil)
|
|
57
|
+
e = dispatch(:find, how, what, driver) {
|
|
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, driver) {
|
|
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, driver) {
|
|
74
|
+
@delegate.executeScript(script, *args)
|
|
75
|
+
}
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def quit
|
|
79
|
+
dispatch(:quit, driver) { @delegate.quit }
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def close
|
|
83
|
+
dispatch(:close, driver) { @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 driver
|
|
94
|
+
@driver ||= Driver.new(self)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def dispatch(name, *args, &blk)
|
|
98
|
+
@listener.__send__("before_#{name}", *args)
|
|
99
|
+
returned = yield
|
|
100
|
+
@listener.__send__("after_#{name}", *args)
|
|
101
|
+
|
|
102
|
+
returned
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def method_missing(meth, *args, &blk)
|
|
106
|
+
@delegate.__send__(meth, *args, &blk)
|
|
107
|
+
end
|
|
108
|
+
end # EventFiringBridge
|
|
109
|
+
|
|
110
|
+
end # Support
|
|
111
|
+
end # WebDriver
|
|
112
|
+
end # Selenium
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
module Selenium
|
|
2
|
+
module WebDriver
|
|
3
|
+
module Support
|
|
4
|
+
class Select
|
|
5
|
+
|
|
6
|
+
#
|
|
7
|
+
# @param [Element] element The select element to use
|
|
8
|
+
#
|
|
9
|
+
|
|
10
|
+
def initialize(element)
|
|
11
|
+
tag_name = element.tag_name
|
|
12
|
+
|
|
13
|
+
unless tag_name.downcase == "select"
|
|
14
|
+
raise ArgumentError, "unexpected tag name #{tag_name.inspect}"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
@element = element
|
|
18
|
+
@multi = ![nil, "false"].include?(element.attribute(:multiple))
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
#
|
|
22
|
+
# Does this select element support selecting multiple options?
|
|
23
|
+
#
|
|
24
|
+
# @return [Boolean]
|
|
25
|
+
#
|
|
26
|
+
|
|
27
|
+
def multiple?
|
|
28
|
+
@multi
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
#
|
|
32
|
+
# Get all options for this select element
|
|
33
|
+
#
|
|
34
|
+
# @return [Array<Element>]
|
|
35
|
+
#
|
|
36
|
+
|
|
37
|
+
def options
|
|
38
|
+
@element.find_elements :tag_name, 'option'
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
#
|
|
42
|
+
# Get all selected options for this select element
|
|
43
|
+
#
|
|
44
|
+
# @return [Array<Element>]
|
|
45
|
+
#
|
|
46
|
+
|
|
47
|
+
def selected_options
|
|
48
|
+
options.select { |e| e.selected? }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
#
|
|
52
|
+
# Get the first selected option in this select element
|
|
53
|
+
#
|
|
54
|
+
# @raise [Error::NoSuchElementError] if no options are selected
|
|
55
|
+
# @return [Element]
|
|
56
|
+
#
|
|
57
|
+
|
|
58
|
+
def first_selected_option
|
|
59
|
+
option = options.find { |e| e.selected? }
|
|
60
|
+
option or raise Error::NoSuchElementError, 'no options are selected'
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
#
|
|
64
|
+
# Select options by visible text, index or value.
|
|
65
|
+
#
|
|
66
|
+
# When selecting by :text, selects options that display text matching the argument. That is, when given "Bar" this
|
|
67
|
+
# would select an option like:
|
|
68
|
+
#
|
|
69
|
+
# <option value="foo">Bar</option>
|
|
70
|
+
#
|
|
71
|
+
# When slecting by :value, selects all options that have a value matching the argument. That is, when given "foo" this
|
|
72
|
+
# would select an option like:
|
|
73
|
+
#
|
|
74
|
+
# <option value="foo">Bar</option>
|
|
75
|
+
#
|
|
76
|
+
# When selecting by :index, selects the option at the given index. This is done by examining the "index" attribute of an
|
|
77
|
+
# element, and not merely by counting.
|
|
78
|
+
#
|
|
79
|
+
# @param [:text, :index, :value] how How to find the option
|
|
80
|
+
# @param [String] what What value to find the option by.
|
|
81
|
+
#
|
|
82
|
+
|
|
83
|
+
def select_by(how, what)
|
|
84
|
+
case how
|
|
85
|
+
when :text
|
|
86
|
+
select_by_text what
|
|
87
|
+
when :index
|
|
88
|
+
select_by_index what
|
|
89
|
+
when :value
|
|
90
|
+
select_by_value what
|
|
91
|
+
else
|
|
92
|
+
raise ArgumentError, "can't select options by #{how.inspect}"
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
#
|
|
97
|
+
# Deselect options by visible text, index or value.
|
|
98
|
+
#
|
|
99
|
+
# @param [:text, :index, :value] how How to find the option
|
|
100
|
+
# @param [String] what What value to find the option by.
|
|
101
|
+
#
|
|
102
|
+
# @see Select#select_by
|
|
103
|
+
#
|
|
104
|
+
|
|
105
|
+
def deselect_by(how, what)
|
|
106
|
+
case how
|
|
107
|
+
when :text
|
|
108
|
+
deselect_by_text what
|
|
109
|
+
when :value
|
|
110
|
+
deselect_by_value what
|
|
111
|
+
when :index
|
|
112
|
+
deselect_by_index what
|
|
113
|
+
else
|
|
114
|
+
raise ArgumentError, "can't deselect options by #{how.inspect}"
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
#
|
|
119
|
+
# Select all unselected options. Only valid if the element supports multiple selections.
|
|
120
|
+
#
|
|
121
|
+
# @raise [Error::UnsupportedOperationError] if the element does not support multiple selections.
|
|
122
|
+
#
|
|
123
|
+
|
|
124
|
+
def select_all
|
|
125
|
+
unless multiple?
|
|
126
|
+
raise Error::UnsupportedOperationError, 'you may only select all options of a multi-select'
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
options.each { |e| select_option e }
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
#
|
|
133
|
+
# Deselect all selected options. Only valid if the element supports multiple selections.
|
|
134
|
+
#
|
|
135
|
+
# @raise [Error::UnsupportedOperationError] if the element does not support multiple selections.
|
|
136
|
+
#
|
|
137
|
+
|
|
138
|
+
def deselect_all
|
|
139
|
+
unless multiple?
|
|
140
|
+
raise Error::UnsupportedOperationError, 'you may only deselect all options of a multi-select'
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
options.each { |e| deselect_option e }
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
private
|
|
147
|
+
|
|
148
|
+
def select_by_text(text)
|
|
149
|
+
opts = find_by_text text
|
|
150
|
+
|
|
151
|
+
if opts.empty?
|
|
152
|
+
raise Error::NoSuchElementError, "cannot locate element with text: #{text.inspect}"
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
select_options opts
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def select_by_index(index)
|
|
159
|
+
opts = find_by_index index
|
|
160
|
+
|
|
161
|
+
if opts.empty?
|
|
162
|
+
raise Error::NoSuchElementError, "cannot locate element with index: #{index.inspect}"
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
select_options opts
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def select_by_value(value)
|
|
169
|
+
opts = find_by_value value
|
|
170
|
+
|
|
171
|
+
if opts.empty?
|
|
172
|
+
raise Error::NoSuchElementError, "cannot locate option with value: #{value.inspect}"
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
select_options opts
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def deselect_by_text(text)
|
|
179
|
+
opts = find_by_text text
|
|
180
|
+
|
|
181
|
+
if opts.empty?
|
|
182
|
+
raise Error::NoSuchElementError, "cannot locate element with text: #{text.inspect}"
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
deselect_options opts
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def deselect_by_value(value)
|
|
189
|
+
opts = find_by_value value
|
|
190
|
+
|
|
191
|
+
if opts.empty?
|
|
192
|
+
raise Error::NoSuchElementError, "cannot locate option with value: #{value.inspect}"
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
deselect_options opts
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def deselect_by_index(index)
|
|
199
|
+
opts = find_by_index index
|
|
200
|
+
|
|
201
|
+
if opts.empty?
|
|
202
|
+
raise Error::NoSuchElementError, "cannot locate option with index: #{index}"
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
deselect_options opts
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
private
|
|
209
|
+
|
|
210
|
+
def select_option(option)
|
|
211
|
+
option.click unless option.selected?
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def deselect_option(option)
|
|
215
|
+
option.click if option.selected?
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def select_options(opts)
|
|
219
|
+
if multiple?
|
|
220
|
+
opts.each { |o| select_option o }
|
|
221
|
+
else
|
|
222
|
+
select_option opts.first
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def deselect_options(opts)
|
|
227
|
+
if multiple?
|
|
228
|
+
opts.each { |o| deselect_option o }
|
|
229
|
+
else
|
|
230
|
+
deselect_option opts.first
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def find_by_text(text)
|
|
235
|
+
xpath = ".//option[normalize-space(.) = #{Escaper.escape text}]"
|
|
236
|
+
opts = @element.find_elements(:xpath, xpath)
|
|
237
|
+
|
|
238
|
+
if opts.empty? && text =~ /\s+/
|
|
239
|
+
longest_word = text.split(/\s+/).max_by { |item| item.length }
|
|
240
|
+
|
|
241
|
+
if longest_word.empty?
|
|
242
|
+
candidates = options
|
|
243
|
+
else
|
|
244
|
+
xpath = ".//option[contains(., #{Escaper.escape longest_word})]"
|
|
245
|
+
candidates = @element.find_elements(:xpath, xpath)
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
if multiple?
|
|
249
|
+
candidates.select { |option| text == option.text }
|
|
250
|
+
else
|
|
251
|
+
Array(candidates.find { |option| text == option.text })
|
|
252
|
+
end
|
|
253
|
+
else
|
|
254
|
+
opts
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def find_by_index(index)
|
|
259
|
+
index = index.to_s
|
|
260
|
+
options.select { |option| option.attribute(:index) == index }
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
def find_by_value(value)
|
|
264
|
+
@element.find_elements(:xpath, ".//option[@value = #{Escaper.escape value}]")
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
#
|
|
268
|
+
# @api private
|
|
269
|
+
#
|
|
270
|
+
|
|
271
|
+
module Escaper
|
|
272
|
+
def self.escape(str)
|
|
273
|
+
if str.include?('"') && str.include?("'")
|
|
274
|
+
parts = str.split('"', -1).map { |part| %{"#{part}"} }
|
|
275
|
+
|
|
276
|
+
quoted = parts.join(%{, '"', }).
|
|
277
|
+
gsub(/^"", |, ""$/, '')
|
|
278
|
+
|
|
279
|
+
"concat(#{quoted})"
|
|
280
|
+
elsif str.include?('"')
|
|
281
|
+
# escape string with just a quote into being single quoted: f"oo -> 'f"oo'
|
|
282
|
+
"'#{str}'"
|
|
283
|
+
else
|
|
284
|
+
# otherwise return the quoted string
|
|
285
|
+
%{"#{str}"}
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
end # Escaper
|
|
289
|
+
|
|
290
|
+
end # Select
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
end
|