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,57 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2007-2009 WebDriver committers
|
|
3
|
+
Copyright 2007-2009 Google Inc.
|
|
4
|
+
Portions copyright 2007 ThoughtWorks, Inc
|
|
5
|
+
|
|
6
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
you may not use this file except in compliance with the License.
|
|
8
|
+
You may obtain a copy of the License at
|
|
9
|
+
|
|
10
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
|
|
12
|
+
Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
See the License for the specific language governing permissions and
|
|
16
|
+
limitations under the License.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
var STATE_START = Components.interfaces.nsIWebProgressListener.STATE_START;
|
|
20
|
+
var STATE_STOP = Components.interfaces.nsIWebProgressListener.STATE_STOP;
|
|
21
|
+
|
|
22
|
+
function WebLoadingListener(browser, toCall) {
|
|
23
|
+
var listener = this;
|
|
24
|
+
|
|
25
|
+
this.handler = {
|
|
26
|
+
QueryInterface: function(iid) {
|
|
27
|
+
if (iid.equals(Components.interfaces.nsIWebProgressListener) ||
|
|
28
|
+
iid.equals(Components.interfaces.nsISupportsWeakReference) ||
|
|
29
|
+
iid.equals(Components.interfaces.nsISupports))
|
|
30
|
+
return this;
|
|
31
|
+
throw Components.results.NS_NOINTERFACE;
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
onStateChange: function(webProgress, request, flags, status) {
|
|
35
|
+
if (flags & STATE_STOP) {
|
|
36
|
+
if (request.URI) {
|
|
37
|
+
WebLoadingListener.removeListener(browser, listener);
|
|
38
|
+
toCall();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return 0;
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
onLocationChange: function(aProgress, aRequest, aURI) { return 0; },
|
|
45
|
+
onProgressChange: function() { return 0; },
|
|
46
|
+
onStatusChange: function() { return 0; },
|
|
47
|
+
onSecurityChange: function() { return 0; },
|
|
48
|
+
onLinkIconAvailable: function() { return 0; }
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
browser.addProgressListener(this.handler,
|
|
52
|
+
Components.interfaces.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
WebLoadingListener.removeListener = function(browser, listener) {
|
|
56
|
+
browser.removeProgressListener(listener.handler);
|
|
57
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2007-2009 WebDriver committers
|
|
3
|
+
Copyright 2007-2009 Google Inc.
|
|
4
|
+
Portions copyright 2007 ThoughtWorks, Inc
|
|
5
|
+
|
|
6
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
you may not use this file except in compliance with the License.
|
|
8
|
+
You may obtain a copy of the License at
|
|
9
|
+
|
|
10
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
|
|
12
|
+
Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
See the License for the specific language governing permissions and
|
|
16
|
+
limitations under the License.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
function WebDriverServer() {
|
|
21
|
+
this.wrappedJSObject = this;
|
|
22
|
+
this.serverSocket =
|
|
23
|
+
Components.classes["@mozilla.org/network/server-socket;1"].
|
|
24
|
+
createInstance(Components.interfaces.nsIServerSocket);
|
|
25
|
+
this.generator =
|
|
26
|
+
Utils.getService("@mozilla.org/uuid-generator;1", "nsIUUIDGenerator");
|
|
27
|
+
this.enableNativeEvents = null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
WebDriverServer.prototype.newDriver = function(window) {
|
|
32
|
+
if (null == this.useNativeEvents) {
|
|
33
|
+
var prefs =
|
|
34
|
+
Utils.getService("@mozilla.org/preferences-service;1", "nsIPrefBranch");
|
|
35
|
+
if (!prefs.prefHasUserValue("webdriver_enable_native_events")) {
|
|
36
|
+
Utils.dumpn('webdriver_enable_native_events not set; defaulting to true');
|
|
37
|
+
}
|
|
38
|
+
this.enableNativeEvents =
|
|
39
|
+
prefs.prefHasUserValue("webdriver_enable_native_events") ?
|
|
40
|
+
prefs.getBoolPref("webdriver_enable_native_events") : false;
|
|
41
|
+
Utils.dumpn('Enable native events: ' + this.enableNativeEvents);
|
|
42
|
+
}
|
|
43
|
+
window.fxdriver = new FirefoxDriver(this, this.enableNativeEvents);
|
|
44
|
+
// Yuck. But it allows us to refer to it later.
|
|
45
|
+
window.fxdriver.window = window;
|
|
46
|
+
return window.fxdriver;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
WebDriverServer.prototype.getNextId = function() {
|
|
51
|
+
return this.generator.generateUUID().toString();
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
WebDriverServer.prototype.onSocketAccepted = function(socket, transport) {
|
|
56
|
+
try {
|
|
57
|
+
var socketListener = new SocketListener(transport);
|
|
58
|
+
} catch(e) {
|
|
59
|
+
dump(e);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
WebDriverServer.prototype.startListening = function(port) {
|
|
65
|
+
if (!port) {
|
|
66
|
+
var prefs =
|
|
67
|
+
Utils.getService("@mozilla.org/preferences-service;1", "nsIPrefBranch");
|
|
68
|
+
|
|
69
|
+
port = prefs.prefHasUserValue("webdriver_firefox_port") ?
|
|
70
|
+
prefs.getIntPref("webdriver_firefox_port") : 7055;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (!this.isListening) {
|
|
74
|
+
this.serverSocket.init(port, true, -1);
|
|
75
|
+
this.serverSocket.asyncListen(this);
|
|
76
|
+
this.isListening = true;
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
WebDriverServer.prototype.onStopListening = function(socket, status)
|
|
82
|
+
{
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
WebDriverServer.prototype.close = function()
|
|
87
|
+
{
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
WebDriverServer.prototype.QueryInterface = function(aIID) {
|
|
92
|
+
if (!aIID.equals(nsISupports))
|
|
93
|
+
throw Components.results.NS_ERROR_NO_INTERFACE;
|
|
94
|
+
return this;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
WebDriverServer.prototype.createInstance = function(ignore1, ignore2, ignore3) {
|
|
99
|
+
var port = WebDriverServer.readPort();
|
|
100
|
+
this.startListening(port);
|
|
101
|
+
};
|
|
@@ -0,0 +1,609 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2007-2009 WebDriver committers
|
|
3
|
+
Copyright 2007-2009 Google Inc.
|
|
4
|
+
Portions copyright 2007 ThoughtWorks, Inc
|
|
5
|
+
|
|
6
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
you may not use this file except in compliance with the License.
|
|
8
|
+
You may obtain a copy of the License at
|
|
9
|
+
|
|
10
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
|
|
12
|
+
Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
See the License for the specific language governing permissions and
|
|
16
|
+
limitations under the License.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
FirefoxDriver.prototype.click = function(respond) {
|
|
21
|
+
var element = Utils.getElementAt(respond.elementId, respond.context);
|
|
22
|
+
|
|
23
|
+
if (!Utils.isDisplayed(element) && !Utils.isInHead(element)) {
|
|
24
|
+
respond.isError = true;
|
|
25
|
+
respond.response =
|
|
26
|
+
"Element is not currently visible and so may not be clicked";
|
|
27
|
+
respond.send();
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
var nativeEvents = Utils.getNativeEvents();
|
|
32
|
+
var node = Utils.getNodeForNativeEvents(element);
|
|
33
|
+
var appInfo = Components.classes["@mozilla.org/xre/app-info;1"].
|
|
34
|
+
getService(Components.interfaces.nsIXULAppInfo);
|
|
35
|
+
var versionChecker = Components.
|
|
36
|
+
classes["@mozilla.org/xpcom/version-comparator;1"].
|
|
37
|
+
getService(Components.interfaces.nsIVersionComparator);
|
|
38
|
+
|
|
39
|
+
// I'm having trouble getting clicks to work on Firefox 2 on Windows. Always
|
|
40
|
+
// fall back for that
|
|
41
|
+
// TODO(simon): Get native clicks working for gecko 1.8+
|
|
42
|
+
var useNativeClick =
|
|
43
|
+
versionChecker.compare(appInfo.platformVersion, "1.9") >= 0;
|
|
44
|
+
|
|
45
|
+
if (this.enableNativeEvents && nativeEvents && node && useNativeClick) {
|
|
46
|
+
var loc = Utils.getLocationOnceScrolledIntoView(element);
|
|
47
|
+
var x = loc.x + (loc.width ? loc.width / 2 : 0);
|
|
48
|
+
var y = loc.y + (loc.height ? loc.height / 2 : 0);
|
|
49
|
+
try {
|
|
50
|
+
nativeEvents.mouseMove(node, this.currentX, this.currentY, x, y);
|
|
51
|
+
nativeEvents.click(node, x, y);
|
|
52
|
+
this.currentX = x;
|
|
53
|
+
this.currentY = y;
|
|
54
|
+
respond.send();
|
|
55
|
+
return;
|
|
56
|
+
} catch (e) {
|
|
57
|
+
// Make sure that we only fall through only if
|
|
58
|
+
// the error returned from the native call indicates it's not
|
|
59
|
+
// implemented.
|
|
60
|
+
|
|
61
|
+
if (e.name != "NS_ERROR_NOT_IMPLEMENTED") {
|
|
62
|
+
respond.isError = true;
|
|
63
|
+
respond.response = e.toString();
|
|
64
|
+
respond.send();
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Fall through to the synthesized click code.
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
Utils.dumpn("Falling back to synthesized click");
|
|
73
|
+
var currentlyActive = Utils.getActiveElement(respond.context);
|
|
74
|
+
|
|
75
|
+
Utils.fireMouseEventOn(respond.context, element, "mouseover");
|
|
76
|
+
Utils.fireMouseEventOn(respond.context, element, "mousemove");
|
|
77
|
+
Utils.fireMouseEventOn(respond.context, element, "mousedown");
|
|
78
|
+
if (element != currentlyActive) {
|
|
79
|
+
currentlyActive.blur();
|
|
80
|
+
element.focus();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
Utils.fireMouseEventOn(respond.context, element, "mouseup");
|
|
84
|
+
Utils.fireMouseEventOn(respond.context, element, "click");
|
|
85
|
+
|
|
86
|
+
var browser = Utils.getBrowser(respond.context);
|
|
87
|
+
var alreadyReplied = false;
|
|
88
|
+
|
|
89
|
+
var clickListener = new WebLoadingListener(browser, function(event) {
|
|
90
|
+
if (!alreadyReplied) {
|
|
91
|
+
alreadyReplied = true;
|
|
92
|
+
respond.send();
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
var contentWindow = browser.contentWindow;
|
|
97
|
+
|
|
98
|
+
var checkForLoad = function() {
|
|
99
|
+
// Returning should be handled by the click listener, unless we're not
|
|
100
|
+
// actually loading something. Do a check and return if we are. There's a
|
|
101
|
+
// race condition here, in that the click event and load may have finished
|
|
102
|
+
// before we get here. For now, let's pretend that doesn't happen. The other
|
|
103
|
+
// race condition is that we make this check before the load has begun. With
|
|
104
|
+
// all the javascript out there, this might actually be a bit of a problem.
|
|
105
|
+
var docLoaderService = browser.webProgress;
|
|
106
|
+
if (!docLoaderService.isLoadingDocument) {
|
|
107
|
+
WebLoadingListener.removeListener(browser, clickListener);
|
|
108
|
+
if (!alreadyReplied) {
|
|
109
|
+
alreadyReplied = true;
|
|
110
|
+
respond.send();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
if (contentWindow.closed) {
|
|
117
|
+
respond.send();
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
contentWindow.setTimeout(checkForLoad, 50);
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
FirefoxDriver.prototype.getText = function(respond) {
|
|
125
|
+
var element = Utils.getElementAt(respond.elementId, respond.context);
|
|
126
|
+
|
|
127
|
+
if (element.tagName == "TITLE") {
|
|
128
|
+
respond.response = Utils.getBrowser(respond.context).contentTitle;
|
|
129
|
+
} else {
|
|
130
|
+
respond.response = Utils.getText(element, true);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
respond.send();
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
FirefoxDriver.prototype.getValue = function(respond) {
|
|
138
|
+
var element = Utils.getElementAt(respond.elementId, respond.context);
|
|
139
|
+
|
|
140
|
+
if (element["value"] !== undefined) {
|
|
141
|
+
respond.response = element.value;
|
|
142
|
+
respond.send();
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (element.hasAttribute("value")) {
|
|
147
|
+
respond.response = element.getAttribute("value");
|
|
148
|
+
respond.send();
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
respond.isError = true;
|
|
153
|
+
respond.response = "No match";
|
|
154
|
+
respond.send();
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
FirefoxDriver.prototype.sendKeys = function(respond, value) {
|
|
159
|
+
var element = Utils.getElementAt(respond.elementId, respond.context);
|
|
160
|
+
|
|
161
|
+
if (!Utils.isDisplayed(element) && !Utils.isInHead(element)) {
|
|
162
|
+
respond.isError = true;
|
|
163
|
+
respond.response =
|
|
164
|
+
"Element is not currently visible and so may not be used for typing";
|
|
165
|
+
respond.send();
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
var currentlyActive = Utils.getActiveElement(respond.context);
|
|
170
|
+
if (currentlyActive != element) {
|
|
171
|
+
currentlyActive.blur();
|
|
172
|
+
element.focus();
|
|
173
|
+
element.ownerDocument.defaultView.focus();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
var use = element;
|
|
177
|
+
var tagName = element.tagName.toLowerCase();
|
|
178
|
+
if (tagName == "body" && element.ownerDocument.defaultView.frameElement) {
|
|
179
|
+
element.ownerDocument.defaultView.focus();
|
|
180
|
+
|
|
181
|
+
// Turns out, this is what we should be using as the target
|
|
182
|
+
// to send events to
|
|
183
|
+
use = element.ownerDocument.getElementsByTagName("html")[0];
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
Utils.type(respond.context, use, value[0], this.enableNativeEvents);
|
|
187
|
+
|
|
188
|
+
respond.send();
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
FirefoxDriver.prototype.clear = function(respond) {
|
|
193
|
+
var element = Utils.getElementAt(respond.elementId, respond.context);
|
|
194
|
+
|
|
195
|
+
if (!Utils.isDisplayed(element) && !Utils.isInHead(element)) {
|
|
196
|
+
respond.isError = true;
|
|
197
|
+
respond.response =
|
|
198
|
+
"Element is not currently visible and so may not be cleared";
|
|
199
|
+
respond.send();
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
var isTextField = element["value"] !== undefined;
|
|
204
|
+
|
|
205
|
+
var currentlyActive = Utils.getActiveElement(respond.context);
|
|
206
|
+
if (currentlyActive != element) {
|
|
207
|
+
currentlyActive.blur();
|
|
208
|
+
element.focus();
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
var currentValue = undefined;
|
|
212
|
+
if (element["value"] !== undefined) {
|
|
213
|
+
currentValue = element.value;
|
|
214
|
+
} else if (element.hasAttribute("value")) {
|
|
215
|
+
currentValue = element.getAttribute("value");
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (isTextField) {
|
|
219
|
+
element.value = "";
|
|
220
|
+
} else {
|
|
221
|
+
element.setAttribute("value", "");
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (currentValue !== undefined && currentValue != "") {
|
|
225
|
+
Utils.fireHtmlEvent(respond.context, element, "change");
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
respond.send();
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
FirefoxDriver.prototype.getTagName = function(respond) {
|
|
233
|
+
var element = Utils.getElementAt(respond.elementId, respond.context);
|
|
234
|
+
|
|
235
|
+
respond.response = element.tagName.toLowerCase();
|
|
236
|
+
respond.send();
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
FirefoxDriver.prototype.getAttribute = function(respond, value) {
|
|
241
|
+
var element = Utils.getElementAt(respond.elementId, respond.context);
|
|
242
|
+
|
|
243
|
+
var attributeName = value[0];
|
|
244
|
+
|
|
245
|
+
if (element.hasAttribute(attributeName)) {
|
|
246
|
+
respond.response = element.getAttribute(attributeName);
|
|
247
|
+
// Is this block necessary?
|
|
248
|
+
if (attributeName.toLowerCase() == "disabled") {
|
|
249
|
+
respond.response = element.disabled;
|
|
250
|
+
} else if (attributeName.toLowerCase() == "selected") {
|
|
251
|
+
respond.response = element.selected;
|
|
252
|
+
} else if (attributeName.toLowerCase() == "checked") {
|
|
253
|
+
respond.response = element.checked;
|
|
254
|
+
} else if (attributeName.toLowerCase() == "readonly") {
|
|
255
|
+
respond.response = element.getAttribute('readonly');
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
respond.send();
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
attributeName = attributeName.toLowerCase();
|
|
263
|
+
|
|
264
|
+
if (attributeName == "disabled") {
|
|
265
|
+
respond.response = element.disabled;
|
|
266
|
+
respond.send();
|
|
267
|
+
return;
|
|
268
|
+
} else if ((attributeName == "checked" || attributeName == "selected") &&
|
|
269
|
+
element.tagName.toLowerCase() == "input") {
|
|
270
|
+
respond.response = element.checked;
|
|
271
|
+
respond.send();
|
|
272
|
+
return;
|
|
273
|
+
} else if (attributeName == "selected" && element.tagName.toLowerCase()
|
|
274
|
+
== "option") {
|
|
275
|
+
respond.response = element.selected;
|
|
276
|
+
respond.send();
|
|
277
|
+
return;
|
|
278
|
+
} else if (attributeName == "index" && element.tagName.toLowerCase()
|
|
279
|
+
== "option") {
|
|
280
|
+
respond.response = element.index;
|
|
281
|
+
respond.send();
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
respond.isError = true;
|
|
285
|
+
respond.response = "No match";
|
|
286
|
+
respond.send();
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
FirefoxDriver.prototype.hover = function(respond) {
|
|
291
|
+
var element = Utils.getElementAt(respond.elementId, respond.context);
|
|
292
|
+
|
|
293
|
+
var events = Utils.getNativeEvents();
|
|
294
|
+
var node = Utils.getNodeForNativeEvents(element);
|
|
295
|
+
|
|
296
|
+
if (this.enableNativeEvents && events && node) {
|
|
297
|
+
var loc = Utils.getLocationOnceScrolledIntoView(element);
|
|
298
|
+
|
|
299
|
+
var x = loc.x + (loc.width ? loc.width / 2 : 0);
|
|
300
|
+
var y = loc.y + (loc.height ? loc.height / 2 : 0);
|
|
301
|
+
|
|
302
|
+
events.mouseMove(node, this.currentX, this.currentY, x, y);
|
|
303
|
+
this.currentX = x;
|
|
304
|
+
this.currentY = y;
|
|
305
|
+
} else {
|
|
306
|
+
respond.isError = true;
|
|
307
|
+
respond.response = "Unable to hover over element";
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
respond.send();
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
FirefoxDriver.prototype.submit = function(respond) {
|
|
315
|
+
var element = Utils.getElementAt(respond.elementId, respond.context);
|
|
316
|
+
|
|
317
|
+
var submitElement = Utils.findForm(element);
|
|
318
|
+
if (submitElement) {
|
|
319
|
+
new WebLoadingListener(Utils.getBrowser(respond.context), function() {
|
|
320
|
+
respond.send();
|
|
321
|
+
});
|
|
322
|
+
if (submitElement["submit"])
|
|
323
|
+
submitElement.submit();
|
|
324
|
+
else
|
|
325
|
+
submitElement.click();
|
|
326
|
+
} else {
|
|
327
|
+
respond.send();
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
FirefoxDriver.prototype.isSelected = function(respond) {
|
|
333
|
+
var element = Utils.getElementAt(respond.elementId, respond.context);
|
|
334
|
+
|
|
335
|
+
var selected = false;
|
|
336
|
+
|
|
337
|
+
try {
|
|
338
|
+
var option =
|
|
339
|
+
element.QueryInterface(Components.interfaces.nsIDOMHTMLOptionElement);
|
|
340
|
+
selected = option.selected;
|
|
341
|
+
} catch(e) {
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
try {
|
|
345
|
+
var inputElement =
|
|
346
|
+
element.QueryInterface(Components.interfaces.nsIDOMHTMLInputElement);
|
|
347
|
+
if (inputElement.type == "checkbox" || inputElement.type == "radio") {
|
|
348
|
+
selected = inputElement.checked;
|
|
349
|
+
}
|
|
350
|
+
} catch(e) {
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
respond.response = selected;
|
|
354
|
+
respond.send();
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
FirefoxDriver.prototype.setSelected = function(respond) {
|
|
359
|
+
var element = Utils.getElementAt(respond.elementId, respond.context);
|
|
360
|
+
|
|
361
|
+
if (!Utils.isDisplayed(element) && !Utils.isInHead(element)) {
|
|
362
|
+
respond.isError = true;
|
|
363
|
+
respond.response =
|
|
364
|
+
"Element is not currently visible and so may not be selected";
|
|
365
|
+
respond.send();
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
var wasSet = "You may not select an unselectable element";
|
|
370
|
+
respond.isError = true;
|
|
371
|
+
|
|
372
|
+
try {
|
|
373
|
+
var inputElement =
|
|
374
|
+
element.QueryInterface(Components.interfaces.nsIDOMHTMLInputElement);
|
|
375
|
+
if (inputElement.disabled) {
|
|
376
|
+
respond.response = "You may not select a disabled element";
|
|
377
|
+
respond.send();
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
} catch(e) {
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
try {
|
|
384
|
+
var option =
|
|
385
|
+
element.QueryInterface(Components.interfaces.nsIDOMHTMLOptionElement);
|
|
386
|
+
respond.isError = false;
|
|
387
|
+
if (!option.selected) {
|
|
388
|
+
option.selected = true;
|
|
389
|
+
Utils.fireHtmlEvent(respond.context, option, "change");
|
|
390
|
+
}
|
|
391
|
+
wasSet = "";
|
|
392
|
+
} catch(e) {
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
try {
|
|
396
|
+
var checkbox =
|
|
397
|
+
element.QueryInterface(Components.interfaces.nsIDOMHTMLInputElement);
|
|
398
|
+
respond.isError = false;
|
|
399
|
+
if (checkbox.type == "checkbox" || checkbox.type == "radio") {
|
|
400
|
+
if (!checkbox.checked) {
|
|
401
|
+
checkbox.checked = true;
|
|
402
|
+
Utils.fireHtmlEvent(respond.context, checkbox, "change");
|
|
403
|
+
}
|
|
404
|
+
wasSet = "";
|
|
405
|
+
}
|
|
406
|
+
} catch(e) {
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
respond.response = wasSet;
|
|
410
|
+
respond.send();
|
|
411
|
+
};
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
FirefoxDriver.prototype.toggle = function(respond) {
|
|
415
|
+
var element = Utils.getElementAt(respond.elementId, respond.context);
|
|
416
|
+
|
|
417
|
+
if (!Utils.isDisplayed(element) && !Utils.isInHead(element)) {
|
|
418
|
+
respond.isError = true;
|
|
419
|
+
respond.response =
|
|
420
|
+
"Element is not currently visible and so may not be toggled";
|
|
421
|
+
respond.send();
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
try {
|
|
426
|
+
var checkbox =
|
|
427
|
+
element.QueryInterface(Components.interfaces.nsIDOMHTMLInputElement);
|
|
428
|
+
if (checkbox.type == "checkbox") {
|
|
429
|
+
checkbox.checked = !checkbox.checked;
|
|
430
|
+
Utils.fireHtmlEvent(respond.context, checkbox, "change");
|
|
431
|
+
respond.send();
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
} catch(e) {
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
try {
|
|
438
|
+
var option =
|
|
439
|
+
element.QueryInterface(Components.interfaces.nsIDOMHTMLOptionElement);
|
|
440
|
+
|
|
441
|
+
// Find our containing select and see if it allows multiple selections
|
|
442
|
+
var select = option.parentNode;
|
|
443
|
+
while (select && select.tagName != "SELECT") {
|
|
444
|
+
select = select.parentNode;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
if (select && select.multiple) {
|
|
448
|
+
option.selected = !option.selected;
|
|
449
|
+
Utils.fireHtmlEvent(respond.context, option, "change");
|
|
450
|
+
respond.send();
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
} catch(e) {
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
respond.isError = true;
|
|
457
|
+
respond.response =
|
|
458
|
+
"You may only toggle an element that is either a checkbox or an " +
|
|
459
|
+
"option in a select that allows multiple selections";
|
|
460
|
+
respond.send();
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
FirefoxDriver.prototype.isDisplayed = function(respond) {
|
|
465
|
+
var element = Utils.getElementAt(respond.elementId, respond.context);
|
|
466
|
+
|
|
467
|
+
respond.response = Utils.isDisplayed(element) ? "true" : "false";
|
|
468
|
+
respond.send();
|
|
469
|
+
};
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
FirefoxDriver.prototype.getLocation = function(respond) {
|
|
473
|
+
var element = Utils.getElementAt(respond.elementId, respond.context);
|
|
474
|
+
|
|
475
|
+
var location = Utils.getElementLocation(element, respond.context);
|
|
476
|
+
|
|
477
|
+
respond.response = location.x + ", " + location.y;
|
|
478
|
+
respond.send();
|
|
479
|
+
};
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
FirefoxDriver.prototype.getSize = function(respond) {
|
|
483
|
+
var element = Utils.getElementAt(respond.elementId, respond.context);
|
|
484
|
+
|
|
485
|
+
var box = Utils.getLocationOnceScrolledIntoView(element);
|
|
486
|
+
|
|
487
|
+
respond.response = box.width + ", " + box.height;
|
|
488
|
+
respond.send();
|
|
489
|
+
};
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
FirefoxDriver.prototype.dragElement = function(respond, movementString) {
|
|
493
|
+
var element = Utils.getElementAt(respond.elementId, respond.context);
|
|
494
|
+
|
|
495
|
+
if (!Utils.isDisplayed(element) && !Utils.isInHead(element)) {
|
|
496
|
+
respond.isError = true;
|
|
497
|
+
respond.response =
|
|
498
|
+
"Element is not currently visible and so may not be used for drag and drop";
|
|
499
|
+
respond.send();
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// Scroll the first element into view
|
|
504
|
+
// element.scrollIntoView(true);
|
|
505
|
+
|
|
506
|
+
var clientStartXY = Utils.getElementLocation(element, respond.context);
|
|
507
|
+
|
|
508
|
+
var clientStartX = clientStartXY.x;
|
|
509
|
+
var clientStartY = clientStartXY.y;
|
|
510
|
+
|
|
511
|
+
var movementX = movementString[0];
|
|
512
|
+
var movementY = movementString[1];
|
|
513
|
+
|
|
514
|
+
var clientFinishX = ((clientStartX + movementX) < 0) ? 0 : (clientStartX
|
|
515
|
+
+ movementX);
|
|
516
|
+
var clientFinishY = ((clientStartY + movementY) < 0) ? 0 : (clientStartY
|
|
517
|
+
+ movementY);
|
|
518
|
+
|
|
519
|
+
// Restrict the desitnation into the sensible dimension
|
|
520
|
+
var body = element.ownerDocument.body;
|
|
521
|
+
|
|
522
|
+
if (clientFinishX > body.scrollWidth)
|
|
523
|
+
clientFinishX = body.scrollWidth;
|
|
524
|
+
if (clientFinishY > body.scrollHeight)
|
|
525
|
+
clientFinishY = body.scrollHeight;
|
|
526
|
+
|
|
527
|
+
var mouseSpeed = this.mouseSpeed;
|
|
528
|
+
var move = function(current, dest) {
|
|
529
|
+
if (current == dest) return current;
|
|
530
|
+
if (Math.abs(current - dest) < mouseSpeed) return dest;
|
|
531
|
+
return (current < dest) ? current + mouseSpeed : current - mouseSpeed;
|
|
532
|
+
};
|
|
533
|
+
|
|
534
|
+
Utils.triggerMouseEvent(element, 'mousedown', clientStartX, clientStartY);
|
|
535
|
+
Utils.triggerMouseEvent(element, 'mousemove', clientStartX, clientStartY);
|
|
536
|
+
var clientX = clientStartX;
|
|
537
|
+
var clientY = clientStartY;
|
|
538
|
+
|
|
539
|
+
while ((clientX != clientFinishX) || (clientY != clientFinishY)) {
|
|
540
|
+
clientX = move(clientX, clientFinishX);
|
|
541
|
+
clientY = move(clientY, clientFinishY);
|
|
542
|
+
|
|
543
|
+
Utils.triggerMouseEvent(element, 'mousemove', clientX, clientY);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
Utils.triggerMouseEvent(element, 'mousemove', clientFinishX, clientFinishY);
|
|
547
|
+
|
|
548
|
+
// TODO(simon.m.stewart) If we can tell which element is under the cursor,
|
|
549
|
+
// send the mouseup to that
|
|
550
|
+
Utils.triggerMouseEvent(element, 'mouseup', clientFinishX, clientFinishY);
|
|
551
|
+
|
|
552
|
+
var finalLoc = Utils.getElementLocation(element, respond.context)
|
|
553
|
+
|
|
554
|
+
respond.response = finalLoc.x + "," + finalLoc.y;
|
|
555
|
+
respond.send();
|
|
556
|
+
};
|
|
557
|
+
|
|
558
|
+
|
|
559
|
+
FirefoxDriver.prototype.getValueOfCssProperty = function(respond,
|
|
560
|
+
propertyName) {
|
|
561
|
+
var element = Utils.getElementAt(respond.elementId, respond.context);
|
|
562
|
+
|
|
563
|
+
respond.response = Utils.getStyleProperty(element, propertyName); // Coeerce to a string
|
|
564
|
+
respond.send();
|
|
565
|
+
};
|
|
566
|
+
|
|
567
|
+
|
|
568
|
+
FirefoxDriver.prototype.getLocationOnceScrolledIntoView = function(respond) {
|
|
569
|
+
var element = Utils.getElementAt(respond.elementId, respond.context);
|
|
570
|
+
|
|
571
|
+
if (!Utils.isDisplayed(element)) {
|
|
572
|
+
respond.response = undefined;
|
|
573
|
+
respond.send();
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
element.ownerDocument.body.focus();
|
|
578
|
+
element.scrollIntoView(true);
|
|
579
|
+
|
|
580
|
+
var retrieval = Utils.newInstance(
|
|
581
|
+
"@mozilla.org/accessibleRetrieval;1", "nsIAccessibleRetrieval");
|
|
582
|
+
|
|
583
|
+
try {
|
|
584
|
+
var accessible = retrieval.getAccessibleFor(element);
|
|
585
|
+
var x = {}, y = {}, width = {}, height = {};
|
|
586
|
+
accessible.getBounds(x, y, width, height);
|
|
587
|
+
|
|
588
|
+
respond.response = {
|
|
589
|
+
x : x.value,
|
|
590
|
+
y : y.value
|
|
591
|
+
};
|
|
592
|
+
respond.send();
|
|
593
|
+
return;
|
|
594
|
+
} catch(e) {
|
|
595
|
+
// Element doesn't have an accessibility node
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// Fallback. Use the (deprecated) method to find out where the element is in
|
|
599
|
+
// the viewport. This should be fine to use because we only fall down this
|
|
600
|
+
// code path on older versions of Firefox (I think!)
|
|
601
|
+
var theDoc = Utils.getDocument(respond.context);
|
|
602
|
+
var box = theDoc.getBoxObjectFor(element);
|
|
603
|
+
|
|
604
|
+
respond.response = {
|
|
605
|
+
x : box.screenX,
|
|
606
|
+
y : box.screenY
|
|
607
|
+
};
|
|
608
|
+
respond.send();
|
|
609
|
+
};
|