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,15 @@
1
+ {
2
+ "name": "WebDriver",
3
+ "version": "0.3",
4
+ "description": "WebDriver extension for Chrome",
5
+ "toolstrips": ["toolstrip.html"],
6
+ "background_page": "background.html",
7
+ "content_scripts": [
8
+ {
9
+ "matches": ["http://*/*", "https://*/*", "file:///*"],
10
+ "js": ["utils.js", "content_script.js"],
11
+ "run_at": "document_start"
12
+ }
13
+ ],
14
+ "permissions": ["http://*/*", "tabs"]
15
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "WebDriver",
3
+ "version": "0.2",
4
+ "description": "WebDriver extension for Chrome",
5
+ "toolstrips": ["toolstrip.html"],
6
+ "background_page": "background.html",
7
+ "content_scripts": [
8
+ {
9
+ "matches": ["http://*/*", "https://*/*", "file:///*"],
10
+ "js": ["utils.js", "content_script.js"],
11
+ "run_at": "document_start"
12
+ }
13
+ ],
14
+ "plugins": [{"path": "npchromedriver.dll", "public": true}],
15
+ "permissions": ["http://*/*", "tabs"]
16
+ }
@@ -0,0 +1,28 @@
1
+ <html>
2
+ <head>
3
+ <script type="text/javascript">
4
+ function setWebdriverToolstripBusy() {
5
+ document.getElementById("toolstripText").className = "toolstripTextBusy";
6
+ }
7
+
8
+ function setWebdriverToolstripFree() {
9
+ document.getElementById("toolstripText").className = "toolstripTextFree";
10
+ }
11
+ </script>
12
+
13
+ <style type="text/css">
14
+ .toolstripTextBusy {
15
+ color: red;
16
+ }
17
+
18
+ .toolstripTextFree {
19
+ color: black;
20
+ }
21
+ </style>
22
+ </head>
23
+ <body>
24
+ <div>
25
+ <span id="toolstripText" class="toolstripTextFree">WebDriver</span>
26
+ </div>
27
+ </body>
28
+ </html>
@@ -0,0 +1,196 @@
1
+ //Very cut-down and slightly modified (generally to remove context) from
2
+ //$WEBDRIVER_HOME/firefox/src/extension/components/utils.js
3
+
4
+ function Utils() {
5
+ }
6
+
7
+ function getTextFromNode(node, toReturn, textSoFar, isPreformatted) {
8
+ if (node['tagName'] && node.tagName == "SCRIPT") {
9
+ return [toReturn, textSoFar];
10
+ } else if (node['tagName'] && node.tagName == "TITLE") {
11
+ return [textSoFar + node.text, ""];
12
+ }
13
+ var children = node.childNodes;
14
+
15
+ for (var i = 0; i < children.length; i++) {
16
+ var child = children[i];
17
+
18
+ // Do we need to collapse the text so far?
19
+ if (child["tagName"] && child.tagName == "PRE") {
20
+ toReturn += collapseWhitespace(textSoFar);
21
+ textSoFar = "";
22
+ var bits = getTextFromNode(child, toReturn, "", true);
23
+ toReturn += bits[1];
24
+ continue;
25
+ }
26
+
27
+ // Or is this just plain text?
28
+ if (child.nodeName == "#text") {
29
+ if (Utils.isDisplayed(child)) {
30
+ var textToAdd = child.nodeValue;
31
+ textToAdd = textToAdd.replace(new RegExp(String.fromCharCode(160), "gm"), " ");
32
+ textSoFar += textToAdd;
33
+ }
34
+ continue;
35
+ }
36
+
37
+ // Treat as another child node.
38
+ var bits = getTextFromNode(child, toReturn, textSoFar, false);
39
+ toReturn = bits[0];
40
+ textSoFar = bits[1];
41
+ }
42
+
43
+ if (isBlockLevel(node)) {
44
+ if (node["tagName"] && node.tagName != "PRE") {
45
+ toReturn += collapseWhitespace(textSoFar) + "\n";
46
+ textSoFar = "";
47
+ } else {
48
+ toReturn += "\n";
49
+ }
50
+ }
51
+ return [toReturn, textSoFar];
52
+ }
53
+ ;
54
+
55
+ function isBlockLevel(node) {
56
+ if (node["tagName"] && node.tagName == "BR")
57
+ return true;
58
+
59
+ try {
60
+ // Should we think about getting hold of the current document?
61
+ return "block" == Utils.getStyleProperty(node, "display");
62
+ } catch (e) {
63
+ return false;
64
+ }
65
+ };
66
+
67
+ Utils.isInHead = function(element) {
68
+ while (element) {
69
+ if (element.tagName && element.tagName.toLowerCase() == "head") {
70
+ return true;
71
+ }
72
+ try {
73
+ element = element.parentNode;
74
+ } catch (e) {
75
+ // Fine. the DOM has dispeared from underneath us
76
+ return false;
77
+ }
78
+ }
79
+
80
+ return false;
81
+ };
82
+
83
+ Utils.isDisplayed = function(element) {
84
+ // Ensure that we're dealing with an element.
85
+ var el = element;
86
+ while (el.nodeType != 1 && !(el.nodeType >= 9 && el.nodeType <= 11)) {
87
+ el = el.parentNode;
88
+ }
89
+
90
+ // Hidden input elements are, by definition, never displayed
91
+ if (el.tagName == "input" && el.type == "hidden") {
92
+ return false;
93
+ }
94
+
95
+ var visibility = Utils.getStyleProperty(el, "visibility");
96
+
97
+ var _isDisplayed = function(e) {
98
+ var display = e.ownerDocument.defaultView.getComputedStyle(e, null).getPropertyValue("display");
99
+ if (display == "none") return display;
100
+ if (e && e.parentNode && e.parentNode.style) {
101
+ return _isDisplayed(e.parentNode);
102
+ }
103
+ return undefined;
104
+ };
105
+
106
+ var displayed = _isDisplayed(el);
107
+
108
+ if (element.scrollIntoView && element.getBoundingClientRect &&
109
+ element.tagName.toLowerCase() != "option") {
110
+ //Option tags have 0-dimension bounding rects so ignore them
111
+ element.scrollIntoView(true);
112
+ var clientRect = element.getBoundingClientRect();
113
+ if (clientRect.width == 0 || clientRect.height == 0) {
114
+ return false;
115
+ }
116
+ }
117
+
118
+ return displayed != "none" && visibility != "hidden";
119
+ };
120
+
121
+ Utils.getStyleProperty = function(node, propertyName) {
122
+ if (!node)
123
+ return undefined;
124
+
125
+ var value = node.ownerDocument.defaultView.getComputedStyle(node, null).getPropertyValue(propertyName);
126
+
127
+ // Convert colours to hex if possible
128
+ var raw = /rgb\((\d{1,3}),\s(\d{1,3}),\s(\d{1,3})\)/.exec(value);
129
+ if (raw) {
130
+ var temp = value.substr(0, raw.index);
131
+
132
+ var hex = "#";
133
+ for (var i = 1; i <= 3; i++) {
134
+ var colour = (raw[i] - 0).toString(16);
135
+ if (colour.length == 1)
136
+ colour = "0" + colour;
137
+ hex += colour
138
+ }
139
+ hex = hex.toLowerCase();
140
+ value = temp + hex + value.substr(raw.index + raw[0].length);
141
+ }
142
+
143
+ if (value == "inherit" && element.parentNode.style) {
144
+ value = Utils.getStyleProperty(node.parentNode, propertyName);
145
+ }
146
+
147
+ return value;
148
+ };
149
+
150
+ function collapseWhitespace(textSoFar) {
151
+ return textSoFar.replace(/\s+/g, " ");
152
+ }
153
+ ;
154
+
155
+ function getPreformattedText(node) {
156
+ var textToAdd = "";
157
+ return getTextFromNode(node, "", textToAdd, true)[1];
158
+ }
159
+ ;
160
+
161
+ function isWhiteSpace(character) {
162
+ return character == '\n' || character == ' ' || character == '\t' || character == '\r';
163
+ }
164
+
165
+ Utils.getText = function(element) {
166
+ var bits = getTextFromNode(element, "", "", element.tagName == "PRE");
167
+ var text = bits[0] + collapseWhitespace(bits[1]);
168
+ var start = 0;
169
+ while (start < text.length && isWhiteSpace(text[start])) {
170
+ ++start;
171
+ }
172
+ var end = text.length;
173
+ while (end > start && isWhiteSpace(text[end - 1])) {
174
+ --end;
175
+ }
176
+ return text.slice(start, end);
177
+ };
178
+
179
+ Utils.fireHtmlEvent = function(element, eventName) {
180
+ var e = document.createEvent("HTMLEvents");
181
+ e.initEvent(eventName, true, true);
182
+ element.dispatchEvent(e);
183
+ };
184
+
185
+
186
+ Utils.fireMouseEventOn = function(element, eventName) {
187
+ Utils.triggerMouseEvent(element, eventName, 0, 0);
188
+ };
189
+
190
+ 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);
196
+ };
@@ -0,0 +1,8 @@
1
+ require "selenium/webdriver/chrome/launcher"
2
+ require "selenium/webdriver/chrome/command_executor"
3
+ require "selenium/webdriver/chrome/bridge"
4
+
5
+ require "fileutils"
6
+ require "thread"
7
+ require "socket"
8
+
@@ -0,0 +1,324 @@
1
+ module Selenium
2
+ module WebDriver
3
+ module Chrome
4
+ class Bridge
5
+ include BridgeHelper
6
+
7
+ def initialize
8
+ @executor = CommandExecutor.new
9
+
10
+ @launcher = Launcher.launcher
11
+ @launcher.launch
12
+ # TODO: @launcher.kill
13
+ end
14
+
15
+ def browser
16
+ :chrome
17
+ end
18
+
19
+ def get(url)
20
+ execute :request => 'get',
21
+ :url => url
22
+ end
23
+
24
+ def goBack
25
+ execute :request => 'goBack'
26
+ end
27
+
28
+ def goForward
29
+ execute :request => 'goForward'
30
+ end
31
+
32
+ def getCurrentUrl
33
+ execute :request => 'getCurrentUrl'
34
+ end
35
+
36
+ def getTitle
37
+ execute :request => 'getTitle'
38
+ end
39
+
40
+ def getPageSource
41
+ execute :request => 'getPageSource'
42
+ end
43
+
44
+ def switchToWindow(name)
45
+ execute :request => 'switchToWindow',
46
+ :windowName => name
47
+ end
48
+
49
+ def switchToFrame(id)
50
+ execute :request => 'switchToFrameByName',
51
+ :name => id
52
+ end
53
+
54
+ def quit
55
+ @launcher.kill # FIXME: let chrome extension take care of this
56
+ execute :request => 'quit'
57
+ end
58
+
59
+ def close
60
+ execute :request => 'close'
61
+ end
62
+
63
+ def getWindowHandles
64
+ execute :request => 'getWindowHandles'
65
+ end
66
+
67
+ def getCurrentWindowHandle
68
+ execute :request => 'getCurrentWindowHandle'
69
+ end
70
+
71
+ def setSpeed(value)
72
+ @speed = value
73
+ end
74
+
75
+ def getSpeed
76
+ @speed
77
+ end
78
+
79
+ def executeScript(script, *args)
80
+ typed_args = args.map { |e| wrap_script_argument(e) }
81
+
82
+ resp = execute :request => 'executeScript',
83
+ :script => script,
84
+ :args => typed_args
85
+
86
+ unwrap_script_argument resp
87
+ end
88
+
89
+ def addCookie(cookie)
90
+ execute :request => 'addCookie',
91
+ :cookie => cookie
92
+ end
93
+
94
+ def deleteCookie(name)
95
+ execute :request => 'deleteCookie',
96
+ :name => name
97
+ end
98
+
99
+ def getAllCookies
100
+ execute :request => 'getCookies'
101
+ end
102
+
103
+ def deleteAllCookies
104
+ execute :request => 'deleteAllCookies'
105
+ end
106
+
107
+ def findElementByClassName(parent, class_name)
108
+ find_element_by 'class name', class_name, parent
109
+ end
110
+
111
+ def findElementsByClassName(parent, class_name)
112
+ find_elements_by 'class name', class_name, parent
113
+ end
114
+
115
+ def findElementById(parent, id)
116
+ find_element_by 'id', id, parent
117
+ end
118
+
119
+ def findElementsById(parent, id)
120
+ find_elements_by 'id', id, parent
121
+ end
122
+
123
+ def findElementByLinkText(parent, link_text)
124
+ find_element_by 'link text', link_text, parent
125
+ end
126
+
127
+ def findElementsByLinkText(parent, link_text)
128
+ find_elements_by 'link text', link_text, parent
129
+ end
130
+
131
+ def findElementByPartialLinkText(parent, link_text)
132
+ find_element_by 'partial link text', link_text, parent
133
+ end
134
+
135
+ def findElementsByPartialLinkText(parent, link_text)
136
+ find_elements_by 'partial link text', link_text, parent
137
+ end
138
+
139
+ def findElementByName(parent, name)
140
+ find_element_by 'name', name, parent
141
+ end
142
+
143
+ def findElementsByName(parent, name)
144
+ find_elements_by 'name', name, parent
145
+ end
146
+
147
+ def findElementByTagName(parent, tag_name)
148
+ find_element_by 'tag name', tag_name, parent
149
+ end
150
+
151
+ def findElementsByTagName(parent, tag_name)
152
+ find_elements_by 'tag name', tag_name, parent
153
+ end
154
+
155
+ def findElementByXpath(parent, xpath)
156
+ find_element_by 'xpath', xpath, parent
157
+ end
158
+
159
+ def findElementsByXpath(parent, xpath)
160
+ find_elements_by 'xpath', xpath, parent
161
+ end
162
+
163
+
164
+ #
165
+ # Element functions
166
+ #
167
+
168
+ def clickElement(element)
169
+ execute :request => 'clickElement',
170
+ :elementId => element
171
+ end
172
+
173
+ def getElementTagName(element)
174
+ execute :request => 'getElementTagName',
175
+ :elementId => element
176
+ end
177
+
178
+ def getElementAttribute(element, name)
179
+ execute :request => 'getElementAttribute',
180
+ :elementId => element,
181
+ :attribute => name
182
+ end
183
+
184
+ def getElementValue(element)
185
+ execute :request => 'getElementValue',
186
+ :elementId => element
187
+ end
188
+
189
+ def getElementText(element)
190
+ execute :request => 'getElementText',
191
+ :elementId => element
192
+ end
193
+
194
+ def getElementLocation(element)
195
+ data = execute :request => 'getElementLocation',
196
+ :elementId => element
197
+
198
+ Point.new data['x'], data['y']
199
+ end
200
+
201
+ def getElementSize(element)
202
+ execute :request => 'getElementSize',
203
+ :elementId => element
204
+ end
205
+
206
+ def sendKeysToElement(element, string)
207
+ execute :request => 'sendKeysToElement',
208
+ :elementId => element,
209
+ :keys => string.split(//u)
210
+ end
211
+
212
+ def clearElement(element)
213
+ execute :request => 'clearElement',
214
+ :elementId => element
215
+ end
216
+
217
+ def isElementEnabled(element)
218
+ execute :request => 'isElementEnabled',
219
+ :elementId => element
220
+ end
221
+
222
+ def isElementSelected(element)
223
+ execute :request => 'isElementSelected',
224
+ :elementId => element
225
+ end
226
+
227
+ def isElementDisplayed(element)
228
+ execute :request => 'isElementDisplayed',
229
+ :elementId => element
230
+ end
231
+
232
+ def submitElement(element)
233
+ execute :request => 'submitElement',
234
+ :elementId => element
235
+ end
236
+
237
+ def toggleElement(element)
238
+ execute :request => 'toggleElement',
239
+ :elementId => element
240
+ end
241
+
242
+ def setElementSelected(element)
243
+ execute :request => 'setElementSelected',
244
+ :elementId => element
245
+ end
246
+
247
+ def getElementValueOfCssProperty(element, prop)
248
+ execute :request => 'getElementValueOfCssProperty',
249
+ :elementId => element,
250
+ :css => prop
251
+ end
252
+
253
+ def getActiveElement
254
+ Element.new self, element_id_from(execute(:request => 'getActiveElement'))
255
+ end
256
+ alias_method :switchToActiveElement, :getActiveElement
257
+
258
+ def hoverOverElement
259
+ execute :request => 'hoverOverElement',
260
+ :elementId => element
261
+ end
262
+
263
+ def dragElement(element, rigth_by, down_by)
264
+ raise UnsupportedOperationError, "drag and drop unsupported in Chrome"
265
+ execute :drag_element, {:id => element}, element, rigth_by, down_by
266
+ end
267
+
268
+ private
269
+
270
+ def find_element_by(how, what, parent = nil)
271
+ if parent
272
+ id = execute :request => 'findChildElement',
273
+ :id => parent,
274
+ :using => how,
275
+ :value => what
276
+ else
277
+ id = execute :request => 'findElement',
278
+ :using => how,
279
+ :value => what
280
+ end
281
+
282
+ Element.new self, element_id_from(id)
283
+ end
284
+
285
+ def find_elements_by(how, what, parent = nil)
286
+ if parent
287
+ ids = execute :request => 'findChildElements',
288
+ :id => parent,
289
+ :using => how,
290
+ :value => what
291
+ else
292
+ ids = execute :request => 'findElements',
293
+ :using => how,
294
+ :value => what
295
+ end
296
+
297
+ ids.map { |id| Element.new self, element_id_from(id) }
298
+ end
299
+
300
+
301
+ private
302
+
303
+ def execute(command)
304
+ resp = raw_execute command
305
+ code = resp['statusCode']
306
+ if e = Error.for_code(code)
307
+ msg = resp['value']['message'] if resp['value']
308
+ msg ||= "unknown exception for #{command.inspect}"
309
+ msg << " (#{code})"
310
+
311
+ raise e, msg
312
+ end
313
+
314
+ resp['value']
315
+ end
316
+
317
+ def raw_execute(command)
318
+ @executor.execute command
319
+ end
320
+
321
+ end # Bridge
322
+ end # Chrome
323
+ end # WebDriver
324
+ end # Selenium