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.
Files changed (86) hide show
  1. data/chrome/prebuilt/Win32/Release/npchromedriver.dll +0 -0
  2. data/chrome/prebuilt/x64/Release/npchromedriver.dll +0 -0
  3. data/chrome/src/extension/background.html +9 -0
  4. data/chrome/src/extension/background.js +933 -0
  5. data/chrome/src/extension/content_script.js +1286 -0
  6. data/chrome/src/extension/manifest-nonwin.json +15 -0
  7. data/chrome/src/extension/manifest-win.json +16 -0
  8. data/chrome/src/extension/toolstrip.html +28 -0
  9. data/chrome/src/extension/utils.js +196 -0
  10. data/chrome/src/rb/lib/selenium/webdriver/chrome.rb +8 -0
  11. data/chrome/src/rb/lib/selenium/webdriver/chrome/bridge.rb +324 -0
  12. data/chrome/src/rb/lib/selenium/webdriver/chrome/command_executor.rb +70 -0
  13. data/chrome/src/rb/lib/selenium/webdriver/chrome/launcher.rb +119 -0
  14. data/common/src/js/abstractcommandprocessor.js +161 -0
  15. data/common/src/js/asserts.js +296 -0
  16. data/common/src/js/by.js +147 -0
  17. data/common/src/js/command.js +274 -0
  18. data/common/src/js/context.js +58 -0
  19. data/common/src/js/extension/README +2 -0
  20. data/common/src/js/extension/dommessenger.js +152 -0
  21. data/common/src/js/factory.js +55 -0
  22. data/common/src/js/future.js +118 -0
  23. data/common/src/js/key.js +117 -0
  24. data/common/src/js/localcommandprocessor.js +181 -0
  25. data/common/src/js/logging.js +249 -0
  26. data/common/src/js/testrunner.js +605 -0
  27. data/common/src/js/timing.js +89 -0
  28. data/common/src/js/wait.js +199 -0
  29. data/common/src/js/webdriver.js +853 -0
  30. data/common/src/js/webelement.js +683 -0
  31. data/common/src/rb/lib/selenium-webdriver.rb +1 -0
  32. data/common/src/rb/lib/selenium/webdriver.rb +52 -0
  33. data/common/src/rb/lib/selenium/webdriver/bridge_helper.rb +88 -0
  34. data/common/src/rb/lib/selenium/webdriver/child_process.rb +85 -0
  35. data/common/src/rb/lib/selenium/webdriver/core_ext/dir.rb +41 -0
  36. data/common/src/rb/lib/selenium/webdriver/driver.rb +128 -0
  37. data/common/src/rb/lib/selenium/webdriver/element.rb +126 -0
  38. data/common/src/rb/lib/selenium/webdriver/error.rb +68 -0
  39. data/common/src/rb/lib/selenium/webdriver/find.rb +69 -0
  40. data/common/src/rb/lib/selenium/webdriver/navigation.rb +23 -0
  41. data/common/src/rb/lib/selenium/webdriver/options.rb +50 -0
  42. data/common/src/rb/lib/selenium/webdriver/platform.rb +82 -0
  43. data/common/src/rb/lib/selenium/webdriver/target_locator.rb +23 -0
  44. data/firefox/prebuilt/nsICommandProcessor.xpt +0 -0
  45. data/firefox/prebuilt/nsINativeEvents.xpt +0 -0
  46. data/firefox/prebuilt/nsIResponseHandler.xpt +0 -0
  47. data/firefox/src/extension/chrome.manifest +3 -0
  48. data/firefox/src/extension/components/context.js +37 -0
  49. data/firefox/src/extension/components/driver-component.js +127 -0
  50. data/firefox/src/extension/components/firefoxDriver.js +706 -0
  51. data/firefox/src/extension/components/json2.js +273 -0
  52. data/firefox/src/extension/components/keytest.html +554 -0
  53. data/firefox/src/extension/components/nsCommandProcessor.js +586 -0
  54. data/firefox/src/extension/components/screenshooter.js +70 -0
  55. data/firefox/src/extension/components/socketListener.js +185 -0
  56. data/firefox/src/extension/components/utils.js +1200 -0
  57. data/firefox/src/extension/components/webLoadingListener.js +57 -0
  58. data/firefox/src/extension/components/webdriverserver.js +101 -0
  59. data/firefox/src/extension/components/wrappedElement.js +609 -0
  60. data/firefox/src/extension/content/fxdriver.xul +30 -0
  61. data/firefox/src/extension/content/server.js +95 -0
  62. data/firefox/src/extension/idl/nsICommandProcessor.idl +38 -0
  63. data/firefox/src/extension/idl/nsIResponseHandler.idl +34 -0
  64. data/firefox/src/extension/install.rdf +29 -0
  65. data/firefox/src/rb/lib/selenium/webdriver/firefox.rb +21 -0
  66. data/firefox/src/rb/lib/selenium/webdriver/firefox/binary.rb +86 -0
  67. data/firefox/src/rb/lib/selenium/webdriver/firefox/bridge.rb +426 -0
  68. data/firefox/src/rb/lib/selenium/webdriver/firefox/extension_connection.rb +82 -0
  69. data/firefox/src/rb/lib/selenium/webdriver/firefox/launcher.rb +132 -0
  70. data/firefox/src/rb/lib/selenium/webdriver/firefox/profile.rb +174 -0
  71. data/firefox/src/rb/lib/selenium/webdriver/firefox/profiles_ini.rb +60 -0
  72. data/firefox/src/rb/lib/selenium/webdriver/firefox/util.rb +23 -0
  73. data/jobbie/prebuilt/Win32/Release/InternetExplorerDriver.dll +0 -0
  74. data/jobbie/prebuilt/x64/Release/InternetExplorerDriver.dll +0 -0
  75. data/jobbie/src/rb/lib/selenium/webdriver/ie.rb +14 -0
  76. data/jobbie/src/rb/lib/selenium/webdriver/ie/bridge.rb +552 -0
  77. data/jobbie/src/rb/lib/selenium/webdriver/ie/lib.rb +94 -0
  78. data/jobbie/src/rb/lib/selenium/webdriver/ie/util.rb +147 -0
  79. data/remote/client/src/rb/lib/selenium/webdriver/remote.rb +16 -0
  80. data/remote/client/src/rb/lib/selenium/webdriver/remote/bridge.rb +374 -0
  81. data/remote/client/src/rb/lib/selenium/webdriver/remote/capabilities.rb +105 -0
  82. data/remote/client/src/rb/lib/selenium/webdriver/remote/commands.rb +53 -0
  83. data/remote/client/src/rb/lib/selenium/webdriver/remote/default_http_client.rb +71 -0
  84. data/remote/client/src/rb/lib/selenium/webdriver/remote/response.rb +43 -0
  85. data/remote/client/src/rb/lib/selenium/webdriver/remote/server_error.rb +32 -0
  86. 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
+ };