selenium-webdriver 0.0.17 → 0.0.18
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.
- data/chrome/prebuilt/Win32/Release/npchromedriver.dll +0 -0
- data/chrome/prebuilt/x64/Release/npchromedriver.dll +0 -0
- data/chrome/src/extension/background.js +64 -48
- data/chrome/src/extension/content_script.js +253 -132
- data/chrome/src/extension/manifest-nonwin.json +1 -1
- data/chrome/src/extension/manifest-win.json +1 -1
- data/chrome/src/extension/utils.js +8 -8
- data/chrome/src/rb/lib/selenium/webdriver/chrome.rb +9 -0
- data/chrome/src/rb/lib/selenium/webdriver/chrome/bridge.rb +38 -280
- data/chrome/src/rb/lib/selenium/webdriver/chrome/command_executor.rb +119 -117
- data/chrome/src/rb/lib/selenium/webdriver/chrome/launcher.rb +36 -26
- data/common/src/js/abstractcommandprocessor.js +9 -11
- data/common/src/js/command.js +159 -83
- data/common/src/js/core/RemoteRunner.html +2 -2
- data/common/src/js/core/TestRunner-splash.html +3 -3
- data/common/src/js/core/TestRunner.html +5 -17
- data/common/src/js/core/scripts/htmlutils.js +4208 -2506
- data/common/src/js/core/scripts/selenium-api.js +2 -2
- data/common/src/js/core/scripts/selenium-browserbot.js +66 -58
- data/common/src/js/core/scripts/selenium-version.js +1 -1
- data/common/src/js/localcommandprocessor.js +5 -19
- data/common/src/js/testcase.js +2 -0
- data/common/src/js/webdriver.js +63 -93
- data/common/src/js/webelement.js +40 -42
- data/common/src/rb/lib/selenium/webdriver.rb +23 -14
- data/common/src/rb/lib/selenium/webdriver/bridge_helper.rb +8 -35
- data/common/src/rb/lib/selenium/webdriver/child_process.rb +2 -0
- data/common/src/rb/lib/selenium/webdriver/core_ext/dir.rb +1 -0
- data/common/src/rb/lib/selenium/webdriver/core_ext/string.rb +5 -0
- data/common/src/rb/lib/selenium/webdriver/driver.rb +20 -15
- data/common/src/rb/lib/selenium/webdriver/driver_extensions/takes_screenshot.rb +7 -2
- data/common/src/rb/lib/selenium/webdriver/element.rb +11 -2
- data/common/src/rb/lib/selenium/webdriver/error.rb +9 -5
- data/common/src/rb/lib/selenium/webdriver/keys.rb +1 -2
- data/common/src/rb/lib/selenium/webdriver/navigation.rb +16 -0
- data/common/src/rb/lib/selenium/webdriver/options.rb +32 -0
- data/common/src/rb/lib/selenium/webdriver/platform.rb +17 -1
- data/firefox/prebuilt/Win32/Release/webdriver-firefox.dll +0 -0
- data/firefox/src/extension/components/dispatcher.js +492 -0
- data/firefox/src/extension/components/driver-component.js +4 -1
- data/firefox/src/extension/components/errorcode.js +70 -0
- data/firefox/src/extension/components/firefoxDriver.js +173 -154
- data/firefox/src/extension/components/nsCommandProcessor.js +171 -132
- data/firefox/src/extension/components/promptService.js +5 -5
- data/firefox/src/extension/components/request.js +219 -0
- data/firefox/src/extension/components/response.js +276 -0
- data/firefox/src/extension/components/session.js +281 -0
- data/firefox/src/extension/components/sessionstore.js +226 -0
- data/firefox/src/extension/components/socketListener.js +350 -100
- data/firefox/src/extension/components/utils.js +166 -98
- data/firefox/src/extension/components/webdriverserver.js +9 -5
- data/firefox/src/extension/components/wrappedElement.js +189 -166
- data/firefox/src/extension/install.rdf +1 -1
- data/firefox/src/rb/lib/selenium/webdriver/firefox.rb +2 -0
- data/firefox/src/rb/lib/selenium/webdriver/firefox/binary.rb +39 -33
- data/firefox/src/rb/lib/selenium/webdriver/firefox/bridge.rb +7 -421
- data/firefox/src/rb/lib/selenium/webdriver/firefox/extension_connection.rb +7 -64
- data/firefox/src/rb/lib/selenium/webdriver/firefox/launcher.rb +2 -3
- data/firefox/src/rb/lib/selenium/webdriver/firefox/profile.rb +54 -10
- data/firefox/src/rb/lib/selenium/webdriver/firefox/profiles_ini.rb +2 -0
- data/firefox/src/rb/lib/selenium/webdriver/firefox/util.rb +6 -0
- data/jobbie/prebuilt/Win32/Release/InternetExplorerDriver.dll +0 -0
- data/jobbie/prebuilt/x64/Release/InternetExplorerDriver.dll +0 -0
- data/jobbie/src/rb/lib/selenium/webdriver/ie.rb +2 -0
- data/jobbie/src/rb/lib/selenium/webdriver/ie/bridge.rb +38 -13
- data/jobbie/src/rb/lib/selenium/webdriver/ie/lib.rb +9 -2
- data/jobbie/src/rb/lib/selenium/webdriver/ie/util.rb +5 -0
- data/remote/client/src/rb/lib/selenium/webdriver/remote.rb +2 -0
- data/remote/client/src/rb/lib/selenium/webdriver/remote/bridge.rb +42 -38
- data/remote/client/src/rb/lib/selenium/webdriver/remote/commands.rb +56 -47
- data/remote/client/src/rb/lib/selenium/webdriver/remote/default_http_client.rb +26 -26
- data/remote/client/src/rb/lib/selenium/webdriver/remote/patron_http_client.rb +58 -0
- data/remote/client/src/rb/lib/selenium/webdriver/remote/response.rb +10 -12
- data/remote/client/src/rb/lib/selenium/webdriver/remote/server_error.rb +2 -17
- metadata +44 -23
- data/common/src/js/context.js +0 -58
- data/firefox/src/extension/components/context.js +0 -37
|
@@ -7,19 +7,13 @@ module Selenium
|
|
|
7
7
|
#
|
|
8
8
|
# Low level bridge to the remote server, through which the rest of the API works.
|
|
9
9
|
#
|
|
10
|
-
# @
|
|
10
|
+
# @private
|
|
11
11
|
#
|
|
12
12
|
|
|
13
13
|
class Bridge
|
|
14
14
|
include Find
|
|
15
15
|
include BridgeHelper
|
|
16
16
|
|
|
17
|
-
DEFAULT_OPTIONS = {
|
|
18
|
-
:url => "http://localhost:4444/wd/hub",
|
|
19
|
-
:http_client => DefaultHttpClient,
|
|
20
|
-
:desired_capabilities => Capabilities.firefox
|
|
21
|
-
}
|
|
22
|
-
|
|
23
17
|
#
|
|
24
18
|
# Defines a wrapper method for a command, which ultimately calls #execute.
|
|
25
19
|
#
|
|
@@ -27,10 +21,7 @@ module Selenium
|
|
|
27
21
|
# name of the resulting method
|
|
28
22
|
# @param url [String]
|
|
29
23
|
# a URL template, which can include some arguments, much like the definitions on the server.
|
|
30
|
-
# the :session_id
|
|
31
|
-
# required method arguments.
|
|
32
|
-
# e.g., "session/:session_id/:context/element/:id/text" will define a method that takes id
|
|
33
|
-
# as it's first argument.
|
|
24
|
+
# the :session_id parameter is implicitly handled, but the remainder will become required method arguments.
|
|
34
25
|
# @param verb [Symbol]
|
|
35
26
|
# the appropriate http verb, such as :get, :post, or :delete
|
|
36
27
|
#
|
|
@@ -51,7 +42,7 @@ module Selenium
|
|
|
51
42
|
#
|
|
52
43
|
|
|
53
44
|
def initialize(opts = {})
|
|
54
|
-
opts =
|
|
45
|
+
opts = default_options.merge(opts)
|
|
55
46
|
http_client_class = opts.delete(:http_client)
|
|
56
47
|
desired_capabilities = opts.delete(:desired_capabilities)
|
|
57
48
|
url = opts.delete(:url)
|
|
@@ -71,7 +62,6 @@ module Selenium
|
|
|
71
62
|
uri = URI.parse(url)
|
|
72
63
|
uri.path += "/" unless uri.path =~ /\/$/
|
|
73
64
|
|
|
74
|
-
@context = "context"
|
|
75
65
|
@http = http_client_class.new uri
|
|
76
66
|
@capabilities = create_session(desired_capabilities)
|
|
77
67
|
end
|
|
@@ -92,17 +82,15 @@ module Selenium
|
|
|
92
82
|
@session_id || raise(Error::WebDriverError, "no current session exists")
|
|
93
83
|
end
|
|
94
84
|
|
|
95
|
-
|
|
96
85
|
def create_session(desired_capabilities)
|
|
97
|
-
resp = raw_execute :newSession, {}, desired_capabilities
|
|
86
|
+
resp = raw_execute :newSession, {}, :desiredCapabilities => desired_capabilities
|
|
98
87
|
@session_id = resp['sessionId'] || raise(Error::WebDriverError, 'no sessionId in returned payload')
|
|
99
|
-
@context = resp['context']
|
|
100
88
|
|
|
101
89
|
Capabilities.json_create resp['value']
|
|
102
90
|
end
|
|
103
91
|
|
|
104
92
|
def get(url)
|
|
105
|
-
execute :get, {}, url
|
|
93
|
+
execute :get, {}, :url => url
|
|
106
94
|
end
|
|
107
95
|
|
|
108
96
|
def goBack
|
|
@@ -134,15 +122,15 @@ module Selenium
|
|
|
134
122
|
end
|
|
135
123
|
|
|
136
124
|
def switchToWindow(name)
|
|
137
|
-
execute :switchToWindow, :name => name
|
|
125
|
+
execute :switchToWindow, {}, :name => name
|
|
138
126
|
end
|
|
139
127
|
|
|
140
128
|
def switchToFrame(id)
|
|
141
|
-
execute :switchToFrame, :id => id
|
|
129
|
+
execute :switchToFrame, {}, :id => id
|
|
142
130
|
end
|
|
143
131
|
|
|
144
132
|
def switchToDefaultContent
|
|
145
|
-
execute :switchToFrame, :id => nil
|
|
133
|
+
execute :switchToFrame, {}, :id => nil
|
|
146
134
|
end
|
|
147
135
|
|
|
148
136
|
def quit
|
|
@@ -166,7 +154,7 @@ module Selenium
|
|
|
166
154
|
end
|
|
167
155
|
|
|
168
156
|
def setSpeed(value)
|
|
169
|
-
execute :setSpeed, {}, value
|
|
157
|
+
execute :setSpeed, {}, :speed => value
|
|
170
158
|
end
|
|
171
159
|
|
|
172
160
|
def getSpeed
|
|
@@ -178,18 +166,16 @@ module Selenium
|
|
|
178
166
|
raise Error::UnsupportedOperationError, "underlying webdriver instance does not support javascript"
|
|
179
167
|
end
|
|
180
168
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
unwrap_script_argument response['value']
|
|
169
|
+
result = execute :executeScript, {}, :script => script, :args => args
|
|
170
|
+
unwrap_script_result result
|
|
185
171
|
end
|
|
186
172
|
|
|
187
173
|
def addCookie(cookie)
|
|
188
|
-
execute :addCookie, {}, cookie
|
|
174
|
+
execute :addCookie, {}, :cookie => cookie
|
|
189
175
|
end
|
|
190
176
|
|
|
191
177
|
def deleteCookie(name)
|
|
192
|
-
execute :
|
|
178
|
+
execute :deleteCookieNamed, :name => name
|
|
193
179
|
end
|
|
194
180
|
|
|
195
181
|
def getAllCookies
|
|
@@ -339,18 +325,20 @@ module Selenium
|
|
|
339
325
|
end
|
|
340
326
|
|
|
341
327
|
def dragElement(element, rigth_by, down_by)
|
|
342
|
-
|
|
343
|
-
|
|
328
|
+
execute :dragElement, {:id => element}, :x => rigth_by, :y => down_by
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
def getCapabilities
|
|
332
|
+
Capabilities.json_create execute(:getCapabilities)
|
|
344
333
|
end
|
|
345
334
|
|
|
346
335
|
private
|
|
347
336
|
|
|
348
337
|
def find_element_by(how, what, parent = nil)
|
|
349
338
|
if parent
|
|
350
|
-
|
|
351
|
-
id = execute :findChildElement, {:id => parent, :using => how}, {:using => how, :value => what}
|
|
339
|
+
id = execute :findChildElement, {:id => parent}, {:using => how, :value => what}
|
|
352
340
|
else
|
|
353
|
-
id = execute :findElement, {}, how, what
|
|
341
|
+
id = execute :findElement, {}, {:using => how, :value => what}
|
|
354
342
|
end
|
|
355
343
|
|
|
356
344
|
Element.new self, element_id_from(id)
|
|
@@ -359,9 +347,9 @@ module Selenium
|
|
|
359
347
|
def find_elements_by(how, what, parent = nil)
|
|
360
348
|
if parent
|
|
361
349
|
# TODO: why is how sent twice in the payload?
|
|
362
|
-
ids = execute :findChildElements, {:id => parent
|
|
350
|
+
ids = execute :findChildElements, {:id => parent}, {:using => how, :value => what}
|
|
363
351
|
else
|
|
364
|
-
ids = execute :findElements, {}, how, what
|
|
352
|
+
ids = execute :findElements, {}, {:using => how, :value => what}
|
|
365
353
|
end
|
|
366
354
|
|
|
367
355
|
ids.map { |id| Element.new self, element_id_from(id) }
|
|
@@ -385,21 +373,37 @@ module Selenium
|
|
|
385
373
|
# Returns a WebDriver::Remote::Response instance
|
|
386
374
|
#
|
|
387
375
|
|
|
388
|
-
def raw_execute(command, opts = {},
|
|
376
|
+
def raw_execute(command, opts = {}, command_hash = nil)
|
|
389
377
|
verb, path = COMMANDS[command] || raise("unknown command #{command.inspect}")
|
|
390
378
|
path = path.dup
|
|
391
379
|
|
|
392
380
|
path[':session_id'] = @session_id if path.include?(":session_id")
|
|
393
|
-
path[':context'] = @context if path.include?(":context")
|
|
394
381
|
|
|
395
382
|
begin
|
|
396
|
-
opts.each { |key, value| path[key.inspect] = URI.escape(value.to_s)
|
|
383
|
+
opts.each { |key, value| path[key.inspect] = URI.escape(value.to_s)}
|
|
397
384
|
rescue IndexError
|
|
398
385
|
raise ArgumentError, "#{opts.inspect} invalid for #{command.inspect}"
|
|
399
386
|
end
|
|
400
387
|
|
|
401
388
|
puts "-> #{verb.to_s.upcase} #{path}" if $DEBUG
|
|
402
|
-
http.call verb, path,
|
|
389
|
+
http.call verb, path, command_hash
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
def default_options
|
|
393
|
+
{
|
|
394
|
+
:url => "http://localhost:4444/wd/hub",
|
|
395
|
+
# TODO(jari): enable Patron when http://github.com/toland/patron/issues/issue/13 is fixed
|
|
396
|
+
:http_client => DefaultHttpClient,
|
|
397
|
+
:desired_capabilities => Capabilities.firefox
|
|
398
|
+
}
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
def http_client_class
|
|
402
|
+
require "selenium/webdriver/remote/patron_http_client"
|
|
403
|
+
PatronHttpClient
|
|
404
|
+
rescue LoadError
|
|
405
|
+
# patron not available
|
|
406
|
+
DefaultHttpClient
|
|
403
407
|
end
|
|
404
408
|
|
|
405
409
|
end # Bridge
|
|
@@ -1,53 +1,62 @@
|
|
|
1
|
+
# @private
|
|
1
2
|
class Selenium::WebDriver::Remote::Bridge
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
command :getCurrentUrl, :get, "session/:session_id/:context/url"
|
|
8
|
-
command :deleteAllCookies, :delete, "session/:session_id/:context/cookie"
|
|
9
|
-
command :deleteCookie, :delete, "session/:session_id/:context/cookie/:name"
|
|
10
|
-
command :dragElement, :post, "session/:session_id/:context/element/:id/drag"
|
|
11
|
-
command :elementEquals, :get, "session/:session_id/:context/element/:id/equals/:other"
|
|
12
|
-
command :executeScript, :post, "session/:session_id/:context/execute"
|
|
13
|
-
command :findElement, :post, "session/:session_id/:context/element"
|
|
14
|
-
command :findElements, :post, "session/:session_id/:context/elements"
|
|
15
|
-
command :findChildElement, :post, "session/:session_id/:context/element/:id/element/:using"
|
|
16
|
-
command :findChildElements, :post, "session/:session_id/:context/element/:id/elements/:using"
|
|
17
|
-
command :goForward, :post, "session/:session_id/:context/forward"
|
|
18
|
-
command :get, :post, "session/:session_id/:context/url"
|
|
19
|
-
command :getActiveElement, :post, "session/:session_id/:context/element/active"
|
|
20
|
-
command :getAllCookies, :get, "session/:session_id/:context/cookie"
|
|
21
|
-
# command :getCookie # TODO: getCookie
|
|
22
|
-
command :getCurrentWindowHandle, :get, "session/:session_id/:context/window_handle"
|
|
23
|
-
command :getElementAttribute, :get, "session/:session_id/:context/element/:id/attribute/:name"
|
|
24
|
-
command :getElementLocation, :get, "session/:session_id/:context/element/:id/location"
|
|
25
|
-
command :getElementSize, :get, "session/:session_id/:context/element/:id/size"
|
|
26
|
-
command :getElementText, :get, "session/:session_id/:context/element/:id/text"
|
|
27
|
-
command :getElementValue, :get, "session/:session_id/:context/element/:id/value"
|
|
28
|
-
command :getSpeed, :get, "session/:session_id/:context/speed"
|
|
29
|
-
command :getElementTagName, :get, "session/:session_id/:context/element/:id/name"
|
|
30
|
-
command :getTitle, :get, "session/:session_id/:context/title"
|
|
31
|
-
command :getElementValueOfCssProperty, :get, "session/:session_id/:context/element/:id/css/:property_name"
|
|
32
|
-
command :getVisible, :get, "session/:session_id/:context/visible"
|
|
33
|
-
command :getWindowHandles, :get, "session/:session_id/:context/window_handles"
|
|
34
|
-
command :hoverOverElement, :post, "session/:session_id/:context/element/:id/hover"
|
|
35
|
-
command :isElementDisplayed, :get, "session/:session_id/:context/element/:id/displayed"
|
|
36
|
-
command :isElementEnabled, :get, "session/:session_id/:context/element/:id/enabled"
|
|
37
|
-
command :isElementSelected, :get, "session/:session_id/:context/element/:id/selected"
|
|
3
|
+
|
|
4
|
+
#
|
|
5
|
+
# http://code.google.com/p/selenium/wiki/JsonWireProtocol#Command_Reference
|
|
6
|
+
#
|
|
7
|
+
|
|
38
8
|
command :newSession, :post, "session"
|
|
39
|
-
command :
|
|
9
|
+
command :getCapabilities, :get, "session/:session_id"
|
|
40
10
|
command :quit, :delete, "session/:session_id"
|
|
41
|
-
command :
|
|
42
|
-
command :
|
|
43
|
-
command :
|
|
44
|
-
command :
|
|
45
|
-
command :
|
|
46
|
-
command :
|
|
47
|
-
command :
|
|
48
|
-
command :
|
|
11
|
+
command :getCurrentWindowHandle, :get, "session/:session_id/window_handle"
|
|
12
|
+
command :getWindowHandles, :get, "session/:session_id/window_handles"
|
|
13
|
+
command :getCurrentUrl, :get, "session/:session_id/url"
|
|
14
|
+
command :get, :post, "session/:session_id/url"
|
|
15
|
+
command :goForward, :post, "session/:session_id/forward"
|
|
16
|
+
command :goBack, :post, "session/:session_id/back"
|
|
17
|
+
command :refresh, :post, "session/:session_id/refresh"
|
|
18
|
+
command :executeScript, :post, "session/:session_id/execute"
|
|
19
|
+
command :screenshot, :get, "session/:session_id/screenshot"
|
|
20
|
+
command :switchToFrame, :post, "session/:session_id/frame"
|
|
21
|
+
command :switchToWindow, :post, "session/:session_id/window"
|
|
22
|
+
command :getSpeed, :get, "session/:session_id/speed"
|
|
23
|
+
command :setSpeed, :post, "session/:session_id/speed"
|
|
24
|
+
command :getAllCookies, :get, "session/:session_id/cookie"
|
|
25
|
+
command :addCookie, :post, "session/:session_id/cookie"
|
|
26
|
+
command :deleteAllCookies, :delete, "session/:session_id/cookie"
|
|
27
|
+
command :deleteCookieNamed, :delete, "session/:session_id/cookie/:name"
|
|
28
|
+
command :getPageSource, :get, "session/:session_id/source"
|
|
29
|
+
command :getTitle, :get, "session/:session_id/title"
|
|
30
|
+
command :findElement, :post, "session/:session_id/element"
|
|
31
|
+
command :findElements, :post, "session/:session_id/elements"
|
|
32
|
+
command :getActiveElement, :post, "session/:session_id/element/active"
|
|
33
|
+
command :describeElement, :get, "session/:session_id/element/:id"
|
|
34
|
+
command :findChildElement, :post, "session/:session_id/element/:id/element"
|
|
35
|
+
command :findChildElements, :post, "session/:session_id/element/:id/elements"
|
|
36
|
+
command :clickElement, :post, "session/:session_id/element/:id/click"
|
|
37
|
+
command :submitElement, :post, "session/:session_id/element/:id/submit"
|
|
38
|
+
command :getElementValue, :get, "session/:session_id/element/:id/value"
|
|
39
|
+
command :sendKeysToElement, :post, "session/:session_id/element/:id/value"
|
|
40
|
+
command :getElementTagName, :get, "session/:session_id/element/:id/name"
|
|
41
|
+
command :clearElement, :post, "session/:session_id/element/:id/clear"
|
|
42
|
+
command :isElementSelected, :get, "session/:session_id/element/:id/selected"
|
|
43
|
+
command :setElementSelected, :post, "session/:session_id/element/:id/selected"
|
|
44
|
+
command :toggleElement, :post, "session/:session_id/element/:id/toggle"
|
|
45
|
+
command :isElementEnabled, :get, "session/:session_id/element/:id/enabled"
|
|
46
|
+
command :getElementAttribute, :get, "session/:session_id/element/:id/attribute/:name"
|
|
47
|
+
command :elementEquals, :get, "session/:session_id/element/:id/equals/:other"
|
|
48
|
+
command :isElementDisplayed, :get, "session/:session_id/element/:id/displayed"
|
|
49
|
+
command :getElementLocation, :get, "session/:session_id/element/:id/location"
|
|
50
|
+
command :getElementLocationInView, :get, "session/:session_id/element/:id/location_in_view"
|
|
51
|
+
command :getElementSize, :get, "session/:session_id/element/:id/size"
|
|
52
|
+
command :hoverOverElement, :post, "session/:session_id/element/:id/hover"
|
|
53
|
+
command :dragElement, :post, "session/:session_id/element/:id/drag"
|
|
54
|
+
command :getElementValueOfCssProperty, :get, "session/:session_id/element/:id/css/:property_name"
|
|
55
|
+
|
|
56
|
+
command :close, :delete, "session/:session_id/window"
|
|
57
|
+
command :getElementText, :get, "session/:session_id/element/:id/text"
|
|
58
|
+
command :getVisible, :get, "session/:session_id/visible"
|
|
59
|
+
command :setVisible, :post, "session/:session_id/visible"
|
|
49
60
|
# command :switchToFrameByIndex # TODO: switchToFrameByIndex
|
|
50
61
|
# command :switchToDefaultContent # TODO: switchToDefaultContent
|
|
51
|
-
command :switchToWindow, :post, "session/:session_id/:context/window/:name"
|
|
52
|
-
command :toggleElement, :post, "session/:session_id/:context/element/:id/toggle"
|
|
53
62
|
end
|
|
@@ -3,45 +3,33 @@ require "net/http"
|
|
|
3
3
|
module Selenium
|
|
4
4
|
module WebDriver
|
|
5
5
|
module Remote
|
|
6
|
+
|
|
7
|
+
# @private
|
|
6
8
|
class DefaultHttpClient
|
|
7
9
|
CONTENT_TYPE = "application/json"
|
|
8
|
-
DEFAULT_HEADERS = { "Accept" => CONTENT_TYPE }
|
|
9
|
-
|
|
10
|
-
class RetryException < StandardError; end
|
|
10
|
+
DEFAULT_HEADERS = { "Accept" => CONTENT_TYPE, "Content-Length" => "0" }
|
|
11
11
|
|
|
12
12
|
def initialize(url)
|
|
13
13
|
@server_url = url
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
def call(verb, url,
|
|
16
|
+
def call(verb, url, command_hash)
|
|
17
17
|
response = nil
|
|
18
18
|
url = @server_url.merge(url) unless url.kind_of?(URI)
|
|
19
19
|
headers = DEFAULT_HEADERS.dup
|
|
20
20
|
|
|
21
|
-
if
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
begin
|
|
28
|
-
request = Net::HTTP.const_get(verb.to_s.capitalize).new(url.path, headers)
|
|
21
|
+
if command_hash
|
|
22
|
+
payload = command_hash.to_json
|
|
23
|
+
headers["Content-Type"] = "#{CONTENT_TYPE}; charset=utf-8"
|
|
24
|
+
headers["Content-Length"] = payload.bytesize.to_s if [:post, :put].include?(verb)
|
|
29
25
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
verb, payload = :get, nil
|
|
34
|
-
url = URI.parse(res["Location"])
|
|
35
|
-
raise RetryException
|
|
36
|
-
else
|
|
37
|
-
response = create_response(res)
|
|
38
|
-
end
|
|
26
|
+
if $DEBUG
|
|
27
|
+
puts " >>> #{payload}"
|
|
28
|
+
puts " > #{headers.inspect}"
|
|
39
29
|
end
|
|
40
|
-
|
|
41
|
-
response
|
|
42
|
-
rescue RetryException
|
|
43
|
-
retry
|
|
44
30
|
end
|
|
31
|
+
|
|
32
|
+
request verb, url, headers, payload
|
|
45
33
|
end
|
|
46
34
|
|
|
47
35
|
private
|
|
@@ -51,6 +39,18 @@ module Selenium
|
|
|
51
39
|
@http ||= Net::HTTP.new @server_url.host, @server_url.port
|
|
52
40
|
end
|
|
53
41
|
|
|
42
|
+
def request(verb, url, headers, payload)
|
|
43
|
+
request = Net::HTTP.const_get(verb.to_s.capitalize).new(url.path, headers)
|
|
44
|
+
response = http.request(request, payload)
|
|
45
|
+
|
|
46
|
+
# TODO: should be checking against a maximum redirect count
|
|
47
|
+
if response.kind_of? Net::HTTPRedirection
|
|
48
|
+
request(:get, URI.parse(response['Location']), DEFAULT_HEADERS.dup, nil)
|
|
49
|
+
else
|
|
50
|
+
create_response response
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
54
|
def create_response(res)
|
|
55
55
|
puts "<- #{res.body}\n" if $DEBUG
|
|
56
56
|
if res.content_type == CONTENT_TYPE
|
|
@@ -68,4 +68,4 @@ module Selenium
|
|
|
68
68
|
end # DefaultHttpClient
|
|
69
69
|
end # Remote
|
|
70
70
|
end # WebDriver
|
|
71
|
-
end # Selenium
|
|
71
|
+
end # Selenium
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
require "patron"
|
|
2
|
+
|
|
3
|
+
module Selenium
|
|
4
|
+
module WebDriver
|
|
5
|
+
module Remote
|
|
6
|
+
|
|
7
|
+
# @private
|
|
8
|
+
class PatronHttpClient
|
|
9
|
+
CONTENT_TYPE = "application/json"
|
|
10
|
+
DEFAULT_HEADERS = { "Accept" => CONTENT_TYPE, "Content-Length" => "0" }
|
|
11
|
+
|
|
12
|
+
def initialize(url)
|
|
13
|
+
@session = Patron::Session.new
|
|
14
|
+
@session.base_url = url
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def call(verb, url, command_hash)
|
|
18
|
+
DEFAULT_HEADERS.each do |key, val|
|
|
19
|
+
@session.headers[key] = val
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
if command_hash
|
|
23
|
+
payload = command_hash.to_json
|
|
24
|
+
@session.headers['Content-Type'] = "#{CONTENT_TYPE}; charset=utf-8;"
|
|
25
|
+
@session.headers['Content-Length'] = payload.bytesize.to_s if [:post, :put].include?(verb)
|
|
26
|
+
if $DEBUG
|
|
27
|
+
puts " >>> #{payload}"
|
|
28
|
+
puts " > #{@session.headers.inspect}"
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
if [:post, :put].include?(verb)
|
|
33
|
+
create_response @session.send(verb, url, payload || '')
|
|
34
|
+
else
|
|
35
|
+
create_response @session.send(verb, url)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
def create_response(res)
|
|
42
|
+
puts "<- #{res.body}\n" if $DEBUG
|
|
43
|
+
if res.headers['Content-Type'].include? CONTENT_TYPE
|
|
44
|
+
Response.new do |r|
|
|
45
|
+
r.code = res.status.to_i
|
|
46
|
+
r.payload = JSON.parse(res.body.strip)
|
|
47
|
+
end
|
|
48
|
+
elsif res.status == '204'
|
|
49
|
+
Response.new { |r| r.code = res.code.to_i }
|
|
50
|
+
else
|
|
51
|
+
raise "Unexpected content type: #{res.headers.inspect} (#{res.status})\n#{res.body}"
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
end # PatronHttpClient
|
|
56
|
+
end # Remote
|
|
57
|
+
end # WebDriver
|
|
58
|
+
end # Selenium
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
module Selenium
|
|
2
2
|
module WebDriver
|
|
3
3
|
module Remote
|
|
4
|
+
|
|
5
|
+
# @private
|
|
4
6
|
class Response
|
|
5
7
|
|
|
6
8
|
attr_accessor :code
|
|
@@ -12,12 +14,11 @@ module Selenium
|
|
|
12
14
|
end
|
|
13
15
|
|
|
14
16
|
def error
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
end
|
|
17
|
+
Error.for_code(payload['status'])
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def error_message
|
|
21
|
+
payload['value']['message']
|
|
21
22
|
end
|
|
22
23
|
|
|
23
24
|
def [](key)
|
|
@@ -31,14 +32,11 @@ module Selenium
|
|
|
31
32
|
private
|
|
32
33
|
|
|
33
34
|
def assert_ok
|
|
34
|
-
if @code.nil? || @code
|
|
35
|
+
if @code.nil? || @code >= 400
|
|
35
36
|
if e = error()
|
|
36
|
-
raise(
|
|
37
|
-
Error.for_remote_class(e['class']),
|
|
38
|
-
e['message'] || self
|
|
39
|
-
)
|
|
37
|
+
raise(e, error_message)
|
|
40
38
|
else
|
|
41
|
-
raise ServerError, self
|
|
39
|
+
raise Error::ServerError, self
|
|
42
40
|
end
|
|
43
41
|
end
|
|
44
42
|
end
|