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,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "WebDriver",
|
|
3
|
+
"version": "0.3",
|
|
4
|
+
"description": "WebDriver extension for Chrome",
|
|
5
|
+
"toolstrips": ["toolstrip.html"],
|
|
6
|
+
"background_page": "background.html",
|
|
7
|
+
"content_scripts": [
|
|
8
|
+
{
|
|
9
|
+
"matches": ["http://*/*", "https://*/*", "file:///*"],
|
|
10
|
+
"js": ["utils.js", "content_script.js"],
|
|
11
|
+
"run_at": "document_start"
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
"permissions": ["http://*/*", "tabs"]
|
|
15
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "WebDriver",
|
|
3
|
+
"version": "0.2",
|
|
4
|
+
"description": "WebDriver extension for Chrome",
|
|
5
|
+
"toolstrips": ["toolstrip.html"],
|
|
6
|
+
"background_page": "background.html",
|
|
7
|
+
"content_scripts": [
|
|
8
|
+
{
|
|
9
|
+
"matches": ["http://*/*", "https://*/*", "file:///*"],
|
|
10
|
+
"js": ["utils.js", "content_script.js"],
|
|
11
|
+
"run_at": "document_start"
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
"plugins": [{"path": "npchromedriver.dll", "public": true}],
|
|
15
|
+
"permissions": ["http://*/*", "tabs"]
|
|
16
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<html>
|
|
2
|
+
<head>
|
|
3
|
+
<script type="text/javascript">
|
|
4
|
+
function setWebdriverToolstripBusy() {
|
|
5
|
+
document.getElementById("toolstripText").className = "toolstripTextBusy";
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function setWebdriverToolstripFree() {
|
|
9
|
+
document.getElementById("toolstripText").className = "toolstripTextFree";
|
|
10
|
+
}
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<style type="text/css">
|
|
14
|
+
.toolstripTextBusy {
|
|
15
|
+
color: red;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.toolstripTextFree {
|
|
19
|
+
color: black;
|
|
20
|
+
}
|
|
21
|
+
</style>
|
|
22
|
+
</head>
|
|
23
|
+
<body>
|
|
24
|
+
<div>
|
|
25
|
+
<span id="toolstripText" class="toolstripTextFree">WebDriver</span>
|
|
26
|
+
</div>
|
|
27
|
+
</body>
|
|
28
|
+
</html>
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
//Very cut-down and slightly modified (generally to remove context) from
|
|
2
|
+
//$WEBDRIVER_HOME/firefox/src/extension/components/utils.js
|
|
3
|
+
|
|
4
|
+
function Utils() {
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function getTextFromNode(node, toReturn, textSoFar, isPreformatted) {
|
|
8
|
+
if (node['tagName'] && node.tagName == "SCRIPT") {
|
|
9
|
+
return [toReturn, textSoFar];
|
|
10
|
+
} else if (node['tagName'] && node.tagName == "TITLE") {
|
|
11
|
+
return [textSoFar + node.text, ""];
|
|
12
|
+
}
|
|
13
|
+
var children = node.childNodes;
|
|
14
|
+
|
|
15
|
+
for (var i = 0; i < children.length; i++) {
|
|
16
|
+
var child = children[i];
|
|
17
|
+
|
|
18
|
+
// Do we need to collapse the text so far?
|
|
19
|
+
if (child["tagName"] && child.tagName == "PRE") {
|
|
20
|
+
toReturn += collapseWhitespace(textSoFar);
|
|
21
|
+
textSoFar = "";
|
|
22
|
+
var bits = getTextFromNode(child, toReturn, "", true);
|
|
23
|
+
toReturn += bits[1];
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Or is this just plain text?
|
|
28
|
+
if (child.nodeName == "#text") {
|
|
29
|
+
if (Utils.isDisplayed(child)) {
|
|
30
|
+
var textToAdd = child.nodeValue;
|
|
31
|
+
textToAdd = textToAdd.replace(new RegExp(String.fromCharCode(160), "gm"), " ");
|
|
32
|
+
textSoFar += textToAdd;
|
|
33
|
+
}
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Treat as another child node.
|
|
38
|
+
var bits = getTextFromNode(child, toReturn, textSoFar, false);
|
|
39
|
+
toReturn = bits[0];
|
|
40
|
+
textSoFar = bits[1];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (isBlockLevel(node)) {
|
|
44
|
+
if (node["tagName"] && node.tagName != "PRE") {
|
|
45
|
+
toReturn += collapseWhitespace(textSoFar) + "\n";
|
|
46
|
+
textSoFar = "";
|
|
47
|
+
} else {
|
|
48
|
+
toReturn += "\n";
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return [toReturn, textSoFar];
|
|
52
|
+
}
|
|
53
|
+
;
|
|
54
|
+
|
|
55
|
+
function isBlockLevel(node) {
|
|
56
|
+
if (node["tagName"] && node.tagName == "BR")
|
|
57
|
+
return true;
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
// Should we think about getting hold of the current document?
|
|
61
|
+
return "block" == Utils.getStyleProperty(node, "display");
|
|
62
|
+
} catch (e) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
Utils.isInHead = function(element) {
|
|
68
|
+
while (element) {
|
|
69
|
+
if (element.tagName && element.tagName.toLowerCase() == "head") {
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
element = element.parentNode;
|
|
74
|
+
} catch (e) {
|
|
75
|
+
// Fine. the DOM has dispeared from underneath us
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return false;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
Utils.isDisplayed = function(element) {
|
|
84
|
+
// Ensure that we're dealing with an element.
|
|
85
|
+
var el = element;
|
|
86
|
+
while (el.nodeType != 1 && !(el.nodeType >= 9 && el.nodeType <= 11)) {
|
|
87
|
+
el = el.parentNode;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Hidden input elements are, by definition, never displayed
|
|
91
|
+
if (el.tagName == "input" && el.type == "hidden") {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
var visibility = Utils.getStyleProperty(el, "visibility");
|
|
96
|
+
|
|
97
|
+
var _isDisplayed = function(e) {
|
|
98
|
+
var display = e.ownerDocument.defaultView.getComputedStyle(e, null).getPropertyValue("display");
|
|
99
|
+
if (display == "none") return display;
|
|
100
|
+
if (e && e.parentNode && e.parentNode.style) {
|
|
101
|
+
return _isDisplayed(e.parentNode);
|
|
102
|
+
}
|
|
103
|
+
return undefined;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
var displayed = _isDisplayed(el);
|
|
107
|
+
|
|
108
|
+
if (element.scrollIntoView && element.getBoundingClientRect &&
|
|
109
|
+
element.tagName.toLowerCase() != "option") {
|
|
110
|
+
//Option tags have 0-dimension bounding rects so ignore them
|
|
111
|
+
element.scrollIntoView(true);
|
|
112
|
+
var clientRect = element.getBoundingClientRect();
|
|
113
|
+
if (clientRect.width == 0 || clientRect.height == 0) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return displayed != "none" && visibility != "hidden";
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
Utils.getStyleProperty = function(node, propertyName) {
|
|
122
|
+
if (!node)
|
|
123
|
+
return undefined;
|
|
124
|
+
|
|
125
|
+
var value = node.ownerDocument.defaultView.getComputedStyle(node, null).getPropertyValue(propertyName);
|
|
126
|
+
|
|
127
|
+
// Convert colours to hex if possible
|
|
128
|
+
var raw = /rgb\((\d{1,3}),\s(\d{1,3}),\s(\d{1,3})\)/.exec(value);
|
|
129
|
+
if (raw) {
|
|
130
|
+
var temp = value.substr(0, raw.index);
|
|
131
|
+
|
|
132
|
+
var hex = "#";
|
|
133
|
+
for (var i = 1; i <= 3; i++) {
|
|
134
|
+
var colour = (raw[i] - 0).toString(16);
|
|
135
|
+
if (colour.length == 1)
|
|
136
|
+
colour = "0" + colour;
|
|
137
|
+
hex += colour
|
|
138
|
+
}
|
|
139
|
+
hex = hex.toLowerCase();
|
|
140
|
+
value = temp + hex + value.substr(raw.index + raw[0].length);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (value == "inherit" && element.parentNode.style) {
|
|
144
|
+
value = Utils.getStyleProperty(node.parentNode, propertyName);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return value;
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
function collapseWhitespace(textSoFar) {
|
|
151
|
+
return textSoFar.replace(/\s+/g, " ");
|
|
152
|
+
}
|
|
153
|
+
;
|
|
154
|
+
|
|
155
|
+
function getPreformattedText(node) {
|
|
156
|
+
var textToAdd = "";
|
|
157
|
+
return getTextFromNode(node, "", textToAdd, true)[1];
|
|
158
|
+
}
|
|
159
|
+
;
|
|
160
|
+
|
|
161
|
+
function isWhiteSpace(character) {
|
|
162
|
+
return character == '\n' || character == ' ' || character == '\t' || character == '\r';
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
Utils.getText = function(element) {
|
|
166
|
+
var bits = getTextFromNode(element, "", "", element.tagName == "PRE");
|
|
167
|
+
var text = bits[0] + collapseWhitespace(bits[1]);
|
|
168
|
+
var start = 0;
|
|
169
|
+
while (start < text.length && isWhiteSpace(text[start])) {
|
|
170
|
+
++start;
|
|
171
|
+
}
|
|
172
|
+
var end = text.length;
|
|
173
|
+
while (end > start && isWhiteSpace(text[end - 1])) {
|
|
174
|
+
--end;
|
|
175
|
+
}
|
|
176
|
+
return text.slice(start, end);
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
Utils.fireHtmlEvent = function(element, eventName) {
|
|
180
|
+
var e = document.createEvent("HTMLEvents");
|
|
181
|
+
e.initEvent(eventName, true, true);
|
|
182
|
+
element.dispatchEvent(e);
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
Utils.fireMouseEventOn = function(element, eventName) {
|
|
187
|
+
Utils.triggerMouseEvent(element, eventName, 0, 0);
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
Utils.triggerMouseEvent = function(element, eventType, clientX, clientY) {
|
|
191
|
+
var event = element.ownerDocument.createEvent("MouseEvents");
|
|
192
|
+
var view = element.ownerDocument.defaultView;
|
|
193
|
+
|
|
194
|
+
event.initMouseEvent(eventType, true, true, view, 1, 0, 0, clientX, clientY, false, false, false, false, 0, element);
|
|
195
|
+
element.dispatchEvent(event);
|
|
196
|
+
};
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
module Selenium
|
|
2
|
+
module WebDriver
|
|
3
|
+
module Chrome
|
|
4
|
+
class Bridge
|
|
5
|
+
include BridgeHelper
|
|
6
|
+
|
|
7
|
+
def initialize
|
|
8
|
+
@executor = CommandExecutor.new
|
|
9
|
+
|
|
10
|
+
@launcher = Launcher.launcher
|
|
11
|
+
@launcher.launch
|
|
12
|
+
# TODO: @launcher.kill
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def browser
|
|
16
|
+
:chrome
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def get(url)
|
|
20
|
+
execute :request => 'get',
|
|
21
|
+
:url => url
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def goBack
|
|
25
|
+
execute :request => 'goBack'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def goForward
|
|
29
|
+
execute :request => 'goForward'
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def getCurrentUrl
|
|
33
|
+
execute :request => 'getCurrentUrl'
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def getTitle
|
|
37
|
+
execute :request => 'getTitle'
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def getPageSource
|
|
41
|
+
execute :request => 'getPageSource'
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def switchToWindow(name)
|
|
45
|
+
execute :request => 'switchToWindow',
|
|
46
|
+
:windowName => name
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def switchToFrame(id)
|
|
50
|
+
execute :request => 'switchToFrameByName',
|
|
51
|
+
:name => id
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def quit
|
|
55
|
+
@launcher.kill # FIXME: let chrome extension take care of this
|
|
56
|
+
execute :request => 'quit'
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def close
|
|
60
|
+
execute :request => 'close'
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def getWindowHandles
|
|
64
|
+
execute :request => 'getWindowHandles'
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def getCurrentWindowHandle
|
|
68
|
+
execute :request => 'getCurrentWindowHandle'
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def setSpeed(value)
|
|
72
|
+
@speed = value
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def getSpeed
|
|
76
|
+
@speed
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def executeScript(script, *args)
|
|
80
|
+
typed_args = args.map { |e| wrap_script_argument(e) }
|
|
81
|
+
|
|
82
|
+
resp = execute :request => 'executeScript',
|
|
83
|
+
:script => script,
|
|
84
|
+
:args => typed_args
|
|
85
|
+
|
|
86
|
+
unwrap_script_argument resp
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def addCookie(cookie)
|
|
90
|
+
execute :request => 'addCookie',
|
|
91
|
+
:cookie => cookie
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def deleteCookie(name)
|
|
95
|
+
execute :request => 'deleteCookie',
|
|
96
|
+
:name => name
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def getAllCookies
|
|
100
|
+
execute :request => 'getCookies'
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def deleteAllCookies
|
|
104
|
+
execute :request => 'deleteAllCookies'
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def findElementByClassName(parent, class_name)
|
|
108
|
+
find_element_by 'class name', class_name, parent
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def findElementsByClassName(parent, class_name)
|
|
112
|
+
find_elements_by 'class name', class_name, parent
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def findElementById(parent, id)
|
|
116
|
+
find_element_by 'id', id, parent
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def findElementsById(parent, id)
|
|
120
|
+
find_elements_by 'id', id, parent
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def findElementByLinkText(parent, link_text)
|
|
124
|
+
find_element_by 'link text', link_text, parent
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def findElementsByLinkText(parent, link_text)
|
|
128
|
+
find_elements_by 'link text', link_text, parent
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def findElementByPartialLinkText(parent, link_text)
|
|
132
|
+
find_element_by 'partial link text', link_text, parent
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def findElementsByPartialLinkText(parent, link_text)
|
|
136
|
+
find_elements_by 'partial link text', link_text, parent
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def findElementByName(parent, name)
|
|
140
|
+
find_element_by 'name', name, parent
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def findElementsByName(parent, name)
|
|
144
|
+
find_elements_by 'name', name, parent
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def findElementByTagName(parent, tag_name)
|
|
148
|
+
find_element_by 'tag name', tag_name, parent
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def findElementsByTagName(parent, tag_name)
|
|
152
|
+
find_elements_by 'tag name', tag_name, parent
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def findElementByXpath(parent, xpath)
|
|
156
|
+
find_element_by 'xpath', xpath, parent
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def findElementsByXpath(parent, xpath)
|
|
160
|
+
find_elements_by 'xpath', xpath, parent
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
#
|
|
165
|
+
# Element functions
|
|
166
|
+
#
|
|
167
|
+
|
|
168
|
+
def clickElement(element)
|
|
169
|
+
execute :request => 'clickElement',
|
|
170
|
+
:elementId => element
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def getElementTagName(element)
|
|
174
|
+
execute :request => 'getElementTagName',
|
|
175
|
+
:elementId => element
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def getElementAttribute(element, name)
|
|
179
|
+
execute :request => 'getElementAttribute',
|
|
180
|
+
:elementId => element,
|
|
181
|
+
:attribute => name
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def getElementValue(element)
|
|
185
|
+
execute :request => 'getElementValue',
|
|
186
|
+
:elementId => element
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def getElementText(element)
|
|
190
|
+
execute :request => 'getElementText',
|
|
191
|
+
:elementId => element
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def getElementLocation(element)
|
|
195
|
+
data = execute :request => 'getElementLocation',
|
|
196
|
+
:elementId => element
|
|
197
|
+
|
|
198
|
+
Point.new data['x'], data['y']
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def getElementSize(element)
|
|
202
|
+
execute :request => 'getElementSize',
|
|
203
|
+
:elementId => element
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def sendKeysToElement(element, string)
|
|
207
|
+
execute :request => 'sendKeysToElement',
|
|
208
|
+
:elementId => element,
|
|
209
|
+
:keys => string.split(//u)
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def clearElement(element)
|
|
213
|
+
execute :request => 'clearElement',
|
|
214
|
+
:elementId => element
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def isElementEnabled(element)
|
|
218
|
+
execute :request => 'isElementEnabled',
|
|
219
|
+
:elementId => element
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def isElementSelected(element)
|
|
223
|
+
execute :request => 'isElementSelected',
|
|
224
|
+
:elementId => element
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def isElementDisplayed(element)
|
|
228
|
+
execute :request => 'isElementDisplayed',
|
|
229
|
+
:elementId => element
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def submitElement(element)
|
|
233
|
+
execute :request => 'submitElement',
|
|
234
|
+
:elementId => element
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def toggleElement(element)
|
|
238
|
+
execute :request => 'toggleElement',
|
|
239
|
+
:elementId => element
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def setElementSelected(element)
|
|
243
|
+
execute :request => 'setElementSelected',
|
|
244
|
+
:elementId => element
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def getElementValueOfCssProperty(element, prop)
|
|
248
|
+
execute :request => 'getElementValueOfCssProperty',
|
|
249
|
+
:elementId => element,
|
|
250
|
+
:css => prop
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
def getActiveElement
|
|
254
|
+
Element.new self, element_id_from(execute(:request => 'getActiveElement'))
|
|
255
|
+
end
|
|
256
|
+
alias_method :switchToActiveElement, :getActiveElement
|
|
257
|
+
|
|
258
|
+
def hoverOverElement
|
|
259
|
+
execute :request => 'hoverOverElement',
|
|
260
|
+
:elementId => element
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
def dragElement(element, rigth_by, down_by)
|
|
264
|
+
raise UnsupportedOperationError, "drag and drop unsupported in Chrome"
|
|
265
|
+
execute :drag_element, {:id => element}, element, rigth_by, down_by
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
private
|
|
269
|
+
|
|
270
|
+
def find_element_by(how, what, parent = nil)
|
|
271
|
+
if parent
|
|
272
|
+
id = execute :request => 'findChildElement',
|
|
273
|
+
:id => parent,
|
|
274
|
+
:using => how,
|
|
275
|
+
:value => what
|
|
276
|
+
else
|
|
277
|
+
id = execute :request => 'findElement',
|
|
278
|
+
:using => how,
|
|
279
|
+
:value => what
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
Element.new self, element_id_from(id)
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
def find_elements_by(how, what, parent = nil)
|
|
286
|
+
if parent
|
|
287
|
+
ids = execute :request => 'findChildElements',
|
|
288
|
+
:id => parent,
|
|
289
|
+
:using => how,
|
|
290
|
+
:value => what
|
|
291
|
+
else
|
|
292
|
+
ids = execute :request => 'findElements',
|
|
293
|
+
:using => how,
|
|
294
|
+
:value => what
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
ids.map { |id| Element.new self, element_id_from(id) }
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
private
|
|
302
|
+
|
|
303
|
+
def execute(command)
|
|
304
|
+
resp = raw_execute command
|
|
305
|
+
code = resp['statusCode']
|
|
306
|
+
if e = Error.for_code(code)
|
|
307
|
+
msg = resp['value']['message'] if resp['value']
|
|
308
|
+
msg ||= "unknown exception for #{command.inspect}"
|
|
309
|
+
msg << " (#{code})"
|
|
310
|
+
|
|
311
|
+
raise e, msg
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
resp['value']
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
def raw_execute(command)
|
|
318
|
+
@executor.execute command
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
end # Bridge
|
|
322
|
+
end # Chrome
|
|
323
|
+
end # WebDriver
|
|
324
|
+
end # Selenium
|