eyes_selenium 2.15.0 → 2.16.0
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 +4 -4
- data/.gitignore +0 -2
- data/.travis.yml +16 -0
- data/Gemfile +1 -1
- data/README.md +14 -4
- data/Rakefile +8 -1
- data/eyes_selenium.gemspec +26 -17
- data/lib/applitools/base/batch_info.rb +19 -0
- data/lib/applitools/base/dimension.rb +21 -0
- data/lib/applitools/base/environment.rb +19 -0
- data/lib/applitools/base/mouse_trigger.rb +33 -0
- data/lib/applitools/base/point.rb +21 -0
- data/lib/applitools/base/region.rb +77 -0
- data/lib/applitools/base/server_connector.rb +113 -0
- data/lib/applitools/base/session.rb +15 -0
- data/lib/applitools/base/start_info.rb +34 -0
- data/lib/applitools/base/test_results.rb +36 -0
- data/lib/applitools/base/text_trigger.rb +22 -0
- data/lib/applitools/eyes.rb +393 -0
- data/lib/applitools/eyes_logger.rb +40 -0
- data/lib/applitools/method_tracer.rb +22 -0
- data/lib/applitools/selenium/driver.rb +194 -0
- data/lib/applitools/selenium/element.rb +66 -0
- data/lib/applitools/selenium/keyboard.rb +27 -0
- data/lib/applitools/selenium/match_window_data.rb +24 -0
- data/lib/applitools/selenium/match_window_task.rb +190 -0
- data/lib/applitools/selenium/mouse.rb +62 -0
- data/lib/applitools/selenium/viewport_size.rb +128 -0
- data/lib/applitools/utils/image_delta_compressor.rb +150 -0
- data/lib/applitools/utils/image_utils.rb +63 -0
- data/lib/applitools/utils/utils.rb +52 -0
- data/lib/applitools/version.rb +3 -0
- data/lib/eyes_selenium.rb +9 -29
- data/spec/driver_passthrough_spec.rb +25 -25
- data/spec/spec_helper.rb +5 -8
- data/test/appium_example_script.rb +57 -0
- data/{test_script.rb → test/test_script.rb} +7 -9
- data/{watir_test.rb → test/watir_test_script.rb} +6 -4
- metadata +120 -48
- data/appium_eyes_example.rb +0 -56
- data/lib/eyes_selenium/capybara.rb +0 -21
- data/lib/eyes_selenium/eyes/agent_connector.rb +0 -76
- data/lib/eyes_selenium/eyes/batch_info.rb +0 -19
- data/lib/eyes_selenium/eyes/dimension.rb +0 -15
- data/lib/eyes_selenium/eyes/driver.rb +0 -266
- data/lib/eyes_selenium/eyes/element.rb +0 -78
- data/lib/eyes_selenium/eyes/environment.rb +0 -15
- data/lib/eyes_selenium/eyes/eyes.rb +0 -396
- data/lib/eyes_selenium/eyes/eyes_keyboard.rb +0 -25
- data/lib/eyes_selenium/eyes/eyes_mouse.rb +0 -60
- data/lib/eyes_selenium/eyes/failure_reports.rb +0 -4
- data/lib/eyes_selenium/eyes/match_level.rb +0 -8
- data/lib/eyes_selenium/eyes/match_window_data.rb +0 -18
- data/lib/eyes_selenium/eyes/match_window_task.rb +0 -182
- data/lib/eyes_selenium/eyes/mouse_trigger.rb +0 -23
- data/lib/eyes_selenium/eyes/region.rb +0 -72
- data/lib/eyes_selenium/eyes/screenshot_taker.rb +0 -18
- data/lib/eyes_selenium/eyes/session.rb +0 -14
- data/lib/eyes_selenium/eyes/start_info.rb +0 -32
- data/lib/eyes_selenium/eyes/test_results.rb +0 -32
- data/lib/eyes_selenium/eyes/text_trigger.rb +0 -19
- data/lib/eyes_selenium/eyes/viewport_size.rb +0 -105
- data/lib/eyes_selenium/eyes_logger.rb +0 -47
- data/lib/eyes_selenium/utils.rb +0 -6
- data/lib/eyes_selenium/utils/image_delta_compressor.rb +0 -149
- data/lib/eyes_selenium/utils/image_utils.rb +0 -76
- data/lib/eyes_selenium/version.rb +0 -3
data/appium_eyes_example.rb
DELETED
@@ -1,56 +0,0 @@
|
|
1
|
-
require 'eyes_selenium'
|
2
|
-
require 'appium_lib'
|
3
|
-
|
4
|
-
##
|
5
|
-
# Based on Appium example: https://github.com/appium/appium/blob/master/sample-code/examples/ruby/
|
6
|
-
|
7
|
-
|
8
|
-
def android_caps
|
9
|
-
{
|
10
|
-
deviceName: 'Samsung Galaxy S4 Emulator',
|
11
|
-
platformName: 'Android',
|
12
|
-
platformVersion: 4.4,
|
13
|
-
app: ENV['ANDROID_NOTES_LIST_APP'],
|
14
|
-
appPackage: 'com.example.android.notepad',
|
15
|
-
appActivity: '.NotesList',
|
16
|
-
# orientation: 'landscape',
|
17
|
-
newCommandTimeout: 300
|
18
|
-
}
|
19
|
-
end
|
20
|
-
def ios_caps
|
21
|
-
{
|
22
|
-
deviceName: 'iPhone 6',
|
23
|
-
platformName: 'ios',
|
24
|
-
platformVersion: 8.3,
|
25
|
-
app: ENV['IOS_DEMO_APP'],
|
26
|
-
orientation: 'landscape',
|
27
|
-
newCommandTimeout: 300
|
28
|
-
}
|
29
|
-
end
|
30
|
-
|
31
|
-
def appium_opts
|
32
|
-
{
|
33
|
-
server_url: 'http://127.0.0.1:4723/wd/hub',
|
34
|
-
}
|
35
|
-
end
|
36
|
-
|
37
|
-
|
38
|
-
@eyes = Applitools::Eyes.new
|
39
|
-
@eyes.log_handler = Logger.new(STDOUT)
|
40
|
-
@eyes.api_key = ENV['APPLITOOLS_API_KEY']
|
41
|
-
begin
|
42
|
-
# @driver = Appium::Driver.new({caps: android_caps, appium_lib: appium_opts})
|
43
|
-
@driver = Appium::Driver.new({caps: ios_caps, appium_lib: appium_opts})
|
44
|
-
@driver.start_driver
|
45
|
-
# @driver.driver.rotate :landscape
|
46
|
-
puts "Screen size: #{@driver.driver.manage.window.size}"
|
47
|
-
puts "orientation: #{@driver.driver.orientation}"
|
48
|
-
puts @driver.caps
|
49
|
-
@eyes.open(app_name: 'Selenium Israel', test_name: 'Appium Notepad', driver: @driver)
|
50
|
-
@eyes.check_window("No notes")
|
51
|
-
|
52
|
-
@eyes.close
|
53
|
-
ensure
|
54
|
-
@eyes.abort_if_not_closed
|
55
|
-
@driver.driver_quit
|
56
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
require 'eyes_selenium'
|
2
|
-
|
3
|
-
# Override create driver to inject into capybara's driver
|
4
|
-
class Applitools::Eyes
|
5
|
-
def test(params={}, &block)
|
6
|
-
begin
|
7
|
-
previous_driver = Capybara.current_driver
|
8
|
-
previous_browser = Capybara.current_session.driver.instance_variable_get(:@browser)
|
9
|
-
Capybara.current_driver = :selenium
|
10
|
-
Capybara.current_session.driver.instance_variable_set(:@browser, driver)
|
11
|
-
open(params)
|
12
|
-
yield(self, driver)
|
13
|
-
close
|
14
|
-
rescue Applitools::EyesError
|
15
|
-
ensure
|
16
|
-
abort_if_not_closed
|
17
|
-
Capybara.current_session.driver.instance_variable_set(:@browser, previous_browser)
|
18
|
-
Capybara.current_driver = previous_driver
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
@@ -1,76 +0,0 @@
|
|
1
|
-
require 'httparty'
|
2
|
-
class Applitools::AgentConnector
|
3
|
-
include HTTParty
|
4
|
-
headers 'Accept' => 'application/json'
|
5
|
-
ssl_ca_file File.join(File.dirname(File.expand_path(__FILE__)), '../../../certs/cacert.pem').to_s
|
6
|
-
default_timeout 300
|
7
|
-
|
8
|
-
# comment out when not debugging
|
9
|
-
#http_proxy 'localhost', 8888
|
10
|
-
#debug_output $stdout
|
11
|
-
|
12
|
-
attr_accessor :server_url, :api_key
|
13
|
-
|
14
|
-
def server_url=(server_url)
|
15
|
-
@server_url = server_url
|
16
|
-
# Remove trailing slashes in server url and add the running sessions endpoint uri.
|
17
|
-
@endpoint_uri = server_url.gsub(/\/$/,'') + '/api/sessions/running'
|
18
|
-
end
|
19
|
-
|
20
|
-
def initialize(server_url)
|
21
|
-
self.server_url = server_url
|
22
|
-
end
|
23
|
-
|
24
|
-
def match_window(session, data)
|
25
|
-
self.class.headers 'Content-Type' => 'application/octet-stream'
|
26
|
-
json_data = data.to_hash.to_json.force_encoding('BINARY') # Notice that this does not include the screenshot
|
27
|
-
body = [json_data.length].pack('L>') + json_data + data.screenshot
|
28
|
-
EyesLogger.debug 'Sending match data...'
|
29
|
-
res = self.class.post(@endpoint_uri + "/#{session.id}", query: {apiKey: api_key}, body: body)
|
30
|
-
raise Applitools::EyesError.new('could not connect to server') if res.code != 200
|
31
|
-
EyesLogger.debug "Got response! #{res.parsed_response['asExpected']}"
|
32
|
-
res.parsed_response['asExpected']
|
33
|
-
end
|
34
|
-
|
35
|
-
def start_session(session_start_info)
|
36
|
-
self.class.headers 'Content-Type' => 'application/json'
|
37
|
-
res = self.class.post(@endpoint_uri, query: {apiKey: api_key}, body: { startInfo: session_start_info.to_hash }.to_json)
|
38
|
-
status_code = res.response.message
|
39
|
-
parsed_res = res.parsed_response
|
40
|
-
Applitools::Session.new(parsed_res['id'], parsed_res['url'], status_code == 'Created' )
|
41
|
-
end
|
42
|
-
|
43
|
-
def stop_session(session, aborted=nil, save=false)
|
44
|
-
self.class.headers 'Content-Type' => 'application/json'
|
45
|
-
res = self.class.send_long_request('stop_session') do
|
46
|
-
self.class.delete(@endpoint_uri + "/#{session.id}", query: { aborted: aborted.to_s, updateBaseline: save.to_s, apiKey: api_key })
|
47
|
-
end
|
48
|
-
parsed_res = res.parsed_response
|
49
|
-
parsed_res.delete('$id')
|
50
|
-
Applitools::TestResults.new(*parsed_res.values)
|
51
|
-
end
|
52
|
-
|
53
|
-
private
|
54
|
-
##
|
55
|
-
# Static method for sending long running requests
|
56
|
-
# Args:
|
57
|
-
# name: (String) name of the method being executed
|
58
|
-
# request_block: (block) The actual block to be executed. Will be called using "yield"
|
59
|
-
# noinspection RubyUnusedLocalVariable
|
60
|
-
def self.send_long_request(name, &request_block)
|
61
|
-
delay = 2 # seconds
|
62
|
-
|
63
|
-
headers 'Eyes-Expect' => '202-accepted'
|
64
|
-
while true
|
65
|
-
# Date should be in RFC 1123 format
|
66
|
-
headers 'Eyes-Date' => Time.now.utc.strftime('%a, %d %b %Y %H:%M:%S GMT')
|
67
|
-
res = yield
|
68
|
-
if res.code != 202
|
69
|
-
return res
|
70
|
-
end
|
71
|
-
EyesLogger.debug "#{name}: Still running... Retrying in #{delay}s"
|
72
|
-
sleep delay
|
73
|
-
delay = [10, (delay*1.5).round].min
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
require 'securerandom'
|
2
|
-
|
3
|
-
class Applitools::BatchInfo
|
4
|
-
attr_accessor :id
|
5
|
-
attr_reader :name, :started_at
|
6
|
-
def initialize(name=nil, started_at = Time.now)
|
7
|
-
@name = name
|
8
|
-
@started_at = started_at
|
9
|
-
@id = SecureRandom.uuid
|
10
|
-
end
|
11
|
-
|
12
|
-
def to_hash
|
13
|
-
{
|
14
|
-
name: name,
|
15
|
-
id: id,
|
16
|
-
startedAt: started_at.iso8601
|
17
|
-
}
|
18
|
-
end
|
19
|
-
end
|
@@ -1,266 +0,0 @@
|
|
1
|
-
require 'socket'
|
2
|
-
require 'selenium-webdriver'
|
3
|
-
|
4
|
-
class Applitools::Driver
|
5
|
-
|
6
|
-
# Rotates the image as necessary. The rotation is either manually forced by passing a value in
|
7
|
-
# the +rotation+ parameter, or automatically inferred if the +rotation+ parameter is +nil+.
|
8
|
-
#
|
9
|
-
# +driver+:: +Applitools::Driver+ The driver which produced the screenshot.
|
10
|
-
# +image+:: +ChunkyPNG::Canvas+ The image to normalize.
|
11
|
-
# +rotation+:: +Integer+|+nil+ The degrees by which to rotate the image: positive values = clockwise rotation,
|
12
|
-
# negative values = counter-clockwise, 0 = force no rotation, +nil+ = rotate
|
13
|
-
# automatically when needed.
|
14
|
-
#
|
15
|
-
def self.normalize_rotation!(driver, image, rotation)
|
16
|
-
EyesLogger.debug "#{__method__}()"
|
17
|
-
if rotation != 0
|
18
|
-
num_quadrants = 0
|
19
|
-
if !rotation.nil?
|
20
|
-
if rotation % 90 != 0
|
21
|
-
raise Applitools::EyesError.new(
|
22
|
-
"Currently only quadrant rotations are supported. Current rotation: #{rotation}")
|
23
|
-
end
|
24
|
-
num_quadrants = (rotation / 90).to_i
|
25
|
-
elsif rotation.nil? && driver.mobile_device? && driver.landscape_orientation? && image.height > image.width
|
26
|
-
# For Android, we need to rotate images to the right, and for iOS to the left.
|
27
|
-
num_quadrants = driver.android? ? 1 : -1
|
28
|
-
end
|
29
|
-
Applitools::Utils::ImageUtils.quadrant_rotate!(image, num_quadrants)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
|
34
|
-
include Selenium::WebDriver::DriverExtensions::HasInputDevices
|
35
|
-
|
36
|
-
attr_reader :remote_server_url, :remote_session_id, :screenshot_taker, :eyes
|
37
|
-
attr_accessor :driver
|
38
|
-
|
39
|
-
DRIVER_METHODS = [
|
40
|
-
:title, :execute_script, :execute_async_script, :quit, :close, :get,
|
41
|
-
:post, :page_source, :window_handles, :window_handle, :switch_to,
|
42
|
-
:navigate, :manage, :capabilities, :current_url
|
43
|
-
]
|
44
|
-
|
45
|
-
## If driver is not provided, Applitools::Driver will raise an EyesError exception.
|
46
|
-
#
|
47
|
-
def initialize(eyes, options)
|
48
|
-
@driver = options[:driver]
|
49
|
-
@is_mobile_device = options.fetch(:is_mobile_device, false)
|
50
|
-
@eyes = eyes
|
51
|
-
# FIXME fix getting "remote address url" or remove "Screenshot taker" altogether.
|
52
|
-
# @remote_server_url = address_of_remote_server
|
53
|
-
@remote_server_url = 'MOCK_URL'
|
54
|
-
@remote_session_id = remote_session_id
|
55
|
-
begin
|
56
|
-
#noinspection RubyResolve
|
57
|
-
if driver.capabilities.takes_screenshot?
|
58
|
-
@screenshot_taker = false
|
59
|
-
else
|
60
|
-
@screenshot_taker = Applitools::ScreenshotTaker.new(@remote_server_url, @remote_session_id)
|
61
|
-
end
|
62
|
-
rescue => e
|
63
|
-
raise Applitools::EyesError.new "Can't take screenshots (#{e.message})"
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
DRIVER_METHODS.each do |method|
|
68
|
-
define_method method do |*args, &block|
|
69
|
-
driver.send(method,*args, &block)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
# Returns:
|
74
|
-
# +String+ The platform name or +nil+ if it is undefined.
|
75
|
-
def platform_name
|
76
|
-
driver.capabilities['platformName']
|
77
|
-
end
|
78
|
-
|
79
|
-
# Returns:
|
80
|
-
# +String+ The platform version or +nil+ if it is undefined.
|
81
|
-
def platform_version
|
82
|
-
version = driver.capabilities['platformVersion']
|
83
|
-
version.nil? ? nil : version.to_s
|
84
|
-
end
|
85
|
-
|
86
|
-
# Returns:
|
87
|
-
# +true+ if the driver is an Android driver.
|
88
|
-
def android?
|
89
|
-
platform_name.to_s.upcase == 'ANDROID'
|
90
|
-
end
|
91
|
-
|
92
|
-
# Returns:
|
93
|
-
# +true+ if the driver is an iOS driver.
|
94
|
-
def ios?
|
95
|
-
platform_name.to_s.upcase == 'IOS'
|
96
|
-
end
|
97
|
-
|
98
|
-
# Returns:
|
99
|
-
# +true+ if the driver orientation is landscape.
|
100
|
-
def landscape_orientation?
|
101
|
-
begin
|
102
|
-
driver.orientation.to_s.upcase == 'LANDSCAPE'
|
103
|
-
rescue NameError
|
104
|
-
EyesLogger.debug 'driver has no "orientation" attribute. Assuming Portrait.'
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
# Returns:
|
109
|
-
# +true+ if the platform running the test is a mobile platform. +false+ otherwise.
|
110
|
-
def mobile_device?
|
111
|
-
# We CAN'T check if the device is an +Appium::Driver+ since it is not a RemoteWebDriver. Because of that we use a
|
112
|
-
# flag we got as an option in the constructor.
|
113
|
-
@is_mobile_device
|
114
|
-
end
|
115
|
-
|
116
|
-
# Return a PNG screenshot in the given format as a string
|
117
|
-
#
|
118
|
-
# +output_type+:: +Symbol+ The format of the screenshot. Accepted values are +:base64+ and +:png+.
|
119
|
-
# +rotation+:: +Integer+|+nil+ The degrees by which to rotate the image: positive values = clockwise rotation,
|
120
|
-
# negative values = counter-clockwise, 0 = force no rotation, +nil+ = rotate
|
121
|
-
# automatically when needed.
|
122
|
-
#
|
123
|
-
# Returns: +String+ A screenshot in the requested format.
|
124
|
-
def screenshot_as(output_type, rotation=nil)
|
125
|
-
# FIXME Check if screenshot_taker is still required
|
126
|
-
screenshot = screenshot_taker ? screenshot_taker.screenshot : driver.screenshot_as(:base64)
|
127
|
-
screenshot = Applitools::Utils::ImageUtils.png_image_from_base64(screenshot)
|
128
|
-
Applitools::Driver.normalize_rotation!(self, screenshot, rotation)
|
129
|
-
case output_type
|
130
|
-
when :base64
|
131
|
-
screenshot = Applitools::Utils::ImageUtils.base64_from_png_image(screenshot)
|
132
|
-
when :png
|
133
|
-
screenshot = Applitools::Utils::ImageUtils.bytes_from_png_image(screenshot)
|
134
|
-
else
|
135
|
-
raise Applitools::EyesError.new("Unsupported screenshot output type #{output_type.to_s}")
|
136
|
-
end
|
137
|
-
screenshot.force_encoding('BINARY')
|
138
|
-
end
|
139
|
-
|
140
|
-
def mouse
|
141
|
-
Applitools::EyesMouse.new(self, driver.mouse)
|
142
|
-
end
|
143
|
-
|
144
|
-
def keyboard
|
145
|
-
Applitools::EyesKeyboard.new(self, driver.keyboard)
|
146
|
-
end
|
147
|
-
|
148
|
-
FINDERS = {
|
149
|
-
:class => 'class name',
|
150
|
-
:class_name => 'class name',
|
151
|
-
:css => 'css selector',
|
152
|
-
:id => 'id',
|
153
|
-
:link => 'link text',
|
154
|
-
:link_text => 'link text',
|
155
|
-
:name => 'name',
|
156
|
-
:partial_link_text => 'partial link text',
|
157
|
-
:tag_name => 'tag name',
|
158
|
-
:xpath => 'xpath',
|
159
|
-
}
|
160
|
-
|
161
|
-
def find_element(*args)
|
162
|
-
how, what = extract_args(args)
|
163
|
-
|
164
|
-
# Make sure that "how" is a valid locator.
|
165
|
-
unless FINDERS[how.to_sym]
|
166
|
-
raise ArgumentError, "cannot find element by #{how.inspect}"
|
167
|
-
end
|
168
|
-
|
169
|
-
Applitools::Element.new(self, driver.find_element(how, what))
|
170
|
-
end
|
171
|
-
|
172
|
-
def find_elements(*args)
|
173
|
-
how, what = extract_args(args)
|
174
|
-
|
175
|
-
unless FINDERS[how.to_sym]
|
176
|
-
raise ArgumentError, "cannot find element by #{how.inspect}"
|
177
|
-
end
|
178
|
-
|
179
|
-
driver.find_elements(how, what).map { |el| Applitools::Element.new(self, el) }
|
180
|
-
end
|
181
|
-
|
182
|
-
def ie?
|
183
|
-
driver.to_s == 'ie'
|
184
|
-
end
|
185
|
-
|
186
|
-
def firefox?
|
187
|
-
driver.to_s == 'firefox'
|
188
|
-
end
|
189
|
-
|
190
|
-
def user_agent
|
191
|
-
execute_script 'return navigator.userAgent'
|
192
|
-
rescue => e
|
193
|
-
EyesLogger.info "getUserAgent(): Failed to obtain user-agent string (#{e.message})"
|
194
|
-
return nil
|
195
|
-
end
|
196
|
-
|
197
|
-
private
|
198
|
-
|
199
|
-
# FIXME Fix extraction of remote server, or remove completely if removed ScreenshotTaker
|
200
|
-
# def address_of_remote_server
|
201
|
-
# # The driver's url is not available using a standard interface, so we use reflection to get it.
|
202
|
-
# #noinspection RubyResolve
|
203
|
-
# uri = URI(driver.instance_eval{@bridge}.instance_eval{@http}.instance_eval{@server_url})
|
204
|
-
# raise Applitools::EyesError.new('Failed to get remote web driver url') if uri.to_s.empty?
|
205
|
-
#
|
206
|
-
# webdriver_host = uri.host
|
207
|
-
# if %w[127.0.0.1 localhost].include?(webdriver_host) && !firefox? && !ie?
|
208
|
-
# uri.host = get_local_ip || 'localhost'
|
209
|
-
# end
|
210
|
-
#
|
211
|
-
# uri
|
212
|
-
# end
|
213
|
-
|
214
|
-
def remote_session_id
|
215
|
-
driver.remote_session_id
|
216
|
-
end
|
217
|
-
|
218
|
-
def get_local_ip
|
219
|
-
begin
|
220
|
-
Socket.ip_address_list.detect do |intf|
|
221
|
-
intf.ipv4? and !intf.ipv4_loopback? and !intf.ipv4_multicast?
|
222
|
-
end.ip_address
|
223
|
-
rescue SocketError => e
|
224
|
-
raise Applitools::EyesError.new("Failed to get local IP! (#{e})")
|
225
|
-
end
|
226
|
-
end
|
227
|
-
|
228
|
-
def extract_args(args)
|
229
|
-
case args.size
|
230
|
-
when 2
|
231
|
-
args
|
232
|
-
when 1
|
233
|
-
arg = args.first
|
234
|
-
|
235
|
-
unless arg.respond_to?(:shift)
|
236
|
-
raise ArgumentError, "expected #{arg.inspect}:#{arg.class} to respond to #shift"
|
237
|
-
end
|
238
|
-
|
239
|
-
# this will be a single-entry hash, so use #shift over #first or #[]
|
240
|
-
arr = arg.dup.shift
|
241
|
-
unless arr.size == 2
|
242
|
-
raise ArgumentError, "expected #{arr.inspect} to have 2 elements"
|
243
|
-
end
|
244
|
-
|
245
|
-
arr
|
246
|
-
else
|
247
|
-
raise ArgumentError, "wrong number of arguments (#{args.size} for 2)"
|
248
|
-
end
|
249
|
-
end
|
250
|
-
|
251
|
-
end
|
252
|
-
|
253
|
-
## .bridge, .session_id and .server_url are private methods in Selenium::WebDriver gem
|
254
|
-
module Selenium::WebDriver
|
255
|
-
class Driver
|
256
|
-
def remote_session_id
|
257
|
-
bridge.session_id
|
258
|
-
end
|
259
|
-
end
|
260
|
-
|
261
|
-
class Remote::Http::Common
|
262
|
-
def get_server_url
|
263
|
-
server_url
|
264
|
-
end
|
265
|
-
end
|
266
|
-
end
|