selenium-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.
- data/chrome/prebuilt/Win32/Release/npchromedriver.dll +0 -0
- data/chrome/prebuilt/x64/Release/npchromedriver.dll +0 -0
- data/chrome/src/extension/background.html +9 -0
- data/chrome/src/extension/background.js +933 -0
- data/chrome/src/extension/content_script.js +1286 -0
- data/chrome/src/extension/manifest-nonwin.json +15 -0
- data/chrome/src/extension/manifest-win.json +16 -0
- data/chrome/src/extension/toolstrip.html +28 -0
- data/chrome/src/extension/utils.js +196 -0
- data/chrome/src/rb/lib/selenium/webdriver/chrome.rb +8 -0
- data/chrome/src/rb/lib/selenium/webdriver/chrome/bridge.rb +324 -0
- data/chrome/src/rb/lib/selenium/webdriver/chrome/command_executor.rb +70 -0
- data/chrome/src/rb/lib/selenium/webdriver/chrome/launcher.rb +119 -0
- data/common/src/js/abstractcommandprocessor.js +161 -0
- data/common/src/js/asserts.js +296 -0
- data/common/src/js/by.js +147 -0
- data/common/src/js/command.js +274 -0
- data/common/src/js/context.js +58 -0
- data/common/src/js/extension/README +2 -0
- data/common/src/js/extension/dommessenger.js +152 -0
- data/common/src/js/factory.js +55 -0
- data/common/src/js/future.js +118 -0
- data/common/src/js/key.js +117 -0
- data/common/src/js/localcommandprocessor.js +181 -0
- data/common/src/js/logging.js +249 -0
- data/common/src/js/testrunner.js +605 -0
- data/common/src/js/timing.js +89 -0
- data/common/src/js/wait.js +199 -0
- data/common/src/js/webdriver.js +853 -0
- data/common/src/js/webelement.js +683 -0
- data/common/src/rb/lib/selenium-webdriver.rb +1 -0
- data/common/src/rb/lib/selenium/webdriver.rb +52 -0
- data/common/src/rb/lib/selenium/webdriver/bridge_helper.rb +88 -0
- data/common/src/rb/lib/selenium/webdriver/child_process.rb +85 -0
- data/common/src/rb/lib/selenium/webdriver/core_ext/dir.rb +41 -0
- data/common/src/rb/lib/selenium/webdriver/driver.rb +128 -0
- data/common/src/rb/lib/selenium/webdriver/element.rb +126 -0
- data/common/src/rb/lib/selenium/webdriver/error.rb +68 -0
- data/common/src/rb/lib/selenium/webdriver/find.rb +69 -0
- data/common/src/rb/lib/selenium/webdriver/navigation.rb +23 -0
- data/common/src/rb/lib/selenium/webdriver/options.rb +50 -0
- data/common/src/rb/lib/selenium/webdriver/platform.rb +82 -0
- data/common/src/rb/lib/selenium/webdriver/target_locator.rb +23 -0
- data/firefox/prebuilt/nsICommandProcessor.xpt +0 -0
- data/firefox/prebuilt/nsINativeEvents.xpt +0 -0
- data/firefox/prebuilt/nsIResponseHandler.xpt +0 -0
- data/firefox/src/extension/chrome.manifest +3 -0
- data/firefox/src/extension/components/context.js +37 -0
- data/firefox/src/extension/components/driver-component.js +127 -0
- data/firefox/src/extension/components/firefoxDriver.js +706 -0
- data/firefox/src/extension/components/json2.js +273 -0
- data/firefox/src/extension/components/keytest.html +554 -0
- data/firefox/src/extension/components/nsCommandProcessor.js +586 -0
- data/firefox/src/extension/components/screenshooter.js +70 -0
- data/firefox/src/extension/components/socketListener.js +185 -0
- data/firefox/src/extension/components/utils.js +1200 -0
- data/firefox/src/extension/components/webLoadingListener.js +57 -0
- data/firefox/src/extension/components/webdriverserver.js +101 -0
- data/firefox/src/extension/components/wrappedElement.js +609 -0
- data/firefox/src/extension/content/fxdriver.xul +30 -0
- data/firefox/src/extension/content/server.js +95 -0
- data/firefox/src/extension/idl/nsICommandProcessor.idl +38 -0
- data/firefox/src/extension/idl/nsIResponseHandler.idl +34 -0
- data/firefox/src/extension/install.rdf +29 -0
- data/firefox/src/rb/lib/selenium/webdriver/firefox.rb +21 -0
- data/firefox/src/rb/lib/selenium/webdriver/firefox/binary.rb +86 -0
- data/firefox/src/rb/lib/selenium/webdriver/firefox/bridge.rb +426 -0
- data/firefox/src/rb/lib/selenium/webdriver/firefox/extension_connection.rb +82 -0
- data/firefox/src/rb/lib/selenium/webdriver/firefox/launcher.rb +132 -0
- data/firefox/src/rb/lib/selenium/webdriver/firefox/profile.rb +174 -0
- data/firefox/src/rb/lib/selenium/webdriver/firefox/profiles_ini.rb +60 -0
- data/firefox/src/rb/lib/selenium/webdriver/firefox/util.rb +23 -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 +14 -0
- data/jobbie/src/rb/lib/selenium/webdriver/ie/bridge.rb +552 -0
- data/jobbie/src/rb/lib/selenium/webdriver/ie/lib.rb +94 -0
- data/jobbie/src/rb/lib/selenium/webdriver/ie/util.rb +147 -0
- data/remote/client/src/rb/lib/selenium/webdriver/remote.rb +16 -0
- data/remote/client/src/rb/lib/selenium/webdriver/remote/bridge.rb +374 -0
- data/remote/client/src/rb/lib/selenium/webdriver/remote/capabilities.rb +105 -0
- data/remote/client/src/rb/lib/selenium/webdriver/remote/commands.rb +53 -0
- data/remote/client/src/rb/lib/selenium/webdriver/remote/default_http_client.rb +71 -0
- data/remote/client/src/rb/lib/selenium/webdriver/remote/response.rb +43 -0
- data/remote/client/src/rb/lib/selenium/webdriver/remote/server_error.rb +32 -0
- metadata +182 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
module Selenium::WebDriver::IE
|
|
2
|
+
module Lib
|
|
3
|
+
extend FFI::Library
|
|
4
|
+
|
|
5
|
+
ffi_lib WebDriver::IE::DLL
|
|
6
|
+
|
|
7
|
+
attach_function :wdAddBooleanScriptArg, [:pointer, :int ], :int
|
|
8
|
+
attach_function :wdAddCookie, [:pointer, :pointer ], :int
|
|
9
|
+
attach_function :wdAddDoubleScriptArg, [:pointer, :double ], :int
|
|
10
|
+
attach_function :wdAddElementScriptArg, [:pointer, :pointer ], :int
|
|
11
|
+
attach_function :wdAddNumberScriptArg, [:pointer, :long ], :int
|
|
12
|
+
attach_function :wdAddStringScriptArg, [:pointer, :pointer ], :int
|
|
13
|
+
attach_function :wdcGetElementAtIndex, [:pointer, :int, :pointer ], :int
|
|
14
|
+
attach_function :wdcGetElementCollectionLength, [:pointer, :pointer ], :int
|
|
15
|
+
attach_function :wdcGetStringAtIndex, [:pointer, :int, :pointer ], :int
|
|
16
|
+
attach_function :wdcGetStringCollectionLength, [:pointer, :pointer ], :int
|
|
17
|
+
attach_function :wdClose, [:pointer ], :int
|
|
18
|
+
attach_function :wdCopyString, [:pointer, :int, :pointer ], :int
|
|
19
|
+
attach_function :wdeClear, [:pointer ], :int
|
|
20
|
+
attach_function :wdeClick, [:pointer ], :int
|
|
21
|
+
attach_function :wdeGetAttribute, [:pointer, :pointer, :pointer ], :int
|
|
22
|
+
attach_function :wdeGetDetailsOnceScrolledOnToScreen, [:pointer, :pointer, :pointer, :pointer, :pointer, :pointer ], :int
|
|
23
|
+
attach_function :wdeGetLocation, [:pointer, :pointer, :pointer ], :int
|
|
24
|
+
attach_function :wdeGetSize, [:pointer, :pointer, :pointer ], :int
|
|
25
|
+
attach_function :wdeGetTagName, [:pointer, :pointer ], :int
|
|
26
|
+
attach_function :wdeGetText, [:pointer, :pointer ], :int
|
|
27
|
+
attach_function :wdeGetValueOfCssProperty, [:pointer, :pointer, :pointer ], :int
|
|
28
|
+
attach_function :wdeIsDisplayed, [:pointer, :pointer ], :int
|
|
29
|
+
attach_function :wdeIsEnabled, [:pointer, :pointer ], :int
|
|
30
|
+
attach_function :wdeIsSelected, [:pointer, :pointer ], :int
|
|
31
|
+
attach_function :wdeMouseDownAt, [:pointer, :long, :long ], :int #hwnd, nativelong
|
|
32
|
+
attach_function :wdeMouseMoveTo, [:pointer, :long, :long, :long, :long, :long ], :int # hwnd, 5x nativelong
|
|
33
|
+
attach_function :wdeMouseUpAt, [:pointer, :long, :long ], :int # hwnd
|
|
34
|
+
attach_function :wdeSendKeys, [:pointer, :pointer ], :int
|
|
35
|
+
attach_function :wdeSetSelected, [:pointer ], :int
|
|
36
|
+
attach_function :wdeSubmit, [:pointer ], :int
|
|
37
|
+
attach_function :wdeToggle, [:pointer, :pointer ], :int
|
|
38
|
+
attach_function :wdExecuteScript, [:pointer, :pointer, :pointer, :pointer ], :int
|
|
39
|
+
attach_function :wdeFreeElement, [:pointer ], :int
|
|
40
|
+
attach_function :wdFindElementByClassName, [:pointer, :pointer, :pointer, :pointer ], :int
|
|
41
|
+
attach_function :wdFindElementById, [:pointer, :pointer, :pointer, :pointer ], :int
|
|
42
|
+
attach_function :wdFindElementByLinkText, [:pointer, :pointer, :pointer, :pointer ], :int
|
|
43
|
+
attach_function :wdFindElementByName, [:pointer, :pointer, :pointer, :pointer ], :int
|
|
44
|
+
attach_function :wdFindElementByPartialLinkText, [:pointer, :pointer, :pointer, :pointer ], :int
|
|
45
|
+
attach_function :wdFindElementByTagName, [:pointer, :pointer, :pointer, :pointer ], :int
|
|
46
|
+
attach_function :wdFindElementByXPath, [:pointer, :pointer, :pointer, :pointer ], :int
|
|
47
|
+
attach_function :wdFindElementsByClassName, [:pointer, :pointer, :pointer, :pointer ], :int
|
|
48
|
+
attach_function :wdFindElementsById, [:pointer, :pointer, :pointer, :pointer ], :int
|
|
49
|
+
attach_function :wdFindElementsByLinkText, [:pointer, :pointer, :pointer, :pointer ], :int
|
|
50
|
+
attach_function :wdFindElementsByName, [:pointer, :pointer, :pointer, :pointer ], :int
|
|
51
|
+
attach_function :wdFindElementsByPartialLinkText, [:pointer, :pointer, :pointer, :pointer ], :int
|
|
52
|
+
attach_function :wdFindElementsByTagName, [:pointer, :pointer, :pointer, :pointer ], :int
|
|
53
|
+
attach_function :wdFindElementsByXPath, [:pointer, :pointer, :pointer, :pointer ], :int
|
|
54
|
+
attach_function :wdFreeDriver, [:pointer ], :int
|
|
55
|
+
attach_function :wdFreeElementCollection, [:pointer, :int ], :int
|
|
56
|
+
attach_function :wdFreeScriptArgs, [:pointer ], :int
|
|
57
|
+
attach_function :wdFreeScriptResult, [:pointer ], :int
|
|
58
|
+
attach_function :wdFreeString, [:pointer ], :int
|
|
59
|
+
attach_function :wdFreeStringCollection, [:pointer ], :int
|
|
60
|
+
attach_function :wdGet, [:pointer, :pointer ], :int
|
|
61
|
+
attach_function :wdGetAllWindowHandles, [:pointer, :pointer ], :int
|
|
62
|
+
attach_function :wdGetBooleanScriptResult, [:pointer, :pointer ], :int
|
|
63
|
+
attach_function :wdGetCookies, [:pointer, :pointer ], :int
|
|
64
|
+
attach_function :wdGetCurrentUrl, [:pointer, :pointer ], :int
|
|
65
|
+
attach_function :wdGetCurrentWindowHandle, [:pointer, :pointer ], :int
|
|
66
|
+
attach_function :wdGetDoubleScriptResult, [:pointer, :pointer ], :int
|
|
67
|
+
attach_function :wdGetElementScriptResult, [:pointer, :pointer, :pointer ], :int
|
|
68
|
+
attach_function :wdGetNumberScriptResult, [:pointer, :pointer ], :int
|
|
69
|
+
attach_function :wdGetPageSource, [:pointer, :pointer ], :int
|
|
70
|
+
attach_function :wdGetScriptResultType, [:pointer, :pointer ], :int
|
|
71
|
+
attach_function :wdGetStringScriptResult, [:pointer, :pointer ], :int
|
|
72
|
+
attach_function :wdGetTitle, [:pointer, :pointer ], :int
|
|
73
|
+
attach_function :wdGetVisible, [:pointer, :pointer ], :int
|
|
74
|
+
attach_function :wdGoBack, [:pointer ], :int
|
|
75
|
+
attach_function :wdGoForward, [:pointer ], :int
|
|
76
|
+
attach_function :wdNewDriverInstance, [:pointer ], :int
|
|
77
|
+
attach_function :wdNewScriptArgs, [:pointer, :int ], :int
|
|
78
|
+
attach_function :wdSetVisible, [:pointer, :int ], :int
|
|
79
|
+
attach_function :wdStringLength, [:pointer, :pointer ], :int
|
|
80
|
+
attach_function :wdSwitchToActiveElement, [:pointer, :pointer ], :int
|
|
81
|
+
attach_function :wdSwitchToFrame, [:pointer, :pointer ], :int
|
|
82
|
+
attach_function :wdSwitchToWindow, [:pointer, :pointer ], :int
|
|
83
|
+
attach_function :wdWaitForLoadToComplete, [:pointer ], :int
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
module Kernel32
|
|
87
|
+
extend FFI::Library
|
|
88
|
+
|
|
89
|
+
ffi_lib "kernel32.dll"
|
|
90
|
+
|
|
91
|
+
attach_function :MultiByteToWideChar, [:int, :long, :pointer, :int, :pointer, :int ], :int
|
|
92
|
+
attach_function :WideCharToMultiByte, [:int, :long, :pointer, :int, :pointer, :int, :pointer, :pointer], :int
|
|
93
|
+
end
|
|
94
|
+
end # WebDriver::IE
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
module Selenium
|
|
2
|
+
module WebDriver
|
|
3
|
+
module IE
|
|
4
|
+
module Util
|
|
5
|
+
CP_ACP = 0
|
|
6
|
+
CP_OEMCP = 1
|
|
7
|
+
CP_MACCP = 2
|
|
8
|
+
CP_THREAD_ACP = 3
|
|
9
|
+
CP_SYMBOL = 42
|
|
10
|
+
CP_UTF7 = 65000
|
|
11
|
+
CP_UTF8 = 65001
|
|
12
|
+
|
|
13
|
+
def string_array_from(raw_strings)
|
|
14
|
+
strings_ptr = raw_strings.get_pointer(0)
|
|
15
|
+
|
|
16
|
+
length_ptr = FFI::MemoryPointer.new :int
|
|
17
|
+
result = Lib.wdcGetStringCollectionLength(strings_ptr, length_ptr)
|
|
18
|
+
|
|
19
|
+
if result != 0
|
|
20
|
+
raise "Cannot extract strings from collection, error code: #{result.inspect}"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
arr = []
|
|
24
|
+
|
|
25
|
+
length_ptr.get_int(0).times do |idx|
|
|
26
|
+
str_ptr_ref = FFI::MemoryPointer.new :pointer
|
|
27
|
+
result = Lib.wdcGetStringAtIndex(strings_ptr, idx, str_ptr_ref)
|
|
28
|
+
|
|
29
|
+
if result != 0
|
|
30
|
+
raise "Unable to get string at index: #{idx}, error: #{result}"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
arr << extract_string_from(str_ptr_ref)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
arr
|
|
37
|
+
ensure
|
|
38
|
+
Lib.wdFreeStringCollection(strings_ptr)
|
|
39
|
+
raw_strings.free
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def create_element(&blk)
|
|
43
|
+
element_ptr_ref = FFI::MemoryPointer.new :pointer
|
|
44
|
+
yield element_ptr_ref
|
|
45
|
+
Element.new(self, element_ptr_ref.get_pointer(0))
|
|
46
|
+
ensure
|
|
47
|
+
element_ptr_ref.free
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def create_element_collection(&blk)
|
|
51
|
+
elements_ptr_ref = FFI::MemoryPointer.new :pointer
|
|
52
|
+
yield elements_ptr_ref
|
|
53
|
+
|
|
54
|
+
extract_elements_from elements_ptr_ref
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def create_string(&blk)
|
|
58
|
+
wrapper = FFI::MemoryPointer.new :pointer
|
|
59
|
+
yield wrapper
|
|
60
|
+
|
|
61
|
+
extract_string_from wrapper
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def extract_string_from(string_ptr_ref)
|
|
65
|
+
string_ptr = string_ptr_ref.get_pointer(0)
|
|
66
|
+
|
|
67
|
+
length_ptr = FFI::MemoryPointer.new :int
|
|
68
|
+
|
|
69
|
+
if Lib.wdStringLength(string_ptr, length_ptr) != 0
|
|
70
|
+
raise "Cannot determine length of string"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
length = length_ptr.get_int(0)
|
|
74
|
+
raw_string = wstring_ptr(" "*length)
|
|
75
|
+
|
|
76
|
+
if Lib.wdCopyString(string_ptr, length, raw_string) != 0
|
|
77
|
+
raise "Cannot copy string from native data to Ruby string"
|
|
78
|
+
end
|
|
79
|
+
#
|
|
80
|
+
wstring_to_bytestring raw_string
|
|
81
|
+
ensure
|
|
82
|
+
Lib.wdFreeString(string_ptr)
|
|
83
|
+
string_ptr_ref.free
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def extract_elements_from(elements_ptr_ref)
|
|
87
|
+
elements_ptr = elements_ptr_ref.get_pointer(0)
|
|
88
|
+
length_ptr = FFI::MemoryPointer.new :int
|
|
89
|
+
|
|
90
|
+
check_error_code Lib.wdcGetElementCollectionLength(elements_ptr, length_ptr),
|
|
91
|
+
"Cannot extract elements from collection"
|
|
92
|
+
|
|
93
|
+
arr = []
|
|
94
|
+
|
|
95
|
+
length_ptr.get_int(0).times do |idx|
|
|
96
|
+
arr << create_element do |ptr|
|
|
97
|
+
result = Lib.wdcGetElementAtIndex(elements_ptr, idx, ptr)
|
|
98
|
+
|
|
99
|
+
if e = WebDriver::Error.for_code(result)
|
|
100
|
+
Lib.wdFreeElementCollection(elements_ptr, 1)
|
|
101
|
+
raise e, "Unable to create element from collection at index #{idx} (#{result})"
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
Lib.wdFreeElementCollection(elements_ptr, 0)
|
|
107
|
+
|
|
108
|
+
arr
|
|
109
|
+
ensure
|
|
110
|
+
elements_ptr_ref.free
|
|
111
|
+
length_ptr.free
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def wstring_ptr(str)
|
|
116
|
+
str = str.to_s
|
|
117
|
+
size = Kernel32.MultiByteToWideChar(CP_UTF8, 0, str, -1, nil, 0)
|
|
118
|
+
|
|
119
|
+
unless size > 0
|
|
120
|
+
raise "Could not convert #{str.inspect} to wchar ptr"
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
buf = FFI::MemoryPointer.new :pointer, size
|
|
124
|
+
Kernel32.MultiByteToWideChar(CP_UTF8, 0, str, -1, buf, size)
|
|
125
|
+
|
|
126
|
+
buf
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def wstring_to_bytestring(wstring)
|
|
130
|
+
size = Kernel32.WideCharToMultiByte(CP_UTF8, 0, wstring, -1, nil, 0, nil, nil)
|
|
131
|
+
|
|
132
|
+
unless size > 0
|
|
133
|
+
raise "Could not convert wstring pointer to bytestring"
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
buf = FFI::MemoryPointer.new :pointer, size
|
|
137
|
+
Kernel32.WideCharToMultiByte(CP_UTF8, 0, wstring, -1, buf, size, nil, nil )
|
|
138
|
+
|
|
139
|
+
buf.get_bytes(0, size - 1)
|
|
140
|
+
ensure
|
|
141
|
+
buf.free if buf
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
end # Util
|
|
145
|
+
end # IE
|
|
146
|
+
end # WebDriver
|
|
147
|
+
end # Selenium
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require "selenium/webdriver/remote/capabilities"
|
|
2
|
+
require "selenium/webdriver/remote/default_http_client"
|
|
3
|
+
require "selenium/webdriver/remote/bridge"
|
|
4
|
+
require "selenium/webdriver/remote/server_error"
|
|
5
|
+
require "selenium/webdriver/remote/response"
|
|
6
|
+
require "selenium/webdriver/remote/commands"
|
|
7
|
+
|
|
8
|
+
module Selenium
|
|
9
|
+
module WebDriver
|
|
10
|
+
module Remote
|
|
11
|
+
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
require "uri"
|
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
module Selenium
|
|
2
|
+
module WebDriver
|
|
3
|
+
module Remote
|
|
4
|
+
DEBUG = $VERBOSE == true
|
|
5
|
+
|
|
6
|
+
COMMANDS = {}
|
|
7
|
+
|
|
8
|
+
#
|
|
9
|
+
# Low level bridge to the remote server, through which the rest of the API works.
|
|
10
|
+
#
|
|
11
|
+
# @api private
|
|
12
|
+
#
|
|
13
|
+
|
|
14
|
+
class Bridge
|
|
15
|
+
include Find
|
|
16
|
+
include BridgeHelper
|
|
17
|
+
|
|
18
|
+
DEFAULT_OPTIONS = {
|
|
19
|
+
:server_url => "http://localhost:7055/",
|
|
20
|
+
:http_client => DefaultHttpClient,
|
|
21
|
+
:desired_capabilities => Capabilities.firefox
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
#
|
|
25
|
+
# Defines a wrapper method for a command, which ultimately calls #execute.
|
|
26
|
+
#
|
|
27
|
+
# @param name [Symbol]
|
|
28
|
+
# name of the resulting method
|
|
29
|
+
# @param url [String]
|
|
30
|
+
# a URL template, which can include some arguments, much like the definitions on the server.
|
|
31
|
+
# the :session_id and :context parameters are implicitly handled, but the remainder will become
|
|
32
|
+
# required method arguments.
|
|
33
|
+
# e.g., "session/:session_id/:context/element/:id/text" will define a method that takes id
|
|
34
|
+
# as it's first argument.
|
|
35
|
+
# @param verb [Symbol]
|
|
36
|
+
# the appropriate http verb, such as :get, :post, or :delete
|
|
37
|
+
#
|
|
38
|
+
|
|
39
|
+
def self.command(name, verb, url)
|
|
40
|
+
COMMANDS[name] = [verb, url.freeze]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
attr_accessor :context, :http
|
|
44
|
+
attr_reader :capabilities
|
|
45
|
+
|
|
46
|
+
#
|
|
47
|
+
# Initializes the bridge with the given server URL.
|
|
48
|
+
#
|
|
49
|
+
# @param server_url [String] base URL for all commands. FIXME: Note that a trailing '/' is very important!
|
|
50
|
+
#
|
|
51
|
+
|
|
52
|
+
def initialize(opts = {})
|
|
53
|
+
opts = DEFAULT_OPTIONS.merge(opts)
|
|
54
|
+
@context = "context"
|
|
55
|
+
@http = opts[:http_client].new URI.parse(opts[:server_url])
|
|
56
|
+
@capabilities = create_session opts[:desired_capabilities]
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def browser
|
|
60
|
+
@browser ||= @capabilities.browser_name.gsub(" ", "_").to_sym
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
#
|
|
64
|
+
# Returns the current session ID.
|
|
65
|
+
#
|
|
66
|
+
|
|
67
|
+
def session_id
|
|
68
|
+
@session_id || raise(StandardError, "no current session exists")
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def create_session(desired_capabilities)
|
|
73
|
+
resp = raw_execute :newSession, {}, desired_capabilities
|
|
74
|
+
@session_id = resp['sessionId'] || raise('no sessionId in returned payload')
|
|
75
|
+
Capabilities.json_create resp['value']
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def get(url)
|
|
79
|
+
execute :get, {}, url
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def goBack
|
|
83
|
+
execute :goBack
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def goForward
|
|
87
|
+
execute :goForward
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def getCurrentUrl
|
|
91
|
+
execute :getCurrentUrl
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def getTitle
|
|
95
|
+
execute :getTitle
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def getPageSource
|
|
99
|
+
execute :getPageSource
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def getVisible
|
|
103
|
+
execute :getVisible
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def setVisible(bool)
|
|
107
|
+
execute :setVisible, {}, bool
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def switchToWindow(name)
|
|
111
|
+
execute :switchToWindow, :name => name
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def switchToFrame(id)
|
|
115
|
+
execute :switchToFrame, :id => id
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def quit
|
|
119
|
+
execute :quit
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def close
|
|
123
|
+
execute :close
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def refresh
|
|
127
|
+
execute :refresh
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def getWindowHandles
|
|
131
|
+
execute :getWindowHandles
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def getCurrentWindowHandle
|
|
135
|
+
execute :getCurrentWindowHandle
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def setSpeed(value)
|
|
139
|
+
execute :setSpeed, {}, value
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def getSpeed
|
|
143
|
+
execute :getSpeed
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def executeScript(script, *args)
|
|
147
|
+
raise UnsupportedOperationError, "underlying webdriver instace does not support javascript" unless capabilities.javascript?
|
|
148
|
+
|
|
149
|
+
typed_args = args.map { |arg| wrap_script_argument(arg) }
|
|
150
|
+
response = raw_execute :executeScript, {}, script, typed_args
|
|
151
|
+
|
|
152
|
+
unwrap_script_argument response['value']
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def addCookie(cookie)
|
|
156
|
+
execute :addCookie, {}, cookie
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def deleteCookie(name)
|
|
160
|
+
execute :deleteCookie, :name => name
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def getAllCookies
|
|
164
|
+
execute :getAllCookies
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def deleteAllCookies
|
|
168
|
+
execute :deleteAllCookies
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def findElementByClassName(parent, class_name)
|
|
172
|
+
find_element_by 'class name', class_name, parent
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def findElementsByClassName(parent, class_name)
|
|
176
|
+
find_elements_by 'class name', class_name, parent
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def findElementById(parent, id)
|
|
180
|
+
find_element_by 'id', id, parent
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def findElementsById(parent, id)
|
|
184
|
+
find_elements_by 'id', id, parent
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def findElementByLinkText(parent, link_text)
|
|
188
|
+
find_element_by 'link text', link_text, parent
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def findElementsByLinkText(parent, link_text)
|
|
192
|
+
find_elements_by 'link text', link_text, parent
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def findElementByPartialLinkText(parent, link_text)
|
|
196
|
+
find_element_by 'partial link text', link_text, parent
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def findElementsByPartialLinkText(parent, link_text)
|
|
200
|
+
find_elements_by 'partial link text', link_text, parent
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def findElementByName(parent, name)
|
|
204
|
+
find_element_by 'name', name, parent
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def findElementsByName(parent, name)
|
|
208
|
+
find_elements_by 'name', name, parent
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def findElementByTagName(parent, tag_name)
|
|
212
|
+
find_element_by 'tag name', tag_name, parent
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def findElementsByTagName(parent, tag_name)
|
|
216
|
+
find_elements_by 'tag name', tag_name, parent
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def findElementByXpath(parent, xpath)
|
|
220
|
+
find_element_by 'xpath', xpath, parent
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def findElementsByXpath(parent, xpath)
|
|
224
|
+
find_elements_by 'xpath', xpath, parent
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
#
|
|
229
|
+
# Element functions
|
|
230
|
+
#
|
|
231
|
+
|
|
232
|
+
def clickElement(element)
|
|
233
|
+
execute :clickElement, :id => element
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def getElementTagName(element)
|
|
237
|
+
execute :getElementTagName, :id => element
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def getElementAttribute(element, name)
|
|
241
|
+
execute :getElementAttribute, :id => element, :name => name
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def getElementValue(element)
|
|
245
|
+
execute :getElementValue, :id => element
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def getElementText(element)
|
|
249
|
+
execute :getElementText, :id => element
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def getElementLocation(element)
|
|
253
|
+
data = execute :getElementLocation, :id => element
|
|
254
|
+
|
|
255
|
+
Point.new data['x'], data['y']
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def getElementSize(element)
|
|
259
|
+
execute :getElementSize, :id => element
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def sendKeysToElement(element, string)
|
|
263
|
+
execute :sendKeysToElement, {:id => element}, {:value => string.split(//u)}
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
def clearElement(element)
|
|
267
|
+
execute :clearElement, :id => element
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
def isElementEnabled(element)
|
|
271
|
+
execute :isElementEnabled, :id => element
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
def isElementSelected(element)
|
|
275
|
+
execute :isElementSelected, :id => element
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
def isElementDisplayed(element)
|
|
279
|
+
execute :isElementDisplayed, :id => element
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
def submitElement(element)
|
|
283
|
+
execute :submitElement, :id => element
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
def toggleElement(element)
|
|
287
|
+
execute :toggleElement, :id => element
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
def setElementSelected(element)
|
|
291
|
+
execute :setElementSelected, :id => element
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
def getElementValueOfCssProperty(element, prop)
|
|
295
|
+
execute :getElementValueOfCssProperty, :id => element, :property_name => prop
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
def getActiveElement
|
|
299
|
+
Element.new self, element_id_from(execute(:getActiveElement))
|
|
300
|
+
end
|
|
301
|
+
alias_method :switchToActiveElement, :getActiveElement
|
|
302
|
+
|
|
303
|
+
def hoverOverElement
|
|
304
|
+
execute :hoverOverElement, :id => element
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
def dragElement(element, rigth_by, down_by)
|
|
308
|
+
# TODO: why is element sent twice in the payload?
|
|
309
|
+
execute :dragElement, {:id => element}, element, rigth_by, down_by
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
private
|
|
313
|
+
|
|
314
|
+
def find_element_by(how, what, parent = nil)
|
|
315
|
+
if parent
|
|
316
|
+
# TODO: why is how sent twice in the payload?
|
|
317
|
+
id = execute :findChildElement, {:id => parent, :using => how}, {:using => how, :value => what}
|
|
318
|
+
else
|
|
319
|
+
id = execute :findElement, {}, how, what
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
Element.new self, element_id_from(id)
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
def find_elements_by(how, what, parent = nil)
|
|
326
|
+
if parent
|
|
327
|
+
# TODO: why is how sent twice in the payload?
|
|
328
|
+
ids = execute :findChildElements, {:id => parent, :using => how}, {:using => how, :value => what}
|
|
329
|
+
else
|
|
330
|
+
ids = execute :findElements, {}, how, what
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
ids.map { |id| Element.new self, element_id_from(id) }
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
#
|
|
338
|
+
# executes a command on the remote server via the REST / JSON API.
|
|
339
|
+
#
|
|
340
|
+
#
|
|
341
|
+
# Returns the 'value' of the returned payload
|
|
342
|
+
#
|
|
343
|
+
|
|
344
|
+
def execute(*args)
|
|
345
|
+
raw_execute(*args)['value']
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
#
|
|
349
|
+
# executes a command on the remote server via the REST / JSON API.
|
|
350
|
+
#
|
|
351
|
+
# Returns a WebDriver::Remote::Response instance
|
|
352
|
+
#
|
|
353
|
+
|
|
354
|
+
def raw_execute(command, opts = {}, *args)
|
|
355
|
+
verb, path = COMMANDS[command] || raise("Unknown command #{command.inspect}")
|
|
356
|
+
path = path.dup
|
|
357
|
+
|
|
358
|
+
path[':session_id'] = @session_id if path.include?(":session_id")
|
|
359
|
+
path[':context'] = @context if path.include?(":context")
|
|
360
|
+
|
|
361
|
+
begin
|
|
362
|
+
opts.each { |key, value| path[key.inspect] = value }
|
|
363
|
+
rescue IndexError
|
|
364
|
+
raise ArgumentError, "#{opts.inspect} invalid for #{command.inspect}"
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
puts "-> #{verb.to_s.upcase} #{path}" if DEBUG
|
|
368
|
+
http.call verb, path, *args
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
end # Bridge
|
|
372
|
+
end # Remote
|
|
373
|
+
end # WebDriver
|
|
374
|
+
end # Selenium
|