selenium-webdriver 0.0.17 → 0.0.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) 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.js +64 -48
  4. data/chrome/src/extension/content_script.js +253 -132
  5. data/chrome/src/extension/manifest-nonwin.json +1 -1
  6. data/chrome/src/extension/manifest-win.json +1 -1
  7. data/chrome/src/extension/utils.js +8 -8
  8. data/chrome/src/rb/lib/selenium/webdriver/chrome.rb +9 -0
  9. data/chrome/src/rb/lib/selenium/webdriver/chrome/bridge.rb +38 -280
  10. data/chrome/src/rb/lib/selenium/webdriver/chrome/command_executor.rb +119 -117
  11. data/chrome/src/rb/lib/selenium/webdriver/chrome/launcher.rb +36 -26
  12. data/common/src/js/abstractcommandprocessor.js +9 -11
  13. data/common/src/js/command.js +159 -83
  14. data/common/src/js/core/RemoteRunner.html +2 -2
  15. data/common/src/js/core/TestRunner-splash.html +3 -3
  16. data/common/src/js/core/TestRunner.html +5 -17
  17. data/common/src/js/core/scripts/htmlutils.js +4208 -2506
  18. data/common/src/js/core/scripts/selenium-api.js +2 -2
  19. data/common/src/js/core/scripts/selenium-browserbot.js +66 -58
  20. data/common/src/js/core/scripts/selenium-version.js +1 -1
  21. data/common/src/js/localcommandprocessor.js +5 -19
  22. data/common/src/js/testcase.js +2 -0
  23. data/common/src/js/webdriver.js +63 -93
  24. data/common/src/js/webelement.js +40 -42
  25. data/common/src/rb/lib/selenium/webdriver.rb +23 -14
  26. data/common/src/rb/lib/selenium/webdriver/bridge_helper.rb +8 -35
  27. data/common/src/rb/lib/selenium/webdriver/child_process.rb +2 -0
  28. data/common/src/rb/lib/selenium/webdriver/core_ext/dir.rb +1 -0
  29. data/common/src/rb/lib/selenium/webdriver/core_ext/string.rb +5 -0
  30. data/common/src/rb/lib/selenium/webdriver/driver.rb +20 -15
  31. data/common/src/rb/lib/selenium/webdriver/driver_extensions/takes_screenshot.rb +7 -2
  32. data/common/src/rb/lib/selenium/webdriver/element.rb +11 -2
  33. data/common/src/rb/lib/selenium/webdriver/error.rb +9 -5
  34. data/common/src/rb/lib/selenium/webdriver/keys.rb +1 -2
  35. data/common/src/rb/lib/selenium/webdriver/navigation.rb +16 -0
  36. data/common/src/rb/lib/selenium/webdriver/options.rb +32 -0
  37. data/common/src/rb/lib/selenium/webdriver/platform.rb +17 -1
  38. data/firefox/prebuilt/Win32/Release/webdriver-firefox.dll +0 -0
  39. data/firefox/src/extension/components/dispatcher.js +492 -0
  40. data/firefox/src/extension/components/driver-component.js +4 -1
  41. data/firefox/src/extension/components/errorcode.js +70 -0
  42. data/firefox/src/extension/components/firefoxDriver.js +173 -154
  43. data/firefox/src/extension/components/nsCommandProcessor.js +171 -132
  44. data/firefox/src/extension/components/promptService.js +5 -5
  45. data/firefox/src/extension/components/request.js +219 -0
  46. data/firefox/src/extension/components/response.js +276 -0
  47. data/firefox/src/extension/components/session.js +281 -0
  48. data/firefox/src/extension/components/sessionstore.js +226 -0
  49. data/firefox/src/extension/components/socketListener.js +350 -100
  50. data/firefox/src/extension/components/utils.js +166 -98
  51. data/firefox/src/extension/components/webdriverserver.js +9 -5
  52. data/firefox/src/extension/components/wrappedElement.js +189 -166
  53. data/firefox/src/extension/install.rdf +1 -1
  54. data/firefox/src/rb/lib/selenium/webdriver/firefox.rb +2 -0
  55. data/firefox/src/rb/lib/selenium/webdriver/firefox/binary.rb +39 -33
  56. data/firefox/src/rb/lib/selenium/webdriver/firefox/bridge.rb +7 -421
  57. data/firefox/src/rb/lib/selenium/webdriver/firefox/extension_connection.rb +7 -64
  58. data/firefox/src/rb/lib/selenium/webdriver/firefox/launcher.rb +2 -3
  59. data/firefox/src/rb/lib/selenium/webdriver/firefox/profile.rb +54 -10
  60. data/firefox/src/rb/lib/selenium/webdriver/firefox/profiles_ini.rb +2 -0
  61. data/firefox/src/rb/lib/selenium/webdriver/firefox/util.rb +6 -0
  62. data/jobbie/prebuilt/Win32/Release/InternetExplorerDriver.dll +0 -0
  63. data/jobbie/prebuilt/x64/Release/InternetExplorerDriver.dll +0 -0
  64. data/jobbie/src/rb/lib/selenium/webdriver/ie.rb +2 -0
  65. data/jobbie/src/rb/lib/selenium/webdriver/ie/bridge.rb +38 -13
  66. data/jobbie/src/rb/lib/selenium/webdriver/ie/lib.rb +9 -2
  67. data/jobbie/src/rb/lib/selenium/webdriver/ie/util.rb +5 -0
  68. data/remote/client/src/rb/lib/selenium/webdriver/remote.rb +2 -0
  69. data/remote/client/src/rb/lib/selenium/webdriver/remote/bridge.rb +42 -38
  70. data/remote/client/src/rb/lib/selenium/webdriver/remote/commands.rb +56 -47
  71. data/remote/client/src/rb/lib/selenium/webdriver/remote/default_http_client.rb +26 -26
  72. data/remote/client/src/rb/lib/selenium/webdriver/remote/patron_http_client.rb +58 -0
  73. data/remote/client/src/rb/lib/selenium/webdriver/remote/response.rb +10 -12
  74. data/remote/client/src/rb/lib/selenium/webdriver/remote/server_error.rb +2 -17
  75. metadata +44 -23
  76. data/common/src/js/context.js +0 -58
  77. data/firefox/src/extension/components/context.js +0 -37
@@ -1,6 +1,8 @@
1
1
  module Selenium
2
2
  module WebDriver
3
3
  module Chrome
4
+
5
+ # @private
4
6
  class Launcher
5
7
  include FileUtils
6
8
 
@@ -21,6 +23,13 @@ module Selenium
21
23
  launcher
22
24
  end
23
25
 
26
+ def self.binary_path
27
+ @binary_path ||= (
28
+ path = possible_paths.find { |f| File.exist?(f) }
29
+ path || raise(Error::WebDriverError, "Could not find Chrome binary. Make sure Chrome is installed (OS: #{Platform.os})")
30
+ )
31
+ end
32
+
24
33
  def launch(server_url)
25
34
  create_extension
26
35
  create_profile
@@ -55,8 +64,7 @@ module Selenium
55
64
  end
56
65
 
57
66
  def launch_chrome(server_url)
58
- check_binary_exists
59
- @process = ChildProcess.new Platform.wrap_in_quotes_if_necessary(binary_path),
67
+ @process = ChildProcess.new Platform.wrap_in_quotes_if_necessary(self.class.binary_path),
60
68
  "--load-extension=#{Platform.wrap_in_quotes_if_necessary tmp_extension_dir}",
61
69
  "--user-data-dir=#{Platform.wrap_in_quotes_if_necessary tmp_profile_dir}",
62
70
  "--activate-on-launch",
@@ -67,12 +75,6 @@ module Selenium
67
75
  @process.start
68
76
  end
69
77
 
70
- def check_binary_exists
71
- unless File.file?(binary_path)
72
- raise Error::WebDriverError, "Could not find Chrome binary. Make sure Chrome is installed (OS: #{Platform.os})"
73
- end
74
- end
75
-
76
78
  def ext_path
77
79
  @ext_path ||= "#{WebDriver.root}/chrome/src/extension"
78
80
  end
@@ -96,36 +98,44 @@ module Selenium
96
98
  end
97
99
 
98
100
  class WindowsLauncher < Launcher
99
- def linked_lib_path
100
- # TODO: x64
101
- @linked_lib_path ||= "#{WebDriver.root}/chrome/prebuilt/Win32/Release/npchromedriver.dll"
101
+ def self.possible_paths
102
+ [
103
+ registry_path,
104
+ "#{ENV['USERPROFILE']}\\Local Settings\\Application Data\\Google\\Chrome\\Application\\chrome.exe",
105
+ "#{ENV['USERPROFILE']}\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe",
106
+ "#{Platform.home}\\Local Settings\\Application Data\\Google\\Chrome\\Application\\chrome.exe",
107
+ "#{Platform.home}\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe",
108
+ ].compact
102
109
  end
103
110
 
104
- def binary_path
105
- @binary_path ||= begin
106
- possible_paths = [
107
- "#{ENV['USERPROFILE']}\\Local Settings\\Application Data\\Google\\Chrome\\Application\\chrome.exe",
108
- "#{ENV['USERPROFILE']}\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe",
109
- "#{Platform.home}\\Local Settings\\Application Data\\Google\\Chrome\\Application\\chrome.exe",
110
- "#{Platform.home}\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe",
111
- ]
112
-
113
- possible_paths.find { |f| File.exist?(f) } || possible_paths.first
114
- end
111
+ def self.registry_path
112
+ require "win32/registry"
113
+
114
+ reg = Win32::Registry::HKEY_LOCAL_MACHINE.open("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\chrome.exe")
115
+ reg[""]
116
+ rescue LoadError
117
+ # older JRuby and IronRuby does not have win32/registry
118
+ nil
119
+ rescue Win32::Registry::Error
120
+ nil
115
121
  end
116
122
 
123
+ def linked_lib_path
124
+ # TODO: x64
125
+ @linked_lib_path ||= "#{WebDriver.root}/chrome/prebuilt/Win32/Release/npchromedriver.dll"
126
+ end
117
127
  end
118
128
 
119
129
  class UnixLauncher < Launcher
120
- def binary_path
121
- @binary_path ||= "/usr/bin/google-chrome"
130
+ def self.possible_paths
131
+ [Platform.find_binary("google-chrome"), "/usr/bin/google-chrome"].compact
122
132
  end
123
133
 
124
134
  end
125
135
 
126
136
  class MacOSXLauncher < UnixLauncher
127
- def binary_path
128
- @binary_path ||= "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
137
+ def self.possible_paths
138
+ ["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome", "#{Platform.home}/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"]
129
139
  end
130
140
  end
131
141
 
@@ -28,6 +28,7 @@ goog.require('goog.object');
28
28
  goog.require('webdriver.CommandName');
29
29
  goog.require('webdriver.Future');
30
30
  goog.require('webdriver.Response');
31
+ goog.require('webdriver.Response.Code');
31
32
  goog.require('webdriver.WebElement');
32
33
  goog.require('webdriver.timing');
33
34
 
@@ -63,14 +64,14 @@ webdriver.AbstractCommandProcessor.resolveFutureParams_ = function(
63
64
  } else if (goog.isObject(obj)) {
64
65
  goog.object.forEach(obj, function(value, key) {
65
66
  if (value instanceof webdriver.Future) {
66
- obj[key] = value.getValue();
67
+ obj[key] = getValue(value);
67
68
  }
68
69
  });
69
70
  }
70
71
  return obj;
71
72
  }
72
73
 
73
- command.parameters = goog.array.map(command.parameters, function(param) {
74
+ command.parameters = goog.object.map(command.parameters, function(param) {
74
75
  if (goog.isArray(param)) {
75
76
  return goog.array.map(param, getValue);
76
77
  } else {
@@ -90,25 +91,22 @@ webdriver.AbstractCommandProcessor.prototype.execute = function(command) {
90
91
  var parameters = command.getParameters();
91
92
  switch (command.getName()) {
92
93
  case webdriver.CommandName.SLEEP:
93
- var ms = parameters[0];
94
+ var ms = parameters['ms'];
94
95
  webdriver.timing.setTimeout(function() {
95
96
  command.setResponse(new webdriver.Response(
96
- false, driver.getContext(), ms));
97
+ webdriver.Response.Code.SUCCESS, ms));
97
98
  }, ms);
98
99
  break;
99
100
 
100
101
  case webdriver.CommandName.WAIT:
101
102
  case webdriver.CommandName.FUNCTION:
102
103
  try {
103
- var fn = parameters[0];
104
- var selfObj = parameters[1];
105
- var args = parameters[2];
106
- var result = fn.apply(selfObj, args);
104
+ var result = parameters['function'].apply(null, parameters['args']);
107
105
  command.setResponse(new webdriver.Response(
108
- false, driver.getContext(), result));
106
+ webdriver.Response.Code.SUCCESS, result));
109
107
  } catch (ex) {
110
108
  command.setResponse(new webdriver.Response(
111
- true, driver.getContext(), null, ex));
109
+ webdriver.Response.Code.UNHANDLED_ERROR, ex));
112
110
  }
113
111
  break;
114
112
 
@@ -117,7 +115,7 @@ webdriver.AbstractCommandProcessor.prototype.execute = function(command) {
117
115
  this.dispatchDriverCommand(command);
118
116
  } catch (ex) {
119
117
  command.setResponse(new webdriver.Response(
120
- true, driver.getContext(), null, ex));
118
+ webdriver.Response.Code.UNHANDLED_ERROR, ex));
121
119
  }
122
120
  break;
123
121
  }
@@ -23,6 +23,7 @@ limitations under the License.
23
23
  goog.provide('webdriver.Command');
24
24
  goog.provide('webdriver.CommandName');
25
25
  goog.provide('webdriver.Response');
26
+ goog.provide('webdriver.Response.Code');
26
27
 
27
28
  goog.require('goog.array');
28
29
  goog.require('goog.events.EventTarget');
@@ -35,13 +36,10 @@ goog.require('webdriver.Future');
35
36
  * {@code webdriver.AbstractCommandProcessor}.
36
37
  * @param {webdriver.WebDriver} driver The driver that this is a command for.
37
38
  * @param {webdriver.CommandName} name The name of this command.
38
- * @param {webdriver.WebElement} opt_element The element to perform this
39
- * command on. If not defined, the command will be performed relative to
40
- * the document root.
41
39
  * @constructor
42
40
  * @extends {goog.events.EventTarget}
43
41
  */
44
- webdriver.Command = function(driver, name, opt_element) {
42
+ webdriver.Command = function(driver, name) {
45
43
  goog.events.EventTarget.call(this);
46
44
 
47
45
  /**
@@ -66,18 +64,11 @@ webdriver.Command = function(driver, name, opt_element) {
66
64
  */
67
65
  this.name = name;
68
66
 
69
- /**
70
- * The element to perform this command on. If not defined, the command will be
71
- * performed relative to the document root.
72
- * @type {webdriver.WebElement}
73
- */
74
- this.element = opt_element;
75
-
76
67
  /**
77
68
  * The parameters to this command.
78
- * @type {Array.<*>}
69
+ * @type {Object}
79
70
  */
80
- this.parameters = [];
71
+ this.parameters = {};
81
72
 
82
73
  /**
83
74
  * The response to this command.
@@ -103,7 +94,6 @@ webdriver.Command.prototype.disposeInternal = function() {
103
94
  delete this.driver_;
104
95
  delete this.futureResult_;
105
96
  delete this.name;
106
- delete this.element;
107
97
  delete this.parameters;
108
98
  delete this.response;
109
99
  };
@@ -149,18 +139,19 @@ webdriver.Command.prototype.isFinished = function() {
149
139
 
150
140
 
151
141
  /**
152
- * Set the parameters to send with this command.
153
- * @param {*} var_args The arguments to send to this command.
142
+ * Sets a parameter to send with this command.
143
+ * @param {string} name The parameter name.
144
+ * @param {*} var_args The parameter value.
154
145
  * @return {webdriver.Command} A self reference.
155
146
  */
156
- webdriver.Command.prototype.setParameters = function(var_args) {
157
- this.parameters = goog.array.slice(arguments, 0);
147
+ webdriver.Command.prototype.setParameter = function(name, value) {
148
+ this.parameters[name] = value;
158
149
  return this;
159
150
  };
160
151
 
161
152
 
162
153
  /**
163
- * @return {Array.<*>} The parameters to send with this command.
154
+ * @return {Object} The parameters to send with this command.
164
155
  */
165
156
  webdriver.Command.prototype.getParameters = function() {
166
157
  return this.parameters;
@@ -186,9 +177,8 @@ webdriver.Command.prototype.setResponse = function(response) {
186
177
  return;
187
178
  }
188
179
  this.response = response;
189
- this.driver_.setContext(this.response.context);
190
- if (!this.response.isFailure) {
191
- this.futureResult_.setValue(this.response.value);
180
+ if (this.response.getStatus() == webdriver.Response.Code.SUCCESS) {
181
+ this.futureResult_.setValue(this.response.getValue());
192
182
  } else {
193
183
  this.dispatchEvent(webdriver.Command.ERROR_EVENT);
194
184
  }
@@ -210,67 +200,114 @@ webdriver.CommandName = {
210
200
  // Commands dispatched to the browser driver. -------------------------------
211
201
  NEW_SESSION: 'newSession',
212
202
  DELETE_SESSION: 'deleteSession',
213
- QUIT: 'quit',
214
- GET_CURRENT_WINDOW_HANDLE: 'getCurrentWindowHandle',
215
- GET_WINDOW_HANDLES: 'getWindowHandles',
216
- GET_CURRENT_URL: 'getCurrentUrl',
203
+
217
204
  CLOSE: 'close',
218
- SWITCH_TO_WINDOW: 'switchToWindow',
219
- SWITCH_TO_FRAME: 'switchToFrame',
220
- SWITCH_TO_DEFAULT_CONTENT: 'switchToDefaultContent',
205
+ QUIT: 'quit',
206
+
221
207
  GET: 'get',
222
- FORWARD: 'goForward',
223
- BACK: 'goBack',
208
+ GO_BACK: 'goBack',
209
+ GO_FORWARD: 'goForward',
224
210
  REFRESH: 'refresh',
225
- GET_TITLE: 'title',
226
- GET_PAGE_SOURCE: 'getPageSource',
227
- EXECUTE_SCRIPT: 'executeScript',
228
- GET_MOUSE_SPEED: 'getMouseSpeed',
229
- SET_MOUSE_SPEED: 'setMouseSpeed',
211
+
212
+ ADD_COOKIE: 'addCookie',
213
+ GET_COOKIE: 'getCookie',
214
+ GET_ALL_COOKIES: 'getCookies',
215
+ DELETE_COOKIE: 'deleteCookie',
216
+ DELETE_ALL_COOKIES: 'deleteAllCookies',
217
+
230
218
  FIND_ELEMENT: 'findElement',
231
219
  FIND_ELEMENTS: 'findElements',
232
220
  FIND_CHILD_ELEMENT: 'findChildElement',
233
221
  FIND_CHILD_ELEMENTS: 'findChildElements',
222
+
223
+ CLEAR_ELEMENT: 'clearElement',
224
+ CLICK_ELEMENT: 'clickElement',
225
+ HOVER_OVER_ELEMNET: 'hoverOverElement',
226
+ SEND_KEYS_TO_ELEMENT: 'sendKeysToElement',
227
+ SUBMIT_ELEMENT: 'submitElement',
228
+ TOGGLE_ELEMENT: 'toggleElement',
229
+
230
+ GET_CURRENT_WINDOW_HANDLE: 'getCurrentWindowHandle',
231
+ GET_WINDOW_HANDLES: 'getWindowHandles',
232
+
233
+ SWITCH_TO_WINDOW: 'switchToWindow',
234
+ SWITCH_TO_FRAME: 'switchToFrame',
235
+ SWITCH_TO_DEFAULT_CONTENT: 'switchToDefaultContent',
234
236
  GET_ACTIVE_ELEMENT: 'getActiveElement',
235
- SET_VISIBLE: 'setVisible',
236
- GET_VISIBLE: 'getVisible',
237
- CLICK: 'click',
238
- CLEAR: 'clear',
239
- SUBMIT: 'submit',
240
- GET_TEXT: 'getText',
241
- SEND_KEYS: 'sendKeys',
242
- GET_VALUE: 'getValue',
243
- GET_TAG_NAME: 'getTagName',
244
- IS_SELECTED: 'isSelected',
245
- SET_SELECTED: 'setSelected',
246
- TOGGLE: 'toggle',
247
- IS_ENABLED: 'isEnabled',
248
- IS_DISPLAYED: 'isDisplayed',
249
- GET_LOCATION: 'getLocation',
250
- GET_SIZE: 'getSize',
251
- GET_ATTRIBUTE: 'getAttribute',
237
+
238
+ GET_CURRENT_URL: 'getCurrentUrl',
239
+ GET_PAGE_SOURCE: 'getPageSource',
240
+ GET_TITLE: 'getTitle',
241
+
242
+ EXECUTE_SCRIPT: 'executeScript',
243
+
244
+ GET_SPEED: 'getSpeed',
245
+ SET_SPEED: 'setSpeed',
246
+
247
+ SET_BROWSE_VISIBLE: 'setBrowserVisible',
248
+ IS_BROWSER_VISIBLE: 'isBrowserVisible',
249
+
250
+ GET_ELEMENT_TEXT: 'getElementText',
251
+ GET_ELEMENT_VALUE: 'getElementValue',
252
+ GET_ELEMENT_TAG_NAME: 'getElementTagName',
253
+ SET_ELEMENT_SELECTED: 'setElementSelected',
252
254
  DRAG_ELEMENT: 'dragElement',
253
- GET_VALUE_OF_CSS_PROPERTY: 'getValueOfCssProperty'
255
+ IS_ELEMENT_SELECTED: 'isElementSelected',
256
+ IS_ELEMENT_ENABLED: 'isElementEnabled',
257
+ IS_ELEMENT_DISPLAYED: 'isElementDisplayed',
258
+ GET_ELEMENT_LOCATION: 'getElementLocation',
259
+ GET_ELEMENT_LOCATION_ONCE_SCROLLED_INTO_VIEW:
260
+ 'getElementLocationOnceScrolledIntoView',
261
+ GET_ELEMENT_SIZE: 'getElementSize',
262
+ GET_ELEMENT_ATTRIBUTE: 'getElementAttribute',
263
+ GET_ELEMENT_VALUE_OF_CSS_PROPERTY: 'getElementValueOfCssProperty',
264
+ ELEMENT_EQUALS: 'elementEquals',
265
+
266
+ SCREENSHOT: 'screenshot',
267
+ DIMISS_ALERT: 'dimissAlert'
254
268
  };
255
269
 
256
270
 
257
271
  /**
258
272
  * Encapsulates a response to a {@code webdriver.Command}.
259
- * @param {boolean} isFailure Whether the command resulted in an error. If
260
- * {@code true}, then {@code value} contains the error message.
261
- * @param {webdriver.Context} context The (potentially new) context resulting
262
- * from the command.
273
+ * @param {webdriver.Response.Code} status The status code for this response.
263
274
  * @param {*} value The value of the response, the meaning of which depends
264
275
  * on the command.
265
- * @parma {Error} opt_error An error that caused this command to fail
266
- * prematurely.
267
276
  * @constructor
268
277
  */
269
- webdriver.Response = function(isFailure, context, value, opt_error) {
270
- this.isFailure = isFailure;
271
- this.context = context;
272
- this.value = value;
273
- this.errors = goog.array.slice(arguments, 3);
278
+ webdriver.Response = function(status, value) {
279
+
280
+ /**
281
+ * The status code for this response.
282
+ * @type {webdriver.Response.Code}
283
+ * @private
284
+ */
285
+ this.status_ = status;
286
+
287
+ /**
288
+ * The value for this response.
289
+ * @type {*}
290
+ * @private
291
+ */
292
+ this.value_ = value;
293
+ };
294
+
295
+
296
+ /** @return {webdriver.Response.Code} The status code for this response. */
297
+ webdriver.Response.prototype.getStatus = function() {
298
+ return this.status_;
299
+ };
300
+
301
+
302
+ /** @return {*} The value of this response. */
303
+ webdriver.Response.prototype.getValue = function() {
304
+ return this.value_;
305
+ };
306
+
307
+
308
+ /** @return {!boolean} Whether this is a response to a successful command. */
309
+ webdriver.Response.prototype.isSuccess = function() {
310
+ return this.status_ == webdriver.Response.Code.SUCCESS;
274
311
  };
275
312
 
276
313
 
@@ -279,26 +316,65 @@ webdriver.Response = function(isFailure, context, value, opt_error) {
279
316
  * failure response.
280
317
  */
281
318
  webdriver.Response.prototype.getErrorMessage = function() {
282
- if (!this.isFailure) {
319
+ if (this.status_ == webdriver.Response.Code.SUCCESS) {
283
320
  return null;
284
321
  }
285
- var message = [];
286
- if (goog.isString(this.value)) {
287
- message.push(this.value);
288
- } else if (null != this.value && goog.isDef(this.value.message)) {
289
- message.push(this.value.message);
290
- if (goog.isDef(this.value.fileName)) {
291
- message.push(this.value.fileName + '@' + this.value.lineNumber);
292
- }
322
+
323
+ if (!this.value_) {
324
+ return 'Unknown error'; // Really should never happen
293
325
  }
294
- goog.array.extend(message, goog.array.map(this.errors, function(error) {
295
- if (goog.isString(error)) {
296
- return error;
326
+
327
+ if (goog.isDef(this.value_['message'])) {
328
+ var message = [this.value_['message']];
329
+
330
+ var stackTrace = this.value_['stackTrace'];
331
+ if (goog.isArray(stackTrace)) {
332
+ goog.array.extend(message, goog.array.map(this.value_['stackTrace'],
333
+ function(frame) {
334
+ var buffer = [];
335
+
336
+ // className is provided by remote java servers
337
+ var className = frame['className'];
338
+ if (goog.isDef(className)) {
339
+ buffer.push(className + '.');
340
+ }
341
+ buffer.push(frame['methodName'] || '<anonymous function>');
342
+ buffer.push('() at ');
343
+ // fileName will be undefined if the method call was to an XPCOM
344
+ // interface.
345
+ buffer.push(frame['fileName'] || '<unknown file>');
346
+ buffer.push(':');
347
+ buffer.push(frame['lineNumber']);
348
+ return buffer.join('');
349
+ }));
350
+ } else if (goog.isDef(stackTrace)) {
351
+ message.push(stackTrace);
352
+ } else if (goog.isDef(this.value_.stack)) {
353
+ message.push(goog.testing.stacktrace.canonicalize(this.value_.stack));
297
354
  }
298
- var errMsg = error.message || error.description || error.toString();
299
- var stack = error.stack ?
300
- goog.testing.stacktrace.canonicalize(error.stack) : error['stackTrace'];
301
- return errMsg + '\n' + stack;
302
- }));
303
- return message.join('\n');
355
+ return message.join('\n');
356
+ } else {
357
+ return this.value_.toString();
358
+ }
359
+ };
360
+
361
+
362
+ /**
363
+ * Error codes used by the wire protocol.
364
+ * @enum {number}
365
+ */
366
+ webdriver.Response.Code = {
367
+ /* keep in sync with codes in org.openqa.selenium.remote.ErrorCodes */
368
+ SUCCESS: 0,
369
+ COOKIE_ERROR: 2,
370
+ NO_SUCH_WINDOW: 3,
371
+ NO_SUCH_ELEMENT: 7,
372
+ NO_SUCH_FRAME: 8,
373
+ UNKNOWN_COMMAND: 9,
374
+ STALE_ELEMENT_REFERENCE: 10,
375
+ ELEMENT_NOT_VISIBLE: 11,
376
+ INVALID_ELEMENT_STATE: 12,
377
+ UNHANDLED_ERROR: 13,
378
+ UNEXPECTED_JAVASCRIPT_ERROR: 17,
379
+ XPATH_LOOKUP_ERROR: 19
304
380
  };