selenium-webdriver 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+ };