selenium-webdriver 0.0.8 → 0.0.9

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.
@@ -77,11 +77,16 @@ function parsePortMessage(message) {
77
77
  element.scrollIntoView(true);
78
78
  //TODO: Work out a way of firing events,
79
79
  //now that synthesising them gives appendMessage errors
80
+ console.log("mouse downing");
80
81
  Utils.fireMouseEventOn(element, "mousedown");
82
+ console.log("mouse up");
81
83
  Utils.fireMouseEventOn(element, "mouseup");
84
+ console.log("mouse click");
82
85
  Utils.fireMouseEventOn(element, "click");
86
+
83
87
  if (element.click) {
84
- element.click();
88
+ console.log("click");
89
+ execute("try { arguments[0].click(); } catch(e){}", {type: "ELEMENT", value: getElementId_(element)});
85
90
  }
86
91
  response.value = {statusCode: 0};
87
92
  break;
@@ -535,6 +540,23 @@ function internalGetElement(elementIdAsString) {
535
540
  }
536
541
  }
537
542
 
543
+ /**
544
+ * Given an element, returning the index that can be used to locate it
545
+ *
546
+ * @param element the element to look up the internal ID of
547
+ * @return A positive integer on success or -1 otherwise
548
+ */
549
+ function getElementId_(element) {
550
+ var length = ChromeDriverContentScript.internalElementArray.length;
551
+ for (var i = 0; i < length; i++) {
552
+ if (ChromeDriverContentScript.internalElementArray[i] === element) {
553
+ return i;
554
+ }
555
+ }
556
+
557
+ return -1;
558
+ }
559
+
538
560
  /**
539
561
  * Ensures the passed element is in view, so that the native click event can be sent
540
562
  * @return object to send back to background page to trigger a native click
@@ -763,6 +785,8 @@ function toggleElement(element) {
763
785
  } catch (e) {
764
786
  return e;
765
787
  }
788
+ console.log("New value: " + newValue);
789
+
766
790
  if (changed) {
767
791
  //TODO: Work out a way of firing events,
768
792
  //now that synthesising them gives appendMessage errors
@@ -842,9 +866,10 @@ function parseWrappedArguments(argument) {
842
866
  * We can't share objects between content script and page, so have to wrap up arguments as JSON
843
867
  * @param script script to execute as a string
844
868
  * @param passedArgs array of arguments to pass to the script
869
+ * @param callback function to call when the result is returned
845
870
  */
846
- function execute(script, passedArgs) {
847
- console.log("execing " + script + ", args: " + JSON.stringify(passedArgs));
871
+ function execute_(script, passedArgs, callback) {
872
+ console.log("executing " + script + ", args: " + JSON.stringify(passedArgs));
848
873
  var func = "function(){" + script + "}";
849
874
  var args = [];
850
875
  for (var i = 0; i < passedArgs.length; ++i) {
@@ -899,11 +924,15 @@ function execute(script, passedArgs) {
899
924
  '}' +
900
925
  'document.getElementsByTagName("script")[document.getElementsByTagName("script").length - 1].dispatchEvent(e);' +
901
926
  'document.getElementsByTagName("html")[0].removeChild(document.getElementsByTagName("script")[document.getElementsByTagName("script").length - 1]);';
902
- scriptTag.addEventListener('DOMAttrModified', returnFromJavascriptInPage, false);
927
+ scriptTag.addEventListener('DOMAttrModified', callback, false);
903
928
  console.log("Injecting script element");
904
929
  ChromeDriverContentScript.currentDocument.getElementsByTagName("html")[0].appendChild(scriptTag);
905
930
  }
906
931
 
932
+ function execute(script, passedArgs) {
933
+ execute_(script, passedArgs, returnFromJavascriptInPage);
934
+ }
935
+
907
936
  function parseReturnValueFromScript(result) {
908
937
  console.log("Parsing: " + JSON.stringify(result));
909
938
  var value = {"type":"NULL"};
@@ -944,7 +973,7 @@ function returnFromJavascriptInPage(e) {
944
973
  console.log("Result was: " + e.newValue.value);
945
974
  var result = JSON.parse(e.newValue).value;
946
975
  var value = parseReturnValueFromScript(result);
947
- console.log("reutrn value: " + JSON.stringify(value));
976
+ console.log("Return value: " + JSON.stringify(value));
948
977
  ChromeDriverContentScript.port.postMessage({sequenceNumber: ChromeDriverContentScript.currentSequenceNumber, response: {response: "execute", value: {statusCode: 0, value: value}}});
949
978
  }
950
979
 
@@ -150,13 +150,11 @@ Utils.getStyleProperty = function(node, propertyName) {
150
150
  function collapseWhitespace(textSoFar) {
151
151
  return textSoFar.replace(/\s+/g, " ");
152
152
  }
153
- ;
154
153
 
155
154
  function getPreformattedText(node) {
156
155
  var textToAdd = "";
157
156
  return getTextFromNode(node, "", textToAdd, true)[1];
158
157
  }
159
- ;
160
158
 
161
159
  function isWhiteSpace(character) {
162
160
  return character == '\n' || character == ' ' || character == '\t' || character == '\r';
@@ -177,9 +175,19 @@ Utils.getText = function(element) {
177
175
  };
178
176
 
179
177
  Utils.fireHtmlEvent = function(element, eventName) {
180
- var e = document.createEvent("HTMLEvents");
181
- e.initEvent(eventName, true, true);
182
- element.dispatchEvent(e);
178
+ var args = [
179
+ {type: "ELEMENT", value: getElementId_(element)},
180
+ {type: "STRING", value: eventName}
181
+ ];
182
+
183
+ // We need to do this because event handlers refer to functions that
184
+ // the content script can't reah. See:
185
+ // http://code.google.com/p/chromium/issues/detail?id=29071
186
+ var script = "var e = document.createEvent('HTMLEvents'); "
187
+ + "e.initEvent(arguments[1], true, true); "
188
+ + "arguments[0].dispatchEvent(e);";
189
+
190
+ execute_(script, args, function(){});
183
191
  };
184
192
 
185
193
 
@@ -188,9 +196,22 @@ Utils.fireMouseEventOn = function(element, eventName) {
188
196
  };
189
197
 
190
198
  Utils.triggerMouseEvent = function(element, eventType, clientX, clientY) {
191
- var event = element.ownerDocument.createEvent("MouseEvents");
192
- var view = element.ownerDocument.defaultView;
193
-
194
- event.initMouseEvent(eventType, true, true, view, 1, 0, 0, clientX, clientY, false, false, false, false, 0, element);
195
- element.dispatchEvent(event);
199
+ var args = [
200
+ {type: "ELEMENT", value: getElementId_(element)},
201
+ {type: "STRING", value: eventType},
202
+ {type: "NUMBER", value: clientX},
203
+ {type: "NUMBER", value: clientY}
204
+ ];
205
+
206
+ // We need to do this because event handlers refer to functions that
207
+ // the content script can't reah. See:
208
+ // http://code.google.com/p/chromium/issues/detail?id=29071
209
+ var script =
210
+ "var event = arguments[0].ownerDocument.createEvent('MouseEvents'); "
211
+ + "var view = arguments[0].ownerDocument.defaultView; "
212
+ + "event.initMouseEvent(arguments[1], true, true, view, 1, 0, 0, arguments[2], arguments[3], false, false, false, false, 0, arguments[0]);"
213
+ + " arguments[0].dispatchEvent(event);";
214
+
215
+ execute_(script, args, function(){});
196
216
  };
217
+
@@ -56,8 +56,12 @@ module Selenium
56
56
  end
57
57
 
58
58
  def quit
59
- @launcher.kill # FIXME: let chrome extension take care of this
60
- execute :request => 'quit'
59
+ begin
60
+ execute :request => 'quit'
61
+ rescue IOError
62
+ end
63
+
64
+ @launcher.kill
61
65
  @executor.close
62
66
  end
63
67
 
@@ -92,6 +96,7 @@ module Selenium
92
96
  :script => script,
93
97
  :args => typed_args
94
98
 
99
+ return if resp.nil?
95
100
  unwrap_script_argument resp
96
101
  end
97
102
 
@@ -310,7 +315,10 @@ module Selenium
310
315
  private
311
316
 
312
317
  def execute(command)
318
+ puts "--> #{command.inspect}" if $DEBUG
313
319
  resp = raw_execute command
320
+ puts "<-- #{resp.inspect}" if $DEBUG
321
+
314
322
  code = resp['statusCode']
315
323
  if e = Error.for_code(code)
316
324
  msg = resp['value']['message'] if resp['value']
@@ -26,9 +26,9 @@ goog.require('goog.Disposable');
26
26
  goog.require('goog.array');
27
27
  goog.require('goog.object');
28
28
  goog.require('webdriver.CommandName');
29
- goog.require('webdriver.Context');
30
29
  goog.require('webdriver.Future');
31
30
  goog.require('webdriver.Response');
31
+ goog.require('webdriver.WebElement');
32
32
  goog.require('webdriver.timing');
33
33
 
34
34
 
@@ -57,11 +57,14 @@ webdriver.AbstractCommandProcessor.resolveFutureParams_ = function(
57
57
  function getValue(obj) {
58
58
  if (obj instanceof webdriver.Future) {
59
59
  return obj.getValue();
60
- } else if (goog.isFunction(obj)) {
60
+ } else if (goog.isFunction(obj) ||
61
+ obj instanceof webdriver.WebElement) {
61
62
  return obj;
62
63
  } else if (goog.isObject(obj)) {
63
64
  goog.object.forEach(obj, function(value, key) {
64
- obj[key] = getValue(value);
65
+ if (value instanceof webdriver.Future) {
66
+ obj[key] = value.getValue();
67
+ }
65
68
  });
66
69
  }
67
70
  return obj;
@@ -80,36 +83,41 @@ webdriver.AbstractCommandProcessor.resolveFutureParams_ = function(
80
83
  /**
81
84
  * Executes a command.
82
85
  * @param {webdriver.Command} command The command to execute.
83
- * @param {string} sessionId The current session ID.
84
- * @param {webdriver.Context} context The context to execute the command in.
85
86
  */
86
- webdriver.AbstractCommandProcessor.prototype.execute = function(command,
87
- sessionId,
88
- context) {
87
+ webdriver.AbstractCommandProcessor.prototype.execute = function(command) {
88
+ var driver = command.getDriver();
89
89
  webdriver.AbstractCommandProcessor.resolveFutureParams_(command);
90
- switch (command.name) {
90
+ var parameters = command.getParameters();
91
+ switch (command.getName()) {
91
92
  case webdriver.CommandName.SLEEP:
92
- var ms = command.parameters[0];
93
+ var ms = parameters[0];
93
94
  webdriver.timing.setTimeout(function() {
94
- command.setResponse(new webdriver.Response(false, context, ms));
95
+ command.setResponse(new webdriver.Response(
96
+ false, driver.getContext(), ms));
95
97
  }, ms);
96
98
  break;
97
99
 
98
100
  case webdriver.CommandName.WAIT:
99
101
  case webdriver.CommandName.FUNCTION:
100
102
  try {
101
- var result = command.parameters[0]();
102
- command.setResponse(new webdriver.Response(false, context, result));
103
+ var fn = parameters[0];
104
+ var selfObj = parameters[1];
105
+ var args = parameters[2];
106
+ var result = fn.apply(selfObj, args);
107
+ command.setResponse(new webdriver.Response(
108
+ false, driver.getContext(), result));
103
109
  } catch (ex) {
104
- command.setResponse(new webdriver.Response(true, context, null, ex));
110
+ command.setResponse(new webdriver.Response(
111
+ true, driver.getContext(), null, ex));
105
112
  }
106
113
  break;
107
114
 
108
115
  default:
109
116
  try {
110
- this.executeDriverCommand(command, sessionId, context);
117
+ this.dispatchDriverCommand(command);
111
118
  } catch (ex) {
112
- command.setResponse(new webdriver.Response(true, context, null, ex));
119
+ command.setResponse(new webdriver.Response(
120
+ true, driver.getContext(), null, ex));
113
121
  }
114
122
  break;
115
123
  }
@@ -120,9 +128,7 @@ webdriver.AbstractCommandProcessor.prototype.execute = function(command,
120
128
  * Sends a command to be executed by a browser driver. This method must be
121
129
  * implemented by each subclass.
122
130
  * @param {webdriver.Command} command The command to execute.
123
- * @param {string} sessionId The current session ID.
124
- * @param {webdriver.Context} context The context to execute the command in.
125
131
  * @protected
126
132
  */
127
- webdriver.AbstractCommandProcessor.prototype.executeDriverCommand =
133
+ webdriver.AbstractCommandProcessor.prototype.dispatchDriverCommand =
128
134
  goog.abstractMethod;
@@ -79,24 +79,6 @@ webdriver.Command = function(driver, name, opt_element) {
79
79
  */
80
80
  this.parameters = [];
81
81
 
82
- /**
83
- * Callback for when the command processor successfully finishes this command.
84
- * The result of this function is included in the final result of the command.
85
- * @type {?function}
86
- */
87
- this.onSuccessCallbackFn = null;
88
-
89
- /**
90
- * Callback for when the command processor fails to successfully finish a
91
- * command. The function should take a single argument, the
92
- * {@code webdriver.Response} from the command processor. The response may be
93
- * modified (for example, to turn an expect failure into a success). If the
94
- * error state is cleared, the {@code onSucessCallbackFn} will still not be
95
- * called.
96
- * @type {?function}
97
- */
98
- this.onFailureCallbackFn = null;
99
-
100
82
  /**
101
83
  * The response to this command.
102
84
  * @type {?webdriver.Response}
@@ -123,8 +105,6 @@ webdriver.Command.prototype.disposeInternal = function() {
123
105
  delete this.name;
124
106
  delete this.element;
125
107
  delete this.parameters;
126
- delete this.onSuccessCallbackFn;
127
- delete this.onFailureCallbackFn;
128
108
  delete this.response;
129
109
  };
130
110
 
@@ -180,35 +160,10 @@ webdriver.Command.prototype.setParameters = function(var_args) {
180
160
 
181
161
 
182
162
  /**
183
- * Set the function to call with the {@code webdriver.Response} when the
184
- * command processor successfully runs this command. This function is considered
185
- * part of the command and any errors will cause the command as a whole to fail.
186
- * @param {function} callbackFn The function to call on success.
187
- * @param {Object} opt_selfObj The object in whose context to execute the
188
- * function.
163
+ * @return {Array.<*>} The parameters to send with this command.
189
164
  */
190
- webdriver.Command.prototype.setSuccessCallback = function(callbackFn,
191
- opt_selfObj) {
192
- if (callbackFn) {
193
- this.onSuccessCallbackFn = goog.bind(callbackFn, opt_selfObj);
194
- }
195
- return this;
196
- };
197
-
198
-
199
- /**
200
- * Set the function to call with the {@code webdriver.Response} when the
201
- * command processor encounters an error while executing this command.
202
- * @param {function} callbackFn The function to call on failure.
203
- * @param {Object} opt_selfObj The object in whose context to execute the
204
- * function.
205
- */
206
- webdriver.Command.prototype.setFailureCallback = function(callbackFn,
207
- opt_selfObj) {
208
- if (callbackFn) {
209
- this.onFailureCallbackFn = goog.bind(callbackFn, opt_selfObj);
210
- }
211
- return this;
165
+ webdriver.Command.prototype.getParameters = function() {
166
+ return this.parameters;
212
167
  };
213
168
 
214
169
 
@@ -231,26 +186,7 @@ webdriver.Command.prototype.setResponse = function(response) {
231
186
  return;
232
187
  }
233
188
  this.response = response;
234
-
235
- var sandbox = goog.bind(function(fn) {
236
- try {
237
- fn.call(this, this.response);
238
- } catch (ex) {
239
- this.response.isFailure = true;
240
- this.response.errors.push(ex);
241
- }
242
- }, this);
243
-
244
- if (!this.response.errors.length) {
245
- if (this.response.isFailure &&
246
- goog.isFunction(this.onFailureCallbackFn)) {
247
- sandbox(this.onFailureCallbackFn);
248
- } else if (!this.response.isFailure &&
249
- goog.isFunction(this.onSuccessCallbackFn)) {
250
- sandbox(this.onSuccessCallbackFn);
251
- }
252
- }
253
-
189
+ this.driver_.setContext(this.response.context);
254
190
  if (!this.response.isFailure) {
255
191
  this.futureResult_.setValue(this.response.value);
256
192
  } else {
@@ -116,7 +116,11 @@ webdriver.Future.prototype.setValue = function(value) {
116
116
  }
117
117
  if (value instanceof webdriver.Future) {
118
118
  if (value.isSet()) {
119
- this.value_ = value.getValue();
119
+ value = value.getValue();
120
+ this.value_ = value;
121
+ goog.array.forEach(this.linkedFutures_, function(future) {
122
+ future.setValue(value);
123
+ });
120
124
  } else {
121
125
  value.linkedFutures_.push(this);
122
126
  }
@@ -0,0 +1,40 @@
1
+ /** @license
2
+ Copyright 2007-2009 WebDriver committers
3
+ Copyright 2007-2009 Google Inc.
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
16
+ */
17
+
18
+ /**
19
+ * @fileoverview File to include for turnning any HTML page into a WebDriver
20
+ * JSUnit test suite by configuring an onload listener to the body that will
21
+ * instantiate and start the test runner.
22
+ */
23
+
24
+ goog.provide('webdriver.jsunit');
25
+
26
+ goog.require('goog.testing.jsunit');
27
+ goog.require('webdriver.TestCase');
28
+ goog.require('webdriver.asserts');
29
+ goog.require('webdriver.factory');
30
+
31
+
32
+ (function() {
33
+ window.onload = function() {
34
+ var test = new webdriver.TestCase(document.title,
35
+ webdriver.factory.createLocalWebDriver);
36
+ test.autoDiscoverTests();
37
+ G_testRunner.initialize(test);
38
+ G_testRunner.execute(test);
39
+ };
40
+ })();
@@ -24,6 +24,7 @@ limitations under the License.
24
24
  goog.provide('webdriver.LocalCommandProcessor');
25
25
 
26
26
  goog.require('goog.array');
27
+ goog.require('goog.debug.Logger');
27
28
  goog.require('goog.dom');
28
29
  goog.require('goog.events');
29
30
  goog.require('goog.json');
@@ -123,9 +124,8 @@ webdriver.LocalCommandProcessor.onResponse_ = function(command, e) {
123
124
  }
124
125
 
125
126
  var rawResponse = goog.json.parse(jsonResponse);
126
- webdriver.logging.info(
127
- 'receiving:\n' +
128
- webdriver.logging.describe(rawResponse, ' '));
127
+ goog.debug.Logger.getLogger('webdriver.LocalCommandProcessor').fine(
128
+ 'receiving:\n' + jsonResponse);
129
129
 
130
130
  var response = new webdriver.Response(
131
131
  rawResponse['isError'],
@@ -144,29 +144,34 @@ webdriver.LocalCommandProcessor.onResponse_ = function(command, e) {
144
144
  /**
145
145
  * @override
146
146
  */
147
- webdriver.LocalCommandProcessor.prototype.executeDriverCommand = function(
148
- command, sessionId, context) {
149
- if (command.name == webdriver.CommandName.SEND_KEYS) {
150
- command.parameters = [command.parameters.join('')];
147
+ webdriver.LocalCommandProcessor.prototype.dispatchDriverCommand = function(
148
+ command) {
149
+ if (command.getName() == webdriver.CommandName.SEND_KEYS) {
150
+ command.setParameters(command.getParameters().join(''));
151
151
  }
152
152
 
153
153
  var jsonCommand = {
154
- 'commandName': command.name,
155
- 'context': context.toString(),
156
- 'parameters': command.parameters
154
+ 'commandName': command.getName(),
155
+ 'context': command.getDriver().getContext().toString(),
156
+ 'parameters': command.getParameters()
157
157
  };
158
158
 
159
159
  if (command.element) {
160
- jsonCommand['elementId'] = command.element.getId().getValue();
160
+ try {
161
+ jsonCommand['elementId'] = command.element.getId().getValue();
162
+ } catch (ex) {
163
+ window.console.dir(command);
164
+ throw ex;
165
+ }
161
166
  }
162
167
 
163
- webdriver.logging.info(
164
- 'sending:\n' +
165
- webdriver.logging.describe(jsonCommand, ' '));
168
+ jsonCommand = goog.json.serialize(jsonCommand);
169
+ goog.debug.Logger.getLogger('webdriver.LocalCommandProcessor').fine(
170
+ 'sending:\n' + jsonCommand);
166
171
 
167
172
  this.documentElement_.setAttribute(
168
173
  webdriver.LocalCommandProcessor.MessageAttribute_.COMMAND,
169
- goog.json.serialize(jsonCommand));
174
+ jsonCommand);
170
175
 
171
176
  goog.events.listen(this.documentElement_,
172
177
  webdriver.LocalCommandProcessor.EventType_.RESPONSE,